@ciandt-flow/cli 1.0.1 → 1.0.2

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 (2) hide show
  1. package/dist/index.js +30 -30
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -1,84 +1,84 @@
1
1
  #!/usr/bin/env node
2
- import {Box,Text,render,useInput}from'ink';import xo,{useMemo,useEffect,useState,useCallback,useRef}from'react';import {jsxs,jsx,Fragment}from'react/jsx-runtime';import {create}from'zustand';import eo,{HTTPError}from'ky';import Wn from'conf';import T,{readFileSync,existsSync,chmodSync,realpathSync}from'fs';import mo from'ink-big-text';import po from'ink-gradient';import*as I from'path';import I__default,{join}from'path';import h from'chalk';import $o from'ink-spinner';import*as it from'os';import it__default,{homedir}from'os';import*as R from'fs/promises';import _o from'extract-zip';import qo from'proper-lockfile';import {randomUUID}from'crypto';import {Command}from'commander';var zn=16;function gt({label:e,value:t,onChange:n,masked:o=false,isActive:r,error:i}){useInput((a,l)=>{l.backspace||l.delete?n(t.slice(0,-1)):a&&!l.ctrl&&!l.meta&&!l.escape&&!l.return&&!l.tab&&!l.upArrow&&!l.downArrow&&!l.leftArrow&&!l.rightArrow&&n(t+a);},{isActive:r});let s=o?"\u2022".repeat(t.length):t;return jsxs(Box,{flexDirection:"column",children:[jsxs(Box,{children:[jsx(Text,{color:r?"cyan":"gray",children:r?"\u25B8 ":" "}),jsx(Text,{color:r?"white":"gray",bold:r,children:e.padEnd(zn)}),jsx(Text,{color:r?"cyan":"gray",children:s}),r&&jsx(Text,{color:"cyan",children:"\u2588"})]}),i&&jsx(Box,{paddingLeft:3,children:jsxs(Text,{color:"red",children:["\u26A0 ",i]})})]})}var L=create(e=>({credentials:null,isAuthenticated:false,justAuthenticated:false,setCredentials:t=>e({credentials:t,isAuthenticated:true}),clearCredentials:()=>e({credentials:null,isAuthenticated:false,justAuthenticated:false}),setJustAuthenticated:t=>e({justAuthenticated:t})}));var m=create(e=>({activeTab:"discover",focus:"list",selectedIndex:0,actionMenuOpen:false,notification:null,loading:false,loadingMessage:"",catalogError:null,setActiveTab:t=>e({activeTab:t}),setFocus:t=>e({focus:t}),setSelectedIndex:t=>e({selectedIndex:t}),setActionMenuOpen:t=>e({actionMenuOpen:t}),showNotification:(t,n)=>e({notification:{message:t,type:n}}),clearNotification:()=>e({notification:null}),setLoading:(t,n="")=>e({loading:t,loadingMessage:t?n:""}),setCatalogError:t=>e({catalogError:t})}));var ge="FLOW",J="flow-skills";var B=new Wn({projectName:ge});function ht(){try{chmodSync(B.path,384);}catch{}}function P(){let e=B.get("credentials");if(!e)return null;try{return JSON.parse(e)}catch{return null}}function yt(e){B.set("credentials",JSON.stringify(e)),ht();}function wt(){B.delete("credentials"),B.delete("tokenCache");}function xt(){return B.path}function bt(e){B.set("tokenCache",{accessToken:e.accessToken,expiresAt:e.expiresAt}),ht();}function _e(){let e=B.get("tokenCache");return e?{accessToken:e.accessToken,expiresAt:e.expiresAt}:null}function N(){let e=_e();return e?new Date(e.expiresAt)>new Date:false}var Qn=[/^localhost\.?$/i,/^127\./,/^10\./,/^172\.(1[6-9]|2\d|3[01])\./,/^192\.168\./,/^169\.254\./,/^::1$/,/^\[::1\]$/,/^\[::ffff:/i,/^0\.0\.0\.0$/,/^\[f[cd]/i,/^\[fe80:/i,/^metadata\.google\.internal\.?$/i,/^metadata\.azure\.internal\.?$/i];function Yn(e){return Qn.some(t=>t.test(e))}function Zn(e,t){let n=process.env[e]??t;if(!n)throw new Error(`Missing required environment variable: ${e}`);return n}function he(e,t){let n=Zn(e,t),o;try{o=new URL(n);}catch{throw new Error(`${e} must be a valid URL. Got: "${n}"`)}if(o.protocol!=="https:")throw new Error(`${e} must be an HTTPS URL. Got protocol: "${o.protocol}"`);if(o.username||o.password)throw new Error(`${e} must not contain embedded credentials (user:pass@host is not allowed)`);if(Yn(o.hostname))throw new Error(`${e} must not point to a private/loopback address. Got: "${o.hostname}"`);return n}var no=/^[a-z0-9][a-z0-9-]{0,62}[a-z0-9]$|^[a-z0-9]$/;function oo(e){if(!no.test(e))throw new Error(`Invalid tenant value: "${e}". Tenant must be lowercase alphanumeric and hyphens (1-64 chars).`)}function ro(e){if(e instanceof HTTPError){let t=e.response.status;return t===401||t===403||t===500?new Error("Invalid credentials"):t>=400&&t<500?new Error("Authentication request was rejected"):new Error("Authentication service unavailable, please try again later")}return e instanceof Error?e:new Error("Authentication failed")}async function ne(e){let t=he("AUTH_ENGINE_URL","https://dev.flow.ciandt.com/auth-engine-api/v2/api-key/token");oo(e.tenant);let n;try{n=await eo.post(t,{headers:{FlowTenant:e.tenant},json:{clientSecret:e.clientSecret}}).json();}catch(r){throw ro(r)}let o=n.expires_at??new Date(Date.now()+(n.expires_in??3600)*1e3).toISOString();yt(e),bt({accessToken:n.access_token,expiresAt:o});}async function vt(){if(N()){let e=_e();if(!e)throw new Error("Flow CLI not configured. Run: npx @flow/cli auth login");return e.accessToken}throw new Error("Flow CLI not configured or token expired. Run: npx @flow/cli auth login")}var A=["clientId","clientSecret","tenant"],so={clientId:"Client ID",clientSecret:"Client Secret",tenant:"Tenant"};function It(){let[e,t]=useState({clientId:"",clientSecret:"",tenant:""}),[n,o]=useState("clientId"),[r,i]=useState({}),[s,a]=useState(null),[l,d]=useState(false),{setCredentials:g,setJustAuthenticated:O}=L(),{setFocus:F}=m();useInput((c,p)=>{if(!l){if(p.shift&&p.tab){let f=A.indexOf(n);f>0&&o(A[f-1]);}else if(p.tab){let f=A.indexOf(n);f<A.length-1&&o(A[f+1]);}else if(p.return)if(n==="tenant")x();else {let f=A.indexOf(n);o(A[f+1]);}}},{isActive:true});let x=async()=>{let c={};for(let p of A)e[p].trim()||(c[p]="This field is required");if(Object.keys(c).length>0){i(c);let p=A.find(f=>c[f]);p&&o(p);return}d(true),a(null);try{await ne(e);let{clientSecret:p,...f}=e;g(f),O(!0),F("list");}catch(p){a(p instanceof Error?p.message:"Authentication failed");}finally{d(false),t(p=>({...p,clientSecret:""}));}},$=c=>p=>{t(f=>({...f,[c]:p})),r[c]&&i(f=>({...f,[c]:void 0}));};return jsxs(Box,{flexDirection:"column",padding:2,children:[jsx(Box,{marginBottom:1,children:jsxs(Text,{bold:true,color:"cyan",children:[ge," \u2014 Initial Setup"]})}),jsx(Box,{flexDirection:"column",children:A.map(c=>jsx(Box,{marginBottom:1,children:jsx(gt,{label:so[c],value:e[c],onChange:$(c),masked:c==="clientSecret",isActive:n===c&&!l,error:r[c]})},c))}),l&&jsx(Box,{marginTop:1,children:jsx(Text,{color:"cyan",children:"Authenticating..."})}),s&&jsx(Box,{marginTop:1,children:jsxs(Text,{color:"red",children:["\u26A0 ",s]})}),jsx(Box,{marginTop:1,children:jsx(Text,{dimColor:true,children:"Tab next field \xB7 Enter confirm"})})]})}var co=JSON.parse(readFileSync(join(import.meta.dirname,"..","package.json"),"utf8")),we=co.version;function St(){return jsxs(Box,{flexDirection:"column",alignItems:"center",children:[jsx(po,{name:"morning",children:jsx(mo,{text:"FLOW",font:"block"})}),jsx(Box,{marginTop:-1,marginBottom:1,children:jsxs(Text,{dimColor:true,children:["Marketplace \xB7 v",we]})})]})}var ze={discover:"Discover",installed:"Installed"},fo=Object.keys(ze);function Et(){let e=m(t=>t.activeTab);return jsxs(Box,{paddingX:1,paddingBottom:1,children:[fo.map(t=>jsx(Box,{marginRight:2,children:t===e?jsx(Text,{bold:true,underline:true,color:"cyan",children:ze[t]}):jsx(Text,{dimColor:true,children:ze[t]})},t)),jsx(Text,{dimColor:true,children:"(Tab to cycle)"})]})}var E=create(e=>({query:"",setQuery:t=>e({query:t}),resetQuery:()=>e({query:""})}));function Rt(){let e=m(o=>o.focus),t=E(o=>o.query),n=e==="search";return jsxs(Box,{borderStyle:"single",borderTop:false,borderBottom:true,borderLeft:false,borderRight:false,paddingX:1,marginX:1,marginBottom:1,children:[jsx(Text,{color:n?"cyan":"gray",children:"\u03C1 "}),n?jsxs(Fragment,{children:[jsx(Text,{color:"white",children:t}),jsx(Text,{color:"cyan",children:"\u2588"})]}):jsx(Text,{dimColor:true,children:t||"Search..."})]})}function w(e){return e.replace(/\x1b\[[0-9;:<=>?]*[ -/]*[@-~]/g,"").replace(/\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)/g,"").replace(/\x1b./g,"").replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g,"")}function z(e){process.stdout.write(h.green(` \u2713 ${w(e)}
3
- `));}function v(e){process.stderr.write(h.red(` \u2717 ${w(e)}
2
+ import {Box,Text,render,useInput}from'ink';import Ir,{useMemo,useEffect,useState,useCallback,useRef}from'react';import {jsxs,jsx,Fragment}from'react/jsx-runtime';import {create}from'zustand';import rr,{HTTPError}from'ky';import Yn from'conf';import T,{readFileSync,existsSync,chmodSync,realpathSync}from'fs';import fr from'ink-big-text';import gr from'ink-gradient';import*as v from'path';import v__default,{join}from'path';import h from'chalk';import Mr from'ink-spinner';import*as it from'os';import it__default,{homedir}from'os';import*as R from'fs/promises';import Hr from'extract-zip';import Jr from'proper-lockfile';import {randomUUID}from'crypto';import {Command}from'commander';var Wn=16;function gt({label:e,value:t,onChange:n,masked:r=false,isActive:o,error:i}){let s=useRef(t);useEffect(()=>{s.current=t;},[t]),useInput((d,c)=>{if(c.backspace||c.delete){let f=s.current.slice(0,-1);s.current=f,n(f);}else if(d&&!c.ctrl&&!c.meta&&!c.escape&&!c.return&&!c.tab&&!c.upArrow&&!c.downArrow&&!c.leftArrow&&!c.rightArrow){let f=s.current+d;s.current=f,n(f);}},{isActive:o});let a=r?"\u2022".repeat(t.length):t;return jsxs(Box,{flexDirection:"column",children:[jsxs(Box,{children:[jsx(Text,{color:o?"cyan":"gray",children:o?"\u25B8 ":" "}),jsx(Text,{color:o?"white":"gray",bold:o,children:e.padEnd(Wn)}),jsx(Text,{color:o?"cyan":"gray",children:a}),o&&jsx(Text,{color:"cyan",children:"\u2588"})]}),i&&jsx(Box,{paddingLeft:3,children:jsxs(Text,{color:"red",children:["\u26A0 ",i]})})]})}var L=create(e=>({credentials:null,isAuthenticated:false,justAuthenticated:false,setCredentials:t=>e({credentials:t,isAuthenticated:true}),clearCredentials:()=>e({credentials:null,isAuthenticated:false,justAuthenticated:false}),setJustAuthenticated:t=>e({justAuthenticated:t})}));var m=create(e=>({activeTab:"discover",focus:"list",selectedIndex:0,actionMenuOpen:false,notification:null,loading:false,loadingMessage:"",catalogError:null,setActiveTab:t=>e({activeTab:t}),setFocus:t=>e({focus:t}),setSelectedIndex:t=>e({selectedIndex:t}),setActionMenuOpen:t=>e({actionMenuOpen:t}),showNotification:(t,n)=>e({notification:{message:t,type:n}}),clearNotification:()=>e({notification:null}),setLoading:(t,n="")=>e({loading:t,loadingMessage:t?n:""}),setCatalogError:t=>e({catalogError:t})}));var ge="FLOW",J="flow-skills";var F=new Yn({projectName:ge});function ht(){try{chmodSync(F.path,384);}catch{}}function S(){let e=F.get("credentials");if(!e)return null;try{return JSON.parse(e)}catch{return null}}function yt(e){F.set("credentials",JSON.stringify(e)),ht();}function wt(){F.delete("credentials"),F.delete("tokenCache");}function xt(){return F.path}function bt(e){F.set("tokenCache",{accessToken:e.accessToken,expiresAt:e.expiresAt}),ht();}function Ke(){let e=F.get("tokenCache");return e?{accessToken:e.accessToken,expiresAt:e.expiresAt}:null}function B(){let e=Ke();return e?new Date(e.expiresAt)>new Date:false}var er=[/^localhost\.?$/i,/^127\./,/^10\./,/^172\.(1[6-9]|2\d|3[01])\./,/^192\.168\./,/^169\.254\./,/^::1$/,/^\[::1\]$/,/^\[::ffff:/i,/^0\.0\.0\.0$/,/^\[f[cd]/i,/^\[fe80:/i,/^metadata\.google\.internal\.?$/i,/^metadata\.azure\.internal\.?$/i];function tr(e){return er.some(t=>t.test(e))}function nr(e,t){let n=process.env[e]??t;if(!n)throw new Error(`Missing required environment variable: ${e}`);return n}function he(e,t){let n=nr(e,t),r;try{r=new URL(n);}catch{throw new Error(`${e} must be a valid URL. Got: "${n}"`)}if(r.protocol!=="https:")throw new Error(`${e} must be an HTTPS URL. Got protocol: "${r.protocol}"`);if(r.username||r.password)throw new Error(`${e} must not contain embedded credentials (user:pass@host is not allowed)`);if(tr(r.hostname))throw new Error(`${e} must not point to a private/loopback address. Got: "${r.hostname}"`);return n}var ir=/^[a-z0-9][a-z0-9-]{0,62}[a-z0-9]$|^[a-z0-9]$/;function sr(e){if(!ir.test(e))throw new Error(`Invalid tenant value: "${e}". Tenant must be lowercase alphanumeric and hyphens (1-64 chars).`)}var It={INVALID_CLIENT_SECRET:"Invalid Client Secret \u2014 check the value and try again",INVALID_CLIENT_ID:"Invalid Client ID \u2014 check the value and try again",INVALID_TENANT:"Invalid Tenant \u2014 check the value and try again",TENANT_NOT_FOUND:"Tenant not found \u2014 verify the tenant identifier"};async function ar(e){if(e instanceof HTTPError){let t=e.response.status,n="";try{let r=await e.response.text(),o=JSON.parse(r);typeof o.error=="string"&&(n=o.error);}catch{}return n&&It[n]?new Error(It[n]):t===401||t===403||t===500?new Error("Invalid credentials"):t>=400&&t<500?new Error("Authentication request was rejected"):new Error("Authentication service unavailable, please try again later")}return e instanceof Error?e:new Error("Authentication failed")}async function ne(e){let t=he("AUTH_ENGINE_URL","https://dev.flow.ciandt.com/auth-engine-api/v2/api-key/token");sr(e.tenant);let n;try{n=await rr.post(t,{headers:{FlowTenant:e.tenant},json:{clientSecret:e.clientSecret}}).json();}catch(o){throw await ar(o)}let r=n.expires_at??new Date(Date.now()+(n.expires_in??3600)*1e3).toISOString();yt(e),bt({accessToken:n.access_token,expiresAt:r});}async function vt(){if(B()){let e=Ke();if(!e)throw new Error("Flow CLI not configured. Run: npx @flow/cli auth login");return e.accessToken}throw new Error("Flow CLI not configured or token expired. Run: npx @flow/cli auth login")}var E=["clientId","clientSecret","tenant"],cr={clientId:"Client ID",clientSecret:"Client Secret",tenant:"Tenant"};function Tt(){let[e,t]=useState({clientId:"",clientSecret:"",tenant:""}),[n,r]=useState("clientId"),[o,i]=useState({}),[s,a]=useState(null),[d,c]=useState(false),{setCredentials:f,setJustAuthenticated:N}=L(),{setFocus:O}=m();useInput((l,p)=>{if(!d){if(p.shift&&p.tab){let g=E.indexOf(n);g>0&&r(E[g-1]);}else if(p.tab){let g=E.indexOf(n);g<E.length-1&&r(E[g+1]);}else if(p.return)if(n==="tenant")x();else {let g=E.indexOf(n);r(E[g+1]);}}},{isActive:true});let x=async()=>{let l={};for(let p of E)e[p].trim()||(l[p]="This field is required");if(Object.keys(l).length>0){i(l);let p=E.find(g=>l[g]);p&&r(p);return}c(true),a(null);try{await ne({clientId:e.clientId.trim(),clientSecret:e.clientSecret.trim(),tenant:e.tenant.trim()});let{clientSecret:p,...g}=e;f(g),N(!0),O("list");}catch(p){a(p instanceof Error?p.message:"Authentication failed");}finally{c(false),t(p=>({...p,clientSecret:""}));}},$=l=>p=>{t(g=>({...g,[l]:p})),o[l]&&i(g=>({...g,[l]:void 0}));};return jsxs(Box,{flexDirection:"column",padding:2,children:[jsx(Box,{marginBottom:1,children:jsxs(Text,{bold:true,color:"cyan",children:[ge," \u2014 Initial Setup"]})}),jsx(Box,{flexDirection:"column",children:E.map(l=>jsx(Box,{marginBottom:1,children:jsx(gt,{label:cr[l],value:e[l],onChange:$(l),masked:l==="clientSecret",isActive:n===l&&!d,error:o[l]})},l))}),d&&jsx(Box,{marginTop:1,children:jsx(Text,{color:"cyan",children:"Authenticating..."})}),s&&jsx(Box,{marginTop:1,children:jsxs(Text,{color:"red",children:["\u26A0 ",s]})}),jsx(Box,{marginTop:1,children:jsx(Text,{dimColor:true,children:"Tab next field \xB7 Enter confirm"})})]})}var mr=JSON.parse(readFileSync(join(import.meta.dirname,"..","package.json"),"utf8")),we=mr.version;function Et(){return jsxs(Box,{flexDirection:"column",alignItems:"center",children:[jsx(gr,{name:"morning",children:jsx(fr,{text:"FLOW",font:"block"})}),jsx(Box,{marginTop:-1,marginBottom:1,children:jsxs(Text,{dimColor:true,children:["Marketplace \xB7 v",we]})})]})}var ze={discover:"Discover",installed:"Installed"},hr=Object.keys(ze);function Ct(){let e=m(t=>t.activeTab);return jsxs(Box,{paddingX:1,paddingBottom:1,children:[hr.map(t=>jsx(Box,{marginRight:2,children:t===e?jsx(Text,{bold:true,underline:true,color:"cyan",children:ze[t]}):jsx(Text,{dimColor:true,children:ze[t]})},t)),jsx(Text,{dimColor:true,children:"(Tab to cycle)"})]})}var A=create(e=>({query:"",setQuery:t=>e({query:t}),resetQuery:()=>e({query:""})}));function kt(){let e=m(r=>r.focus),t=A(r=>r.query),n=e==="search";return jsxs(Box,{borderStyle:"single",borderTop:false,borderBottom:true,borderLeft:false,borderRight:false,paddingX:1,marginX:1,marginBottom:1,children:[jsx(Text,{color:n?"cyan":"gray",children:"\u03C1 "}),n?jsxs(Fragment,{children:[jsx(Text,{color:"white",children:t}),jsx(Text,{color:"cyan",children:"\u2588"})]}):jsx(Text,{dimColor:true,children:t||"Search..."})]})}function w(e){return e.replace(/\x1b\[[0-9;:<=>?]*[ -/]*[@-~]/g,"").replace(/\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)/g,"").replace(/\x1b./g,"").replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g,"")}function z(e){process.stdout.write(h.green(` \u2713 ${w(e)}
3
+ `));}function I(e){process.stderr.write(h.red(` \u2717 ${w(e)}
4
4
  `));}function C(e){process.stdout.write(h.cyan(` \u2139 ${w(e)}
5
- `));}function Ie(e,t){let n=t.map(a=>a.map(w)),o=[e,...n],r=e.map((a,l)=>Math.max(...o.map(d=>(d[l]??"").length))),i=r.map(a=>"\u2500".repeat(a)).join(" "),s=a=>a.map((l,d)=>l.padEnd(r[d])).join(" ");process.stdout.write(`
5
+ `));}function ve(e,t){let n=t.map(a=>a.map(w)),r=[e,...n],o=e.map((a,d)=>Math.max(...r.map(c=>(c[d]??"").length))),i=o.map(a=>"\u2500".repeat(a)).join(" "),s=a=>a.map((d,c)=>d.padEnd(o[c])).join(" ");process.stdout.write(`
6
6
  `),process.stdout.write(` ${h.bold(s(e))}
7
7
  `),process.stdout.write(` ${h.dim(i)}
8
8
  `);for(let a of n)process.stdout.write(` ${s(a)}
9
9
  `);process.stdout.write(`
10
10
  `);}function Te(e){process.stdout.write(JSON.stringify(e,null,2)+`
11
- `);}function Pe(e){let t=new Date(e);return isNaN(t.getTime())?"\u2014":new Intl.DateTimeFormat("en-US",{dateStyle:"short"}).format(t)}var kt=xo.memo(function({item:t,isSelected:n}){let o=t.status==="disabled"?"yellow":"green";return jsxs(Box,{flexDirection:"column",paddingBottom:1,children:[jsxs(Box,{children:[jsx(Text,{color:n?"cyan":"gray",children:n?"\u203A ":"\u25CB "}),jsx(Text,{bold:n,color:n?"cyan":"white",children:t.name}),jsxs(Text,{dimColor:true,children:[t.authorName?` \xB7 ${t.authorName}`:""," \xB7 v",t.version]}),t.status&&jsxs(Text,{color:o,children:[" [",t.status,"]"]}),t.updateAvailable&&jsx(Text,{color:"yellow",children:" [update available]"}),t.installedBadge&&jsx(Text,{color:"cyan",children:" [installed]"}),t.installedAt&&jsxs(Text,{dimColor:true,children:[" \xB7 ",Pe(t.installedAt)]})]}),jsx(Box,{paddingLeft:2,children:jsx(Text,{dimColor:true,children:t.description})})]})});function Lt({message:e}){return jsx(Box,{paddingX:2,paddingY:1,children:jsx(Text,{dimColor:true,children:e??"No items found."})})}var We=5;function Dt({items:e,emptyMessage:t}){let n=m(l=>l.selectedIndex);if(e.length===0)return jsx(Lt,{message:t});let o=Math.max(0,n-Math.floor(We/2)),r=Math.min(e.length,o+We);r===e.length&&(o=Math.max(0,r-We));let i=e.slice(o,r),s=o,a=e.length-r;return jsxs(Box,{flexDirection:"column",children:[s>0&&jsx(Box,{paddingX:2,children:jsxs(Text,{dimColor:true,children:["\u2191 ",s," more above"]})}),i.map((l,d)=>jsx(kt,{item:l,isSelected:o+d===n},l.name)),a>0&&jsx(Box,{paddingX:2,children:jsxs(Text,{dimColor:true,children:["\u2193 ",a," more below"]})})]})}var Io={discover:"Discover plugins",installed:"Installed plugins"};function Ft({items:e,tabId:t,emptyMessage:n}){return jsxs(Box,{flexDirection:"column",children:[jsxs(Box,{paddingX:1,paddingBottom:1,children:[jsx(Text,{bold:true,children:Io[t]}),jsxs(Text,{dimColor:true,children:[" (",e.length,")"]})]}),jsx(Rt,{}),jsx(Dt,{items:e,emptyMessage:n})]})}function Bt({filteredItems:e,emptyMessage:t}){let n=m(o=>o.activeTab);return jsx(Box,{flexDirection:"column",flexGrow:1,children:n==="discover"?jsx(Ft,{items:e,tabId:"discover",emptyMessage:t},"discover"):jsx(Ft,{items:e,tabId:"installed",emptyMessage:t},"installed")})}var So={tabs:"Tab: switch tab | \u2191\u2193: navigate | Enter: select | /: search | q: quit",list:"Tab: switch tab | \u2191\u2193: navigate | Enter: select | /: search | q: quit",search:"Type to filter | Esc: cancel search | Enter: confirm",actionMenu:"\u2191\u2193: navigate options | Enter: confirm | Esc: close menu",auth:"Tab: next field | Enter: confirm | Ctrl+C: quit"};function Ut(){let e=m(t=>t.focus);return jsx(Box,{borderStyle:"single",borderTop:true,borderBottom:false,borderLeft:false,borderRight:false,children:jsx(Text,{dimColor:true,children:So[e]})})}function jt({message:e,type:t}){return e?jsx(Box,{paddingX:1,children:jsxs(Text,{color:t==="success"?"green":t==="info"?"cyan":"red",children:[t==="success"?"\u2713":t==="info"?"(i)":"\u2717"," ",e]})}):null}function Ht({message:e}){return jsxs(Box,{children:[jsx(Text,{color:"cyan",children:jsx($o,{type:"dots"})}),jsxs(Text,{children:[" ",e]})]})}function Vt({message:e,onRetry:t,onBack:n}){return useInput((o,r)=>{o==="r"&&t?t():r.escape&&n&&n();}),jsxs(Box,{flexDirection:"column",paddingX:2,paddingY:1,children:[jsxs(Text,{color:"red",children:["\u2717 ",e]}),t&&jsx(Text,{dimColor:true,children:"Press r to retry"}),n&&jsx(Text,{dimColor:true,children:"Press Escape to go back"})]})}function Ae({itemName:e,actions:t,onAction:n,onClose:o}){let r=m(a=>a.focus),[i,s]=useState(0);return useInput((a,l)=>{l.upArrow?s(d=>d>0?d-1:d):l.downArrow?s(d=>d<t.length-1?d+1:d):l.return?n(t[i]):l.escape&&o();},{isActive:r==="actionMenu"}),jsxs(Box,{flexDirection:"column",borderStyle:"round",paddingX:1,children:[jsx(Text,{bold:true,children:e}),jsx(Box,{flexDirection:"column",marginTop:1,children:t.map((a,l)=>jsx(Box,{children:jsxs(Text,{bold:l===i,color:l===i?"cyan":void 0,children:[l===i?"\u203A ":" ",a]})},l))})]})}function Xt({itemName:e,onInstall:t,onClose:n}){return jsx(Ae,{itemName:e,actions:["Install","Cancel"],onAction:i=>{i==="Install"?t():n();},onClose:n})}function Zt({itemName:e,itemStatus:t,updateAvailable:n,onUninstall:o,onToggleStatus:r,onUpdate:i,onClose:s}){let[a,l]=useState(false),d=m(x=>x.focus);if(useInput((x,$)=>{$.escape||x==="n"?l(false):x==="y"&&o();},{isActive:a&&d==="actionMenu"}),a)return jsxs(Box,{flexDirection:"column",borderStyle:"round",paddingX:1,children:[jsx(Text,{bold:true,children:e}),jsxs(Box,{marginTop:1,children:[jsx(Text,{children:"Uninstall "}),jsx(Text,{bold:true,color:"red",children:e}),jsx(Text,{children:"? (y/N)"})]})]});let g=t==="enabled"?"Disable":"Enable";return jsx(Ae,{itemName:e,actions:n?["Uninstall",g,"Update","Cancel"]:["Uninstall",g,"Cancel"],onAction:x=>{x==="Uninstall"?l(true):x===g?r():x==="Update"?i?.():s();},onClose:s})}var Uo=".claude",jo=".flow";function en(e){return I.join(it.homedir(),Uo,"plugins","cache",J,e)}function tn(){return I.join(it.homedir(),jo,"cache","install.lock")}async function nn(e,t){let n=I.resolve(t);await R.mkdir(n,{recursive:true});let o=I.join(I.dirname(n),`${randomUUID()}.zip`);try{await R.writeFile(o,e),await _o(o,{dir:n,onEntry(r){if((r.externalFileAttributes>>16&61440)===40960)throw new Error(`Zip Slip (symlink): entry "${r.fileName}" is a symbolic link and was rejected`);let s=I.resolve(n,r.fileName);if(!s.startsWith(n+I.sep)&&s!==n)throw new Error(`Zip Slip detected: entry "${r.fileName}" would escape target directory`)}});try{let r=realpathSync(n);if(!r.startsWith(I.resolve(I.dirname(n))))throw new Error(`Zip Slip (post-extract): resolved path "${r}" is outside expected parent`)}catch(r){if(r.code!=="ENOENT")throw r}}finally{try{await R.unlink(o);}catch{}}}async function rt(e){await R.rm(e,{recursive:true,force:true});}async function ae(){let e=tn();await R.mkdir(I.dirname(e),{recursive:true});try{await R.writeFile(e,"",{flag:"wx"});}catch(n){if(n.code!=="EEXIST")throw n}return await qo.lock(e,{stale:1e4,retries:{retries:2,minTimeout:500,maxTimeout:500}})}function on(){return I__default.join(it__default.homedir(),".claude","plugins","installed_plugins.json")}function Jo(){return I__default.join(it__default.homedir(),".claude","plugins")}function zo(e){let t=I__default.resolve(e),n=I__default.resolve(Jo());if(!t.startsWith(n+I__default.sep)&&t!==n)throw new Error(`Security error: installPath '${e}' is outside the plugins directory`)}function rn(){return I__default.join(it__default.homedir(),".claude","settings.json")}function W(){let e=on();if(!T.existsSync(e))return {version:2,plugins:{}};try{return JSON.parse(T.readFileSync(e,"utf-8"))}catch{return {version:2,plugins:{}}}}function st(e){let t=on();T.mkdirSync(I__default.dirname(t),{recursive:true});let n=`${t}.tmp`;T.writeFileSync(n,JSON.stringify(e,null,2),"utf-8"),T.renameSync(n,t);}function le(e){let t=e.lastIndexOf("@");return t===-1?{name:e,marketplace:""}:{name:e.slice(0,t),marketplace:e.slice(t+1)}}function Vo(e){let t=I__default.join(e,".claude-plugin","plugin.json");if(!T.existsSync(t))return null;try{return JSON.parse(T.readFileSync(t,"utf-8"))}catch{return null}}function at(){let e=rn();if(!T.existsSync(e))return {};try{return JSON.parse(T.readFileSync(e,"utf-8"))}catch{return {}}}function sn(e){let t=rn(),n=`${t}.tmp`;T.writeFileSync(n,JSON.stringify(e,null,2),"utf-8"),T.renameSync(n,t);}function Go(){return at().enabledPlugins??{}}function Wo(e){let t=at(),n=t.enabledPlugins;if(!n||!(e in n))return;let{[e]:o,...r}=n;t.enabledPlugins=r,sn(t);}function lt(e,t){let n=at(),o=n.enabledPlugins??{};n.enabledPlugins={...o,[e]:t},sn(n);}function k(){let e=W(),t=Go();return Object.entries(e.plugins).map(([n,o])=>{let r=o[0],{name:i,marketplace:s}=le(n),a=Vo(r.installPath),l=t[n];return {name:i,marketplace:s,version:r.version,installedAt:r.installedAt,installPath:r.installPath,scope:r.scope,description:a?.description,author:a?.author,status:l===false?"disabled":"enabled"}})}async function Ce(e){let t=await ae();try{let{name:n,marketplace:o}=le(e),r=W(),i;if(o?(i=`${n}@${o}`,r.plugins[i]||(i=void 0)):i=Object.keys(r.plugins).filter(g=>le(g).name===n)[0],!i)throw new Error(`Plugin '${n}' is not installed`);let s=r.plugins[i][0].installPath;zo(s),T.rmSync(s,{recursive:!0,force:!0});let{[i]:a,...l}=r.plugins;st({...r,plugins:l}),Wo(i);}finally{await t();}}async function ce(e,t){let n=await ae();try{let{name:o}=le(e),r=W(),i=Object.keys(r.plugins).filter(s=>le(s).name===o);if(i.length===0)throw new Error(`Plugin '${o}' is not installed`);lt(i[0],t==="enabled");}finally{await n();}}var K=create(e=>({installedItems:[],setInstalledItems:t=>e({installedItems:t}),loadFromDisk:()=>e({installedItems:k()})}));var S=["discover","installed"];function an(e,t,n){if(t.rightArrow||t.tab){let o=S.indexOf(n.activeTab);return [{type:"setTab",tab:S[(o+1)%S.length]},{type:"setSelectedIndex",index:0},{type:"setFocus",focus:"list"}]}if(t.leftArrow){let o=S.indexOf(n.activeTab);return [{type:"setTab",tab:S[(o-1+S.length)%S.length]},{type:"setSelectedIndex",index:0},{type:"setFocus",focus:"list"}]}return t.downArrow?[{type:"setFocus",focus:"list"}]:[]}function ln(e,t,n,o){if(t.upArrow&&n.selectedIndex>0)return [{type:"setSelectedIndex",index:n.selectedIndex-1}];if(t.downArrow&&n.selectedIndex<o-1)return [{type:"setSelectedIndex",index:n.selectedIndex+1}];if(t.tab){let r=S.indexOf(n.activeTab);return [{type:"setTab",tab:S[(r+1)%S.length]},{type:"setSelectedIndex",index:0}]}return t.return?[{type:"setActionMenuOpen",open:true},{type:"setFocus",focus:"actionMenu"}]:e==="/"?[{type:"setFocus",focus:"search"}]:[]}function cn(e,t){return t.escape?[{type:"setActionMenuOpen",open:false},{type:"setFocus",focus:"list"}]:[]}function un(e,t){return t.escape?{actions:[{type:"setFocus",focus:"list"}],queryUpdate:"reset"}:t.return?{actions:[{type:"setFocus",focus:"list"}],queryUpdate:null}:t.backspace||t.delete?{actions:[],queryUpdate:{backspace:true}}:e&&!t.ctrl&&!t.meta?{actions:[],queryUpdate:{append:e}}:{actions:[],queryUpdate:null}}function Re(e){let{setActiveTab:t,setFocus:n,setSelectedIndex:o,setActionMenuOpen:r}=m.getState();for(let i of e)i.type==="setTab"?t(i.tab):i.type==="setFocus"?n(i.focus):i.type==="setSelectedIndex"?o(i.index):i.type==="setActionMenuOpen"&&r(i.open);}function mn({listLength:e}){let t=m(c=>c.focus),n=m(c=>c.selectedIndex),o=m(c=>c.actionMenuOpen),r=m(c=>c.setFocus),i=m(c=>c.setActionMenuOpen),s=E(c=>c.query),a=E(c=>c.setQuery),l=E(c=>c.resetQuery),d=useRef(e);useEffect(()=>{d.current=e;},[e]);let[g,O]=useState("");useEffect(()=>{let c=setTimeout(()=>O(s),300);return ()=>clearTimeout(c)},[s]),useInput((c,p)=>{c==="q"&&process.exit(0);},{isActive:t!=="search"&&t!=="auth"}),useInput((c,p)=>{let{activeTab:f,selectedIndex:b,actionMenuOpen:Y}=m.getState();Re(an(c,p,{activeTab:f}));},{isActive:t==="tabs"}),useInput((c,p)=>{let{activeTab:f,selectedIndex:b,actionMenuOpen:Y}=m.getState();Re(ln(c,p,{activeTab:f,selectedIndex:b},d.current));},{isActive:t==="list"}),useInput((c,p)=>{Re(cn(c,p));},{isActive:t==="actionMenu"}),useInput((c,p)=>{let f=un(c,p),b=f.queryUpdate;Re(f.actions),b==="reset"?(l(),O("")):b!==null&&("backspace"in b?a(E.getState().query.slice(0,-1)):a(E.getState().query+b.append));},{isActive:t==="search"});let F=useCallback(()=>{i(false),r("list");},[i,r]),x=useCallback(c=>{let{setSelectedIndex:p,selectedIndex:f}=m.getState();c===0?p(0):f>=c&&p(c-1);},[]),$=useCallback(c=>{if(!g)return d.current=c.length,c;let p=g.toLowerCase(),f=c.filter(b=>b.name.toLowerCase().includes(p)||b.description?.toLowerCase().includes(p));return d.current=f.length,f},[g]);return {actionMenuOpen:o,closeMenu:F,selectedIndex:n,clampIndex:x,filteredItems:$}}var pn=800;var er=/^[a-z0-9][a-z0-9-]{0,62}[a-z0-9]$|^[a-z0-9]$/;function ke(){return eo.create({prefixUrl:he("PROMPT_MANAGER_URL","https://dev.flow.ciandt.com/prompt-manager-api/"),hooks:{beforeRequest:[async e=>{let t=await vt();e.headers.set("Authorization",`Bearer ${t}`);let n=P();n?.tenant&&er.test(n.tenant)&&e.headers.set("FlowTenant",n.tenant);}]}})}var tr=/^[a-z0-9][a-z0-9-]{0,62}[a-z0-9]$|^[a-z0-9]$/;function fn(e){if(!e||!tr.test(e))throw new Error(`Invalid plugin name: "${e}". Must be 1-64 chars, lowercase alphanumeric and hyphens only.`)}async function X(){try{let{plugins:e}=await ke().get("v1/plugins/catalog").json();return e}catch(e){throw e instanceof Error?e.message.includes("401")||e.message.includes("403")?new Error("Authentication failed. Run: flow auth login"):e.message.includes("timeout")?new Error("Request timed out while fetching plugin catalog"):new Error(`Failed to fetch plugin catalog: ${e.message}`):e}}async function gn(e){fn(e);try{return await ke().get(`v1/plugins/${e}/manifest`).json()}catch(t){throw t instanceof Error?t.message.includes("404")?new Error(`Plugin '${e}' not found in catalog`):t.message.includes("timeout")?new Error("Download timed out after 30s"):new Error(`Failed to fetch plugin manifest: ${t.message}`):t}}async function hn(e){fn(e);try{let t=await ke().get(`v1/plugins/${e}/archive`);return Buffer.from(await t.arrayBuffer())}catch(t){throw t instanceof Error?t.message.includes("timeout")?new Error("Download timed out after 30s"):new Error(`Failed to download plugin: ${t.message}`):t}}async function yn(e){await new Promise(t=>setTimeout(t,pn)),console.warn("Update not implemented yet");}function wn(){let[e,t]=useState([]),[n,o]=useState(true),[r,i]=useState(null),s=useCallback(async()=>{o(true),i(null);try{let a=await X();t(a);}catch(a){i(a instanceof Error?a:new Error(String(a))),t([]);}finally{o(false);}},[]);return useEffect(()=>{s();},[s]),{catalog:e,isLoading:n,error:r,refetch:s}}function xn(){return {items:K(t=>t.installedItems)}}var Q=class extends Error{constructor(n,o){super(`${n} v${o} is already installed. Use --force to reinstall.`);this.pluginName=n;this.version=o;this.name="AlreadyInstalledError";}};var rr=/^[a-z0-9][a-z0-9-]{0,62}[a-z0-9]$|^[a-z0-9]$/;function ir(e){if(!rr.test(e))throw new Error(`Invalid plugin name from manifest: "${e}". Plugin names must be lowercase alphanumeric and hyphens (1-64 chars).`)}function sr(e,t){return n=>{t&&console.log(`[${e}] ${n}`);}}function ar(e,t){let n=`${e}@${J}`,r=W().plugins[n];if(r&&!t)throw new Q(e,r[0].version);return {pluginKey:n,alreadyInstalled:r}}async function lr(e,t,n,o){n&&await rt(t);try{o(`Extracting to ${t}...`),await nn(e,t);}catch(r){throw await rt(t),r}}function cr(e,t,n){let o=W(),r={scope:"user",installPath:t,version:n,installedAt:new Date().toISOString()};o.plugins[e]=[r],st(o),lt(e,true);}async function $e(e,t={}){let n=Date.now(),o=sr(e,t.verbose),r=null;try{o("Acquiring lock..."),r=await ae();let{pluginKey:i,alreadyInstalled:s}=ar(e,t.force);o("Fetching manifest...");let a=await gn(e);ir(a.name),o("Downloading archive...");let l=await hn(e),d=en(a.name);await lr(l,d,!!s&&!!t.force,o),cr(i,d,a.version);let g=Date.now()-n;return o(`Installed successfully in ${g}ms`),{name:a.name,version:a.version,path:d,duration_ms:g}}finally{r&&await r();}}function bn(){let e=K(s=>s.installedItems),t=K(s=>s.setInstalledItems),n=useCallback(async s=>{await $e(s.name),K.getState().loadFromDisk();},[]),o=useCallback(async s=>{await Ce(s),t(e.filter(a=>a.name!==s));},[e,t]),r=useCallback(async s=>{let l=e.find(d=>d.name===s)?.status==="enabled"?"disabled":"enabled";await ce(s,l),t(e.map(d=>d.name===s?{...d,status:l}:d));},[e,t]),i=useCallback(async s=>{await yn(),t(e.map(a=>a.name===s?{...a,updateAvailable:false}:a));},[e,t]);return {install:n,uninstall:o,toggle:r,update:i}}function mr(e){return {name:e.name,version:e.version,description:e.description,authorName:e.author.name,updateAvailable:e.updateAvailable}}function pr(e){return {name:e.name,version:e.version,description:e.description,authorName:e.author?.name,status:e.status,updateAvailable:e.updateAvailable,installedAt:e.installedAt}}function vn(){let e=m(u=>u.activeTab),t=m(u=>u.notification),n=m(u=>u.showNotification),o=m(u=>u.clearNotification),r=m(u=>u.loading),i=m(u=>u.loadingMessage),s=m(u=>u.catalogError),a=m(u=>u.setLoading),l=m(u=>u.setCatalogError),d=E(u=>u.query),{catalog:g,isLoading:O,error:F,refetch:x}=wn(),{items:$}=xn(),c=K(u=>u.loadFromDisk),p=useMemo(()=>new Set($.map(u=>`${u.name}|${u.author?.name??""}|${u.marketplace}`)),[$]),{install:f,uninstall:b,toggle:Y,update:On}=bn(),mt=L(u=>u.justAuthenticated),Fe=L(u=>u.credentials),Fn=L(u=>u.setJustAuthenticated),Be=e==="discover"?g.filter(u=>!p.has(`${u.name}|${u.author.name}|${J}`)).map(u=>mr(u)):$.map(u=>pr(u)),{actionMenuOpen:pt,closeMenu:Ne,selectedIndex:Bn,clampIndex:Ue,filteredItems:Nn}=mn({listLength:Be.length}),me=Nn(Be),y=me[Bn]??null;useEffect(()=>{c();},[]),useEffect(()=>{Ue(me.length);},[me.length,Ue]),useEffect(()=>{mt&&Fe&&(n(`Authenticated. Tenant: ${Fe.tenant}`,"success"),Fn(false));},[mt,Fe]),useEffect(()=>{if(!t)return;let u=setTimeout(o,3e3);return ()=>clearTimeout(u)},[t]),useEffect(()=>{F&&(console.error("[usePluginCatalog]",F),l("Failed to load catalog"));},[F]);let ft=(u,Z)=>{n(u,Z);},pe=async(u,Z,Hn)=>{a(true,u),Ne();try{await Z();let fe=Be.length;Ue(fe),ft(Hn,"success");}catch(fe){ft(fe instanceof Error?fe.message:"Something went wrong","error");}finally{a(false);}},Un=()=>{if(!y)return;let u=g.find(Z=>Z.name===y.name);u&&pe(`Installing ${y.name}...`,()=>f(u),"\u2713 Installed successfully");},jn=()=>{y&&pe(`Uninstalling ${y.name}...`,()=>b(y.name),"\u2713 Uninstalled");},Kn=()=>{if(!y)return;let u=y.status==="enabled";pe(u?`Disabling ${y.name}...`:`Enabling ${y.name}...`,()=>Y(y.name),u?"\u2713 Disabled":"\u2713 Enabled");},_n=e==="installed"?"No plugins installed \u2014 explore the Discover tab!":d?`No plugins found for '${d}'`:"No plugins available in the catalog",qn=()=>{y&&pe(`Updating ${y.name}...`,()=>On(y.name),"\u2713 Updated");};return jsxs(Box,{flexDirection:"column",borderStyle:"round",paddingX:1,children:[jsx(St,{}),jsx(Et,{}),jsx(Bt,{filteredItems:me,emptyMessage:_n}),(r||O)&&jsx(Ht,{message:r?i:"Loading catalog..."}),s&&!O&&e==="discover"&&jsx(Vt,{message:s,onRetry:()=>{l(null),x();},onBack:()=>l(null)}),t&&jsx(jt,{message:t.message,type:t.type}),pt&&y&&e==="discover"&&jsx(Xt,{itemName:y.name,onInstall:Un,onClose:Ne}),pt&&y&&e==="installed"&&jsx(Zt,{itemName:y.name,itemStatus:y.status??"enabled",updateAvailable:y.updateAvailable??false,onUninstall:jn,onToggleStatus:Kn,onUpdate:qn,onClose:Ne}),jsx(Ut,{})]})}var In=P();if(In&&N()){let{clientSecret:e,...t}=In;L.getState().setCredentials(t),m.getState().setFocus("list");}else m.getState().setFocus("auth");function Pn(){return L(t=>t.isAuthenticated)?jsx(vn,{}):jsx(It,{})}function Me(e,t={}){return new Promise((n,o)=>{let{masked:r=false,defaultValue:i=""}=t;process.stdout.write(e+i);let s=i,a=g=>{if(g===""){l(),o(new Error("SIGINT"));return}if(g==="\r"||g===`
12
- `){l(),process.stdout.write(`
13
- `),n(s);return}if(g==="\x7F"){s.length>0&&(s=s.slice(0,-1),process.stdout.write("\b \b"));return}g.startsWith("\x1B")||(s+=g,process.stdout.write(r?"*".repeat(g.length):g));};function l(){process.stdin.setRawMode(false),process.stdin.removeListener("data",a),process.removeListener("uncaughtException",d),process.removeListener("unhandledRejection",d);}function d(){try{process.stdin.setRawMode(!1);}catch{}}process.on("uncaughtException",d),process.on("unhandledRejection",d),process.stdin.setRawMode(true),process.stdin.resume(),process.stdin.setEncoding("utf8"),process.stdin.on("data",a);})}async function gr(e){try{return await ne(e),process.stdout.write(h.green(` \u2713 Setup complete. Tenant: ${e.tenant}
11
+ `);}function Se(e){let t=new Date(e);return isNaN(t.getTime())?"\u2014":new Intl.DateTimeFormat("en-US",{dateStyle:"short"}).format(t)}var $t=Ir.memo(function({item:t,isSelected:n}){let r=t.status==="disabled"?"yellow":"green";return jsxs(Box,{flexDirection:"column",paddingBottom:1,children:[jsxs(Box,{children:[jsx(Text,{color:n?"cyan":"gray",children:n?"\u203A ":"\u25CB "}),jsx(Text,{bold:n,color:n?"cyan":"white",children:t.name}),jsxs(Text,{dimColor:true,children:[t.authorName?` \xB7 ${t.authorName}`:""," \xB7 v",t.version]}),t.status&&jsxs(Text,{color:r,children:[" [",t.status,"]"]}),t.updateAvailable&&jsx(Text,{color:"yellow",children:" [update available]"}),t.installedBadge&&jsx(Text,{color:"cyan",children:" [installed]"}),t.installedAt&&jsxs(Text,{dimColor:true,children:[" \xB7 ",Se(t.installedAt)]})]}),jsx(Box,{paddingLeft:2,children:jsx(Text,{dimColor:true,children:t.description})})]})});function Mt({message:e}){return jsx(Box,{paddingX:2,paddingY:1,children:jsx(Text,{dimColor:true,children:e??"No items found."})})}var We=5;function Nt({items:e,emptyMessage:t}){let n=m(d=>d.selectedIndex);if(e.length===0)return jsx(Mt,{message:t});let r=Math.max(0,n-Math.floor(We/2)),o=Math.min(e.length,r+We);o===e.length&&(r=Math.max(0,o-We));let i=e.slice(r,o),s=r,a=e.length-o;return jsxs(Box,{flexDirection:"column",children:[s>0&&jsx(Box,{paddingX:2,children:jsxs(Text,{dimColor:true,children:["\u2191 ",s," more above"]})}),i.map((d,c)=>jsx($t,{item:d,isSelected:r+c===n},d.name)),a>0&&jsx(Box,{paddingX:2,children:jsxs(Text,{dimColor:true,children:["\u2193 ",a," more below"]})})]})}var Sr={discover:"Discover plugins",installed:"Installed plugins"};function Ft({items:e,tabId:t,emptyMessage:n}){return jsxs(Box,{flexDirection:"column",children:[jsxs(Box,{paddingX:1,paddingBottom:1,children:[jsx(Text,{bold:true,children:Sr[t]}),jsxs(Text,{dimColor:true,children:[" (",e.length,")"]})]}),jsx(kt,{}),jsx(Nt,{items:e,emptyMessage:n})]})}function Bt({filteredItems:e,emptyMessage:t}){let n=m(r=>r.activeTab);return jsx(Box,{flexDirection:"column",flexGrow:1,children:n==="discover"?jsx(Ft,{items:e,tabId:"discover",emptyMessage:t},"discover"):jsx(Ft,{items:e,tabId:"installed",emptyMessage:t},"installed")})}var Ar={tabs:"Tab: switch tab | \u2191\u2193: navigate | Enter: select | /: search | q: quit",list:"Tab: switch tab | \u2191\u2193: navigate | Enter: select | /: search | q: quit",search:"Type to filter | Esc: cancel search | Enter: confirm",actionMenu:"\u2191\u2193: navigate options | Enter: confirm | Esc: close menu",auth:"Tab: next field | Enter: confirm | Ctrl+C: quit"};function jt(){let e=m(t=>t.focus);return jsx(Box,{borderStyle:"single",borderTop:true,borderBottom:false,borderLeft:false,borderRight:false,children:jsx(Text,{dimColor:true,children:Ar[e]})})}function _t({message:e,type:t}){return e?jsx(Box,{paddingX:1,children:jsxs(Text,{color:t==="success"?"green":t==="info"?"cyan":"red",children:[t==="success"?"\u2713":t==="info"?"(i)":"\u2717"," ",e]})}):null}function Jt({message:e}){return jsxs(Box,{children:[jsx(Text,{color:"cyan",children:jsx(Mr,{type:"dots"})}),jsxs(Text,{children:[" ",e]})]})}function Gt({message:e,onRetry:t,onBack:n}){return useInput((r,o)=>{r==="r"&&t?t():o.escape&&n&&n();}),jsxs(Box,{flexDirection:"column",paddingX:2,paddingY:1,children:[jsxs(Text,{color:"red",children:["\u2717 ",e]}),t&&jsx(Text,{dimColor:true,children:"Press r to retry"}),n&&jsx(Text,{dimColor:true,children:"Press Escape to go back"})]})}function Ee({itemName:e,actions:t,onAction:n,onClose:r}){let o=m(a=>a.focus),[i,s]=useState(0);return useInput((a,d)=>{d.upArrow?s(c=>c>0?c-1:c):d.downArrow?s(c=>c<t.length-1?c+1:c):d.return?n(t[i]):d.escape&&r();},{isActive:o==="actionMenu"}),jsxs(Box,{flexDirection:"column",borderStyle:"round",paddingX:1,children:[jsx(Text,{bold:true,children:e}),jsx(Box,{flexDirection:"column",marginTop:1,children:t.map((a,d)=>jsx(Box,{children:jsxs(Text,{bold:d===i,color:d===i?"cyan":void 0,children:[d===i?"\u203A ":" ",a]})},d))})]})}function Qt({itemName:e,onInstall:t,onClose:n}){return jsx(Ee,{itemName:e,actions:["Install","Cancel"],onAction:i=>{i==="Install"?t():n();},onClose:n})}function en({itemName:e,itemStatus:t,updateAvailable:n,onUninstall:r,onToggleStatus:o,onUpdate:i,onClose:s}){let[a,d]=useState(false),c=m(x=>x.focus);if(useInput((x,$)=>{$.escape||x==="n"?d(false):x==="y"&&r();},{isActive:a&&c==="actionMenu"}),a)return jsxs(Box,{flexDirection:"column",borderStyle:"round",paddingX:1,children:[jsx(Text,{bold:true,children:e}),jsxs(Box,{marginTop:1,children:[jsx(Text,{children:"Uninstall "}),jsx(Text,{bold:true,color:"red",children:e}),jsx(Text,{children:"? (y/N)"})]})]});let f=t==="enabled"?"Disable":"Enable";return jsx(Ee,{itemName:e,actions:n?["Uninstall",f,"Update","Cancel"]:["Uninstall",f,"Cancel"],onAction:x=>{x==="Uninstall"?d(true):x===f?o():x==="Update"?i?.():s();},onClose:s})}var _r=".claude",Kr=".flow";function tn(e){return v.join(it.homedir(),_r,"plugins","cache",J,e)}function nn(){return v.join(it.homedir(),Kr,"cache","install.lock")}async function rn(e,t){let n=v.resolve(t);await R.mkdir(n,{recursive:true});let r=v.join(v.dirname(n),`${randomUUID()}.zip`);try{await R.writeFile(r,e),await Hr(r,{dir:n,onEntry(o){if((o.externalFileAttributes>>16&61440)===40960)throw new Error(`Zip Slip (symlink): entry "${o.fileName}" is a symbolic link and was rejected`);let s=v.resolve(n,o.fileName);if(!s.startsWith(n+v.sep)&&s!==n)throw new Error(`Zip Slip detected: entry "${o.fileName}" would escape target directory`)}});try{let o=realpathSync(n);if(!o.startsWith(v.resolve(v.dirname(n))))throw new Error(`Zip Slip (post-extract): resolved path "${o}" is outside expected parent`)}catch(o){if(o.code!=="ENOENT")throw o}}finally{try{await R.unlink(r);}catch{}}}async function ot(e){await R.rm(e,{recursive:true,force:true});}async function ae(){let e=nn();await R.mkdir(v.dirname(e),{recursive:true});try{await R.writeFile(e,"",{flag:"wx"});}catch(n){if(n.code!=="EEXIST")throw n}return await Jr.lock(e,{stale:1e4,retries:{retries:2,minTimeout:500,maxTimeout:500}})}function on(){return v__default.join(it__default.homedir(),".claude","plugins","installed_plugins.json")}function Vr(){return v__default.join(it__default.homedir(),".claude","plugins")}function Gr(e){let t=v__default.resolve(e),n=v__default.resolve(Vr());if(!t.startsWith(n+v__default.sep)&&t!==n)throw new Error(`Security error: installPath '${e}' is outside the plugins directory`)}function sn(){return v__default.join(it__default.homedir(),".claude","settings.json")}function W(){let e=on();if(!T.existsSync(e))return {version:2,plugins:{}};try{return JSON.parse(T.readFileSync(e,"utf-8"))}catch{return {version:2,plugins:{}}}}function st(e){let t=on();T.mkdirSync(v__default.dirname(t),{recursive:true});let n=`${t}.tmp`;T.writeFileSync(n,JSON.stringify(e,null,2),"utf-8"),T.renameSync(n,t);}function le(e){let t=e.lastIndexOf("@");return t===-1?{name:e,marketplace:""}:{name:e.slice(0,t),marketplace:e.slice(t+1)}}function Wr(e){let t=v__default.join(e,".claude-plugin","plugin.json");if(!T.existsSync(t))return null;try{return JSON.parse(T.readFileSync(t,"utf-8"))}catch{return null}}function at(){let e=sn();if(!T.existsSync(e))return {};try{return JSON.parse(T.readFileSync(e,"utf-8"))}catch{return {}}}function an(e){let t=sn(),n=`${t}.tmp`;T.writeFileSync(n,JSON.stringify(e,null,2),"utf-8"),T.renameSync(n,t);}function Xr(){return at().enabledPlugins??{}}function Qr(e){let t=at(),n=t.enabledPlugins;if(!n||!(e in n))return;let{[e]:r,...o}=n;t.enabledPlugins=o,an(t);}function lt(e,t){let n=at(),r=n.enabledPlugins??{};n.enabledPlugins={...r,[e]:t},an(n);}function k(){let e=W(),t=Xr();return Object.entries(e.plugins).map(([n,r])=>{let o=r[0],{name:i,marketplace:s}=le(n),a=Wr(o.installPath),d=t[n];return {name:i,marketplace:s,version:o.version,installedAt:o.installedAt,installPath:o.installPath,scope:o.scope,description:a?.description,author:a?.author,status:d===false?"disabled":"enabled"}})}async function Ce(e){let t=await ae();try{let{name:n,marketplace:r}=le(e),o=W(),i;if(r?(i=`${n}@${r}`,o.plugins[i]||(i=void 0)):i=Object.keys(o.plugins).filter(f=>le(f).name===n)[0],!i)throw new Error(`Plugin '${n}' is not installed`);let s=o.plugins[i][0].installPath;Gr(s),T.rmSync(s,{recursive:!0,force:!0});let{[i]:a,...d}=o.plugins;st({...o,plugins:d}),Qr(i);}finally{await t();}}async function ce(e,t){let n=await ae();try{let{name:r}=le(e),o=W(),i=Object.keys(o.plugins).filter(s=>le(s).name===r);if(i.length===0)throw new Error(`Plugin '${r}' is not installed`);lt(i[0],t==="enabled");}finally{await n();}}var _=create(e=>({installedItems:[],setInstalledItems:t=>e({installedItems:t}),loadFromDisk:()=>e({installedItems:k()})}));var P=["discover","installed"];function ln(e,t,n){if(t.rightArrow||t.tab){let r=P.indexOf(n.activeTab);return [{type:"setTab",tab:P[(r+1)%P.length]},{type:"setSelectedIndex",index:0},{type:"setFocus",focus:"list"}]}if(t.leftArrow){let r=P.indexOf(n.activeTab);return [{type:"setTab",tab:P[(r-1+P.length)%P.length]},{type:"setSelectedIndex",index:0},{type:"setFocus",focus:"list"}]}return t.downArrow?[{type:"setFocus",focus:"list"}]:[]}function cn(e,t,n,r){if(t.upArrow&&n.selectedIndex>0)return [{type:"setSelectedIndex",index:n.selectedIndex-1}];if(t.downArrow&&n.selectedIndex<r-1)return [{type:"setSelectedIndex",index:n.selectedIndex+1}];if(t.tab){let o=P.indexOf(n.activeTab);return [{type:"setTab",tab:P[(o+1)%P.length]},{type:"setSelectedIndex",index:0}]}return t.return?[{type:"setActionMenuOpen",open:true},{type:"setFocus",focus:"actionMenu"}]:e==="/"?[{type:"setFocus",focus:"search"}]:[]}function un(e,t){return t.escape?[{type:"setActionMenuOpen",open:false},{type:"setFocus",focus:"list"}]:[]}function dn(e,t){return t.escape?{actions:[{type:"setFocus",focus:"list"}],queryUpdate:"reset"}:t.return?{actions:[{type:"setFocus",focus:"list"}],queryUpdate:null}:t.backspace||t.delete?{actions:[],queryUpdate:{backspace:true}}:e&&!t.ctrl&&!t.meta?{actions:[],queryUpdate:{append:e}}:{actions:[],queryUpdate:null}}function Re(e){let{setActiveTab:t,setFocus:n,setSelectedIndex:r,setActionMenuOpen:o}=m.getState();for(let i of e)i.type==="setTab"?t(i.tab):i.type==="setFocus"?n(i.focus):i.type==="setSelectedIndex"?r(i.index):i.type==="setActionMenuOpen"&&o(i.open);}function pn({listLength:e}){let t=m(l=>l.focus),n=m(l=>l.selectedIndex),r=m(l=>l.actionMenuOpen),o=m(l=>l.setFocus),i=m(l=>l.setActionMenuOpen),s=A(l=>l.query),a=A(l=>l.setQuery),d=A(l=>l.resetQuery),c=useRef(e);useEffect(()=>{c.current=e;},[e]);let[f,N]=useState("");useEffect(()=>{let l=setTimeout(()=>N(s),300);return ()=>clearTimeout(l)},[s]),useInput((l,p)=>{l==="q"&&process.exit(0);},{isActive:t!=="search"&&t!=="auth"}),useInput((l,p)=>{let{activeTab:g,selectedIndex:b,actionMenuOpen:Y}=m.getState();Re(ln(l,p,{activeTab:g}));},{isActive:t==="tabs"}),useInput((l,p)=>{let{activeTab:g,selectedIndex:b,actionMenuOpen:Y}=m.getState();Re(cn(l,p,{activeTab:g,selectedIndex:b},c.current));},{isActive:t==="list"}),useInput((l,p)=>{Re(un(l,p));},{isActive:t==="actionMenu"}),useInput((l,p)=>{let g=dn(l,p),b=g.queryUpdate;Re(g.actions),b==="reset"?(d(),N("")):b!==null&&("backspace"in b?a(A.getState().query.slice(0,-1)):a(A.getState().query+b.append));},{isActive:t==="search"});let O=useCallback(()=>{i(false),o("list");},[i,o]),x=useCallback(l=>{let{setSelectedIndex:p,selectedIndex:g}=m.getState();l===0?p(0):g>=l&&p(l-1);},[]),$=useCallback(l=>{if(!f)return c.current=l.length,l;let p=f.toLowerCase(),g=l.filter(b=>b.name.toLowerCase().includes(p)||b.description?.toLowerCase().includes(p));return c.current=g.length,g},[f]);return {actionMenuOpen:r,closeMenu:O,selectedIndex:n,clampIndex:x,filteredItems:$}}var fn=800;var no=/^[a-z0-9][a-z0-9-]{0,62}[a-z0-9]$|^[a-z0-9]$/;function ke(){return rr.create({prefixUrl:he("PROMPT_MANAGER_URL","https://dev.flow.ciandt.com/prompt-manager-api/"),hooks:{beforeRequest:[async e=>{let t=await vt();e.headers.set("Authorization",`Bearer ${t}`);let n=S();n?.tenant&&no.test(n.tenant)&&e.headers.set("FlowTenant",n.tenant);}]}})}var ro=/^[a-z0-9][a-z0-9-]{0,62}[a-z0-9]$|^[a-z0-9]$/;function gn(e){if(!e||!ro.test(e))throw new Error(`Invalid plugin name: "${e}". Must be 1-64 chars, lowercase alphanumeric and hyphens only.`)}async function X(){try{let{plugins:e}=await ke().get("v1/plugins/catalog").json();return e}catch(e){throw e instanceof Error?e.message.includes("401")||e.message.includes("403")?new Error("Authentication failed. Run: flow auth login"):e.message.includes("timeout")?new Error("Request timed out while fetching plugin catalog"):new Error(`Failed to fetch plugin catalog: ${e.message}`):e}}async function hn(e){gn(e);try{return await ke().get(`v1/plugins/${e}/manifest`).json()}catch(t){throw t instanceof Error?t.message.includes("404")?new Error(`Plugin '${e}' not found in catalog`):t.message.includes("timeout")?new Error("Download timed out after 30s"):new Error(`Failed to fetch plugin manifest: ${t.message}`):t}}async function yn(e){gn(e);try{let t=await ke().get(`v1/plugins/${e}/archive`);return Buffer.from(await t.arrayBuffer())}catch(t){throw t instanceof Error?t.message.includes("timeout")?new Error("Download timed out after 30s"):new Error(`Failed to download plugin: ${t.message}`):t}}async function wn(e){await new Promise(t=>setTimeout(t,fn)),console.warn("Update not implemented yet");}function xn(){let[e,t]=useState([]),[n,r]=useState(true),[o,i]=useState(null),s=useCallback(async()=>{r(true),i(null);try{let a=await X();t(a);}catch(a){i(a instanceof Error?a:new Error(String(a))),t([]);}finally{r(false);}},[]);return useEffect(()=>{s();},[s]),{catalog:e,isLoading:n,error:o,refetch:s}}function bn(){return {items:_(t=>t.installedItems)}}var Q=class extends Error{constructor(n,r){super(`${n} v${r} is already installed. Use --force to reinstall.`);this.pluginName=n;this.version=r;this.name="AlreadyInstalledError";}};var so=/^[a-z0-9][a-z0-9-]{0,62}[a-z0-9]$|^[a-z0-9]$/;function ao(e){if(!so.test(e))throw new Error(`Invalid plugin name from manifest: "${e}". Plugin names must be lowercase alphanumeric and hyphens (1-64 chars).`)}function lo(e,t){return n=>{t&&console.log(`[${e}] ${n}`);}}function co(e,t){let n=`${e}@${J}`,o=W().plugins[n];if(o&&!t)throw new Q(e,o[0].version);return {pluginKey:n,alreadyInstalled:o}}async function uo(e,t,n,r){n&&await ot(t);try{r(`Extracting to ${t}...`),await rn(e,t);}catch(o){throw await ot(t),o}}function mo(e,t,n){let r=W(),o={scope:"user",installPath:t,version:n,installedAt:new Date().toISOString()};r.plugins[e]=[o],st(r),lt(e,true);}async function $e(e,t={}){let n=Date.now(),r=lo(e,t.verbose),o=null;try{r("Acquiring lock..."),o=await ae();let{pluginKey:i,alreadyInstalled:s}=co(e,t.force);r("Fetching manifest...");let a=await hn(e);ao(a.name),r("Downloading archive...");let d=await yn(e),c=tn(a.name);await uo(d,c,!!s&&!!t.force,r),mo(i,c,a.version);let f=Date.now()-n;return r(`Installed successfully in ${f}ms`),{name:a.name,version:a.version,path:c,duration_ms:f}}finally{o&&await o();}}function In(){let e=_(s=>s.installedItems),t=_(s=>s.setInstalledItems),n=useCallback(async s=>{await $e(s.name),_.getState().loadFromDisk();},[]),r=useCallback(async s=>{await Ce(s),t(e.filter(a=>a.name!==s));},[e,t]),o=useCallback(async s=>{let d=e.find(c=>c.name===s)?.status==="enabled"?"disabled":"enabled";await ce(s,d),t(e.map(c=>c.name===s?{...c,status:d}:c));},[e,t]),i=useCallback(async s=>{await wn(),t(e.map(a=>a.name===s?{...a,updateAvailable:false}:a));},[e,t]);return {install:n,uninstall:r,toggle:o,update:i}}function go(e){return {name:e.name,version:e.version,description:e.description,authorName:e.author.name,updateAvailable:e.updateAvailable}}function ho(e){return {name:e.name,version:e.version,description:e.description,authorName:e.author?.name,status:e.status,updateAvailable:e.updateAvailable,installedAt:e.installedAt}}function vn(){let e=m(u=>u.activeTab),t=m(u=>u.notification),n=m(u=>u.showNotification),r=m(u=>u.clearNotification),o=m(u=>u.loading),i=m(u=>u.loadingMessage),s=m(u=>u.catalogError),a=m(u=>u.setLoading),d=m(u=>u.setCatalogError),c=A(u=>u.query),{catalog:f,isLoading:N,error:O,refetch:x}=xn(),{items:$}=bn(),l=_(u=>u.loadFromDisk),p=useMemo(()=>new Set($.map(u=>`${u.name}|${u.author?.name??""}|${u.marketplace}`)),[$]),{install:g,uninstall:b,toggle:Y,update:On}=In(),mt=L(u=>u.justAuthenticated),Oe=L(u=>u.credentials),Fn=L(u=>u.setJustAuthenticated),Fe=e==="discover"?f.filter(u=>!p.has(`${u.name}|${u.author.name}|${J}`)).map(u=>go(u)):$.map(u=>ho(u)),{actionMenuOpen:pt,closeMenu:Be,selectedIndex:Bn,clampIndex:Ue,filteredItems:Un}=pn({listLength:Fe.length}),me=Un(Fe),y=me[Bn]??null;useEffect(()=>{l();},[]),useEffect(()=>{Ue(me.length);},[me.length,Ue]),useEffect(()=>{mt&&Oe&&(n(`Authenticated. Tenant: ${Oe.tenant}`,"success"),Fn(false));},[mt,Oe]),useEffect(()=>{if(!t)return;let u=setTimeout(r,3e3);return ()=>clearTimeout(u)},[t]),useEffect(()=>{O&&(console.error("[usePluginCatalog]",O),d("Failed to load catalog"));},[O]);let ft=(u,Z)=>{n(u,Z);},pe=async(u,Z,Jn)=>{a(true,u),Be();try{await Z();let fe=Fe.length;Ue(fe),ft(Jn,"success");}catch(fe){ft(fe instanceof Error?fe.message:"Something went wrong","error");}finally{a(false);}},jn=()=>{if(!y)return;let u=f.find(Z=>Z.name===y.name);u&&pe(`Installing ${y.name}...`,()=>g(u),"\u2713 Installed successfully");},_n=()=>{y&&pe(`Uninstalling ${y.name}...`,()=>b(y.name),"\u2713 Uninstalled");},Kn=()=>{if(!y)return;let u=y.status==="enabled";pe(u?`Disabling ${y.name}...`:`Enabling ${y.name}...`,()=>Y(y.name),u?"\u2713 Disabled":"\u2713 Enabled");},qn=e==="installed"?"No plugins installed \u2014 explore the Discover tab!":c?`No plugins found for '${c}'`:"No plugins available in the catalog",Hn=()=>{y&&pe(`Updating ${y.name}...`,()=>On(y.name),"\u2713 Updated");};return jsxs(Box,{flexDirection:"column",borderStyle:"round",paddingX:1,children:[jsx(Et,{}),jsx(Ct,{}),jsx(Bt,{filteredItems:me,emptyMessage:qn}),(o||N)&&jsx(Jt,{message:o?i:"Loading catalog..."}),s&&!N&&e==="discover"&&jsx(Gt,{message:s,onRetry:()=>{d(null),x();},onBack:()=>d(null)}),t&&jsx(_t,{message:t.message,type:t.type}),pt&&y&&e==="discover"&&jsx(Qt,{itemName:y.name,onInstall:jn,onClose:Be}),pt&&y&&e==="installed"&&jsx(en,{itemName:y.name,itemStatus:y.status??"enabled",updateAvailable:y.updateAvailable??false,onUninstall:_n,onToggleStatus:Kn,onUpdate:Hn,onClose:Be}),jsx(jt,{})]})}var Tn=S();if(Tn&&B()){let{clientSecret:e,...t}=Tn;L.getState().setCredentials(t),m.getState().setFocus("list");}else m.getState().setFocus("auth");function Pn(){return L(t=>t.isAuthenticated)?jsx(vn,{}):jsx(Tt,{})}function Me(e,t={}){return new Promise((n,r)=>{let{masked:o=false,defaultValue:i=""}=t;process.stdout.write(e+i);let s=i,a=f=>{if(f===""){d(),r(new Error("SIGINT"));return}if(f==="\r"||f===`
12
+ `){d(),process.stdout.write(`
13
+ `),n(s);return}if(f==="\x7F"){s.length>0&&(s=s.slice(0,-1),process.stdout.write("\b \b"));return}f.startsWith("\x1B")||(s+=f,process.stdout.write(o?"*".repeat(f.length):f));};function d(){process.stdin.setRawMode(false),process.stdin.removeListener("data",a),process.removeListener("uncaughtException",c),process.removeListener("unhandledRejection",c);}function c(){try{process.stdin.setRawMode(!1);}catch{}}process.on("uncaughtException",c),process.on("unhandledRejection",c),process.stdin.setRawMode(true),process.stdin.resume(),process.stdin.setEncoding("utf8"),process.stdin.on("data",a);})}async function wo(e){try{return await ne(e),process.stdout.write(h.green(` \u2713 Setup complete. Tenant: ${e.tenant}
14
14
 
15
15
  `)),0}catch(t){let n=w(t instanceof Error?t.message:"unknown error");return process.stderr.write(h.red(` \u2717 Authentication failed: ${n}
16
- `)),1}}async function hr(){try{process.stdout.write(`
16
+ `)),1}}async function xo(){try{process.stdout.write(`
17
17
  `);let e=(await Me(h.cyan(" ? ")+"Client ID: ")).trim(),t=(await Me(h.cyan(" ? ")+"Client Secret: ",{masked:!0})).trim(),n=(await Me(h.cyan(" ? ")+"Tenant: ")).trim();if(!e||!t||!n)return process.stderr.write(h.red(` \u2717 All fields are required
18
- `)),1;try{await ne({clientId:e,clientSecret:t,tenant:n});}catch(o){let r=w(o instanceof Error?o.message:"unknown error");return process.stderr.write(h.red(` \u2717 Authentication failed: ${r}
18
+ `)),1;try{await ne({clientId:e,clientSecret:t,tenant:n});}catch(r){let o=w(r instanceof Error?r.message:"unknown error");return process.stderr.write(h.red(` \u2717 Authentication failed: ${o}
19
19
  `)),1}return process.stdout.write(h.green(` \u2713 Setup complete. Tenant: ${n}
20
20
 
21
21
  `)),0}catch(e){if(e instanceof Error&&e.message==="SIGINT")throw e;let t=w(e instanceof Error?e.message:"unknown error");return process.stderr.write(h.red(` \u2717 Unexpected error: ${t}
22
- `)),1}}async function dt(e={}){if(e.clientId&&e.clientSecret&&e.tenant)return gr({clientId:e.clientId,clientSecret:e.clientSecret,tenant:e.tenant});try{return await hr()}catch(t){if(t instanceof Error&&t.message==="SIGINT")return process.stdout.write(`
23
- `),130;throw t}}async function yr(){try{return process.stdout.write(`
22
+ `)),1}}async function dt(e={}){if(e.clientId&&e.clientSecret&&e.tenant)return wo({clientId:e.clientId,clientSecret:e.clientSecret,tenant:e.tenant});try{return await xo()}catch(t){if(t instanceof Error&&t.message==="SIGINT")return process.stdout.write(`
23
+ `),130;throw t}}async function bo(){try{return process.stdout.write(`
24
24
  `),(await Me(h.cyan(" ? ")+"Are you sure? This will remove your local credentials. (y/N): ")).toLowerCase()!=="y"?(process.stdout.write(h.yellow(` \u26A0 Logout cancelled
25
25
  `)),0):null}catch(e){if(e instanceof Error&&e.message==="SIGINT")return process.stdout.write(`
26
- `),130;throw e}}async function Sn(e){if(!P())return process.stdout.write(h.yellow(` \u26A0 You are not authenticated
27
- `)),0;if(!e){let t=await yr();if(t!==null)return t}try{return wt(),process.stdout.write(h.green(` \u2713 Credentials removed successfully
26
+ `),130;throw e}}async function En(e){if(!S())return process.stdout.write(h.yellow(` \u26A0 You are not authenticated
27
+ `)),0;if(!e){let t=await bo();if(t!==null)return t}try{return wt(),process.stdout.write(h.green(` \u2713 Credentials removed successfully
28
28
  `)),0}catch{return process.stderr.write(h.red(` \u2717 Error removing credentials
29
- `)),1}}async function An(){let e=P();if(!e)return process.stdout.write(h.yellow(" \u26A0 Not authenticated. Run `npx @flow/cli` or `npx @flow/cli auth login` to set up.\n")),0;if(!N())return process.stdout.write(h.yellow(" \u26A0 Session expired. Run `npx @flow/cli auth login` to re-authenticate.\n")),0;let t=e.clientSecret.length>4?"****...****"+e.clientSecret.slice(-4):"****";return process.stdout.write(`
29
+ `)),1}}async function An(){let e=S();if(!e)return process.stdout.write(h.yellow(" \u26A0 Not authenticated. Run `npx @flow/cli` or `npx @flow/cli auth login` to set up.\n")),0;if(!B())return process.stdout.write(h.yellow(" \u26A0 Session expired. Run `npx @flow/cli auth login` to re-authenticate.\n")),0;let t=e.clientSecret.length>4?"****...****"+e.clientSecret.slice(-4):"****";return process.stdout.write(`
30
30
  `+h.bold(` Authenticated
31
31
  `)),process.stdout.write(h.dim(" Tenant: ")+w(e.tenant)+`
32
32
  `),process.stdout.write(h.dim(" Client ID: ")+w(e.clientId)+`
33
33
  `),process.stdout.write(h.dim(" Client Secret: ")+t+`
34
34
  `),process.stdout.write(h.dim(" Config: ")+w(xt())+`
35
35
  `),process.stdout.write(`
36
- `),0}function _(){return P()?true:(v("Not authenticated. Run: flow-plugins auth"),false)}async function wr(e){let t=k(),n;try{n=await X();}catch{n=[];}let o=new Set(t.map(r=>r.name));return e.json?(Te(n.map(r=>({...r,installed:o.has(r.name)}))),0):(Ie(["","Name","Version","Category","Status"],n.map(r=>[o.has(r.name)?"*":" ",r.name,r.version,r.category,o.has(r.name)?"installed":"available"])),0)}function xr(e){let n=k().filter(o=>o.updateAvailable);return n.length===0?(C("All plugins are up to date."),0):e.json?(Te(n),0):(Ie(["Name","Installed","Available"],n.map(o=>[o.name,o.version,"\u2014"])),process.stdout.write(`
36
+ `),0}function K(){return S()?true:(I("Not authenticated. Run: flow-plugins auth"),false)}async function Io(e){let t=k(),n;try{n=await X();}catch{n=[];}let r=new Set(t.map(o=>o.name));return e.json?(Te(n.map(o=>({...o,installed:r.has(o.name)}))),0):(ve(["","Name","Version","Category","Status"],n.map(o=>[r.has(o.name)?"*":" ",o.name,o.version,o.category,r.has(o.name)?"installed":"available"])),0)}function vo(e){let n=k().filter(r=>r.updateAvailable);return n.length===0?(C("All plugins are up to date."),0):e.json?(Te(n),0):(ve(["Name","Installed","Available"],n.map(r=>[r.name,r.version,"\u2014"])),process.stdout.write(`
37
37
  ${n.length} plugin(s) outdated.
38
- `),0)}function br(e){let t=k();return t.length===0?(C("No plugins installed. Use `flow plugin install <name>` to install one."),0):e.json?(Te(t),0):(Ie(["Name","Version","Installed at"],t.map(n=>[n.name,n.version,Pe(n.installedAt)])),process.stdout.write(`
38
+ `),0)}function To(e){let t=k();return t.length===0?(C("No plugins installed. Use `flow plugin install <name>` to install one."),0):e.json?(Te(t),0):(ve(["Name","Version","Installed at"],t.map(n=>[n.name,n.version,Se(n.installedAt)])),process.stdout.write(`
39
39
  ${t.length} plugin(s) installed.
40
- `),0)}async function En(e){if(!_())return 1;try{return e.available?await wr(e):e.outdated?xr(e):br(e)}catch(t){return v(t instanceof Error?t.message:"Failed to list plugins."),1}}function De(e){return e instanceof Error?e.message:String(e)}async function vr(e,t,n){n.silent||C(`${t}Installing ${e}...`);try{let o=await $e(e,n);return n.silent||z(`${t}${o.name} v${o.version} installed successfully`),{name:e,success:!0}}catch(o){if(o instanceof Q)return n.silent||C(`${t}${o.message}`),{name:e,success:true};let r=De(o);return v(`${t}Failed to install ${e}: ${r}`),{name:e,success:false,error:r}}}function Ir(e){let t=e.filter(o=>o.success).length,n=e.filter(o=>!o.success).length;C(`
41
- Installation summary: ${t} succeeded, ${n} failed`);}async function Cn(e,t={}){if(!_())return 1;let n=[];for(let o=0;o<e.length;o++){let r=e.length>1?`[${o+1}/${e.length}] `:"",i=await vr(e[o],r,t);n.push(i);}return e.length>1&&!t.silent&&Ir(n),n.some(o=>!o.success)?1:0}async function Rn(e,t){if(!_())return 1;if(!t.force){let n=k().find(s=>s.name===e);if(!n)return v(`Plugin "${e}" is not installed`),1;let o=w(n.name),r=w(n.version);if(!await Tr(`Remove ${o} v${r}? [y/N] `))return C("Operation cancelled."),0}try{return await Ce(e),z("Plugin removed successfully"),0}catch(n){return v(De(n)),1}}async function Tr(e){let n=(await import('readline')).default.createInterface({input:process.stdin,output:process.stdout});return new Promise(o=>{n.question(e,r=>{n.close(),o(r.toLowerCase()==="y");});})}async function kn(e){if(!_())return 1;let t=k().find(n=>n.name===e);if(!t)return v(`Plugin "${e}" is not installed`),1;if(t.status==="enabled")return C(`${t.name} is already enabled`),0;try{return await ce(e,"enabled"),z(`${t.name} enabled successfully`),0}catch(n){return v(De(n)),1}}async function $n(e){if(!_())return 1;let t=k().find(n=>n.name===e);if(!t)return v(`Plugin "${e}" is not installed`),1;if(t.status==="disabled")return C(`${t.name} is already disabled`),0;try{return await ce(e,"disabled"),z(`${t.name} disabled successfully`),0}catch(n){return v(De(n)),1}}async function Ln(e){return _()?(z(`${e} updated successfully`),0):1}function Er(){return P()?{passed:true,message:"Credentials configured"}:{passed:false,message:"Credentials not configured \u2014 Run `auth login`"}}async function Cr(){let e=Date.now();try{await X();let t=Date.now()-e;return {passed:!0,message:`Prompt Manager accessible (${t}ms)`,latency:t}}catch(t){return t instanceof Error&&t.name==="TimeoutError"?{passed:false,message:"Timeout after 5s \u2014 check your connection"}:{passed:false,message:`Connection error: ${t instanceof Error?t.message:"Unknown"}`}}}function Rr(){return N()?{passed:true,message:"Token is valid"}:{passed:false,message:"Token expired \u2014 run `auth login` to re-authenticate"}}function kr(){let e=join(homedir(),".claude","settings.json");return existsSync(e)?{passed:true,message:"Claude Code detected"}:{passed:false,message:"Claude Code not detected"}}async function Mn(){process.stdout.write(`
40
+ `),0)}async function Cn(e){if(!K())return 1;try{return e.available?await Io(e):e.outdated?vo(e):To(e)}catch(t){return I(t instanceof Error?t.message:"Failed to list plugins."),1}}function De(e){return e instanceof Error?e.message:String(e)}async function So(e,t,n){n.silent||C(`${t}Installing ${e}...`);try{let r=await $e(e,n);return n.silent||z(`${t}${r.name} v${r.version} installed successfully`),{name:e,success:!0}}catch(r){if(r instanceof Q)return n.silent||C(`${t}${r.message}`),{name:e,success:true};let o=De(r);return I(`${t}Failed to install ${e}: ${o}`),{name:e,success:false,error:o}}}function Po(e){let t=e.filter(r=>r.success).length,n=e.filter(r=>!r.success).length;C(`
41
+ Installation summary: ${t} succeeded, ${n} failed`);}async function Rn(e,t={}){if(!K())return 1;let n=[];for(let r=0;r<e.length;r++){let o=e.length>1?`[${r+1}/${e.length}] `:"",i=await So(e[r],o,t);n.push(i);}return e.length>1&&!t.silent&&Po(n),n.some(r=>!r.success)?1:0}async function kn(e,t){if(!K())return 1;if(!t.force){let n=k().find(s=>s.name===e);if(!n)return I(`Plugin "${e}" is not installed`),1;let r=w(n.name),o=w(n.version);if(!await Eo(`Remove ${r} v${o}? [y/N] `))return C("Operation cancelled."),0}try{return await Ce(e),z("Plugin removed successfully"),0}catch(n){return I(De(n)),1}}async function Eo(e){let n=(await import('readline')).default.createInterface({input:process.stdin,output:process.stdout});return new Promise(r=>{n.question(e,o=>{n.close(),r(o.toLowerCase()==="y");});})}async function $n(e){if(!K())return 1;let t=k().find(n=>n.name===e);if(!t)return I(`Plugin "${e}" is not installed`),1;if(t.status==="enabled")return C(`${t.name} is already enabled`),0;try{return await ce(e,"enabled"),z(`${t.name} enabled successfully`),0}catch(n){return I(De(n)),1}}async function Ln(e){if(!K())return 1;let t=k().find(n=>n.name===e);if(!t)return I(`Plugin "${e}" is not installed`),1;if(t.status==="disabled")return C(`${t.name} is already disabled`),0;try{return await ce(e,"disabled"),z(`${t.name} disabled successfully`),0}catch(n){return I(De(n)),1}}async function Mn(e){return K()?(z(`${e} updated successfully`),0):1}function ko(){return S()?{passed:true,message:"Credentials configured"}:{passed:false,message:"Credentials not configured \u2014 Run `auth login`"}}async function $o(){let e=Date.now();try{await X();let t=Date.now()-e;return {passed:!0,message:`Prompt Manager accessible (${t}ms)`,latency:t}}catch(t){return t instanceof Error&&t.name==="TimeoutError"?{passed:false,message:"Timeout after 5s \u2014 check your connection"}:{passed:false,message:`Connection error: ${t instanceof Error?t.message:"Unknown"}`}}}function Lo(){return B()?{passed:true,message:"Token is valid"}:{passed:false,message:"Token expired \u2014 run `auth login` to re-authenticate"}}function Mo(){let e=join(homedir(),".claude","settings.json");return existsSync(e)?{passed:true,message:"Claude Code detected"}:{passed:false,message:"Claude Code not detected"}}async function Dn(){process.stdout.write(`
42
42
  `+h.bold(` FlowSetup CLI Diagnostics
43
43
 
44
- `));let e=[{name:"Credentials",fn:Er},{name:"Prompt Manager",fn:Cr},{name:"Valid Token",fn:Rr},{name:"Claude Code",fn:kr}],t=true;for(let n of e){let o=await n.fn(),r="",i=h.green;o.passed?r=h.green("[OK] "):(r=h.red("[FAIL]"),i=h.red,t=false);let s=` ${r} ${i(n.name.padEnd(18))} ${w(o.message)}`;process.stdout.write(s+`
44
+ `));let e=[{name:"Credentials",fn:ko},{name:"Prompt Manager",fn:$o},{name:"Valid Token",fn:Lo},{name:"Claude Code",fn:Mo}],t=true;for(let n of e){let r=await n.fn(),o="",i=h.green;r.passed?o=h.green("[OK] "):(o=h.red("[FAIL]"),i=h.red,t=false);let s=` ${o} ${i(n.name.padEnd(18))} ${w(r.message)}`;process.stdout.write(s+`
45
45
  `);}return process.stdout.write(`
46
46
  `),t?(process.stdout.write(h.green(` \u2713 All checks passed!
47
47
 
48
48
  `)),0):(process.stdout.write(h.red(` \u2717 Some checks failed \u2014 verify your configuration
49
49
 
50
- `)),1)}function Dn(e){let t=new Command;t.name("flow").description("FlowSetup CLI \u2014 Manage Flow plugins in your Claude Code").version(`@flow/cli v${we}`,"-V, --version","Display the CLI version").addHelpText("after",`
50
+ `)),1)}function Nn(e){let t=new Command;t.name("flow").description("FlowSetup CLI \u2014 Manage Flow plugins in your Claude Code").version(`@flow/cli v${we}`,"-V, --version","Display the CLI version").addHelpText("after",`
51
51
  Without arguments, opens the interactive interface (TUI).
52
52
  Use 'flow <command> --help' for details on each command.`).action(()=>{e();});let n=new Command("setup").description("Configure the CLI by detecting Claude Code credentials");n.command("init").description("Initialize the Flow CLI configuration").addHelpText("after",`
53
53
  Examples:
54
- $ flow setup init`).action(async()=>{let i=await dt();process.exit(i);}),t.addCommand(n);let o=new Command("plugin").description("Manage plugins from the Findr catalog installed in your Claude Code");o.command("list").description("List available or installed plugins").option("--available","show full catalog with installation status",false).option("--outdated","show only plugins with updates available",false).option("--json","output as JSON",false).addHelpText("after",`
54
+ $ flow setup init`).action(async()=>{let i=await dt();process.exit(i);}),t.addCommand(n);let r=new Command("plugin").description("Manage plugins from the Findr catalog installed in your Claude Code");r.command("list").description("List available or installed plugins").option("--available","show full catalog with installation status",false).option("--outdated","show only plugins with updates available",false).option("--json","output as JSON",false).addHelpText("after",`
55
55
  Examples:
56
56
  $ flow plugin list
57
57
  $ flow plugin list --available
58
58
  $ flow plugin list --outdated
59
- $ flow plugin list --json`).action(async i=>{let s=await En(i);process.exit(s);}),o.command("install").description("Install one or more plugins from the Findr catalog into Claude Code").argument("<name...>","Name(s) of the plugin(s) to install (space-separated)").option("--force","Reinstall even if the version is already installed").option("--verbose","Display each step of the installation process").option("--silent","Output in JSON only").addHelpText("after",`
59
+ $ flow plugin list --json`).action(async i=>{let s=await Cn(i);process.exit(s);}),r.command("install").description("Install one or more plugins from the Findr catalog into Claude Code").argument("<name...>","Name(s) of the plugin(s) to install (space-separated)").option("--force","Reinstall even if the version is already installed").option("--verbose","Display each step of the installation process").option("--silent","Output in JSON only").addHelpText("after",`
60
60
  Examples:
61
61
  $ flow plugin install flow-adr-writer
62
62
  $ flow plugin install flow-adr-writer flow-prd-writer startup-pack-ai
63
63
  $ flow plugin install flow-adr-writer --force
64
- $ flow plugin install flow-adr-writer --silent`).action(async(i,s)=>{let a=await Cn(i,s);process.exit(a);}),o.command("uninstall").description("Remove an installed plugin from Claude Code").argument("<name>","Name of the plugin to remove").option("--force","Skip interactive confirmation").addHelpText("after",`
64
+ $ flow plugin install flow-adr-writer --silent`).action(async(i,s)=>{let a=await Rn(i,s);process.exit(a);}),r.command("uninstall").description("Remove an installed plugin from Claude Code").argument("<name>","Name of the plugin to remove").option("--force","Skip interactive confirmation").addHelpText("after",`
65
65
  Examples:
66
66
  $ flow plugin uninstall flow-adr-writer
67
- $ flow plugin uninstall startup-pack-ai --force`).action(async(i,s)=>{let a=await Rn(i,s);process.exit(a);}),o.command("update").description("Update plugins to the latest version").argument("[name]","Name of the plugin to update (omit to update all)").addHelpText("after",`
67
+ $ flow plugin uninstall startup-pack-ai --force`).action(async(i,s)=>{let a=await kn(i,s);process.exit(a);}),r.command("update").description("Update plugins to the latest version").argument("[name]","Name of the plugin to update (omit to update all)").addHelpText("after",`
68
68
  Examples:
69
69
  $ flow plugin update
70
- $ flow plugin update flow-adr-writer`).action(async i=>{if(i){let s=await Ln(i);process.exit(s);}else console.log("Update all plugins coming soon."),process.exit(0);}),o.command("enable").description("Enable an installed plugin").argument("<name>","Name of the plugin to enable").addHelpText("after",`
70
+ $ flow plugin update flow-adr-writer`).action(async i=>{if(i){let s=await Mn(i);process.exit(s);}else console.log("Update all plugins coming soon."),process.exit(0);}),r.command("enable").description("Enable an installed plugin").argument("<name>","Name of the plugin to enable").addHelpText("after",`
71
71
  Examples:
72
- $ flow plugin enable flow-adr-writer`).action(async i=>{let s=await kn(i);process.exit(s);}),o.command("disable").description("Disable an installed plugin").argument("<name>","Name of the plugin to disable").addHelpText("after",`
72
+ $ flow plugin enable flow-adr-writer`).action(async i=>{let s=await $n(i);process.exit(s);}),r.command("disable").description("Disable an installed plugin").argument("<name>","Name of the plugin to disable").addHelpText("after",`
73
73
  Examples:
74
- $ flow plugin disable flow-adr-writer`).action(async i=>{let s=await $n(i);process.exit(s);}),t.addCommand(o);let r=new Command("auth").description("Manage authentication credentials");return r.command("login").description("Authenticate and save credentials locally").option("--client-id <id>","Client ID for non-interactive authentication").option("--client-secret <secret>","Client Secret for non-interactive authentication").option("--tenant <tenant>","Tenant for non-interactive authentication").addHelpText("after",`
74
+ $ flow plugin disable flow-adr-writer`).action(async i=>{let s=await Ln(i);process.exit(s);}),t.addCommand(r);let o=new Command("auth").description("Manage authentication credentials");return o.command("login").description("Authenticate and save credentials locally").option("--client-id <id>","Client ID for non-interactive authentication").option("--client-secret <secret>","Client Secret for non-interactive authentication").option("--tenant <tenant>","Tenant for non-interactive authentication").addHelpText("after",`
75
75
  Examples:
76
76
  $ flow auth login
77
- $ flow auth login --client-id ID --client-secret SECRET --tenant TENANT`).action(async i=>{let s=await dt(i);process.exit(s);}),r.command("logout").description("Remove locally saved credentials").option("--force","Skip interactive confirmation").addHelpText("after",`
77
+ $ flow auth login --client-id ID --client-secret SECRET --tenant TENANT`).action(async i=>{let s=await dt(i);process.exit(s);}),o.command("logout").description("Remove locally saved credentials").option("--force","Skip interactive confirmation").addHelpText("after",`
78
78
  Examples:
79
79
  $ flow auth logout
80
- $ flow auth logout --force`).action(async i=>{let s=await Sn(i.force);process.exit(s);}),r.command("status").description("Display the current authentication status").addHelpText("after",`
80
+ $ flow auth logout --force`).action(async i=>{let s=await En(i.force);process.exit(s);}),o.command("status").description("Display the current authentication status").addHelpText("after",`
81
81
  Examples:
82
- $ flow auth status`).action(async()=>{let i=await An();process.exit(i);}),t.addCommand(r),t.command("health").description("Check the CLI configuration and connectivity").addHelpText("after",`
82
+ $ flow auth status`).action(async()=>{let i=await An();process.exit(i);}),t.addCommand(o),t.command("health").description("Check the CLI configuration and connectivity").addHelpText("after",`
83
83
  Examples:
84
- $ flow health`).action(async()=>{let i=await Mn();process.exit(i);}),t}var Lr=Dn(()=>{render(jsx(Pn,{}));});Lr.parse();
84
+ $ flow health`).action(async()=>{let i=await Dn();process.exit(i);}),t}var No=Nn(()=>{render(jsx(Pn,{}));});No.parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ciandt-flow/cli",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "TUI for browsing and installing Claude Code plugins from the Flow ecosystem",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -22,7 +22,7 @@
22
22
  "scripts": {
23
23
  "build": "npm run typecheck && tsup && npm run obfuscate",
24
24
  "build:npm": "npm run typecheck && tsup",
25
- "obfuscate": "javascript-obfuscator dist/index.js --output dist/index.js --options-preset medium-obfuscation --string-array true --string-array-encoding rc4",
25
+ "obfuscate": "javascript-obfuscator dist/index.js --output dist/index.js --options-preset medium-obfuscation --string-array true --string-array-encoding base64",
26
26
  "typecheck": "tsc --noEmit",
27
27
  "dev": "tsx --env-file=.env src/cli.tsx",
28
28
  "dev:watch": "tsup --watch & sleep 2 && node --watch dist/index.js",