@kizenapps/cli 1.12.0-a2af6ac → 1.13.0-1bb4c57

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 (28) hide show
  1. package/README.md +18 -2
  2. package/dist/THIRD-PARTY-NOTICES.txt +1 -1
  3. package/dist/index.js +145 -175
  4. package/dist/index.js.map +1 -1
  5. package/dist/viewer/assets/{AppDetailPage-D9xr-bY8.js → AppDetailPage-CGrukEIj.js} +1 -1
  6. package/dist/viewer/assets/{CodeStepsPage-D_kTMpRO.js → CodeStepsPage-Cu9UiRy9.js} +1 -1
  7. package/dist/viewer/assets/ConfigurationPage-CI0pRNJ0.js +1 -0
  8. package/dist/viewer/assets/{DevSidebar-zX-4CWYv.js → DevSidebar-BFsoIbMt.js} +1 -1
  9. package/dist/viewer/assets/{SandboxPage-DuCHX1FY.js → SandboxPage-Dyb8i7vf.js} +1 -1
  10. package/dist/viewer/assets/{SecretsPage-Da55-e_S.js → SecretsPage-g2FF7d-B.js} +1 -1
  11. package/dist/viewer/assets/{WhenBadge-B7s7fns2.js → WhenBadge-DKz8ukwo.js} +1 -1
  12. package/dist/viewer/assets/api--pW2v3sH.js +11 -0
  13. package/dist/viewer/assets/{bootstrapQuery-CyYWFe68.js → bootstrapQuery-DTAPKOf-.js} +1 -1
  14. package/dist/viewer/assets/{calendarSource.worker-CTgMuhqr.js → calendarSource.worker-DjLHW14n.js} +1 -1
  15. package/dist/viewer/assets/{floatingFrame.worker-zn66fKUA.js → floatingFrame.worker-Cy3ysIc7.js} +1 -1
  16. package/dist/viewer/assets/{generic.worker-gJPrf_ED.js → generic.worker-DKCeuXG7.js} +1 -1
  17. package/dist/viewer/assets/{index-BF1Fk_v0.js → index-GvAPdgKb.js} +3 -3
  18. package/dist/viewer/assets/{recordDetail.worker-CGLG0Evq.js → recordDetail.worker-DrTKYLJc.js} +1 -1
  19. package/dist/viewer/assets/storageKeys-BDp-0diL.js +1 -0
  20. package/dist/viewer/assets/useCompleteSetup-QS3W9RRO.js +40 -0
  21. package/dist/viewer/assets/usePluginConfig--4sAyik4.js +1 -0
  22. package/dist/viewer/index.html +4 -4
  23. package/package.json +3 -3
  24. package/dist/viewer/assets/ConfigurationPage-5qOX-sx0.js +0 -1
  25. package/dist/viewer/assets/api--Ax6VWLq.js +0 -11
  26. package/dist/viewer/assets/storageKeys-DPq6kaaE.js +0 -1
  27. package/dist/viewer/assets/useCompleteSetup-DUHoBgca.js +0 -40
  28. package/dist/viewer/assets/usePluginConfig-C8d13THZ.js +0 -1
package/dist/index.js CHANGED
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
- import{readFileSync as Ya}from"fs";import{dirname as Xa,join as Za}from"path";import{fileURLToPath as Qa}from"url";import{Command as el}from"commander";import{createElement as ui}from"react";import{render as fi}from"ink";import{useEffect as vr,useState as Me}from"react";import{Box as ze,Text as Re,useApp as ci}from"ink";import{PluginValidationError as di}from"@kizenapps/packager";import{mkdir as zo,writeFile as Ho}from"fs/promises";import{join as Uo}from"path";import{PluginValidationError as Vo,packagePlugin as qo,parseManifestFromFiles as Jo,transformDeployablePlugin as Wo,transformFiles as Ko,validatePluginApp as Go}from"@kizenapps/packager";import{readdir as Do,readFile as fr}from"fs/promises";import{join as mr,relative as Fo}from"path";var Oo=new Set([".png",".svg"]),jo=new Set([".kzn"]),$o=new Set([".DS_Store"]),tt=new Set(["node_modules",".git",".kizenapp",".github",".claude","__pycache__"]),Lo=8e3;function Mo(e){return e.subarray(0,Lo).includes(0)}async function gr(e,t){let n=await Do(e,{withFileTypes:!0}),o=[];for(let r of n)if(r.isDirectory()){if(tt.has(r.name))continue;o.push(...await gr(mr(e,r.name),t))}else r.isFile()&&($o.has(r.name)||o.push(mr(e,r.name)));return o}async function rt(e,{detectBinaryByContent:t=!1}={}){let n=await gr(e,e);return Promise.all(n.map(async o=>{let r=Fo(e,o).split("\\").join("/"),i=r.lastIndexOf("."),d=i>=0?r.slice(i).toLowerCase():"";if(Oo.has(d)){let g=await fr(o);return{path:r,content:"",base64Image:g.toString("base64")}}let f=await fr(o);return jo.has(d)||t&&Mo(f)?{path:r,content:"",binaryData:f}:{path:r,content:f.toString("utf-8")}}))}var Yo=(e,t)=>({...e,thumbnail:e.thumbnail?Buffer.from(e.thumbnail).toString("base64"):null,kznFile:e.kznFile?Buffer.from(e.kznFile).toString("base64"):null,allReleaseNotes:t});async function nt(e,t,n){await zo(t,{recursive:!0}),n?.("reading-files");let o=await rt(e);n?.("validating");let r=Go(o);if(r.some(x=>x.severity==="error"))throw new Vo(r);n?.("minifying");let i=await Ko(o);n?.("packaging");let d=Jo(i),f=qo(i,d),g=Object.values(f).map(Wo);n?.("writing-bundle");let m=g.map(x=>{let p=x.release_notes_directory?.replace(/\/$/,""),y=p?o.filter(S=>S.path.startsWith(p+"/")&&S.path.endsWith(".md")&&S.content).map(S=>({version:S.path.slice(S.path.lastIndexOf("/")+1,-3),notes:S.content})).sort((S,H)=>H.version.localeCompare(S.version,void 0,{numeric:!0})):[];return Yo(x,y)}),b=JSON.stringify(m,null,2),T=(x,p)=>x==="allReleaseNotes"?void 0:p,P=Buffer.byteLength(JSON.stringify(m,T,2),"utf-8");return await Ho(Uo(t,"bundle.json"),b,"utf-8"),{bundleSize:P}}function $e(e){return e<1024?`${String(e)} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/(1024*1024)).toFixed(2)} MB`}import{Box as ei,Text as ti}from"ink";import{Box as Xo,Text as Zo}from"ink";import{jsx as hr}from"react/jsx-runtime";var Qo=[" :::::::: "," :::::: ::::::::::: "," :::::: :::::::::: "," :::::: :::::: ::::::: "," ::::: :::::: ::::::::::::::::: "," ::::: ::::: ::::::::::::::::::: "," ::::: ::::: :::::: ::::: ",":::: ::::: ::: ::::: :: ","::::: :::::: :::::::::: ","::::: :::::: ::::::::::: "," ::::: ::: ::::::: "," ::::::: ::: ::::: "," ::::::::::: :::::: :::::"," :::::::::: :::::: :::::"," :: ::::: ::: ::::: ::::"," ::::: :::::: ::::: ::::: ::: "," ::::::::::::::::::: ::::: ::::: "," ::::::::::::::::: ::::: ::::: "," ::::::::: :::::: :::::: "," :::::::::: :::::: "," ::::::::::: :::::: "," :::::::: "],yr=()=>hr(Xo,{flexDirection:"column",children:Qo.map((e,t)=>hr(Zo,{color:"cyan",children:e},t))});import{Fragment as ri,jsx as jt,jsxs as ni}from"react/jsx-runtime";var q=({marginBottom:e=0})=>ni(ri,{children:[jt(yr,{}),jt(ei,{flexDirection:"column",marginTop:1,marginBottom:e,children:jt(ti,{bold:!0,color:"cyan",children:"Kizen App Development Toolkit"})})]});import{useEffect as oi,useState as ii}from"react";import{Text as si}from"ink";import{jsx as ai}from"react/jsx-runtime";var br=["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F"],me=()=>{let[e,t]=ii(0);return oi(()=>{let n=setInterval(()=>{t(o=>(o+1)%br.length)},80);return()=>{clearInterval(n)}},[]),ai(si,{color:"cyan",children:br[e]??"\u280B"})};import{Box as $t,Text as ot}from"ink";import{jsx as xr,jsxs as Le}from"react/jsx-runtime";var li=e=>{let t=new Map;for(let n of e){let o=n.path??n.pluginApiName??"general",r=t.get(o)??[];r.push(n),t.set(o,r)}return t},it=({issues:e})=>{let t=e.filter(n=>n.severity==="error").length;return Le($t,{flexDirection:"column",marginTop:1,children:[Le(ot,{color:"red",children:["\u2717 ",t," validation ",t===1?"error":"errors"]}),[...li(e)].map(([n,o])=>Le($t,{flexDirection:"column",marginTop:1,children:[xr(ot,{bold:!0,children:n}),o.map((r,i)=>xr($t,{paddingLeft:2,children:Le(ot,{color:r.severity==="error"?"red":"yellow",children:[r.severity==="error"?"\u2717":"\u26A0"," ",r.message," ",Le(ot,{dimColor:!0,children:["(",r.rule,")"]})]})},`${r.rule}-${String(i)}`))]},n))]})};import{Fragment as pi,jsx as ge,jsxs as Ee}from"react/jsx-runtime";var wr=["creating-dir","reading-files","validating","minifying","packaging","writing-bundle"],st={"creating-dir":"Creating .kizenapp directory","reading-files":"Reading plugin files",validating:"Validating plugin app",minifying:"Minifying scripts",packaging:"Packaging plugin","writing-bundle":"Writing bundle.json"},Cr=({outputDir:e,pluginDir:t})=>{let n=ci(),[o,r]=Me("creating-dir"),[i,d]=Me(!1),[f,g]=Me(null),[m,b]=Me(null),[T,P]=Me(null);vr(()=>{nt(t,e,r).then(({bundleSize:y})=>{P(y),r("done")}).catch(y=>{y instanceof di?g(y.issues):b(y instanceof Error?y.message:String(y)),d(!0),process.exitCode=1})},[e,t]),vr(()=>{(o==="done"||i)&&n.exit()},[o,i,n]);let x=wr.indexOf(o),p=o==="done";return Ee(ze,{flexDirection:"column",paddingY:1,paddingX:2,children:[ge(q,{marginBottom:1}),Ee(ze,{flexDirection:"column",gap:0,children:[wr.map((y,S)=>{let H=o===y,O=p||x>S;return ge(ze,{gap:1,children:i&&S===x?Ee(Re,{color:"red",children:["\u2717 ",st[y]]}):O?Ee(Re,{color:"green",children:["\u2713 ",st[y]]}):H?Ee(pi,{children:[ge(me,{}),ge(Re,{children:st[y]})]}):Ee(Re,{dimColor:!0,children:[" ",st[y]]})},y)}),p&&T!==null&&ge(ze,{marginTop:1,gap:1,children:Ee(Re,{color:"green",children:["\u2713 bundle \u2014 ",$e(T)]})}),f!==null&&ge(it,{issues:f}),m!==null&&ge(ze,{marginTop:1,borderStyle:"single",borderColor:"red",paddingX:1,children:ge(Re,{color:"red",children:m})})]})]})};import*as Ae from"fs";import*as Sr from"path";function Ne(e){let t=Sr.join(e,".gitignore"),n=".kizenapp/",o="";if(Ae.existsSync(t)){o=Ae.readFileSync(t,"utf8");let i=o.split(`
3
- `).map(d=>d.trim());if(i.includes(n)||i.includes(".kizenapp"))return}let r=o.endsWith(`
4
- `)?n+`
5
- `:`
6
- `+n+`
7
- `;Ae.writeFileSync(t,o+r)}function Tr(e){e.command("build").description("Bundle the plugin app into .kizenapp directory").action(async()=>{let t=process.cwd(),n=`${t}/.kizenapp`;Ne(t);let{waitUntilExit:o}=fi(ui(Cr,{outputDir:n,pluginDir:t}));await o()})}import{createElement as hs}from"react";import{render as ys}from"ink";import{useCallback as mt,useState as Be}from"react";import{Box as z,Text as I,useApp as rs,useInput as ns}from"ink";import{join as gt}from"path";import{access as Zi,mkdir as lt,writeFile as Ut}from"fs/promises";import{dirname as Qi,join as ce}from"path";var _r=`{
2
+ import{readFileSync as ul}from"fs";import{dirname as fl,join as ml}from"path";import{fileURLToPath as gl}from"url";import{Command as hl}from"commander";import{createElement as hi}from"react";import{render as yi}from"ink";import{useEffect as wr,useState as Me}from"react";import{Box as He,Text as Be,useApp as ui}from"ink";import{PluginValidationError as fi}from"@kizenapps/packager";import{mkdir as Vo,writeFile as qo}from"fs/promises";import{join as Jo}from"path";import{PluginValidationError as Wo,packagePlugin as Go,parseManifestFromFiles as Ko,transformDeployablePlugin as Yo,transformFiles as Xo,validatePluginApp as Zo}from"@kizenapps/packager";import{readdir as jo,readFile as mr}from"fs/promises";import{join as gr,relative as Lo}from"path";var Oo=new Set([".png",".svg"]),zo=new Set([".kzn"]),Mo=new Set([".DS_Store"]),rt=new Set(["node_modules",".git",".kizenapp",".copilot-docs",".github",".claude","__pycache__"]),Ho=8e3;function Uo(e){return e.subarray(0,Ho).includes(0)}async function hr(e,t){let n=await jo(e,{withFileTypes:!0}),o=[];for(let r of n)if(r.isDirectory()){if(rt.has(r.name))continue;o.push(...await hr(gr(e,r.name),t))}else r.isFile()&&(Mo.has(r.name)||o.push(gr(e,r.name)));return o}async function nt(e,{detectBinaryByContent:t=!1}={}){let n=await hr(e,e);return Promise.all(n.map(async o=>{let r=Lo(e,o).split("\\").join("/"),i=r.lastIndexOf("."),p=i>=0?r.slice(i).toLowerCase():"";if(Oo.has(p)){let g=await mr(o);return{path:r,content:"",base64Image:g.toString("base64")}}let f=await mr(o);return zo.has(p)||t&&Uo(f)?{path:r,content:"",binaryData:f}:{path:r,content:f.toString("utf-8")}}))}var Qo=(e,t)=>({...e,thumbnail:e.thumbnail?Buffer.from(e.thumbnail).toString("base64"):null,kznFile:e.kznFile?Buffer.from(e.kznFile).toString("base64"):null,allReleaseNotes:t});async function ot(e,t,n){await Vo(t,{recursive:!0}),n?.("reading-files");let o=await nt(e);n?.("validating");let r=Zo(o);if(r.some(x=>x.severity==="error"))throw new Wo(r);n?.("minifying");let i=await Xo(o);n?.("packaging");let p=Ko(i),f=Go(i,p),g=Object.values(f).map(Yo);n?.("writing-bundle");let m=g.map(x=>{let c=x.release_notes_directory?.replace(/\/$/,""),b=c?o.filter(w=>w.path.startsWith(c+"/")&&w.path.endsWith(".md")&&w.content).map(w=>({version:w.path.slice(w.path.lastIndexOf("/")+1,-3),notes:w.content})).sort((w,H)=>H.version.localeCompare(w.version,void 0,{numeric:!0})):[];return Qo(x,b)}),y=JSON.stringify(m,null,2),T=(x,c)=>x==="allReleaseNotes"?void 0:c,P=Buffer.byteLength(JSON.stringify(m,T,2),"utf-8");return await qo(Jo(t,"bundle.json"),y,"utf-8"),{bundleSize:P}}function Oe(e){return e<1024?`${String(e)} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/(1024*1024)).toFixed(2)} MB`}import{Box as ni,Text as oi}from"ink";import{Box as ei,Text as ti}from"ink";import{jsx as yr}from"react/jsx-runtime";var ri=[" :::::::: "," :::::: ::::::::::: "," :::::: :::::::::: "," :::::: :::::: ::::::: "," ::::: :::::: ::::::::::::::::: "," ::::: ::::: ::::::::::::::::::: "," ::::: ::::: :::::: ::::: ",":::: ::::: ::: ::::: :: ","::::: :::::: :::::::::: ","::::: :::::: ::::::::::: "," ::::: ::: ::::::: "," ::::::: ::: ::::: "," ::::::::::: :::::: :::::"," :::::::::: :::::: :::::"," :: ::::: ::: ::::: ::::"," ::::: :::::: ::::: ::::: ::: "," ::::::::::::::::::: ::::: ::::: "," ::::::::::::::::: ::::: ::::: "," ::::::::: :::::: :::::: "," :::::::::: :::::: "," ::::::::::: :::::: "," :::::::: "],br=()=>yr(ei,{flexDirection:"column",children:ri.map((e,t)=>yr(ti,{color:"cyan",children:e},t))});import{Fragment as ii,jsx as Lt,jsxs as si}from"react/jsx-runtime";var q=({marginBottom:e=0})=>si(ii,{children:[Lt(br,{}),Lt(ni,{flexDirection:"column",marginTop:1,marginBottom:e,children:Lt(oi,{bold:!0,color:"cyan",children:"Kizen App Development Toolkit"})})]});import{useEffect as ai,useState as li}from"react";import{Text as ci}from"ink";import{jsx as di}from"react/jsx-runtime";var xr=["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F"],me=()=>{let[e,t]=li(0);return ai(()=>{let n=setInterval(()=>{t(o=>(o+1)%xr.length)},80);return()=>{clearInterval(n)}},[]),di(ci,{color:"cyan",children:xr[e]??"\u280B"})};import{Box as Ot,Text as it}from"ink";import{jsx as vr,jsxs as ze}from"react/jsx-runtime";var pi=e=>{let t=new Map;for(let n of e){let o=n.path??n.pluginApiName??"general",r=t.get(o)??[];r.push(n),t.set(o,r)}return t},st=({issues:e})=>{let t=e.filter(n=>n.severity==="error").length;return ze(Ot,{flexDirection:"column",marginTop:1,children:[ze(it,{color:"red",children:["\u2717 ",t," validation ",t===1?"error":"errors"]}),[...pi(e)].map(([n,o])=>ze(Ot,{flexDirection:"column",marginTop:1,children:[vr(it,{bold:!0,children:n}),o.map((r,i)=>vr(Ot,{paddingLeft:2,children:ze(it,{color:r.severity==="error"?"red":"yellow",children:[r.severity==="error"?"\u2717":"\u26A0"," ",r.message," ",ze(it,{dimColor:!0,children:["(",r.rule,")"]})]})},`${r.rule}-${String(i)}`))]},n))]})};import{Fragment as mi,jsx as ge,jsxs as Pe}from"react/jsx-runtime";var Cr=["creating-dir","reading-files","validating","minifying","packaging","writing-bundle"],at={"creating-dir":"Creating .kizenapp directory","reading-files":"Reading plugin files",validating:"Validating plugin app",minifying:"Minifying scripts",packaging:"Packaging plugin","writing-bundle":"Writing bundle.json"},Sr=({outputDir:e,pluginDir:t})=>{let n=ui(),[o,r]=Me("creating-dir"),[i,p]=Me(!1),[f,g]=Me(null),[m,y]=Me(null),[T,P]=Me(null);wr(()=>{ot(t,e,r).then(({bundleSize:b})=>{P(b),r("done")}).catch(b=>{b instanceof fi?g(b.issues):y(b instanceof Error?b.message:String(b)),p(!0),process.exitCode=1})},[e,t]),wr(()=>{(o==="done"||i)&&n.exit()},[o,i,n]);let x=Cr.indexOf(o),c=o==="done";return Pe(He,{flexDirection:"column",paddingY:1,paddingX:2,children:[ge(q,{marginBottom:1}),Pe(He,{flexDirection:"column",gap:0,children:[Cr.map((b,w)=>{let H=o===b,j=c||x>w;return ge(He,{gap:1,children:i&&w===x?Pe(Be,{color:"red",children:["\u2717 ",at[b]]}):j?Pe(Be,{color:"green",children:["\u2713 ",at[b]]}):H?Pe(mi,{children:[ge(me,{}),ge(Be,{children:at[b]})]}):Pe(Be,{dimColor:!0,children:[" ",at[b]]})},b)}),c&&T!==null&&ge(He,{marginTop:1,gap:1,children:Pe(Be,{color:"green",children:["\u2713 bundle \u2014 ",Oe(T)]})}),f!==null&&ge(st,{issues:f}),m!==null&&ge(He,{marginTop:1,borderStyle:"single",borderColor:"red",paddingX:1,children:ge(Be,{color:"red",children:m})})]})]})};import*as Ae from"fs";import*as Tr from"path";var gi=[".kizenapp/",".copilot-docs/"];function he(e){let t=Tr.join(e,".gitignore"),n="";Ae.existsSync(t)&&(n=Ae.readFileSync(t,"utf8"));let o=new Set(n.split(`
3
+ `).map(f=>f.trim())),r=gi.filter(f=>!o.has(f)&&!o.has(f.replace(/\/$/,"")));if(r.length===0)return;let i=r.join(`
4
+ `)+`
5
+ `,p=n===""||n.endsWith(`
6
+ `)?i:`
7
+ `+i;Ae.writeFileSync(t,n+p)}function Er(e){e.command("build").description("Bundle the plugin app into .kizenapp directory").action(async()=>{let t=process.cwd(),n=`${t}/.kizenapp`;he(t);let{waitUntilExit:o}=yi(hi(Sr,{outputDir:n,pluginDir:t}));await o()})}import{createElement as ws}from"react";import{render as Cs}from"ink";import{useCallback as gt,useState as De}from"react";import{Box as M,Text as I,useApp as as,useInput as ls}from"ink";import{join as ht}from"path";import{access as ns,mkdir as dt,writeFile as Vt}from"fs/promises";import{dirname as os,join as ce}from"path";var _r=`{
8
8
  "name": "Hello Frame",
9
9
  "api_name": "hello_frame",
10
10
  "title": "Hello Frame",
@@ -13,13 +13,13 @@ import{readFileSync as Ya}from"fs";import{dirname as Xa,join as Za}from"path";im
13
13
  "height": 320,
14
14
  "width": 280
15
15
  }
