@explorer02/cfm-survey-sdk 0.2.4 → 0.2.5

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.
Files changed (31) hide show
  1. package/dist/cli/index.js +34 -33
  2. package/dist/cli/index.mjs +35 -34
  3. package/package.json +1 -6
  4. package/postinstall.js +2 -1
  5. package/templates/AGENT.md +3 -3
  6. package/templates/docs/00-integration/agent-execution-flow.md +39 -27
  7. package/templates/docs/00-integration/agent-operating-contract.md +13 -5
  8. package/templates/docs/00-integration/apply-ui-config.md +35 -10
  9. package/templates/docs/00-integration/aws-deploy.md +117 -3
  10. package/templates/docs/00-integration/component-checklist.md +4 -2
  11. package/templates/docs/00-integration/constraints.md +3 -2
  12. package/templates/docs/00-integration/custom-field-logic-and-navigation.md +1 -1
  13. package/templates/docs/00-integration/mockup-ui-extraction.md +113 -0
  14. package/templates/docs/00-integration/placeholders-and-custom-fields-wiring.md +192 -0
  15. package/templates/docs/00-integration/placeholders-and-tokens.md +2 -1
  16. package/templates/docs/00-integration/ui-customization-wizard.md +83 -104
  17. package/templates/docs/00-integration/wizard-api.md +74 -82
  18. package/templates/docs/00-integration/wizard-config-handoff.md +55 -9
  19. package/templates/docs/00-integration/wizard-preview-build-guide.md +12 -7
  20. package/templates/docs/00-integration/wizard-question-type-styling.md +4 -2
  21. package/templates/docs/00-integration/wizard-troubleshooting.md +80 -0
  22. package/templates/docs/01-components/10-header-footer.md +3 -3
  23. package/templates/docs/MANIFEST.json +30 -13
  24. package/templates/docs/index.md +7 -9
  25. package/templates/docs/templates/deploy-to-aws.sh +74 -0
  26. package/templates/docs/templates/implementation_plan.md +19 -12
  27. package/templates/wizard-dist/assets/{PreviewMock-DgHfrVeb.js → PreviewMock-AoZdAEPZ.js} +1 -1
  28. package/templates/wizard-dist/assets/{TypePanel-CFVC3Ptn.js → TypePanel-39FnbtvG.js} +1 -1
  29. package/templates/wizard-dist/assets/index-CWKdsJOp.js +34 -0
  30. package/templates/wizard-dist/index.html +1 -1
  31. package/templates/wizard-dist/assets/index-DYK3X1e5.js +0 -34
@@ -1,19 +1,19 @@
1
1
  #!/usr/bin/env node