16
- `;var Er=`this.outputUI(\`
16
+ `;var kr=`this.outputUI(\`
17
17
  <div class="hello-frame">
18
18
  <h2 class="hello-frame__title">Hello from a floating frame</h2>
19
19
  <p class="hello-frame__body">Edit src/floatingFrames/helloFrame/script.js to change this.</p>
20
20
  </div>
21
21
  \`);
22
- `;var kr=`.hello-frame {
22
+ `;var Pr=`.hello-frame {
23
23
  padding: 16px;
24
24
  font-family: system-ui, sans-serif;
25
25
  }
@@ -33,12 +33,12 @@ import{readFileSync as Ya}from"fs";import{dirname as Xa,join as Za}from"path";im
33
33
  margin: 0;
34
34
  color: #555;
35
35
  }
36
- `;var Pr=`{
36
+ `;var Ir=`{
37
37
  "name": "Hello Block",
38
38
  "api_name": "hello_block",
39
39
  "types": ["dashboards"]
40
40
  }
41
- `;var Ir=`this.outputUI(\`
41
+ `;var Nr=`this.outputUI(\`
42
42
  <div class="hello-block">
43
43
  <h2 class="hello-block__title">Hello from a block</h2>
44
44
  <p class="hello-block__body">Edit src/blocks/helloBlock/script.js to change this.</p>
@@ -60,25 +60,25 @@ import{readFileSync as Ya}from"fs";import{dirname as Xa,join as Za}from"path";im
60
60
  margin: 0;
61
61
  color: #555;
62
62
  }
63
- `;var Ar=`{
63
+ `;var Br=`{
64
64
  "icon": "phone",
65
65
  "color": "#0ea5e9",
66
66
  "tooltip": "Hello adornment",
67
67
  "field_type": "phonenumber"
68
68
  }
69
- `;var Nr=`this.showToast('Hello from a data adornment.', { variant: 'success' });
70
- `;var Br=`{
69
+ `;var Ar=`this.showToast('Hello from a data adornment.', { variant: 'success' });
70
+ `;var Dr=`{
71
71
  "name": "Hello Page",
72
72
  "api_name": "hello_page"
73
73
  }
74
- `;var Dr=`this.outputUI(\`
74
+ `;var Fr=`this.outputUI(\`
75
75
  <div class="hello-page">
76
76
  <p class="hello-page__loading">Loading\u2026</p>
77
77
  </div>
78
78
  \`);
79
79
 
80
80
  this.runEventScript('greet');
81
- `;var Fr=`.hello-page {
81
+ `;var $r=`.hello-page {
82
82
  padding: 24px;
83
83
  font-family: system-ui, sans-serif;
84
84
  }
@@ -116,7 +116,7 @@ this.runEventScript('greet');
116
116
  .hello-page__button:hover {
117
117
  background: #cbd5e1;
118
118
  }
119
- `;var Or=`const tone = this.args?.formData?.tone?.[0] ?? 'plain';
119
+ `;var jr=`const tone = this.args?.formData?.tone?.[0] ?? 'plain';
120
120
 
121
121
  const greeting = tone === 'cheer' ? 'Hello, and good to see you!' : 'Hello from a routable page.';
122
122
 
@@ -139,170 +139,138 @@ this.outputUI(\`
139
139
  </div>
140
140
  </div>
141
141
  \`);
142
- `;var jr=`{
142
+ `;var Lr=`{
143
143
  "api_name": "hello_toolbar_item",
144
144
  "label": "Hello Toolbar Item",
145
145
  "icon": "star",
146
146
  "color": "#0ea5e9"
147
147
  }
148
- `;var $r=`this.showToast('Hello from a toolbar item.', { variant: 'success' });
149
- `;var Lr=`{
148
+ `;var Or=`this.showToast('Hello from a toolbar item.', { variant: 'success' });
149
+ `;var zr=`{
150
150
  "api_name": "hello_object_settings_item",
151
151
  "label": "Hello Object Settings"
152
152
  }
153
153
  `;var Mr=`this.showToast('Hello from an object settings item.', { variant: 'success' });
154
- `;var zr=`{
154
+ `;var Hr=`{
155
155
  "name": "Hello Action",
156
156
  "api_name": "hello_action",
157
157
  "hint_object_name": "client_client"
158
158
  }
159
- `;var Hr=`this.showToast('Hello from a JS action.', { variant: 'success' });
160
- `;var X=["floatingFrame","block","dataAdornment","page","toolbarItem","objectSettingsItem","jsAction"],Lt={floatingFrame:"Floating frame",block:"Block",dataAdornment:"Data adornment",page:"Routable page",toolbarItem:"Toolbar item",objectSettingsItem:"Object settings item",jsAction:"JS action"},Ni={floatingFrame:{directory:"floatingFrames",component:"helloFrame",files:{"config.json":_r,"script.js":Er,"styles.css":kr}},block:{directory:"blocks",component:"helloBlock",files:{"config.json":Pr,"script.js":Ir,"styles.css":Rr}},dataAdornment:{directory:"dataAdornments",component:"helloAdornment",files:{"config.json":Ar,"script.js":Nr}},page:{directory:"pages",component:"helloPage",files:{"config.json":Br,"script.js":Dr,"styles.css":Fr,"eventScripts/greet.js":Or}},toolbarItem:{directory:"toolbarItems",component:"helloToolbarItem",files:{"config.json":jr,"script.js":$r}},objectSettingsItem:{directory:"objectSettingsItems",component:"helloObjectSettingsItem",files:{"config.json":Lr,"script.js":Mr}},jsAction:{directory:"actions",component:"helloAction",files:{"config.json":zr,"script.js":Hr}}};function Bi(e,t="src"){let{directory:n,component:o,files:r}=Ni[e];return Object.entries(r).map(([i,d])=>({path:`${t}/${n}/${o}/${i}`,content:d}))}function Ur(e,t="src"){return[...new Set(e)].flatMap(n=>Bi(n,t))}var Vr='# Copilot review instructions for this Kizen plugin\n\nThis repo is a Kizen plugin app: a `kizen.json` manifest plus the artifacts\nthat `@kizenapps/packager` finds by walking the directory tree under the\nmanifest\'s `entry` (default `src/`). No manifest key lists artifacts. The\ndirectory layout decides what gets packaged.\n\n## Component directories\n\nUnder `entry`, the packager treats these directory names as component types:\n\n- `floatingFrames`\n- `blocks`\n- `dataAdornments`\n- `pages`\n- `views`\n- `toolbarItems`\n- `objectSettingsItems`\n- `actions`\n- `routeScripts`\n- `automationSteps`\n- `calendarSources`\n\nEvery directory under a component type needs a `config.json`. `views/` is the\none exception.\n\n## `api_name` rules\n\n- An `api_name` must match `/^[a-z_][a-z0-9_]+$/`: lowercase letters, digits\n and underscores, starting with a letter or underscore, at least 2 characters.\n- Set `api_name` explicitly in each artifact\'s `config.json`. The fallback\n lowercases and strips the directory name (`myFrame` becomes `myframe`), and\n that result can collide with another artifact\'s explicit `api_name`.\n- Data adornments have no `api_name` field. Flag one that adds it as dead\n configuration.\n- Sibling components in the same directory need unique `api_name`s. `pages/`\n and `views/` go further and share one namespace, so a page and a view with\n the same `api_name` collide even though they live in different directories.\n\n## A green build does not mean a correct artifact\n\nThe packager coerces malformed artifact config instead of rejecting it: an\ninvalid `field_type` on a data adornment becomes `phonenumber`, and an invalid\n`minimized_style` on a floating frame becomes `circle`. It also says nothing\nabout a missing required field. Publishing is the real gate. The publish step\ncreates each artifact with no defaulting, so a field the packager never emitted\nis absent and the publish request 400s. Review each\n`config.json` as if the build will not catch mistakes in it, because for these\ncases it does not.\n\nPublishing an app requires these fields per artifact type. An artifact missing\none builds clean and fails to publish:\n\n| Artifact | Required fields |\n| --- | --- |\n| Floating frame | `api_name`, `name`, `title` |\n| Block | `api_name`, `name` |\n| Data adornment | `field_type` (one of `phonenumber`, `date`, `datetime`) |\n| Routable page | `api_name`, `name` |\n| Toolbar item | `api_name`, `label`, and a non-blank `script.js` |\n| Object settings item | `api_name`, `label`, and a non-blank `script.js` |\n| JS action | `api_name`, `name`, `hint_object_name` (non-blank) |\n\nA floating frame whose `default_position` ends in `-fixed` must set\n`minimized_style: "circle"` or omit `minimized_style`. Any other value fails\nthe build with `structure/fixed-frame-minimized-style`.\n\n## Publishing\n\nPublishing an app requires exactly one `thumbnail.png`, and it must sit inside\nthe `entry` directory (`src/thumbnail.png` by default). The packager never sees\na thumbnail at the repo root, and publishing then fails with "Thumbnail is\nrequired for publishing".\n\n## Scope\n\nThis file covers repo structure and general review. Two path-scoped files\ncover the rest: `.github/instructions/security.instructions.md` for\nsecurity-sensitive patterns and\n`.github/instructions/version-discipline.instructions.md` for manifest version\nbumps.\n';var qr=`---
161
- applyTo: "src/**/*.js,kizen.json"
162
- ---
163
-
164
- # Security review rules for plugin scripts
165
-
166
- These rules mirror the \`security/*\` validation rules in \`@kizenapps/packager\`.
167
- Flag violations the way the packager would, and also flag the patterns listed
168
- here that its static scan cannot detect.
169
-
170
- ## \`__dangerouslySkipProxy\`
171
-
172
- The packager lets \`__dangerouslySkipProxy\` through with the build WARNING
173
- \`security/dangerously-skip-proxy\`. Flag every occurrence for human review
174
- anyway, because the request leaves the browser directly instead of passing
175
- through the Kizen proxy.
176
-
177
- ## Plaintext credentials
178
-
179
- In \`kizen.json\`, a service's \`auth_credentials.token\`,
180
- \`auth_credentials.password\` and \`auth_credentials.client_secret\` must each be
181
- one of:
182
-
183
- - an encrypted envelope (\`{ "encrypted": true, "value": "..." }\`) that
184
- \`appbuilder encrypt\` produced
185
- - a \`{{secret.KEY}}\` reference, with \`KEY\` declared in \`base_config.secrets\`
186
- - a reference through \`auth_credentials.integration_secret_api_name\`
187
-
188
- A raw literal in any of those three fields is the build ERROR
189
- \`security/plaintext-credential\`. Treat a credential that reaches a commit in
190
- plaintext as compromised and rotate it; deleting the line does not undo the
191
- exposure.
192
-
193
- \`client_id\` is excluded from this rule on purpose. Public client ids are not
194
- sensitive, so do not flag them.
195
-
196
- ## Undeclared secret references
197
-
198
- A \`{{secret.KEY}}\` reference whose \`KEY\` is missing from \`base_config.secrets\`
199
- is the build ERROR \`security/undeclared-secret-reference\`, because nothing
200
- would supply the value at install time.
201
-
202
- ## Dynamic code execution
203
-
204
- \`eval(...)\`, \`new Function(...)\` or \`Function(...)\`, and a string argument to
205
- \`setTimeout\` or \`setInterval\` are the build ERROR \`security/dynamic-code\`.
206
-
207
- This rule catches direct, literal usage only. The packager's scan is
208
- parser-based, so a call built through a computed property or a reassigned
209
- reference gets past it. Obfuscated dynamic code stays a human-review concern.
210
-
211
- ## Secret logging and exfiltration
212
-
213
- The packager has no static check for a secret that gets logged, sent to an
214
- unexpected endpoint, or otherwise exfiltrated. Review for this by hand: look
215
- for credentials or decrypted secret values flowing into \`console.log\`, error
216
- messages, analytics calls, or outbound requests to anything other than the
217
- service they belong to.
218
-
219
- ## Handling secrets in this repo
220
-
221
- Encrypt secrets locally with \`appbuilder encrypt\` before committing them. Do
222
- not commit a plaintext secret value in any form; a comment, a script fixture,
223
- and a commit you intend to rewrite later all count.
224
- `;var Jr=`---
159
+ `;var Ur=`this.showToast('Hello from a JS action.', { variant: 'success' });
160
+ `;var X=["floatingFrame","block","dataAdornment","page","toolbarItem","objectSettingsItem","jsAction"],zt={floatingFrame:"Floating frame",block:"Block",dataAdornment:"Data adornment",page:"Routable page",toolbarItem:"Toolbar item",objectSettingsItem:"Object settings item",jsAction:"JS action"},$i={floatingFrame:{directory:"floatingFrames",component:"helloFrame",files:{"config.json":_r,"script.js":kr,"styles.css":Pr}},block:{directory:"blocks",component:"helloBlock",files:{"config.json":Ir,"script.js":Nr,"styles.css":Rr}},dataAdornment:{directory:"dataAdornments",component:"helloAdornment",files:{"config.json":Br,"script.js":Ar}},page:{directory:"pages",component:"helloPage",files:{"config.json":Dr,"script.js":Fr,"styles.css":$r,"eventScripts/greet.js":jr}},toolbarItem:{directory:"toolbarItems",component:"helloToolbarItem",files:{"config.json":Lr,"script.js":Or}},objectSettingsItem:{directory:"objectSettingsItems",component:"helloObjectSettingsItem",files:{"config.json":zr,"script.js":Mr}},jsAction:{directory:"actions",component:"helloAction",files:{"config.json":Hr,"script.js":Ur}}};function ji(e,t="src"){let{directory:n,component:o,files:r}=$i[e];return Object.entries(r).map(([i,p])=>({path:`${t}/${n}/${o}/${i}`,content:p}))}function Vr(e,t="src"){return[...new Set(e)].flatMap(n=>ji(n,t))}var qr=`# Copilot review instructions for this Kizen plugin
161
+
162
+ This repo is a Kizen plugin app: a \`kizen.json\` manifest plus the artifacts
163
+ that \`@kizenapps/packager\` finds by walking the directory tree under the
164
+ manifest's \`entry\` (default \`src/\`). No manifest key lists artifacts. The
165
+ directory layout decides what gets packaged.
166
+
167
+ ## The full Kizen plugin documentation is available at \`.copilot-docs/\`
168
+
169
+ Before this review started, the complete Kizen plugin developer documentation
170
+ was fetched into \`.copilot-docs/\` by \`.github/workflows/copilot-code-review.yml\`.
171
+ It is not committed to this repo \u2014 it is cloned from \`kizen/app-engine\` at review
172
+ time, so it is always current. It is the authoritative reference for every plugin
173
+ API, manifest field and runtime contract. Deliberately, no plugin rules are
174
+ copied into this repo: read them from \`.copilot-docs/\` instead.
175
+
176
+ Use it. Start from:
177
+
178
+ - \`.copilot-docs/17-gotchas.md\` \u2014 the consolidated list of traps and silent
179
+ failure modes, grouped by topic. Scan the sections relevant to the changed
180
+ files.
181
+ - \`.copilot-docs/method-index.md\` \u2014 A\u2013Z lookup from any method, manifest field,
182
+ endpoint or identifier to the doc that owns it.
183
+ - \`.copilot-docs/03-manifest-reference.md\` \u2014 every \`kizen.json\` and \`config.json\`
184
+ field, the component directory names, \`api_name\` rules, and the build/publish
185
+ validation rules.
186
+ - The other numbered docs (\`.copilot-docs/04-worker-runtime-api.md\`,
187
+ \`.copilot-docs/07-automation-steps.md\`, \`.copilot-docs/08-actions.md\`, and so
188
+ on) for complete contracts.
189
+
190
+ **Many Kizen plugin APIs fail silently when misused** \u2014 the call succeeds,
191
+ nothing throws, and the behavior is quietly wrong. These defects are not
192
+ detectable from the calling code alone, and they are the single most valuable
193
+ thing to catch in review. When a changed file calls a \`this.*\` worker method,
194
+ look that method up in \`method-index.md\` and read its contract before concluding
195
+ the call is correct.
196
+
197
+ The same applies to artifact config: check each \`config.json\` against
198
+ \`03-manifest-reference.md\`, and each automation step against
199
+ \`07-automation-steps.md\`.
200
+
201
+ When a review comment is based on the documentation, name the file it came from.
202
+
203
+ If \`.copilot-docs/\` is not present, the setup workflow did not run \u2014 it only
204
+ takes effect once it is on the repository's default branch \u2014 so say that in
205
+ the review instead of guessing at the rules from memory.
206
+
207
+ ## Scope
208
+
209
+ This file covers repo structure and general review. Two path-scoped files cover
210
+ the rest: \`.github/instructions/security.instructions.md\` for security-sensitive
211
+ patterns and \`.github/instructions/version-discipline.instructions.md\` for
212
+ manifest version bumps.
213
+ `;var Jr='---\napplyTo: "src/**/*.js,kizen.json"\n---\n\n# Security review rules for plugin scripts\n\nThe rules themselves live in the docs corpus that\n`.github/workflows/copilot-code-review.yml` fetches into `.copilot-docs/`, so\nthey cannot drift out of date here. Read them there rather than reviewing from\nmemory.\n\nWhen a change touches a service, `auth_credentials`, a `{{secret.KEY}}`\nreference, `base_config.secrets`, or dynamic code (`eval`, `new Function`, or a\nstring argument to `setTimeout` or `setInterval`), read\n`.copilot-docs/06-auth-secrets-services.md` together with the "Services, auth &\nsecrets" and "Release & publish" sections of `.copilot-docs/17-gotchas.md`, and\nreview the change against what they say.\n\nWhen a change uses `__dangerouslySkipProxy`, also read\n`.copilot-docs/11-output-ui-iframes-frames.md`.\n';var Wr=`---
225
214
  applyTo: "kizen.json"
226
215
  ---
227
216
 
228
217
  # Version-bump discipline for \`kizen.json\`
229
218
 
230
- ## What a wrong bump breaks
231
-
232
- A business that installs this plugin accumulates its own stored state
233
- (automation runs, config values, references to entities) shaped by what was
234
- published at the time. Publishing is additive: it never rewrites a business's
235
- stored rows, and the plugin author has no way to migrate that state for them.
236
- A change is breaking when it invalidates an assumption the business's existing
237
- data already depends on.
238
-
239
- A MINOR or PATCH republish applies at once to a business's running automations
240
- and installed artifacts. Only a new MAJOR version waits for the business to
241
- upgrade explicitly. A change that needed MAJOR but shipped as MINOR or PATCH
242
- therefore breaks the business with no upgrade gate in between.
243
-
244
- Two kinds of change get MAJOR because they fail without an error:
245
-
246
- - Renaming a config field, changing its type, or adding a required key. A
247
- template reference like \`{{config.key}}\` for a key that no longer exists
248
- resolves to a literal \`null\`, and the artifact renders wrong or does
249
- nothing.
250
- - Removing or renaming a JS action. A business's automation and UI
251
- associations key on the action's \`api_name\` as a plain string, with no
252
- foreign key. After a rename or removal those associations stop firing.
253
-
254
- Review every \`kizen.json\` diff against the table below before approving the
255
- version bump in the same PR.
256
-
257
- ## Bump matrix
258
-
259
- | Resource | Change | Required bump |
260
- | --- | --- | --- |
261
- | Plugin | change \`api_name\` | **HARD-BLOCK**: identity can never change |
262
- | Service | add | MINOR |
263
- | Service | remove | MAJOR |
264
- | Service | change auth type or \`auth_level\` | MAJOR |
265
- | Service | change \`auth_credentials\` (client id/secret, scopes, authorize/token URLs) | MAJOR |
266
- | Service | change base URL or other non-auth field | PATCH |
267
- | Service | rename \`api_name\` | MAJOR |
268
- | Secret | add | MINOR |
269
- | Secret | remove | MINOR |
270
- | Secret | rename key | MAJOR |
271
- | Secret | re-encrypt value only | PATCH |
272
- | Automation step | add | MINOR |
273
- | Automation step | remove entire step | MAJOR |
274
- | Automation step | remove an input or output | MAJOR |
275
- | Automation step | change input/output \`data_type\` | MAJOR |
276
- | Automation step | add required input | MAJOR |
277
- | Automation step | add optional input | MINOR |
278
- | Automation step | change python runtime | PATCH |
279
- | Automation step | edit script body only | PATCH |
280
- | Artifact (frame, block, adornment, page, route script, toolbar/object-settings item, calendar source) | add | MINOR |
281
- | Artifact | remove | MINOR |
282
- | Artifact | rename \`api_name\` | MINOR |
283
- | Artifact | edit script or behavior | PATCH |
284
- | JS action | add | MINOR |
285
- | JS action | remove | MAJOR |
286
- | JS action | rename \`api_name\` | MAJOR |
287
- | JS action | change \`hint_object_name\` or script | PATCH |
288
- | Config field | add optional (with default) | MINOR |
289
- | Config field | add required (no default) | MAJOR |
290
- | Config field | remove | MINOR |
291
- | Config field | rename | MAJOR |
292
- | Config field | change type | MAJOR |
293
- | Config field | change default or label | PATCH |
294
- | \`required_entitlement\` | add gating | MINOR |
295
- | \`required_entitlement\` | change or remove | PATCH |
296
- | Manifest metadata (\`name\`, \`description\`, \`entry\`, \`release_branches\`, \`release_environments\`, \`published\`, \`developer_business_id\`) | any change | PATCH |
297
- `;function Wr(){return[{path:".github/copilot-instructions.md",content:Vr},{path:".github/instructions/security.instructions.md",content:qr},{path:".github/instructions/version-discipline.instructions.md",content:Jr}]}import{deflateSync as ji}from"zlib";var zt=512,$i=150,Li=26,Ht=46,Kr=.6,Mi=Ht*.55,zi=.55,Hi=.47;function Ui(e){let t=2166136261;for(let n=0;n<e.length;n+=1)t^=e.charCodeAt(n),t=t+((t<<1)+(t<<4)+(t<<7)+(t<<8)+(t<<24))>>>0;return t}function Vi(e){let t=Ui(e);return{hue:t%360,quarterTurns:(t>>>16)%4}}function qi(e,t,n){let o=(1-Math.abs(2*n-1))*t,r=e/60,i=o*(1-Math.abs(r%2-1)),d=n-o/2,[f,g,m]=r<1?[o,i,0]:r<2?[i,o,0]:r<3?[0,o,i]:r<4?[0,i,o]:r<5?[i,0,o]:[o,0,i];return[Math.round((f+d)*255),Math.round((g+d)*255),Math.round((m+d)*255)]}function He(e,t,n,o,r){let i=Math.abs(e)-n+r,d=Math.abs(t)-o+r;return Math.hypot(Math.max(i,0),Math.max(d,0))+Math.min(Math.max(i,d),0)-r}function at(e,t,n,o,r){return Math.hypot(e-n,t-o)-r}function Ji(e,t){let n=$i,o=Ht,r=o*Kr,i=Mi,d=He(e,t,n,n,Li),f=Math.min(at(e,t,0,-n-r,o),He(e,t+n+r/2,i,r/2+1,0)),g=Math.min(at(e,t,n+r,0,o),He(e-n-r/2,t,r/2+1,i,0));d=Math.min(d,f,g);let m=Math.min(at(e,t,0,n-r,o),He(e,t-n+r/2,i,r/2+1,0)),b=Math.min(at(e,t,-n+r,0,o),He(e+n-r/2,t,r/2+1,i,0));return Math.max(d,-m,-b)}function Wi(e){let t=zt,n=new Uint8Array(t*t*4),[o,r,i]=qi(e.hue,zi,Hi),d=Ht*(1+Kr),f=(t-1)/2,g=d/2;for(let m=0;m<t;m+=1)for(let b=0;b<t;b+=1){let T=b-f,P=m-f;for(let S=0;S<e.quarterTurns;S+=1)[T,P]=[-P,T];let x=Ji(T+g,P-g),p=Math.min(1,Math.max(0,.5-x));if(p<=0)continue;let y=(m*t+b)*4;n[y]=o,n[y+1]=r,n[y+2]=i,n[y+3]=Math.round(p*255)}return n}var Ki=new Uint32Array(256).map((e,t)=>{let n=t;for(let o=0;o<8;o+=1)n=n&1?3988292384^n>>>1:n>>>1;return n>>>0});function Gi(e){let t=4294967295;for(let n of e)t=(Ki[(t^n)&255]??0)^t>>>8;return(t^4294967295)>>>0}function Mt(e,t){let n=Buffer.from(e,"latin1"),o=Buffer.alloc(4);o.writeUInt32BE(t.length);let r=Buffer.alloc(4);return r.writeUInt32BE(Gi(Buffer.concat([n,t]))),Buffer.concat([o,n,t,r])}var Yi=Buffer.from([137,80,78,71,13,10,26,10]);function Xi(e,t,n){if(n.length!==e*t*4)throw new Error(`encodePng: expected ${String(e*t*4)} bytes of RGBA for ${String(e)}x${String(t)}, got ${String(n.length)}`);let o=Buffer.alloc(13);o.writeUInt32BE(e,0),o.writeUInt32BE(t,4),o[8]=8,o[9]=6;let r=e*4,i=Buffer.alloc((r+1)*t);for(let d=0;d<t;d+=1)i.set(n.subarray(d*r,(d+1)*r),d*(r+1)+1);return Buffer.concat([Yi,Mt("IHDR",o),Mt("IDAT",ji(i,{level:9})),Mt("IEND",new Uint8Array(0))])}function Gr(e){return Xi(zt,zt,Wi(Vi(e)))}var es="src/thumbnail.png",ts=["go","fmo"];async function ct(e){try{return await Zi(e),!0}catch{return!1}}async function dt(e){return await ct(ce(e,"kizen.json"))?"has-manifest":await ct(ce(e,".kizenapp"))?"has-kizenapp":"ok"}async function Xr(e,t){let n=ce(e,t);if(!await ct(n))return n;for(let o=1;o<1e3;o++){let r=ce(e,`${t}-${String(o)}`);if(!await ct(r))return r}throw new Error(`Could not find an available directory name for "${t}"`)}function Vt(e){let t=e.developerBusinessId.trim(),n=t!==""&&!ts.includes(e.developerEnvironment)?[e.developerEnvironment]:["prod"];return{name:e.name,version:"1.0.0",published:!0,api_name:e.apiName,external_link:e.externalLink,description:e.description,entry:"src/",engine:"1.0.0",release_notes_directory:"releaseNotes/",release_environments:n,config_template:{},base_config:{},...t?{developer_business_id:{[e.developerEnvironment]:t}}:{}}}async function Yr(e,t){let n=t.map(r=>({fullPath:ce(e,...r.path.split("/")),content:r.content})),o=new Set(n.map(r=>Qi(r.fullPath)));await Promise.all([...o].map(r=>lt(r,{recursive:!0}))),await Promise.all(n.map(r=>Ut(r.fullPath,r.content,"utf-8")))}async function pt(e){await lt(e.targetDir,{recursive:!0});let t=Vt(e);await Ut(ce(e.targetDir,"kizen.json"),JSON.stringify(t,null,2)+`
298
- `,"utf-8"),await lt(ce(e.targetDir,"src"),{recursive:!0}),await lt(ce(e.targetDir,"releaseNotes"),{recursive:!0}),await Promise.all([Yr(e.targetDir,Ur(e.artifacts??[])),Yr(e.targetDir,Wr()),Ut(ce(e.targetDir,...es.split("/")),Gr(e.apiName))]),Ne(e.targetDir)}var he=["name","apiName","externalLink","description","developerBusinessId"],ut={name:"Name",apiName:"API name",externalLink:"External link",description:"Description",developerBusinessId:"Business ID"},qt=["name","apiName","description"],Jt=/^[a-z_][a-z0-9_]+$/,Wt="must start with a letter or underscore and contain only lowercase letters, numbers, or underscores (minimum 2 characters)";function ft(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,"_").replace(/^_+|_+$/g,"")}function Zr(e){return{name:"",apiName:"",externalLink:"",description:"",developerBusinessId:e}}function Qr(e,t){let n=t.trim();if(qt.includes(e)&&!n)return`${ut[e]} is required`;if(e==="apiName"&&!Jt.test(n))return`${ut[e]} ${Wt}`}function en(e,t){return e==="description"?t:t.trim()}function tn(e,t){let n=new Set(e);return n.has(t)?n.delete(t):n.add(t),X.filter(o=>n.has(o))}import{jsx as E,jsxs as N}from"react/jsx-runtime";var ke=({text:e})=>E(I,{dimColor:!0,children:e}),rn=({parentDir:e,defaultBusinessId:t,defaultEnvironment:n})=>{let o=rs(),[r,i]=Be({type:"target-select",cursor:0}),[d,f]=Be("in-place"),[g,m]=Be(()=>Zr(t)),[b,T]=Be(()=>[...X]),[P,x]=Be(""),[p,y]=Be(e),S=mt((v,c)=>{f(v),x(c.name),i({type:"field-entry",field:0,values:c})},[]),H=mt(async v=>{let c=await dt(v);if(c!=="ok"){i({type:"precheck-error",targetDir:v,reason:c});return}y(v),S("in-place",g)},[g,S]),O=mt(async(v,c)=>{try{let a=await Xr(e,v.apiName);y(a),i({type:"confirm",values:v,artifacts:c})}catch(a){i({type:"error",message:a instanceof Error?a.message:String(a)})}},[e]),w=mt(async(v,c,a)=>{try{await pt({targetDir:c,name:v.name,apiName:v.apiName,externalLink:v.externalLink,description:v.description,developerBusinessId:v.developerBusinessId,developerEnvironment:n,artifacts:a}),i({type:"done",targetDir:c})}catch(s){i({type:"error",message:s instanceof Error?s.message:String(s)})}},[n]);if(ns((v,c)=>{if(c.ctrl&&v==="c"){o.exit();return}if(r.type==="target-select"){c.upArrow?i({type:"target-select",cursor:0}):c.downArrow?i({type:"target-select",cursor:1}):c.return?r.cursor===0?H(e):S("sub-dir",g):c.escape&&o.exit();return}if(r.type==="precheck-error"){(c.return||c.escape)&&o.exit();return}if(r.type==="field-entry"){let{field:a,values:s}=r,l=he[a];if(!l)return;if(c.escape){o.exit();return}if(c.backspace||c.delete){x(u=>u.slice(0,-1));return}if(c.upArrow&&a>0){let u={...s,[l]:P},h=a-1,k=he[h];i({type:"field-entry",field:h,values:u}),m(u),x(k?u[k]:"");return}if(c.return||c.tab||c.downArrow){let u=Qr(l,P);if(u!==void 0){i({type:"field-entry",field:a,values:s,fieldError:u});return}let h=en(l,P),k={...s,[l]:h};m(k);let _=a+1;if(_>=he.length)x(""),i({type:"artifact-select",values:k,cursor:0,selected:b});else{let A=he[_],M=A?k[A]:"",W=A==="apiName"&&!M?ft(k.name):M;i({type:"field-entry",field:_,values:k}),x(W)}return}v&&!c.ctrl&&!c.meta&&x(u=>u+v);return}if(r.type==="artifact-select"){let{cursor:a,selected:s,values:l}=r;if(c.escape){let u=he.length-1,h=he[u];i({type:"field-entry",field:u,values:l}),x(h?l[h]:"");return}if(c.upArrow){i({...r,cursor:Math.max(0,a-1)});return}if(c.downArrow){i({...r,cursor:Math.min(X.length-1,a+1)});return}if(v===" "){let u=X[a];if(u){let h=tn(s,u);T(h),i({...r,selected:h})}return}if(v==="a"){T([...X]),i({...r,selected:[...X]});return}if(v==="n"){T([]),i({...r,selected:[]});return}c.return&&(d==="sub-dir"?(i({type:"resolving-target"}),O(l,s)):i({type:"confirm",values:l,artifacts:s}));return}if(r.type==="confirm"){if(c.escape){i({type:"artifact-select",values:r.values,cursor:0,selected:r.artifacts});return}c.return&&(i({type:"writing"}),w(r.values,p,r.artifacts));return}(r.type==="done"||r.type==="error")&&(c.return||c.escape)&&o.exit()}),r.type==="target-select"){let v=[{label:"Use current directory",desc:e},{label:"Create new sub-directory",desc:`${e}/<inferred from API name>`}];return N(z,{flexDirection:"column",paddingY:1,paddingX:2,gap:1,children:[E(q,{}),N(z,{flexDirection:"column",gap:0,children:[E(I,{bold:!0,children:"Where should the new plugin live?"}),v.map((c,a)=>{let s=r.cursor===a;return N(z,{gap:2,children:[E(I,{...s&&{color:"cyan"},children:s?"\u276F":" "}),E(I,{bold:s,...s&&{color:"cyan"},children:c.label}),E(I,{dimColor:!0,children:c.desc})]},c.label)})]}),E(ke,{text:"\u2191\u2193 to move \xB7 Enter to select \xB7 Esc to cancel"})]})}if(r.type==="precheck-error"){let{targetDir:v,reason:c}=r;return N(z,{flexDirection:"column",paddingY:1,paddingX:2,gap:1,children:[E(q,{}),E(I,{color:"red",bold:!0,children:"Cannot create plugin"}),N(z,{flexDirection:"column",gap:0,children:[N(I,{children:[v," already contains ",E(I,{bold:!0,children:c==="has-manifest"?"kizen.json":".kizenapp/"}),"."]}),E(I,{dimColor:!0,children:"Remove the conflicting file/directory or choose a different target to avoid overwriting an existing plugin."})]}),E(ke,{text:"Enter or Esc to exit"})]})}if(r.type==="field-entry"){let{field:v,fieldError:c}=r,a=d==="sub-dir"?`Target: sub-directory of ${e} (inferred from API name)`:`Target: ${p}`;return N(z,{flexDirection:"column",paddingY:1,paddingX:2,gap:1,children:[E(q,{}),N(z,{flexDirection:"column",gap:0,children:[E(I,{bold:!0,children:"Plugin details"}),E(I,{dimColor:!0,children:a})]}),c!==void 0&&N(I,{color:"red",children:["Error: ",c]}),E(z,{flexDirection:"column",gap:0,children:he.map((s,l)=>{let u=v===l,h=u?P:g[s],k=qt.includes(s),_=`${ut[s]}${k?"":" (optional)"}`;return N(z,{gap:2,children:[E(z,{width:24,children:E(I,{bold:u,...u&&{color:"cyan"},children:_})}),E(I,{...u&&{color:"cyan"},children:">"}),E(I,{children:h}),u&&E(I,{color:"cyan",children:"\u2588"})]},s)})}),E(ke,{text:"Enter/Tab/\u2193 next \xB7 \u2191 previous \xB7 Backspace delete \xB7 Esc cancel"})]})}if(r.type==="artifact-select"){let{cursor:v,selected:c}=r;return N(z,{flexDirection:"column",paddingY:1,paddingX:2,gap:1,children:[E(q,{}),N(z,{flexDirection:"column",gap:0,children:[E(I,{bold:!0,children:"Which artifacts should we scaffold?"}),E(I,{dimColor:!0,children:"Each one gets a directory with a config.json and a script that runs."})]}),E(z,{flexDirection:"column",gap:0,children:X.map((a,s)=>{let l=v===s,u=c.includes(a);return N(z,{gap:1,children:[E(I,{...l&&{color:"cyan"},children:l?"\u276F":" "}),E(I,{...u&&{color:"green"},children:u?"\u25C9":"\u25EF"}),E(I,{bold:l,...l&&{color:"cyan"},children:Lt[a]})]},a)})}),E(ke,{text:"\u2191\u2193 move \xB7 Space toggle \xB7 a all \xB7 n none \xB7 Enter continue \xB7 Esc back"})]})}if(r.type==="confirm"){let v=Vt({targetDir:p,name:r.values.name,apiName:r.values.apiName,externalLink:r.values.externalLink,description:r.values.description,developerBusinessId:r.values.developerBusinessId,developerEnvironment:n});return N(z,{flexDirection:"column",paddingY:1,paddingX:2,gap:1,children:[E(q,{}),N(z,{flexDirection:"column",gap:0,children:[E(I,{bold:!0,children:"Ready to create"}),N(I,{dimColor:!0,children:["Target: ",p]})]}),N(z,{flexDirection:"column",gap:0,children:[E(I,{bold:!0,children:"kizen.json preview"}),E(I,{children:JSON.stringify(v,null,2)})]}),N(z,{flexDirection:"column",gap:0,children:[E(I,{bold:!0,children:"Artifacts"}),r.artifacts.length===0?N(I,{dimColor:!0,children:[" ","none (src/ will hold only thumbnail.png)"]}):r.artifacts.map(c=>N(I,{dimColor:!0,children:[" ",Lt[c]]},c))]}),N(z,{flexDirection:"column",gap:0,children:[E(I,{dimColor:!0,children:"Also creates:"}),N(I,{dimColor:!0,children:[" ",gt(p,"src/")]}),N(I,{dimColor:!0,children:[" ",gt(p,"src/thumbnail.png")," (generated placeholder)"]}),N(I,{dimColor:!0,children:[" ",gt(p,"releaseNotes/")]}),N(I,{dimColor:!0,children:[" ",gt(p,".gitignore")," (adds .kizenapp/)"]})]}),E(ke,{text:"Enter to create \xB7 Esc to go back"})]})}return r.type==="resolving-target"?E(z,{paddingY:1,paddingX:2,children:E(I,{dimColor:!0,children:"Finding available sub-directory\u2026"})}):r.type==="writing"?E(z,{paddingY:1,paddingX:2,children:E(I,{dimColor:!0,children:"Creating plugin\u2026"})}):r.type==="done"?N(z,{flexDirection:"column",paddingY:1,paddingX:2,gap:1,children:[E(q,{}),N(I,{color:"green",bold:!0,children:["Plugin created at ",r.targetDir]}),N(z,{flexDirection:"column",gap:0,children:[E(I,{dimColor:!0,children:"Next steps:"}),N(I,{children:[" ","cd ",r.targetDir]}),N(I,{children:[" ","npx --yes @kizenapps/cli dev"]}),N(I,{dimColor:!0,children:[" ","Replace src/thumbnail.png with real artwork before publishing."]})]}),E(ke,{text:"Enter or Esc to exit"})]}):N(z,{flexDirection:"column",paddingY:1,paddingX:2,gap:1,children:[E(q,{}),E(I,{color:"red",bold:!0,children:"Failed to create plugin"}),E(I,{children:r.message}),E(ke,{text:"Enter or Esc to exit"})]})};import{mkdir as nn,readFile as os,readdir as is,writeFile as on}from"fs/promises";import{homedir as ss}from"os";import{dirname as as,join as ht}from"path";var Y=["go","fmo","staging","integration","test1"];var Pe=ht(ss(),".kizenappbuilder"),De=ht(Pe,"credentials.json"),ye="credentials";function ls(e){return Y.includes(e)}function cs(e){if(typeof e!="object"||e===null)throw new Error("Credentials must be a JSON object");let t=e,n=t.environment;return{apiKey:typeof t.apiKey=="string"?t.apiKey:"",userId:typeof t.userId=="string"?t.userId:"",businessId:typeof t.businessId=="string"?t.businessId:"",environment:ls(n)?n:"go"}}async function be(e){let t=await os(e,"utf-8");return cs(JSON.parse(t))}async function Z(){try{return await be(De)}catch{return null}}async function ds(e){await nn(as(De),{recursive:!0,mode:448}),await on(De,JSON.stringify(e,null,2),{encoding:"utf-8",mode:384})}function sn(e){return ht(Pe,`${e}.json`)}async function Ie(){let e=[{name:ye,path:De,isDefault:!0}];try{let t=await is(Pe);for(let n of t){if(!n.endsWith(".json"))continue;let o=n.slice(0,-5);o!==ye&&e.push({name:o,path:ht(Pe,n),isDefault:!1})}}catch{}return e}async function an(e,t){if(e===ye){await ds(t);return}await nn(Pe,{recursive:!0,mode:448}),await on(sn(e),JSON.stringify(t,null,2),{encoding:"utf-8",mode:384})}async function de(e){try{return await be(sn(e))}catch{return null}}var ps="A hello-world Kizen plugin.";function us(e){if(e===void 0||e.trim()===""||e.trim()==="all")return[...X];if(e.trim()==="none")return[];let t=e.split(",").map(o=>o.trim()).filter(o=>o!==""),n=t.filter(o=>!X.includes(o));if(n.length>0)throw new Error(`Unknown artifact type(s): ${n.join(", ")}. Valid types: ${X.join(", ")}, or "all" / "none".`);return[...new Set(t)]}function fs(e,t,n){let o=e.name?.trim()??"";if(o==="")throw new Error("--name is required for a non-interactive run.");let r=(e.apiName?.trim()??"")||ft(o);if(!Jt.test(r))throw new Error(`api_name "${r}" is invalid: ${Wt}. Pass --api-name.`);let i=e.description?.trim(),d=e.businessId?.trim()??t.businessId,f=gs(e,t);return{targetDir:n,name:o,apiName:r,externalLink:e.externalLink?.trim()??"",description:i===void 0||i===""?ps:i,developerBusinessId:d,developerEnvironment:f,artifacts:us(e.artifacts)}}function ms(e){return Y.includes(e)}function gs(e,t){let n=e.environment?.trim();if(n!==void 0&&n!==""){if(!ms(n))throw new Error(`Unknown environment "${n}". Valid environments: ${Y.join(", ")}.`);return n}if(e.businessId!==void 0&&t.businessId==="")throw new Error("--environment is required alongside --business-id when no credentials are saved, so the id is keyed to the environment that issued it.");return t.environment}async function ln(e,t,n,o){let r;try{r=fs(e,t,n)}catch(f){o.writeStderr(`Error: ${f instanceof Error?f.message:String(f)}
219
+ The bump matrix lives in the docs corpus that
220
+ \`.github/workflows/copilot-code-review.yml\` fetches into \`.copilot-docs/\`, so it
221
+ cannot drift out of date here.
222
+
223
+ Check every \`kizen.json\` diff against the "How big a bump?" matrix in
224
+ \`.copilot-docs/16-release-and-publish.md\` and the "Release & publish" section of
225
+ \`.copilot-docs/17-gotchas.md\`, and name the change that sets the required level.
226
+ `;var Gr=`# Copilot only reads this file from the default branch, and only if the job is named copilot-setup-steps.
227
+ name: Copilot code review setup
228
+
229
+ on:
230
+ workflow_dispatch:
231
+
232
+ jobs:
233
+ copilot-setup-steps:
234
+ runs-on: ubuntu-latest
235
+ timeout-minutes: 10
236
+ permissions:
237
+ contents: read
238
+ steps:
239
+ - name: Check out this plugin repo
240
+ uses: actions/checkout@v4
241
+
242
+ - name: Fetch the Kizen plugin docs corpus into .copilot-docs/
243
+ run: |
244
+ set -euo pipefail
245
+ git clone --depth 1 --filter=blob:none --sparse \\
246
+ https://github.com/kizen/app-engine.git .docs-src
247
+ git -C .docs-src sparse-checkout set --no-cone '/docs/**/*.md' '!/docs/site/**'
248
+ mv .docs-src/docs .copilot-docs
249
+ rm -rf .docs-src
250
+
251
+ - name: Verify the corpus landed
252
+ run: |
253
+ set -euo pipefail
254
+ test -f .copilot-docs/17-gotchas.md
255
+ test -f .copilot-docs/method-index.md
256
+
257
+ numbered=$(find .copilot-docs -maxdepth 1 -name '[0-9][0-9]-*.md' | wc -l | tr -d ' ')
258
+ test "$numbered" -ge 18
259
+ test -f .copilot-docs/examples/kitchen_sink.md
260
+
261
+ count=$(find .copilot-docs -name '*.md' | wc -l | tr -d ' ')
262
+ echo "Fetched $count markdown files into .copilot-docs/ ($numbered numbered docs)"
263
+ test "$count" -ge 24
264
+ du -sh .copilot-docs
265
+ `;function lt(){return[{path:".github/copilot-instructions.md",content:qr},{path:".github/instructions/security.instructions.md",content:Jr},{path:".github/instructions/version-discipline.instructions.md",content:Wr},{path:".github/workflows/copilot-code-review.yml",content:Gr}]}import{deflateSync as Hi}from"zlib";var Ht=512,Ui=150,Vi=26,Ut=46,Kr=.6,qi=Ut*.55,Ji=.55,Wi=.47;function Gi(e){let t=2166136261;for(let n=0;n<e.length;n+=1)t^=e.charCodeAt(n),t=t+((t<<1)+(t<<4)+(t<<7)+(t<<8)+(t<<24))>>>0;return t}function Ki(e){let t=Gi(e);return{hue:t%360,quarterTurns:(t>>>16)%4}}function Yi(e,t,n){let o=(1-Math.abs(2*n-1))*t,r=e/60,i=o*(1-Math.abs(r%2-1)),p=n-o/2,[f,g,m]=r<1?[o,i,0]:r<2?[i,o,0]:r<3?[0,o,i]:r<4?[0,i,o]:r<5?[i,0,o]:[o,0,i];return[Math.round((f+p)*255),Math.round((g+p)*255),Math.round((m+p)*255)]}function Ue(e,t,n,o,r){let i=Math.abs(e)-n+r,p=Math.abs(t)-o+r;return Math.hypot(Math.max(i,0),Math.max(p,0))+Math.min(Math.max(i,p),0)-r}function ct(e,t,n,o,r){return Math.hypot(e-n,t-o)-r}function Xi(e,t){let n=Ui,o=Ut,r=o*Kr,i=qi,p=Ue(e,t,n,n,Vi),f=Math.min(ct(e,t,0,-n-r,o),Ue(e,t+n+r/2,i,r/2+1,0)),g=Math.min(ct(e,t,n+r,0,o),Ue(e-n-r/2,t,r/2+1,i,0));p=Math.min(p,f,g);let m=Math.min(ct(e,t,0,n-r,o),Ue(e,t-n+r/2,i,r/2+1,0)),y=Math.min(ct(e,t,-n+r,0,o),Ue(e+n-r/2,t,r/2+1,i,0));return Math.max(p,-m,-y)}function Zi(e){let t=Ht,n=new Uint8Array(t*t*4),[o,r,i]=Yi(e.hue,Ji,Wi),p=Ut*(1+Kr),f=(t-1)/2,g=p/2;for(let m=0;m<t;m+=1)for(let y=0;y<t;y+=1){let T=y-f,P=m-f;for(let w=0;w<e.quarterTurns;w+=1)[T,P]=[-P,T];let x=Xi(T+g,P-g),c=Math.min(1,Math.max(0,.5-x));if(c<=0)continue;let b=(m*t+y)*4;n[b]=o,n[b+1]=r,n[b+2]=i,n[b+3]=Math.round(c*255)}return n}var Qi=new Uint32Array(256).map((e,t)=>{let n=t;for(let o=0;o<8;o+=1)n=n&1?3988292384^n>>>1:n>>>1;return n>>>0});function es(e){let t=4294967295;for(let n of e)t=(Qi[(t^n)&255]??0)^t>>>8;return(t^4294967295)>>>0}function Mt(e,t){let n=Buffer.from(e,"latin1"),o=Buffer.alloc(4);o.writeUInt32BE(t.length);let r=Buffer.alloc(4);return r.writeUInt32BE(es(Buffer.concat([n,t]))),Buffer.concat([o,n,t,r])}var ts=Buffer.from([137,80,78,71,13,10,26,10]);function rs(e,t,n){if(n.length!==e*t*4)throw new Error(`encodePng: expected ${String(e*t*4)} bytes of RGBA for ${String(e)}x${String(t)}, got ${String(n.length)}`);let o=Buffer.alloc(13);o.writeUInt32BE(e,0),o.writeUInt32BE(t,4),o[8]=8,o[9]=6;let r=e*4,i=Buffer.alloc((r+1)*t);for(let p=0;p<t;p+=1)i.set(n.subarray(p*r,(p+1)*r),p*(r+1)+1);return Buffer.concat([ts,Mt("IHDR",o),Mt("IDAT",Hi(i,{level:9})),Mt("IEND",new Uint8Array(0))])}function Yr(e){return rs(Ht,Ht,Zi(Ki(e)))}var is="src/thumbnail.png",ss=["go","fmo"];async function pt(e){try{return await ns(e),!0}catch{return!1}}async function ye(e){return await pt(ce(e,"kizen.json"))?"has-manifest":await pt(ce(e,".kizenapp"))?"has-kizenapp":"ok"}async function Zr(e,t){let n=ce(e,t);if(!await pt(n))return n;for(let o=1;o<1e3;o++){let r=ce(e,`${t}-${String(o)}`);if(!await pt(r))return r}throw new Error(`Could not find an available directory name for "${t}"`)}function qt(e){let t=e.developerBusinessId.trim(),n=t!==""&&!ss.includes(e.developerEnvironment)?[e.developerEnvironment]:["prod"];return{name:e.name,version:"1.0.0",published:!0,api_name:e.apiName,external_link:e.externalLink,description:e.description,entry:"src/",engine:"1.0.0",release_notes_directory:"releaseNotes/",release_environments:n,config_template:{},base_config:{},...t?{developer_business_id:{[e.developerEnvironment]:t}}:{}}}async function Xr(e,t){let n=t.map(r=>({fullPath:ce(e,...r.path.split("/")),content:r.content})),o=new Set(n.map(r=>os(r.fullPath)));await Promise.all([...o].map(r=>dt(r,{recursive:!0}))),await Promise.all(n.map(r=>Vt(r.fullPath,r.content,"utf-8")))}async function ut(e){await dt(e.targetDir,{recursive:!0});let t=qt(e);await Vt(ce(e.targetDir,"kizen.json"),JSON.stringify(t,null,2)+`
266
+ `,"utf-8"),await dt(ce(e.targetDir,"src"),{recursive:!0}),await dt(ce(e.targetDir,"releaseNotes"),{recursive:!0}),await Promise.all([Xr(e.targetDir,Vr(e.artifacts??[])),Xr(e.targetDir,lt()),Vt(ce(e.targetDir,...is.split("/")),Yr(e.apiName))]),he(e.targetDir)}var be=["name","apiName","externalLink","description","developerBusinessId"],ft={name:"Name",apiName:"API name",externalLink:"External link",description:"Description",developerBusinessId:"Business ID"},Jt=["name","apiName","description"],Wt=/^[a-z_][a-z0-9_]+$/,Gt="must start with a letter or underscore and contain only lowercase letters, numbers, or underscores (minimum 2 characters)";function mt(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,"_").replace(/^_+|_+$/g,"")}function Qr(e){return{name:"",apiName:"",externalLink:"",description:"",developerBusinessId:e}}function en(e,t){let n=t.trim();if(Jt.includes(e)&&!n)return`${ft[e]} is required`;if(e==="apiName"&&!Wt.test(n))return`${ft[e]} ${Gt}`}function tn(e,t){return e==="description"?t:t.trim()}function rn(e,t){let n=new Set(e);return n.has(t)?n.delete(t):n.add(t),X.filter(o=>n.has(o))}import{jsx as _,jsxs as B}from"react/jsx-runtime";var Ie=({text:e})=>_(I,{dimColor:!0,children:e}),nn=({parentDir:e,defaultBusinessId:t,defaultEnvironment:n})=>{let o=as(),[r,i]=De({type:"target-select",cursor:0}),[p,f]=De("in-place"),[g,m]=De(()=>Qr(t)),[y,T]=De(()=>[...X]),[P,x]=De(""),[c,b]=De(e),w=gt((v,d)=>{f(v),x(d.name),i({type:"field-entry",field:0,values:d})},[]),H=gt(async v=>{let d=await ye(v);if(d!=="ok"){i({type:"precheck-error",targetDir:v,reason:d});return}b(v),w("in-place",g)},[g,w]),j=gt(async(v,d)=>{try{let l=await Zr(e,v.apiName);b(l),i({type:"confirm",values:v,artifacts:d})}catch(l){i({type:"error",message:l instanceof Error?l.message:String(l)})}},[e]),C=gt(async(v,d,l)=>{try{await ut({targetDir:d,name:v.name,apiName:v.apiName,externalLink:v.externalLink,description:v.description,developerBusinessId:v.developerBusinessId,developerEnvironment:n,artifacts:l}),i({type:"done",targetDir:d})}catch(s){i({type:"error",message:s instanceof Error?s.message:String(s)})}},[n]);if(ls((v,d)=>{if(d.ctrl&&v==="c"){o.exit();return}if(r.type==="target-select"){d.upArrow?i({type:"target-select",cursor:0}):d.downArrow?i({type:"target-select",cursor:1}):d.return?r.cursor===0?H(e):w("sub-dir",g):d.escape&&o.exit();return}if(r.type==="precheck-error"){(d.return||d.escape)&&o.exit();return}if(r.type==="field-entry"){let{field:l,values:s}=r,a=be[l];if(!a)return;if(d.escape){o.exit();return}if(d.backspace||d.delete){x(u=>u.slice(0,-1));return}if(d.upArrow&&l>0){let u={...s,[a]:P},h=l-1,k=be[h];i({type:"field-entry",field:h,values:u}),m(u),x(k?u[k]:"");return}if(d.return||d.tab||d.downArrow){let u=en(a,P);if(u!==void 0){i({type:"field-entry",field:l,values:s,fieldError:u});return}let h=tn(a,P),k={...s,[a]:h};m(k);let E=l+1;if(E>=be.length)x(""),i({type:"artifact-select",values:k,cursor:0,selected:y});else{let R=be[E],z=R?k[R]:"",W=R==="apiName"&&!z?mt(k.name):z;i({type:"field-entry",field:E,values:k}),x(W)}return}v&&!d.ctrl&&!d.meta&&x(u=>u+v);return}if(r.type==="artifact-select"){let{cursor:l,selected:s,values:a}=r;if(d.escape){let u=be.length-1,h=be[u];i({type:"field-entry",field:u,values:a}),x(h?a[h]:"");return}if(d.upArrow){i({...r,cursor:Math.max(0,l-1)});return}if(d.downArrow){i({...r,cursor:Math.min(X.length-1,l+1)});return}if(v===" "){let u=X[l];if(u){let h=rn(s,u);T(h),i({...r,selected:h})}return}if(v==="a"){T([...X]),i({...r,selected:[...X]});return}if(v==="n"){T([]),i({...r,selected:[]});return}d.return&&(p==="sub-dir"?(i({type:"resolving-target"}),j(a,s)):i({type:"confirm",values:a,artifacts:s}));return}if(r.type==="confirm"){if(d.escape){i({type:"artifact-select",values:r.values,cursor:0,selected:r.artifacts});return}d.return&&(i({type:"writing"}),C(r.values,c,r.artifacts));return}(r.type==="done"||r.type==="error")&&(d.return||d.escape)&&o.exit()}),r.type==="target-select"){let v=[{label:"Use current directory",desc:e},{label:"Create new sub-directory",desc:`${e}/<inferred from API name>`}];return B(M,{flexDirection:"column",paddingY:1,paddingX:2,gap:1,children:[_(q,{}),B(M,{flexDirection:"column",gap:0,children:[_(I,{bold:!0,children:"Where should the new plugin live?"}),v.map((d,l)=>{let s=r.cursor===l;return B(M,{gap:2,children:[_(I,{...s&&{color:"cyan"},children:s?"\u276F":" "}),_(I,{bold:s,...s&&{color:"cyan"},children:d.label}),_(I,{dimColor:!0,children:d.desc})]},d.label)})]}),_(Ie,{text:"\u2191\u2193 to move \xB7 Enter to select \xB7 Esc to cancel"})]})}if(r.type==="precheck-error"){let{targetDir:v,reason:d}=r;return B(M,{flexDirection:"column",paddingY:1,paddingX:2,gap:1,children:[_(q,{}),_(I,{color:"red",bold:!0,children:"Cannot create plugin"}),B(M,{flexDirection:"column",gap:0,children:[B(I,{children:[v," already contains ",_(I,{bold:!0,children:d==="has-manifest"?"kizen.json":".kizenapp/"}),"."]}),_(I,{dimColor:!0,children:"Remove the conflicting file/directory or choose a different target to avoid overwriting an existing plugin."})]}),_(Ie,{text:"Enter or Esc to exit"})]})}if(r.type==="field-entry"){let{field:v,fieldError:d}=r,l=p==="sub-dir"?`Target: sub-directory of ${e} (inferred from API name)`:`Target: ${c}`;return B(M,{flexDirection:"column",paddingY:1,paddingX:2,gap:1,children:[_(q,{}),B(M,{flexDirection:"column",gap:0,children:[_(I,{bold:!0,children:"Plugin details"}),_(I,{dimColor:!0,children:l})]}),d!==void 0&&B(I,{color:"red",children:["Error: ",d]}),_(M,{flexDirection:"column",gap:0,children:be.map((s,a)=>{let u=v===a,h=u?P:g[s],k=Jt.includes(s),E=`${ft[s]}${k?"":" (optional)"}`;return B(M,{gap:2,children:[_(M,{width:24,children:_(I,{bold:u,...u&&{color:"cyan"},children:E})}),_(I,{...u&&{color:"cyan"},children:">"}),_(I,{children:h}),u&&_(I,{color:"cyan",children:"\u2588"})]},s)})}),_(Ie,{text:"Enter/Tab/\u2193 next \xB7 \u2191 previous \xB7 Backspace delete \xB7 Esc cancel"})]})}if(r.type==="artifact-select"){let{cursor:v,selected:d}=r;return B(M,{flexDirection:"column",paddingY:1,paddingX:2,gap:1,children:[_(q,{}),B(M,{flexDirection:"column",gap:0,children:[_(I,{bold:!0,children:"Which artifacts should we scaffold?"}),_(I,{dimColor:!0,children:"Each one gets a directory with a config.json and a script that runs."})]}),_(M,{flexDirection:"column",gap:0,children:X.map((l,s)=>{let a=v===s,u=d.includes(l);return B(M,{gap:1,children:[_(I,{...a&&{color:"cyan"},children:a?"\u276F":" "}),_(I,{...u&&{color:"green"},children:u?"\u25C9":"\u25EF"}),_(I,{bold:a,...a&&{color:"cyan"},children:zt[l]})]},l)})}),_(Ie,{text:"\u2191\u2193 move \xB7 Space toggle \xB7 a all \xB7 n none \xB7 Enter continue \xB7 Esc back"})]})}if(r.type==="confirm"){let v=qt({targetDir:c,name:r.values.name,apiName:r.values.apiName,externalLink:r.values.externalLink,description:r.values.description,developerBusinessId:r.values.developerBusinessId,developerEnvironment:n});return B(M,{flexDirection:"column",paddingY:1,paddingX:2,gap:1,children:[_(q,{}),B(M,{flexDirection:"column",gap:0,children:[_(I,{bold:!0,children:"Ready to create"}),B(I,{dimColor:!0,children:["Target: ",c]})]}),B(M,{flexDirection:"column",gap:0,children:[_(I,{bold:!0,children:"kizen.json preview"}),_(I,{children:JSON.stringify(v,null,2)})]}),B(M,{flexDirection:"column",gap:0,children:[_(I,{bold:!0,children:"Artifacts"}),r.artifacts.length===0?B(I,{dimColor:!0,children:[" ","none (src/ will hold only thumbnail.png)"]}):r.artifacts.map(d=>B(I,{dimColor:!0,children:[" ",zt[d]]},d))]}),B(M,{flexDirection:"column",gap:0,children:[_(I,{dimColor:!0,children:"Also creates:"}),B(I,{dimColor:!0,children:[" ",ht(c,"src/")]}),B(I,{dimColor:!0,children:[" ",ht(c,"src/thumbnail.png")," (generated placeholder)"]}),B(I,{dimColor:!0,children:[" ",ht(c,"releaseNotes/")]}),B(I,{dimColor:!0,children:[" ",ht(c,".gitignore")," (adds .kizenapp/)"]})]}),_(Ie,{text:"Enter to create \xB7 Esc to go back"})]})}return r.type==="resolving-target"?_(M,{paddingY:1,paddingX:2,children:_(I,{dimColor:!0,children:"Finding available sub-directory\u2026"})}):r.type==="writing"?_(M,{paddingY:1,paddingX:2,children:_(I,{dimColor:!0,children:"Creating plugin\u2026"})}):r.type==="done"?B(M,{flexDirection:"column",paddingY:1,paddingX:2,gap:1,children:[_(q,{}),B(I,{color:"green",bold:!0,children:["Plugin created at ",r.targetDir]}),B(M,{flexDirection:"column",gap:0,children:[_(I,{dimColor:!0,children:"Next steps:"}),B(I,{children:[" ","cd ",r.targetDir]}),B(I,{children:[" ","npx --yes @kizenapps/cli dev"]}),B(I,{dimColor:!0,children:[" ","Replace src/thumbnail.png with real artwork before publishing."]})]}),_(Ie,{text:"Enter or Esc to exit"})]}):B(M,{flexDirection:"column",paddingY:1,paddingX:2,gap:1,children:[_(q,{}),_(I,{color:"red",bold:!0,children:"Failed to create plugin"}),_(I,{children:r.message}),_(Ie,{text:"Enter or Esc to exit"})]})};import{mkdir as on,readFile as cs,readdir as ds,writeFile as sn}from"fs/promises";import{homedir as ps}from"os";import{dirname as us,join as yt}from"path";var Y=["go","fmo","staging","integration","test1"];var Ne=yt(ps(),".kizenappbuilder"),Fe=yt(Ne,"credentials.json"),xe="credentials";function fs(e){return Y.includes(e)}function ms(e){if(typeof e!="object"||e===null)throw new Error("Credentials must be a JSON object");let t=e,n=t.environment;return{apiKey:typeof t.apiKey=="string"?t.apiKey:"",userId:typeof t.userId=="string"?t.userId:"",businessId:typeof t.businessId=="string"?t.businessId:"",environment:fs(n)?n:"go"}}async function ve(e){let t=await cs(e,"utf-8");return ms(JSON.parse(t))}async function Z(){try{return await ve(Fe)}catch{return null}}async function gs(e){await on(us(Fe),{recursive:!0,mode:448}),await sn(Fe,JSON.stringify(e,null,2),{encoding:"utf-8",mode:384})}function an(e){return yt(Ne,`${e}.json`)}async function Re(){let e=[{name:xe,path:Fe,isDefault:!0}];try{let t=await ds(Ne);for(let n of t){if(!n.endsWith(".json"))continue;let o=n.slice(0,-5);o!==xe&&e.push({name:o,path:yt(Ne,n),isDefault:!1})}}catch{}return e}async function ln(e,t){if(e===xe){await gs(t);return}await on(Ne,{recursive:!0,mode:448}),await sn(an(e),JSON.stringify(t,null,2),{encoding:"utf-8",mode:384})}async function de(e){try{return await ve(an(e))}catch{return null}}var hs="A hello-world Kizen plugin.";function ys(e){if(e===void 0||e.trim()===""||e.trim()==="all")return[...X];if(e.trim()==="none")return[];let t=e.split(",").map(o=>o.trim()).filter(o=>o!==""),n=t.filter(o=>!X.includes(o));if(n.length>0)throw new Error(`Unknown artifact type(s): ${n.join(", ")}. Valid types: ${X.join(", ")}, or "all" / "none".`);return[...new Set(t)]}function bs(e,t,n){let o=e.name?.trim()??"";if(o==="")throw new Error("--name is required for a non-interactive run.");let r=(e.apiName?.trim()??"")||mt(o);if(!Wt.test(r))throw new Error(`api_name "${r}" is invalid: ${Gt}. Pass --api-name.`);let i=e.description?.trim(),p=e.businessId?.trim()??t.businessId,f=vs(e,t);return{targetDir:n,name:o,apiName:r,externalLink:e.externalLink?.trim()??"",description:i===void 0||i===""?hs:i,developerBusinessId:p,developerEnvironment:f,artifacts:ys(e.artifacts)}}function xs(e){return Y.includes(e)}function vs(e,t){let n=e.environment?.trim();if(n!==void 0&&n!==""){if(!xs(n))throw new Error(`Unknown environment "${n}". Valid environments: ${Y.join(", ")}.`);return n}if(e.businessId!==void 0&&t.businessId==="")throw new Error("--environment is required alongside --business-id when no credentials are saved, so the id is keyed to the environment that issued it.");return t.environment}async function cn(e,t,n,o){let r;try{r=bs(e,t,n)}catch(f){o.writeStderr(`Error: ${f instanceof Error?f.message:String(f)}
299
267
  `),o.setExitCode(1);return}let i=await o.precheckTargetDir(n);if(i!=="ok"){let f=i==="has-manifest"?"kizen.json":".kizenapp/";o.writeStderr(`Error: ${n} already contains ${f}. Refusing to overwrite an existing plugin.
300
268
  `),o.setExitCode(1);return}try{await o.createPlugin(r)}catch(f){o.writeStderr(`Error: ${f instanceof Error?f.message:String(f)}
301
- `),o.setExitCode(1);return}let d=r.artifacts&&r.artifacts.length>0?r.artifacts.join(", "):"none";o.writeStdout(`Created plugin ${r.apiName} at ${n}
302
- `),o.writeStdout(`Artifacts: ${d}
269
+ `),o.setExitCode(1);return}let p=r.artifacts&&r.artifacts.length>0?r.artifacts.join(", "):"none";o.writeStdout(`Created plugin ${r.apiName} at ${n}
270
+ `),o.writeStdout(`Artifacts: ${p}
303
271
  `),o.writeStdout(`Thumbnail: src/thumbnail.png (generated placeholder; replace it before publishing)
304
272
  `),r.developerBusinessId.trim()===""&&o.writeStderr(`Warning: no developer_business_id configured, so this plugin cannot be preview-published yet.
305
- `)}function cn(e){e.command("create").description("Scaffold a new Kizen plugin project").option("-n, --name <name>","plugin display name (implies a non-interactive run)").option("-a, --api-name <name>","plugin api_name (inferred from --name when omitted)").option("-d, --description <text>","plugin description").option("-l, --external-link <url>","external link shown on the plugin listing").option("-b, --business-id <id>","developer business id (defaults to saved credentials)").option("-e, --environment <env>",`environment the business id belongs to: ${Y.join(", ")} (defaults to saved credentials)`).option("--artifacts <list>",`comma-separated artifact types, or "all" / "none" (default: all). Types: ${X.join(", ")}`).action(async t=>{let n=process.cwd(),o=await Z(),r=o?.businessId??"",i=o?.environment??"go",d=Object.values(t).some(m=>m!==void 0);if(!process.stdin.isTTY||!process.stdout.isTTY||d){await ln(t,{businessId:r,environment:i},n,{precheckTargetDir:dt,createPlugin:pt,writeStdout:m=>{process.stdout.write(m)},writeStderr:m=>{process.stderr.write(m)},setExitCode:m=>{process.exitCode=m}});return}let{waitUntilExit:g}=ys(hs(rn,{parentDir:n,defaultBusinessId:r,defaultEnvironment:i}),{exitOnCtrlC:!1});await g()})}import{createElement as Un}from"react";import{render as Vn}from"ink";import{useCallback as Fe,useEffect as St,useRef as pe,useState as Q}from"react";import{Box as K,Text as B,useInput as ma}from"ink";import{PluginValidationError as ga}from"@kizenapps/packager";import{watch as ha}from"fs";import{createServer as ya}from"http";import{join as Mn}from"path";import{WebSocketServer as ba}from"ws";import{createReadStream as _n,realpathSync as js}from"fs";import{access as $s,readdir as Ls,readFile as Ms,realpath as zs,stat as En}from"fs/promises";import{dirname as Hs,extname as kn,join as Ke,resolve as Us,sep as nr}from"path";import{fileURLToPath as Vs}from"url";var bs=new Set(["set-cookie","strict-transport-security","content-security-policy","content-security-policy-report-only","x-frame-options","content-encoding","content-length"]);function yt(e){let t={};for(let[n,o]of Object.entries(e)){let r=n.toLowerCase();bs.has(r)||r.startsWith("access-control-")||(t[n]=o)}return t}var Kt=10*1024*1024,xs=6e4,vs=200,Ue=class extends Error{bytesRead;limit;constructor(t,n){super(`Upstream response exceeded ${String(n)} bytes (read ${String(t)}).`),this.name="ProxyResponseTooLargeError",this.bytesRead=t,this.limit=n}};async function Gt(e,t){let n=e.body;if(n===null)return Buffer.alloc(0);let o=[],r=0;for await(let i of n){if(r+=i.length,r>t)throw new Ue(r,t);o.push(i)}return Buffer.concat(o)}async function dn(e){let t=yt(Object.fromEntries(e.headers)),n=await Gt(e,Kt);return{status:e.status,headers:t,body:n}}function pn(e={}){let{onChange:t,enabled:n=!0}=e;if(!n)return{async get(d,f){return{response:await dn(await f()),fromCache:!1}},clear(){}};let o=new Map,r=()=>{t?.(o.size)},i=d=>{o.delete(d)&&r()};return{get(d,f){let g=o.get(d);if(g!==void 0){if(Date.now()-g.insertedAt<xs)return g.promise.then(b=>({response:b,fromCache:!0}));i(d)}if(o.size>=vs){let b=o.keys().next().value;b!==void 0&&i(b)}let m=f().then(dn).catch(b=>{throw i(d),b});return o.set(d,{insertedAt:Date.now(),promise:m}),r(),m.then(b=>((b.status<200||b.status>=300)&&i(d),{response:b,fromCache:!1}))},clear(){o.clear(),r()}}}var Yt={".html":"text/html; charset=utf-8",".js":"application/javascript; charset=utf-8",".mjs":"application/javascript; charset=utf-8",".css":"text/css; charset=utf-8",".png":"image/png",".jpg":"image/jpeg",".svg":"image/svg+xml",".ico":"image/x-icon",".json":"application/json; charset=utf-8",".woff":"font/woff",".woff2":"font/woff2",".ttf":"font/ttf",".map":"application/json"};import{mkdir as ws,readFile as Cs,writeFile as Ss}from"fs/promises";import{join as un}from"path";async function xe(e){try{let t=await Cs(un(e,"config.json"),"utf-8");return JSON.parse(t)}catch{return{}}}async function ve(e,t){await ws(e,{recursive:!0}),await Ss(un(e,"config.json"),JSON.stringify(t,null,2),"utf-8")}var Xt={prod:"https://plugin-wizard.kizen.com",dev:"https://plugin-wizard.kizen.dev",localDev:"http://localhost:9823"};function Ve(e){let t=process.env.PLUGIN_WIZARD_URL;return t!==void 0&&t!==""?t:e==="prod"?process.env.PLUGIN_WIZARD_URL_PROD||Xt.prod:process.env.PLUGIN_WIZARD_URL_DEV!==void 0&&process.env.PLUGIN_WIZARD_URL_DEV!==""?process.env.PLUGIN_WIZARD_URL_DEV:process.env.APPBUILDER_LOCAL_DEV!==void 0&&process.env.APPBUILDER_LOCAL_DEV!==""?Xt.localDev:Xt.dev}import{spawn as tr}from"child_process";import{writeFile as yn,rm as er,mkdtemp as ks,access as Ps}from"fs/promises";import{join as Je}from"path";import{tmpdir as Is}from"os";var fn=`awslambdaric
273
+ `)}function dn(e){e.command("create").description("Scaffold a new Kizen plugin project").option("-n, --name <name>","plugin display name (implies a non-interactive run)").option("-a, --api-name <name>","plugin api_name (inferred from --name when omitted)").option("-d, --description <text>","plugin description").option("-l, --external-link <url>","external link shown on the plugin listing").option("-b, --business-id <id>","developer business id (defaults to saved credentials)").option("-e, --environment <env>",`environment the business id belongs to: ${Y.join(", ")} (defaults to saved credentials)`).option("--artifacts <list>",`comma-separated artifact types, or "all" / "none" (default: all). Types: ${X.join(", ")}`).action(async t=>{let n=process.cwd(),o=await Z(),r=o?.businessId??"",i=o?.environment??"go",p=Object.values(t).some(m=>m!==void 0);if(!process.stdin.isTTY||!process.stdout.isTTY||p){await cn(t,{businessId:r,environment:i},n,{precheckTargetDir:ye,createPlugin:ut,writeStdout:m=>{process.stdout.write(m)},writeStderr:m=>{process.stderr.write(m)},setExitCode:m=>{process.exitCode=m}});return}let{waitUntilExit:g}=Cs(ws(nn,{parentDir:n,defaultBusinessId:r,defaultEnvironment:i}),{exitOnCtrlC:!1});await g()})}import{createElement as Vn}from"react";import{render as qn}from"ink";import{useCallback as $e,useEffect as Tt,useRef as pe,useState as Q}from"react";import{Box as G,Text as A,useInput as Sa}from"ink";import{PluginValidationError as Ta}from"@kizenapps/packager";import{watch as Ea}from"fs";import{createServer as _a}from"http";import{join as Mn}from"path";import{WebSocketServer as ka}from"ws";import{createReadStream as _n,realpathSync as Vs}from"fs";import{access as qs,readdir as Js,readFile as Ws,realpath as Gs,stat as kn}from"fs/promises";import{dirname as Ks,extname as Pn,join as Ke,resolve as Ys,sep as or}from"path";import{fileURLToPath as Xs}from"url";var Ss=new Set(["set-cookie","strict-transport-security","content-security-policy","content-security-policy-report-only","x-frame-options","content-encoding","content-length"]);function bt(e){let t={};for(let[n,o]of Object.entries(e)){let r=n.toLowerCase();Ss.has(r)||r.startsWith("access-control-")||(t[n]=o)}return t}var Kt=10*1024*1024,Ts=6e4,Es=200,Ve=class extends Error{bytesRead;limit;constructor(t,n){super(`Upstream response exceeded ${String(n)} bytes (read ${String(t)}).`),this.name="ProxyResponseTooLargeError",this.bytesRead=t,this.limit=n}};async function Yt(e,t){let n=e.body;if(n===null)return Buffer.alloc(0);let o=[],r=0;for await(let i of n){if(r+=i.length,r>t)throw new Ve(r,t);o.push(i)}return Buffer.concat(o)}async function pn(e){let t=bt(Object.fromEntries(e.headers)),n=await Yt(e,Kt);return{status:e.status,headers:t,body:n}}function un(e={}){let{onChange:t,enabled:n=!0}=e;if(!n)return{async get(p,f){return{response:await pn(await f()),fromCache:!1}},clear(){}};let o=new Map,r=()=>{t?.(o.size)},i=p=>{o.delete(p)&&r()};return{get(p,f){let g=o.get(p);if(g!==void 0){if(Date.now()-g.insertedAt<Ts)return g.promise.then(y=>({response:y,fromCache:!0}));i(p)}if(o.size>=Es){let y=o.keys().next().value;y!==void 0&&i(y)}let m=f().then(pn).catch(y=>{throw i(p),y});return o.set(p,{insertedAt:Date.now(),promise:m}),r(),m.then(y=>((y.status<200||y.status>=300)&&i(p),{response:y,fromCache:!1}))},clear(){o.clear(),r()}}}var Xt={".html":"text/html; charset=utf-8",".js":"application/javascript; charset=utf-8",".mjs":"application/javascript; charset=utf-8",".css":"text/css; charset=utf-8",".png":"image/png",".jpg":"image/jpeg",".svg":"image/svg+xml",".ico":"image/x-icon",".json":"application/json; charset=utf-8",".woff":"font/woff",".woff2":"font/woff2",".ttf":"font/ttf",".map":"application/json"};import{mkdir as _s,readFile as ks,writeFile as Ps}from"fs/promises";import{join as fn}from"path";async function we(e){try{let t=await ks(fn(e,"config.json"),"utf-8");return JSON.parse(t)}catch{return{}}}async function Ce(e,t){await _s(e,{recursive:!0}),await Ps(fn(e,"config.json"),JSON.stringify(t,null,2),"utf-8")}var Zt={prod:"https://plugin-wizard.kizen.com",dev:"https://plugin-wizard.kizen.dev",localDev:"http://localhost:9823"};function qe(e){let t=process.env.PLUGIN_WIZARD_URL;return t!==void 0&&t!==""?t:e==="prod"?process.env.PLUGIN_WIZARD_URL_PROD||Zt.prod:process.env.PLUGIN_WIZARD_URL_DEV!==void 0&&process.env.PLUGIN_WIZARD_URL_DEV!==""?process.env.PLUGIN_WIZARD_URL_DEV:process.env.APPBUILDER_LOCAL_DEV!==void 0&&process.env.APPBUILDER_LOCAL_DEV!==""?Zt.localDev:Zt.dev}import{spawn as rr}from"child_process";import{writeFile as bn,rm as tr,mkdtemp as Bs,access as As}from"fs/promises";import{join as We}from"path";import{tmpdir as Ds}from"os";var mn=`awslambdaric
306
274
  bcrypt
307
275
  boto3
308
276
  fpdf2
@@ -320,8 +288,8 @@ pytz
320
288
  requests
321
289
  sqlalchemy>=2.0,<2.1
322
290
  tzdata
323
- `;function mn(e){return e.split(`
324
- `).map(t=>t.trim().replace(/\s+#.*$/,"")).filter(t=>t.length>0&&!t.startsWith("#"))}function gn(e){let t=/^python-(\d+)[.-](\d+)$/.exec(e),n=t?.[1],o=t?.[2];return n!==void 0&&o!==void 0?`python${n}.${o}`:"python3"}function _s(e){return e==null||e.trim()===""?null:e}function Es(e){return e==null?null:typeof e=="string"?_s(e):typeof e=="number"||typeof e=="boolean"||typeof e=="bigint"?String(e):typeof e=="function"||typeof e=="symbol"?null:JSON.stringify(e)}function hn(e){return e?Object.fromEntries(Object.entries(e).map(([t,n])=>[t,Es(n)])):{}}var Rs=`
291
+ `;import{AUTOMATION_SCRIPT_RUNTIMES as Fs,isSupportedScriptRuntime as $s,scriptRuntimeToApiName as vn}from"@kizenapps/packager";function gn(e){return e.split(`
292
+ `).map(t=>t.trim().replace(/\s+#.*$/,"")).filter(t=>t.length>0&&!t.startsWith("#"))}function hn(e){let t=/^python-(\d+)[.-](\d+)$/.exec(e),n=t?.[1],o=t?.[2];return n!==void 0&&o!==void 0?`python${n}.${o}`:"python3"}function Ns(e){return e==null||e.trim()===""?null:e}function Rs(e){return e==null?null:typeof e=="string"?Ns(e):typeof e=="number"||typeof e=="boolean"||typeof e=="bigint"?String(e):typeof e=="function"||typeof e=="symbol"?null:JSON.stringify(e)}function yn(e){return e?Object.fromEntries(Object.entries(e).map(([t,n])=>[t,Rs(n)])):{}}var js=`
325
293
  import sys, json, os, traceback
326
294
 
327
295
  # --- Inputs proxy (attribute access) ---
@@ -481,23 +449,23 @@ sys.stdout.write('\\n__KIZEN_RESULT_START__\\n')
481
449
  sys.stdout.write(json.dumps(result, ensure_ascii=False))
482
450
  sys.stdout.write('\\n__KIZEN_RESULT_END__\\n')
483
451
  sys.stdout.flush()
484
- `.trim(),As=3e4,bt=Je(process.cwd(),".kizenapp","venv"),xn=["python-3-12","python-3-13"];function Ns(e){return xn.includes(e)}var vn=mn(fn);if(vn.length===0)throw new Error("python-requirements.txt bundled no packages \u2014 check the build output");var qe=null,We=[3,10];function wn([e,t]){return e>We[0]||e===We[0]&&t>=We[1]}function Zt(e){return`${String(e[0])}.${String(e[1])}`}function Cn(e){return new Promise(t=>{let n=tr(e,["-c","import sys; print('%d.%d' % sys.version_info[:2])"],{stdio:["ignore","pipe","ignore"]}),o="";n.stdout.on("data",r=>{o+=r.toString("utf-8")}),n.on("error",()=>{t(null)}),n.on("close",r=>{let i=/(\d+)\.(\d+)/.exec(o);if(r!==0||!i){t(null);return}t([Number(i[1]),Number(i[2])])})})}async function Bs(e){let t=gn(e),n=t==="python3"?["python3"]:[t,"python3"],o=[];for(let r of n){let i=await Cn(r);if(!i){o.push(`${r}: not found`);continue}if(wn(i))return r;o.push(`${r}: ${Zt(i)} (too old)`)}throw new Error(`No Python >= ${Zt(We)} found for runtime "${e}". The local runner needs Python ${Zt(We)}+ to install the bundled packages (e.g. psycopg 3.3), matching the remote code-runner (3.12 / 3.13). Tried ${o.join(", ")}. Install Python 3.12 or 3.13 and retry.`)}function bn(e,t,n){return new Promise((o,r)=>{let i=tr(e,t,{stdio:["ignore","pipe","pipe"]}),d=(g,m)=>{let b=[],T="";return g.on("data",P=>{T+=P.toString("utf-8");let x=T.indexOf(`
485
- `);for(;x>=0;){let p=T.slice(0,x).replace(/\r$/,"");T=T.slice(x+1),b.push(p),n?.(p,m),x=T.indexOf(`
486
- `)}}),g.on("end",()=>{if(T.length>0){let P=T.replace(/\r$/,"");b.push(P),n?.(P,m)}}),b},f=d(i.stderr,"stderr");d(i.stdout,"stdout"),i.on("error",r),i.on("close",g=>{if(g===0)o();else{let m=f.slice(-10).join(`
487
- `).trim(),b=m.length>0?`: ${m}`:"";r(new Error(`${e} exited with code ${String(g)}${b}`))}})})}var Qt=null;function Ds(e,t){if(qe)return t&&Qt?.add(t),qe;let n=new Set;t&&n.add(t),Qt=n;let o=i=>{for(let d of n)d(i)},r=Je(bt,"bin","python");return qe=(async()=>{try{let i=!1;try{await Ps(r);let d=await Cn(r);i=d!==null&&wn(d)}catch{i=!1}if(!i){await er(bt,{recursive:!0,force:!0}).catch(()=>{});let d=await Bs(e);await bn(d,["-m","venv",bt])}return o({kind:"start"}),await bn(r,["-m","pip","install","--disable-pip-version-check",...vn],(d,f)=>{o({kind:"log",line:d,stream:f})}),o({kind:"complete"}),r}catch(i){let d=i instanceof Error?i.message:String(i);throw o({kind:"error",message:d}),qe=null,await er(bt,{recursive:!0,force:!0}).catch(()=>{}),i}finally{Qt=null}})(),qe}function Fs(e){let t="__KIZEN_RESULT_START__",n="__KIZEN_RESULT_END__",o=e.indexOf(t),r=e.indexOf(n);if(o===-1||r===-1)return{userStdout:e,result:null};let i=e.slice(0,o).trimEnd(),d=e.slice(o+t.length,r).trim();try{let f=JSON.parse(d);return{userStdout:i,result:f}}catch{return{userStdout:e,result:null}}}function Os(e){return{success:!1,outputValues:{},logs:[],stdout:"",stderr:"",error:e,exitCode:1,durationMs:0}}async function Sn(e){let t=e.timeout??As;if(!Ns(e.scriptRuntime))return Os(`Unsupported runtime "${e.scriptRuntime}". Supported runtimes: ${xn.join(", ")}. Update the step's config.json "runtime" field (e.g. "python 3.13").`);let n=await Ds(e.scriptRuntime,e.onInstallProgress),o=Date.now(),r;try{r=await ks(Je(Is(),"kizen-step-"));let i=Je(r,"wrapper.py"),d=Je(r,"script.py");await Promise.all([yn(i,Rs,"utf-8"),yn(d,e.script,"utf-8")]);let f={...process.env,__KIZEN_INPUTS__:JSON.stringify(e.inputs),__KIZEN_SECRETS__:JSON.stringify(e.secrets),__KIZEN_SCRIPT_PATH__:d},{exitCode:g,stdout:m,stderr:b}=await new Promise(y=>{let S=[],H=[],O=!1,w=tr(n,[i],{env:f,cwd:r,stdio:["ignore","pipe","pipe"]}),v=setTimeout(()=>{w.kill("SIGKILL")},t);w.stdout.on("data",a=>{S.push(a)}),w.stderr.on("data",a=>{H.push(a)});let c=a=>{O||(O=!0,clearTimeout(v),y({exitCode:a??1,stdout:Buffer.concat(S).toString("utf-8"),stderr:Buffer.concat(H).toString("utf-8")}))};w.on("close",c),w.on("error",a=>{O||(O=!0,clearTimeout(v),y({exitCode:1,stdout:"",stderr:a.message}))})}),T=Date.now()-o,{userStdout:P,result:x}=Fs(m);if(x){let y={success:x.success,outputValues:x.outputValues,logs:x.logs,stdout:P,stderr:b,exitCode:g,durationMs:T};return x.error!==null&&(y.error=x.error),x.httpRequests&&(y.httpRequests=x.httpRequests),y}let p={success:!1,outputValues:{},logs:[],stdout:P,stderr:b,exitCode:g,durationMs:T};return g!==0&&(p.error=`Process exited with code ${String(g)}`),p}finally{r&&er(r,{recursive:!0,force:!0})}}var Tn=new Set([".ts",".tsx",".js",".jsx",".mjs",".cjs",".json",".md",".mdx",".yml",".yaml",".toml",".css",".scss",".html",".htm",".xml",".svg",".txt",".sh",".py",".env",".gitignore",".prettierrc",".eslintrc"]);import{CRYPTO_ALG as Pn,CRYPTO_VERSION as In,deserializeEnvelope as qs,encrypt as Js,serializeEnvelope as Ws}from"@kizenapps/packager";function rr(e){if(e.kind==="info")return e.message;let t=e.fromCache?" [cache]":"",n=e.upstreamStatus!==void 0?` (upstream ${String(e.upstreamStatus)})`:"";return`${e.method} ${e.url} \u2192 ${String(e.status)}${n}${t}`}var Ks=2*1024*1024,Gs=new Set([".DS_Store",".gitignore"]);function Ys(e){if(e===void 0||e==="")return!1;let t=e.startsWith("[")?e.slice(0,e.indexOf("]")+1):e.split(":")[0]??"";return t==="localhost"||t==="127.0.0.1"||t==="[::1]"}var Bn=["kizen.com","kizen.dev"];function Xs(e){let t;try{t=new URL(e)}catch{return!1}let n=t.hostname.toLowerCase();return n==="localhost"||n==="127.0.0.1"||n==="[::1]"?!0:t.protocol!=="https:"?!1:Bn.some(o=>n===o||n.endsWith("."+o))}function Zs(e){let t;try{t=new URL(e)}catch{return!1}if(t.protocol!=="https:")return!1;let n=t.hostname.toLowerCase();return Bn.some(o=>n===o||n.endsWith("."+o))}function Qs(e){if(e===void 0||e==="")return!1;try{let{hostname:t}=new URL(e);return t==="localhost"||t==="127.0.0.1"||t==="::1"}catch{return!1}}async function Rn(e,t){if(t.includes("\0"))return null;let n=t.replace(/^\/+/,""),o=Us(e,n);if(o!==e&&!o.startsWith(e+nr))return null;try{let r=await zs(o);return r!==e&&!r.startsWith(e+nr)?null:r}catch{return null}}function An(e,t){let n=t===e?"":t.slice(e.length+1);return n===""?!1:n.split(nr).some(r=>tt.has(r))}function Dn(){let e=Vs(import.meta.url);return Ke(Hs(e),"viewer")}function Nn(e,t,n){if(e.includes("/external-integrations/proxy")&&t["content-type"]?.includes("application/json"))try{let o=JSON.parse(n.toString("utf8"));return typeof o.status_code=="number"?o.status_code:void 0}catch{return}}async function or(e){try{return await $s(e),!0}catch{return!1}}function Fn(e,t,n,o,r,i,d,f,g,m,b){let T=pn({onChange:f,enabled:b}),P=js(m);return(x,p)=>{(async()=>{let y=x.url??"/";try{if(!Ys(x.headers.host)){p.writeHead(403,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify({error:"Forbidden"}));return}if((x.method==="POST"||x.method==="PATCH"||x.method==="DELETE")&&!Qs(x.headers.origin)){p.writeHead(403,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify({error:"Forbidden"}));return}if(t(`Received request: ${y}`),y==="/api/credentials"){p.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify({credentials:o.current??null,activeProfile:r.current??null}));return}if(y==="/api/credential-profiles"&&x.method==="GET"){let a=await Ie();p.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify({profiles:a,active:r.current}));return}if(y==="/api/credentials/switch"&&x.method==="POST"){let a=[];for await(let h of x)a.push(h);let l=JSON.parse(Buffer.concat(a).toString("utf-8")||"{}").profile,u=l===void 0||l===""?await Z():await de(l);if(u!==null){o.current=u,r.current=l??void 0;let h=r.current,k=await xe(i);await ve(i,{...k,credentialMode:"global",...h!==void 0&&{activeCredentialProfile:h}}),d({type:"credentials-updated",credentials:u,activeProfile:r.current??null})}p.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify({ok:u!==null}));return}if(y==="/api/bundle"){let a=Ke(process.cwd(),".kizenapp","bundle.json");try{let s=await Ms(a,"utf-8");p.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),p.end(s)}catch{p.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),p.end("{}")}return}if(y==="/api/last-path"&&x.method==="POST"){let a=[];for await(let l of x)a.push(l);let s=JSON.parse(Buffer.concat(a).toString("utf-8")||"{}");if(typeof s.path=="string"){g.current=s.path;let l=await xe(i);await ve(i,{...l,lastPath:s.path})}p.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),p.end('{"ok":true}');return}if(y==="/api/encryption-target"&&x.method==="GET"){let s=(await xe(i)).encryptionTarget==="dev"?"dev":"prod";p.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify({target:s}));return}if(y==="/api/encryption-target"&&x.method==="POST"){let a=[];for await(let h of x)a.push(h);let s=JSON.parse(Buffer.concat(a).toString("utf-8")||"{}"),l=s!==null&&typeof s=="object"?s:{};if(l.target!=="dev"&&l.target!=="prod"){p.writeHead(400,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify({error:"target must be one of: 'dev', 'prod'"}));return}let u=await xe(i);await ve(i,{...u,encryptionTarget:l.target}),p.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),p.end('{"ok":true}');return}if(y==="/api/execute-step"&&x.method==="POST"){let a=[];for await(let h of x)a.push(h);let s=JSON.parse(Buffer.concat(a).toString("utf-8")||"{}");if(typeof s.script!="string"){p.writeHead(400,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify({error:"Missing required field: script"}));return}let l={script:s.script,scriptRuntime:s.scriptRuntime??"python-3-13",inputs:hn(s.inputs),secrets:s.secrets??{},onInstallProgress:h=>{h.kind==="start"?d({type:"venv-install-start"}):h.kind==="log"?d({type:"venv-install-log",line:h.line,stream:h.stream}):h.kind==="complete"?d({type:"venv-install-complete"}):d({type:"venv-install-error",message:h.message})}};typeof s.timeout=="number"&&s.timeout>0&&(l.timeout=Math.min(s.timeout,300*1e3));let u=await Sn(l);p.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify(u));return}if(y==="/api/proxy-cache/clear"){T.clear(),n({kind:"info",message:"Proxy cache cleared"}),p.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),p.end('{"ok":true}');return}if(y==="/api/local/encrypt"&&x.method==="POST"){let a=[];for await(let l of x)a.push(l);let s=JSON.parse(Buffer.concat(a).toString("utf-8")||"{}");if(typeof s.publicKeyPem!="string"||typeof s.value!="string"){p.writeHead(400,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify({error:"Missing required fields: publicKeyPem, value"}));return}try{let l=Js(s.value,s.publicKeyPem),u=Ws(l);p.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify(u))}catch(l){p.writeHead(400,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify({error:l.message}))}return}if(y==="/api/local/validate"&&x.method==="POST"){let a=[];for await(let _ of x)a.push(_);let s=JSON.parse(Buffer.concat(a).toString("utf-8")||"{}");if(typeof s.value!="string"){p.writeHead(400,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify({error:"Missing required field: value"}));return}let l,u;try{l=qs(s.value)}catch(_){u=_.message}if(u!==void 0||l===void 0){p.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify({valid:!1,checks:[],error:u}));return}let h=_=>Buffer.from(_,"base64").length,k=[{label:"Version",expected:String(In),actual:String(l.v),pass:l.v===In},{label:"Algorithm",expected:Pn,actual:l.alg,pass:l.alg===Pn},{label:"Wrapped key",expected:"384 bytes (RSA-3072)",actual:`${String(h(l.k))} bytes`,pass:h(l.k)===384},{label:"IV",expected:"12 bytes",actual:`${String(h(l.iv))} bytes`,pass:h(l.iv)===12},{label:"Auth tag",expected:"16 bytes",actual:`${String(h(l.tag))} bytes`,pass:h(l.tag)===16},{label:"Ciphertext",expected:"\u2265 1 byte",actual:`${String(h(l.ct))} bytes`,pass:h(l.ct)>=1}];p.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify({valid:k.every(_=>_.pass),checks:k}));return}if(y.startsWith("/api/wizard")){let a=x.headers["x-encryption-target"],l=(Array.isArray(a)?a[0]:a)==="dev"?"dev":"prod",u=Ve(l);if(!Xs(u)){p.writeHead(500,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify({error:`Encryption API host is not allowed: ${u}`}));return}let h=y.slice(11)||"/",k=`${u}${h}`,_=x.method??"GET",A=[];for await(let Se of x)A.push(Se);let{host:M,"x-encryption-target":W,...te}=x.headers,oe=A.length>0?Buffer.concat(A):void 0,ie=oe&&oe.length>0?oe:void 0,re;try{re=await fetch(k,{method:_,headers:te,...ie!==void 0&&{body:ie}})}catch(Se){let It=Se.code==="ECONNREFUSED"?`plugin-wizard is not running at ${u}`:`Failed to reach plugin-wizard: ${Se.message}`;p.writeHead(503,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify({error:It}));return}let ee=yt(Object.fromEntries(re.headers)),Oe=await re.arrayBuffer();p.writeHead(re.status,ee),p.end(Buffer.from(Oe));return}if(y.startsWith("/api/proxy")){let a=x.headers["x-proxy-target"];if(typeof a!="string"){p.writeHead(400),p.end("Missing x-proxy-target header");return}if(!Zs(a)){p.writeHead(400),p.end("Invalid proxy target");return}let s=y.slice(10)||"/",l=`${a}${s}`,u=x.method??"GET",h=[];for await(let re of x)h.push(re);let{host:k,"x-proxy-target":_,...A}=x.headers;if(u==="GET"){let re=`GET::${l}`,{response:ee,fromCache:Oe}=await T.get(re,()=>fetch(l,{method:"GET",headers:A}));n({kind:"request",method:"GET",status:ee.status,upstreamStatus:Nn(s,ee.headers,ee.body),fromCache:Oe,url:s}),p.writeHead(ee.status,ee.headers),p.end(ee.body);return}let M=h.length>0?Buffer.concat(h):void 0,W=M&&M.length>0?M:void 0,te=await fetch(l,{method:u,headers:A,...W!==void 0&&{body:W}}),oe=yt(Object.fromEntries(te.headers)),ie=await Gt(te,Kt);n({kind:"request",method:u,status:te.status,upstreamStatus:Nn(s,oe,ie),fromCache:!1,url:s}),p.writeHead(te.status,oe),p.end(ie);return}if(y.startsWith("/api/source/tree")&&x.method==="GET"){let s=new URL(y,"http://localhost").searchParams.get("path")??"",l=await Rn(P,s);if(l===null){p.writeHead(403,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify({error:"Invalid path"}));return}if(An(P,l)){p.writeHead(403,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify({error:"Path is excluded"}));return}try{let u=await Ls(l,{withFileTypes:!0}),h=await Promise.all(u.filter(_=>_.isDirectory()?!tt.has(_.name):_.isFile()?!Gs.has(_.name):!1).map(async _=>{let A=_.isDirectory()?"dir":"file",M={name:_.name,kind:A};if(A==="file")try{let W=await En(Ke(l,_.name));M.size=W.size}catch{}return M}));h.sort((_,A)=>_.kind!==A.kind?_.kind==="dir"?-1:1:_.name.localeCompare(A.name));let k=l===P?"":l.slice(P.length+1);p.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify({path:k,entries:h}))}catch(u){let h=u instanceof Error?u.message:String(u);t(`source/tree failed (${s}): ${h}`),p.writeHead(404,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify({error:"Not found"}))}return}if(y.startsWith("/api/source/file")&&x.method==="GET"){let s=new URL(y,"http://localhost").searchParams.get("path")??"";if(s===""){p.writeHead(400,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify({error:"Missing path"}));return}let l=await Rn(P,s);if(l===null){p.writeHead(403,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify({error:"Invalid path"}));return}if(An(P,l)){p.writeHead(403,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify({error:"Path is excluded"}));return}try{let u=await En(l);if(!u.isFile()){p.writeHead(400,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify({error:"Not a file"}));return}if(u.size>Ks){p.writeHead(413,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify({error:"File too large",size:u.size}));return}let h=kn(l).toLowerCase(),k=Yt[h],_=Tn.has(h),A=k??(_?"text/plain; charset=utf-8":"application/octet-stream");p.writeHead(200,{"Content-Type":A,"Content-Length":String(u.size)}),_n(l).pipe(p)}catch(u){let h=u instanceof Error?u.message:String(u);t(`source/file failed (${s}): ${h}`),p.writeHead(404,{"Content-Type":"application/json; charset=utf-8"}),p.end(JSON.stringify({error:"Not found"}))}return}let O=Ke(e,y==="/"?"/index.html":y),w=await or(O)?O:Ke(e,"index.html"),v=kn(w),c=Yt[v]??"application/octet-stream";p.writeHead(200,{"Content-Type":c}),_n(w).pipe(p)}catch(S){if(y.startsWith("/api/proxy")){let H=y.slice(10)||"/",O=x.method??"GET";S instanceof Ue?n({kind:"info",message:`${O} ${H} \u2192 502 (response exceeded ${String(S.limit)} bytes)`}):n({kind:"request",method:O,status:502,fromCache:!1,url:H})}else n({kind:"info",message:`Error handling ${y}: ${S instanceof Error?S.message:String(S)}`});p.headersSent||(p.writeHead(502),p.end("Bad Gateway"))}})()}}import{launch as ea}from"chrome-launcher";import{createRequire as ta}from"module";import{mkdirSync as ra}from"fs";import{readFile as na}from"fs/promises";import{dirname as oa,join as ia}from"path";import{fileURLToPath as sa}from"url";var On=ta(import.meta.url)("chrome-remote-interface"),aa=new Set(["content-security-policy","content-security-policy-report-only","x-frame-options"]),$n=["kizen.dev","kizen.com"];function jn(e){try{let{hostname:t}=new URL(e);return $n.some(n=>t===n||t.endsWith("."+n))}catch{return!1}}async function la(e){try{let t=ia(oa(sa(import.meta.url)),"viewer","icon.png"),n=await na(t);await e.Browser.setDockTile({image:n.toString("base64")})}catch{}}async function Ln(e){ra(e.userDataDir,{recursive:!0});let t=`http://localhost:${String(e.port)}`,n=await ea({startingUrl:t,chromeFlags:[`--app=${t}`,"--no-first-run","--no-default-browser-check","--disable-extensions","--disable-features=DeviceBoundSessions"],userDataDir:e.userDataDir,handleSIGINT:!1,logLevel:"silent"}),o=n.port,r=null,i=null,d=null,f=null,g=0,m=!1,b=w=>{e.debugLog?.(w)},T=w=>{e.verbose&&e.debugLog?.(w)},P=()=>{i!==null&&(clearInterval(i),i=null)},x=w=>w==="chrome://new-tab-page/"||w==="chrome://newtab/",p=async w=>{P(),d=null,await la(w),await w.Fetch.enable({patterns:$n.flatMap(c=>[{urlPattern:`*://${c}/*`,requestStage:"Response"},{urlPattern:`*://*.${c}/*`,requestStage:"Response"}])}),w.on("Fetch.requestPaused",c=>{(async()=>{let a=c,{requestId:s,request:l,responseHeaders:u,responseStatusCode:h}=a,k=l.url;T(`Fetch ${String(h??"?")} ${k}`);let _=[],A=!1;for(let M of u??[])if(!aa.has(M.name.toLowerCase()))if(M.name.toLowerCase()==="set-cookie"&&jn(k)){let W=M.value.split(`
452
+ `.trim(),Ls=3e4,xt=We(process.cwd(),".kizenapp","venv"),Os=Fs.map(vn),wn=gn(mn);if(wn.length===0)throw new Error("python-requirements.txt bundled no packages \u2014 check the build output");var Je=null,Ge=[3,10];function Cn([e,t]){return e>Ge[0]||e===Ge[0]&&t>=Ge[1]}function Qt(e){return`${String(e[0])}.${String(e[1])}`}function Sn(e){return new Promise(t=>{let n=rr(e,["-c","import sys; print('%d.%d' % sys.version_info[:2])"],{stdio:["ignore","pipe","ignore"]}),o="";n.stdout.on("data",r=>{o+=r.toString("utf-8")}),n.on("error",()=>{t(null)}),n.on("close",r=>{let i=/(\d+)\.(\d+)/.exec(o);if(r!==0||!i){t(null);return}t([Number(i[1]),Number(i[2])])})})}async function zs(e){let t=hn(e),n=t==="python3"?["python3"]:[t,"python3"],o=[];for(let r of n){let i=await Sn(r);if(!i){o.push(`${r}: not found`);continue}if(Cn(i))return r;o.push(`${r}: ${Qt(i)} (too old)`)}throw new Error(`No Python >= ${Qt(Ge)} found for runtime "${e}". The local runner needs Python ${Qt(Ge)}+ to install the bundled packages (e.g. psycopg 3.3), matching the remote code-runner (3.12 / 3.13). Tried ${o.join(", ")}. Install Python 3.12 or 3.13 and retry.`)}function xn(e,t,n){return new Promise((o,r)=>{let i=rr(e,t,{stdio:["ignore","pipe","pipe"]}),p=(g,m)=>{let y=[],T="";return g.on("data",P=>{T+=P.toString("utf-8");let x=T.indexOf(`
453
+ `);for(;x>=0;){let c=T.slice(0,x).replace(/\r$/,"");T=T.slice(x+1),y.push(c),n?.(c,m),x=T.indexOf(`
454
+ `)}}),g.on("end",()=>{if(T.length>0){let P=T.replace(/\r$/,"");y.push(P),n?.(P,m)}}),y},f=p(i.stderr,"stderr");p(i.stdout,"stdout"),i.on("error",r),i.on("close",g=>{if(g===0)o();else{let m=f.slice(-10).join(`
455
+ `).trim(),y=m.length>0?`: ${m}`:"";r(new Error(`${e} exited with code ${String(g)}${y}`))}})})}var er=null;function Ms(e,t){if(Je)return t&&er?.add(t),Je;let n=new Set;t&&n.add(t),er=n;let o=i=>{for(let p of n)p(i)},r=We(xt,"bin","python");return Je=(async()=>{try{let i=!1;try{await As(r);let p=await Sn(r);i=p!==null&&Cn(p)}catch{i=!1}if(!i){await tr(xt,{recursive:!0,force:!0}).catch(()=>{});let p=await zs(e);await xn(p,["-m","venv",xt])}return o({kind:"start"}),await xn(r,["-m","pip","install","--disable-pip-version-check",...wn],(p,f)=>{o({kind:"log",line:p,stream:f})}),o({kind:"complete"}),r}catch(i){let p=i instanceof Error?i.message:String(i);throw o({kind:"error",message:p}),Je=null,await tr(xt,{recursive:!0,force:!0}).catch(()=>{}),i}finally{er=null}})(),Je}function Hs(e){let t="__KIZEN_RESULT_START__",n="__KIZEN_RESULT_END__",o=e.indexOf(t),r=e.indexOf(n);if(o===-1||r===-1)return{userStdout:e,result:null};let i=e.slice(0,o).trimEnd(),p=e.slice(o+t.length,r).trim();try{let f=JSON.parse(p);return{userStdout:i,result:f}}catch{return{userStdout:e,result:null}}}function Us(e){return{success:!1,outputValues:{},logs:[],stdout:"",stderr:"",error:e,exitCode:1,durationMs:0}}async function Tn(e){let t=e.timeout??Ls;if(!$s(e.scriptRuntime))return Us(`Unsupported runtime "${e.scriptRuntime}". Supported runtimes: ${Os.join(", ")}. Update the step's config.json "runtime" field (e.g. "python 3.13").`);let o=await Ms(vn(e.scriptRuntime),e.onInstallProgress),r=Date.now(),i;try{i=await Bs(We(Ds(),"kizen-step-"));let p=We(i,"wrapper.py"),f=We(i,"script.py");await Promise.all([bn(p,js,"utf-8"),bn(f,e.script,"utf-8")]);let g={...process.env,__KIZEN_INPUTS__:JSON.stringify(e.inputs),__KIZEN_SECRETS__:JSON.stringify(e.secrets),__KIZEN_SCRIPT_PATH__:f},{exitCode:m,stdout:y,stderr:T}=await new Promise(w=>{let H=[],j=[],C=!1,v=rr(o,[p],{env:g,cwd:i,stdio:["ignore","pipe","pipe"]}),d=setTimeout(()=>{v.kill("SIGKILL")},t);v.stdout.on("data",s=>{H.push(s)}),v.stderr.on("data",s=>{j.push(s)});let l=s=>{C||(C=!0,clearTimeout(d),w({exitCode:s??1,stdout:Buffer.concat(H).toString("utf-8"),stderr:Buffer.concat(j).toString("utf-8")}))};v.on("close",l),v.on("error",s=>{C||(C=!0,clearTimeout(d),w({exitCode:1,stdout:"",stderr:s.message}))})}),P=Date.now()-r,{userStdout:x,result:c}=Hs(y);if(c){let w={success:c.success,outputValues:c.outputValues,logs:c.logs,stdout:x,stderr:T,exitCode:m,durationMs:P};return c.error!==null&&(w.error=c.error),c.httpRequests&&(w.httpRequests=c.httpRequests),w}let b={success:!1,outputValues:{},logs:[],stdout:x,stderr:T,exitCode:m,durationMs:P};return m!==0&&(b.error=`Process exited with code ${String(m)}`),b}finally{i&&tr(i,{recursive:!0,force:!0})}}var En=new Set([".ts",".tsx",".js",".jsx",".mjs",".cjs",".json",".md",".mdx",".yml",".yaml",".toml",".css",".scss",".html",".htm",".xml",".svg",".txt",".sh",".py",".env",".gitignore",".prettierrc",".eslintrc"]);import{CRYPTO_ALG as In,CRYPTO_VERSION as Nn,DEFAULT_AUTOMATION_RUNTIME as Zs,deserializeEnvelope as Qs,encrypt as ea,scriptRuntimeToApiName as ta,serializeEnvelope as ra}from"@kizenapps/packager";function nr(e){if(e.kind==="info")return e.message;let t=e.fromCache?" [cache]":"",n=e.upstreamStatus!==void 0?` (upstream ${String(e.upstreamStatus)})`:"";return`${e.method} ${e.url} \u2192 ${String(e.status)}${n}${t}`}var na=2*1024*1024,oa=new Set([".DS_Store",".gitignore"]);function ia(e){if(e===void 0||e==="")return!1;let t=e.startsWith("[")?e.slice(0,e.indexOf("]")+1):e.split(":")[0]??"";return t==="localhost"||t==="127.0.0.1"||t==="[::1]"}var Dn=["kizen.com","kizen.dev"];function sa(e){let t;try{t=new URL(e)}catch{return!1}let n=t.hostname.toLowerCase();return n==="localhost"||n==="127.0.0.1"||n==="[::1]"?!0:t.protocol!=="https:"?!1:Dn.some(o=>n===o||n.endsWith("."+o))}function aa(e){let t;try{t=new URL(e)}catch{return!1}if(t.protocol!=="https:")return!1;let n=t.hostname.toLowerCase();return Dn.some(o=>n===o||n.endsWith("."+o))}function la(e){if(e===void 0||e==="")return!1;try{let{hostname:t}=new URL(e);return t==="localhost"||t==="127.0.0.1"||t==="::1"}catch{return!1}}async function Rn(e,t){if(t.includes("\0"))return null;let n=t.replace(/^\/+/,""),o=Ys(e,n);if(o!==e&&!o.startsWith(e+or))return null;try{let r=await Gs(o);return r!==e&&!r.startsWith(e+or)?null:r}catch{return null}}function Bn(e,t){let n=t===e?"":t.slice(e.length+1);return n===""?!1:n.split(or).some(r=>rt.has(r))}function Fn(){let e=Xs(import.meta.url);return Ke(Ks(e),"viewer")}function An(e,t,n){if(e.includes("/external-integrations/proxy")&&t["content-type"]?.includes("application/json"))try{let o=JSON.parse(n.toString("utf8"));return typeof o.status_code=="number"?o.status_code:void 0}catch{return}}async function ir(e){try{return await qs(e),!0}catch{return!1}}function $n(e,t,n,o,r,i,p,f,g,m,y){let T=un({onChange:f,enabled:y}),P=Vs(m);return(x,c)=>{(async()=>{let b=x.url??"/";try{if(!ia(x.headers.host)){c.writeHead(403,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify({error:"Forbidden"}));return}if((x.method==="POST"||x.method==="PATCH"||x.method==="DELETE")&&!la(x.headers.origin)){c.writeHead(403,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify({error:"Forbidden"}));return}if(t(`Received request: ${b}`),b==="/api/credentials"){c.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify({credentials:o.current??null,activeProfile:r.current??null}));return}if(b==="/api/credential-profiles"&&x.method==="GET"){let l=await Re();c.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify({profiles:l,active:r.current}));return}if(b==="/api/credentials/switch"&&x.method==="POST"){let l=[];for await(let h of x)l.push(h);let a=JSON.parse(Buffer.concat(l).toString("utf-8")||"{}").profile,u=a===void 0||a===""?await Z():await de(a);if(u!==null){o.current=u,r.current=a??void 0;let h=r.current,k=await we(i);await Ce(i,{...k,credentialMode:"global",...h!==void 0&&{activeCredentialProfile:h}}),p({type:"credentials-updated",credentials:u,activeProfile:r.current??null})}c.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify({ok:u!==null}));return}if(b==="/api/bundle"){let l=Ke(process.cwd(),".kizenapp","bundle.json");try{let s=await Ws(l,"utf-8");c.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),c.end(s)}catch{c.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),c.end("{}")}return}if(b==="/api/last-path"&&x.method==="POST"){let l=[];for await(let a of x)l.push(a);let s=JSON.parse(Buffer.concat(l).toString("utf-8")||"{}");if(typeof s.path=="string"){g.current=s.path;let a=await we(i);await Ce(i,{...a,lastPath:s.path})}c.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),c.end('{"ok":true}');return}if(b==="/api/encryption-target"&&x.method==="GET"){let s=(await we(i)).encryptionTarget==="dev"?"dev":"prod";c.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify({target:s}));return}if(b==="/api/encryption-target"&&x.method==="POST"){let l=[];for await(let h of x)l.push(h);let s=JSON.parse(Buffer.concat(l).toString("utf-8")||"{}"),a=s!==null&&typeof s=="object"?s:{};if(a.target!=="dev"&&a.target!=="prod"){c.writeHead(400,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify({error:"target must be one of: 'dev', 'prod'"}));return}let u=await we(i);await Ce(i,{...u,encryptionTarget:a.target}),c.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),c.end('{"ok":true}');return}if(b==="/api/execute-step"&&x.method==="POST"){let l=[];for await(let h of x)l.push(h);let s=JSON.parse(Buffer.concat(l).toString("utf-8")||"{}");if(typeof s.script!="string"){c.writeHead(400,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify({error:"Missing required field: script"}));return}let a={script:s.script,scriptRuntime:s.scriptRuntime??ta(Zs),inputs:yn(s.inputs),secrets:s.secrets??{},onInstallProgress:h=>{h.kind==="start"?p({type:"venv-install-start"}):h.kind==="log"?p({type:"venv-install-log",line:h.line,stream:h.stream}):h.kind==="complete"?p({type:"venv-install-complete"}):p({type:"venv-install-error",message:h.message})}};typeof s.timeout=="number"&&s.timeout>0&&(a.timeout=Math.min(s.timeout,300*1e3));let u=await Tn(a);c.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify(u));return}if(b==="/api/proxy-cache/clear"){T.clear(),n({kind:"info",message:"Proxy cache cleared"}),c.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),c.end('{"ok":true}');return}if(b==="/api/local/encrypt"&&x.method==="POST"){let l=[];for await(let a of x)l.push(a);let s=JSON.parse(Buffer.concat(l).toString("utf-8")||"{}");if(typeof s.publicKeyPem!="string"||typeof s.value!="string"){c.writeHead(400,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify({error:"Missing required fields: publicKeyPem, value"}));return}try{let a=ea(s.value,s.publicKeyPem),u=ra(a);c.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify(u))}catch(a){c.writeHead(400,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify({error:a.message}))}return}if(b==="/api/local/validate"&&x.method==="POST"){let l=[];for await(let E of x)l.push(E);let s=JSON.parse(Buffer.concat(l).toString("utf-8")||"{}");if(typeof s.value!="string"){c.writeHead(400,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify({error:"Missing required field: value"}));return}let a,u;try{a=Qs(s.value)}catch(E){u=E.message}if(u!==void 0||a===void 0){c.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify({valid:!1,checks:[],error:u}));return}let h=E=>Buffer.from(E,"base64").length,k=[{label:"Version",expected:String(Nn),actual:String(a.v),pass:a.v===Nn},{label:"Algorithm",expected:In,actual:a.alg,pass:a.alg===In},{label:"Wrapped key",expected:"384 bytes (RSA-3072)",actual:`${String(h(a.k))} bytes`,pass:h(a.k)===384},{label:"IV",expected:"12 bytes",actual:`${String(h(a.iv))} bytes`,pass:h(a.iv)===12},{label:"Auth tag",expected:"16 bytes",actual:`${String(h(a.tag))} bytes`,pass:h(a.tag)===16},{label:"Ciphertext",expected:"\u2265 1 byte",actual:`${String(h(a.ct))} bytes`,pass:h(a.ct)>=1}];c.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify({valid:k.every(E=>E.pass),checks:k}));return}if(b.startsWith("/api/wizard")){let l=x.headers["x-encryption-target"],a=(Array.isArray(l)?l[0]:l)==="dev"?"dev":"prod",u=qe(a);if(!sa(u)){c.writeHead(500,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify({error:`Encryption API host is not allowed: ${u}`}));return}let h=b.slice(11)||"/",k=`${u}${h}`,E=x.method??"GET",R=[];for await(let Ee of x)R.push(Ee);let{host:z,"x-encryption-target":W,...te}=x.headers,oe=R.length>0?Buffer.concat(R):void 0,ie=oe&&oe.length>0?oe:void 0,re;try{re=await fetch(k,{method:E,headers:te,...ie!==void 0&&{body:ie}})}catch(Ee){let Nt=Ee.code==="ECONNREFUSED"?`plugin-wizard is not running at ${u}`:`Failed to reach plugin-wizard: ${Ee.message}`;c.writeHead(503,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify({error:Nt}));return}let ee=bt(Object.fromEntries(re.headers)),je=await re.arrayBuffer();c.writeHead(re.status,ee),c.end(Buffer.from(je));return}if(b.startsWith("/api/proxy")){let l=x.headers["x-proxy-target"];if(typeof l!="string"){c.writeHead(400),c.end("Missing x-proxy-target header");return}if(!aa(l)){c.writeHead(400),c.end("Invalid proxy target");return}let s=b.slice(10)||"/",a=`${l}${s}`,u=x.method??"GET",h=[];for await(let re of x)h.push(re);let{host:k,"x-proxy-target":E,...R}=x.headers;if(u==="GET"){let re=`GET::${a}`,{response:ee,fromCache:je}=await T.get(re,()=>fetch(a,{method:"GET",headers:R}));n({kind:"request",method:"GET",status:ee.status,upstreamStatus:An(s,ee.headers,ee.body),fromCache:je,url:s}),c.writeHead(ee.status,ee.headers),c.end(ee.body);return}let z=h.length>0?Buffer.concat(h):void 0,W=z&&z.length>0?z:void 0,te=await fetch(a,{method:u,headers:R,...W!==void 0&&{body:W}}),oe=bt(Object.fromEntries(te.headers)),ie=await Yt(te,Kt);n({kind:"request",method:u,status:te.status,upstreamStatus:An(s,oe,ie),fromCache:!1,url:s}),c.writeHead(te.status,oe),c.end(ie);return}if(b.startsWith("/api/source/tree")&&x.method==="GET"){let s=new URL(b,"http://localhost").searchParams.get("path")??"",a=await Rn(P,s);if(a===null){c.writeHead(403,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify({error:"Invalid path"}));return}if(Bn(P,a)){c.writeHead(403,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify({error:"Path is excluded"}));return}try{let u=await Js(a,{withFileTypes:!0}),h=await Promise.all(u.filter(E=>E.isDirectory()?!rt.has(E.name):E.isFile()?!oa.has(E.name):!1).map(async E=>{let R=E.isDirectory()?"dir":"file",z={name:E.name,kind:R};if(R==="file")try{let W=await kn(Ke(a,E.name));z.size=W.size}catch{}return z}));h.sort((E,R)=>E.kind!==R.kind?E.kind==="dir"?-1:1:E.name.localeCompare(R.name));let k=a===P?"":a.slice(P.length+1);c.writeHead(200,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify({path:k,entries:h}))}catch(u){let h=u instanceof Error?u.message:String(u);t(`source/tree failed (${s}): ${h}`),c.writeHead(404,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify({error:"Not found"}))}return}if(b.startsWith("/api/source/file")&&x.method==="GET"){let s=new URL(b,"http://localhost").searchParams.get("path")??"";if(s===""){c.writeHead(400,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify({error:"Missing path"}));return}let a=await Rn(P,s);if(a===null){c.writeHead(403,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify({error:"Invalid path"}));return}if(Bn(P,a)){c.writeHead(403,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify({error:"Path is excluded"}));return}try{let u=await kn(a);if(!u.isFile()){c.writeHead(400,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify({error:"Not a file"}));return}if(u.size>na){c.writeHead(413,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify({error:"File too large",size:u.size}));return}let h=Pn(a).toLowerCase(),k=Xt[h],E=En.has(h),R=k??(E?"text/plain; charset=utf-8":"application/octet-stream");c.writeHead(200,{"Content-Type":R,"Content-Length":String(u.size)}),_n(a).pipe(c)}catch(u){let h=u instanceof Error?u.message:String(u);t(`source/file failed (${s}): ${h}`),c.writeHead(404,{"Content-Type":"application/json; charset=utf-8"}),c.end(JSON.stringify({error:"Not found"}))}return}let j=Ke(e,b==="/"?"/index.html":b),C=await ir(j)?j:Ke(e,"index.html"),v=Pn(C),d=Xt[v]??"application/octet-stream";c.writeHead(200,{"Content-Type":d}),_n(C).pipe(c)}catch(w){if(b.startsWith("/api/proxy")){let H=b.slice(10)||"/",j=x.method??"GET";w instanceof Ve?n({kind:"info",message:`${j} ${H} \u2192 502 (response exceeded ${String(w.limit)} bytes)`}):n({kind:"request",method:j,status:502,fromCache:!1,url:H})}else n({kind:"info",message:`Error handling ${b}: ${w instanceof Error?w.message:String(w)}`});c.headersSent||(c.writeHead(502),c.end("Bad Gateway"))}})()}}import{launch as ca}from"chrome-launcher";import{createRequire as da}from"module";import{mkdirSync as pa}from"fs";import{readFile as ua}from"fs/promises";import{dirname as fa,join as ma}from"path";import{fileURLToPath as ga}from"url";var jn=da(import.meta.url)("chrome-remote-interface"),ha=new Set(["content-security-policy","content-security-policy-report-only","x-frame-options"]),On=["kizen.dev","kizen.com"];function Ln(e){try{let{hostname:t}=new URL(e);return On.some(n=>t===n||t.endsWith("."+n))}catch{return!1}}async function ya(e){try{let t=ma(fa(ga(import.meta.url)),"viewer","icon.png"),n=await ua(t);await e.Browser.setDockTile({image:n.toString("base64")})}catch{}}async function zn(e){pa(e.userDataDir,{recursive:!0});let t=`http://localhost:${String(e.port)}`,n=await ca({startingUrl:t,chromeFlags:[`--app=${t}`,"--no-first-run","--no-default-browser-check","--disable-extensions","--disable-features=DeviceBoundSessions"],userDataDir:e.userDataDir,handleSIGINT:!1,logLevel:"silent"}),o=n.port,r=null,i=null,p=null,f=null,g=0,m=!1,y=C=>{e.debugLog?.(C)},T=C=>{e.verbose&&e.debugLog?.(C)},P=()=>{i!==null&&(clearInterval(i),i=null)},x=C=>C==="chrome://new-tab-page/"||C==="chrome://newtab/",c=async C=>{P(),p=null,await ya(C),await C.Fetch.enable({patterns:On.flatMap(d=>[{urlPattern:`*://${d}/*`,requestStage:"Response"},{urlPattern:`*://*.${d}/*`,requestStage:"Response"}])}),C.on("Fetch.requestPaused",d=>{(async()=>{let l=d,{requestId:s,request:a,responseHeaders:u,responseStatusCode:h}=l,k=a.url;T(`Fetch ${String(h??"?")} ${k}`);let E=[],R=!1;for(let z of u??[])if(!ha.has(z.name.toLowerCase()))if(z.name.toLowerCase()==="set-cookie"&&Ln(k)){let W=z.value.split(`
488
456
  `).map(te=>/SameSite=/i.test(te)?te.replace(/SameSite=\w+/i,"SameSite=None"):te+"; SameSite=None; Secure").join(`
489
- `);_.push({name:M.name,value:W}),A=!0}else _.push(M);A&&T(` rewrote Set-Cookie SameSite on ${k}`);try{let{body:M,base64Encoded:W}=await w.Fetch.getResponseBody({requestId:s});await w.Fetch.fulfillRequest({requestId:s,responseCode:h??200,responseHeaders:_,body:M,...W&&{base64Encoded:!0}})}catch(M){T(` fulfillRequest failed (${M.message}), falling through`);try{await w.Fetch.continueRequest({requestId:s})}catch(W){T(` continueRequest also failed (${W.message})`)}}})()}),i=setInterval(()=>{(async()=>{try{let{cookies:c}=await w.Network.getAllCookies(),a=0;for(let s of c){if(!jn(`https://${s.domain??""}`)||s.sameSite==="None")continue;let l=s.domain??"",u=l.startsWith(".")?l.slice(1):l;await w.Network.setCookie({url:`https://${u}`,name:s.name,value:s.value,domain:l,path:s.path??"/",secure:!0,...s.httpOnly!==void 0&&{httpOnly:s.httpOnly},...s.expirationDate!==void 0&&{expires:s.expirationDate},sameSite:"None"}),a++}a>0&&T(`cookie-patch cycle: updated ${String(a)} cookie(s) to SameSite=None`)}catch(c){T(`cookie-patch cycle failed: ${c.message}`)}})()},2e3),await w.Target.setDiscoverTargets({discover:!0});let v=c=>{if(c.type==="page"){if(x(c.url)){b(`closed stray new-tab-page target ${c.targetId}`),d!==null&&w.Target.activateTarget({targetId:d}).catch(()=>{}),w.Target.closeTarget({targetId:c.targetId}).catch(()=>{});return}d===null&&(d=c.targetId,b(`captured main target ${c.targetId} (${c.url})`))}};w.on("Target.targetCreated",c=>{let{targetInfo:a}=c;T(`target +${a.type} ${a.targetId} ${a.url}`),v(a)}),w.on("Target.targetInfoChanged",c=>{let{targetInfo:a}=c;T(`target ~${a.type} ${a.targetId} ${a.url}`),v(a)}),w.on("disconnect",()=>{m||r!==w||(b("CDP disconnected"),r=null,P(),y())})},y=()=>{if(m||f!==null)return;let w=Math.min(1e3*2**g,1e4),v=g+1;g++,b(`CDP reconnect scheduled in ${String(w)}ms (attempt #${String(v)})`),f=setTimeout(()=>{f=null,(async()=>{let c;try{c=await On({port:o})}catch{b(`CDP reconnect attempt #${String(v)} failed`),y();return}if(m){try{await c.close()}catch{}return}r=c;try{await p(c),b(`CDP reconnected after ${String(v)} attempt(s)`),g=0}catch{r===c&&(r=null);try{await c.close()}catch{}b(`CDP reconnect attempt #${String(v)} failed during setup`),y()}})()},w)},S=30,H=300;for(let w=0;w<S;w++){await new Promise(v=>setTimeout(v,H)),b(`CDP connect attempt ${String(w+1)}/${String(S)}`);try{let v=await On({port:o});r=v,e.path&&v.send("Page.navigate",{url:`${t}${e.path}`});try{await p(v),b("CDP connected")}catch{r===v&&(r=null);try{await v.close()}catch{}b("CDP setup failed after connect")}break}catch{if(w===S-1){let v=`CDP unavailable after ${String(S)} attempts \u2014 viewer running without interception (CSP/cookie rewrites disabled)`;return b(v),e.onWarn?.(v),{kill:()=>{n.kill()}}}}}return r?{kill:()=>{if(b("CDP kill requested \u2014 tearing down"),m=!0,f!==null&&(clearTimeout(f),f=null),P(),r!==null){try{r.close()}catch{}r=null}n.kill()}}:{kill:()=>{n.kill()}}}import{useCallback as ca,useState as da}from"react";function xt(e){let[t,n]=da([]),o=ca(r=>{n(i=>[...i,`${new Date().toLocaleTimeString()}: ${r}`].slice(-e))},[e]);return[t,o]}import{useCallback as vt,useEffect as ir,useState as wt}from"react";import{Box as V,Text as j,useInput as pa}from"ink";import{jsx as R,jsxs as J}from"react/jsx-runtime";var we=["apiKey","userId","businessId"],ua={apiKey:"API Key",userId:"User ID",businessId:"Business ID"},Ge=({text:e})=>R(j,{dimColor:!0,children:e}),Ct=({initialMode:e,showProfileManager:t,onComplete:n,onCancel:o})=>{let[r,i]=wt(e==="global"&&!t?{type:"loading"}:e==="global"&&t?{type:"profile-loading"}:{type:"mode-select",cursor:0}),[d,f]=wt(""),[g,m]=wt(null),[b,T]=wt(void 0),P=vt(c=>{if(c==="local"){n({mode:"local",credentials:null});return}i({type:"profile-loading"})},[n]),x=vt(async c=>{if(c===null){i({type:"profile-loading"});let l=await Ie();i({type:"name-entry",nameBuffer:"",existingProfiles:l});return}T(c.isDefault?void 0:c.name),i({type:"loading"});let a=c.isDefault?await Z():await de(c.name),s=a?Math.max(0,Y.indexOf(a.environment)):0;i({type:"creds-entry",field:0,values:a??{},envCursor:s})},[]),p=vt(async(c,a)=>{let s=Y[a]??"go",l={apiKey:c.apiKey??"",userId:c.userId??"",businessId:c.businessId??"",environment:s};i({type:"saving"});try{await an(b??ye,l),n({mode:"global",credentials:l,...b!==void 0&&{profileName:b}})}catch(u){m(u instanceof Error?u.message:String(u)),i({type:"creds-entry",field:0,values:c,envCursor:a})}},[n,b]);pa((c,a)=>{if(a.ctrl&&c==="c"&&process.exit(0),a.escape){if((r.type==="creds-entry"||r.type==="name-entry")&&e==="global"&&t){i({type:"profile-loading"}),y();return}o?.();return}if(r.type==="mode-select"){if(a.upArrow)i({type:"mode-select",cursor:0});else if(a.downArrow)i({type:"mode-select",cursor:1});else if(a.return){let s=r.cursor===0?"global":"local";P(s)}return}if(r.type==="profile-select"){let{profiles:s,cursor:l}=r,u=s.length,h=s.length+1;if(a.upArrow)i({...r,cursor:(l-1+h)%h});else if(a.downArrow)i({...r,cursor:(l+1)%h});else if(a.return)if(l===u)i({type:"name-entry",nameBuffer:"",existingProfiles:s});else{let k=s[l]??s[0];k&&x(k)}return}if(r.type==="name-entry"){let{nameBuffer:s,existingProfiles:l}=r;if(a.backspace||a.delete)i({type:"name-entry",nameBuffer:s.slice(0,-1),existingProfiles:l});else if(a.return){let u=s.trim();if(!u){i({...r,nameError:"Name cannot be empty"});return}if(u===ye){i({...r,nameError:`"${ye}" is reserved`});return}if(l.some(h=>h.name===u)){i({...r,nameError:`Profile "${u}" already exists`});return}T(u),i({type:"creds-entry",field:0,values:{},envCursor:0}),f("")}else c&&!a.ctrl&&!a.meta&&i({type:"name-entry",nameBuffer:s+c,existingProfiles:l});return}if(r.type==="creds-entry"){let{field:s,values:l,envCursor:u}=r;if(s===we.length){a.leftArrow?i({...r,envCursor:(u-1+Y.length)%Y.length}):a.rightArrow?i({...r,envCursor:(u+1)%Y.length}):a.upArrow?(i({...r,field:s-1}),f(l[we[s-1]]??"")):a.return&&p(l,u);return}let k=we[s];if(!k)return;if(a.backspace||a.delete)f(_=>_.slice(0,-1));else if(a.upArrow&&s>0){let _={...l,[k]:d},A=s-1;i({...r,field:A,values:_}),f(_[we[A]]??"")}else if(a.return||a.tab||a.downArrow){let _={...l,[k]:d},A=s+1;i({...r,field:A,values:_}),A<we.length?f(_[we[A]]??""):f("")}else c&&!a.ctrl&&!a.meta&&f(_=>_+c)}});let y=vt(async()=>{let c=await Ie();i({type:"profile-select",profiles:c,cursor:0})},[]);if(ir(()=>{r.type==="profile-loading"&&y()},[r.type,y]),ir(()=>{e==="global"&&!t&&(async()=>{let c=await Z(),a=c?Math.max(0,Y.indexOf(c.environment)):0;i({type:"creds-entry",field:0,values:c??{},envCursor:a})})()},[]),ir(()=>{r.type==="creds-entry"&&r.field===0&&f(r.values.apiKey??"")},[r.type]),r.type==="loading"||r.type==="saving"||r.type==="profile-loading"){let c=r.type==="saving"?"Saving credentials\u2026":r.type==="profile-loading"?"Loading profiles\u2026":"Loading credentials\u2026";return R(V,{paddingY:1,paddingX:2,children:R(j,{dimColor:!0,children:c})})}if(r.type==="done")return null;if(r.type==="mode-select")return J(V,{flexDirection:"column",paddingY:1,paddingX:2,gap:1,children:[R(q,{}),J(V,{flexDirection:"column",gap:0,children:[R(j,{bold:!0,children:"Credential mode"}),[{label:"Global",desc:"~/.kizenappbuilder/credentials.json",mode:"global"},{label:"Local",desc:"Enter credentials in the browser dev tools",mode:"local"}].map((a,s)=>{let l=r.cursor===s;return J(V,{gap:2,children:[R(j,{...l&&{color:"cyan"},children:l?"\u276F":" "}),R(j,{bold:l,...l&&{color:"cyan"},children:a.label}),R(j,{dimColor:!0,children:a.desc})]},a.mode)})]}),R(Ge,{text:"\u2191\u2193 to move \xB7 Enter to select \xB7 Ctrl+C to quit"})]});if(r.type==="profile-select"){let{profiles:c,cursor:a}=r,s=c.length;return J(V,{flexDirection:"column",paddingY:1,paddingX:2,gap:1,children:[R(q,{}),J(V,{flexDirection:"column",gap:0,children:[R(j,{bold:!0,children:"Credential profiles"}),c.map((l,u)=>{let h=a===u;return J(V,{gap:2,children:[R(j,{...h&&{color:"cyan"},children:h?"\u276F":" "}),R(j,{bold:h,...h&&{color:"cyan"},children:l.isDefault?"Default":l.name}),R(j,{dimColor:!0,children:l.path})]},l.name)}),J(V,{gap:2,children:[R(j,{...a===s&&{color:"cyan"},children:a===s?"\u276F":" "}),R(j,{bold:a===s,...a===s&&{color:"cyan"},children:"+ Add new profile"})]})]}),R(Ge,{text:"\u2191\u2193 to move \xB7 Enter to select \xB7 Esc to cancel"})]})}if(r.type==="name-entry"){let{nameBuffer:c,nameError:a}=r;return J(V,{flexDirection:"column",paddingY:1,paddingX:2,gap:1,children:[R(q,{}),R(V,{flexDirection:"column",gap:0,children:R(j,{bold:!0,children:"New credential profile"})}),a&&J(j,{color:"red",children:["Error: ",a]}),J(V,{gap:2,children:[R(V,{width:12,children:R(j,{bold:!0,color:"cyan",children:"Profile name"})}),R(j,{color:"cyan",children:">"}),R(j,{children:c}),R(j,{color:"cyan",children:"\u2588"})]}),R(Ge,{text:"Type a name \xB7 Enter to confirm \xB7 Esc to go back"})]})}let{field:S,values:H,envCursor:O}=r,w=S===we.length,v=b??ye;return J(V,{flexDirection:"column",paddingY:1,paddingX:2,gap:1,children:[R(q,{}),J(V,{flexDirection:"column",gap:0,children:[R(j,{bold:!0,children:b!==void 0?`Profile: ${b}`:"Global credentials"}),J(j,{dimColor:!0,children:["Saved to:"," ",b!==void 0?`~/.kizenappbuilder/${b}.json`:De]})]}),g&&J(j,{color:"red",children:["Error: ",g]}),J(V,{flexDirection:"column",gap:0,children:[we.map((c,a)=>{let s=S===a,l=s?d:H[c]??"";return J(V,{gap:2,children:[R(V,{width:12,children:R(j,{bold:s,...s&&{color:"cyan"},children:ua[c]})}),R(j,{...s&&{color:"cyan"},children:">"}),R(j,{children:l}),s&&R(j,{color:"cyan",children:"\u2588"})]},c)}),J(V,{gap:2,children:[R(V,{width:12,children:R(j,{bold:w,...w&&{color:"cyan"},children:"Environment"})}),R(j,{...w&&{color:"cyan"},children:">"}),R(V,{gap:1,children:Y.map((c,a)=>{let s=a===O;return w?R(j,{bold:s,...s&&{color:"cyan"},children:s?`[${c}]`:c},c):R(j,{dimColor:!s,bold:s,children:c},c)})})]})]}),w?R(Ge,{text:"\u2190\u2192 to select \xB7 \u2191\u2193 to move \xB7 Enter to save \xB7 Esc to cancel"}):R(Ge,{text:"\u2191\u2193 to move \xB7 Backspace to delete \xB7 Esc to cancel"}),J(j,{dimColor:!0,children:["Profile: ",v]})]})};import{jsx as D,jsxs as U}from"react/jsx-runtime";var xa=[".kizenapp",".git"],zn=({port:e,pluginDir:t,outputDir:n,credentials:o,credentialMode:r,activeCredentialProfile:i,lastPath:d,debug:f=!1,verbose:g=!1,autoViewer:m=!0,cacheEnabled:b=!0})=>{let T=pe(o),P=pe(i),x=pe(d),[p,y]=Q("main"),[S,H]=Q(r),[O,w]=Q("starting"),[v,c]=Q(null),[a,s]=xt(50),[l,u]=xt(50),[h,k]=xt(50),[_,A]=Q([]),[M,W]=Q("pending"),[te,oe]=Q(null),[ie,re]=Q(null),[ee,Oe]=Q(null),[Se,It]=Q(null),[Rt,At]=Q(0),[cr,ko]=Q(0),[Po,Io]=Q(0),[Nt,Ro]=Q(0),Bt=pe(!1),dr=pe(!1),Xe=pe(null),je=pe(null),ue=pe(new Set),Ze=pe([]),ne=Fe(C=>{let L=JSON.stringify(C);if(ue.current.size===0){Ze.current=[...Ze.current,L].slice(-50);return}let fe=!1;for(let se of ue.current)if(se.readyState===1)try{se.send(L)}catch{ue.current.delete(se),fe=!0}fe&&At(ue.current.size)},[]),Qe=s,Dt=Fe(()=>{Xe.current?.kill(),Xe.current=null,Ln({port:e,userDataDir:Mn(n,".chrome"),broadcast:ne,onWarn:C=>{s(`\u26A0 ${C}`)},...x.current!==void 0&&{path:x.current},...f&&{debugLog:k},...g&&{verbose:!0}}).then(C=>{Xe.current=C})},[e,n,ne,f,g,k,s]);St(()=>{let C=()=>{Xe.current?.kill()};return process.on("exit",C),()=>{process.off("exit",C)}},[]),ma((C,L)=>{(C==="q"||L.ctrl&&C==="c")&&process.exit(0),C==="c"&&y("editing"),C==="v"&&Dt()},{isActive:p==="main"}),St(()=>{O!=="running"||dr.current||!m||(dr.current=!0,Dt())},[O,m,Dt]);let Ao=Fe(C=>{T.current=C.credentials,P.current=C.profileName,y("main"),H(C.mode);let L=C.profileName;ve(n,{credentialMode:C.mode,...L!==void 0&&{activeCredentialProfile:L}}),ne({type:"credentials-updated",credentials:C.credentials})},[n,ne]),pr=Fe(C=>{A(L=>[...L,`${new Date().toLocaleTimeString()}: ${rr(C)}`].slice(-50)),C.kind==="request"&&(C.fromCache?Io(L=>L+1):Ro(L=>L+1)),ne({type:"proxy-log",entry:C})},[ne]),Te=Fe(C=>{u(C),ne({type:"log",message:C})},[u,ne]),Ft=Fe(()=>{Bt.current||(Bt.current=!0,W("building"),oe(null),re(null),Te("Build started"),nt(t,n).then(({bundleSize:C})=>{Te(`Build finished \u2014 bundle: ${$e(C)}`),W("done"),Oe(new Date),It(C),Te("Notifying viewers to reload"),ne({type:"rebuild"})}).catch(C=>{C instanceof ga?(re(C.issues),oe(null)):(oe(C instanceof Error?C.message:String(C)),re(null)),W("error")}).finally(()=>{Bt.current=!1}))},[t,n,Te,ne]);if(St(()=>{Ft();let C=ha(t,{recursive:!0},(L,fe)=>{if(!fe)return;let se=fe.replace(/\\/g,"/");xa.some(et=>se.startsWith(et))||(Te(`File change detected: ${fe}`),je.current!==null&&clearTimeout(je.current),je.current=setTimeout(Ft,150))});return C.on("error",L=>{Te(`File watcher error \u2014 rebuilds have stopped: ${L.message}`)}),()=>{C.close(),je.current!==null&&clearTimeout(je.current)}},[t,Ft,Te]),St(()=>{let C=Dn();or(Mn(C,"index.html")).then(L=>{if(!L){c("Viewer not built. Run 'pnpm build:viewer' first."),w("error");return}let fe=Fn(C,Qe,pr,T,P,n,ne,ko,x,t,b),se=ya(fe),et=new ba({server:se});return et.on("connection",_e=>{for(let Bo of Ze.current)_e.readyState===1&&_e.send(Bo);Ze.current=[],Qe("Viewer connected for live reload"),ue.current.add(_e),At(ue.current.size),_e.on("close",()=>{ue.current.delete(_e),At(ue.current.size)})}),se.listen(e,"127.0.0.1",()=>{w("running"),Qe(`Server started on 127.0.0.1:${String(e)}`)}),se.on("error",_e=>{c(_e.message),w("error")}),()=>{et.close(),se.close()}})},[e,Qe,pr,ne,n,t,b]),p==="editing")return D(Ct,{...S!==void 0&&{initialMode:S},showProfileManager:S==="global",onComplete:Ao,onCancel:()=>{y("main")}});let Ot=ee!==null?Math.round((Date.now()-ee.getTime())/1e3):null,No=Ot===null?"":Ot<5?" (just now)":` (${String(Ot)}s ago)`,ur=ie?.filter(C=>C.severity==="error").length??0;return U(K,{flexDirection:"column",paddingY:1,paddingX:2,children:[D(q,{marginBottom:1}),U(K,{flexDirection:"column",children:[U(K,{gap:2,marginBottom:0,children:[D(B,{bold:!0,dimColor:!0,children:"App Build"}),M==="pending"&&D(B,{dimColor:!0,children:"waiting\u2026"}),M==="building"&&U(K,{gap:1,children:[D(me,{}),D(B,{children:"Building plugin package\u2026"})]}),M==="done"&&U(K,{gap:1,children:[D(B,{color:"green",children:"\u2713 Built"}),ee!==null&&U(B,{dimColor:!0,children:["at ",ee.toLocaleTimeString(),No]}),Se!==null&&U(B,{dimColor:!0,children:["\xB7 bundle: ",$e(Se)]})]}),M==="error"&&(ie!==null?U(B,{color:"red",children:["\u2717 ",ur," validation ",ur===1?"error":"errors"]}):U(B,{color:"red",children:["\u2717 ",te??"unknown error"]}))]}),ie!==null&&D(it,{issues:ie}),D(K,{flexDirection:"column",height:10,borderStyle:"single",borderColor:"gray",overflow:"hidden",children:l.slice(-8).map((C,L)=>D(B,{dimColor:!0,wrap:"truncate",children:C},L))})]}),U(K,{marginTop:1,flexDirection:"column",children:[U(K,{gap:2,children:[D(B,{bold:!0,dimColor:!0,children:"Web Server"}),O==="starting"&&D(B,{dimColor:!0,children:"starting\u2026"}),O==="running"&&U(K,{gap:2,children:[D(B,{color:"green",children:"\u2713 Running"}),U(B,{dimColor:!0,children:["\u25CF ",Rt," viewer",Rt!==1?"s":""]})]}),O==="error"&&U(B,{color:"red",children:["\u2717 ",v??"Server error"]})]}),D(K,{flexDirection:"column",height:10,borderStyle:"single",borderColor:"gray",overflow:"hidden",children:a.slice(-8).map((C,L)=>D(B,{dimColor:!0,wrap:"truncate",children:C},L))})]}),U(K,{marginTop:1,flexDirection:"column",children:[U(K,{gap:2,children:[D(B,{bold:!0,dimColor:!0,children:"Network Proxy"}),D(B,{color:"green",children:"\u2713 Active"}),D(B,{dimColor:!0,children:b?`\u25CF ${String(cr)} key${cr!==1?"s":""} in the network cache \xB7 ${String(Po)} hit \xB7 ${String(Nt)} miss`:`\u25CF network cache disabled \xB7 ${String(Nt)} request${Nt!==1?"s":""}`})]}),D(K,{flexDirection:"column",height:10,borderStyle:"single",borderColor:"gray",overflow:"hidden",children:_.length===0?D(B,{dimColor:!0,children:" No requests yet."}):_.slice(-8).map((C,L)=>D(B,{dimColor:!0,wrap:"truncate",children:C},L))})]}),f&&U(K,{marginTop:1,flexDirection:"column",children:[U(K,{gap:2,children:[D(B,{bold:!0,dimColor:!0,children:"CDP Debug"}),U(B,{dimColor:!0,children:["\u25CF ",h.length," event(s)"]})]}),D(K,{flexDirection:"column",height:10,borderStyle:"single",borderColor:"gray",overflow:"hidden",children:h.length===0?D(B,{dimColor:!0,children:" No CDP events yet."}):h.slice(-8).map((C,L)=>D(B,{dimColor:!0,wrap:"truncate",children:C},L))})]}),U(K,{marginTop:1,gap:1,children:[D(B,{dimColor:!0,children:"["}),D(B,{children:"q"}),D(B,{dimColor:!0,children:"] quit ["}),D(B,{children:"c"}),D(B,{dimColor:!0,children:"] credentials ["}),D(B,{children:"v"}),U(B,{dimColor:!0,children:["] ",Rt===0?"open viewer":"relaunch viewer"]})]})]})};async function Hn(e){return new Promise(t=>{let n=null,o=i=>{n?.(),t(i)},{unmount:r}=Vn(Un(Ct,{...e!==void 0&&{initialMode:e},onComplete:o}),{exitOnCtrlC:!1});n=r})}function qn(e){e.command("dev").description("Start the plugin viewer dev server").option("-p, --port <port>","port to listen on","3121").option("-c, --credentials <path>","path to a credentials JSON file").option("-d, --debug","Enable CDP lifecycle logs in the TUI").option("-v, --verbose","Log every CDP event and handled error (implies --debug)").option("--no-viewer","Don't auto-launch the viewer on startup (press [v] to launch manually)").option("--no-cache","Disable the network proxy cache (always fetch upstream)").action(async t=>{let n=parseInt(t.port,10),o=process.cwd(),r=`${o}/.kizenapp`;Ne(o);let i=null,d,f,{lastPath:g}=await xe(r);if(t.credentials)i=await be(t.credentials);else{let p=await xe(r);if(p.credentialMode==="local")d="local";else if(p.credentialMode==="global"){if(d="global",f=p.activeCredentialProfile,f?(i=await de(f),i||(i=await Z(),f=void 0)):i=await Z(),!i){let y=await Hn("global");i=y.credentials,f=y.profileName}}else{let y=await Hn();i=y.credentials,d=y.mode,f=y.profileName;let S=y.profileName;await ve(r,{credentialMode:y.mode,...S!==void 0&&{activeCredentialProfile:S}})}}let m=t.verbose===!0,b=m||t.debug===!0,T=t.viewer!==!1,P=t.cache!==!1,{waitUntilExit:x}=Vn(Un(zn,{port:n,pluginDir:o,outputDir:r,credentials:i,...d!==void 0&&{credentialMode:d},...f!==void 0&&{activeCredentialProfile:f},...g!==void 0&&{lastPath:g},debug:b,verbose:m,autoViewer:T,cacheEnabled:P}),{exitOnCtrlC:!1});await x()})}import{createElement as Oa}from"react";import{render as ja}from"ink";import{useCallback as _t,useEffect as Xn,useState as Et}from"react";import{Box as ae,Text as $,useApp as Ra,useInput as Aa}from"ink";import{encrypt as va,serializeEnvelope as wa}from"@kizenapps/packager";function Ca(e){let t=e;return t.code==="ECONNREFUSED"||t.cause?.code==="ECONNREFUSED"}function Jn(e){return{"Content-Type":"application/json","x-api-key":e.apiKey,"x-user-id":e.userId,"x-business-id":e.businessId,"x-auth-environment":e.environment}}async function Wn(e,t,n){try{return await fetch(`${e}${t}`,n)}catch(o){throw new Error(Ca(o)?`Plugin-wizard is not running at ${e}`:`Failed to reach plugin-wizard: ${o.message}`)}}async function Kn(e){let t=await e.text();if(t==="")return{};try{let n=JSON.parse(t);return typeof n=="object"&&n!==null?n:{}}catch{return{}}}async function Sa(e,t,n){let o=Ve(e.stage),r=await Wn(o,"/get-public-key",{method:"POST",headers:Jn(t),body:JSON.stringify({api_name:n})}),i=await Kn(r);if(!r.ok||typeof i.public_key!="string"){let d=typeof i.error=="string"?i.error:`HTTP ${String(r.status)}`;throw new Error(`Failed to fetch public key: ${d}`)}return i.public_key}function Ta(e,t){let n=va(t,e),o=wa(n);if(typeof o.value!="string")throw new Error("Unexpected serialized envelope shape from @kizenapps/packager");return o.value}async function _a(e,t,n,o){let r=Ve(e.stage),i=await Wn(r,"/encrypt",{method:"POST",headers:Jn(t),body:JSON.stringify({api_name:n,value:o})}),d=await Kn(i);if(!i.ok||d.encrypted!==!0||typeof d.value!="string"){let f=typeof d.error=="string"?d.error:`HTTP ${String(i.status)}`;throw new Error(`Encryption via plugin-wizard failed: ${f}`)}return d.value}async function Tt(e,t,n,o,r){if(e.isRemote)return r?.("encrypting"),_a(e,t,n,o);r?.("fetching-key");let i=await Sa(e,t,n);return r?.("encrypting"),Ta(i,o)}import{spawn as Ea}from"child_process";import{platform as Gn}from"process";function ka(){return Gn==="darwin"?[{cmd:"pbcopy",args:[]}]:Gn==="win32"?[{cmd:"clip",args:[]}]:[{cmd:"wl-copy",args:[]},{cmd:"xclip",args:["-selection","clipboard"]},{cmd:"xsel",args:["--clipboard","--input"]}]}var Pa=2e3;function Ia(e,{cmd:t,args:n}){return new Promise(o=>{let r;try{r=Ea(t,n,{stdio:["pipe","ignore","ignore"]})}catch{o(!1);return}let i=r,d=!1;function f(m){d||(d=!0,clearTimeout(g),o(m))}let g=setTimeout(()=>{i.kill(),f(!1)},Pa);g.unref(),i.on("error",()=>{f(!1)}),i.on("close",m=>{f(m===0)}),i.stdin.on("error",()=>{f(!1)});try{i.stdin.end(e)}catch{f(!1)}})}async function Yn(e){for(let t of ka())if(await Ia(e,t))return!0;return!1}import{Fragment as kt,jsx as F,jsxs as G}from"react/jsx-runtime";var sr=({text:e})=>F($,{dimColor:!0,children:e}),Zn=({ctx:e,stageDefaulted:t,credentialsPath:n,initialApiName:o,defaultApiName:r,initialValue:i,onDone:d})=>{let f=Ra(),[g,m]=Et({type:"loading"}),[b,T]=Et(null),[P,x]=Et(o??""),[p,y]=Et(i??""),S=_t(s=>{process.exitCode=1,m({type:"error",message:s instanceof Error?s.message:String(s)})},[]),H=_t(async(s,l,u)=>{try{let h=await Tt(e,s,l,u,A=>{m(A==="fetching-key"?{type:"fetching-key"}:{type:"encrypting"})}),k=JSON.stringify({encrypted:!0,value:h},null,2);d?.(h);let _=await Yn(k);m({type:"done",envelope:k,copied:_})}catch(h){S(h)}},[e,S,d]),O=_t((s,l,u)=>{if(l.trim()===""){m({type:"api-name-entry",buffer:r??""});return}if(u===""){m({type:"value-entry",buffer:""});return}H(s,l.trim(),u)},[r,H]),w=_t(async s=>{try{m({type:"loading"});let l=s.isDefault?await Z():await de(s.name);if(l===null)throw new Error(`Could not load credential profile: ${s.name}`);T(l),O(l,P,p)}catch(l){S(l)}},[P,p,O,S]);Xn(()=>{(async()=>{try{if(n!==void 0){let u;try{u=await be(n)}catch(h){throw new Error(`Could not load credentials from ${n}: ${h instanceof Error?h.message:String(h)}`)}T(u),O(u,P,p);return}let s=await Ie();if(s.length===0)throw new Error("No credential profiles found. Create ~/.kizenappbuilder/credentials.json first.");let[l]=s;if(s.length===1&&l!==void 0){let u=l.isDefault?await Z():await de(l.name);if(u===null)throw new Error(`Could not load credential profile: ${l.name}`);T(u),O(u,P,p);return}m({type:"profile-select",profiles:s,cursor:0})}catch(s){S(s)}})()},[]),Xn(()=>{(g.type==="done"||g.type==="error")&&f.exit()},[g,f]),Aa((s,l)=>{if(l.ctrl&&s==="c"){process.exitCode=130,f.exit();return}if(g.type==="profile-select"){let{profiles:u,cursor:h}=g;if(l.upArrow)m({...g,cursor:(h-1+u.length)%u.length});else if(l.downArrow)m({...g,cursor:(h+1)%u.length});else if(l.return){let k=u[h];k!==void 0&&w(k)}return}if(g.type==="api-name-entry"){let{buffer:u}=g;if(l.backspace||l.delete)m({type:"api-name-entry",buffer:u.slice(0,-1)});else if(l.return){let h=u.trim();if(h===""){m({type:"api-name-entry",buffer:u,error:"api_name cannot be empty"});return}x(h),b?O(b,h,p):S(new Error("Internal error: credentials were not loaded"))}else s&&!l.ctrl&&!l.meta&&m({type:"api-name-entry",buffer:u+s});return}if(g.type==="value-entry"){let{buffer:u}=g;if(l.backspace||l.delete)m({type:"value-entry",buffer:u.slice(0,-1)});else if(l.return){if(u===""){m({type:"value-entry",buffer:u,error:"secret cannot be empty"});return}y(u),b?O(b,P,u):S(new Error("Internal error: credentials were not loaded"))}else s&&!l.ctrl&&!l.meta&&m({type:"value-entry",buffer:u+s});return}});let v=e.isRemote?"remote Kizen API":"on-machine",c=t===!0?`${e.stage} (default)`:e.stage,a=s=>G(ae,{flexDirection:"column",paddingY:1,paddingX:2,gap:1,children:[F(q,{}),G($,{dimColor:!0,children:["Mode: ",v," Stage: ",c]}),s]});if(g.type==="loading")return a(G(ae,{gap:1,children:[F(me,{}),F($,{dimColor:!0,children:"Loading credentials\u2026"})]}));if(g.type==="profile-select"){let{profiles:s,cursor:l}=g;return a(G(kt,{children:[F($,{bold:!0,children:"Credential profile"}),F(ae,{flexDirection:"column",children:s.map((u,h)=>{let k=l===h;return G(ae,{gap:2,children:[F($,{...k&&{color:"cyan"},children:k?"\u276F":" "}),F($,{bold:k,...k&&{color:"cyan"},children:u.isDefault?"Default":u.name}),F($,{dimColor:!0,children:u.path})]},u.name)})}),F(sr,{text:"\u2191\u2193 to move \xB7 Enter to select \xB7 Ctrl+C to quit"})]}))}return g.type==="api-name-entry"?a(G(kt,{children:[F($,{bold:!0,children:"Plugin api_name"}),g.error!==void 0&&G($,{color:"red",children:["Error: ",g.error]}),G(ae,{gap:1,children:[F($,{color:"cyan",children:">"}),F($,{children:g.buffer}),F($,{color:"cyan",children:"\u2588"})]}),F(sr,{text:"Type the api_name \xB7 Enter to confirm \xB7 Ctrl+C to quit"})]})):g.type==="value-entry"?a(G(kt,{children:[F($,{bold:!0,children:"Secret value"}),g.error!==void 0&&G($,{color:"red",children:["Error: ",g.error]}),G(ae,{gap:1,children:[F($,{color:"cyan",children:">"}),F($,{children:"\u2022".repeat(g.buffer.length)}),F($,{color:"cyan",children:"\u2588"})]}),F(sr,{text:"Input hidden \xB7 Enter to encrypt \xB7 Ctrl+C to quit"})]})):g.type==="fetching-key"?a(G(ae,{gap:1,children:[F(me,{}),G($,{children:["Fetching ",e.stage," public key for ",F($,{bold:!0,children:P}),"\u2026"]})]})):g.type==="encrypting"?a(G(ae,{gap:1,children:[F(me,{}),F($,{children:"Encrypting\u2026"})]})):g.type==="error"?a(G(ae,{gap:1,children:[F($,{color:"red",children:"\u2717"}),F($,{color:"red",children:g.message})]})):a(G(kt,{children:[G(ae,{gap:1,children:[F($,{color:"green",children:"\u2713"}),F($,{bold:!0,children:"Encrypted secret ready"})]}),g.copied?F($,{color:"green",children:"\u2713 Copied to clipboard \u2014 paste it into the secret value in your kizen.json."}):F($,{dimColor:!0,children:"Paste this into the secret value in your kizen.json (re-run with --out <path> to save it to a file; selecting it here may capture line wraps):"}),F($,{children:g.envelope})]}))};import{readFile as Na,writeFile as Ba}from"fs/promises";import{join as Da}from"path";function Qn(e){return{encrypted:!0,value:e}}function eo(e){return JSON.stringify(Qn(e))}async function ar(e,t){await Ba(e,`${JSON.stringify(Qn(t),null,2)}
490
- `,"utf-8")}var Fa="prod";function to(e){return e==="dev"||e==="prod"}function ro(e){return`Error: --stage must be "dev" or "prod" (got: "${e}")`}function no(e){return{stage:e==="dev"||e==="prod"?e:Fa,wasDefaulted:e===void 0}}function oo(e){return`No --stage given; defaulting to ${e} encryption keys (pass --stage dev to override)
491
- `}async function io(e=process.cwd()){try{let t=await Na(Da(e,"kizen.json"),"utf-8"),n=JSON.parse(t),o=Array.isArray(n)?n[0]:n,r=typeof o.api_name=="string"&&o.api_name!==""?o.api_name:void 0;return{...r!==void 0&&{apiName:r}}}catch{}return{}}function so(e){return e.replace(/[\r\n]+$/,"")}async function ao(){let e=[];for await(let t of process.stdin)e.push(t);return Buffer.concat(e).toString("utf-8")}async function lo(e,t,n,o,r){let i=t.credentials!==void 0?await r.loadCredentialsFromFile(t.credentials):await r.loadGlobalCredentials();if(i===null)throw new Error("No credentials found. Pass --credentials or create ~/.kizenappbuilder/credentials.json.");let d=t.apiName??n.apiName;if(d===void 0||d.trim()==="")throw new Error("api_name is required in non-interactive mode. Pass --api-name or run inside a plugin directory.");o&&r.writeStderr(oo(e.stage));let f=t.value;if(f===void 0){if(r.stdinIsTTY())throw new Error('No secret provided and stdin is a terminal. Pass --value, or pipe the secret in (e.g. `printf %s "$SECRET" | npx --yes @kizenapps/cli encrypt \u2026`).');r.writeStderr(`Reading secret from stdin (pass --value to skip)\u2026
492
- `),f=so(await r.readStdin())}if(f==="")throw new Error("A secret value is required. Pass --value or pipe it via stdin.");let g=await r.encryptSecret(e,i,d.trim(),f);if(r.writeStdout(`${eo(g)}
457
+ `);E.push({name:z.name,value:W}),R=!0}else E.push(z);R&&T(` rewrote Set-Cookie SameSite on ${k}`);try{let{body:z,base64Encoded:W}=await C.Fetch.getResponseBody({requestId:s});await C.Fetch.fulfillRequest({requestId:s,responseCode:h??200,responseHeaders:E,body:z,...W&&{base64Encoded:!0}})}catch(z){T(` fulfillRequest failed (${z.message}), falling through`);try{await C.Fetch.continueRequest({requestId:s})}catch(W){T(` continueRequest also failed (${W.message})`)}}})()}),i=setInterval(()=>{(async()=>{try{let{cookies:d}=await C.Network.getAllCookies(),l=0;for(let s of d){if(!Ln(`https://${s.domain??""}`)||s.sameSite==="None")continue;let a=s.domain??"",u=a.startsWith(".")?a.slice(1):a;await C.Network.setCookie({url:`https://${u}`,name:s.name,value:s.value,domain:a,path:s.path??"/",secure:!0,...s.httpOnly!==void 0&&{httpOnly:s.httpOnly},...s.expirationDate!==void 0&&{expires:s.expirationDate},sameSite:"None"}),l++}l>0&&T(`cookie-patch cycle: updated ${String(l)} cookie(s) to SameSite=None`)}catch(d){T(`cookie-patch cycle failed: ${d.message}`)}})()},2e3),await C.Target.setDiscoverTargets({discover:!0});let v=d=>{if(d.type==="page"){if(x(d.url)){y(`closed stray new-tab-page target ${d.targetId}`),p!==null&&C.Target.activateTarget({targetId:p}).catch(()=>{}),C.Target.closeTarget({targetId:d.targetId}).catch(()=>{});return}p===null&&(p=d.targetId,y(`captured main target ${d.targetId} (${d.url})`))}};C.on("Target.targetCreated",d=>{let{targetInfo:l}=d;T(`target +${l.type} ${l.targetId} ${l.url}`),v(l)}),C.on("Target.targetInfoChanged",d=>{let{targetInfo:l}=d;T(`target ~${l.type} ${l.targetId} ${l.url}`),v(l)}),C.on("disconnect",()=>{m||r!==C||(y("CDP disconnected"),r=null,P(),b())})},b=()=>{if(m||f!==null)return;let C=Math.min(1e3*2**g,1e4),v=g+1;g++,y(`CDP reconnect scheduled in ${String(C)}ms (attempt #${String(v)})`),f=setTimeout(()=>{f=null,(async()=>{let d;try{d=await jn({port:o})}catch{y(`CDP reconnect attempt #${String(v)} failed`),b();return}if(m){try{await d.close()}catch{}return}r=d;try{await c(d),y(`CDP reconnected after ${String(v)} attempt(s)`),g=0}catch{r===d&&(r=null);try{await d.close()}catch{}y(`CDP reconnect attempt #${String(v)} failed during setup`),b()}})()},C)},w=30,H=300;for(let C=0;C<w;C++){await new Promise(v=>setTimeout(v,H)),y(`CDP connect attempt ${String(C+1)}/${String(w)}`);try{let v=await jn({port:o});r=v,e.path&&v.send("Page.navigate",{url:`${t}${e.path}`});try{await c(v),y("CDP connected")}catch{r===v&&(r=null);try{await v.close()}catch{}y("CDP setup failed after connect")}break}catch{if(C===w-1){let v=`CDP unavailable after ${String(w)} attempts \u2014 viewer running without interception (CSP/cookie rewrites disabled)`;return y(v),e.onWarn?.(v),{kill:()=>{n.kill()}}}}}return r?{kill:()=>{if(y("CDP kill requested \u2014 tearing down"),m=!0,f!==null&&(clearTimeout(f),f=null),P(),r!==null){try{r.close()}catch{}r=null}n.kill()}}:{kill:()=>{n.kill()}}}import{useCallback as ba,useState as xa}from"react";function vt(e){let[t,n]=xa([]),o=ba(r=>{n(i=>[...i,`${new Date().toLocaleTimeString()}: ${r}`].slice(-e))},[e]);return[t,o]}import{useCallback as wt,useEffect as sr,useState as Ct}from"react";import{Box as V,Text as $,useInput as va}from"ink";import{jsx as N,jsxs as J}from"react/jsx-runtime";var Se=["apiKey","userId","businessId"],wa={apiKey:"API Key",userId:"User ID",businessId:"Business ID"},Ye=({text:e})=>N($,{dimColor:!0,children:e}),St=({initialMode:e,showProfileManager:t,onComplete:n,onCancel:o})=>{let[r,i]=Ct(e==="global"&&!t?{type:"loading"}:e==="global"&&t?{type:"profile-loading"}:{type:"mode-select",cursor:0}),[p,f]=Ct(""),[g,m]=Ct(null),[y,T]=Ct(void 0),P=wt(d=>{if(d==="local"){n({mode:"local",credentials:null});return}i({type:"profile-loading"})},[n]),x=wt(async d=>{if(d===null){i({type:"profile-loading"});let a=await Re();i({type:"name-entry",nameBuffer:"",existingProfiles:a});return}T(d.isDefault?void 0:d.name),i({type:"loading"});let l=d.isDefault?await Z():await de(d.name),s=l?Math.max(0,Y.indexOf(l.environment)):0;i({type:"creds-entry",field:0,values:l??{},envCursor:s})},[]),c=wt(async(d,l)=>{let s=Y[l]??"go",a={apiKey:d.apiKey??"",userId:d.userId??"",businessId:d.businessId??"",environment:s};i({type:"saving"});try{await ln(y??xe,a),n({mode:"global",credentials:a,...y!==void 0&&{profileName:y}})}catch(u){m(u instanceof Error?u.message:String(u)),i({type:"creds-entry",field:0,values:d,envCursor:l})}},[n,y]);va((d,l)=>{if(l.ctrl&&d==="c"&&process.exit(0),l.escape){if((r.type==="creds-entry"||r.type==="name-entry")&&e==="global"&&t){i({type:"profile-loading"}),b();return}o?.();return}if(r.type==="mode-select"){if(l.upArrow)i({type:"mode-select",cursor:0});else if(l.downArrow)i({type:"mode-select",cursor:1});else if(l.return){let s=r.cursor===0?"global":"local";P(s)}return}if(r.type==="profile-select"){let{profiles:s,cursor:a}=r,u=s.length,h=s.length+1;if(l.upArrow)i({...r,cursor:(a-1+h)%h});else if(l.downArrow)i({...r,cursor:(a+1)%h});else if(l.return)if(a===u)i({type:"name-entry",nameBuffer:"",existingProfiles:s});else{let k=s[a]??s[0];k&&x(k)}return}if(r.type==="name-entry"){let{nameBuffer:s,existingProfiles:a}=r;if(l.backspace||l.delete)i({type:"name-entry",nameBuffer:s.slice(0,-1),existingProfiles:a});else if(l.return){let u=s.trim();if(!u){i({...r,nameError:"Name cannot be empty"});return}if(u===xe){i({...r,nameError:`"${xe}" is reserved`});return}if(a.some(h=>h.name===u)){i({...r,nameError:`Profile "${u}" already exists`});return}T(u),i({type:"creds-entry",field:0,values:{},envCursor:0}),f("")}else d&&!l.ctrl&&!l.meta&&i({type:"name-entry",nameBuffer:s+d,existingProfiles:a});return}if(r.type==="creds-entry"){let{field:s,values:a,envCursor:u}=r;if(s===Se.length){l.leftArrow?i({...r,envCursor:(u-1+Y.length)%Y.length}):l.rightArrow?i({...r,envCursor:(u+1)%Y.length}):l.upArrow?(i({...r,field:s-1}),f(a[Se[s-1]]??"")):l.return&&c(a,u);return}let k=Se[s];if(!k)return;if(l.backspace||l.delete)f(E=>E.slice(0,-1));else if(l.upArrow&&s>0){let E={...a,[k]:p},R=s-1;i({...r,field:R,values:E}),f(E[Se[R]]??"")}else if(l.return||l.tab||l.downArrow){let E={...a,[k]:p},R=s+1;i({...r,field:R,values:E}),R<Se.length?f(E[Se[R]]??""):f("")}else d&&!l.ctrl&&!l.meta&&f(E=>E+d)}});let b=wt(async()=>{let d=await Re();i({type:"profile-select",profiles:d,cursor:0})},[]);if(sr(()=>{r.type==="profile-loading"&&b()},[r.type,b]),sr(()=>{e==="global"&&!t&&(async()=>{let d=await Z(),l=d?Math.max(0,Y.indexOf(d.environment)):0;i({type:"creds-entry",field:0,values:d??{},envCursor:l})})()},[]),sr(()=>{r.type==="creds-entry"&&r.field===0&&f(r.values.apiKey??"")},[r.type]),r.type==="loading"||r.type==="saving"||r.type==="profile-loading"){let d=r.type==="saving"?"Saving credentials\u2026":r.type==="profile-loading"?"Loading profiles\u2026":"Loading credentials\u2026";return N(V,{paddingY:1,paddingX:2,children:N($,{dimColor:!0,children:d})})}if(r.type==="done")return null;if(r.type==="mode-select")return J(V,{flexDirection:"column",paddingY:1,paddingX:2,gap:1,children:[N(q,{}),J(V,{flexDirection:"column",gap:0,children:[N($,{bold:!0,children:"Credential mode"}),[{label:"Global",desc:"~/.kizenappbuilder/credentials.json",mode:"global"},{label:"Local",desc:"Enter credentials in the browser dev tools",mode:"local"}].map((l,s)=>{let a=r.cursor===s;return J(V,{gap:2,children:[N($,{...a&&{color:"cyan"},children:a?"\u276F":" "}),N($,{bold:a,...a&&{color:"cyan"},children:l.label}),N($,{dimColor:!0,children:l.desc})]},l.mode)})]}),N(Ye,{text:"\u2191\u2193 to move \xB7 Enter to select \xB7 Ctrl+C to quit"})]});if(r.type==="profile-select"){let{profiles:d,cursor:l}=r,s=d.length;return J(V,{flexDirection:"column",paddingY:1,paddingX:2,gap:1,children:[N(q,{}),J(V,{flexDirection:"column",gap:0,children:[N($,{bold:!0,children:"Credential profiles"}),d.map((a,u)=>{let h=l===u;return J(V,{gap:2,children:[N($,{...h&&{color:"cyan"},children:h?"\u276F":" "}),N($,{bold:h,...h&&{color:"cyan"},children:a.isDefault?"Default":a.name}),N($,{dimColor:!0,children:a.path})]},a.name)}),J(V,{gap:2,children:[N($,{...l===s&&{color:"cyan"},children:l===s?"\u276F":" "}),N($,{bold:l===s,...l===s&&{color:"cyan"},children:"+ Add new profile"})]})]}),N(Ye,{text:"\u2191\u2193 to move \xB7 Enter to select \xB7 Esc to cancel"})]})}if(r.type==="name-entry"){let{nameBuffer:d,nameError:l}=r;return J(V,{flexDirection:"column",paddingY:1,paddingX:2,gap:1,children:[N(q,{}),N(V,{flexDirection:"column",gap:0,children:N($,{bold:!0,children:"New credential profile"})}),l&&J($,{color:"red",children:["Error: ",l]}),J(V,{gap:2,children:[N(V,{width:12,children:N($,{bold:!0,color:"cyan",children:"Profile name"})}),N($,{color:"cyan",children:">"}),N($,{children:d}),N($,{color:"cyan",children:"\u2588"})]}),N(Ye,{text:"Type a name \xB7 Enter to confirm \xB7 Esc to go back"})]})}let{field:w,values:H,envCursor:j}=r,C=w===Se.length,v=y??xe;return J(V,{flexDirection:"column",paddingY:1,paddingX:2,gap:1,children:[N(q,{}),J(V,{flexDirection:"column",gap:0,children:[N($,{bold:!0,children:y!==void 0?`Profile: ${y}`:"Global credentials"}),J($,{dimColor:!0,children:["Saved to:"," ",y!==void 0?`~/.kizenappbuilder/${y}.json`:Fe]})]}),g&&J($,{color:"red",children:["Error: ",g]}),J(V,{flexDirection:"column",gap:0,children:[Se.map((d,l)=>{let s=w===l,a=s?p:H[d]??"";return J(V,{gap:2,children:[N(V,{width:12,children:N($,{bold:s,...s&&{color:"cyan"},children:wa[d]})}),N($,{...s&&{color:"cyan"},children:">"}),N($,{children:a}),s&&N($,{color:"cyan",children:"\u2588"})]},d)}),J(V,{gap:2,children:[N(V,{width:12,children:N($,{bold:C,...C&&{color:"cyan"},children:"Environment"})}),N($,{...C&&{color:"cyan"},children:">"}),N(V,{gap:1,children:Y.map((d,l)=>{let s=l===j;return C?N($,{bold:s,...s&&{color:"cyan"},children:s?`[${d}]`:d},d):N($,{dimColor:!s,bold:s,children:d},d)})})]})]}),C?N(Ye,{text:"\u2190\u2192 to select \xB7 \u2191\u2193 to move \xB7 Enter to save \xB7 Esc to cancel"}):N(Ye,{text:"\u2191\u2193 to move \xB7 Backspace to delete \xB7 Esc to cancel"}),J($,{dimColor:!0,children:["Profile: ",v]})]})};import{jsx as D,jsxs as U}from"react/jsx-runtime";var Pa=[".kizenapp",".git"],Hn=({port:e,pluginDir:t,outputDir:n,credentials:o,credentialMode:r,activeCredentialProfile:i,lastPath:p,debug:f=!1,verbose:g=!1,autoViewer:m=!0,cacheEnabled:y=!0})=>{let T=pe(o),P=pe(i),x=pe(p),[c,b]=Q("main"),[w,H]=Q(r),[j,C]=Q("starting"),[v,d]=Q(null),[l,s]=vt(50),[a,u]=vt(50),[h,k]=vt(50),[E,R]=Q([]),[z,W]=Q("pending"),[te,oe]=Q(null),[ie,re]=Q(null),[ee,je]=Q(null),[Ee,Nt]=Q(null),[Rt,Bt]=Q(0),[dr,No]=Q(0),[Ro,Bo]=Q(0),[At,Ao]=Q(0),Dt=pe(!1),pr=pe(!1),Ze=pe(null),Le=pe(null),ue=pe(new Set),Qe=pe([]),ne=$e(S=>{let O=JSON.stringify(S);if(ue.current.size===0){Qe.current=[...Qe.current,O].slice(-50);return}let fe=!1;for(let se of ue.current)if(se.readyState===1)try{se.send(O)}catch{ue.current.delete(se),fe=!0}fe&&Bt(ue.current.size)},[]),et=s,Ft=$e(()=>{Ze.current?.kill(),Ze.current=null,zn({port:e,userDataDir:Mn(n,".chrome"),broadcast:ne,onWarn:S=>{s(`\u26A0 ${S}`)},...x.current!==void 0&&{path:x.current},...f&&{debugLog:k},...g&&{verbose:!0}}).then(S=>{Ze.current=S})},[e,n,ne,f,g,k,s]);Tt(()=>{let S=()=>{Ze.current?.kill()};return process.on("exit",S),()=>{process.off("exit",S)}},[]),Sa((S,O)=>{(S==="q"||O.ctrl&&S==="c")&&process.exit(0),S==="c"&&b("editing"),S==="v"&&Ft()},{isActive:c==="main"}),Tt(()=>{j!=="running"||pr.current||!m||(pr.current=!0,Ft())},[j,m,Ft]);let Do=$e(S=>{T.current=S.credentials,P.current=S.profileName,b("main"),H(S.mode);let O=S.profileName;Ce(n,{credentialMode:S.mode,...O!==void 0&&{activeCredentialProfile:O}}),ne({type:"credentials-updated",credentials:S.credentials})},[n,ne]),ur=$e(S=>{R(O=>[...O,`${new Date().toLocaleTimeString()}: ${nr(S)}`].slice(-50)),S.kind==="request"&&(S.fromCache?Bo(O=>O+1):Ao(O=>O+1)),ne({type:"proxy-log",entry:S})},[ne]),_e=$e(S=>{u(S),ne({type:"log",message:S})},[u,ne]),$t=$e(()=>{Dt.current||(Dt.current=!0,W("building"),oe(null),re(null),_e("Build started"),ot(t,n).then(({bundleSize:S})=>{_e(`Build finished \u2014 bundle: ${Oe(S)}`),W("done"),je(new Date),Nt(S),_e("Notifying viewers to reload"),ne({type:"rebuild"})}).catch(S=>{S instanceof Ta?(re(S.issues),oe(null)):(oe(S instanceof Error?S.message:String(S)),re(null)),W("error")}).finally(()=>{Dt.current=!1}))},[t,n,_e,ne]);if(Tt(()=>{$t();let S=Ea(t,{recursive:!0},(O,fe)=>{if(!fe)return;let se=fe.replace(/\\/g,"/");Pa.some(tt=>se.startsWith(tt))||(_e(`File change detected: ${fe}`),Le.current!==null&&clearTimeout(Le.current),Le.current=setTimeout($t,150))});return S.on("error",O=>{_e(`File watcher error \u2014 rebuilds have stopped: ${O.message}`)}),()=>{S.close(),Le.current!==null&&clearTimeout(Le.current)}},[t,$t,_e]),Tt(()=>{let S=Fn();ir(Mn(S,"index.html")).then(O=>{if(!O){d("Viewer not built. Run 'pnpm build:viewer' first."),C("error");return}let fe=$n(S,et,ur,T,P,n,ne,No,x,t,y),se=_a(fe),tt=new ka({server:se});return tt.on("connection",ke=>{for(let $o of Qe.current)ke.readyState===1&&ke.send($o);Qe.current=[],et("Viewer connected for live reload"),ue.current.add(ke),Bt(ue.current.size),ke.on("close",()=>{ue.current.delete(ke),Bt(ue.current.size)})}),se.listen(e,"127.0.0.1",()=>{C("running"),et(`Server started on 127.0.0.1:${String(e)}`)}),se.on("error",ke=>{d(ke.message),C("error")}),()=>{tt.close(),se.close()}})},[e,et,ur,ne,n,t,y]),c==="editing")return D(St,{...w!==void 0&&{initialMode:w},showProfileManager:w==="global",onComplete:Do,onCancel:()=>{b("main")}});let jt=ee!==null?Math.round((Date.now()-ee.getTime())/1e3):null,Fo=jt===null?"":jt<5?" (just now)":` (${String(jt)}s ago)`,fr=ie?.filter(S=>S.severity==="error").length??0;return U(G,{flexDirection:"column",paddingY:1,paddingX:2,children:[D(q,{marginBottom:1}),U(G,{flexDirection:"column",children:[U(G,{gap:2,marginBottom:0,children:[D(A,{bold:!0,dimColor:!0,children:"App Build"}),z==="pending"&&D(A,{dimColor:!0,children:"waiting\u2026"}),z==="building"&&U(G,{gap:1,children:[D(me,{}),D(A,{children:"Building plugin package\u2026"})]}),z==="done"&&U(G,{gap:1,children:[D(A,{color:"green",children:"\u2713 Built"}),ee!==null&&U(A,{dimColor:!0,children:["at ",ee.toLocaleTimeString(),Fo]}),Ee!==null&&U(A,{dimColor:!0,children:["\xB7 bundle: ",Oe(Ee)]})]}),z==="error"&&(ie!==null?U(A,{color:"red",children:["\u2717 ",fr," validation ",fr===1?"error":"errors"]}):U(A,{color:"red",children:["\u2717 ",te??"unknown error"]}))]}),ie!==null&&D(st,{issues:ie}),D(G,{flexDirection:"column",height:10,borderStyle:"single",borderColor:"gray",overflow:"hidden",children:a.slice(-8).map((S,O)=>D(A,{dimColor:!0,wrap:"truncate",children:S},O))})]}),U(G,{marginTop:1,flexDirection:"column",children:[U(G,{gap:2,children:[D(A,{bold:!0,dimColor:!0,children:"Web Server"}),j==="starting"&&D(A,{dimColor:!0,children:"starting\u2026"}),j==="running"&&U(G,{gap:2,children:[D(A,{color:"green",children:"\u2713 Running"}),U(A,{dimColor:!0,children:["\u25CF ",Rt," viewer",Rt!==1?"s":""]})]}),j==="error"&&U(A,{color:"red",children:["\u2717 ",v??"Server error"]})]}),D(G,{flexDirection:"column",height:10,borderStyle:"single",borderColor:"gray",overflow:"hidden",children:l.slice(-8).map((S,O)=>D(A,{dimColor:!0,wrap:"truncate",children:S},O))})]}),U(G,{marginTop:1,flexDirection:"column",children:[U(G,{gap:2,children:[D(A,{bold:!0,dimColor:!0,children:"Network Proxy"}),D(A,{color:"green",children:"\u2713 Active"}),D(A,{dimColor:!0,children:y?`\u25CF ${String(dr)} key${dr!==1?"s":""} in the network cache \xB7 ${String(Ro)} hit \xB7 ${String(At)} miss`:`\u25CF network cache disabled \xB7 ${String(At)} request${At!==1?"s":""}`})]}),D(G,{flexDirection:"column",height:10,borderStyle:"single",borderColor:"gray",overflow:"hidden",children:E.length===0?D(A,{dimColor:!0,children:" No requests yet."}):E.slice(-8).map((S,O)=>D(A,{dimColor:!0,wrap:"truncate",children:S},O))})]}),f&&U(G,{marginTop:1,flexDirection:"column",children:[U(G,{gap:2,children:[D(A,{bold:!0,dimColor:!0,children:"CDP Debug"}),U(A,{dimColor:!0,children:["\u25CF ",h.length," event(s)"]})]}),D(G,{flexDirection:"column",height:10,borderStyle:"single",borderColor:"gray",overflow:"hidden",children:h.length===0?D(A,{dimColor:!0,children:" No CDP events yet."}):h.slice(-8).map((S,O)=>D(A,{dimColor:!0,wrap:"truncate",children:S},O))})]}),U(G,{marginTop:1,gap:1,children:[D(A,{dimColor:!0,children:"["}),D(A,{children:"q"}),D(A,{dimColor:!0,children:"] quit ["}),D(A,{children:"c"}),D(A,{dimColor:!0,children:"] credentials ["}),D(A,{children:"v"}),U(A,{dimColor:!0,children:["] ",Rt===0?"open viewer":"relaunch viewer"]})]})]})};async function Un(e){return new Promise(t=>{let n=null,o=i=>{n?.(),t(i)},{unmount:r}=qn(Vn(St,{...e!==void 0&&{initialMode:e},onComplete:o}),{exitOnCtrlC:!1});n=r})}function Jn(e){e.command("dev").description("Start the plugin viewer dev server").option("-p, --port <port>","port to listen on","3121").option("-c, --credentials <path>","path to a credentials JSON file").option("-d, --debug","Enable CDP lifecycle logs in the TUI").option("-v, --verbose","Log every CDP event and handled error (implies --debug)").option("--no-viewer","Don't auto-launch the viewer on startup (press [v] to launch manually)").option("--no-cache","Disable the network proxy cache (always fetch upstream)").action(async t=>{let n=parseInt(t.port,10),o=process.cwd(),r=`${o}/.kizenapp`;he(o);let i=null,p,f,{lastPath:g}=await we(r);if(t.credentials)i=await ve(t.credentials);else{let c=await we(r);if(c.credentialMode==="local")p="local";else if(c.credentialMode==="global"){if(p="global",f=c.activeCredentialProfile,f?(i=await de(f),i||(i=await Z(),f=void 0)):i=await Z(),!i){let b=await Un("global");i=b.credentials,f=b.profileName}}else{let b=await Un();i=b.credentials,p=b.mode,f=b.profileName;let w=b.profileName;await Ce(r,{credentialMode:b.mode,...w!==void 0&&{activeCredentialProfile:w}})}}let m=t.verbose===!0,y=m||t.debug===!0,T=t.viewer!==!1,P=t.cache!==!1,{waitUntilExit:x}=qn(Vn(Hn,{port:n,pluginDir:o,outputDir:r,credentials:i,...p!==void 0&&{credentialMode:p},...f!==void 0&&{activeCredentialProfile:f},...g!==void 0&&{lastPath:g},debug:y,verbose:m,autoViewer:T,cacheEnabled:P}),{exitOnCtrlC:!1});await x()})}import{createElement as qa}from"react";import{render as Ja}from"ink";import{useCallback as _t,useEffect as Zn,useState as kt}from"react";import{Box as ae,Text as L,useApp as Oa,useInput as za}from"ink";import{encrypt as Ia,serializeEnvelope as Na}from"@kizenapps/packager";function Ra(e){let t=e;return t.code==="ECONNREFUSED"||t.cause?.code==="ECONNREFUSED"}function Wn(e){return{"Content-Type":"application/json","x-api-key":e.apiKey,"x-user-id":e.userId,"x-business-id":e.businessId,"x-auth-environment":e.environment}}async function Gn(e,t,n){try{return await fetch(`${e}${t}`,n)}catch(o){throw new Error(Ra(o)?`Plugin-wizard is not running at ${e}`:`Failed to reach plugin-wizard: ${o.message}`)}}async function Kn(e){let t=await e.text();if(t==="")return{};try{let n=JSON.parse(t);return typeof n=="object"&&n!==null?n:{}}catch{return{}}}async function Ba(e,t,n){let o=qe(e.stage),r=await Gn(o,"/get-public-key",{method:"POST",headers:Wn(t),body:JSON.stringify({api_name:n})}),i=await Kn(r);if(!r.ok||typeof i.public_key!="string"){let p=typeof i.error=="string"?i.error:`HTTP ${String(r.status)}`;throw new Error(`Failed to fetch public key: ${p}`)}return i.public_key}function Aa(e,t){let n=Ia(t,e),o=Na(n);if(typeof o.value!="string")throw new Error("Unexpected serialized envelope shape from @kizenapps/packager");return o.value}async function Da(e,t,n,o){let r=qe(e.stage),i=await Gn(r,"/encrypt",{method:"POST",headers:Wn(t),body:JSON.stringify({api_name:n,value:o})}),p=await Kn(i);if(!i.ok||p.encrypted!==!0||typeof p.value!="string"){let f=typeof p.error=="string"?p.error:`HTTP ${String(i.status)}`;throw new Error(`Encryption via plugin-wizard failed: ${f}`)}return p.value}async function Et(e,t,n,o,r){if(e.isRemote)return r?.("encrypting"),Da(e,t,n,o);r?.("fetching-key");let i=await Ba(e,t,n);return r?.("encrypting"),Aa(i,o)}import{spawn as Fa}from"child_process";import{platform as Yn}from"process";function $a(){return Yn==="darwin"?[{cmd:"pbcopy",args:[]}]:Yn==="win32"?[{cmd:"clip",args:[]}]:[{cmd:"wl-copy",args:[]},{cmd:"xclip",args:["-selection","clipboard"]},{cmd:"xsel",args:["--clipboard","--input"]}]}var ja=2e3;function La(e,{cmd:t,args:n}){return new Promise(o=>{let r;try{r=Fa(t,n,{stdio:["pipe","ignore","ignore"]})}catch{o(!1);return}let i=r,p=!1;function f(m){p||(p=!0,clearTimeout(g),o(m))}let g=setTimeout(()=>{i.kill(),f(!1)},ja);g.unref(),i.on("error",()=>{f(!1)}),i.on("close",m=>{f(m===0)}),i.stdin.on("error",()=>{f(!1)});try{i.stdin.end(e)}catch{f(!1)}})}async function Xn(e){for(let t of $a())if(await La(e,t))return!0;return!1}import{Fragment as Pt,jsx as F,jsxs as K}from"react/jsx-runtime";var ar=({text:e})=>F(L,{dimColor:!0,children:e}),Qn=({ctx:e,stageDefaulted:t,credentialsPath:n,initialApiName:o,defaultApiName:r,initialValue:i,onDone:p})=>{let f=Oa(),[g,m]=kt({type:"loading"}),[y,T]=kt(null),[P,x]=kt(o??""),[c,b]=kt(i??""),w=_t(s=>{process.exitCode=1,m({type:"error",message:s instanceof Error?s.message:String(s)})},[]),H=_t(async(s,a,u)=>{try{let h=await Et(e,s,a,u,R=>{m(R==="fetching-key"?{type:"fetching-key"}:{type:"encrypting"})}),k=JSON.stringify({encrypted:!0,value:h},null,2);p?.(h);let E=await Xn(k);m({type:"done",envelope:k,copied:E})}catch(h){w(h)}},[e,w,p]),j=_t((s,a,u)=>{if(a.trim()===""){m({type:"api-name-entry",buffer:r??""});return}if(u===""){m({type:"value-entry",buffer:""});return}H(s,a.trim(),u)},[r,H]),C=_t(async s=>{try{m({type:"loading"});let a=s.isDefault?await Z():await de(s.name);if(a===null)throw new Error(`Could not load credential profile: ${s.name}`);T(a),j(a,P,c)}catch(a){w(a)}},[P,c,j,w]);Zn(()=>{(async()=>{try{if(n!==void 0){let u;try{u=await ve(n)}catch(h){throw new Error(`Could not load credentials from ${n}: ${h instanceof Error?h.message:String(h)}`)}T(u),j(u,P,c);return}let s=await Re();if(s.length===0)throw new Error("No credential profiles found. Create ~/.kizenappbuilder/credentials.json first.");let[a]=s;if(s.length===1&&a!==void 0){let u=a.isDefault?await Z():await de(a.name);if(u===null)throw new Error(`Could not load credential profile: ${a.name}`);T(u),j(u,P,c);return}m({type:"profile-select",profiles:s,cursor:0})}catch(s){w(s)}})()},[]),Zn(()=>{(g.type==="done"||g.type==="error")&&f.exit()},[g,f]),za((s,a)=>{if(a.ctrl&&s==="c"){process.exitCode=130,f.exit();return}if(g.type==="profile-select"){let{profiles:u,cursor:h}=g;if(a.upArrow)m({...g,cursor:(h-1+u.length)%u.length});else if(a.downArrow)m({...g,cursor:(h+1)%u.length});else if(a.return){let k=u[h];k!==void 0&&C(k)}return}if(g.type==="api-name-entry"){let{buffer:u}=g;if(a.backspace||a.delete)m({type:"api-name-entry",buffer:u.slice(0,-1)});else if(a.return){let h=u.trim();if(h===""){m({type:"api-name-entry",buffer:u,error:"api_name cannot be empty"});return}x(h),y?j(y,h,c):w(new Error("Internal error: credentials were not loaded"))}else s&&!a.ctrl&&!a.meta&&m({type:"api-name-entry",buffer:u+s});return}if(g.type==="value-entry"){let{buffer:u}=g;if(a.backspace||a.delete)m({type:"value-entry",buffer:u.slice(0,-1)});else if(a.return){if(u===""){m({type:"value-entry",buffer:u,error:"secret cannot be empty"});return}b(u),y?j(y,P,u):w(new Error("Internal error: credentials were not loaded"))}else s&&!a.ctrl&&!a.meta&&m({type:"value-entry",buffer:u+s});return}});let v=e.isRemote?"remote Kizen API":"on-machine",d=t===!0?`${e.stage} (default)`:e.stage,l=s=>K(ae,{flexDirection:"column",paddingY:1,paddingX:2,gap:1,children:[F(q,{}),K(L,{dimColor:!0,children:["Mode: ",v," Stage: ",d]}),s]});if(g.type==="loading")return l(K(ae,{gap:1,children:[F(me,{}),F(L,{dimColor:!0,children:"Loading credentials\u2026"})]}));if(g.type==="profile-select"){let{profiles:s,cursor:a}=g;return l(K(Pt,{children:[F(L,{bold:!0,children:"Credential profile"}),F(ae,{flexDirection:"column",children:s.map((u,h)=>{let k=a===h;return K(ae,{gap:2,children:[F(L,{...k&&{color:"cyan"},children:k?"\u276F":" "}),F(L,{bold:k,...k&&{color:"cyan"},children:u.isDefault?"Default":u.name}),F(L,{dimColor:!0,children:u.path})]},u.name)})}),F(ar,{text:"\u2191\u2193 to move \xB7 Enter to select \xB7 Ctrl+C to quit"})]}))}return g.type==="api-name-entry"?l(K(Pt,{children:[F(L,{bold:!0,children:"Plugin api_name"}),g.error!==void 0&&K(L,{color:"red",children:["Error: ",g.error]}),K(ae,{gap:1,children:[F(L,{color:"cyan",children:">"}),F(L,{children:g.buffer}),F(L,{color:"cyan",children:"\u2588"})]}),F(ar,{text:"Type the api_name \xB7 Enter to confirm \xB7 Ctrl+C to quit"})]})):g.type==="value-entry"?l(K(Pt,{children:[F(L,{bold:!0,children:"Secret value"}),g.error!==void 0&&K(L,{color:"red",children:["Error: ",g.error]}),K(ae,{gap:1,children:[F(L,{color:"cyan",children:">"}),F(L,{children:"\u2022".repeat(g.buffer.length)}),F(L,{color:"cyan",children:"\u2588"})]}),F(ar,{text:"Input hidden \xB7 Enter to encrypt \xB7 Ctrl+C to quit"})]})):g.type==="fetching-key"?l(K(ae,{gap:1,children:[F(me,{}),K(L,{children:["Fetching ",e.stage," public key for ",F(L,{bold:!0,children:P}),"\u2026"]})]})):g.type==="encrypting"?l(K(ae,{gap:1,children:[F(me,{}),F(L,{children:"Encrypting\u2026"})]})):g.type==="error"?l(K(ae,{gap:1,children:[F(L,{color:"red",children:"\u2717"}),F(L,{color:"red",children:g.message})]})):l(K(Pt,{children:[K(ae,{gap:1,children:[F(L,{color:"green",children:"\u2713"}),F(L,{bold:!0,children:"Encrypted secret ready"})]}),g.copied?F(L,{color:"green",children:"\u2713 Copied to clipboard \u2014 paste it into the secret value in your kizen.json."}):F(L,{dimColor:!0,children:"Paste this into the secret value in your kizen.json (re-run with --out <path> to save it to a file; selecting it here may capture line wraps):"}),F(L,{children:g.envelope})]}))};import{readFile as Ma,writeFile as Ha}from"fs/promises";import{join as Ua}from"path";function eo(e){return{encrypted:!0,value:e}}function to(e){return JSON.stringify(eo(e))}async function lr(e,t){await Ha(e,`${JSON.stringify(eo(t),null,2)}
458
+ `,"utf-8")}var Va="prod";function ro(e){return e==="dev"||e==="prod"}function no(e){return`Error: --stage must be "dev" or "prod" (got: "${e}")`}function oo(e){return{stage:e==="dev"||e==="prod"?e:Va,wasDefaulted:e===void 0}}function io(e){return`No --stage given; defaulting to ${e} encryption keys (pass --stage dev to override)
459
+ `}async function so(e=process.cwd()){try{let t=await Ma(Ua(e,"kizen.json"),"utf-8"),n=JSON.parse(t),o=Array.isArray(n)?n[0]:n,r=typeof o.api_name=="string"&&o.api_name!==""?o.api_name:void 0;return{...r!==void 0&&{apiName:r}}}catch{}return{}}function ao(e){return e.replace(/[\r\n]+$/,"")}async function lo(){let e=[];for await(let t of process.stdin)e.push(t);return Buffer.concat(e).toString("utf-8")}async function co(e,t,n,o,r){let i=t.credentials!==void 0?await r.loadCredentialsFromFile(t.credentials):await r.loadGlobalCredentials();if(i===null)throw new Error("No credentials found. Pass --credentials or create ~/.kizenappbuilder/credentials.json.");let p=t.apiName??n.apiName;if(p===void 0||p.trim()==="")throw new Error("api_name is required in non-interactive mode. Pass --api-name or run inside a plugin directory.");o&&r.writeStderr(io(e.stage));let f=t.value;if(f===void 0){if(r.stdinIsTTY())throw new Error('No secret provided and stdin is a terminal. Pass --value, or pipe the secret in (e.g. `printf %s "$SECRET" | npx --yes @kizenapps/cli encrypt \u2026`).');r.writeStderr(`Reading secret from stdin (pass --value to skip)\u2026
460
+ `),f=ao(await r.readStdin())}if(f==="")throw new Error("A secret value is required. Pass --value or pipe it via stdin.");let g=await r.encryptSecret(e,i,p.trim(),f);if(r.writeStdout(`${to(g)}
493
461
  `),t.out!==void 0)try{await r.writeEnvelopeFile(t.out,g),r.writeStderr(`Wrote encrypted envelope to ${t.out}
494
462
  `)}catch(m){r.writeStderr(`Error writing ${t.out}: ${m instanceof Error?m.message:String(m)}
495
- `),r.setExitCode(1)}}function co(e){e.command("encrypt").description("Encrypt a secret for a plugin against its encryption keys").option("--remote","encrypt via the plugin-wizard's remote API instead of on-machine").option("-c, --credentials <path>","path to a credentials JSON file").option("-a, --api-name <name>","plugin api_name the secret belongs to").option("-v, --value <value>","plaintext secret value to encrypt").option("-s, --stage <stage>","which encryption API to use: dev or prod (default: prod)").option("-o, --out <path>","also write the encrypted envelope to a file").action(async t=>{t.stage!==void 0&&!to(t.stage)&&(console.error(ro(t.stage)),process.exit(1));let o=t.apiName===void 0?await io():{},{stage:r,wasDefaulted:i}=no(t.stage),d={isRemote:t.remote===!0,stage:r};if(!process.stdin.isTTY||!process.stdout.isTTY){try{await lo(d,t,o,i,{loadCredentialsFromFile:be,loadGlobalCredentials:Z,encryptSecret:Tt,readStdin:ao,stdinIsTTY:()=>process.stdin.isTTY,writeStdout:m=>{process.stdout.write(m)},writeStderr:m=>{process.stderr.write(m)},writeEnvelopeFile:ar,setExitCode:m=>{process.exitCode=m}})}catch(m){console.error(`Error: ${m instanceof Error?m.message:String(m)}`),process.exit(1)}return}let f,{waitUntilExit:g}=ja(Oa(Zn,{ctx:d,stageDefaulted:i,onDone:m=>{f=m},...t.credentials!==void 0&&{credentialsPath:t.credentials},...t.apiName!==void 0&&{initialApiName:t.apiName},...o.apiName!==void 0&&{defaultApiName:o.apiName},...t.value!==void 0&&{initialValue:t.value}}),{exitOnCtrlC:!1});if(await g(),f!==void 0&&t.out!==void 0)try{await ar(t.out,f),process.stderr.write(`Wrote encrypted envelope to ${t.out}
496
- `)}catch(m){console.error(`Error writing ${t.out}: ${m instanceof Error?m.message:String(m)}`),process.exitCode=1}})}var $a=new Set(["phone","envelope","pen-nib","calendar-days","paperclip","file","clipboard","pen","tag","book","print","pen-to-square","folder","folder-open","thumbtack","globe","city","briefcase","compass","address-book","business-time","computer-classic","pen-fancy","badge-check","mug-saucer","landmark","chart-simple","envelopes","diagram-venn","calendar","pencil","phone-volume","copy","table","building","network-wired","address-card","tags","registered","signature","phone-office","projector","sitemap","marker","badge","wallet","copyright","bullseye","calculator","certificate","percent","eraser","file-spreadsheet","glasses","industry","vault","user-tie-hair-long","user-tie-hair","user-hair-mullet","trademark","timeline-arrow","timeline","table-tree","table-rows","table-pivot","table-layout","table-columns","stapler","square-poll-vertical","square-poll-horizontal","square-phone-flip","square-phone","square-pen","square-kanban","square-envelope","socks","slot-machine","signature-slash","signature-lock","shredder","scissors","scanner-image","scale-unbalanced-flip","scale-unbalanced","scale-balanced","router","rectangle-pro","print-slash","print-magnifying-glass","presentation-screen","podium","phone-slash","phone-intercom","phone-flip","person-chalkboard","pen-nib-slash","pen-clip","paste","paperclip-vertical","notebook","note-sticky","money-check-pen","money-check-dollar-pen","magnifying-glass-chart","magnifying-glass-arrow-right","list-tree","list-timeline","list-radio","list-dropdown","list-check","laptop-file","lamp-desk","keynote","industry-windows","inboxes","inbox-full","house-laptop","highlighter","folders","folder-xmark","folder-tree","folder-plus","folder-minus","folder-arrow-up","folder-arrow-down","floppy-disk-circle-xmark","floppy-disk-circle-arrow-right","floppy-disk","file-user","file-lines","file-circle-plus","file-circle-info","file-chart-pie","file-chart-column","fax","envelope-open","envelope-dot","envelope-circle-check","coffee-pot","cloud-word","clipboard-question","chart-user","chart-tree-map","chart-simple-horizontal","chart-pyramid","chart-pie-simple","chart-pie","chart-line-up","chart-line-down","chart-line","cake-candles","cabinet-filing","bullhorn","briefcase-blank","briefcase-arrow-right","brain-arrow-curved-right","boxes-packing","box-archive","book-section","bars-staggered","bars-progress","badge-percent","badge-dollar","arrows-to-eye","arrows-to-dot","arrows-spin","sparkles","megaphone","block-question","lightbulb-slash","comments-dollar","comments","bullseye-pointer","lightbulb","user-group-crown","user-crown","signal-stream-slash","signal-stream","rectangle-ad","ranking-star","person-rays","people-group","messages-dollar","message-dollar","magnifying-glass-location","magnifying-glass-dollar","lightbulb-on","lightbulb-exclamation","lightbulb-dollar","lightbulb-cfl-on","lightbulb-cfl","hundred-points","group-arrows-rotate","gift-card","filter-circle-dollar","envelopes-bulk","envelope-open-text","envelope-open-dollar","comment-dollar","chart-mixed","bullseye-arrow","star","heart","camera-retro","truck-fast","bell","cart-shopping","gift","barcode","bookmark","camera","thumbs-up","thumbs-down","key","truck","balloons","handshake","shop","shirt","bag-shopping","moped","cart-plus","credit-card","store","cash-register","booth-curtain","trophy","receipt","truck-container","truck-clock","truck-bolt","trophy-star","store-slash","store-lock","star-exclamation","shop-slash","shop-lock","rectangle-barcode","person-booth","nfc-trash","nfc-symbol","nfc-slash","nfc-signal","nfc-pen","nfc-magnifying-glass","nfc-lock","nfc","money-check-dollar","money-check","mobile-signal-out","mobile-signal","hexagon-vertical-nft-slanted","hexagon-vertical-nft","hexagon-image","hand-holding-box","gifts","gem","credit-card-front","credit-card-blank","cart-xmark","cart-shopping-fast","cart-minus","cart-circle-xmark","cart-circle-plus","cart-circle-exclamation","cart-circle-check","cart-circle-arrow-up","cart-circle-arrow-down","cart-arrow-up","cart-arrow-down","box-open-full","basket-shopping-simple","basket-shopping","barcode-scan","barcode-read","balloon","bags-shopping","bars","browser","chart-bar","cog","database","calendar-alt","play","kizen-k","add","book-alt","form-entity","arrows-to-circle","question-circle","chevron-down","chevron-up","window-restore","forward"]),La=[...$a].sort(),Ma=new Set(["kizen-k","form-entity"]),po=[...La,...[...Ma].sort()];function uo(e){e.command("icons").description("List all valid icon names accepted by toolbar items, pages, and adornments").action(()=>{for(let t of po)console.log(t)})}import{mkdir as Ka,writeFile as So,readFile as Ga}from"fs/promises";import{join as Pt}from"path";var za=new Set(["developer_business_id"]);function Ha(e){return Array.isArray(e)?e.map(t=>{if(typeof t!="object"||t===null)return t;let n=t;if(typeof n.auth_credentials!="object"||n.auth_credentials===null)return n;let o=Object.fromEntries(Object.keys(n.auth_credentials).map(r=>[r,"*****"]));return{...n,auth_credentials:o}}):e}function mo(e){let t={name:"",children:new Map,isFile:!1,filePath:""};for(let n of e){let o=n.path.split("/"),r=t;o.forEach((i,d)=>{r.children.has(i)||r.children.set(i,{name:i,children:new Map,isFile:d===o.length-1,filePath:o.slice(0,d+1).join("/")});let f=r.children.get(i);f&&(r=f)})}return t}function go(e){return[...e.children.values()].sort((t,n)=>t.isFile!==n.isFile?t.isFile?1:-1:t.name.localeCompare(n.name))}function lr(e){return"file-"+e.replace(/[^a-zA-Z0-9]/g,"-")}function le(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}function ho(e){let t=e.lastIndexOf(".");return t>=0?e.slice(t).toLowerCase():""}var Ua={".ts":"typescript",".tsx":"typescript",".js":"javascript",".jsx":"javascript",".mjs":"javascript",".cjs":"javascript",".json":"json",".css":"css",".scss":"scss",".html":"html",".htm":"html",".md":"markdown",".mdx":"markdown",".py":"python",".sh":"bash",".yml":"yaml",".yaml":"yaml",".xml":"xml",".toml":"toml"};function Va(e){return Ua[ho(e)]??""}function fo(e){let t=[...e.matchAll(/`+/g)].reduce((n,o)=>Math.max(n,o[0].length),0);return"`".repeat(Math.max(3,t+1))}function yo(e,t=""){let n=go(e);return n.map((o,r)=>{let i=r===n.length-1,d=i?"\u2514\u2500\u2500 ":"\u251C\u2500\u2500 ",f=i?" ":"\u2502 ";return o.isFile?`${t}${d}${o.name}`:`${t}${d}${o.name}/
497
- ${yo(o,t+f)}`}).join(`
498
- `)}var qa=/(^|\/)licen[cs]e(\.md|\.txt)?$/i;function bo(e){return e.filter(t=>t.path!=="kizen.json"&&t.path!=="plugin-report.html"&&!qa.test(t.path))}function xo(e){return Object.fromEntries(Object.entries(e).filter(([t])=>!za.has(t)).map(([t,n])=>[t,t==="services"?Ha(n):n]))}var Ja={".png":"image/png",".svg":"image/svg+xml",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".webp":"image/webp"};function vo(e){return`<ul>${go(e).map(o=>o.isFile?`<li class="tf"><a href="#${lr(o.filePath)}" data-id="${lr(o.filePath)}">${le(o.name)}</a></li>`:`<li class="td"><span class="dn">${le(o.name)}/</span>${vo(o)}</li>`).join("")}</ul>`}function Wa(e){let t;return e.base64Image!==void 0?t=`<img src="data:${Ja[ho(e.path)]??"image/png"};base64,${e.base64Image}" alt="${le(e.path)}" style="max-width:100%">`:e.binaryData!==void 0?t=`<p class="bin">[Binary file: ${String(e.binaryData.length)} bytes]</p>`:t=`<pre><code>${le(e.content)}</code></pre>`,`<section id="${lr(e.path)}"><h2 class="fp">${le(e.path)}</h2><div class="fb">${t}</div></section>`}function wo(e,t){let n=xo(e),o=typeof e.name=="string"?e.name:"Plugin",r=typeof e.version=="string"?e.version:"",i=typeof e.description=="string"?e.description:"",d=bo(t),f=[];f.push(`# ${o}${r?` v${r}`:""}`),i&&f.push("",i);let g=JSON.stringify(n,null,2),m=fo(g);f.push("","## Configuration (`kizen.json`)","",`${m}json`,g,m),f.push("","## File Tree","","```",yo(mo(d)),"```"),f.push("","## Files");for(let b of d)if(f.push("",`### \`${b.path}\``,""),b.base64Image!==void 0)f.push(`[Image file: ${b.path}]`);else if(b.binaryData!==void 0)f.push(`[Binary file: ${String(b.binaryData.length)} bytes]`);else{let T=fo(b.content);f.push(`${T}${Va(b.path)}`,b.content,T)}return f.join(`
463
+ `),r.setExitCode(1)}}function po(e){e.command("encrypt").description("Encrypt a secret for a plugin against its encryption keys").option("--remote","encrypt via the plugin-wizard's remote API instead of on-machine").option("-c, --credentials <path>","path to a credentials JSON file").option("-a, --api-name <name>","plugin api_name the secret belongs to").option("-v, --value <value>","plaintext secret value to encrypt").option("-s, --stage <stage>","which encryption API to use: dev or prod (default: prod)").option("-o, --out <path>","also write the encrypted envelope to a file").action(async t=>{t.stage!==void 0&&!ro(t.stage)&&(console.error(no(t.stage)),process.exit(1));let o=t.apiName===void 0?await so():{},{stage:r,wasDefaulted:i}=oo(t.stage),p={isRemote:t.remote===!0,stage:r};if(!process.stdin.isTTY||!process.stdout.isTTY){try{await co(p,t,o,i,{loadCredentialsFromFile:ve,loadGlobalCredentials:Z,encryptSecret:Et,readStdin:lo,stdinIsTTY:()=>process.stdin.isTTY,writeStdout:m=>{process.stdout.write(m)},writeStderr:m=>{process.stderr.write(m)},writeEnvelopeFile:lr,setExitCode:m=>{process.exitCode=m}})}catch(m){console.error(`Error: ${m instanceof Error?m.message:String(m)}`),process.exit(1)}return}let f,{waitUntilExit:g}=Ja(qa(Qn,{ctx:p,stageDefaulted:i,onDone:m=>{f=m},...t.credentials!==void 0&&{credentialsPath:t.credentials},...t.apiName!==void 0&&{initialApiName:t.apiName},...o.apiName!==void 0&&{defaultApiName:o.apiName},...t.value!==void 0&&{initialValue:t.value}}),{exitOnCtrlC:!1});if(await g(),f!==void 0&&t.out!==void 0)try{await lr(t.out,f),process.stderr.write(`Wrote encrypted envelope to ${t.out}
464
+ `)}catch(m){console.error(`Error writing ${t.out}: ${m instanceof Error?m.message:String(m)}`),process.exitCode=1}})}var Wa=new Set(["phone","envelope","pen-nib","calendar-days","paperclip","file","clipboard","pen","tag","book","print","pen-to-square","folder","folder-open","thumbtack","globe","city","briefcase","compass","address-book","business-time","computer-classic","pen-fancy","badge-check","mug-saucer","landmark","chart-simple","envelopes","diagram-venn","calendar","pencil","phone-volume","copy","table","building","network-wired","address-card","tags","registered","signature","phone-office","projector","sitemap","marker","badge","wallet","copyright","bullseye","calculator","certificate","percent","eraser","file-spreadsheet","glasses","industry","vault","user-tie-hair-long","user-tie-hair","user-hair-mullet","trademark","timeline-arrow","timeline","table-tree","table-rows","table-pivot","table-layout","table-columns","stapler","square-poll-vertical","square-poll-horizontal","square-phone-flip","square-phone","square-pen","square-kanban","square-envelope","socks","slot-machine","signature-slash","signature-lock","shredder","scissors","scanner-image","scale-unbalanced-flip","scale-unbalanced","scale-balanced","router","rectangle-pro","print-slash","print-magnifying-glass","presentation-screen","podium","phone-slash","phone-intercom","phone-flip","person-chalkboard","pen-nib-slash","pen-clip","paste","paperclip-vertical","notebook","note-sticky","money-check-pen","money-check-dollar-pen","magnifying-glass-chart","magnifying-glass-arrow-right","list-tree","list-timeline","list-radio","list-dropdown","list-check","laptop-file","lamp-desk","keynote","industry-windows","inboxes","inbox-full","house-laptop","highlighter","folders","folder-xmark","folder-tree","folder-plus","folder-minus","folder-arrow-up","folder-arrow-down","floppy-disk-circle-xmark","floppy-disk-circle-arrow-right","floppy-disk","file-user","file-lines","file-circle-plus","file-circle-info","file-chart-pie","file-chart-column","fax","envelope-open","envelope-dot","envelope-circle-check","coffee-pot","cloud-word","clipboard-question","chart-user","chart-tree-map","chart-simple-horizontal","chart-pyramid","chart-pie-simple","chart-pie","chart-line-up","chart-line-down","chart-line","cake-candles","cabinet-filing","bullhorn","briefcase-blank","briefcase-arrow-right","brain-arrow-curved-right","boxes-packing","box-archive","book-section","bars-staggered","bars-progress","badge-percent","badge-dollar","arrows-to-eye","arrows-to-dot","arrows-spin","sparkles","megaphone","block-question","lightbulb-slash","comments-dollar","comments","bullseye-pointer","lightbulb","user-group-crown","user-crown","signal-stream-slash","signal-stream","rectangle-ad","ranking-star","person-rays","people-group","messages-dollar","message-dollar","magnifying-glass-location","magnifying-glass-dollar","lightbulb-on","lightbulb-exclamation","lightbulb-dollar","lightbulb-cfl-on","lightbulb-cfl","hundred-points","group-arrows-rotate","gift-card","filter-circle-dollar","envelopes-bulk","envelope-open-text","envelope-open-dollar","comment-dollar","chart-mixed","bullseye-arrow","star","heart","camera-retro","truck-fast","bell","cart-shopping","gift","barcode","bookmark","camera","thumbs-up","thumbs-down","key","truck","balloons","handshake","shop","shirt","bag-shopping","moped","cart-plus","credit-card","store","cash-register","booth-curtain","trophy","receipt","truck-container","truck-clock","truck-bolt","trophy-star","store-slash","store-lock","star-exclamation","shop-slash","shop-lock","rectangle-barcode","person-booth","nfc-trash","nfc-symbol","nfc-slash","nfc-signal","nfc-pen","nfc-magnifying-glass","nfc-lock","nfc","money-check-dollar","money-check","mobile-signal-out","mobile-signal","hexagon-vertical-nft-slanted","hexagon-vertical-nft","hexagon-image","hand-holding-box","gifts","gem","credit-card-front","credit-card-blank","cart-xmark","cart-shopping-fast","cart-minus","cart-circle-xmark","cart-circle-plus","cart-circle-exclamation","cart-circle-check","cart-circle-arrow-up","cart-circle-arrow-down","cart-arrow-up","cart-arrow-down","box-open-full","basket-shopping-simple","basket-shopping","barcode-scan","barcode-read","balloon","bags-shopping","bars","browser","chart-bar","cog","database","calendar-alt","play","kizen-k","add","book-alt","form-entity","arrows-to-circle","question-circle","chevron-down","chevron-up","window-restore","forward"]),Ga=[...Wa].sort(),Ka=new Set(["kizen-k","form-entity"]),uo=[...Ga,...[...Ka].sort()];function fo(e){e.command("icons").description("List all valid icon names accepted by toolbar items, pages, and adornments").action(()=>{for(let t of uo)console.log(t)})}import{mkdir as nl,writeFile as To,readFile as ol}from"fs/promises";import{join as It}from"path";var Ya=new Set(["developer_business_id"]);function Xa(e){return Array.isArray(e)?e.map(t=>{if(typeof t!="object"||t===null)return t;let n=t;if(typeof n.auth_credentials!="object"||n.auth_credentials===null)return n;let o=Object.fromEntries(Object.keys(n.auth_credentials).map(r=>[r,"*****"]));return{...n,auth_credentials:o}}):e}function go(e){let t={name:"",children:new Map,isFile:!1,filePath:""};for(let n of e){let o=n.path.split("/"),r=t;o.forEach((i,p)=>{r.children.has(i)||r.children.set(i,{name:i,children:new Map,isFile:p===o.length-1,filePath:o.slice(0,p+1).join("/")});let f=r.children.get(i);f&&(r=f)})}return t}function ho(e){return[...e.children.values()].sort((t,n)=>t.isFile!==n.isFile?t.isFile?1:-1:t.name.localeCompare(n.name))}function cr(e){return"file-"+e.replace(/[^a-zA-Z0-9]/g,"-")}function le(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}function yo(e){let t=e.lastIndexOf(".");return t>=0?e.slice(t).toLowerCase():""}var Za={".ts":"typescript",".tsx":"typescript",".js":"javascript",".jsx":"javascript",".mjs":"javascript",".cjs":"javascript",".json":"json",".css":"css",".scss":"scss",".html":"html",".htm":"html",".md":"markdown",".mdx":"markdown",".py":"python",".sh":"bash",".yml":"yaml",".yaml":"yaml",".xml":"xml",".toml":"toml"};function Qa(e){return Za[yo(e)]??""}function mo(e){let t=[...e.matchAll(/`+/g)].reduce((n,o)=>Math.max(n,o[0].length),0);return"`".repeat(Math.max(3,t+1))}function bo(e,t=""){let n=ho(e);return n.map((o,r)=>{let i=r===n.length-1,p=i?"\u2514\u2500\u2500 ":"\u251C\u2500\u2500 ",f=i?" ":"\u2502 ";return o.isFile?`${t}${p}${o.name}`:`${t}${p}${o.name}/
465
+ ${bo(o,t+f)}`}).join(`
466
+ `)}var el=/(^|\/)licen[cs]e(\.md|\.txt)?$/i;function xo(e){return e.filter(t=>t.path!=="kizen.json"&&t.path!=="plugin-report.html"&&!el.test(t.path))}function vo(e){return Object.fromEntries(Object.entries(e).filter(([t])=>!Ya.has(t)).map(([t,n])=>[t,t==="services"?Xa(n):n]))}var tl={".png":"image/png",".svg":"image/svg+xml",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".webp":"image/webp"};function wo(e){return`<ul>${ho(e).map(o=>o.isFile?`<li class="tf"><a href="#${cr(o.filePath)}" data-id="${cr(o.filePath)}">${le(o.name)}</a></li>`:`<li class="td"><span class="dn">${le(o.name)}/</span>${wo(o)}</li>`).join("")}</ul>`}function rl(e){let t;return e.base64Image!==void 0?t=`<img src="data:${tl[yo(e.path)]??"image/png"};base64,${e.base64Image}" alt="${le(e.path)}" style="max-width:100%">`:e.binaryData!==void 0?t=`<p class="bin">[Binary file: ${String(e.binaryData.length)} bytes]</p>`:t=`<pre><code>${le(e.content)}</code></pre>`,`<section id="${cr(e.path)}"><h2 class="fp">${le(e.path)}</h2><div class="fb">${t}</div></section>`}function Co(e,t){let n=vo(e),o=typeof e.name=="string"?e.name:"Plugin",r=typeof e.version=="string"?e.version:"",i=typeof e.description=="string"?e.description:"",p=xo(t),f=[];f.push(`# ${o}${r?` v${r}`:""}`),i&&f.push("",i);let g=JSON.stringify(n,null,2),m=mo(g);f.push("","## Configuration (`kizen.json`)","",`${m}json`,g,m),f.push("","## File Tree","","```",bo(go(p)),"```"),f.push("","## Files");for(let y of p)if(f.push("",`### \`${y.path}\``,""),y.base64Image!==void 0)f.push(`[Image file: ${y.path}]`);else if(y.binaryData!==void 0)f.push(`[Binary file: ${String(y.binaryData.length)} bytes]`);else{let T=mo(y.content);f.push(`${T}${Qa(y.path)}`,y.content,T)}return f.join(`
499
467
  `)+`
500
- `}function Co(e,t){let n=xo(e),o=typeof e.name=="string"?e.name:"Plugin",r=typeof e.version=="string"?e.version:"",i=typeof e.description=="string"?e.description:"",d=bo(t),f=vo(mo(d)),g=d.map(Wa).join(`
468
+ `}function So(e,t){let n=vo(e),o=typeof e.name=="string"?e.name:"Plugin",r=typeof e.version=="string"?e.version:"",i=typeof e.description=="string"?e.description:"",p=xo(t),f=wo(go(p)),g=p.map(rl).join(`
501
469
  `);return`<!DOCTYPE html>
502
470
  <html lang="en">
503
471
  <head>
@@ -563,7 +531,9 @@ ${g}
563
531
  })();
564
532
  </script>
565
533
  </body>
566
- </html>`}var To=Pt(Pe,"examples");function _o(e){e.command("report").description("Generate a self-contained HTML report of the plugin").option("-o, --output <path>",`output file path (default: ${To}/<api_name>.html)`).action(async t=>{let n=process.cwd(),o;try{let g=await Ga(Pt(n,"kizen.json"),"utf-8"),m=JSON.parse(g);o=Array.isArray(m)?m[0]:m}catch{console.error("Error: kizen.json not found. Run this command from a plugin directory."),process.exit(1)}let r=typeof o.api_name=="string"?o.api_name:"plugin",i=t.output??Pt(To,`${r}.html`),d=i.replace(/\.html$/,".md"),f=await rt(n,{detectBinaryByContent:!0});await Ka(Pt(i,".."),{recursive:!0}),await Promise.all([So(i,Co(o,f),"utf-8"),So(d,wo(o,f),"utf-8")]),console.log(`Plugin report written to:
534
+ </html>`}var Eo=It(Ne,"examples");function _o(e){e.command("report").description("Generate a self-contained HTML report of the plugin").option("-o, --output <path>",`output file path (default: ${Eo}/<api_name>.html)`).action(async t=>{let n=process.cwd(),o;try{let g=await ol(It(n,"kizen.json"),"utf-8"),m=JSON.parse(g);o=Array.isArray(m)?m[0]:m}catch{console.error("Error: kizen.json not found. Run this command from a plugin directory."),process.exit(1)}let r=typeof o.api_name=="string"?o.api_name:"plugin",i=t.output??It(Eo,`${r}.html`),p=i.replace(/\.html$/,".md"),f=await nt(n,{detectBinaryByContent:!0});await nl(It(i,".."),{recursive:!0}),await Promise.all([To(i,So(o,f),"utf-8"),To(p,Co(o,f),"utf-8")]),console.log(`Plugin report written to:
567
535
  ${i}
568
- ${d}`)})}function tl(){let e=Za(Xa(Qa(import.meta.url)),"..","package.json");return JSON.parse(Ya(e,"utf-8")).version}function Eo(){let e=new el;return e.name("appbuilder").description("Kizen plugin app builder").version(tl()),cn(e),Tr(e),qn(e),co(e),_o(e),uo(e),e}Eo().parse();
536
+ ${p}`)})}import{mkdir as il,readFile as sl,writeFile as al}from"fs/promises";import{dirname as ll,join as cl}from"path";async function dl(e){try{return await sl(e,"utf-8")}catch(t){if(t.code==="ENOENT")return;throw t}}async function pl(e,t,n){let o=cl(e,...t.path.split("/")),r=await dl(o);if(r===t.content)return{path:t.path,status:"unchanged"};let i=r===void 0?"created":"updated";return n||(await il(ll(o),{recursive:!0}),await al(o,t.content,"utf-8")),{path:t.path,status:i}}async function ko(e,t={}){if(await ye(e)!=="has-manifest")throw new Error(`No kizen.json found in ${e}`);let n=t.dryRun===!0,o=await Promise.all(lt().map(r=>pl(e,r,n)));return n||he(e),{files:o}}function Po(e){e.command("setup-copilot").description("Add or refresh the Copilot code-review setup in an existing plugin repo").option("--dry-run","report what would change without writing anything").action(async t=>{let n=process.cwd();if(await ye(n)!=="has-manifest"){console.error(`No kizen.json found in ${n} \u2014 run "appbuilder setup-copilot" from the root of a plugin repo.`),process.exitCode=1;return}let o=t.dryRun===!0;try{let r=await ko(n,{dryRun:o});for(let i of r.files)console.log(`${i.status.padEnd(9)} ${i.path}`);if(o){console.log(`
537
+ Dry run \u2014 no files and no .gitignore entries were written.`);return}console.log(`
538
+ Ensured .gitignore ignores .kizenapp/ and .copilot-docs/.`),console.log("The code review workflow only takes effect once it is on the repository default branch \u2014 merge it before expecting reviews to cite .copilot-docs/.")}catch(r){console.error(`Error: ${r instanceof Error?r.message:String(r)}`),process.exitCode=1}})}function yl(){let e=ml(fl(gl(import.meta.url)),"..","package.json");return JSON.parse(ul(e,"utf-8")).version}function Io(){let e=new hl;return e.name("appbuilder").description("Kizen plugin app builder").version(yl()),dn(e),Po(e),Er(e),Jn(e),po(e),_o(e),fo(e),e}Io().parse();
569
539
  //# sourceMappingURL=index.js.map