2
- var Io=Object.defineProperty;var he=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(o,t)=>(typeof require<"u"?require:o)[t]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});var B=(e,o)=>()=>(e&&(o=e(e=0)),o);var Re=(e,o)=>{for(var t in o)Io(e,t,{get:o[t],enumerable:!0})};var c,M=B(()=>{"use strict";c={reset:"\x1B[0m",bold:"\x1B[1m",green:"\x1B[32m",red:"\x1B[31m",cyan:"\x1B[36m",yellow:"\x1B[33m",dim:"\x1B[2m"}});var oe,ve=B(()=>{"use strict";oe=["MCQ","TEXTFIELD","NPS_SCALE","CFM_MATRIX","CSAT_MATRIX","RATING_MATRIX","SLIDER_MATRIX","FILE_UPLOAD","TEXT_AND_MEDIA","HEATMAP","RANK_ORDER"]});function Lo(e){let o={};for(let t of e)Ve[t]&&(o[t]={...Ve[t]});return o}function Mo(e=[],o){return{version:"1.0",instanceId:o,surveyTypes:e,global:{surveyTitle:"Customer Feedback Survey",companyName:"Sprinklr",browserTabTitle:"Customer Feedback Survey",thankYouMessage:"Thank you for your valuable feedback!",logo:{fileName:null,url:null},header:{height:120,logoBoxWidth:120,logoBoxHeight:120,logoPadding:10,logoPlacement:"left",showCompanyName:!0,companyNamePlacement:"left",companyNameFontSize:18,companyNameFontWeight:600,companyNameColor:"#1A1F36",backgroundColor:"#FFFFFF",shadowEnabled:!0,borderBottomColor:"#E5E7EB",contentPaddingX:40},footer:{backgroundColor:"#262626",textColor:"#9CA3AF",linkColor:"#9CA3AF",linkHoverColor:"#FFFFFF",showLogo:!0,logoWidth:120,logoHeight:32,logoPlacement:"left",copyrightText:"\xA9 Company Name",layout:"row",paddingY:24,paddingX:40,links:[]},theme:{pageBackground:"#FFFFFF",cardBackground:"#FFFFFF",cardBorderColor:"#E5E7EB",cardPadding:24,cardShadowEnabled:!0,selectedBackground:"#E8F5FD",zebraRowColor:"rgba(249,250,251,0.8)",rowBandColor:"#F3F4F6",validationBorder:"#333333",validationBackground:"#D9D9D9",tooltipBackground:"#1F2937",progressTrackHeight:12,progressTrackColor:"#E5E7EB",progressFillColor:"#1A1F36",stickyChromePaddingTop:16,stickyChromePaddingBottom:20,languageSelectorBackground:"#FFFFFF",languageSelectorTextColor:"#2563EB",languageSelectorBorderColor:"#2563EB"},layout:{showHeader:!0,showFooter:!0,showProgressBar:!0,showLanguageSwitcher:!1,showNextButton:!0,showBackButton:!0,showQuestionNumbers:!0,showRequiredAsterisk:!0,width:"standard",borderStyle:"rounded",fontStyle:"modern"},buttons:{next:"Next",back:"Back",submit:"Submit"},colorScheme:{...N},colorSource:"auto",typography:{fontFamily:"Inter, sans-serif",headingWeight:700},motion:{enabled:!1,durationMs:200}},questionTypes:Lo(e),placeholders:{firstName:"Alex",lastName:"Customer",email:"alex@example.com"},customFields:{},debug:{enabled:!1,sampleAnswers:{}},deploy:{target:"aws",autoDeploy:!1}}}function H(e,o){return{...e,...o??{}}}function Xe(e){let o=(e.surveyTypes??[]).filter(r=>oe.includes(r)),t=Mo(o,e.instanceId),n=e.global??{},i=t.global,s={...t.questionTypes};if(e.questionTypes)for(let[r,a]of Object.entries(e.questionTypes))s[r]={...s[r]??{},...a};return{...t,...e,configuredAt:void 0,surveyTypes:o.length?o:t.surveyTypes,global:{...i,...n,header:H(i.header,n.header),footer:H(i.footer,n.footer),theme:H(i.theme,n.theme),layout:H(i.layout,n.layout),buttons:H(i.buttons,n.buttons),logo:H(i.logo,n.logo),colorScheme:H(i.colorScheme,n.colorScheme),typography:H(i.typography,n.typography),motion:H(i.motion,n.motion)},questionTypes:s,placeholders:{...t.placeholders,...e.placeholders??{}},customFields:{...t.customFields,...e.customFields??{}},debug:{enabled:e.debug?.enabled??t.debug?.enabled??!1,sampleAnswers:e.debug?.sampleAnswers??t.debug?.sampleAnswers},deploy:{...t.deploy,...e.deploy??{}}}}var N,Ve,qe=B(()=>{"use strict";ve();N={primary:"#1A1F36",secondary:"#E8F5FD",accent:"#00B5AD",background:"#FFFFFF",text:"#1A1F36",buttonText:"#FFFFFF"},Ve={MCQ:{cardStyle:"outlined",selectedAccent:N.accent,optionGap:8,borderRadius:8,cardPadding:12,selectedBackground:N.secondary,hoverBorderColor:N.accent},TEXTFIELD:{inputRadius:8,focusRing:N.accent,borderColor:"#E5E7EB",inputPadding:12,inputHeight:44,placeholderColor:"#9CA3AF"},NPS_SCALE:{buttonStyle:"standard",selectedFill:N.secondary,labelColor:N.text,trackBarColor:"#F2F2F2",trackHighlightColor:"#FBE8F3",cellSize:40,cellGap:4},CFM_MATRIX:{rowLabelWidth:180,cellSelectedColor:N.accent,headerStyle:"bold",bipolarColumnWidthPercent:25,carouselDotColor:"#2563EB",cellPadding:8},CSAT_MATRIX:{rowLabelWidth:180,cellSelectedColor:N.accent,headerStyle:"bold",bipolarColumnWidthPercent:25,carouselDotColor:N.primary,cellPadding:8,accentColor:N.accent,emojiSize:24,unselectedOpacity:.5,selectedRingColor:N.accent,cellSize:40,tooltipBg:"#1F2937"},RATING_MATRIX:{starColor:"#F59E0B",badgeColor:N.primary,rowLabelWidth:180,unselectedStarOpacity:.5},SLIDER_MATRIX:{trackColor:N.accent,thumbColor:N.primary,tickColor:"#9CA3AF",rowLabelWidth:180,rowBandColor:"#F3F4F6",tickBadgeSize:28},FILE_UPLOAD:{dropzoneStyle:"dashed",accentColor:N.accent,dropzonePadding:24},TEXT_AND_MEDIA:{mediaMaxWidth:100,mediaRadius:8,captionColor:"#6B7280",captionSize:14},HEATMAP:{pinColor:N.accent,pinSize:12,pinBorderColor:"#FFFFFF",overlayOpacity:.3},RANK_ORDER:{itemBg:"#F9FAFB",dragHandleColor:"#9CA3AF",rankBadgeColor:N.primary,itemPadding:12,itemGap:8}}});import*as we from"fs";import*as ge from"path";function Ze(e){let o={},t=/--cfm-[\w-]+\s*:\s*([^;]+);/g,n;for(;(n=t.exec(e))!==null;){let i=n[0].split(":")[0].trim(),s=n[1].trim();o[i]=s}return o}function b(e){if(!e)return;let o=parseFloat(e.replace(/px$/,""));return Number.isFinite(o)?o:void 0}function Ye(e){if(!e)return;let o=parseFloat(e.replace(/%$/,""));return Number.isFinite(o)?o:void 0}function de(e){if(!e)return;let o=parseFloat(e);return Number.isFinite(o)?o:void 0}function eo(e){let o={global:{},questionTypes:{}},t=o.global,n={},i={},s={},r={},a={},l={},w={},y=o.questionTypes;if(e["--cfm-primary"]&&(n.primary=e["--cfm-primary"]),e["--cfm-secondary"]&&(n.secondary=e["--cfm-secondary"]),e["--cfm-accent"]&&(n.accent=e["--cfm-accent"]),e["--cfm-background"]&&(n.background=e["--cfm-background"]),e["--cfm-text"]&&(n.text=e["--cfm-text"]),e["--cfm-button-text"]&&(n.buttonText=e["--cfm-button-text"]),e["--cfm-max-width"]&&Qe[e["--cfm-max-width"]]&&(a.width=Qe[e["--cfm-max-width"]]),e["--cfm-border-radius"]&&Ge[e["--cfm-border-radius"]]&&(a.borderStyle=Ge[e["--cfm-border-radius"]]),e["--cfm-font-family"]&&(l.fontFamily=e["--cfm-font-family"],Ke[e["--cfm-font-family"]]&&(a.fontStyle=Ke[e["--cfm-font-family"]])),e["--cfm-heading-weight"]&&(l.headingWeight=de(e["--cfm-heading-weight"])),e["--cfm-motion-duration"]){let j=b(e["--cfm-motion-duration"]);j!==void 0&&(w.durationMs=j,w.enabled=j>0)}e["--cfm-header-height"]&&(i.height=b(e["--cfm-header-height"])),e["--cfm-header-logo-width"]&&(i.logoBoxWidth=b(e["--cfm-header-logo-width"])),e["--cfm-header-logo-height"]&&(i.logoBoxHeight=b(e["--cfm-header-logo-height"])),e["--cfm-header-logo-padding"]&&(i.logoPadding=b(e["--cfm-header-logo-padding"])),e["--cfm-header-bg"]&&(i.backgroundColor=e["--cfm-header-bg"]),e["--cfm-header-company-color"]&&(i.companyNameColor=e["--cfm-header-company-color"]),e["--cfm-header-company-size"]&&(i.companyNameFontSize=b(e["--cfm-header-company-size"])),e["--cfm-header-company-weight"]&&(i.companyNameFontWeight=de(e["--cfm-header-company-weight"])),e["--cfm-header-border"]&&(i.borderBottomColor=e["--cfm-header-border"]),e["--cfm-header-padding-x"]&&(i.contentPaddingX=b(e["--cfm-header-padding-x"])),e["--cfm-footer-bg"]&&(s.backgroundColor=e["--cfm-footer-bg"]),e["--cfm-footer-text"]&&(s.textColor=e["--cfm-footer-text"]),e["--cfm-footer-link"]&&(s.linkColor=e["--cfm-footer-link"]),e["--cfm-footer-link-hover"]&&(s.linkHoverColor=e["--cfm-footer-link-hover"]),e["--cfm-footer-logo-width"]&&(s.logoWidth=b(e["--cfm-footer-logo-width"])),e["--cfm-footer-logo-height"]&&(s.logoHeight=b(e["--cfm-footer-logo-height"])),e["--cfm-footer-padding-y"]&&(s.paddingY=b(e["--cfm-footer-padding-y"])),e["--cfm-footer-padding-x"]&&(s.paddingX=b(e["--cfm-footer-padding-x"])),e["--cfm-background"]&&(r.pageBackground=e["--cfm-background"]),e["--cfm-card-bg"]&&(r.cardBackground=e["--cfm-card-bg"]),e["--cfm-card-border-color"]&&(r.cardBorderColor=e["--cfm-card-border-color"]),e["--cfm-card-padding"]&&(r.cardPadding=b(e["--cfm-card-padding"])),e["--cfm-card-shadow"]&&(r.cardShadowEnabled=e["--cfm-card-shadow"]!=="none"),e["--cfm-selected-bg"]&&(r.selectedBackground=e["--cfm-selected-bg"]),e["--cfm-zebra-row"]&&(r.zebraRowColor=e["--cfm-zebra-row"]),e["--cfm-row-band"]&&(r.rowBandColor=e["--cfm-row-band"]),e["--cfm-validation-border"]&&(r.validationBorder=e["--cfm-validation-border"]),e["--cfm-validation-bg"]&&(r.validationBackground=e["--cfm-validation-bg"]),e["--cfm-tooltip-bg"]&&(r.tooltipBackground=e["--cfm-tooltip-bg"]),e["--cfm-progress-height"]&&(r.progressTrackHeight=b(e["--cfm-progress-height"])),e["--cfm-progress-track"]&&(r.progressTrackColor=e["--cfm-progress-track"]),e["--cfm-progress-fill"]&&(r.progressFillColor=e["--cfm-progress-fill"]),e["--cfm-sticky-pt"]&&(r.stickyChromePaddingTop=b(e["--cfm-sticky-pt"])),e["--cfm-sticky-pb"]&&(r.stickyChromePaddingBottom=b(e["--cfm-sticky-pb"]));let T={};e["--cfm-mcq-selected-accent"]&&(T.selectedAccent=e["--cfm-mcq-selected-accent"]),e["--cfm-mcq-border-radius"]&&(T.borderRadius=b(e["--cfm-mcq-border-radius"])),e["--cfm-mcq-option-gap"]&&(T.optionGap=b(e["--cfm-mcq-option-gap"])),e["--cfm-mcq-card-padding"]&&(T.cardPadding=b(e["--cfm-mcq-card-padding"])),e["--cfm-mcq-selected-bg"]&&(T.selectedBackground=e["--cfm-mcq-selected-bg"]),e["--cfm-mcq-hover-border"]&&(T.hoverBorderColor=e["--cfm-mcq-hover-border"]),Object.keys(T).length&&(y.MCQ=T);let C={};e["--cfm-input-radius"]&&(C.inputRadius=b(e["--cfm-input-radius"])),e["--cfm-input-focus-ring"]&&(C.focusRing=e["--cfm-input-focus-ring"]),e["--cfm-input-border"]&&(C.borderColor=e["--cfm-input-border"]),e["--cfm-input-padding"]&&(C.inputPadding=b(e["--cfm-input-padding"])),e["--cfm-input-height"]&&(C.inputHeight=b(e["--cfm-input-height"])),e["--cfm-input-placeholder"]&&(C.placeholderColor=e["--cfm-input-placeholder"]),Object.keys(C).length&&(y.TEXTFIELD=C);let E={};e["--cfm-nps-selected-fill"]&&(E.selectedFill=e["--cfm-nps-selected-fill"]),e["--cfm-nps-label-color"]&&(E.labelColor=e["--cfm-nps-label-color"]),e["--cfm-nps-track-bar"]&&(E.trackBarColor=e["--cfm-nps-track-bar"]),e["--cfm-nps-track-highlight"]&&(E.trackHighlightColor=e["--cfm-nps-track-highlight"]),e["--cfm-nps-cell-size"]&&(E.cellSize=b(e["--cfm-nps-cell-size"])),e["--cfm-nps-cell-gap"]&&(E.cellGap=b(e["--cfm-nps-cell-gap"])),Object.keys(E).length&&(y.NPS_SCALE=E);let I=b(e["--cfm-matrix-row-width"]),m={};I!==void 0&&(m.rowLabelWidth=I),e["--cfm-matrix-selected"]&&(m.cellSelectedColor=e["--cfm-matrix-selected"]),e["--cfm-matrix-bipolar-width"]&&(m.bipolarColumnWidthPercent=Ye(e["--cfm-matrix-bipolar-width"])),e["--cfm-matrix-carousel-dot"]&&(m.carouselDotColor=e["--cfm-matrix-carousel-dot"]),e["--cfm-matrix-cell-padding"]&&(m.cellPadding=b(e["--cfm-matrix-cell-padding"])),Object.keys(m).length&&(y.CFM_MATRIX=m);let f={...m};e["--cfm-csat-accent"]&&(f.accentColor=e["--cfm-csat-accent"]),e["--cfm-csat-emoji-size"]&&(f.emojiSize=b(e["--cfm-csat-emoji-size"])),e["--cfm-csat-unselected-opacity"]&&(f.unselectedOpacity=de(e["--cfm-csat-unselected-opacity"])),e["--cfm-csat-ring-color"]&&(f.selectedRingColor=e["--cfm-csat-ring-color"]),e["--cfm-csat-cell-size"]&&(f.cellSize=b(e["--cfm-csat-cell-size"])),e["--cfm-csat-tooltip-bg"]&&(f.tooltipBg=e["--cfm-csat-tooltip-bg"]),(Object.keys(f).length>Object.keys(m).length||e["--cfm-csat-accent"])&&(y.CSAT_MATRIX=f);let u={};e["--cfm-star-color"]&&(u.starColor=e["--cfm-star-color"]),e["--cfm-badge-color"]&&(u.badgeColor=e["--cfm-badge-color"]),I!==void 0&&(u.rowLabelWidth=I),e["--cfm-star-unselected-opacity"]&&(u.unselectedStarOpacity=de(e["--cfm-star-unselected-opacity"])),Object.keys(u).length&&(y.RATING_MATRIX=u);let h={};e["--cfm-slider-track"]&&(h.trackColor=e["--cfm-slider-track"]),e["--cfm-slider-thumb"]&&(h.thumbColor=e["--cfm-slider-thumb"]),e["--cfm-slider-tick"]&&(h.tickColor=e["--cfm-slider-tick"]),I!==void 0&&(h.rowLabelWidth=I),e["--cfm-slider-row-band"]&&(h.rowBandColor=e["--cfm-slider-row-band"]),e["--cfm-slider-tick-size"]&&(h.tickBadgeSize=b(e["--cfm-slider-tick-size"])),Object.keys(h).length&&(y.SLIDER_MATRIX=h);let x={};e["--cfm-upload-accent"]&&(x.accentColor=e["--cfm-upload-accent"]),e["--cfm-upload-padding"]&&(x.dropzonePadding=b(e["--cfm-upload-padding"])),Object.keys(x).length&&(y.FILE_UPLOAD=x);let S={};e["--cfm-media-max-width"]&&(S.mediaMaxWidth=Ye(e["--cfm-media-max-width"])),e["--cfm-media-radius"]&&(S.mediaRadius=b(e["--cfm-media-radius"])),e["--cfm-media-caption-color"]&&(S.captionColor=e["--cfm-media-caption-color"]),e["--cfm-media-caption-size"]&&(S.captionSize=b(e["--cfm-media-caption-size"])),Object.keys(S).length&&(y.TEXT_AND_MEDIA=S);let $={};e["--cfm-heatmap-pin"]&&($.pinColor=e["--cfm-heatmap-pin"]),e["--cfm-heatmap-pin-size"]&&($.pinSize=b(e["--cfm-heatmap-pin-size"])),e["--cfm-heatmap-pin-border"]&&($.pinBorderColor=e["--cfm-heatmap-pin-border"]),e["--cfm-heatmap-overlay-opacity"]&&($.overlayOpacity=de(e["--cfm-heatmap-overlay-opacity"])),Object.keys($).length&&(y.HEATMAP=$);let k={};return e["--cfm-rank-item-bg"]&&(k.itemBg=e["--cfm-rank-item-bg"]),e["--cfm-rank-badge"]&&(k.rankBadgeColor=e["--cfm-rank-badge"]),e["--cfm-rank-handle"]&&(k.dragHandleColor=e["--cfm-rank-handle"]),e["--cfm-rank-item-padding"]&&(k.itemPadding=b(e["--cfm-rank-item-padding"])),e["--cfm-rank-item-gap"]&&(k.itemGap=b(e["--cfm-rank-item-gap"])),Object.keys(k).length&&(y.RANK_ORDER=k),Object.keys(n).length&&(t.colorScheme=n),Object.keys(i).length&&(t.header=i),Object.keys(s).length&&(t.footer=s),Object.keys(r).length&&(t.theme=r),Object.keys(a).length&&(t.layout=a),Object.keys(l).length&&(t.typography=l),Object.keys(w).length&&(t.motion=w),o}function te(e){let o=[ge.join(e,"src","styles","survey-theme.css"),ge.join(e,"src","app","survey-theme.css"),ge.join(e,"src","styles","globals.css"),ge.join(e,"src","app","globals.css")];for(let t of o)if(we.existsSync(t)&&we.readFileSync(t,"utf8").includes("--cfm-"))return t;return null}var Qe,Ge,Ke,Se=B(()=>{"use strict";Qe={"36rem":"narrow","48rem":"standard","64rem":"wide"},Ge={"0px":"sharp","12px":"rounded","9999px":"pill"},Ke={"system-ui, sans-serif":"system","Inter, sans-serif":"modern","Georgia, serif":"serif"}});import*as be from"fs";import*as oo from"path";function zo(e){for(let o of Uo){let t=oo.join(e,o);if(be.existsSync(t))return t}return null}function Bo(e){let o=e.trim();if(!o||o.startsWith("http")||o.startsWith("data:"))return null;let t=o.split("?")[0];return t.startsWith("/")?t.slice(1):t}function to(e){let o=zo(e);if(!o)return null;let t=be.readFileSync(o,"utf8"),n=t.match(/data-cfm-logo[\s\S]*?src=["']([^"']+)["']/i)??t.match(/src=["']([^"']+)["'][\s\S]*?data-cfm-logo/i);if(n){let r=Bo(n[1]);if(r)return{mode:"image",publicPath:r,fileName:r}}let i=t.match(/data-cfm-logo-text[^>]*>([^<]+)</i);if(i)return{mode:"text",label:i[1].trim()};let s=t.match(/data-cfm-company[^>]*>([^<]+)</i);return s&&!n?{mode:"text",label:s[1].trim()}:null}var Uo,no=B(()=>{"use strict";Uo=["src/components/Header.tsx","components/Header.tsx","app/components/Header.tsx"]});var ao={};Re(ao,{logSeedSource:()=>Fe,resolveInitialConfig:()=>ie,writeResolvedUiConfig:()=>je});import*as W from"fs";import*as V from"path";function Ie(e){return e.filter(o=>oe.includes(o))}function io(e){try{let o=JSON.parse(W.readFileSync(e,"utf8"));return o.version!=="1.0"?null:(delete o.configuredAt,o)}catch{return null}}function Ho(e){let o={global:{}};if(!W.existsSync(e))return o;let t=W.readFileSync(e,"utf8"),n=new Set;for(let s of oe)t.includes(s)&&n.add(s);n.size&&(o.surveyTypes=[...n]);let i=t.match(/\*\*Branding source:\*\*\s*(.+)/i);if(i){let s=i[1].trim(),r=s.match(/company[:\s]+([^,;]+)/i),a=s.match(/title[:\s]+([^,;]+)/i);if(r&&(o.global.companyName=r[1].trim()),a){let l=a[1].trim();o.global.surveyTitle=l,o.global.browserTabTitle=l}}return o}function co(e,o){let t=V.join(e,o);if(!W.existsSync(t))return null;let n=W.readFileSync(t);if(n.length>Wo)return{fileName:o,dataUrl:""};let i=V.extname(o).toLowerCase(),s=Jo[i]??"application/octet-stream";return{fileName:o,dataUrl:`data:${s};base64,${n.toString("base64")}`}}function ro(e,o){if(!o)return null;if(o.url&&typeof o.url=="string")return{fileName:o.fileName??null,url:o.url};if(o.fileName){let t=co(e,o.fileName);if(t)return{fileName:t.fileName,url:t.dataUrl||null}}return o.fileName===null&&o.url===null?{fileName:null,url:null}:null}function so(e,o){let t=e.global??{},n=o.global??{},i=e.questionTypes??{},s=o.questionTypes??{},r={...i};for(let[a,l]of Object.entries(s))r[a]={...r[a]??{},...l};return{...e,...o,surveyTypes:o.surveyTypes??e.surveyTypes,global:{...t,...n,header:{...t.header,...n.header},footer:{...t.footer,...n.footer},theme:{...t.theme,...n.theme},layout:{...t.layout,...n.layout},buttons:{...t.buttons,...n.buttons},logo:{...t.logo,...n.logo},colorScheme:{...t.colorScheme,...n.colorScheme},typography:{...t.typography,...n.typography},motion:{...t.motion,...n.motion}},questionTypes:r,placeholders:{...e.placeholders,...o.placeholders},customFields:{...e.customFields,...o.customFields},deploy:{...e.deploy,...o.deploy}}}function ie(e){let o=e.projectRoot??process.env.INIT_CWD??process.cwd(),t=V.join(o,"survey-ui-config.json"),n=V.join(o,"implementation_plan.md"),i=V.join(o,"public"),s=Ie(e.surveyTypes),r={},a="defaults",l=te(o);if(l){let k=W.readFileSync(l,"utf8"),j=Ze(k);Object.keys(j).length>0&&(r=eo(j),a="survey-theme.css")}let w=Ho(n);r=so(r,w);let y=io(t);y&&(r=so(r,y),a="survey-ui-config.json");let T=V.join(o,"survey-ui-config.final.json"),C=io(T),E=!!y?.configuredAt,I=!!C?.configuredAt;if(C&&I&&!E){let k=ro(i,C.global?.logo);k&&(r.global={...r.global??{},logo:{fileName:k.fileName,url:k.url}})}let m=ro(i,r.global?.logo),f=to(o),u=!!y?.configuredAt,h=m?.fileName!=null&&/^logo_\d+_/i.test(m.fileName),x=f?.mode==="image"?f.fileName:null,S=!u&&h&&x!=null&&m?.fileName!==x;if(m&&!S)r.global={...r.global??{},logo:{fileName:m.fileName,url:m.url}};else if(f?.mode==="image"){let k=co(i,f.fileName);r.global={...r.global??{},logo:{fileName:f.fileName,url:k?.dataUrl||null}}}else f?.mode==="text"&&(r.global={...r.global??{},logo:{fileName:null,url:null},companyName:r.global?.companyName??f.label});return r.surveyTypes=Ie(r.surveyTypes??s),r.surveyTypes?.length||(r.surveyTypes=s),e.instanceId&&(r.instanceId=e.instanceId),{config:Xe(r),source:a}}function Fe(e){console.log(e==="survey-ui-config.json"?`${ne.dim} Seeding wizard from survey-ui-config.json${ne.reset}`:e==="survey-theme.css"?`${ne.dim} Seeding wizard from survey-theme.css + defaults${ne.reset}`:`${ne.dim} Seeding wizard from SDK defaults${ne.reset}`)}function je(e={}){let o=e.projectRoot??process.env.INIT_CWD??process.cwd(),t=e.surveyTypes??Ie(oe),{config:n}=ie({projectRoot:o,surveyTypes:t,instanceId:e.instanceId}),i=V.join(o,"survey-ui-config.json");return W.writeFileSync(i,JSON.stringify(n,null,2),"utf8"),i}var ne,Wo,Jo,pe=B(()=>{"use strict";M();qe();Se();ve();no();ne=c,Wo=512e3,Jo={".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".webp":"image/webp",".svg":"image/svg+xml"}});import*as ce from"fs";import*as ae from"path";function mo(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function ho(e,o){return JSON.stringify(e)===JSON.stringify(o)}function se(e){return typeof e=="string"&&e.startsWith("data:")&&e.length>80?`${e.slice(0,48)}\u2026 (${e.length} chars)`:e}function yo(e,o,t,n){if(ho(e,o)){n.unchangedCount+=1;return}if(e===void 0&&o!==void 0){n.added.push({path:t,before:void 0,after:se(o)});return}if(e!==void 0&&o===void 0){n.removed.push({path:t,before:se(e),after:void 0});return}if(Array.isArray(e)&&Array.isArray(o)){ho(e,o)?n.unchangedCount+=1:n.changed.push({path:t,before:se(e),after:se(o)});return}if(mo(e)&&mo(o)){let i=new Set([...Object.keys(e),...Object.keys(o)]);for(let s of i){if(st.has(s)&&t==="")continue;let r=t?`${t}.${s}`:s;yo(e[s],o[s],r,n)}return}n.changed.push({path:t,before:se(e),after:se(o)})}function Oe(e,o){let t={changed:[],added:[],removed:[],unchangedCount:0};return yo(e,o,"",t),t}function xe(e){let o=["# UI Config Diff (seed \u2192 final)","",`**Changed:** ${e.changed.length} \xB7 **Added:** ${e.added.length} \xB7 **Removed:** ${e.removed.length}`,"","> Review only \u2014 run `npx cfm-sdk confirm-ui-config` to apply final config to the project.",""],t=(n,i)=>{if(i.length){o.push(`## ${n}`,"");for(let s of i)o.push(`### \`${s.path}\``),o.push(`- **Before:** \`${JSON.stringify(s.before)}\``),o.push(`- **After:** \`${JSON.stringify(s.after)}\``),o.push("")}};return t("Changed",e.changed),t("Added",e.added),t("Removed",e.removed),!e.changed.length&&!e.added.length&&!e.removed.length&&o.push("_No differences \u2014 final config matches seed._",""),o.join(`
3
- `)}function G(e){return{seedPath:ae.join(e,"survey-ui-config.seed.json"),finalPath:ae.join(e,"survey-ui-config.final.json"),diffJsonPath:ae.join(e,"survey-ui-config.diff.json"),diffMdPath:ae.join(e,"survey-ui-config.diff.md"),activeConfigPath:ae.join(e,"survey-ui-config.json")}}function ke(e,o,t){let n=G(e),i=Oe(o,t);return ce.writeFileSync(n.seedPath,JSON.stringify(o,null,2),"utf8"),ce.writeFileSync(n.finalPath,JSON.stringify(t,null,2),"utf8"),ce.writeFileSync(n.diffJsonPath,JSON.stringify(i,null,2),"utf8"),ce.writeFileSync(n.diffMdPath,xe(i),"utf8"),ce.writeFileSync(n.activeConfigPath,JSON.stringify(o,null,2),"utf8"),i}var st,Te=B(()=>{"use strict";st=new Set(["configuredAt","instanceId"])});import*as K from"fs";import*as So from"http";import*as bo from"https";import*as Le from"path";function Pe(e){if(!e.config)return null;let o=JSON.parse(JSON.stringify(e.config)),n=o.global?.logo;return e.logoUrl&&n&&(n.url=e.logoUrl),o}function wo(e){return new Promise((o,t)=>{let n=new URL(e);(n.protocol==="https:"?bo:So).get(n,s=>{if((s.statusCode??500)>=400){t(new Error(`Logo download failed HTTP ${s.statusCode}`));return}let r=[];s.on("data",a=>r.push(a)),s.on("end",()=>o(Buffer.concat(r)))}).on("error",t)})}async function ct(e,o={}){return new Promise((t,n)=>{let i=new URL(e),r=(i.protocol==="https:"?bo:So).request(i,{method:"GET",headers:o.headers??{}},a=>{let l="";a.on("data",w=>l+=w),a.on("end",()=>{if((a.statusCode??500)>=400){n(new Error(`HTTP ${a.statusCode}: ${l}`));return}try{t(JSON.parse(l))}catch{n(new Error(`Invalid JSON: ${l.slice(0,200)}`))}})});r.on("error",n),r.end()})}async function Y(e){let{projectRoot:o,fileName:t,logoUrl:n,jwt:i,apiBase:s,surveyId:r}=e,a=Le.join(o,"public");K.existsSync(a)||K.mkdirSync(a,{recursive:!0});let l=Le.join(a,t);if(n){let w=await wo(n);return K.writeFileSync(l,w),l}if(i&&s&&r){let w=await ct(`${s.replace(/\/$/,"")}/wizard/logo/${encodeURIComponent(r)}/${encodeURIComponent(t)}`,{headers:{Authorization:`Bearer ${i}`}}),y=await wo(w.downloadUrl);return K.writeFileSync(l,y),l}throw new Error("Logo download requires logoUrl from wizard poll or CFM_INSTANCE_ID + CFM_DEPLOY_API_BASE")}var Ee=B(()=>{"use strict"});var To={};Re(To,{runConfirmUiConfig:()=>pt});import*as J from"fs";function gt(e){try{let o=e.split(".")[1];return JSON.parse(Buffer.from(o,"base64url").toString("utf8")).surveyId??null}catch{return null}}async function pt(e={}){let o=process.env.INIT_CWD??process.cwd(),t=G(o);if(!J.existsSync(t.finalPath))throw new Error(`Missing ${t.finalPath}. Run customize-ui with --review and complete the wizard first.`);let n=JSON.parse(J.readFileSync(J.existsSync(t.seedPath)?t.seedPath:t.activeConfigPath,"utf8")),i=JSON.parse(J.readFileSync(t.finalPath,"utf8")),s=Oe(n,i);if(console.log(`
2
+ var Io=Object.defineProperty;var ye=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(o,t)=>(typeof require<"u"?require:o)[t]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});var B=(e,o)=>()=>(e&&(o=e(e=0)),o);var Re=(e,o)=>{for(var t in o)Io(e,t,{get:o[t],enumerable:!0})};var c,M=B(()=>{"use strict";c={reset:"\x1B[0m",bold:"\x1B[1m",green:"\x1B[32m",red:"\x1B[31m",cyan:"\x1B[36m",yellow:"\x1B[33m",dim:"\x1B[2m"}});var Q,Se=B(()=>{"use strict";Q=["MCQ","TEXTFIELD","NPS_SCALE","CFM_MATRIX","CSAT_MATRIX","RATING_MATRIX","SLIDER_MATRIX","FILE_UPLOAD","TEXT_AND_MEDIA","HEATMAP","RANK_ORDER"]});function Lo(e){let o={};for(let t of e)Ve[t]&&(o[t]={...Ve[t]});return o}function Mo(e=[],o){return{version:"1.0",instanceId:o,surveyTypes:e,global:{surveyTitle:"Customer Feedback Survey",companyName:"Sprinklr",browserTabTitle:"Customer Feedback Survey",thankYouMessage:"Thank you for your valuable feedback!",logo:{fileName:null,url:null},header:{height:120,logoBoxWidth:120,logoBoxHeight:120,logoPadding:10,logoPlacement:"left",showCompanyName:!0,companyNamePlacement:"left",companyNameFontSize:18,companyNameFontWeight:600,companyNameColor:"#1A1F36",backgroundColor:"#FFFFFF",shadowEnabled:!0,borderBottomColor:"#E5E7EB",contentPaddingX:40},footer:{backgroundColor:"#262626",textColor:"#9CA3AF",linkColor:"#9CA3AF",linkHoverColor:"#FFFFFF",showLogo:!0,logoWidth:120,logoHeight:32,logoPlacement:"left",copyrightText:"\xA9 Company Name",layout:"row",paddingY:24,paddingX:40,links:[]},theme:{pageBackground:"#FFFFFF",cardBackground:"#FFFFFF",cardBorderColor:"#E5E7EB",cardPadding:24,cardShadowEnabled:!0,selectedBackground:"#E8F5FD",zebraRowColor:"rgba(249,250,251,0.8)",rowBandColor:"#F3F4F6",validationBorder:"#333333",validationBackground:"#D9D9D9",tooltipBackground:"#1F2937",progressTrackHeight:12,progressTrackColor:"#E5E7EB",progressFillColor:"#1A1F36",stickyChromePaddingTop:16,stickyChromePaddingBottom:20,languageSelectorBackground:"#FFFFFF",languageSelectorTextColor:"#2563EB",languageSelectorBorderColor:"#2563EB"},layout:{showHeader:!0,showFooter:!0,showProgressBar:!0,showLanguageSwitcher:!1,showNextButton:!0,showBackButton:!0,showQuestionNumbers:!0,showRequiredAsterisk:!0,width:"standard",borderStyle:"rounded",fontStyle:"modern"},buttons:{next:"Next",back:"Back",submit:"Submit"},colorScheme:{...N},colorSource:"auto",typography:{fontFamily:"Inter, sans-serif",headingWeight:700},motion:{enabled:!1,durationMs:200}},questionTypes:Lo(e),placeholders:{firstName:"Alex",lastName:"Customer",email:"alex@example.com"},customFields:{},debug:{enabled:!1,sampleAnswers:{}},deploy:{target:"aws",autoDeploy:!1}}}function H(e,o){return{...e,...o??{}}}function Xe(e){let o=(e.surveyTypes??[]).filter(r=>Q.includes(r)),t=Mo(o,e.instanceId),n=e.global??{},i=t.global,s={...t.questionTypes};if(e.questionTypes)for(let[r,a]of Object.entries(e.questionTypes))s[r]={...s[r]??{},...a};return{...t,...e,configuredAt:void 0,surveyTypes:o.length?o:t.surveyTypes,global:{...i,...n,header:H(i.header,n.header),footer:H(i.footer,n.footer),theme:H(i.theme,n.theme),layout:H(i.layout,n.layout),buttons:H(i.buttons,n.buttons),logo:H(i.logo,n.logo),colorScheme:H(i.colorScheme,n.colorScheme),typography:H(i.typography,n.typography),motion:H(i.motion,n.motion)},questionTypes:s,placeholders:{...t.placeholders,...e.placeholders??{}},customFields:{...t.customFields,...e.customFields??{}},debug:{enabled:e.debug?.enabled??t.debug?.enabled??!1,sampleAnswers:e.debug?.sampleAnswers??t.debug?.sampleAnswers},deploy:{...t.deploy,...e.deploy??{}}}}var N,Ve,qe=B(()=>{"use strict";Se();N={primary:"#1A1F36",secondary:"#E8F5FD",accent:"#00B5AD",background:"#FFFFFF",text:"#1A1F36",buttonText:"#FFFFFF"},Ve={MCQ:{cardStyle:"outlined",selectedAccent:N.accent,optionGap:8,borderRadius:8,cardPadding:12,selectedBackground:N.secondary,hoverBorderColor:N.accent},TEXTFIELD:{inputRadius:8,focusRing:N.accent,borderColor:"#E5E7EB",inputPadding:12,inputHeight:44,placeholderColor:"#9CA3AF"},NPS_SCALE:{buttonStyle:"standard",selectedFill:N.secondary,labelColor:N.text,trackBarColor:"#F2F2F2",trackHighlightColor:"#FBE8F3",cellSize:40,cellGap:4},CFM_MATRIX:{rowLabelWidth:180,cellSelectedColor:N.accent,headerStyle:"bold",bipolarColumnWidthPercent:25,carouselDotColor:"#2563EB",cellPadding:8},CSAT_MATRIX:{rowLabelWidth:180,cellSelectedColor:N.accent,headerStyle:"bold",bipolarColumnWidthPercent:25,carouselDotColor:N.primary,cellPadding:8,accentColor:N.accent,emojiSize:24,unselectedOpacity:.5,selectedRingColor:N.accent,cellSize:40,tooltipBg:"#1F2937"},RATING_MATRIX:{starColor:"#F59E0B",badgeColor:N.primary,rowLabelWidth:180,unselectedStarOpacity:.5},SLIDER_MATRIX:{trackColor:N.accent,thumbColor:N.primary,tickColor:"#9CA3AF",rowLabelWidth:180,rowBandColor:"#F3F4F6",tickBadgeSize:28},FILE_UPLOAD:{dropzoneStyle:"dashed",accentColor:N.accent,dropzonePadding:24},TEXT_AND_MEDIA:{mediaMaxWidth:100,mediaRadius:8,captionColor:"#6B7280",captionSize:14},HEATMAP:{pinColor:N.accent,pinSize:12,pinBorderColor:"#FFFFFF",overlayOpacity:.3},RANK_ORDER:{itemBg:"#F9FAFB",dragHandleColor:"#9CA3AF",rankBadgeColor:N.primary,itemPadding:12,itemGap:8}}});import*as be from"fs";import*as ge from"path";function Ze(e){let o={},t=/--cfm-[\w-]+\s*:\s*([^;]+);/g,n;for(;(n=t.exec(e))!==null;){let i=n[0].split(":")[0].trim(),s=n[1].trim();o[i]=s}return o}function C(e){if(!e)return;let o=parseFloat(e.replace(/px$/,""));return Number.isFinite(o)?o:void 0}function Ye(e){if(!e)return;let o=parseFloat(e.replace(/%$/,""));return Number.isFinite(o)?o:void 0}function de(e){if(!e)return;let o=parseFloat(e);return Number.isFinite(o)?o:void 0}function eo(e){let o={global:{},questionTypes:{}},t=o.global,n={},i={},s={},r={},a={},l={},w={},m=o.questionTypes;if(e["--cfm-primary"]&&(n.primary=e["--cfm-primary"]),e["--cfm-secondary"]&&(n.secondary=e["--cfm-secondary"]),e["--cfm-accent"]&&(n.accent=e["--cfm-accent"]),e["--cfm-background"]&&(n.background=e["--cfm-background"]),e["--cfm-text"]&&(n.text=e["--cfm-text"]),e["--cfm-button-text"]&&(n.buttonText=e["--cfm-button-text"]),e["--cfm-max-width"]&&Qe[e["--cfm-max-width"]]&&(a.width=Qe[e["--cfm-max-width"]]),e["--cfm-border-radius"]&&Ge[e["--cfm-border-radius"]]&&(a.borderStyle=Ge[e["--cfm-border-radius"]]),e["--cfm-font-family"]&&(l.fontFamily=e["--cfm-font-family"],Ke[e["--cfm-font-family"]]&&(a.fontStyle=Ke[e["--cfm-font-family"]])),e["--cfm-heading-weight"]&&(l.headingWeight=de(e["--cfm-heading-weight"])),e["--cfm-motion-duration"]){let F=C(e["--cfm-motion-duration"]);F!==void 0&&(w.durationMs=F,w.enabled=F>0)}e["--cfm-header-height"]&&(i.height=C(e["--cfm-header-height"])),e["--cfm-header-logo-width"]&&(i.logoBoxWidth=C(e["--cfm-header-logo-width"])),e["--cfm-header-logo-height"]&&(i.logoBoxHeight=C(e["--cfm-header-logo-height"])),e["--cfm-header-logo-padding"]&&(i.logoPadding=C(e["--cfm-header-logo-padding"])),e["--cfm-header-bg"]&&(i.backgroundColor=e["--cfm-header-bg"]),e["--cfm-header-company-color"]&&(i.companyNameColor=e["--cfm-header-company-color"]),e["--cfm-header-company-size"]&&(i.companyNameFontSize=C(e["--cfm-header-company-size"])),e["--cfm-header-company-weight"]&&(i.companyNameFontWeight=de(e["--cfm-header-company-weight"])),e["--cfm-header-border"]&&(i.borderBottomColor=e["--cfm-header-border"]),e["--cfm-header-padding-x"]&&(i.contentPaddingX=C(e["--cfm-header-padding-x"])),e["--cfm-footer-bg"]&&(s.backgroundColor=e["--cfm-footer-bg"]),e["--cfm-footer-text"]&&(s.textColor=e["--cfm-footer-text"]),e["--cfm-footer-link"]&&(s.linkColor=e["--cfm-footer-link"]),e["--cfm-footer-link-hover"]&&(s.linkHoverColor=e["--cfm-footer-link-hover"]),e["--cfm-footer-logo-width"]&&(s.logoWidth=C(e["--cfm-footer-logo-width"])),e["--cfm-footer-logo-height"]&&(s.logoHeight=C(e["--cfm-footer-logo-height"])),e["--cfm-footer-padding-y"]&&(s.paddingY=C(e["--cfm-footer-padding-y"])),e["--cfm-footer-padding-x"]&&(s.paddingX=C(e["--cfm-footer-padding-x"])),e["--cfm-background"]&&(r.pageBackground=e["--cfm-background"]),e["--cfm-card-bg"]&&(r.cardBackground=e["--cfm-card-bg"]),e["--cfm-card-border-color"]&&(r.cardBorderColor=e["--cfm-card-border-color"]),e["--cfm-card-padding"]&&(r.cardPadding=C(e["--cfm-card-padding"])),e["--cfm-card-shadow"]&&(r.cardShadowEnabled=e["--cfm-card-shadow"]!=="none"),e["--cfm-selected-bg"]&&(r.selectedBackground=e["--cfm-selected-bg"]),e["--cfm-zebra-row"]&&(r.zebraRowColor=e["--cfm-zebra-row"]),e["--cfm-row-band"]&&(r.rowBandColor=e["--cfm-row-band"]),e["--cfm-validation-border"]&&(r.validationBorder=e["--cfm-validation-border"]),e["--cfm-validation-bg"]&&(r.validationBackground=e["--cfm-validation-bg"]),e["--cfm-tooltip-bg"]&&(r.tooltipBackground=e["--cfm-tooltip-bg"]),e["--cfm-progress-height"]&&(r.progressTrackHeight=C(e["--cfm-progress-height"])),e["--cfm-progress-track"]&&(r.progressTrackColor=e["--cfm-progress-track"]),e["--cfm-progress-fill"]&&(r.progressFillColor=e["--cfm-progress-fill"]),e["--cfm-sticky-pt"]&&(r.stickyChromePaddingTop=C(e["--cfm-sticky-pt"])),e["--cfm-sticky-pb"]&&(r.stickyChromePaddingBottom=C(e["--cfm-sticky-pb"]));let $={};e["--cfm-mcq-selected-accent"]&&($.selectedAccent=e["--cfm-mcq-selected-accent"]),e["--cfm-mcq-border-radius"]&&($.borderRadius=C(e["--cfm-mcq-border-radius"])),e["--cfm-mcq-option-gap"]&&($.optionGap=C(e["--cfm-mcq-option-gap"])),e["--cfm-mcq-card-padding"]&&($.cardPadding=C(e["--cfm-mcq-card-padding"])),e["--cfm-mcq-selected-bg"]&&($.selectedBackground=e["--cfm-mcq-selected-bg"]),e["--cfm-mcq-hover-border"]&&($.hoverBorderColor=e["--cfm-mcq-hover-border"]),Object.keys($).length&&(m.MCQ=$);let b={};e["--cfm-input-radius"]&&(b.inputRadius=C(e["--cfm-input-radius"])),e["--cfm-input-focus-ring"]&&(b.focusRing=e["--cfm-input-focus-ring"]),e["--cfm-input-border"]&&(b.borderColor=e["--cfm-input-border"]),e["--cfm-input-padding"]&&(b.inputPadding=C(e["--cfm-input-padding"])),e["--cfm-input-height"]&&(b.inputHeight=C(e["--cfm-input-height"])),e["--cfm-input-placeholder"]&&(b.placeholderColor=e["--cfm-input-placeholder"]),Object.keys(b).length&&(m.TEXTFIELD=b);let R={};e["--cfm-nps-selected-fill"]&&(R.selectedFill=e["--cfm-nps-selected-fill"]),e["--cfm-nps-label-color"]&&(R.labelColor=e["--cfm-nps-label-color"]),e["--cfm-nps-track-bar"]&&(R.trackBarColor=e["--cfm-nps-track-bar"]),e["--cfm-nps-track-highlight"]&&(R.trackHighlightColor=e["--cfm-nps-track-highlight"]),e["--cfm-nps-cell-size"]&&(R.cellSize=C(e["--cfm-nps-cell-size"])),e["--cfm-nps-cell-gap"]&&(R.cellGap=C(e["--cfm-nps-cell-gap"])),Object.keys(R).length&&(m.NPS_SCALE=R);let I=C(e["--cfm-matrix-row-width"]),h={};I!==void 0&&(h.rowLabelWidth=I),e["--cfm-matrix-selected"]&&(h.cellSelectedColor=e["--cfm-matrix-selected"]),e["--cfm-matrix-bipolar-width"]&&(h.bipolarColumnWidthPercent=Ye(e["--cfm-matrix-bipolar-width"])),e["--cfm-matrix-carousel-dot"]&&(h.carouselDotColor=e["--cfm-matrix-carousel-dot"]),e["--cfm-matrix-cell-padding"]&&(h.cellPadding=C(e["--cfm-matrix-cell-padding"])),Object.keys(h).length&&(m.CFM_MATRIX=h);let f={...h};e["--cfm-csat-accent"]&&(f.accentColor=e["--cfm-csat-accent"]),e["--cfm-csat-emoji-size"]&&(f.emojiSize=C(e["--cfm-csat-emoji-size"])),e["--cfm-csat-unselected-opacity"]&&(f.unselectedOpacity=de(e["--cfm-csat-unselected-opacity"])),e["--cfm-csat-ring-color"]&&(f.selectedRingColor=e["--cfm-csat-ring-color"]),e["--cfm-csat-cell-size"]&&(f.cellSize=C(e["--cfm-csat-cell-size"])),e["--cfm-csat-tooltip-bg"]&&(f.tooltipBg=e["--cfm-csat-tooltip-bg"]),(Object.keys(f).length>Object.keys(h).length||e["--cfm-csat-accent"])&&(m.CSAT_MATRIX=f);let g={};e["--cfm-star-color"]&&(g.starColor=e["--cfm-star-color"]),e["--cfm-badge-color"]&&(g.badgeColor=e["--cfm-badge-color"]),I!==void 0&&(g.rowLabelWidth=I),e["--cfm-star-unselected-opacity"]&&(g.unselectedStarOpacity=de(e["--cfm-star-unselected-opacity"])),Object.keys(g).length&&(m.RATING_MATRIX=g);let y={};e["--cfm-slider-track"]&&(y.trackColor=e["--cfm-slider-track"]),e["--cfm-slider-thumb"]&&(y.thumbColor=e["--cfm-slider-thumb"]),e["--cfm-slider-tick"]&&(y.tickColor=e["--cfm-slider-tick"]),I!==void 0&&(y.rowLabelWidth=I),e["--cfm-slider-row-band"]&&(y.rowBandColor=e["--cfm-slider-row-band"]),e["--cfm-slider-tick-size"]&&(y.tickBadgeSize=C(e["--cfm-slider-tick-size"])),Object.keys(y).length&&(m.SLIDER_MATRIX=y);let x={};e["--cfm-upload-accent"]&&(x.accentColor=e["--cfm-upload-accent"]),e["--cfm-upload-padding"]&&(x.dropzonePadding=C(e["--cfm-upload-padding"])),Object.keys(x).length&&(m.FILE_UPLOAD=x);let S={};e["--cfm-media-max-width"]&&(S.mediaMaxWidth=Ye(e["--cfm-media-max-width"])),e["--cfm-media-radius"]&&(S.mediaRadius=C(e["--cfm-media-radius"])),e["--cfm-media-caption-color"]&&(S.captionColor=e["--cfm-media-caption-color"]),e["--cfm-media-caption-size"]&&(S.captionSize=C(e["--cfm-media-caption-size"])),Object.keys(S).length&&(m.TEXT_AND_MEDIA=S);let T={};e["--cfm-heatmap-pin"]&&(T.pinColor=e["--cfm-heatmap-pin"]),e["--cfm-heatmap-pin-size"]&&(T.pinSize=C(e["--cfm-heatmap-pin-size"])),e["--cfm-heatmap-pin-border"]&&(T.pinBorderColor=e["--cfm-heatmap-pin-border"]),e["--cfm-heatmap-overlay-opacity"]&&(T.overlayOpacity=de(e["--cfm-heatmap-overlay-opacity"])),Object.keys(T).length&&(m.HEATMAP=T);let k={};return e["--cfm-rank-item-bg"]&&(k.itemBg=e["--cfm-rank-item-bg"]),e["--cfm-rank-badge"]&&(k.rankBadgeColor=e["--cfm-rank-badge"]),e["--cfm-rank-handle"]&&(k.dragHandleColor=e["--cfm-rank-handle"]),e["--cfm-rank-item-padding"]&&(k.itemPadding=C(e["--cfm-rank-item-padding"])),e["--cfm-rank-item-gap"]&&(k.itemGap=C(e["--cfm-rank-item-gap"])),Object.keys(k).length&&(m.RANK_ORDER=k),Object.keys(n).length&&(t.colorScheme=n),Object.keys(i).length&&(t.header=i),Object.keys(s).length&&(t.footer=s),Object.keys(r).length&&(t.theme=r),Object.keys(a).length&&(t.layout=a),Object.keys(l).length&&(t.typography=l),Object.keys(w).length&&(t.motion=w),o}function te(e){let o=[ge.join(e,"src","styles","survey-theme.css"),ge.join(e,"src","app","survey-theme.css"),ge.join(e,"src","styles","globals.css"),ge.join(e,"src","app","globals.css")];for(let t of o)if(be.existsSync(t)&&be.readFileSync(t,"utf8").includes("--cfm-"))return t;return null}var Qe,Ge,Ke,Ce=B(()=>{"use strict";Qe={"36rem":"narrow","48rem":"standard","64rem":"wide"},Ge={"0px":"sharp","12px":"rounded","9999px":"pill"},Ke={"system-ui, sans-serif":"system","Inter, sans-serif":"modern","Georgia, serif":"serif"}});import*as $e from"fs";import*as oo from"path";function zo(e){for(let o of Uo){let t=oo.join(e,o);if($e.existsSync(t))return t}return null}function Bo(e){let o=e.trim();if(!o||o.startsWith("http")||o.startsWith("data:"))return null;let t=o.split("?")[0];return t.startsWith("/")?t.slice(1):t}function to(e){let o=zo(e);if(!o)return null;let t=$e.readFileSync(o,"utf8"),n=t.match(/data-cfm-logo[\s\S]*?src=["']([^"']+)["']/i)??t.match(/src=["']([^"']+)["'][\s\S]*?data-cfm-logo/i);if(n){let r=Bo(n[1]);if(r)return{mode:"image",publicPath:r,fileName:r}}let i=t.match(/data-cfm-logo-text[^>]*>([^<]+)</i);if(i)return{mode:"text",label:i[1].trim()};let s=t.match(/data-cfm-company[^>]*>([^<]+)</i);return s&&!n?{mode:"text",label:s[1].trim()}:null}var Uo,no=B(()=>{"use strict";Uo=["src/components/Header.tsx","components/Header.tsx","app/components/Header.tsx"]});var ao={};Re(ao,{logSeedSource:()=>je,resolveInitialConfig:()=>ie,writeResolvedUiConfig:()=>Fe});import*as W from"fs";import*as V from"path";function Ie(e){return e.filter(o=>Q.includes(o))}function io(e){try{let o=JSON.parse(W.readFileSync(e,"utf8"));return o.version!=="1.0"?null:(delete o.configuredAt,o)}catch{return null}}function Ho(e){let o={global:{}};if(!W.existsSync(e))return o;let t=W.readFileSync(e,"utf8"),n=new Set;for(let s of Q)t.includes(s)&&n.add(s);n.size&&(o.surveyTypes=[...n]);let i=t.match(/\*\*Branding source:\*\*\s*(.+)/i);if(i){let s=i[1].trim(),r=s.match(/company[:\s]+([^,;]+)/i),a=s.match(/title[:\s]+([^,;]+)/i);if(r&&(o.global.companyName=r[1].trim()),a){let l=a[1].trim();o.global.surveyTitle=l,o.global.browserTabTitle=l}}return o}function co(e,o){let t=V.join(e,o);if(!W.existsSync(t))return null;let n=W.readFileSync(t);if(n.length>Wo)return{fileName:o,dataUrl:""};let i=V.extname(o).toLowerCase(),s=Jo[i]??"application/octet-stream";return{fileName:o,dataUrl:`data:${s};base64,${n.toString("base64")}`}}function ro(e,o){if(!o)return null;if(o.url&&typeof o.url=="string")return{fileName:o.fileName??null,url:o.url};if(o.fileName){let t=co(e,o.fileName);if(t)return{fileName:t.fileName,url:t.dataUrl||null}}return o.fileName===null&&o.url===null?{fileName:null,url:null}:null}function so(e,o){let t=e.global??{},n=o.global??{},i=e.questionTypes??{},s=o.questionTypes??{},r={...i};for(let[a,l]of Object.entries(s))r[a]={...r[a]??{},...l};return{...e,...o,surveyTypes:o.surveyTypes??e.surveyTypes,global:{...t,...n,header:{...t.header,...n.header},footer:{...t.footer,...n.footer},theme:{...t.theme,...n.theme},layout:{...t.layout,...n.layout},buttons:{...t.buttons,...n.buttons},logo:{...t.logo,...n.logo},colorScheme:{...t.colorScheme,...n.colorScheme},typography:{...t.typography,...n.typography},motion:{...t.motion,...n.motion}},questionTypes:r,placeholders:{...e.placeholders,...o.placeholders},customFields:{...e.customFields,...o.customFields},deploy:{...e.deploy,...o.deploy}}}function ie(e){let o=e.projectRoot??process.env.INIT_CWD??process.cwd(),t=V.join(o,"survey-ui-config.json"),n=V.join(o,"implementation_plan.md"),i=V.join(o,"public"),s=Ie(e.surveyTypes),r={},a="defaults",l=te(o);if(l){let k=W.readFileSync(l,"utf8"),F=Ze(k);Object.keys(F).length>0&&(r=eo(F),a="survey-theme.css")}let w=Ho(n);r=so(r,w);let m=io(t);m&&(r=so(r,m),a="survey-ui-config.json");let $=V.join(o,"survey-ui-config.final.json"),b=io($),R=!!m?.configuredAt,I=!!b?.configuredAt;if(b&&I&&!R){let k=ro(i,b.global?.logo);k&&(r.global={...r.global??{},logo:{fileName:k.fileName,url:k.url}})}let h=ro(i,r.global?.logo),f=to(o),g=!!m?.configuredAt,y=h?.fileName!=null&&/^logo_\d+_/i.test(h.fileName),x=f?.mode==="image"?f.fileName:null,S=!g&&y&&x!=null&&h?.fileName!==x;if(h&&!S)r.global={...r.global??{},logo:{fileName:h.fileName,url:h.url}};else if(f?.mode==="image"){let k=co(i,f.fileName);r.global={...r.global??{},logo:{fileName:f.fileName,url:k?.dataUrl||null}}}else f?.mode==="text"&&(r.global={...r.global??{},logo:{fileName:null,url:null},companyName:r.global?.companyName??f.label});return r.surveyTypes=Ie(r.surveyTypes??s),r.surveyTypes?.length||(r.surveyTypes=s),e.instanceId&&(r.instanceId=e.instanceId),{config:Xe(r),source:a}}function je(e){console.log(e==="survey-ui-config.json"?`${ne.dim} Seeding wizard from survey-ui-config.json${ne.reset}`:e==="survey-theme.css"?`${ne.dim} Seeding wizard from survey-theme.css + defaults${ne.reset}`:`${ne.dim} Seeding wizard from SDK defaults${ne.reset}`)}function Fe(e={}){let o=e.projectRoot??process.env.INIT_CWD??process.cwd(),t=e.surveyTypes??Ie(Q),{config:n}=ie({projectRoot:o,surveyTypes:t,instanceId:e.instanceId}),i=V.join(o,"survey-ui-config.json");return W.writeFileSync(i,JSON.stringify(n,null,2),"utf8"),i}var ne,Wo,Jo,ue=B(()=>{"use strict";M();qe();Ce();Se();no();ne=c,Wo=512e3,Jo={".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".webp":"image/webp",".svg":"image/svg+xml"}});import*as ce from"fs";import*as ae from"path";function mo(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function ho(e,o){return JSON.stringify(e)===JSON.stringify(o)}function se(e){return typeof e=="string"&&e.startsWith("data:")&&e.length>80?`${e.slice(0,48)}\u2026 (${e.length} chars)`:e}function yo(e,o,t,n){if(ho(e,o)){n.unchangedCount+=1;return}if(e===void 0&&o!==void 0){n.added.push({path:t,before:void 0,after:se(o)});return}if(e!==void 0&&o===void 0){n.removed.push({path:t,before:se(e),after:void 0});return}if(Array.isArray(e)&&Array.isArray(o)){ho(e,o)?n.unchangedCount+=1:n.changed.push({path:t,before:se(e),after:se(o)});return}if(mo(e)&&mo(o)){let i=new Set([...Object.keys(e),...Object.keys(o)]);for(let s of i){if(st.has(s)&&t==="")continue;let r=t?`${t}.${s}`:s;yo(e[s],o[s],r,n)}return}n.changed.push({path:t,before:se(e),after:se(o)})}function Oe(e,o){let t={changed:[],added:[],removed:[],unchangedCount:0};return yo(e,o,"",t),t}function Te(e){let o=["# UI Config Diff (seed \u2192 final)","",`**Changed:** ${e.changed.length} \xB7 **Added:** ${e.added.length} \xB7 **Removed:** ${e.removed.length}`,"","> Review only \u2014 run `npx cfm-sdk confirm-ui-config` to apply final config to the project.",""],t=(n,i)=>{if(i.length){o.push(`## ${n}`,"");for(let s of i)o.push(`### \`${s.path}\``),o.push(`- **Before:** \`${JSON.stringify(s.before)}\``),o.push(`- **After:** \`${JSON.stringify(s.after)}\``),o.push("")}};return t("Changed",e.changed),t("Added",e.added),t("Removed",e.removed),!e.changed.length&&!e.added.length&&!e.removed.length&&o.push("_No differences \u2014 final config matches seed._",""),o.join(`
3
+ `)}function K(e){return{seedPath:ae.join(e,"survey-ui-config.seed.json"),finalPath:ae.join(e,"survey-ui-config.final.json"),diffJsonPath:ae.join(e,"survey-ui-config.diff.json"),diffMdPath:ae.join(e,"survey-ui-config.diff.md"),activeConfigPath:ae.join(e,"survey-ui-config.json")}}function ke(e,o,t){let n=K(e),i=Oe(o,t);return ce.writeFileSync(n.seedPath,JSON.stringify(o,null,2),"utf8"),ce.writeFileSync(n.finalPath,JSON.stringify(t,null,2),"utf8"),ce.writeFileSync(n.diffJsonPath,JSON.stringify(i,null,2),"utf8"),ce.writeFileSync(n.diffMdPath,Te(i),"utf8"),ce.writeFileSync(n.activeConfigPath,JSON.stringify(o,null,2),"utf8"),i}var st,Pe=B(()=>{"use strict";st=new Set(["configuredAt","instanceId"])});import*as Y from"fs";import*as So from"http";import*as bo from"https";import*as Le from"path";function Ee(e){if(!e.config)return null;let o=JSON.parse(JSON.stringify(e.config)),n=o.global?.logo;return e.logoUrl&&n&&(n.url=e.logoUrl),o}function wo(e){return new Promise((o,t)=>{let n=new URL(e);(n.protocol==="https:"?bo:So).get(n,s=>{if((s.statusCode??500)>=400){t(new Error(`Logo download failed HTTP ${s.statusCode}`));return}let r=[];s.on("data",a=>r.push(a)),s.on("end",()=>o(Buffer.concat(r)))}).on("error",t)})}async function ct(e,o={}){return new Promise((t,n)=>{let i=new URL(e),r=(i.protocol==="https:"?bo:So).request(i,{method:"GET",headers:o.headers??{}},a=>{let l="";a.on("data",w=>l+=w),a.on("end",()=>{if((a.statusCode??500)>=400){n(new Error(`HTTP ${a.statusCode}: ${l}`));return}try{t(JSON.parse(l))}catch{n(new Error(`Invalid JSON: ${l.slice(0,200)}`))}})});r.on("error",n),r.end()})}async function Z(e){let{projectRoot:o,fileName:t,logoUrl:n,jwt:i,apiBase:s,surveyId:r}=e,a=Le.join(o,"public");Y.existsSync(a)||Y.mkdirSync(a,{recursive:!0});let l=Le.join(a,t);if(n){let w=await wo(n);return Y.writeFileSync(l,w),l}if(i&&s&&r){let w=await ct(`${s.replace(/\/$/,"")}/wizard/logo/${encodeURIComponent(r)}/${encodeURIComponent(t)}`,{headers:{Authorization:`Bearer ${i}`}}),m=await wo(w.downloadUrl);return Y.writeFileSync(l,m),l}throw new Error("Logo download requires logoUrl from wizard poll or CFM_INSTANCE_ID + CFM_DEPLOY_API_BASE")}var ve=B(()=>{"use strict"});var ko={};Re(ko,{runConfirmUiConfig:()=>ut});import*as J from"fs";function gt(e){try{let o=e.split(".")[1];return JSON.parse(Buffer.from(o,"base64url").toString("utf8")).surveyId??null}catch{return null}}async function ut(e={}){let o=process.env.INIT_CWD??process.cwd(),t=K(o);if(!J.existsSync(t.finalPath))throw new Error(`Missing ${t.finalPath}. Run customize-ui with --review and complete the wizard first.`);let n=JSON.parse(J.readFileSync(J.existsSync(t.seedPath)?t.seedPath:t.activeConfigPath,"utf8")),i=JSON.parse(J.readFileSync(t.finalPath,"utf8")),s=Oe(n,i);if(console.log(`
4
4
  ${U.bold}${U.cyan}\u{1F4CB} UI config review${U.reset}
5
- `),console.log(xe(s)),e.diffOnly){J.writeFileSync(t.diffJsonPath,JSON.stringify(s,null,2),"utf8"),J.writeFileSync(t.diffMdPath,xe(s),"utf8"),console.log(`${U.dim} Updated ${t.diffMdPath}${U.reset}`);return}J.writeFileSync(t.activeConfigPath,JSON.stringify(i,null,2),"utf8"),console.log(`${U.green}\u2705 Applied final config \u2192 ${t.activeConfigPath}${U.reset}`);let r=i.global?.logo;if(!r?.fileName)return;let a=process.env.CFM_INSTANCE_ID,l=(process.env.CFM_DEPLOY_API_BASE??"").replace(/\/$/,""),w=a?gt(a):null;try{await Y({projectRoot:o,fileName:r.fileName,logoUrl:r.url,jwt:a??void 0,apiBase:l||void 0,surveyId:w??void 0}),console.log(`${U.green} Logo saved to public/${r.fileName}${U.reset}`),r.url&&console.log(`${U.dim} Public logo URL: ${r.url}${U.reset}`)}catch(y){console.log(`${U.yellow} Logo not downloaded \u2014 ${y instanceof Error?y.message:String(y)}${U.reset}`)}}var U,Po=B(()=>{"use strict";M();Te();Ee();U=c});var Eo={};Re(Eo,{runFetchUiConfig:()=>wt});import*as me from"fs";import*as ut from"http";import*as mt from"https";async function ht(e,o={}){return new Promise((t,n)=>{let i=new URL(e),r=(i.protocol==="https:"?mt:ut).request(i,{method:"GET",headers:o.headers??{}},a=>{let l="";a.on("data",w=>l+=w),a.on("end",()=>{if((a.statusCode??500)>=400){n(new Error(`HTTP ${a.statusCode}: ${l}`));return}try{t(JSON.parse(l))}catch{n(new Error(`Invalid JSON: ${l.slice(0,200)}`))}})});r.on("error",n),r.end()})}function yt(e){try{let o=e.split(".")[1];return JSON.parse(Buffer.from(o,"base64url").toString("utf8")).surveyId??null}catch{return null}}async function wt(e={}){let o=process.env.CFM_INSTANCE_ID,t=(process.env.CFM_DEPLOY_API_BASE??"").replace(/\/$/,""),n=e.sessionId??process.env.CFM_WIZARD_SESSION_ID;if(!o)throw new Error("CFM_INSTANCE_ID (JWT) is required");if(!t)throw new Error("CFM_DEPLOY_API_BASE is required");if(!n)throw new Error("CFM_WIZARD_SESSION_ID or --session= is required");let i=yt(o);if(!i)throw new Error("Could not parse surveyId from CFM_INSTANCE_ID JWT");let s=process.env.INIT_CWD??process.cwd(),r=G(s),a=me.existsSync(r.seedPath)?r.seedPath:r.activeConfigPath;if(!me.existsSync(a))throw new Error(`Missing seed config at ${a}. Run customize-ui --review first.`);let l=await ht(`${t}/wizard/config/${encodeURIComponent(i)}?sessionId=${encodeURIComponent(n)}`,{headers:{Authorization:`Bearer ${o}`}});if(l.status!=="ready"||!l.config)throw new Error(`Wizard not complete yet (status: ${l.status})`);let w=Pe(l)??l.config,y=JSON.parse(me.readFileSync(a,"utf8")),T=ke(s,y,w),C=w.global?.logo;if(C?.fileName)try{await Y({projectRoot:s,fileName:C.fileName,logoUrl:l.logoUrl,jwt:o,apiBase:t,surveyId:i}),console.log(`${L.green} Logo saved to public/${C.fileName}${L.reset}`)}catch(E){console.warn(`${L.yellow} Logo download failed: ${E}${L.reset}`)}console.log(`
6
- ${L.green}\u2705 Fetched final config (review mode)${L.reset}`),console.log(`${L.green} Final: ${r.finalPath}${L.reset}`),console.log(`${L.green} Diff: ${r.diffMdPath}${L.reset}`),console.log(`${L.yellow} ${T.changed.length} changed, ${T.added.length} added, ${T.removed.length} removed${L.reset}`),console.log(`${L.dim} Apply when ready: npx cfm-sdk confirm-ui-config${L.reset}`)}var L,Ro=B(()=>{"use strict";M();Te();Ee();L=c});M();M();import{execSync as Ue,spawn as Fo}from"child_process";function Z(e){try{let o=process.platform==="win32"?`where ${e}`:`command -v ${e}`;return Ue(o,{stdio:"ignore"}),!0}catch{return!1}}var jo={stdio:"inherit",shell:process.platform==="win32"?"cmd.exe":"/bin/sh"};function fe(e,o){try{let t=`${e} ${o.join(" ")}`;return Ue(t,jo),!0}catch{return!1}}function ye(e,o){return new Promise(t=>{Fo(e,o,{stdio:"inherit",shell:!0}).on("close",i=>{t(i)})})}import Ao from"readline/promises";import{stdin as No,stdout as _o}from"process";async function ee(e){let o=Ao.createInterface({input:No,output:_o});try{return(await o.question(e)).trim()}finally{o.close()}}async function ze(){let e=parseInt(process.version.slice(1).split(".")[0],10);if(console.log(`${c.dim}Step 1/4: Checking Node.js version (current: ${process.version})...${c.reset}`),e<18){console.log(`\u26A0\uFE0F ${c.yellow}Outdated Node.js version detected. v18.0.0 or higher is required.${c.reset}`),console.log(`${c.dim}Note: If you already have a higher version installed via nvm, please run 'nvm use <version>' first.${c.reset}
7
- `);let o=await ee("Would you like to install/upgrade Node.js v18+ automatically? (y/N): ");o.toLowerCase()==="y"||o.toLowerCase()==="yes"||(console.log(`
5
+ `),console.log(Te(s)),e.diffOnly){J.writeFileSync(t.diffJsonPath,JSON.stringify(s,null,2),"utf8"),J.writeFileSync(t.diffMdPath,Te(s),"utf8"),console.log(`${U.dim} Updated ${t.diffMdPath}${U.reset}`);return}J.writeFileSync(t.activeConfigPath,JSON.stringify(i,null,2),"utf8"),console.log(`${U.green}\u2705 Applied final config \u2192 ${t.activeConfigPath}${U.reset}`);let r=i.global?.logo;if(!r?.fileName)return;let a=process.env.CFM_INSTANCE_ID,l=(process.env.CFM_DEPLOY_API_BASE??"").replace(/\/$/,""),w=a?gt(a):null;try{await Z({projectRoot:o,fileName:r.fileName,logoUrl:r.url,jwt:a??void 0,apiBase:l||void 0,surveyId:w??void 0}),console.log(`${U.green} Logo saved to public/${r.fileName}${U.reset}`),r.url&&console.log(`${U.dim} Public logo URL: ${r.url}${U.reset}`)}catch(m){console.log(`${U.yellow} Logo not downloaded \u2014 ${m instanceof Error?m.message:String(m)}${U.reset}`)}}var U,Po=B(()=>{"use strict";M();Pe();ve();U=c});var Eo={};Re(Eo,{runFetchUiConfig:()=>wt});import*as he from"fs";import*as pt from"http";import*as mt from"https";async function ht(e,o={}){return new Promise((t,n)=>{let i=new URL(e),r=(i.protocol==="https:"?mt:pt).request(i,{method:"GET",headers:o.headers??{}},a=>{let l="";a.on("data",w=>l+=w),a.on("end",()=>{if((a.statusCode??500)>=400){n(new Error(`HTTP ${a.statusCode}: ${l}`));return}try{t(JSON.parse(l))}catch{n(new Error(`Invalid JSON: ${l.slice(0,200)}`))}})});r.on("error",n),r.end()})}function yt(e){try{let o=e.split(".")[1];return JSON.parse(Buffer.from(o,"base64url").toString("utf8")).surveyId??null}catch{return null}}async function wt(e={}){let o=process.env.CFM_INSTANCE_ID,t=(process.env.CFM_DEPLOY_API_BASE??"").replace(/\/$/,""),n=e.sessionId??process.env.CFM_WIZARD_SESSION_ID;if(!o)throw new Error("CFM_INSTANCE_ID (JWT) is required");if(!t)throw new Error("CFM_DEPLOY_API_BASE is required");if(!n)throw new Error("CFM_WIZARD_SESSION_ID or --session= is required");let i=yt(o);if(!i)throw new Error("Could not parse surveyId from CFM_INSTANCE_ID JWT");let s=process.env.INIT_CWD??process.cwd(),r=K(s),a=he.existsSync(r.seedPath)?r.seedPath:r.activeConfigPath;if(!he.existsSync(a))throw new Error(`Missing seed config at ${a}. Run customize-ui --review first.`);let l=await ht(`${t}/wizard/config/${encodeURIComponent(i)}?sessionId=${encodeURIComponent(n)}`,{headers:{Authorization:`Bearer ${o}`}});if(l.status!=="ready"||!l.config)throw new Error(`Wizard not complete yet (status: ${l.status})`);let w=Ee(l)??l.config,m=JSON.parse(he.readFileSync(a,"utf8")),$=ke(s,m,w),b=w.global?.logo;if(b?.fileName)try{await Z({projectRoot:s,fileName:b.fileName,logoUrl:l.logoUrl,jwt:o,apiBase:t,surveyId:i}),console.log(`${L.green} Logo saved to public/${b.fileName}${L.reset}`)}catch(R){console.warn(`${L.yellow} Logo download failed: ${R}${L.reset}`)}console.log(`
6
+ ${L.green}\u2705 Fetched final config (review mode)${L.reset}`),console.log(`${L.green} Final: ${r.finalPath}${L.reset}`),console.log(`${L.green} Diff: ${r.diffMdPath}${L.reset}`),console.log(`${L.yellow} ${$.changed.length} changed, ${$.added.length} added, ${$.removed.length} removed${L.reset}`),console.log(`${L.dim} Apply when ready: npx cfm-sdk confirm-ui-config${L.reset}`)}var L,vo=B(()=>{"use strict";M();Pe();ve();L=c});M();M();import{execSync as Ue,spawn as jo}from"child_process";function ee(e){try{let o=process.platform==="win32"?`where ${e}`:`command -v ${e}`;return Ue(o,{stdio:"ignore"}),!0}catch{return!1}}var Fo={stdio:"inherit",shell:process.platform==="win32"?"cmd.exe":"/bin/sh"};function fe(e,o){try{let t=`${e} ${o.join(" ")}`;return Ue(t,Fo),!0}catch{return!1}}function we(e,o){return new Promise(t=>{jo(e,o,{stdio:"inherit",shell:!0}).on("close",i=>{t(i)})})}import Ao from"readline/promises";import{stdin as No,stdout as _o}from"process";async function oe(e){let o=Ao.createInterface({input:No,output:_o});try{return(await o.question(e)).trim()}finally{o.close()}}async function ze(){let e=parseInt(process.version.slice(1).split(".")[0],10);if(console.log(`${c.dim}Step 1/4: Checking Node.js version (current: ${process.version})...${c.reset}`),e<18){console.log(`\u26A0\uFE0F ${c.yellow}Outdated Node.js version detected. v18.0.0 or higher is required.${c.reset}`),console.log(`${c.dim}Note: If you already have a higher version installed via nvm, please run 'nvm use <version>' first.${c.reset}
7
+ `);let o=await oe("Would you like to install/upgrade Node.js v18+ automatically? (y/N): ");o.toLowerCase()==="y"||o.toLowerCase()==="yes"||(console.log(`
8
8
  \u274C ${c.red}Aborted. Please manually upgrade Node.js to v18+ and try again.${c.reset}
9
- `),process.exit(1));let n=process.platform==="win32",i=process.platform==="darwin";n?Z("winget")?(console.log(`
9
+ `),process.exit(1));let n=process.platform==="win32",i=process.platform==="darwin";n?ee("winget")?(console.log(`
10
10
  \u{1F4E6} ${c.green}winget package manager found! Installing Node.js v18+ in background...${c.reset}`),fe("winget",["upgrade","OpenJS.NodeJS","--silent","--accept-package-agreements","--accept-source-agreements"])?(console.log(`
11
11
  \u2714 ${c.green}Node.js installation triggered successfully. Please restart your terminal/command-prompt for changes to take effect.${c.reset}
12
12
  `),process.exit(0)):(console.log(`
13
13
  \u274C ${c.red}winget update failed. Please update Node.js manually at https://nodejs.org/${c.reset}
14
14
  `),process.exit(1))):(console.log(`
15
15
  \u274C ${c.red}winget package manager is not installed on this system.${c.reset}`),console.log(`${c.bold}\u{1F449} To proceed, please either:${c.reset}`),console.log(" 1. Install winget (App Installer) from the Microsoft Store."),console.log(` 2. Or manually download and install Node.js (v18+) from: https://nodejs.org/
16
- `),process.exit(1)):i?Z("brew")?(console.log(`
16
+ `),process.exit(1)):i?ee("brew")?(console.log(`
17
17
  \u{1F4E6} ${c.green}Homebrew package manager found! Installing Node.js v18+ in background...${c.reset}`),fe("brew",["install","node"])?console.log(`
18
18
  \u2714 ${c.green}Node.js installed successfully via Homebrew.${c.reset}
19
19
  `):(console.log(`
@@ -23,17 +23,17 @@ ${L.green}\u2705 Fetched final config (review mode)${L.reset}`),console.log(`${L
23
23
  `),process.exit(1)):(console.log(`
24
24
  \u274C ${c.red}Please install or update Node.js to v18+ using your system's package manager.${c.reset}
25
25
  `),process.exit(1))}else console.log(`\u2714 ${c.green}Node.js version (v${e}) is sufficient.${c.reset}`)}M();async function Be(){console.log(`
26
- ${c.dim}Step 2/4: Checking Vercel CLI...${c.reset}`);let e="vercel",o=!1;if(Z("vercel"))console.log(`\u2714 ${c.green}Vercel CLI is installed!${c.reset}`);else{console.log(`\u2753 ${c.yellow}Vercel CLI was not found on your system.${c.reset}`);let t=await ee("\u{1F449} Would you like to install Vercel CLI globally? (Y/n): ");t.toLowerCase()==="y"||t===""?(console.log(`
27
- \u{1F4E5} ${c.cyan}Installing Vercel CLI globally... (npm install -g vercel)${c.reset}`),fe("npm",["install","-g","vercel"])&&Z("vercel")?console.log(`\u2714 ${c.green}Vercel CLI installed successfully!${c.reset}`):(console.log(`
26
+ ${c.dim}Step 2/4: Checking Vercel CLI...${c.reset}`);let e="vercel",o=!1;if(ee("vercel"))console.log(`\u2714 ${c.green}Vercel CLI is installed!${c.reset}`);else{console.log(`\u2753 ${c.yellow}Vercel CLI was not found on your system.${c.reset}`);let t=await oe("\u{1F449} Would you like to install Vercel CLI globally? (Y/n): ");t.toLowerCase()==="y"||t===""?(console.log(`
27
+ \u{1F4E5} ${c.cyan}Installing Vercel CLI globally... (npm install -g vercel)${c.reset}`),fe("npm",["install","-g","vercel"])&&ee("vercel")?console.log(`\u2714 ${c.green}Vercel CLI installed successfully!${c.reset}`):(console.log(`
28
28
  \u26A0\uFE0F ${c.yellow}Global installation failed or permissions restricted.${c.reset}`),console.log(`\u2139 ${c.dim}Falling back: Running Vercel dynamically via npx.${c.reset}`),e="npx --yes vercel",o=!0)):(console.log(`\u2139 ${c.dim}Skipping global installation. Running Vercel dynamically via npx.${c.reset}`),e="npx --yes vercel",o=!0)}return{vercelCmd:e,useNpx:o}}M();import{execSync as Do}from"child_process";var Oo={stdio:"ignore",shell:process.platform==="win32"?"cmd.exe":"/bin/sh"};async function We(e){console.log(`
29
- ${c.dim}Step 3/4: Checking Vercel Login...${c.reset}`);let o=!!process.env.VERCEL_TOKEN,t=!1;if(o)console.log(`\u2714 ${c.green}VERCEL_TOKEN environment variable detected. Skipping login check.${c.reset}`),t=!0;else try{Do(e?"npx --yes vercel whoami":"vercel whoami",Oo),t=!0,console.log(`\u2714 ${c.green}Logged in!${c.reset}`)}catch{t=!1}if(!t){console.log(`\u{1F511} ${c.yellow}Not logged in to Vercel.${c.reset}`),await ee("\u{1F449} Press [Enter] to login to Vercel... ");let n=["login"],i=e?"npx":"vercel",s=e?["--yes","vercel",...n]:n;if(await ye(i,s)!==0)throw new Error("Vercel login failed or was aborted.");console.log(`
29
+ ${c.dim}Step 3/4: Checking Vercel Login...${c.reset}`);let o=!!process.env.VERCEL_TOKEN,t=!1;if(o)console.log(`\u2714 ${c.green}VERCEL_TOKEN environment variable detected. Skipping login check.${c.reset}`),t=!0;else try{Do(e?"npx --yes vercel whoami":"vercel whoami",Oo),t=!0,console.log(`\u2714 ${c.green}Logged in!${c.reset}`)}catch{t=!1}if(!t){console.log(`\u{1F511} ${c.yellow}Not logged in to Vercel.${c.reset}`),await oe("\u{1F449} Press [Enter] to login to Vercel... ");let n=["login"],i=e?"npx":"vercel",s=e?["--yes","vercel",...n]:n;if(await we(i,s)!==0)throw new Error("Vercel login failed or was aborted.");console.log(`
30
30
  \u2714 ${c.green}Logged in successfully!${c.reset}`)}return o}M();async function Je(e,o){console.log(`
31
31
  ${c.dim}Step 4/4: Deploying project to production...${c.reset}`);let t=["--prod","--yes"];o&&t.push("--token",process.env.VERCEL_TOKEN);let n=e?"npx":"vercel",i=e?["--yes","vercel",...t]:t;if(console.log(`${c.cyan}\u26A1 Running deployment in: ${process.cwd()}${c.reset}
32
- `),await ye(n,i)!==0)throw new Error("Vercel deployment failed.");console.log(`
32
+ `),await we(n,i)!==0)throw new Error("Vercel deployment failed.");console.log(`
33
33
  ${c.bold}${c.green}\u{1F389} Deployment completed successfully!${c.reset}
34
34
  `)}async function He(){console.log(`
35
35
  ${c.bold}${c.cyan}\u{1F680} Starting CFM Vercel Deployment...${c.reset}
36
- `),await ze();let{vercelCmd:e,useNpx:o}=await Be(),t=await We(o);await Je(o,t)}M();import*as ue from"http";import*as P from"fs";import*as A from"path";function O(e){return e instanceof Error?e.message:String(e)}pe();M();import*as v from"fs";import*as R from"path";Se();Se();import*as g from"fs";import*as p from"path";import{execSync as Vo}from"child_process";function Q(e,o){if(g.existsSync(e)){g.mkdirSync(o,{recursive:!0});for(let t of g.readdirSync(e,{withFileTypes:!0})){let n=p.join(e,t.name),i=p.join(o,t.name);t.isDirectory()?Q(n,i):g.copyFileSync(n,i)}}}function Ae(e){let o=[],t=e;for(let n=0;n<6;n++){let i=p.join(t,"node_modules");g.existsSync(i)&&o.push(i);let s=p.dirname(t);if(s===t)break;t=s}return o}function Xo(e,o){let t=Ae(e);for(let n of t)for(let i of["@explorer02/cfm-survey-sdk","@repo/sdk"])for(let s of["mjs","js"]){let r=p.join(n,i,"dist",`index.${s}`);if(g.existsSync(r))return r}for(let n of["mjs","js"]){let i=p.join(o,"dist",`index.${n}`);if(g.existsSync(i))return i}throw new Error("Could not resolve @explorer02/cfm-survey-sdk for preview build")}function qo(e,o){let t=[...Ae(o).map(n=>p.join(n,"vite","bin","vite.js")),p.join(e,"node_modules","vite","bin","vite.js")];for(let n of t)if(g.existsSync(n))return n;throw new Error("Vite is required for agent preview builds. Install vite in the project or SDK package.")}function Qo(e){let o=p.join(e,"src","components");if(!g.existsSync(p.join(o,"Question.tsx")))throw new Error(`Missing src/components/Question.tsx in ${e}. Build the survey UI before export-previews.`);let t=p.join(e,"src","lib"),n=p.join(e,"public");return{componentsDir:o,libDir:g.existsSync(t)?t:void 0,publicDir:g.existsSync(n)?n:void 0}}function Go(e){let o=`import React from 'react';
36
+ `),await ze();let{vercelCmd:e,useNpx:o}=await Be(),t=await We(o);await Je(o,t)}M();import*as me from"http";import*as P from"fs";import*as A from"path";function O(e){return e instanceof Error?e.message:String(e)}ue();M();import*as v from"fs";import*as E from"path";Ce();Ce();import*as u from"fs";import*as p from"path";import{execSync as Vo}from"child_process";function G(e,o){if(u.existsSync(e)){u.mkdirSync(o,{recursive:!0});for(let t of u.readdirSync(e,{withFileTypes:!0})){let n=p.join(e,t.name),i=p.join(o,t.name);t.isDirectory()?G(n,i):u.copyFileSync(n,i)}}}function Ae(e){let o=[],t=e;for(let n=0;n<6;n++){let i=p.join(t,"node_modules");u.existsSync(i)&&o.push(i);let s=p.dirname(t);if(s===t)break;t=s}return o}function Xo(e,o){let t=Ae(e);for(let n of t)for(let i of["@explorer02/cfm-survey-sdk","@repo/sdk"])for(let s of["mjs","js"]){let r=p.join(n,i,"dist",`index.${s}`);if(u.existsSync(r))return r}for(let n of["mjs","js"]){let i=p.join(o,"dist",`index.${n}`);if(u.existsSync(i))return i}throw new Error("Could not resolve @explorer02/cfm-survey-sdk for preview build")}function qo(e,o){let t=[...Ae(o).map(n=>p.join(n,"vite","bin","vite.js")),p.join(e,"node_modules","vite","bin","vite.js")];for(let n of t)if(u.existsSync(n))return n;throw new Error("Vite is required for agent preview builds. Install vite in the project or SDK package.")}function Qo(e){let o=p.join(e,"src","components");if(!u.existsSync(p.join(o,"Question.tsx")))throw new Error(`Missing src/components/Question.tsx in ${e}. Build the survey UI before export-previews.`);let t=p.join(e,"src","lib"),n=p.join(e,"public");return{componentsDir:o,libDir:u.existsSync(t)?t:void 0,publicDir:u.existsSync(n)?n:void 0}}function Go(e){let o=`import React from 'react';
37
37
  import { mountPreview } from '../mount';
38
38
  `;switch(e){case"header":return`${o}import Header from '@/components/Header';
39
39
  import ProgressBar from '@/components/ProgressBar';
@@ -111,36 +111,37 @@ ${s}
111
111
  },
112
112
  },
113
113
  });
114
- `;g.writeFileSync(p.join(e,"vite.config.mjs"),r)}function Yo(e,o){let t=g.readFileSync(e,"utf8");if(t.includes("preview-bridge.inline"))return;let n=`<script>${o}</script>`;t=t.includes("</body>")?t.replace("</body>",`${n}
114
+ `;u.writeFileSync(p.join(e,"vite.config.mjs"),r)}function Yo(e,o){let t=u.readFileSync(e,"utf8");if(t.includes("preview-bridge.inline"))return;let n=`<script>${o}</script>`;t=t.includes("</body>")?t.replace("</body>",`${n}
115
115
  </body>`):`${t}
116
- ${n}`,g.writeFileSync(e,t)}function Zo(e){return e.replace(/_/g," ")}async function lo(e){let{projectRoot:o,outputDir:t,keys:n}=e,i=p.join(__dirname,"..",".."),s=p.join(i,"templates","preview-harness","vite-app");if(!g.existsSync(s))throw new Error(`Missing Vite preview harness template at ${s}`);let r=Qo(o),a=p.join(t,".preview-vite-work");g.existsSync(a)&&g.rmSync(a,{recursive:!0,force:!0}),Q(s,a),g.mkdirSync(p.join(a,"agent","src"),{recursive:!0}),Q(r.componentsDir,p.join(a,"agent","src","components")),r.libDir&&Q(r.libDir,p.join(a,"agent","src","lib")),r.publicDir&&Q(r.publicDir,p.join(a,"agent","public"));let l=te(o),w=p.join(a,"src","survey-theme.css");g.writeFileSync(w,l?g.readFileSync(l,"utf8"):g.readFileSync(p.join(i,"templates","survey-theme.css"),"utf8")),g.mkdirSync(p.join(a,"src","entries"),{recursive:!0});for(let u of n)g.mkdirSync(p.join(a,u),{recursive:!0}),g.writeFileSync(p.join(a,u,"index.html"),`<!DOCTYPE html>
116
+ ${n}`,u.writeFileSync(e,t)}function Zo(e){return e.replace(/_/g," ")}async function lo(e){let{projectRoot:o,outputDir:t,keys:n}=e,i=p.join(__dirname,"..",".."),s=p.join(i,"templates","preview-harness","vite-app");if(!u.existsSync(s))throw new Error(`Missing Vite preview harness template at ${s}`);let r=Qo(o),a=p.join(t,".preview-vite-work");u.existsSync(a)&&u.rmSync(a,{recursive:!0,force:!0}),G(s,a),u.mkdirSync(p.join(a,"agent","src"),{recursive:!0}),G(r.componentsDir,p.join(a,"agent","src","components")),r.libDir&&G(r.libDir,p.join(a,"agent","src","lib")),r.publicDir&&G(r.publicDir,p.join(a,"agent","public"));let l=te(o),w=p.join(a,"src","survey-theme.css");u.writeFileSync(w,l?u.readFileSync(l,"utf8"):u.readFileSync(p.join(i,"templates","survey-theme.css"),"utf8")),u.mkdirSync(p.join(a,"src","entries"),{recursive:!0});for(let g of n)u.mkdirSync(p.join(a,g),{recursive:!0}),u.writeFileSync(p.join(a,g,"index.html"),`<!DOCTYPE html>
117
117
  <html lang="en">
118
118
  <head>
119
119
  <meta charset="UTF-8" />
120
120
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
121
- <title>${Zo(u)} \u2014 CFM Preview</title>
121
+ <title>${Zo(g)} \u2014 CFM Preview</title>
122
122
  </head>
123
123
  <body>
124
124
  <div id="root"></div>
125
- <script type="module" src="../src/entries/${u}.tsx"></script>
125
+ <script type="module" src="../src/entries/${g}.tsx"></script>
126
126
  </body>
127
- </html>`),g.writeFileSync(p.join(a,"src","entries",`${u}.tsx`),Go(u));g.writeFileSync(p.join(a,"tsconfig.json"),JSON.stringify({compilerOptions:{target:"ES2020",lib:["ES2020","DOM","DOM.Iterable"],module:"ESNext",moduleResolution:"bundler",jsx:"react-jsx",strict:!0,skipLibCheck:!0,paths:{"@/*":["./agent/src/*"]}},include:["src","agent/src","stubs"]},null,2)),Ko(a,o,i,n);let y=qo(i,o),T=Ae(o).join(p.delimiter);Vo(`node "${y}" build --config "${p.join(a,"vite.config.mjs")}"`,{cwd:a,stdio:"inherit",env:{...process.env,NODE_PATH:T}});let C=p.join(t,"previews");g.mkdirSync(C,{recursive:!0});let E=p.join(a,"dist"),I=g.readFileSync(p.join(i,"templates","preview-harness","preview-bridge.inline.js"),"utf8");for(let u of n){let h=p.join(E,u),x=p.join(C,u);if(!g.existsSync(p.join(h,"index.html")))throw new Error(`Vite build did not produce ${u}/index.html`);g.existsSync(x)&&g.rmSync(x,{recursive:!0,force:!0}),Q(h,x),Yo(p.join(x,"index.html"),I)}let m=p.join(E,"assets");g.existsSync(m)&&Q(m,p.join(C,"assets"));let f=p.join(a,"agent","public");if(g.existsSync(f))for(let u of g.readdirSync(f)){let h=p.join(f,u);g.statSync(h).isFile()&&g.copyFileSync(h,p.join(C,u))}g.rmSync(a,{recursive:!0,force:!0})}import*as Ne from"fs";import*as _e from"path";function Ce(e){if(e)return e;let o=process.cwd();if(Ne.existsSync(_e.join(o,"src","components","Question.tsx")))return o;let t=process.env.INIT_CWD;return t&&Ne.existsSync(_e.join(t,"src","components","Question.tsx"))?t:o}var _=c;function et(){return R.join(__dirname,"..","..","templates")}function ot(e){let o=v.readFileSync(e,"utf8"),t=new Set,n=["MCQ","TEXTFIELD","NPS_SCALE","CFM_MATRIX","CSAT_MATRIX","RATING_MATRIX","SLIDER_MATRIX","FILE_UPLOAD","TEXT_AND_MEDIA","HEATMAP","RANK_ORDER"];for(let i of n)o.includes(i)&&t.add(i);return t.size?[...t]:n}function tt(e,o){let t=["header","footer","chrome","survey_page","intro","end"],n={MCQ:["MCQ_single","MCQ_multiple"],TEXTFIELD:["TEXTFIELD_short","TEXTFIELD_long"],NPS_SCALE:["NPS_SCALE"],CFM_MATRIX:["CFM_likert","CFM_bipolar"],CSAT_MATRIX:["CSAT_emoji","CSAT_star","CSAT_numbered","CSAT_graphics","CSAT_carousel","CSAT_dropdown"],RATING_MATRIX:["RATING_star","RATING_numbered","RATING_radio","RATING_emoji","RATING_graphics","RATING_slider"],SLIDER_MATRIX:["SLIDER_matrix"],FILE_UPLOAD:["FILE_UPLOAD"],HEATMAP:["HEATMAP"],RANK_ORDER:["RANK_drag","RANK_dropdown"]},i=new Set(t);for(let s of o)for(let r of n[s]??[])i.add(r);return e.filter(s=>i.has(s))}function De(e,o,t){if(v.existsSync(e))for(let n of v.readdirSync(e)){let i=R.join(e,n),s=R.posix.join(o,n);if(v.statSync(i).isDirectory())De(i,s,t);else{let r=R.extname(n).toLowerCase(),a=r===".html"?"text/html":r===".css"?"text/css":r===".js"?"application/javascript":r===".json"?"application/json":r===".svg"?"image/svg+xml":r===".jpg"||r===".jpeg"?"image/jpeg":r===".png"?"image/png":"application/octet-stream";t.push({path:s,contentType:a,sizeBytes:v.statSync(i).size})}}}async function re(e={}){let o=Ce(e.projectRoot),t=e.outputDir??R.join(o,"out"),n=et(),i=R.join(n,"preview-harness");e.useTemplatesOnly&&console.log(`${_.dim} Using SDK template preview harness only (--use-templates-only)${_.reset}`);let s=R.join(i,"previewPages.js"),{PREVIEW_PAGE_DEFS:r,buildPreviewHtml:a,PREVIEW_KEYS:l}=he(s),w=(()=>{let f=te(o);return f?(console.log(`${_.dim} Using project theme: ${R.relative(o,f)}${_.reset}`),v.readFileSync(f,"utf8")):v.readFileSync(R.join(n,"survey-theme.css"),"utf8")})(),y=v.readFileSync(R.join(i,"preview-bridge.inline.js"),"utf8"),T=e.surveyTypes;if(!T){let f=R.join(o,"implementation_plan.md");T=v.existsSync(f)?ot(f):["MCQ","TEXTFIELD","NPS_SCALE","CFM_MATRIX","CSAT_MATRIX","RATING_MATRIX","SLIDER_MATRIX","FILE_UPLOAD","TEXT_AND_MEDIA","HEATMAP","RANK_ORDER"]}let C=tt(l,T),E=R.join(t,"previews");if(v.existsSync(E)&&(v.rmSync(E,{recursive:!0,force:!0}),console.log(`${_.dim} Cleared previous preview output${_.reset}`)),v.mkdirSync(E,{recursive:!0}),!e.useTemplatesOnly)try{console.log(`${_.dim} Building previews from agent components (Vite)\u2026${_.reset}`),await lo({projectRoot:o,outputDir:t,keys:C});let f={};for(let h of C)f[h]=`previews/${h}/index.html`;v.writeFileSync(R.join(t,"previews","manifest.json"),JSON.stringify(f,null,2));let u=[];return De(R.join(t,"previews"),"previews",u),console.log(`${_.green}\u2705 Exported ${C.length} agent component previews \u2192 ${t}${_.reset}`),{outputDir:t,manifestPath:R.join(t,"previews","manifest.json"),files:u,surveyTypes:T}}catch(f){console.warn(`${_.yellow}\u26A0 Agent Vite preview build failed; falling back to template harness.${_.reset}`),console.warn(`${_.dim} ${O(f)}${_.reset}`)}for(let f of r){if(!C.includes(f.key))continue;let u=R.join(t,"previews",f.key);v.mkdirSync(u,{recursive:!0}),v.writeFileSync(R.join(u,"index.html"),a(f,w,y))}let I={};for(let f of C)I[f]=`previews/${f}/index.html`;v.writeFileSync(R.join(t,"previews","manifest.json"),JSON.stringify(I,null,2));let m=[];return De(R.join(t,"previews"),"previews",m),console.log(`${_.green}\u2705 Exported ${C.length} preview pages \u2192 ${t}${_.reset}`),{outputDir:t,manifestPath:R.join(t,"previews","manifest.json"),files:m,surveyTypes:T}}var D=c,$e=["MCQ","TEXTFIELD","NPS_SCALE","CFM_MATRIX","CSAT_MATRIX","RATING_MATRIX","SLIDER_MATRIX","FILE_UPLOAD","TEXT_AND_MEDIA","HEATMAP","RANK_ORDER"];function po(e){return new Promise(o=>{let t=ue.createServer();t.listen(e,()=>{t.close(()=>o(e))}),t.on("error",()=>o(po(e+1)))})}function fo(e){return new Promise((o,t)=>{let n="";e.on("data",i=>n+=i),e.on("end",()=>o(n)),e.on("error",t)})}function nt(e){let{exec:o}=he("child_process"),t=process.platform==="darwin"?`open "${e}"`:process.platform==="win32"?`start "" "${e}"`:`xdg-open "${e}"`;o(t)}function go(e){let o=A.extname(e).toLowerCase();return{".html":"text/html",".js":"application/javascript",".css":"text/css",".json":"application/json",".svg":"image/svg+xml",".png":"image/png",".jpg":"image/jpeg",".woff2":"font/woff2",".ico":"image/x-icon"}[o]??"application/octet-stream"}function it(e){let o=new Set,t,n=e.match(/\*\*instanceId:\*\*\s*(.+)/i);if(n){let s=n[1].replace(/[()[\]]/g,"").trim();s&&!s.startsWith("(")&&s!=="JWT"&&(t=s)}for(let s of $e)e.includes(s)&&o.add(s);let i=e.matchAll(/\|\s*`([A-Z_]+)`\s*\|/g);for(let s of i)$e.includes(s[1])&&o.add(s[1]);return{surveyTypes:o.size>0?[...o]:[...$e],instanceId:t}}async function rt(e){return new Promise(o=>{try{let t=ue.get(e,n=>{o((n.statusCode??500)<500),n.resume()});t.on("error",()=>o(!1)),t.setTimeout(2e3,()=>{t.destroy(),o(!1)})}catch{o(!1)}})}async function uo(){let e=process.env.INIT_CWD||process.cwd(),o=A.join(e,"public"),t=A.join(e,"survey-ui-config.json"),n=A.join(e,"implementation_plan.md"),i=A.join(__dirname,"..","..","templates"),s=A.join(i,"wizard-dist"),r=process.env.CFM_PREVIEW_URL??"http://localhost:3000",a={},l=A.join(e,"out","previews"),w=A.join(l,"manifest.json");P.existsSync(w)||(console.log(`${D.dim} Exporting component previews for local wizard\u2026${D.reset}`),await re({projectRoot:e})),P.existsSync(w)&&(a=JSON.parse(P.readFileSync(w,"utf8")));let y=await po(4200),T=`http://localhost:${y}`;return new Promise((C,E)=>{let I=ue.createServer(async(m,f)=>{try{let u=m.url??"/";if(m.method==="GET"&&u==="/api/inventory"){let h=[...$e],x;if(P.existsSync(n)){let $=P.readFileSync(n,"utf8"),k=it($);h=k.surveyTypes,x=k.instanceId}if(P.existsSync(t))try{let $=JSON.parse(P.readFileSync(t,"utf8"));$.surveyTypes?.length&&(h=$.surveyTypes),$.instanceId&&(x=$.instanceId)}catch{}let{config:S}=ie({projectRoot:e,surveyTypes:h,instanceId:x});f.writeHead(200,{"Content-Type":"application/json"}),f.end(JSON.stringify({surveyTypes:h,instanceId:x,previewUrl:r,initialConfig:S,previewManifest:Object.fromEntries(Object.keys(a).map($=>[$,`${T}/previews/${$}/index.html`]))}));return}if(m.method==="GET"&&u==="/api/preview-url"){let h=await rt(r);f.writeHead(200,{"Content-Type":"application/json"}),f.end(JSON.stringify({url:r,connected:h}));return}if(m.method==="POST"&&u==="/api/upload-logo"){let h=await fo(m),x=JSON.parse(h);P.existsSync(o)||P.mkdirSync(o,{recursive:!0});let S=x.base64.replace(/^data:image\/\w+;base64,/,""),$=Buffer.from(S,"base64"),k=A.extname(x.filename),j=A.basename(x.filename,k).toLowerCase().replace(/[^a-z0-9_-]/g,""),z=`logo_${Date.now()}_${j}${k||".png"}`;P.writeFileSync(A.join(o,z),$),f.writeHead(200,{"Content-Type":"application/json"}),f.end(JSON.stringify({fileName:z}));return}if(m.method==="POST"&&u==="/api/save-config"){let h=await fo(m),x=JSON.parse(h);x.configuredAt=new Date().toISOString(),P.writeFileSync(t,JSON.stringify(x,null,2),"utf8"),console.log(`
128
- ${D.green}\u2705 UI configuration saved to ${t}${D.reset}`),f.writeHead(200,{"Content-Type":"application/json"}),f.end(JSON.stringify({ok:!0})),setTimeout(()=>{I.close(()=>C())},500);return}if(m.method==="GET"){let h=u.split("?")[0];if(h==="/"&&(h="/index.html"),h.startsWith("/previews/")&&P.existsSync(l)){let $=h.replace(/^\/previews\//,""),k=A.join(l,$),j=A.normalize(k);if(j.startsWith(l)&&P.existsSync(j)&&P.statSync(j).isFile()){let z=P.readFileSync(j);f.writeHead(200,{"Content-Type":go(j)}),f.end(z);return}}let x=P.existsSync(s),S=x?A.join(s,h):A.join(i,"wizard.html");if(x&&P.existsSync(S)&&P.statSync(S).isFile()){let $=P.readFileSync(S);f.writeHead(200,{"Content-Type":go(S)}),f.end($);return}if(!x&&h==="/index.html"){let $=P.readFileSync(A.join(i,"wizard.html"),"utf8");f.writeHead(200,{"Content-Type":"text/html"}),f.end($);return}}f.writeHead(404,{"Content-Type":"text/plain"}),f.end("Not found")}catch(u){f.writeHead(500,{"Content-Type":"text/plain"}),f.end(`Server error: ${O(u)}`)}});I.listen(y,()=>{let m=T;console.log(`
129
- ${D.bold}${D.cyan}\u{1F3A8} Survey UI Customization Wizard${D.reset}`),console.log(`${D.dim} Running at ${D.reset}${D.green}${m}${D.reset}`),console.log(`${D.dim} Live previews: ${D.reset}${Object.keys(a).length} components`),console.log(`${D.dim} Preview target: ${D.reset}${r}
130
- `),nt(m)}),I.on("error",E)})}M();import*as le from"fs";import*as Co from"path";import*as $o from"http";import*as xo from"https";pe();Te();Ee();var d=c;function at(e){let{exec:o}=he("child_process"),t=process.platform==="darwin"?`open "${e}"`:process.platform==="win32"?`start "" "${e}"`:`xdg-open "${e}"`;o(t)}function lt(e){return new Promise(o=>setTimeout(o,e))}async function Me(e,o={}){return new Promise((t,n)=>{let i=new URL(e),r=(i.protocol==="https:"?xo:$o).request(i,{method:o.method??"GET",headers:o.headers??{}},a=>{let l="";a.on("data",w=>l+=w),a.on("end",()=>{if((a.statusCode??500)>=400){n(new Error(`HTTP ${a.statusCode}: ${l}`));return}try{t(JSON.parse(l))}catch{n(new Error(`Invalid JSON: ${l.slice(0,200)}`))}})});r.on("error",n),o.body&&r.write(o.body),r.end()})}async function ft(e,o,t){return new Promise((n,i)=>{let s=new URL(e),a=(s.protocol==="https:"?xo:$o).request(s,{method:"PUT",headers:{"Content-Type":t,"Content-Length":o.length}},l=>{if((l.statusCode??500)>=400){let w="";l.on("data",y=>w+=y),l.on("end",()=>i(new Error(`PUT failed ${l.statusCode}: ${w}`)));return}l.resume(),n()});a.on("error",i),a.write(o),a.end()})}function dt(e){try{let o=e.split(".")[1];return JSON.parse(Buffer.from(o,"base64url").toString("utf8")).surveyId??null}catch{return null}}async function ko(e={}){let o=e.wait!==!1,t=e.pollIntervalMs??Number(process.env.CFM_WIZARD_POLL_MS??3e3),n=e.timeoutMs??Number(process.env.CFM_WIZARD_TIMEOUT_MS??72e5),i=process.env.CFM_INSTANCE_ID,s=(process.env.CFM_DEPLOY_API_BASE??"http://localhost:3000").replace(/\/$/,"");if(!i)throw new Error("CFM_INSTANCE_ID (JWT) is required");let r=dt(i);if(!r)throw new Error("Could not parse surveyId from CFM_INSTANCE_ID JWT");let a=Ce(),l=G(a),w=l.activeConfigPath,y=e.apply?!1:e.review!==!1;console.log(`
127
+ </html>`),u.writeFileSync(p.join(a,"src","entries",`${g}.tsx`),Go(g));u.writeFileSync(p.join(a,"tsconfig.json"),JSON.stringify({compilerOptions:{target:"ES2020",lib:["ES2020","DOM","DOM.Iterable"],module:"ESNext",moduleResolution:"bundler",jsx:"react-jsx",strict:!0,skipLibCheck:!0,paths:{"@/*":["./agent/src/*"]}},include:["src","agent/src","stubs"]},null,2)),Ko(a,o,i,n);let m=qo(i,o),$=Ae(o).join(p.delimiter);Vo(`node "${m}" build --config "${p.join(a,"vite.config.mjs")}"`,{cwd:a,stdio:"inherit",env:{...process.env,NODE_PATH:$}});let b=p.join(t,"previews");u.mkdirSync(b,{recursive:!0});let R=p.join(a,"dist"),I=u.readFileSync(p.join(i,"templates","preview-harness","preview-bridge.inline.js"),"utf8");for(let g of n){let y=p.join(R,g),x=p.join(b,g);if(!u.existsSync(p.join(y,"index.html")))throw new Error(`Vite build did not produce ${g}/index.html`);u.existsSync(x)&&u.rmSync(x,{recursive:!0,force:!0}),G(y,x),Yo(p.join(x,"index.html"),I)}let h=p.join(R,"assets");u.existsSync(h)&&G(h,p.join(b,"assets"));let f=p.join(a,"agent","public");if(u.existsSync(f))for(let g of u.readdirSync(f)){let y=p.join(f,g);u.statSync(y).isFile()&&u.copyFileSync(y,p.join(b,g))}u.rmSync(a,{recursive:!0,force:!0})}import*as Ne from"fs";import*as _e from"path";function xe(e){if(e)return e;let o=process.cwd();if(Ne.existsSync(_e.join(o,"src","components","Question.tsx")))return o;let t=process.env.INIT_CWD;return t&&Ne.existsSync(_e.join(t,"src","components","Question.tsx"))?t:o}var D=c;function et(){return E.join(__dirname,"..","..","templates")}function ot(e){let o=v.readFileSync(e,"utf8"),t=new Set,n=["MCQ","TEXTFIELD","NPS_SCALE","CFM_MATRIX","CSAT_MATRIX","RATING_MATRIX","SLIDER_MATRIX","FILE_UPLOAD","TEXT_AND_MEDIA","HEATMAP","RANK_ORDER"];for(let i of n)o.includes(i)&&t.add(i);return t.size?[...t]:n}function tt(e,o){let t=["header","footer","chrome","survey_page","intro","end"],n={MCQ:["MCQ_single","MCQ_multiple"],TEXTFIELD:["TEXTFIELD_short","TEXTFIELD_long"],NPS_SCALE:["NPS_SCALE"],CFM_MATRIX:["CFM_likert","CFM_bipolar"],CSAT_MATRIX:["CSAT_emoji","CSAT_star","CSAT_numbered","CSAT_graphics","CSAT_carousel","CSAT_dropdown"],RATING_MATRIX:["RATING_star","RATING_numbered","RATING_radio","RATING_emoji","RATING_graphics","RATING_slider"],SLIDER_MATRIX:["SLIDER_matrix"],FILE_UPLOAD:["FILE_UPLOAD"],HEATMAP:["HEATMAP"],RANK_ORDER:["RANK_drag","RANK_dropdown"]},i=new Set(t);for(let s of o)for(let r of n[s]??[])i.add(r);return e.filter(s=>i.has(s))}function De(e,o,t){if(v.existsSync(e))for(let n of v.readdirSync(e)){let i=E.join(e,n),s=E.posix.join(o,n);if(v.statSync(i).isDirectory())De(i,s,t);else{let r=E.extname(n).toLowerCase(),a=r===".html"?"text/html":r===".css"?"text/css":r===".js"?"application/javascript":r===".json"?"application/json":r===".svg"?"image/svg+xml":r===".jpg"||r===".jpeg"?"image/jpeg":r===".png"?"image/png":"application/octet-stream";t.push({path:s,contentType:a,sizeBytes:v.statSync(i).size})}}}async function re(e={}){let o=xe(e.projectRoot),t=e.outputDir??E.join(o,"out"),n=et(),i=E.join(n,"preview-harness");e.useTemplatesOnly&&console.log(`${D.dim} Using SDK template preview harness only (--use-templates-only)${D.reset}`);let s=E.join(i,"previewPages.js"),{PREVIEW_PAGE_DEFS:r,buildPreviewHtml:a,PREVIEW_KEYS:l}=ye(s),w=(()=>{let f=te(o);return f?(console.log(`${D.dim} Using project theme: ${E.relative(o,f)}${D.reset}`),v.readFileSync(f,"utf8")):v.readFileSync(E.join(n,"survey-theme.css"),"utf8")})(),m=v.readFileSync(E.join(i,"preview-bridge.inline.js"),"utf8"),$=e.surveyTypes;if(!$){let f=E.join(o,"implementation_plan.md");$=v.existsSync(f)?ot(f):["MCQ","TEXTFIELD","NPS_SCALE","CFM_MATRIX","CSAT_MATRIX","RATING_MATRIX","SLIDER_MATRIX","FILE_UPLOAD","TEXT_AND_MEDIA","HEATMAP","RANK_ORDER"]}let b=tt(l,$),R=E.join(t,"previews");if(v.existsSync(R)&&(v.rmSync(R,{recursive:!0,force:!0}),console.log(`${D.dim} Cleared previous preview output${D.reset}`)),v.mkdirSync(R,{recursive:!0}),!e.useTemplatesOnly)try{console.log(`${D.dim} Building previews from agent components (Vite)\u2026${D.reset}`),await lo({projectRoot:o,outputDir:t,keys:b});let f={};for(let y of b)f[y]=`previews/${y}/index.html`;v.writeFileSync(E.join(t,"previews","manifest.json"),JSON.stringify(f,null,2));let g=[];return De(E.join(t,"previews"),"previews",g),console.log(`${D.green}\u2705 Exported ${b.length} agent component previews \u2192 ${t}${D.reset}`),{outputDir:t,manifestPath:E.join(t,"previews","manifest.json"),files:g,surveyTypes:$}}catch(f){console.warn(`${D.yellow}\u26A0 Agent Vite preview build failed; falling back to template harness.${D.reset}`),console.warn(`${D.dim} ${O(f)}${D.reset}`)}for(let f of r){if(!b.includes(f.key))continue;let g=E.join(t,"previews",f.key);v.mkdirSync(g,{recursive:!0}),v.writeFileSync(E.join(g,"index.html"),a(f,w,m))}let I={};for(let f of b)I[f]=`previews/${f}/index.html`;v.writeFileSync(E.join(t,"previews","manifest.json"),JSON.stringify(I,null,2));let h=[];return De(E.join(t,"previews"),"previews",h),console.log(`${D.green}\u2705 Exported ${b.length} preview pages \u2192 ${t}${D.reset}`),{outputDir:t,manifestPath:E.join(t,"previews","manifest.json"),files:h,surveyTypes:$}}var _=c,pe=["MCQ","TEXTFIELD","NPS_SCALE","CFM_MATRIX","CSAT_MATRIX","RATING_MATRIX","SLIDER_MATRIX","FILE_UPLOAD","TEXT_AND_MEDIA","HEATMAP","RANK_ORDER"];function uo(e){return new Promise(o=>{let t=me.createServer();t.listen(e,()=>{t.close(()=>o(e))}),t.on("error",()=>o(uo(e+1)))})}function fo(e){return new Promise((o,t)=>{let n="";e.on("data",i=>n+=i),e.on("end",()=>o(n)),e.on("error",t)})}function nt(e){let{exec:o}=ye("child_process"),t=process.platform==="darwin"?`open "${e}"`:process.platform==="win32"?`start "" "${e}"`:`xdg-open "${e}"`;o(t)}function go(e){let o=A.extname(e).toLowerCase();return{".html":"text/html",".js":"application/javascript",".css":"text/css",".json":"application/json",".svg":"image/svg+xml",".png":"image/png",".jpg":"image/jpeg",".woff2":"font/woff2",".ico":"image/x-icon"}[o]??"application/octet-stream"}function it(e){let o=new Set,t,n=e.match(/\*\*instanceId:\*\*\s*(.+)/i);if(n){let s=n[1].replace(/[()[\]]/g,"").trim();s&&!s.startsWith("(")&&s!=="JWT"&&(t=s)}for(let s of pe)e.includes(s)&&o.add(s);let i=e.matchAll(/\|\s*`([A-Z_]+)`\s*\|/g);for(let s of i)pe.includes(s[1])&&o.add(s[1]);return{surveyTypes:o.size>0?[...o]:[...pe],instanceId:t}}async function rt(e){return new Promise(o=>{try{let t=me.get(e,n=>{o((n.statusCode??500)<500),n.resume()});t.on("error",()=>o(!1)),t.setTimeout(2e3,()=>{t.destroy(),o(!1)})}catch{o(!1)}})}async function po(){let e=process.env.INIT_CWD||process.cwd(),o=A.join(e,"public"),t=A.join(e,"survey-ui-config.json"),n=A.join(e,"implementation_plan.md"),i=A.join(__dirname,"..","..","templates"),s=A.join(i,"wizard-dist"),r=process.env.CFM_PREVIEW_URL??"http://localhost:3000",a={},l=A.join(e,"out","previews"),w=A.join(l,"manifest.json");P.existsSync(w)||(console.log(`${_.dim} Exporting component previews for local wizard\u2026${_.reset}`),await re({projectRoot:e,surveyTypes:[...pe]})),P.existsSync(w)&&(a=JSON.parse(P.readFileSync(w,"utf8")));let m=await uo(4200),$=`http://localhost:${m}`;return new Promise((b,R)=>{let I=me.createServer(async(h,f)=>{try{let g=h.url??"/";if(h.method==="GET"&&g==="/api/inventory"){let y;if(P.existsSync(n)){let T=P.readFileSync(n,"utf8");y=it(T).instanceId}if(P.existsSync(t))try{let T=JSON.parse(P.readFileSync(t,"utf8"));T.instanceId&&(y=T.instanceId)}catch{}let x=[...pe],{config:S}=ie({projectRoot:e,surveyTypes:x,instanceId:y});f.writeHead(200,{"Content-Type":"application/json"}),f.end(JSON.stringify({surveyTypes:x,instanceId:y,previewUrl:r,initialConfig:S,previewManifest:Object.fromEntries(Object.keys(a).map(T=>[T,`${$}/previews/${T}/index.html`]))}));return}if(h.method==="GET"&&g==="/api/preview-url"){let y=await rt(r);f.writeHead(200,{"Content-Type":"application/json"}),f.end(JSON.stringify({url:r,connected:y}));return}if(h.method==="POST"&&g==="/api/upload-logo"){let y=await fo(h),x=JSON.parse(y);P.existsSync(o)||P.mkdirSync(o,{recursive:!0});let S=x.base64.replace(/^data:image\/\w+;base64,/,""),T=Buffer.from(S,"base64"),k=A.extname(x.filename),F=A.basename(x.filename,k).toLowerCase().replace(/[^a-z0-9_-]/g,""),z=`logo_${Date.now()}_${F}${k||".png"}`;P.writeFileSync(A.join(o,z),T),f.writeHead(200,{"Content-Type":"application/json"}),f.end(JSON.stringify({fileName:z}));return}if(h.method==="POST"&&g==="/api/save-config"){let y=await fo(h),x=JSON.parse(y);x.configuredAt=new Date().toISOString();let S=x.global?.logo;S?.url?.startsWith("data:")&&(S.url=null),P.writeFileSync(t,JSON.stringify(x,null,2),"utf8"),console.log(`
128
+ ${_.green}\u2705 UI configuration saved to ${t}${_.reset}`),f.writeHead(200,{"Content-Type":"application/json"}),f.end(JSON.stringify({ok:!0})),setTimeout(()=>{I.close(()=>b())},500);return}if(h.method==="GET"){let y=g.split("?")[0];if(y==="/"&&(y="/index.html"),y.startsWith("/previews/")&&P.existsSync(l)){let T=y.replace(/^\/previews\//,""),k=A.join(l,T),F=A.normalize(k);if(F.startsWith(l)&&P.existsSync(F)&&P.statSync(F).isFile()){let z=P.readFileSync(F);f.writeHead(200,{"Content-Type":go(F)}),f.end(z);return}}let x=P.existsSync(s),S=x?A.join(s,y):A.join(i,"wizard.html");if(x&&P.existsSync(S)&&P.statSync(S).isFile()){let T=P.readFileSync(S);f.writeHead(200,{"Content-Type":go(S)}),f.end(T);return}if(!x&&y==="/index.html"){let T=P.readFileSync(A.join(i,"wizard.html"),"utf8");f.writeHead(200,{"Content-Type":"text/html"}),f.end(T);return}}f.writeHead(404,{"Content-Type":"text/plain"}),f.end("Not found")}catch(g){f.writeHead(500,{"Content-Type":"text/plain"}),f.end(`Server error: ${O(g)}`)}});I.listen(m,()=>{let h=$;console.log(`
129
+ ${_.bold}${_.cyan}\u{1F3A8} Survey UI Customization Wizard${_.reset}`),console.log(`${_.dim} Running at ${_.reset}${_.green}${h}${_.reset}`),console.log(`${_.dim} Live previews: ${_.reset}${Object.keys(a).length} components`),console.log(`${_.dim} Preview target: ${_.reset}${r}`),console.log(`${_.dim} Default wizard \u2014 saves directly to survey-ui-config.json when client clicks Review & Build${_.reset}
130
+ `),nt(h)}),I.on("error",R)})}M();import*as le from"fs";import*as Co from"path";import*as $o from"http";import*as xo from"https";Se();ue();Pe();ve();var d=c;function at(e){let{exec:o}=ye("child_process"),t=process.platform==="darwin"?`open "${e}"`:process.platform==="win32"?`start "" "${e}"`:`xdg-open "${e}"`;o(t)}function lt(e){return new Promise(o=>setTimeout(o,e))}async function Me(e,o={}){return new Promise((t,n)=>{let i=new URL(e),r=(i.protocol==="https:"?xo:$o).request(i,{method:o.method??"GET",headers:o.headers??{}},a=>{let l="";a.on("data",w=>l+=w),a.on("end",()=>{if((a.statusCode??500)>=400){n(new Error(`HTTP ${a.statusCode}: ${l}`));return}try{t(JSON.parse(l))}catch{n(new Error(`Invalid JSON: ${l.slice(0,200)}`))}})});r.on("error",n),o.body&&r.write(o.body),r.end()})}async function ft(e,o,t,n){return new Promise((i,s)=>{let r=new URL(e),a=r.protocol==="https:"?xo:$o,l={"Content-Type":t,"Content-Length":o.length};n&&(l["X-Wizard-Session"]=n.sessionSecret,l["X-Wizard-Session-Id"]=n.sessionId);let w=a.request(r,{method:"PUT",headers:l},m=>{if((m.statusCode??500)>=400){let $="";m.on("data",b=>$+=b),m.on("end",()=>s(new Error(`PUT failed ${m.statusCode}: ${$}`)));return}m.resume(),i()});w.on("error",s),w.write(o),w.end()})}function dt(e){try{let o=e.split(".")[1];return JSON.parse(Buffer.from(o,"base64url").toString("utf8")).surveyId??null}catch{return null}}async function To(e={}){let o=e.wait!==!1,t=e.pollIntervalMs??Number(process.env.CFM_WIZARD_POLL_MS??3e3),n=e.timeoutMs??Number(process.env.CFM_WIZARD_TIMEOUT_MS??72e5),i=process.env.CFM_INSTANCE_ID,s=(process.env.CFM_DEPLOY_API_BASE??"http://localhost:3000").replace(/\/$/,"");if(!i)throw new Error("CFM_INSTANCE_ID (JWT) is required");let r=dt(i);if(!r)throw new Error("Could not parse surveyId from CFM_INSTANCE_ID JWT");let a=xe(),l=K(a),w=l.activeConfigPath,m=e.apply?!1:e.review!==!1;console.log(`
131
131
  ${d.bold}${d.cyan}\u{1F3A8} CFM UI Customization (AWS)${d.reset}
132
- `),y&&(console.log(`${d.dim} Review mode: seed kept in survey-ui-config.json; final + diff written on complete.${d.reset}`),console.log(`${d.dim} Apply later with: npx cfm-sdk confirm-ui-config${d.reset}
133
- `));let{outputDir:T,files:C,surveyTypes:E}=await re({projectRoot:a,useTemplatesOnly:e.useTemplatesOnly}),I=C.map(S=>({path:S.path,contentType:S.contentType,sizeBytes:S.sizeBytes})),{config:m,source:f}=ie({projectRoot:a,surveyTypes:E,instanceId:r});Fe(f),y&&(le.writeFileSync(l.seedPath,JSON.stringify(m,null,2),"utf8"),le.writeFileSync(w,JSON.stringify(m,null,2),"utf8"),console.log(`${d.dim} Seed snapshot \u2192 survey-ui-config.json (+ .seed.json)${d.reset}`));let u=await Me(`${s}/wizard/session/start`,{method:"POST",headers:{Authorization:`Bearer ${i}`,"Content-Type":"application/json"},body:JSON.stringify({files:I,surveyTypes:E,initialConfig:m})});console.log(`${d.dim} Uploading ${I.length} preview files\u2026${d.reset}`);for(let S of u.uploads){let $=Co.join(T,S.path),k=le.readFileSync($),j=I.find(z=>z.path===S.path)?.contentType??"application/octet-stream";await ft(S.uploadUrl,k,j)}if(await Me(`${s}/wizard/previews/upload/complete`,{method:"POST",headers:{Authorization:`Bearer ${i}`,"Content-Type":"application/json"},body:JSON.stringify({sessionId:u.sessionId})}),console.log(`${d.green}\u2705 Previews uploaded${d.reset}`),console.log(`${d.dim} ${I.length} component preview page(s) \u2192 S3 (wizard loads via EC2 proxy)${d.reset}`),console.log(`
134
- ${d.bold}${d.cyan}\u{1F517} Client wizard link \u2014 share with the client:${d.reset}`),console.log(`${d.green} ${u.wizardUrl}${d.reset}`),console.log(`${d.dim} (Deployed on EC2 \u2014 client customizes here; agent keeps CLI open until submit)${d.reset}
135
- `),at(u.wizardUrl),!o){console.log(`${d.yellow}--no-wait: wizard URL (not polling):${d.reset}`),console.log(u.wizardUrl),y&&console.log(`${d.dim} When wizard completes, poll manually or re-run without --no-wait to capture final + diff.${d.reset}`);return}let h=Date.now()+n,x=0;for(;Date.now()<h;){x+=1,process.stdout.write(`\r${d.dim}Waiting for client to finish wizard\u2026 (poll ${x})${d.reset}`);let S=await Me(`${s}/wizard/config/${encodeURIComponent(r)}?sessionId=${u.sessionId}`,{headers:{Authorization:`Bearer ${i}`}});if(S.status==="ready"&&S.config){let $=Pe(S)??S.config;if(console.log(`
136
- ${d.green}\u2705 Configuration ready${d.reset}`),S.logoUrl&&console.log(`${d.dim} Logo URL: ${S.logoUrl}${d.reset}`),y){let j=ke(a,m,$);console.log(`${d.green} Seed (unchanged active): ${w}${d.reset}`),console.log(`${d.green} Final: ${l.finalPath}${d.reset}`),console.log(`${d.green} Diff: ${l.diffMdPath}${d.reset}`),console.log(`${d.yellow} ${j.changed.length} changed, ${j.added.length} added, ${j.removed.length} removed${d.reset}`);let z=$.global?.logo;if(z?.fileName)try{await Y({projectRoot:a,fileName:z.fileName,logoUrl:S.logoUrl,jwt:i,apiBase:s,surveyId:r}),console.log(`${d.green} Logo saved to public/${z.fileName}${d.reset}`)}catch(vo){console.warn(`${d.yellow} Logo download deferred: ${O(vo)}${d.reset}`)}console.log(`${d.dim} Apply when ready: npx cfm-sdk confirm-ui-config${d.reset}`);return}le.writeFileSync(w,JSON.stringify($,null,2),"utf8"),console.log(`${d.green} Written ${w}${d.reset}`);let k=$.global?.logo;k?.fileName&&(await Y({projectRoot:a,fileName:k.fileName,logoUrl:S.logoUrl,jwt:i,apiBase:s,surveyId:r}),console.log(`${d.green} Logo saved to public/${k.fileName}${d.reset}`));return}await lt(t)}throw new Error("Timed out waiting for wizard completion")}pe();M();var F=c,q=process.argv.slice(2),X=q[0];async function St(){if(X==="customize"||X==="init"){X==="init"&&console.log(`${F.yellow}\u26A0 cfm-sdk init is deprecated. Use \`cfm-sdk customize\` instead.${F.reset}
137
- `);try{await uo()}catch(e){console.error(`
138
- ${F.red}\u274C Error: ${O(e)}${F.reset}`),process.exit(1)}}else if(X==="customize-ui"){let e=q.includes("--use-templates-only"),o=q.includes("--no-wait"),t=q.includes("--apply"),n=q.includes("--no-review")?!1:!t;try{await ko({useTemplatesOnly:e,wait:!o,review:n,apply:t})}catch(i){console.error(`
139
- ${F.red}\u274C Error: ${O(i)}${F.reset}`),process.exit(1)}}else if(X==="confirm-ui-config"){let e=q.includes("--diff-only");try{let{runConfirmUiConfig:o}=await Promise.resolve().then(()=>(Po(),To));await o({diffOnly:e})}catch(o){console.error(`
140
- ${F.red}\u274C Error: ${O(o)}${F.reset}`),process.exit(1)}}else if(X==="fetch-ui-config"){let o=q.find(t=>t.startsWith("--session="))?.split("=")[1];try{let{runFetchUiConfig:t}=await Promise.resolve().then(()=>(Ro(),Eo));await t({sessionId:o})}catch(t){console.error(`
141
- ${F.red}\u274C Error: ${O(t)}${F.reset}`),process.exit(1)}}else if(X==="export-previews"){let e=q.includes("--use-templates-only");try{await re({useTemplatesOnly:e})}catch(o){console.error(`
142
- ${F.red}\u274C Error: ${O(o)}${F.reset}`),process.exit(1)}}else if(X==="resolve-ui-config"){let e=q.includes("--write");try{if(e){let o=je();console.log(`${F.green}\u2705 Wrote ${o}${F.reset}`)}else{let{resolveInitialConfig:o}=await Promise.resolve().then(()=>(pe(),ao)),{config:t,source:n}=o({surveyTypes:[]});console.log(JSON.stringify({source:n,config:t},null,2))}}catch(o){console.error(`
143
- ${F.red}\u274C Error: ${O(o)}${F.reset}`),process.exit(1)}}else if(X==="deploy")try{await He()}catch(e){console.error(`
144
- ${F.red}\u274C Error: ${O(e)}${F.reset}`),process.exit(1)}else console.log(`
145
- ${F.bold}${F.cyan}CFM SDK CLI Tool${F.reset}`),console.log(`
132
+ `),m&&(console.log(`${d.dim} Review mode: seed kept in survey-ui-config.json; final + diff written on complete.${d.reset}`),console.log(`${d.dim} Apply later with: npx cfm-sdk confirm-ui-config${d.reset}
133
+ `));let $=[...Q],{outputDir:b,files:R}=await re({projectRoot:a,useTemplatesOnly:e.useTemplatesOnly,surveyTypes:$}),I=R.map(S=>({path:S.path,contentType:S.contentType,sizeBytes:S.sizeBytes})),{config:h,source:f}=ie({projectRoot:a,surveyTypes:$,instanceId:r});h.surveyTypes=$,je(f),m&&(le.writeFileSync(l.seedPath,JSON.stringify(h,null,2),"utf8"),le.writeFileSync(w,JSON.stringify(h,null,2),"utf8"),console.log(`${d.dim} Seed snapshot \u2192 survey-ui-config.json (+ .seed.json)${d.reset}`));let g=await Me(`${s}/wizard/session/start`,{method:"POST",headers:{Authorization:`Bearer ${i}`,"Content-Type":"application/json"},body:JSON.stringify({files:I,surveyTypes:$,initialConfig:h})});console.log(`${d.dim} Uploading ${I.length} preview files\u2026${d.reset}`);for(let S of g.uploads){let T=Co.join(b,S.path),k=le.readFileSync(T),F=I.find(z=>z.path===S.path)?.contentType??"application/octet-stream";await ft(S.uploadUrl,k,F,{sessionId:g.sessionId,sessionSecret:g.sessionSecret})}if(await Me(`${s}/wizard/previews/upload/complete`,{method:"POST",headers:{Authorization:`Bearer ${i}`,"Content-Type":"application/json"},body:JSON.stringify({sessionId:g.sessionId})}),console.log(`${d.green}\u2705 Previews uploaded${d.reset}`),console.log(`${d.dim} ${I.length} component preview page(s) \u2192 EC2 local server (disk)${d.reset}`),console.log(`
134
+ ${d.bold}${d.cyan}\u{1F517} Client wizard link \u2014 share with the client:${d.reset}`),console.log(`${d.green} ${g.wizardUrl}${d.reset}`),console.log(`${d.dim} (Deployed on EC2 \u2014 client customizes here; agent keeps CLI open until submit)${d.reset}
135
+ `),at(g.wizardUrl),!o){console.log(`${d.yellow}--no-wait: wizard URL (not polling):${d.reset}`),console.log(g.wizardUrl),m&&console.log(`${d.dim} When wizard completes, poll manually or re-run without --no-wait to capture final + diff.${d.reset}`);return}let y=Date.now()+n,x=0;for(;Date.now()<y;){x+=1,process.stdout.write(`\r${d.dim}Waiting for client to finish wizard\u2026 (poll ${x})${d.reset}`);let S=await Me(`${s}/wizard/config/${encodeURIComponent(r)}?sessionId=${g.sessionId}`,{headers:{Authorization:`Bearer ${i}`}});if(S.status==="abandoned")throw console.log(`
136
+ ${d.yellow}\u26A0 Client quit the wizard \u2014 session cleaned up on S3${d.reset}`),new Error("Client quit the wizard without saving. S3 preview garbage was removed. Re-run customize-ui to start a new session.");if(S.status==="ready"&&S.config){let T=Ee(S)??S.config;if(console.log(`
137
+ ${d.green}\u2705 Configuration ready${d.reset}`),S.logoUrl&&console.log(`${d.dim} Logo URL: ${S.logoUrl}${d.reset}`),m){let F=ke(a,h,T);console.log(`${d.green} Seed (unchanged active): ${w}${d.reset}`),console.log(`${d.green} Final: ${l.finalPath}${d.reset}`),console.log(`${d.green} Diff: ${l.diffMdPath}${d.reset}`),console.log(`${d.yellow} ${F.changed.length} changed, ${F.added.length} added, ${F.removed.length} removed${d.reset}`);let z=T.global?.logo;if(z?.fileName)try{await Z({projectRoot:a,fileName:z.fileName,logoUrl:S.logoUrl,jwt:i,apiBase:s,surveyId:r}),console.log(`${d.green} Logo saved to public/${z.fileName}${d.reset}`)}catch(Ro){console.warn(`${d.yellow} Logo download deferred: ${O(Ro)}${d.reset}`)}console.log(`${d.dim} Apply when ready: npx cfm-sdk confirm-ui-config${d.reset}`);return}le.writeFileSync(w,JSON.stringify(T,null,2),"utf8"),console.log(`${d.green} Written ${w}${d.reset}`);let k=T.global?.logo;k?.fileName&&(await Z({projectRoot:a,fileName:k.fileName,logoUrl:S.logoUrl,jwt:i,apiBase:s,surveyId:r}),console.log(`${d.green} Logo saved to public/${k.fileName}${d.reset}`));return}await lt(t)}throw new Error("Timed out waiting for wizard completion")}ue();M();var j=c,q=process.argv.slice(2),X=q[0];async function St(){if(X==="customize"||X==="init"){X==="init"&&console.log(`${j.yellow}\u26A0 cfm-sdk init is deprecated. Use \`cfm-sdk customize\` instead.${j.reset}
138
+ `);try{await po()}catch(e){console.error(`
139
+ ${j.red}\u274C Error: ${O(e)}${j.reset}`),process.exit(1)}}else if(X==="customize-ui"){let e=q.includes("--use-templates-only"),o=q.includes("--no-wait"),t=q.includes("--apply"),n=q.includes("--no-review")?!1:!t;try{await To({useTemplatesOnly:e,wait:!o,review:n,apply:t})}catch(i){console.error(`
140
+ ${j.red}\u274C Error: ${O(i)}${j.reset}`),process.exit(1)}}else if(X==="confirm-ui-config"){let e=q.includes("--diff-only");try{let{runConfirmUiConfig:o}=await Promise.resolve().then(()=>(Po(),ko));await o({diffOnly:e})}catch(o){console.error(`
141
+ ${j.red}\u274C Error: ${O(o)}${j.reset}`),process.exit(1)}}else if(X==="fetch-ui-config"){let o=q.find(t=>t.startsWith("--session="))?.split("=")[1];try{let{runFetchUiConfig:t}=await Promise.resolve().then(()=>(vo(),Eo));await t({sessionId:o})}catch(t){console.error(`
142
+ ${j.red}\u274C Error: ${O(t)}${j.reset}`),process.exit(1)}}else if(X==="export-previews"){let e=q.includes("--use-templates-only");try{await re({useTemplatesOnly:e})}catch(o){console.error(`
143
+ ${j.red}\u274C Error: ${O(o)}${j.reset}`),process.exit(1)}}else if(X==="resolve-ui-config"){let e=q.includes("--write");try{if(e){let o=Fe();console.log(`${j.green}\u2705 Wrote ${o}${j.reset}`)}else{let{resolveInitialConfig:o}=await Promise.resolve().then(()=>(ue(),ao)),{config:t,source:n}=o({surveyTypes:[]});console.log(JSON.stringify({source:n,config:t},null,2))}}catch(o){console.error(`
144
+ ${j.red}\u274C Error: ${O(o)}${j.reset}`),process.exit(1)}}else if(X==="deploy")try{await He()}catch(e){console.error(`
145
+ ${j.red}\u274C Error: ${O(e)}${j.reset}`),process.exit(1)}else console.log(`
146
+ ${j.bold}${j.cyan}CFM SDK CLI Tool${j.reset}`),console.log(`
146
147
  Usage:`),console.log(" npx cfm-sdk customize \u2013 Local UI customization wizard"),console.log(" npx cfm-sdk customize-ui \u2013 AWS wizard (review mode: seed + diff, no auto-apply)"),console.log(" npx cfm-sdk customize-ui --apply \u2013 AWS wizard (legacy: write final config immediately)"),console.log(" npx cfm-sdk confirm-ui-config \u2013 Apply survey-ui-config.final.json after review"),console.log(" npx cfm-sdk fetch-ui-config \u2013 Pull final + diff after client completes (--no-wait)"),console.log(" npx cfm-sdk export-previews \u2013 Build component preview pages only"),console.log(" npx cfm-sdk resolve-ui-config --write \u2013 Write draft survey-ui-config.json from project"),console.log(" npx cfm-sdk deploy \u2013 Deploy to Vercel"),process.exit(0)}St();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@explorer02/cfm-survey-sdk",
3
- "version": "0.2.4",
3
+ "version": "0.2.5",
4
4
  "main": "dist/index.js",
5
5
  "module": "dist/index.mjs",
6
6
  "types": "dist/index.d.ts",
@@ -27,20 +27,15 @@
27
27
  "react": ">=17.0.0"
28
28
  },
29
29
  "devDependencies": {
30
- "@tailwindcss/vite": "^4.3.0",
31
30
  "@testing-library/jest-dom": "^6.4.2",
32
31
  "@testing-library/react": "^14.2.1",
33
32
  "@testing-library/user-event": "^14.5.2",
34
- "@vitejs/plugin-react": "^4.5.2",
35
33
  "@vitest/coverage-v8": "^1.3.1",
36
34
  "@types/react": "^17.0.0",
37
35
  "@tanstack/react-query": "^5.0.0",
38
36
  "jsdom": "^24.0.0",
39
- "react": "^19.1.0",
40
- "react-dom": "^19.1.0",
41
37
  "tsup": "^8.0.2",
42
38
  "typescript": "^6.0.0",
43
- "vite": "^6.3.5",
44
39
  "vitest": "^1.3.1"
45
40
  }
46
41
  }
package/postinstall.js CHANGED
@@ -24,7 +24,8 @@ function getSdkRulesBody() {
24
24
  'RULE 1 — DOCS-FIRST FLOW (OPTIONAL WIZARD):',
25
25
  'Follow the phases in index.md. Initial branding comes from the client prompt.',
26
26
  'After building and starting localhost dev, ask if the client wants UI customization via web wizard.',
27
- 'If yes, run `npx cfm-sdk customize` — read `survey-ui-config.json` when saved; apply UI tokens only.',
27
+ 'If yes, run `npx cfm-sdk customize` (default) — read `survey-ui-config.json` when saved; apply UI tokens only.',
28
+ 'Use `npx cfm-sdk customize-ui` only when the client must customize from another device (EC2 fallback).',
28
29
  'Do NOT run the wizard before the survey UI is built. Do NOT read legacy `survey-config.json`.',
29
30
  '',
30
31
  'RULE 2 — DEEP CONTEXT BEFORE CODE:',
@@ -39,14 +39,14 @@ Import from whatever appears in `package.json`:
39
39
 
40
40
  | Phase | Action |
41
41
  |-------|--------|
42
- | 0 | Orient — read operating contract + execution flow; detect framework; extract branding |
42
+ | 0 | Orient — read operating contract + execution flow; **UI-only** mockup notes (`mockup-ui-extraction.md`); detect framework |
43
43
  | 1 | Scaffold — `00-integration/setup.md` |
44
44
  | 2 | Ask JWT — `useSurveySDK.md` |
45
45
  | 3 | SDK contract — `client-integration-guide.md` + logic/lifecycle docs |
46
- | 4 | Plan — fetch survey, inventory types, copy `Question.tsx` + `implementation_plan.md` |
46
+ | 4 | Plan — fetch survey, inventory types **from API**, placeholders + custom fields, copy `Question.tsx` + `implementation_plan.md` |
47
47
  | 5 | **Build wizard-ready UI** — read per-type `03-ui-specs/*` for every inventory type |
48
48
  | 6 | Verify — `verify-agent-build.sh`; start dev server; **ask wizard (INPUT 3)** |
49
- | 6b | Optional — `npx cfm-sdk customize-ui` upload previews → **send deployed wizard link to client** block until submit; read `survey-ui-config.diff.md` |
49
+ | 6b | Optional — **`npx cfm-sdk customize`** (default when client says yes); `customize-ui` only for remote client |
50
50
  | 6c | Apply every path from `survey-ui-config.final.json` → `confirm-ui-config` → re-verify |
51
51
  | 7 | Deploy — on confirmation per prompt or `deploy.target` |
52
52
 
@@ -25,7 +25,7 @@ Machine-readable routing: [`MANIFEST.json`](../MANIFEST.json) `phases[]`.
25
25
 
26
26
  | # | When | Agent asks (verbatim intent) | On answer |
27
27
  |---|------|------------------------------|-----------|
28
- | **1** | Start (usually given) | *(Client prompt — mockup, brand, deploy target hints)* | Extract branding; note AWS/Vercel keywords |
28
+ | **1** | Start (usually given) | *(Client prompt — mockup, brand, deploy target hints)* | UI-only notes per `mockup-ui-extraction.md`; **not** survey structure |
29
29
  | **2** | Phase 2 | *"Please provide your survey instance ID (JWT token)."* | Store as `CFM_INSTANCE_ID` / `SURVEY_INSTANCE_ID`; fetch survey |
30
30
  | **3** | Phase 6 (after verify + dev server) | *"Your survey is running locally. Would you like to customize the UI through the web wizard?"* | **Yes** → Phase 6b. **No** → Phase 7 ask |
31
31
  | **4** | Phase 7 | *"Your survey is built and verified. Ready to deploy to production?"* | **Yes** → deploy per prompt/config. **No** → stop |
@@ -42,7 +42,8 @@ Machine-readable routing: [`MANIFEST.json`](../MANIFEST.json) `phases[]`.
42
42
 
43
43
  **Do:**
44
44
  - Detect framework from `package.json` → `setup.md`
45
- - Extract colors, logo style, layout from client prompt into notes for `implementation_plan.md`
45
+ - Extract **UI-only** from mockup/prompt per [`mockup-ui-extraction.md`](mockup-ui-extraction.md) colors, chrome, header/footer format, display copy
46
+ - Do **not** infer question types, language, or logic from mockup
46
47
 
47
48
  ---
48
49
 
@@ -102,8 +103,9 @@ Machine-readable routing: [`MANIFEST.json`](../MANIFEST.json) `phases[]`.
102
103
 
103
104
  **Do:**
104
105
  1. Fetch survey with instanceId
105
- 2. List unique `question.type` values in `implementation_plan.md` §3b
106
- 3. Copy `templates/implementation_plan.md` project root; fill all sections
106
+ 2. List unique `question.type` values in `implementation_plan.md` §3b (**from fetch only**)
107
+ 3. Scan placeholders + `_c_…` custom fields per [`placeholders-and-custom-fields-wiring.md`](placeholders-and-custom-fields-wiring.md)
108
+ 4. Copy `templates/implementation_plan.md` → project root; fill all sections
107
109
  4. Copy `templates/Question.tsx` as dispatcher starting point
108
110
  5. **Auto-proceed to Phase 5** — no approval wait
109
111
 
@@ -177,36 +179,35 @@ Machine-readable routing: [`MANIFEST.json`](../MANIFEST.json) `phases[]`.
177
179
 
178
180
  ### Phase 6b — Wizard session (optional, INPUT 3 = Yes)
179
181
 
180
- **Read:** `wizard-config-handoff.md`, `ui-customization-wizard.md`, `wizard-api.md`, `wizard-preview-build-guide.md`
182
+ **Default:** `npx cfm-sdk customize` — local wizard on `localhost:4200`. Best for preview smoothness, direct JSON save, and automatic cleanup.
183
+
184
+ **EC2 fallback:** `customize-ui` — only when client customizes from **another device**.
185
+
186
+ **Read:** `ui-customization-wizard.md`, `wizard-preview-build-guide.md`, `wizard-troubleshooting.md`, `apply-ui-config.md`
181
187
 
182
188
  **Prerequisites:** Phase 6 passed; draft `survey-ui-config.json` exists
183
189
 
184
- **Run (agent blocks until client submits):**
190
+ **Run (default — agent blocks until client saves):**
185
191
  ```bash
186
- export CFM_INSTANCE_ID="<JWT>"
187
- export CFM_DEPLOY_API_BASE="http://43.204.26.213:3000"
188
- npx cfm-sdk customize-ui
192
+ npx cfm-sdk customize
189
193
  ```
190
194
 
191
195
  **Sequence:**
192
- 1. CLI exports component previews and uploads to S3
193
- 2. CLI prints **deployed wizard link** — agent **copies and sends to client**
194
- 3. Client opens EC2 link, customizes, clicks **Review & Build**
195
- 4. Agent keeps CLI open until `✅ Configuration ready`
196
-
197
- **Agent must:**
198
- 1. Share the deployed wizard URL with the client (from CLI output, after S3 upload)
199
- 2. Tell client to complete wizard and click **Review & Build**
200
- 2. **Keep CLI running** — poll until `✅ Configuration ready` (do not Ctrl+C)
201
- 3. Read `survey-ui-config.diff.md` when CLI exits 0
202
- 4. **Do not apply** to codebase yet — proceed to Phase 6c
196
+ 1. CLI auto-exports all 11 component previews to `out/previews/`
197
+ 2. Opens wizard at `http://localhost:4200`
198
+ 3. Client customizes (same machine as agent); live iframes from local previews
199
+ 4. Client clicks **Review & Build** `survey-ui-config.json` written
200
+ 5. CLI exits 0 → agent applies per Phase 6c
203
201
 
204
- **Artifacts (AWS review mode):**
205
- - `survey-ui-config.final.json` — apply source
206
- - `survey-ui-config.diff.md` — audit every changed path
207
- - `survey-ui-config.json` — still **seed** until Phase 6c confirm step
202
+ **Tell the client:** *"Complete the wizard in the browser that just opened and click **Review & Build**."*
208
203
 
209
- **Local alternative:** `npx cfm-sdk customize` — blocks until `UI configuration saved` → writes `survey-ui-config.json` directly.
204
+ **Remote client only:**
205
+ ```bash
206
+ export CFM_INSTANCE_ID="<JWT>"
207
+ export CFM_DEPLOY_API_BASE="http://43.204.26.213:3000"
208
+ npx cfm-sdk customize-ui
209
+ ```
210
+ Share EC2 link; keep CLI open until `✅ Configuration ready`. See `wizard-config-handoff.md`.
210
211
 
211
212
  **If client said No:** skip to Phase 7 ask.
212
213
 
@@ -229,8 +230,10 @@ npx cfm-sdk customize-ui
229
230
  6. Wire `placeholders`, `customFields`, `debug` from final config
230
231
  7. Apply per-type `questionTypes.*` for every type in `surveyTypes[]`
231
232
  8. AWS: `npx cfm-sdk confirm-ui-config` (promotes final → active + downloads logo)
232
- 9. Re-run `verify-agent-build.sh` + `npm run build`
233
- 10. **Do not** change dispatch logic in `Question.tsx`
233
+ 9. When `global.logo.fileName` is set: update `Header.tsx` `data-cfm-logo src="./{fileName}"`; verify `public/{fileName}` exists
234
+ 10. Re-run `verify-agent-build.sh` + `npm run build`
235
+ 11. Verify logo in static output: `test -f out/$(jq -r '.global.logo.fileName' survey-ui-config.json)` when fileName set
236
+ 12. **Do not** change dispatch logic in `Question.tsx`
234
237
 
235
238
  **Blocking:** Do not proceed to Phase 7 until diff paths are applied and verify passes.
236
239
 
@@ -240,6 +243,15 @@ npx cfm-sdk customize-ui
240
243
 
241
244
  **Ask:** deploy confirmation (see table)
242
245
 
246
+ **Before AWS deploy (when wizard set a logo):**
247
+
248
+ ```bash
249
+ LOGO=$(python3 -c "import json; print(json.load(open('survey-ui-config.json')).get('global',{}).get('logo',{}).get('fileName') or '')")
250
+ test -z "$LOGO" || test -f "out/$LOGO" || { echo "Logo missing from out/ — fix Phase 6c Header + public/"; exit 1; }
251
+ ```
252
+
253
+ See [`aws-deploy.md`](aws-deploy.md) § Logos & local assets.
254
+
243
255
  **Route:**
244
256
  - AWS keywords in prompt → `aws-deploy.md` + `deploy-to-aws.sh`
245
257
  - Else / Vercel → `npx cfm-sdk deploy`