@stackone/cli 1.43.0 → 1.43.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.cjs CHANGED
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node
2
- const e=require(`./agentConfig-KBkYYmMr.cjs`),t=require(`./cliCore-DYlbldYc.cjs`);require(`./setupMigration-rqPZ8MV6.cjs`),require(`./agentApiKey-BDp7EFMI.cjs`);let n=require(`dotenv`);process.env.DOTENV_CONFIG_QUIET=`true`,(0,n.config)(),new t.t().run();
2
+ const e=require(`./agentConfig-KBkYYmMr.cjs`),t=require(`./cliCore-mMrBxsVZ.cjs`);require(`./setupMigration-rqPZ8MV6.cjs`),require(`./agentApiKey-BDp7EFMI.cjs`);let n=require(`dotenv`);process.env.DOTENV_CONFIG_QUIET=`true`,(0,n.config)(),new t.t().run();
package/dist/cli.mjs CHANGED
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node
2
- import{t as e}from"./cliCore-DnpNl8Z6.mjs";import"./agentConfig-BWQWMYKQ.mjs";import"./setupMigration-C1ShGzOu.mjs";import"./agentApiKey-CWXxJgCO.mjs";import{config as t}from"dotenv";process.env.DOTENV_CONFIG_QUIET=`true`,t(),new e().run();export{};
2
+ import{t as e}from"./cliCore-CeD5mOhR.mjs";import"./agentConfig-BWQWMYKQ.mjs";import"./setupMigration-C1ShGzOu.mjs";import"./agentApiKey-CWXxJgCO.mjs";import{config as t}from"dotenv";process.env.DOTENV_CONFIG_QUIET=`true`,t(),new e().run();export{};
@@ -138,22 +138,22 @@ Error: `+(e instanceof Error?e.message:String(e)))),process.exit(1)}c?.stop(),y.
138
138
  `))}async executeOrchestratedBuild(e){let{provider:t,category:n,verbose:r}=e,i=n?` (${n})`:``;y.log(T.bold(`\nOrchestrated build: ${t}${i}\n`));let a=null,o=new Map;try{for await(let t of Ut(e))switch(t.type){case`phase_start`:{let e=Sn[t.phase]||`${t.phase}...`,n=t.model?T.dim(` (${dt(t.model)})`):``;a?.stop(),a=J(T.cyan(`[${t.phase}]${n} ${e}`)).start(),o.set(t.phase,Date.now());break}case`phase_complete`:{let e=o.get(t.phase),n=e===void 0?0:Math.round((Date.now()-e)/1e3);a?.succeed(T.green(`[${t.phase}] Done (${n}s)`)),a=null;break}case`phase_error`:a?.fail(T.red(`[${t.phase}] ${t.error}`)),a=null;break;case`agent_message`:wn(t,a,r);break}}catch(e){a?.fail(),y.error(T.red(`
139
139
  Error: `+(e instanceof Error?e.message:String(e)))),process.exit(1)}a?.stop(),y.log(T.green(`
140
140
  ✓ Build complete
141
- `))}};const wn=(e,t,n)=>{let r=e.message;switch(r.type){case`text`:n&&process.stdout.write(r.content??``);break;case`tool_call`:{let n=r.toolName??`unknown tool`;t&&(t.text=T.cyan(`[${e.phase}] Tool: ${n}`));break}case`tool_error`:y.error(T.red(`\n[${e.phase}] Tool error (${r.toolName}): ${r.error??`Unknown error`}`));break;case`error`:y.error(T.red(`\n[${e.phase}] ${r.error??`Unknown error`}`));break;default:break}};function Tn(e,t){switch(e.type){case`text`:t(null),process.stdout.write(e.content??``);break;case`tool_call`:{let n=e.toolName??`unknown tool`;t(J(T.cyan(`Tool: ${n}`)).start());break}case`tool_result`:t(null);break;case`tool_progress`:{let n=e.progress?.operation||e.toolName||`Working...`;t(J(T.cyan(`Tool: ${n}`)).start());break}case`tool_error`:t(null),y.error(T.red(`\nTool error (${e.toolName}): ${e.error??`Unknown error`}`));break;case`error`:t(null),y.error(T.red(`\n${e.error??`Unknown error`}`));break;case`done`:t(null);break;default:process.env.VERBOSE&&console.warn(`[AgentRun] Unknown message type:`,e.type);break}}const En=e=>{let t=e.trim();return t===`~`?I():t.startsWith(`~/`)?R(I(),t.slice(2)):t},Dn=(e,t,n)=>e?`global`:t?`local`:n?null:`global`,On=(e,t)=>e?.trim()||(t?null:process.cwd()),kn=e=>e.existingConfig?`overwrite`:An(e),An=e=>e.mode===`local`&&e.alreadyAuthed?`work`:`auth`,jn=(e,t)=>{switch(e){case`mode`:return t.mode===`local`?t.hasGit?`repo-confirm`:`path-input`:kn(t);case`repo-confirm`:return t.repoAccepted?kn(t):`path-input`;case`path-input`:return kn(t);case`overwrite`:return An(t);case`auth`:return`work`;default:return`done`}},Mn=(e,t)=>Te(`git`,[`-C`,e,...t],{encoding:`utf-8`,stdio:[`ignore`,`pipe`,`ignore`]}).trim(),Nn=e=>{try{let t=Mn(e,[`rev-parse`,`--show-toplevel`]);if(!t)return null;let n;try{n=Mn(e,[`remote`,`get-url`,`origin`])||void 0}catch{}return{root:t,remoteUrl:n}}catch{return null}},Pn=`connector-guide.md`,Fn=`<!-- BEGIN stackone-connector-guide -->`,In=`<!-- END stackone-connector-guide -->`,Ln=/^[a-z0-9][a-z0-9_-]*$/,Rn=e=>e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`),zn=e=>`<!-- Generated by \`stackone agent sync\` from @stackone/agent-harness@${e}. Edit upstream, not here. -->`,Bn=e=>{if(e.includes(`..`)||!Ln.test(e))throw Error(`Refusing unsafe path segment: ${JSON.stringify(e)}`)},Vn=(e,...t)=>{let n=_e(e),r=_e(n,...t);if(r!==n&&!r.startsWith(n+ve))throw Error(`Refusing path outside ${n}: ${r}`);return r},Hn=(e,...t)=>de(Vn(e,...t),`utf-8`),Un=(e,...t)=>de(Vn(e,...t)),Wn=()=>{let e=w(import.meta.url).resolve(`@stackone/agent-harness`),t=ge(e);for(let e=0;e<6;e++){if(N(R(t,`package.json`))&&N(R(t,`plugin`)))return t;let e=ge(t);if(e===t)break;t=e}return ge(ge(e))},Gn=()=>R(Wn(),`plugin`),Kn=e=>{try{let t=e?_e(e,`..`):Wn();return JSON.parse(Hn(t,`package.json`)).version??`unknown`}catch{return`unknown`}},qn=e=>{let t=e.charCodeAt(0)===65279?e.slice(1):e,n=t.match(/^---\n[\s\S]*?\n---\n?/);return n&&(t=t.slice(n[0].length)),t=t.replace(/^\s*<!--[\s\S]*?-->\s*/,``),t.trim()},Jn=(e,t,n)=>{let r=[Fn,zn(n),``,t,``,In].join(`
142
- `);if(e.includes(Fn)&&e.includes(In)){let t=RegExp(`${Rn(Fn)}[\\s\\S]*?${Rn(In)}`);return e.replace(t,r)}let i=e.replace(/\s*$/,``);return i.length>0?`${i}\n\n${r}\n`:`${r}\n`},Yn=e=>{let t=[];for(let n of P(e,{withFileTypes:!0}))if(n.isDirectory()){let r=Yn(Vn(e,n.name));t.push(...r.map(e=>R(n.name,e)))}else t.push(n.name);return t},Xn=(e,t)=>{if(!N(t))return!1;let n=Yn(e).sort(),r=Yn(t).sort();return n.length!==r.length||n.some((e,t)=>e!==r[t])?!1:n.every(n=>Un(e,n).equals(Un(t,n)))},Zn=(e,t)=>{fe(t,{recursive:!0,force:!0}),ue(ge(t),{recursive:!0}),le(e,t,{recursive:!0})},Qn=e=>N(e)?P(e,{withFileTypes:!0}).filter(e=>e.isDirectory()&&Ln.test(e.name)).filter(t=>N(Vn(e,t.name,`SKILL.md`))).map(e=>e.name).sort():[],$n=()=>({changed:[],unchanged:[],missing:[]}),er=(e,t,n,r)=>{let i=$n();for(let a of e){Bn(a);let e=Vn(t,a);if(!N(e)||!pe(e).isDirectory()){i.missing.push(a);continue}let o=Vn(n,a);if(Xn(e,o)){i.unchanged.push(a);continue}i.changed.push(a),r||Zn(e,o)}return i},tr=(e,t,n,r)=>{if(!N(Vn(e,Pn)))return`missing-source`;let i=qn(Hn(e,Pn)),a=Vn(t,`CLAUDE.md`),o=N(a)?Hn(t,`CLAUDE.md`):``,s=Jn(o,i,n);return s===o?`unchanged`:(r||me(a,s),`changed`)},nr=e=>{let t=_e(e.pluginDir??Gn()),n=_e(e.cwd),r=e.version??Kn(t),i=e.check??!1,a=Vn(n,`.claude`),o=Vn(t,`skills`),s=er(Qn(o),o,Vn(a,`skills`),i),c=tr(t,n,r,i),l=s.changed.length>0||c===`changed`,u=c!==`missing-source`||s.changed.length+s.unchanged.length>0;if(!i&&u){ue(a,{recursive:!0});let e={harnessVersion:r,skills:s.changed.concat(s.unchanged).sort(),guide:c!==`missing-source`};me(Vn(a,`.stackone-connector-env.json`),`${JSON.stringify(e,null,2)}\n`)}return{skills:s,guide:c,hasChanges:l}},rr=e=>{try{let t=e??Gn();return pe(t).isDirectory()?e?JSON.parse(Hn(_e(t,`..`),`package.json`)).name===`@stackone/agent-harness`:!0:!1}catch{return!1}},ir=({message:e,choices:t,initialIndex:n=0,onSelect:r,onCancel:i})=>{let[a,o]=G(()=>t.length?Math.min(Math.max(n,0),t.length-1):0);return V((e,n)=>{if(t.length===0){n.escape&&i?.();return}n.upArrow?o(e=>(e-1+t.length)%t.length):n.downArrow?o(e=>(e+1)%t.length):n.return?r(t[a].value):n.escape&&i?.()}),t.length===0?null:H.createElement(z,{flexDirection:`column`,paddingY:1},H.createElement(z,{borderStyle:`round`,borderColor:`cyan`,flexDirection:`column`,paddingX:2,paddingY:1},H.createElement(B,{bold:!0},e),H.createElement(z,{flexDirection:`column`,marginTop:1},t.map((e,t)=>H.createElement(B,{key:e.value,color:t===a?`#00af66`:`white`},t===a?`❯ `:` `,e.label)))),H.createElement(z,{marginTop:1},H.createElement(B,{dimColor:!0},`↑↓ to navigate • Enter to select`)))},ar=({message:e,initialValue:t=``,validate:n,onSubmit:r,onCancel:i})=>{let[a,o]=G(t),[s,c]=G(null);return V((e,t)=>{if(t.return){let e=n?n(a):!0;e===!0?r(a):c(e);return}if(t.escape){i?.();return}if(t.backspace||t.delete){o(e=>e.slice(0,-1)),c(null);return}e&&!t.ctrl&&!t.meta&&!t.tab&&!t.upArrow&&!t.downArrow&&(o(t=>t+e),c(null))}),H.createElement(z,{flexDirection:`column`,paddingY:1},H.createElement(B,{bold:!0},e),H.createElement(z,{marginTop:1},H.createElement(B,null,`> `),H.createElement(B,null,a),H.createElement(B,{inverse:!0},` `)),s&&H.createElement(z,{marginTop:1},H.createElement(B,{color:`red`},s)),H.createElement(z,{marginTop:1},H.createElement(B,{dimColor:!0},`Enter to submit • Esc to cancel`)))},or=e=>N(`${e}/CLAUDE.md`)||N(`${e}/.mcp.json`),sr=e=>{try{return pe(e).isDirectory()}catch{return!1}},cr=({initialMode:e,pathFlag:t,startDir:n,onExit:r})=>{let[i,o]=G(`mode`),[c,u]=G(null),[f,p]=G(!1),[h,g]=G([]),[v,y]=G(``),[b,x]=G(e),[C,te]=G(``),[w,T]=G(``),[E,ne]=G(!1),[D,re]=G(null),ie=W(0),ae=xe(e=>{ie.current+=1;let t=ie.current;g(n=>[...n,{...e,id:t}])},[]),O=xe(e=>{u(e)},[]),oe=xe(async e=>{let t=_e(En(e));if(!sr(t)){O({status:`error`,message:N(t)?`Target path is not a directory: ${t}`:`Target path does not exist: ${t}`});return}te(t);let n=or(t),r=d(await ee());ne(r),o(jn(`path-input`,{mode:`local`,hasGit:!1,repoAccepted:!1,existingConfig:n,alreadyAuthed:r}))},[O]),se=xe(e=>{if(x(e),e===`local`){let e=t?.trim();if(e){oe(e);return}let r=Nn(n);r&&(T(`Install the connector setup into this repo? ${r.remoteUrl?`${r.remoteUrl} (${r.root})`:r.root}`),te(r.root)),o(jn(`mode`,{mode:`local`,hasGit:!!r,repoAccepted:!1,existingConfig:!1,alreadyAuthed:!1}));return}o(jn(`mode`,{mode:`global`,hasGit:!1,repoAccepted:!1,existingConfig:or(n),alreadyAuthed:!1}))},[t,n,oe]);U(()=>{e&&se(e)},[]);let k=xe(e=>{e?oe(C):o(`path-input`)},[oe,C]),A=xe(e=>{if(!e){O({status:`cancelled`});return}o(jn(`overwrite`,{mode:b??`global`,hasGit:!1,repoAccepted:!1,existingConfig:!0,alreadyAuthed:E}))},[b,E,O]);return U(()=>{if(i!==`auth`)return;let e=!1;return y(`Starting browser authentication…`),vn(t=>{e||y(t)}).then(t=>{e||(re(t),ae({icon:`✓`,text:t.email?`Authenticated as ${t.email}`:`Authenticated`,color:Q.success}),o(`work`))}).catch(t=>{e||O({status:`error`,message:t instanceof Error?t.message:`Authentication failed`})}),()=>{e=!0}},[i,ae,O]),U(()=>{if(i!==`work`)return;let e=!1;return(async()=>{try{let t=D??await ee();if(!t)throw Error(`Not authenticated — no API key found`);let r=await S(b===`local`?C:n,t.apiKey);if(r.migrated&&ae({icon:`✓`,text:`Migrated ${r.actions.length} item(s) from a previous setup`,color:Q.success}),b===`local`){y(`Creating .mcp.json…`),l(m(C),s(),t.apiKey),ae({icon:`✓`,text:`Created .mcp.json`,color:Q.success}),y(`Syncing connector-building skills + guide…`);let e=nr({cwd:C});ae({icon:`✓`,text:`Connector environment ready (${e.skills.changed.length+e.skills.unchanged.length} skills in .claude/, ${e.guide===`missing-source`?`guide unavailable in this version`:`guide in CLAUDE.md`})`,color:Q.success})}else y(`Installing global MCP configuration…`),l(a(),_(),t.apiKey),ae({icon:`✓`,text:`Installed to Claude (global)`,color:Q.success});if(e)return;y(``),O({status:`done`})}catch(t){if(e)return;O({status:`error`,message:t instanceof Error?t.message:`Setup failed`})}})(),()=>{e=!0}},[i,D,b,C,n,ae,O]),U(()=>{if(!c)return;let e=setTimeout(()=>r(c),60);return()=>clearTimeout(e)},[c,r]),H.createElement(z,{flexDirection:`column`,padding:1},f?H.createElement(Ct,{wordmark:!0}):H.createElement(Tt,{ready:!0,onComplete:()=>p(!0)}),h.length>0&&H.createElement(z,{flexDirection:`column`,marginTop:1},h.map(e=>H.createElement(B,{key:e.id,color:e.color},e.icon?`${e.icon} `:``,e.text))),H.createElement(z,{marginTop:1},(()=>{if(c)return c.status===`error`?H.createElement(B,{color:Q.error},`✗ `,c.message??`Setup failed`):c.status===`cancelled`?H.createElement(B,{color:Q.dim},`Setup cancelled.`):H.createElement(z,{flexDirection:`column`},H.createElement(B,{color:Q.success},`✓ Setup complete!`),H.createElement(z,{marginTop:1,flexDirection:`column`},H.createElement(B,{color:Q.dim},`Verify with `,H.createElement(B,{color:Q.primary},`claude mcp list`)),H.createElement(B,{color:Q.dim},`Tip: run`,` `,H.createElement(B,{color:Q.primary},`claude --dangerously-skip-permissions`),` `,`to skip permission prompts`),b===`local`&&H.createElement(B,{color:Q.dim},`Refresh skills anytime with`,` `,H.createElement(B,{color:Q.primary},`stackone agent sync`))));switch(i){case`mode`:return e?null:H.createElement(ir,{message:`How do you want to set up the StackOne agent?`,initialIndex:0,choices:[{label:`Local — this project: auth + .mcp.json + connector skills (.claude/) + guide (CLAUDE.md)`,value:`local`},{label:`Global — any repo: auth + global MCP only (no connector skills/guide)`,value:`global`}],onSelect:e=>se(e),onCancel:()=>O({status:`cancelled`})});case`repo-confirm`:return H.createElement(ir,{message:w,initialIndex:0,choices:[{label:`Yes`,value:`yes`},{label:`No, let me choose a path`,value:`no`}],onSelect:e=>k(e===`yes`),onCancel:()=>O({status:`cancelled`})});case`path-input`:return H.createElement(ar,{message:`Path to install the connector setup into:`,initialValue:n,validate:e=>{let t=En(e)||n;return N(t)?sr(t)?!0:`Path is not a directory: ${t}`:`Path does not exist: ${t}`},onSubmit:e=>void oe(e.trim()||n),onCancel:()=>O({status:`cancelled`})});case`overwrite`:{let e=b===`local`;return H.createElement(ir,{message:e?`Existing setup found in ${C}. Overwrite it?`:`Local setup detected in ${n} (it won't be modified). Set up the agent globally anyway?`,initialIndex:e?1:0,choices:[{label:e?`Yes, overwrite`:`Yes, set up globally`,value:`yes`},{label:`No, cancel`,value:`no`}],onSelect:e=>A(e===`yes`),onCancel:()=>O({status:`cancelled`})})}case`auth`:case`work`:return H.createElement(B,null,H.createElement(B,{color:Q.primary},H.createElement(De,{type:`dots`})),` `,v);default:return null}})()))},lr=e=>new Promise(t=>{let{unmount:n}=ye(e(e=>{n(),t(e)}))}),ur=()=>lr(e=>H.createElement(ir,{message:`How do you want to set up the StackOne agent?`,initialIndex:0,choices:[{label:`Local — this project: auth + .mcp.json + connector skills (.claude/) + guide (CLAUDE.md)`,value:`local`},{label:`Global — any repo: auth + global MCP only (no connector skills/guide)`,value:`global`}],onSelect:t=>e(t)})),dr=(e,t=!0)=>lr(n=>H.createElement(ir,{message:e,initialIndex:t?0:1,choices:[{label:`Yes`,value:`yes`},{label:`No`,value:`no`}],onSelect:e=>n(e===`yes`),onCancel:()=>n(!1)})),fr=async e=>{let t=Nn(e);return t&&await dr(`Install the connector setup into this repo? ${t.remoteUrl?`${t.remoteUrl} (${t.root})`:t.root}`,!0)?t.root:lr(n=>H.createElement(ar,{message:t?`Path to install into:`:`Current directory is not a git repo. Path to install into:`,initialValue:e,validate:t=>{let n=En(t)||e;return N(n)?!0:`Path does not exist: ${n}`},onSubmit:t=>n(En(t)||e)}))},pr=e=>new Promise(t=>{let{unmount:n}=ye(H.createElement(cr,{initialMode:e.initialMode,pathFlag:e.pathFlag,startDir:e.startDir??process.cwd(),onExit:e=>{n(),t(e)}}))});var mr=class{async execute(e){y.log(T.blue.bold(`🤖 StackOne Agent Setup - Local Project
141
+ `))}};const wn=(e,t,n)=>{let r=e.message;switch(r.type){case`text`:n&&process.stdout.write(r.content??``);break;case`tool_call`:{let n=r.toolName??`unknown tool`;t&&(t.text=T.cyan(`[${e.phase}] Tool: ${n}`));break}case`tool_error`:y.error(T.red(`\n[${e.phase}] Tool error (${r.toolName}): ${r.error??`Unknown error`}`));break;case`error`:y.error(T.red(`\n[${e.phase}] ${r.error??`Unknown error`}`));break;default:break}};function Tn(e,t){switch(e.type){case`text`:t(null),process.stdout.write(e.content??``);break;case`tool_call`:{let n=e.toolName??`unknown tool`;t(J(T.cyan(`Tool: ${n}`)).start());break}case`tool_result`:t(null);break;case`tool_progress`:{let n=e.progress?.operation||e.toolName||`Working...`;t(J(T.cyan(`Tool: ${n}`)).start());break}case`tool_error`:t(null),y.error(T.red(`\nTool error (${e.toolName}): ${e.error??`Unknown error`}`));break;case`error`:t(null),y.error(T.red(`\n${e.error??`Unknown error`}`));break;case`done`:t(null);break;default:process.env.VERBOSE&&console.warn(`[AgentRun] Unknown message type:`,e.type);break}}const En=e=>{let t=e.trim();return t===`~`?I():t.startsWith(`~/`)?R(I(),t.slice(2)):t},Dn=(e,t,n)=>e?`global`:t?`local`:n?null:`global`,On=(e,t)=>e?.trim()||(t?null:process.cwd()),kn=e=>e.existingConfig?`overwrite`:An(e),An=e=>e.mode===`local`&&e.alreadyAuthed?`work`:`auth`,jn=(e,t)=>{switch(e){case`mode`:return t.mode===`local`?t.hasGit?`repo-confirm`:`path-input`:kn(t);case`repo-confirm`:return t.repoAccepted?kn(t):`path-input`;case`path-input`:return kn(t);case`overwrite`:return An(t);case`auth`:return`work`;default:return`done`}},Mn=(e,t)=>Te(`git`,[`-C`,e,...t],{encoding:`utf-8`,stdio:[`ignore`,`pipe`,`ignore`]}).trim(),Nn=e=>{try{let t=Mn(e,[`rev-parse`,`--show-toplevel`]);if(!t)return null;let n;try{n=Mn(e,[`remote`,`get-url`,`origin`])||void 0}catch{}return{root:t,remoteUrl:n}}catch{return null}},Pn=`connector-guide.md`,Fn=`<!-- BEGIN stackone-connector-guide -->`,In=`<!-- END stackone-connector-guide -->`,Ln=/^[a-z0-9][a-z0-9_-]*$/,Rn=e=>e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`),zn=e=>`<!-- Generated by \`stackone agent sync\` from @stackone/agent-harness@${e}. Edit upstream, not here. -->`,Bn=e=>{if(e.includes(`..`)||!Ln.test(e))throw Error(`Refusing unsafe path segment: ${JSON.stringify(e)}`)},Vn=e=>{let t=e.split(`/`);if(t.length===0)throw Error(`Refusing empty path: ${JSON.stringify(e)}`);for(let e of t)Bn(e)},Hn=(e,...t)=>{let n=_e(e),r=_e(n,...t);if(r!==n&&!r.startsWith(n+ve))throw Error(`Refusing path outside ${n}: ${r}`);return r},Un=(e,...t)=>de(Hn(e,...t),`utf-8`),Wn=(e,...t)=>de(Hn(e,...t)),Gn=()=>{let e=w(import.meta.url).resolve(`@stackone/agent-harness`),t=ge(e);for(let e=0;e<6;e++){if(N(R(t,`package.json`))&&N(R(t,`plugin`)))return t;let e=ge(t);if(e===t)break;t=e}return ge(ge(e))},Kn=()=>R(Gn(),`plugin`),qn=e=>{try{let t=e?_e(e,`..`):Gn();return JSON.parse(Un(t,`package.json`)).version??`unknown`}catch{return`unknown`}},Jn=e=>{let t=e.charCodeAt(0)===65279?e.slice(1):e,n=t.match(/^---\n[\s\S]*?\n---\n?/);return n&&(t=t.slice(n[0].length)),t=t.replace(/^\s*<!--[\s\S]*?-->\s*/,``),t.trim()},Yn=(e,t,n)=>{let r=[Fn,zn(n),``,t,``,In].join(`
142
+ `);if(e.includes(Fn)&&e.includes(In)){let t=RegExp(`${Rn(Fn)}[\\s\\S]*?${Rn(In)}`);return e.replace(t,r)}let i=e.replace(/\s*$/,``);return i.length>0?`${i}\n\n${r}\n`:`${r}\n`},Xn=e=>{let t=[];for(let n of P(e,{withFileTypes:!0}))if(n.isDirectory()){let r=Xn(Hn(e,n.name));t.push(...r.map(e=>R(n.name,e)))}else t.push(n.name);return t},Zn=(e,t)=>{if(!N(t))return!1;let n=Xn(e).sort(),r=Xn(t).sort();return n.length!==r.length||n.some((e,t)=>e!==r[t])?!1:n.every(n=>Wn(e,n).equals(Wn(t,n)))},Qn=(e,t)=>{fe(t,{recursive:!0,force:!0}),ue(ge(t),{recursive:!0}),le(e,t,{recursive:!0})},$n=(e,t=``)=>{if(!N(e))return[];let n=[];for(let r of P(e,{withFileTypes:!0})){if(!r.isDirectory()||!Ln.test(r.name))continue;let i=t?`${t}/${r.name}`:r.name;if(N(Hn(e,r.name,`SKILL.md`))){n.push(i);continue}n.push(...$n(Hn(e,r.name),i))}return n.sort()},er=()=>({changed:[],unchanged:[],missing:[]}),tr=(e,t,n,r)=>{let i=er();for(let a of e){Vn(a);let e=Hn(t,a);if(!N(e)||!pe(e).isDirectory()){i.missing.push(a);continue}let o=Hn(n,a);if(Zn(e,o)){i.unchanged.push(a);continue}i.changed.push(a),r||Qn(e,o)}return i},nr=(e,t,n,r)=>{if(!N(Hn(e,Pn)))return`missing-source`;let i=Jn(Un(e,Pn)),a=Hn(t,`CLAUDE.md`),o=N(a)?Un(t,`CLAUDE.md`):``,s=Yn(o,i,n);return s===o?`unchanged`:(r||me(a,s),`changed`)},rr=e=>{let t=_e(e.pluginDir??Kn()),n=_e(e.cwd),r=e.version??qn(t),i=e.check??!1,a=Hn(n,`.claude`),o=Hn(t,`skills`),s=tr($n(o),o,Hn(a,`skills`),i),c=nr(t,n,r,i),l=s.changed.length>0||c===`changed`,u=c!==`missing-source`||s.changed.length+s.unchanged.length>0;if(!i&&u){ue(a,{recursive:!0});let e={harnessVersion:r,skills:s.changed.concat(s.unchanged).sort(),guide:c!==`missing-source`};me(Hn(a,`.stackone-connector-env.json`),`${JSON.stringify(e,null,2)}\n`)}return{skills:s,guide:c,hasChanges:l}},ir=e=>{try{let t=e??Kn();return pe(t).isDirectory()?e?JSON.parse(Un(_e(t,`..`),`package.json`)).name===`@stackone/agent-harness`:!0:!1}catch{return!1}},ar=({message:e,choices:t,initialIndex:n=0,onSelect:r,onCancel:i})=>{let[a,o]=G(()=>t.length?Math.min(Math.max(n,0),t.length-1):0);return V((e,n)=>{if(t.length===0){n.escape&&i?.();return}n.upArrow?o(e=>(e-1+t.length)%t.length):n.downArrow?o(e=>(e+1)%t.length):n.return?r(t[a].value):n.escape&&i?.()}),t.length===0?null:H.createElement(z,{flexDirection:`column`,paddingY:1},H.createElement(z,{borderStyle:`round`,borderColor:`cyan`,flexDirection:`column`,paddingX:2,paddingY:1},H.createElement(B,{bold:!0},e),H.createElement(z,{flexDirection:`column`,marginTop:1},t.map((e,t)=>H.createElement(B,{key:e.value,color:t===a?`#00af66`:`white`},t===a?`❯ `:` `,e.label)))),H.createElement(z,{marginTop:1},H.createElement(B,{dimColor:!0},`↑↓ to navigate • Enter to select`)))},or=({message:e,initialValue:t=``,validate:n,onSubmit:r,onCancel:i})=>{let[a,o]=G(t),[s,c]=G(null);return V((e,t)=>{if(t.return){let e=n?n(a):!0;e===!0?r(a):c(e);return}if(t.escape){i?.();return}if(t.backspace||t.delete){o(e=>e.slice(0,-1)),c(null);return}e&&!t.ctrl&&!t.meta&&!t.tab&&!t.upArrow&&!t.downArrow&&(o(t=>t+e),c(null))}),H.createElement(z,{flexDirection:`column`,paddingY:1},H.createElement(B,{bold:!0},e),H.createElement(z,{marginTop:1},H.createElement(B,null,`> `),H.createElement(B,null,a),H.createElement(B,{inverse:!0},` `)),s&&H.createElement(z,{marginTop:1},H.createElement(B,{color:`red`},s)),H.createElement(z,{marginTop:1},H.createElement(B,{dimColor:!0},`Enter to submit • Esc to cancel`)))},sr=e=>N(`${e}/CLAUDE.md`)||N(`${e}/.mcp.json`),cr=e=>{try{return pe(e).isDirectory()}catch{return!1}},lr=({initialMode:e,pathFlag:t,startDir:n,onExit:r})=>{let[i,o]=G(`mode`),[c,u]=G(null),[f,p]=G(!1),[h,g]=G([]),[v,y]=G(``),[b,x]=G(e),[C,te]=G(``),[w,T]=G(``),[E,ne]=G(!1),[D,re]=G(null),ie=W(0),ae=xe(e=>{ie.current+=1;let t=ie.current;g(n=>[...n,{...e,id:t}])},[]),O=xe(e=>{u(e)},[]),oe=xe(async e=>{let t=_e(En(e));if(!cr(t)){O({status:`error`,message:N(t)?`Target path is not a directory: ${t}`:`Target path does not exist: ${t}`});return}te(t);let n=sr(t),r=d(await ee());ne(r),o(jn(`path-input`,{mode:`local`,hasGit:!1,repoAccepted:!1,existingConfig:n,alreadyAuthed:r}))},[O]),se=xe(e=>{if(x(e),e===`local`){let e=t?.trim();if(e){oe(e);return}let r=Nn(n);r&&(T(`Install the connector setup into this repo? ${r.remoteUrl?`${r.remoteUrl} (${r.root})`:r.root}`),te(r.root)),o(jn(`mode`,{mode:`local`,hasGit:!!r,repoAccepted:!1,existingConfig:!1,alreadyAuthed:!1}));return}o(jn(`mode`,{mode:`global`,hasGit:!1,repoAccepted:!1,existingConfig:sr(n),alreadyAuthed:!1}))},[t,n,oe]);U(()=>{e&&se(e)},[]);let k=xe(e=>{e?oe(C):o(`path-input`)},[oe,C]),A=xe(e=>{if(!e){O({status:`cancelled`});return}o(jn(`overwrite`,{mode:b??`global`,hasGit:!1,repoAccepted:!1,existingConfig:!0,alreadyAuthed:E}))},[b,E,O]);return U(()=>{if(i!==`auth`)return;let e=!1;return y(`Starting browser authentication…`),vn(t=>{e||y(t)}).then(t=>{e||(re(t),ae({icon:`✓`,text:t.email?`Authenticated as ${t.email}`:`Authenticated`,color:Q.success}),o(`work`))}).catch(t=>{e||O({status:`error`,message:t instanceof Error?t.message:`Authentication failed`})}),()=>{e=!0}},[i,ae,O]),U(()=>{if(i!==`work`)return;let e=!1;return(async()=>{try{let t=D??await ee();if(!t)throw Error(`Not authenticated — no API key found`);let r=await S(b===`local`?C:n,t.apiKey);if(r.migrated&&ae({icon:`✓`,text:`Migrated ${r.actions.length} item(s) from a previous setup`,color:Q.success}),b===`local`){y(`Creating .mcp.json…`),l(m(C),s(),t.apiKey),ae({icon:`✓`,text:`Created .mcp.json`,color:Q.success}),y(`Syncing connector-building skills + guide…`);let e=rr({cwd:C});ae({icon:`✓`,text:`Connector environment ready (${e.skills.changed.length+e.skills.unchanged.length} skills in .claude/, ${e.guide===`missing-source`?`guide unavailable in this version`:`guide in CLAUDE.md`})`,color:Q.success})}else y(`Installing global MCP configuration…`),l(a(),_(),t.apiKey),ae({icon:`✓`,text:`Installed to Claude (global)`,color:Q.success});if(e)return;y(``),O({status:`done`})}catch(t){if(e)return;O({status:`error`,message:t instanceof Error?t.message:`Setup failed`})}})(),()=>{e=!0}},[i,D,b,C,n,ae,O]),U(()=>{if(!c)return;let e=setTimeout(()=>r(c),60);return()=>clearTimeout(e)},[c,r]),H.createElement(z,{flexDirection:`column`,padding:1},f?H.createElement(Ct,{wordmark:!0}):H.createElement(Tt,{ready:!0,onComplete:()=>p(!0)}),h.length>0&&H.createElement(z,{flexDirection:`column`,marginTop:1},h.map(e=>H.createElement(B,{key:e.id,color:e.color},e.icon?`${e.icon} `:``,e.text))),H.createElement(z,{marginTop:1},(()=>{if(c)return c.status===`error`?H.createElement(B,{color:Q.error},`✗ `,c.message??`Setup failed`):c.status===`cancelled`?H.createElement(B,{color:Q.dim},`Setup cancelled.`):H.createElement(z,{flexDirection:`column`},H.createElement(B,{color:Q.success},`✓ Setup complete!`),H.createElement(z,{marginTop:1,flexDirection:`column`},H.createElement(B,{color:Q.dim},`Verify with `,H.createElement(B,{color:Q.primary},`claude mcp list`)),H.createElement(B,{color:Q.dim},`Tip: run`,` `,H.createElement(B,{color:Q.primary},`claude --dangerously-skip-permissions`),` `,`to skip permission prompts`),b===`local`&&H.createElement(B,{color:Q.dim},`Refresh skills anytime with`,` `,H.createElement(B,{color:Q.primary},`stackone agent sync`))));switch(i){case`mode`:return e?null:H.createElement(ar,{message:`How do you want to set up the StackOne agent?`,initialIndex:0,choices:[{label:`Local — this project: auth + .mcp.json + connector skills (.claude/) + guide (CLAUDE.md)`,value:`local`},{label:`Global — any repo: auth + global MCP only (no connector skills/guide)`,value:`global`}],onSelect:e=>se(e),onCancel:()=>O({status:`cancelled`})});case`repo-confirm`:return H.createElement(ar,{message:w,initialIndex:0,choices:[{label:`Yes`,value:`yes`},{label:`No, let me choose a path`,value:`no`}],onSelect:e=>k(e===`yes`),onCancel:()=>O({status:`cancelled`})});case`path-input`:return H.createElement(or,{message:`Path to install the connector setup into:`,initialValue:n,validate:e=>{let t=En(e)||n;return N(t)?cr(t)?!0:`Path is not a directory: ${t}`:`Path does not exist: ${t}`},onSubmit:e=>void oe(e.trim()||n),onCancel:()=>O({status:`cancelled`})});case`overwrite`:{let e=b===`local`;return H.createElement(ar,{message:e?`Existing setup found in ${C}. Overwrite it?`:`Local setup detected in ${n} (it won't be modified). Set up the agent globally anyway?`,initialIndex:e?1:0,choices:[{label:e?`Yes, overwrite`:`Yes, set up globally`,value:`yes`},{label:`No, cancel`,value:`no`}],onSelect:e=>A(e===`yes`),onCancel:()=>O({status:`cancelled`})})}case`auth`:case`work`:return H.createElement(B,null,H.createElement(B,{color:Q.primary},H.createElement(De,{type:`dots`})),` `,v);default:return null}})()))},ur=e=>new Promise(t=>{let{unmount:n}=ye(e(e=>{n(),t(e)}))}),dr=()=>ur(e=>H.createElement(ar,{message:`How do you want to set up the StackOne agent?`,initialIndex:0,choices:[{label:`Local — this project: auth + .mcp.json + connector skills (.claude/) + guide (CLAUDE.md)`,value:`local`},{label:`Global — any repo: auth + global MCP only (no connector skills/guide)`,value:`global`}],onSelect:t=>e(t)})),fr=(e,t=!0)=>ur(n=>H.createElement(ar,{message:e,initialIndex:t?0:1,choices:[{label:`Yes`,value:`yes`},{label:`No`,value:`no`}],onSelect:e=>n(e===`yes`),onCancel:()=>n(!1)})),pr=async e=>{let t=Nn(e);return t&&await fr(`Install the connector setup into this repo? ${t.remoteUrl?`${t.remoteUrl} (${t.root})`:t.root}`,!0)?t.root:ur(n=>H.createElement(or,{message:t?`Path to install into:`:`Current directory is not a git repo. Path to install into:`,initialValue:e,validate:t=>{let n=En(t)||e;return N(n)?!0:`Path does not exist: ${n}`},onSubmit:t=>n(En(t)||e)}))},mr=e=>new Promise(t=>{let{unmount:n}=ye(H.createElement(lr,{initialMode:e.initialMode,pathFlag:e.pathFlag,startDir:e.startDir??process.cwd(),onExit:e=>{n(),t(e)}}))});var hr=class{async execute(e){y.log(T.blue.bold(`🤖 StackOne Agent Setup - Local Project
143
143
  `));try{let t=_e(En(e?.targetPath??process.cwd()));await Le(t).then(()=>!0).catch(()=>!1)||(y.error(`Target path does not exist: ${t}`),process.exit(1)),e?.targetPath&&y.log(T.dim(`Installing into ${t}\n`));let n=await Le(`${t}/CLAUDE.md`).then(()=>!0).catch(()=>!1),r=await Le(`${t}/.mcp.json`).then(()=>!0).catch(()=>!1);if(n||r){y.warn(`Existing local setup detected:`),n&&y.log(T.dim(` • CLAUDE.md found`)),r&&y.log(T.dim(` • .mcp.json found`)),y.log(``);let t=on(!!e?.legacy,e?.credentials),i=!!process.stdin.isTTY;t||!i?y.log(T.dim(t?`Non-interactive credentials detected; proceeding without confirmation.
144
144
  `:`No interactive terminal detected; proceeding without overwrite confirmation.
145
- `)):(await dr(`Overwrite existing local configuration?`,!1)||(y.log(T.dim(`
145
+ `)):(await fr(`Overwrite existing local configuration?`,!1)||(y.log(T.dim(`
146
146
  Setup cancelled.`)),process.exit(0)),y.log(``))}let i=await ee();(!i||!d(i))&&(y.warn(`Not authenticated globally.`),y.log(T.white(`Let's authenticate now...
147
147
  `)),i=await yn(!!e?.legacy,e?.credentials),y.log(``)),C(await S(t,i.apiKey));let a=J(`Creating .mcp.json...`).start();try{l(m(t),s(),i.apiKey),a.succeed(`Created .mcp.json`),y.success(`Local setup complete!`),y.log(T.white(`Files created:`)),y.log(T.cyan(` • .mcp.json`)),y.log(T.dim(`Token stored securely in Claude MCP server config.`)),y.log(T.dim(`
148
148
  💡 The stackone-agent-local MCP server is now available in this project`)),y.log(T.dim(`
149
149
  💡 Tip: Run Claude without permission prompts:`),T.cyan(`claude --dangerously-skip-permissions`)),y.log(T.blue(`
150
- Verify:`),T.cyan(`claude mcp list`)),y.log(``)}catch(e){a.fail(`Failed to create .mcp.json`),e instanceof Error&&y.error(e.message)}let o=J(`Syncing connector-building skills + guide...`).start();try{let e=nr({cwd:t}),n=e.skills.changed.length+e.skills.unchanged.length,r=e.guide===`missing-source`?`unavailable in this version`:`in CLAUDE.md`;o.succeed(`Connector-building environment ready (${n} skills in .claude/, guide ${r})`),y.log(T.dim(` Refresh anytime with`),T.cyan(`stackone agent sync`))}catch(e){o.fail(`Failed to sync connector-building environment`),e instanceof Error&&y.error(e.message)}process.exit(0)}catch(e){e instanceof Error?y.error(e.message):y.error(`Unknown error occurred`),process.exit(1)}}},hr=class{async execute(e){let t=k(),n=e?.mode;if(y.log(T.bold(`
150
+ Verify:`),T.cyan(`claude mcp list`)),y.log(``)}catch(e){a.fail(`Failed to create .mcp.json`),e instanceof Error&&y.error(e.message)}let o=J(`Syncing connector-building skills + guide...`).start();try{let e=rr({cwd:t}),n=e.skills.changed.length+e.skills.unchanged.length,r=e.guide===`missing-source`?`unavailable in this version`:`in CLAUDE.md`;o.succeed(`Connector-building environment ready (${n} skills in .claude/, guide ${r})`),y.log(T.dim(` Refresh anytime with`),T.cyan(`stackone agent sync`))}catch(e){o.fail(`Failed to sync connector-building environment`),e instanceof Error&&y.error(e.message)}process.exit(0)}catch(e){e instanceof Error?y.error(e.message):y.error(`Unknown error occurred`),process.exit(1)}}},gr=class{async execute(e){let t=k(),n=e?.mode;if(y.log(T.bold(`
151
151
  Available skills
152
152
  `)),t.length===0){y.log(T.dim(` No bundled skills found.
153
- `));return}for(let e of t)y.log(` • ${e}`);if(n){let e=j(n);if(e.length>0){y.log(T.bold(`\nRecommended for mode "${n}":\n`));for(let n of e){let e=t.includes(n);y.log(` • ${n}${e?``:T.dim(` (not found)`)}`)}}}y.log(``)}};const gr=(e,t,n)=>{let r=n?`stale`:`synced`;t.changed.length>0&&y.log(T.cyan(` • ${e} ${r}: ${t.changed.join(`, `)}`)),t.missing.length>0&&y.log(T.dim(` • ${e} not in this harness version: ${t.missing.join(`, `)}`))},_r=(e,t)=>{e===`missing-source`?y.log(T.dim(` • connector-guide.md not in this harness version — skipped CLAUDE.md`)):e===`changed`&&y.log(T.cyan(` • CLAUDE.md guide block ${t?`stale`:`updated`}`))};var vr=class{async execute(e){let t=!!e?.check,n=e?.pluginDir;rr(n)||(y.error(n?`--plugin-dir is not a valid @stackone/agent-harness plugin dir: ${n}`:`Could not locate the bundled @stackone/agent-harness plugin. Reinstall the CLI and try again.`),process.exit(1));let r=Kn(n);y.log(T.blue.bold(`🧩 ${t?`Checking`:`Syncing`} connector-building environment`)+T.dim(` (agent-harness@${r}${n?` [--plugin-dir]`:``})\n`));try{let e=nr({cwd:process.cwd(),check:t,pluginDir:n});gr(`skills`,e.skills,t),_r(e.guide,t),t&&(e.hasChanges&&(y.log(``),y.error("Connector-building environment is out of date. Run `stackone agent sync` to update."),process.exit(1)),y.success(`Connector-building environment is up to date.`),process.exit(0)),e.hasChanges?(y.success(`Connector-building environment synced into .claude/ and CLAUDE.md.`),y.log(T.dim(`
154
- 💡 Skills and the connector guide are managed by the CLI — `),T.dim("re-run `stackone agent sync` after a CLI update."))):y.success(`Already up to date — nothing to sync.`),process.exit(0)}catch(e){y.error(e instanceof Error?e.message:`Unknown error during sync`),process.exit(1)}}};const yr={profiles:{}},br=()=>{let t=i.readConfigFile(e);if(!t)return yr;try{return JSON.parse(t)}catch{return yr}},xr=e=>br().profiles[e],Sr=e=>!!br().profiles[e],Cr=(t,n)=>{let r=br();r.profiles[t]=n,i.writeConfigFile(e,JSON.stringify(r,null,2))},wr=()=>{let e=br();return Object.keys(e.profiles)},Tr=`https://api.stackone.com`;var Er=class{async execute({profile:e,connector:r,apiUrl:i,apiKey:a}={}){if(!e&&!a&&(y.error(`Profile or API key is required`),y.log(`Please provide a profile using the ${t(`--profile`)} option or an API key using the ${t(`--api-key`)} option.`),y.log(`To create a profile, run ${t(`stackone init`)}.`),process.exit(1)),e&&a&&(y.error(`Please provide either a profile or an API key, not both`),process.exit(1)),e&&i&&y.warn(`Specifying ${t(`--api-url`)} with a profile won't have any effect. Using API url from profile.`),e&&!Sr(e)){y.error(`Configuration profile ${t(e)} not found`),y.log(`Run ${t(`stackone init`)} to create a new configuration profile.\n`);let n=wr();n.length>0&&(y.info(`Available configuration profiles:`),n.forEach(e=>{y.log(` - ${T.blue(e)}`)})),process.exit(1)}let o=e?xr(e):{apiUrl:i??Tr,apiKey:a};o?.apiKey||(y.error(`API key is missing`),y.log(`Please provide a valid API key in the profile or via the ${t(`--api-key`)} option.`),process.exit(1)),r||(y.error(`Connector identifier is required in the format provider_key@version.`),process.exit(1));let s=r.split(`@`);(s.length!==2||!s[0]||!s[1])&&(y.error(`Invalid connector format ${n(r)}. Expected format: ${t(`provider_key@version`)}`),process.exit(1));let c=o.apiUrl??Tr,l=await this.dropConnector(r,c,o.apiKey);process.exit(l?0:1)}async dropConnector(e,n,i){let a=J(`🗑️ Dropping connector ${t(e)}...`).start();try{let r=Buffer.from(i).toString(`base64`),o=await fetch(`${n}/registry/connectors/${e}`,{method:`DELETE`,headers:{Authorization:`Basic ${r}`}});return a.stop(),o.status===204?(y.success(`Successfully dropped connector ${t(e)} from the registry`),!0):o.status===404?(y.error(`Connector ${t(e)} not found in the registry`),!1):o.status===401||o.status===403?(y.error(`You do not have permission to drop this connector`),!1):o.status===409?(y.error(`Connector ${t(e)} has associated configs and cannot be dropped`),y.log(`Please delete all associated integration configurations before dropping the connector.`),!1):(o.ok||await b(o,`Failed to drop connector ${t(e)} from the registry`),!1)}catch(i){return a.stop(),y.error(`Failed to drop connector ${t(e)} from registry: ${i.message}`),y.log(`Please ensure that the API at ${r(n)} is reachable and the API key is valid`),!1}}};const Dr=`stackone`;async function Or(e,n){n.length===0&&(y.error(`Multiple versions of connector ${t(e)} were found but no owner information was returned`),process.exit(1));let r=n.map(e=>({value:e,label:e===Dr?`StackOne`:`Custom`,hint:e===Dr?`Official StackOne connector`:`Custom connector version created by your organization`}));y.warn(`Multiple versions of connector ${t(e)} were found. Please select which version to use.`);let i=await Ye({message:`Which version would you like to use?`,options:r});return Ke(i)&&(y.error(`Operation cancelled.`),process.exit(1)),i}const kr=`https://api.stackone.com`;var Ar=class{async execute({profile:e,connector:r,accountId:i,format:a,outputFile:s,apiUrl:c,apiKey:l,owner:u}={}){if(!e&&!l&&(y.error(`Profile or API key is required`),y.log(`Please provide a profile using the ${t(`--profile`)} option or an API key using the ${t(`--api-key`)} option.`),y.log(`To create a profile, run ${t(`stackone init`)}.`),process.exit(1)),e&&l&&(y.error(`Please provide either a profile or an API key, not both`),process.exit(1)),e&&c&&y.warn(`Specifying ${t(`--api-url`)} with a profile won't have any effect. Using API url from profile.`),e&&!Sr(e)){y.error(`Configuration profile ${t(e)} not found`),y.log(`Run ${t(`stackone init`)} to create a new configuration profile.\n`);let n=wr();n.length>0&&(y.info(`Available configuration profiles:`),n.forEach(e=>{y.log(` - ${T.blue(e)}`)})),process.exit(1)}let d=e?xr(e):{apiUrl:c??kr,apiKey:l};d?.apiKey||(y.error(`API key is missing`),y.log(`Please provide a valid API key in the profile or via the ${t(`--api-key`)} option.`),process.exit(1)),Y(r)&&Y(i)&&(y.error(`Either ${t(`--connector`)} or ${t(`--account-id`)} must be provided`),process.exit(1)),X(r)&&X(i)&&(y.error(`Please provide either ${t(`--connector`)} or ${t(`--account-id`)}, not both.`),process.exit(1)),X(a)&&a!==`yaml`&&a!==`json`&&(y.error(`Format must be either ${t(`yaml`)} or ${t(`json`)}.`),process.exit(1));let f=d.apiUrl??kr,p;if(X(r)){this.#t(r)||(y.error(`Invalid connector format ${n(r)}. Expected format: ${t(`provider_key@version`)} or ${t(`provider_key`)}`),process.exit(1));let e=this.#n(r);p=await this.#r(e,f,d.apiKey,a,u)}else X(i)?p=await this.#i(i,f,d.apiKey,a):(y.error(`Either ${t(`--connector`)} or ${t(`--account-id`)} must be provided`),process.exit(1));if(X(s))try{K.writeFileSync(s,p,`utf-8`),y.success(`Connector written to file: ${t(s)}`)}catch(e){y.error(`Failed to write connector to file ${t(s)}: ${e.message}`),process.exit(1)}else if(y.log(`\n${T.blue.inverse(` CONNECTOR CONTENT `)}\n`),!a||a===`yaml`)y.log(this.#e(p));else if(a===`json`)try{o(JSON.parse(p))}catch{y.log(p)}else y.log(p);process.exit(0)}#e(e){return e.split(`
153
+ `));return}for(let e of t)y.log(` • ${e}`);if(n){let e=j(n);if(e.length>0){y.log(T.bold(`\nRecommended for mode "${n}":\n`));for(let n of e){let e=t.includes(n);y.log(` • ${n}${e?``:T.dim(` (not found)`)}`)}}}y.log(``)}};const _r=(e,t,n)=>{let r=n?`stale`:`synced`;t.changed.length>0&&y.log(T.cyan(` • ${e} ${r}: ${t.changed.join(`, `)}`)),t.missing.length>0&&y.log(T.dim(` • ${e} not in this harness version: ${t.missing.join(`, `)}`))},vr=(e,t)=>{e===`missing-source`?y.log(T.dim(` • connector-guide.md not in this harness version — skipped CLAUDE.md`)):e===`changed`&&y.log(T.cyan(` • CLAUDE.md guide block ${t?`stale`:`updated`}`))};var yr=class{async execute(e){let t=!!e?.check,n=e?.pluginDir;ir(n)||(y.error(n?`--plugin-dir is not a valid @stackone/agent-harness plugin dir: ${n}`:`Could not locate the bundled @stackone/agent-harness plugin. Reinstall the CLI and try again.`),process.exit(1));let r=qn(n);y.log(T.blue.bold(`🧩 ${t?`Checking`:`Syncing`} connector-building environment`)+T.dim(` (agent-harness@${r}${n?` [--plugin-dir]`:``})\n`));try{let e=rr({cwd:process.cwd(),check:t,pluginDir:n});_r(`skills`,e.skills,t),vr(e.guide,t),t&&(e.hasChanges&&(y.log(``),y.error("Connector-building environment is out of date. Run `stackone agent sync` to update."),process.exit(1)),y.success(`Connector-building environment is up to date.`),process.exit(0)),e.hasChanges?(y.success(`Connector-building environment synced into .claude/ and CLAUDE.md.`),y.log(T.dim(`
154
+ 💡 Skills and the connector guide are managed by the CLI — `),T.dim("re-run `stackone agent sync` after a CLI update."))):y.success(`Already up to date — nothing to sync.`),process.exit(0)}catch(e){y.error(e instanceof Error?e.message:`Unknown error during sync`),process.exit(1)}}};const br={profiles:{}},xr=()=>{let t=i.readConfigFile(e);if(!t)return br;try{return JSON.parse(t)}catch{return br}},Sr=e=>xr().profiles[e],Cr=e=>!!xr().profiles[e],wr=(t,n)=>{let r=xr();r.profiles[t]=n,i.writeConfigFile(e,JSON.stringify(r,null,2))},Tr=()=>{let e=xr();return Object.keys(e.profiles)},Er=`https://api.stackone.com`;var Dr=class{async execute({profile:e,connector:r,apiUrl:i,apiKey:a}={}){if(!e&&!a&&(y.error(`Profile or API key is required`),y.log(`Please provide a profile using the ${t(`--profile`)} option or an API key using the ${t(`--api-key`)} option.`),y.log(`To create a profile, run ${t(`stackone init`)}.`),process.exit(1)),e&&a&&(y.error(`Please provide either a profile or an API key, not both`),process.exit(1)),e&&i&&y.warn(`Specifying ${t(`--api-url`)} with a profile won't have any effect. Using API url from profile.`),e&&!Cr(e)){y.error(`Configuration profile ${t(e)} not found`),y.log(`Run ${t(`stackone init`)} to create a new configuration profile.\n`);let n=Tr();n.length>0&&(y.info(`Available configuration profiles:`),n.forEach(e=>{y.log(` - ${T.blue(e)}`)})),process.exit(1)}let o=e?Sr(e):{apiUrl:i??Er,apiKey:a};o?.apiKey||(y.error(`API key is missing`),y.log(`Please provide a valid API key in the profile or via the ${t(`--api-key`)} option.`),process.exit(1)),r||(y.error(`Connector identifier is required in the format provider_key@version.`),process.exit(1));let s=r.split(`@`);(s.length!==2||!s[0]||!s[1])&&(y.error(`Invalid connector format ${n(r)}. Expected format: ${t(`provider_key@version`)}`),process.exit(1));let c=o.apiUrl??Er,l=await this.dropConnector(r,c,o.apiKey);process.exit(l?0:1)}async dropConnector(e,n,i){let a=J(`🗑️ Dropping connector ${t(e)}...`).start();try{let r=Buffer.from(i).toString(`base64`),o=await fetch(`${n}/registry/connectors/${e}`,{method:`DELETE`,headers:{Authorization:`Basic ${r}`}});return a.stop(),o.status===204?(y.success(`Successfully dropped connector ${t(e)} from the registry`),!0):o.status===404?(y.error(`Connector ${t(e)} not found in the registry`),!1):o.status===401||o.status===403?(y.error(`You do not have permission to drop this connector`),!1):o.status===409?(y.error(`Connector ${t(e)} has associated configs and cannot be dropped`),y.log(`Please delete all associated integration configurations before dropping the connector.`),!1):(o.ok||await b(o,`Failed to drop connector ${t(e)} from the registry`),!1)}catch(i){return a.stop(),y.error(`Failed to drop connector ${t(e)} from registry: ${i.message}`),y.log(`Please ensure that the API at ${r(n)} is reachable and the API key is valid`),!1}}};const Or=`stackone`;async function kr(e,n){n.length===0&&(y.error(`Multiple versions of connector ${t(e)} were found but no owner information was returned`),process.exit(1));let r=n.map(e=>({value:e,label:e===Or?`StackOne`:`Custom`,hint:e===Or?`Official StackOne connector`:`Custom connector version created by your organization`}));y.warn(`Multiple versions of connector ${t(e)} were found. Please select which version to use.`);let i=await Ye({message:`Which version would you like to use?`,options:r});return Ke(i)&&(y.error(`Operation cancelled.`),process.exit(1)),i}const Ar=`https://api.stackone.com`;var jr=class{async execute({profile:e,connector:r,accountId:i,format:a,outputFile:s,apiUrl:c,apiKey:l,owner:u}={}){if(!e&&!l&&(y.error(`Profile or API key is required`),y.log(`Please provide a profile using the ${t(`--profile`)} option or an API key using the ${t(`--api-key`)} option.`),y.log(`To create a profile, run ${t(`stackone init`)}.`),process.exit(1)),e&&l&&(y.error(`Please provide either a profile or an API key, not both`),process.exit(1)),e&&c&&y.warn(`Specifying ${t(`--api-url`)} with a profile won't have any effect. Using API url from profile.`),e&&!Cr(e)){y.error(`Configuration profile ${t(e)} not found`),y.log(`Run ${t(`stackone init`)} to create a new configuration profile.\n`);let n=Tr();n.length>0&&(y.info(`Available configuration profiles:`),n.forEach(e=>{y.log(` - ${T.blue(e)}`)})),process.exit(1)}let d=e?Sr(e):{apiUrl:c??Ar,apiKey:l};d?.apiKey||(y.error(`API key is missing`),y.log(`Please provide a valid API key in the profile or via the ${t(`--api-key`)} option.`),process.exit(1)),Y(r)&&Y(i)&&(y.error(`Either ${t(`--connector`)} or ${t(`--account-id`)} must be provided`),process.exit(1)),X(r)&&X(i)&&(y.error(`Please provide either ${t(`--connector`)} or ${t(`--account-id`)}, not both.`),process.exit(1)),X(a)&&a!==`yaml`&&a!==`json`&&(y.error(`Format must be either ${t(`yaml`)} or ${t(`json`)}.`),process.exit(1));let f=d.apiUrl??Ar,p;if(X(r)){this.#t(r)||(y.error(`Invalid connector format ${n(r)}. Expected format: ${t(`provider_key@version`)} or ${t(`provider_key`)}`),process.exit(1));let e=this.#n(r);p=await this.#r(e,f,d.apiKey,a,u)}else X(i)?p=await this.#i(i,f,d.apiKey,a):(y.error(`Either ${t(`--connector`)} or ${t(`--account-id`)} must be provided`),process.exit(1));if(X(s))try{K.writeFileSync(s,p,`utf-8`),y.success(`Connector written to file: ${t(s)}`)}catch(e){y.error(`Failed to write connector to file ${t(s)}: ${e.message}`),process.exit(1)}else if(y.log(`\n${T.blue.inverse(` CONNECTOR CONTENT `)}\n`),!a||a===`yaml`)y.log(this.#e(p));else if(a===`json`)try{o(JSON.parse(p))}catch{y.log(p)}else y.log(p);process.exit(0)}#e(e){return e.split(`
155
155
  `).map(e=>{if(e.trim().startsWith(`#`))return T.gray(e);if(e.includes(`:`)){let t=e.indexOf(`:`),n=e.substring(0,t+1),r=e.substring(t+1),i=r,a=r.trim();return a===`true`||a===`false`?i=r.replace(a,T.cyan(a)):a===`null`||a===`~`?i=r.replace(a,T.gray(a)):/^-?\d+(\.\d+)?$/.test(a)?i=r.replace(a,T.green(a)):(a.startsWith(`"`)&&a.endsWith(`"`)||a.startsWith(`'`)&&a.endsWith(`'`)||a&&!a.startsWith(`-`))&&(i=r.replace(a,T.yellow(a))),T.red(n)+i}return e.trim().startsWith(`-`)?e.replace(`-`,T.gray(`-`)):e}).join(`
156
- `)}#t=e=>!e.includes(`/`)&&!e.includes(`\\`)&&!e.endsWith(`.yaml`)&&!e.endsWith(`.yml`)?e.includes(`@`)?e.split(`@`).length===2:!0:!1;#n=e=>e.includes(`@`)?e:`${e}@latest`;async#r(e,n,i,a,o){let s=J(`Getting connector ${t(e)} from registry...`).start();try{let r=Buffer.from(i).toString(`base64`),c=a?`?format=${a}`:``,l=o?`${c?`&`:`?`}owner=${encodeURIComponent(o)}`:``,u=await fetch(`${n}/registry/connectors/${e}${c}${l}`,{method:`GET`,headers:{Authorization:`Basic ${r}`}});if(s.stop(),u.status===409){o&&(await b(u,`Failed to get connector ${t(e)} from the registry`),process.exit(1));let i=await Or(e,(await u.json()).availableOwners??[]),a=`${n}/registry/connectors/${e}${c}${c?`&`:`?`}owner=${encodeURIComponent(i)}`;s.text=`Getting connector ${t(e)} from registry...`,s.start();let l=await fetch(a,{method:`GET`,headers:{Authorization:`Basic ${r}`}});return s.stop(),l.ok||(await b(l,`Failed to get connector ${t(e)} from the registry`),process.exit(1)),await l.text()}return u.ok||(await b(u,`Failed to get connector ${t(e)} from the registry`),process.exit(1)),await u.text()}catch(i){s.stop(),y.error(`Failed to get connector ${t(e)} from the registry: ${i.message}`),y.log(`Please ensure that the API at ${r(n)} is reachable and the API key is valid`),process.exit(1)}}async#i(e,n,i,a){let o=J(`Getting connector from account ${t(e)}...`).start();try{let r=Buffer.from(i).toString(`base64`),s=a?`?format=${a}`:``,c=await fetch(`${n}/accounts/${e}/connector${s}`,{method:`GET`,headers:{Authorization:`Basic ${r}`}});return o.stop(),c.ok||(await b(c,`Failed to get connector from account ${t(e)}`),process.exit(1)),await c.text()}catch(i){o.stop(),y.error(`Failed to get connector from account ${t(e)}: ${i.message}`),y.log(`Please ensure that the API at ${r(n)} is reachable and the API key is valid`),process.exit(1)}}};const jr=`http://localhost:4000`;var Mr=class{async execute({environment:e}={}){let n=e?.toLowerCase()??`production`;try{Ge(`${T.inverse(` Initialize profile `)}`);let e=await Xe({message:`Profile label`,validate:e=>{if(!e||e.trim().length===0)return`The profile label is required`;if(e.includes(` `))return`The profile label cannot contain spaces`}});if(Ke(e))return Ue(`Configuration profile initialization cancelled`),process.exit(0);if(Sr(e)){let n=await We({message:`Configuration profile with name ${t(e)} already exists. Do you want to overwrite it?`});if(Ke(n)||!n)return Ue(`Configuration profile initialization cancelled`),process.exit(0)}let r;if(n===`production`)r=`https://api.stackone.com`;else if(n===`staging`)r=`https://api.stackone-dev.com`;else{let e=await Xe({message:`API URL`,placeholder:jr,initialValue:jr,validate:e=>{if(!e||e.trim().length===0)return`API URL is required`;try{new URL(e)}catch{return`Please enter a valid URL`}}});if(Ke(e))return Ue(`Configuration profile initialization cancelled`),process.exit(0);r=e}let i=await Je({message:`API Key`,validate:e=>{if(!e||e.trim().length===0)return`API Key is required`}});if(Ke(i))return Ue(`Configuration profile initialization cancelled`),process.exit(0);Cr(e,{label:e,environment:n,apiUrl:r,apiKey:i}),qe(`${T.green(`✔`)} Configuration profile ${t(e)} initialized successfully!`),process.exit(0)}catch(e){e?.isTtyError?y.error(`Prompt couldn't be rendered in the current environment`):y.error(`Failed to initialize configuration profile: ${e}`),process.exit(1)}}};const $={pending:`○`,acceptRemote:`●`,acceptLocal:`◐`,acceptBoth:`◑`,current:`◉`,arrow:`→`,check:`✓`,cross:`✗`,warning:`⚠`};var Nr=class{constructor(e,t,n,r){this.conflicts=[],this.currentIndex=0,this.totalConflicts=0,this.currentCleanup=null,this.connectorId=t,this.localVersion=n,this.remoteVersion=r,this.conflicts=e.map(e=>({conflict:e,choice:e.type===`unchanged`?`remote`:`pending`})),this.totalConflicts=e.filter(e=>e.type===`conflict`).length}resetForReResolution(){this.currentIndex=0}async resolve(){return this.totalConflicts===0?{cancelled:!1,states:this.conflicts}:(this.moveToNextConflict(),new Promise(e=>{let t=nt({input:process.stdin,output:process.stdout});process.stdin.isTTY&&process.stdin.setRawMode(!0),process.stdin.resume(),this.render();let n=n=>{let r=n.toString();if(r===``){this.cleanup(t),this.renderCancelled(),e({cancelled:!0,states:this.conflicts});return}if(r===`\x1B`&&n.length===1){this.cleanup(t),this.renderCancelled(),e({cancelled:!0,states:this.conflicts});return}if(r.startsWith(`\x1B[`)){switch(r.slice(2)){case`D`:this.moveToPrevConflict(),this.render();break;case`C`:this.moveToNextConflict(),this.render();break}return}switch(r){case`r`:case`R`:this.setCurrentChoice(`remote`),this.advanceAfterChoice(t);break;case`l`:case`L`:this.setCurrentChoice(`local`),this.advanceAfterChoice(t);break;case`b`:case`B`:this.setCurrentChoice(`both`),this.advanceAfterChoice(t);break;case`\r`:case`
156
+ `)}#t=e=>!e.includes(`/`)&&!e.includes(`\\`)&&!e.endsWith(`.yaml`)&&!e.endsWith(`.yml`)?e.includes(`@`)?e.split(`@`).length===2:!0:!1;#n=e=>e.includes(`@`)?e:`${e}@latest`;async#r(e,n,i,a,o){let s=J(`Getting connector ${t(e)} from registry...`).start();try{let r=Buffer.from(i).toString(`base64`),c=a?`?format=${a}`:``,l=o?`${c?`&`:`?`}owner=${encodeURIComponent(o)}`:``,u=await fetch(`${n}/registry/connectors/${e}${c}${l}`,{method:`GET`,headers:{Authorization:`Basic ${r}`}});if(s.stop(),u.status===409){o&&(await b(u,`Failed to get connector ${t(e)} from the registry`),process.exit(1));let i=await kr(e,(await u.json()).availableOwners??[]),a=`${n}/registry/connectors/${e}${c}${c?`&`:`?`}owner=${encodeURIComponent(i)}`;s.text=`Getting connector ${t(e)} from registry...`,s.start();let l=await fetch(a,{method:`GET`,headers:{Authorization:`Basic ${r}`}});return s.stop(),l.ok||(await b(l,`Failed to get connector ${t(e)} from the registry`),process.exit(1)),await l.text()}return u.ok||(await b(u,`Failed to get connector ${t(e)} from the registry`),process.exit(1)),await u.text()}catch(i){s.stop(),y.error(`Failed to get connector ${t(e)} from the registry: ${i.message}`),y.log(`Please ensure that the API at ${r(n)} is reachable and the API key is valid`),process.exit(1)}}async#i(e,n,i,a){let o=J(`Getting connector from account ${t(e)}...`).start();try{let r=Buffer.from(i).toString(`base64`),s=a?`?format=${a}`:``,c=await fetch(`${n}/accounts/${e}/connector${s}`,{method:`GET`,headers:{Authorization:`Basic ${r}`}});return o.stop(),c.ok||(await b(c,`Failed to get connector from account ${t(e)}`),process.exit(1)),await c.text()}catch(i){o.stop(),y.error(`Failed to get connector from account ${t(e)}: ${i.message}`),y.log(`Please ensure that the API at ${r(n)} is reachable and the API key is valid`),process.exit(1)}}};const Mr=`http://localhost:4000`;var Nr=class{async execute({environment:e}={}){let n=e?.toLowerCase()??`production`;try{Ge(`${T.inverse(` Initialize profile `)}`);let e=await Xe({message:`Profile label`,validate:e=>{if(!e||e.trim().length===0)return`The profile label is required`;if(e.includes(` `))return`The profile label cannot contain spaces`}});if(Ke(e))return Ue(`Configuration profile initialization cancelled`),process.exit(0);if(Cr(e)){let n=await We({message:`Configuration profile with name ${t(e)} already exists. Do you want to overwrite it?`});if(Ke(n)||!n)return Ue(`Configuration profile initialization cancelled`),process.exit(0)}let r;if(n===`production`)r=`https://api.stackone.com`;else if(n===`staging`)r=`https://api.stackone-dev.com`;else{let e=await Xe({message:`API URL`,placeholder:Mr,initialValue:Mr,validate:e=>{if(!e||e.trim().length===0)return`API URL is required`;try{new URL(e)}catch{return`Please enter a valid URL`}}});if(Ke(e))return Ue(`Configuration profile initialization cancelled`),process.exit(0);r=e}let i=await Je({message:`API Key`,validate:e=>{if(!e||e.trim().length===0)return`API Key is required`}});if(Ke(i))return Ue(`Configuration profile initialization cancelled`),process.exit(0);wr(e,{label:e,environment:n,apiUrl:r,apiKey:i}),qe(`${T.green(`✔`)} Configuration profile ${t(e)} initialized successfully!`),process.exit(0)}catch(e){e?.isTtyError?y.error(`Prompt couldn't be rendered in the current environment`):y.error(`Failed to initialize configuration profile: ${e}`),process.exit(1)}}};const $={pending:`○`,acceptRemote:`●`,acceptLocal:`◐`,acceptBoth:`◑`,current:`◉`,arrow:`→`,check:`✓`,cross:`✗`,warning:`⚠`};var Pr=class{constructor(e,t,n,r){this.conflicts=[],this.currentIndex=0,this.totalConflicts=0,this.currentCleanup=null,this.connectorId=t,this.localVersion=n,this.remoteVersion=r,this.conflicts=e.map(e=>({conflict:e,choice:e.type===`unchanged`?`remote`:`pending`})),this.totalConflicts=e.filter(e=>e.type===`conflict`).length}resetForReResolution(){this.currentIndex=0}async resolve(){return this.totalConflicts===0?{cancelled:!1,states:this.conflicts}:(this.moveToNextConflict(),new Promise(e=>{let t=nt({input:process.stdin,output:process.stdout});process.stdin.isTTY&&process.stdin.setRawMode(!0),process.stdin.resume(),this.render();let n=n=>{let r=n.toString();if(r===``){this.cleanup(t),this.renderCancelled(),e({cancelled:!0,states:this.conflicts});return}if(r===`\x1B`&&n.length===1){this.cleanup(t),this.renderCancelled(),e({cancelled:!0,states:this.conflicts});return}if(r.startsWith(`\x1B[`)){switch(r.slice(2)){case`D`:this.moveToPrevConflict(),this.render();break;case`C`:this.moveToNextConflict(),this.render();break}return}switch(r){case`r`:case`R`:this.setCurrentChoice(`remote`),this.advanceAfterChoice(t);break;case`l`:case`L`:this.setCurrentChoice(`local`),this.advanceAfterChoice(t);break;case`b`:case`B`:this.setCurrentChoice(`both`),this.advanceAfterChoice(t);break;case`\r`:case`
157
157
  `:this.allResolved()?(this.cleanup(t),e({cancelled:!1,states:this.conflicts})):(this.moveToNextUnresolved(),this.render());break;case`q`:case`Q`:this.cleanup(t),this.renderCancelled(),e({cancelled:!0,states:this.conflicts});break;case`a`:case`A`:this.acceptAllRemaining(`remote`),this.render();break;case`u`:case`U`:this.setCurrentChoice(`pending`),this.render();break}};process.stdin.on(`data`,n),this.currentCleanup=()=>{process.stdin.removeListener(`data`,n),process.stdin.isTTY&&process.stdin.setRawMode(!1),t.close()}}))}cleanup(e){this.currentCleanup?(this.currentCleanup(),this.currentCleanup=null):(process.stdin.isTTY&&process.stdin.setRawMode(!1),e.close())}advanceAfterChoice(e){this.allResolved()||this.moveToNextUnresolved(),this.render()}render(){v();let e=process.stdout.columns||80;this.renderHeader(e),this.renderProgressBar(e),this.renderCurrentConflict(e),this.renderControls(e)}renderHeader(e){let t=this.connectorId,n=`${this.localVersion} ${$.arrow} ${this.remoteVersion}`,r=Math.max(0,e-17),i=Math.floor(r/2),a=r-i,o=` `.repeat(i)+`CONFLICT RESOLVER`+` `.repeat(a);y.log(``),y.log(T.bgBlue.white.bold(o)),y.log(T.gray(this.centerText(t,e))),y.log(T.gray(this.centerText(n,e))),y.log(``)}renderProgressBar(e){let t=this.conflicts.filter(e=>e.conflict.type===`conflict`),n=this.getCurrentConflictIndex(),r=t.map((e,t)=>{let r=t===n,i,a;switch(e.choice){case`remote`:i=r?$.current:$.acceptRemote,a=T.green;break;case`local`:i=r?$.current:$.acceptLocal,a=T.yellow;break;case`both`:i=r?$.current:$.acceptBoth,a=T.cyan;break;default:i=r?$.current:$.pending,a=r?T.white:T.gray}return a(i)}),i=t.filter(e=>e.choice!==`pending`).length,a=` Conflict ${n+1} of ${this.totalConflicts} • ${i}/${this.totalConflicts} resolved `;y.log(T.gray(this.centerText(a,e))),y.log(this.centerText(r.join(` `),e)),y.log(``)}renderCurrentConflict(e){let t=this.conflicts[this.currentIndex];if(!t||t.conflict.type!==`conflict`)return;let n=t.conflict;if(y.log(T.gray(`_`.repeat(e))),y.log(`
158
158
 
159
159
  `),n.local){let e=t.choice===`local`||t.choice===`both`?T.yellow.bold(`${$.check} LOCAL (keeping)`):T.red.bold(`${$.cross} LOCAL (removing)`),r=n.local.split(`
@@ -167,9 +167,9 @@ Available skills
167
167
  `),s=r.length>20?`\n${T.gray(`... and ${r.length-20} more lines`)}`:``;y.log(`${e}\n\n${o}${s}`)}y.log(`
168
168
 
169
169
  `),y.log(T.gray(`_`.repeat(e))),y.log(``)}renderControls(e){let t=[T.green(`[R] Accept Remote`),T.yellow(`[L] Keep Local`),T.cyan(`[B] Keep Both`),T.gray(`[U] Undo`)],n=[T.gray(`[←/→] Navigate`),T.gray(`[A] Accept all remaining`)],r=this.allResolved()?[T.green.bold(`[Enter] Apply Changes`),T.gray(`[Esc] Cancel`)]:[T.gray(`[Enter] Next Unresolved`),T.gray(`[Esc] Cancel`)];y.log(this.centerText(t.join(` `),e)),y.log(``),y.log(this.centerText(n.join(` `),e)),y.log(``),y.log(this.centerText(r.join(` `),e)),this.allResolved()&&(y.log(``),y.log(T.green.bold(this.centerText(`✓ All conflicts resolved!`,e))))}renderFinalSummary(){v();let e=this.conflicts.filter(e=>e.conflict.type===`conflict`),t=0,n=0,r=0;for(let i of e)switch(i.choice){case`remote`:t++;break;case`local`:n++;break;case`both`:r++;break}let i=[T.green.bold(`Conflict resolution complete`),``,`${T.bold(this.totalConflicts)} conflicts resolved:`,``,`${T.green($.acceptRemote)} Accepted remote: ${t}`,`${T.yellow($.acceptLocal)} Kept local: ${n}`,`${T.cyan($.acceptBoth)} Kept both: ${r}`];y.box(i.join(`
170
- `))}renderCancelled(){v(),y.log(T.yellow(`Conflict resolution cancelled`)),y.log(``),y.log(`No changes were made to your local connector file.`)}getCurrentConflictIndex(){let e=-1;for(let t=0;t<=this.currentIndex&&t<this.conflicts.length;t++)this.conflicts[t].conflict.type===`conflict`&&e++;return e}moveToNextConflict(){for(let e=this.currentIndex+1;e<this.conflicts.length;e++)if(this.conflicts[e].conflict.type===`conflict`){this.currentIndex=e;return}for(let e=0;e<this.currentIndex;e++)if(this.conflicts[e].conflict.type===`conflict`){this.currentIndex=e;return}}moveToPrevConflict(){for(let e=this.currentIndex-1;e>=0;e--)if(this.conflicts[e].conflict.type===`conflict`){this.currentIndex=e;return}for(let e=this.conflicts.length-1;e>this.currentIndex;e--)if(this.conflicts[e].conflict.type===`conflict`){this.currentIndex=e;return}}moveToNextUnresolved(){for(let e=this.currentIndex+1;e<this.conflicts.length;e++)if(this.conflicts[e].conflict.type===`conflict`&&this.conflicts[e].choice===`pending`){this.currentIndex=e;return}for(let e=0;e<this.currentIndex;e++)if(this.conflicts[e].conflict.type===`conflict`&&this.conflicts[e].choice===`pending`){this.currentIndex=e;return}}setCurrentChoice(e){this.conflicts[this.currentIndex]?.conflict.type===`conflict`&&(this.conflicts[this.currentIndex].choice=e)}allResolved(){return this.conflicts.filter(e=>e.conflict.type===`conflict`).every(e=>e.choice!==`pending`)}acceptAllRemaining(e){for(let t of this.conflicts)t.conflict.type===`conflict`&&t.choice===`pending`&&(t.choice=e)}centerText(e,t){let n=this.stripAnsi(e),r=Math.max(0,Math.floor((t-n.length)/2));return` `.repeat(r)+e}stripAnsi(e){return e.replace(/\x1b\[[0-9;]*m/g,``)}getResolvedContent(){let e=[];for(let t of this.conflicts)if(t.conflict.type===`unchanged`)e.push(t.conflict.content||``);else if(t.conflict.type===`conflict`)switch(t.choice){case`remote`:t.conflict.remote&&e.push(t.conflict.remote);break;case`local`:t.conflict.local&&e.push(t.conflict.local);break;case`both`:t.conflict.local&&e.push(t.conflict.local),t.conflict.remote&&e.push(t.conflict.remote);break;case`pending`:t.conflict.remote&&e.push(t.conflict.remote);break}return e.join(``)}};const Pr=`https://api.stackone.com`;var Fr=class{async execute({profile:e,connector:n,outputPath:r,apiUrl:i,apiKey:a,owner:o}={}){if(Y(n)&&(y.error(`Connector identifier is required`),y.log(`Please provide a connector identifier using the ${t(`--connector`)} option in the format: ${t(`provider_key@version`)} or ${t(`provider_key`)}`),y.log(`If no version is specified, the latest version will be pulled.`),process.exit(1)),!e&&!a&&(y.error(`Profile or API key is required`),y.log(`Please provide a profile using the ${t(`--profile`)} option or an API key using the ${t(`--api-key`)} option.`),y.log(`To create a profile, run ${t(`stackone init`)}.`),process.exit(1)),e&&a&&(y.error(`Please provide either a profile or an API key, not both`),process.exit(1)),e&&i&&y.warn(`Specifying ${t(`--api-url`)} with a profile won't have any effect. Using API url from profile.`),e&&!Sr(e)){y.error(`Configuration profile ${t(e)} not found`),y.log(`Run ${t(`stackone init`)} to create a new configuration profile.\n`);let n=wr();n.length>0&&(y.info(`Available configuration profiles:`),n.forEach(e=>{y.log(` - ${T.blue(e)}`)})),process.exit(1)}let s=e?xr(e):{apiUrl:i??Pr,apiKey:a};s?.apiKey||(y.error(`API key is missing`),y.log(`Please provide a valid API key in the profile or via the ${t(`--api-key`)} option.`),process.exit(1));let c=s.apiUrl??Pr,[l,u]=n.split(`@`),d=await this.#f(l,c,s.apiKey,u??`latest`,o),f=this.#e(d),p=f.version??`unknown`,m=this.#t(r,f.key,p),h=this.#r(m),g=h===null,_=d;if(!g){let e=this.#i(h,m);e&&(y.warn(e.message),e.errors.length>0&&x(e.errors,!1),y.log(``));let t=e?void 0:this.#e(h);if(this.#o(h,d)){this.#a(h,d,m);let e=t?.version??`unknown`,r=await this.#s(h,d,n,e,p);r.action===`cancel`&&(Ue(`Pull cancelled`),process.exit(0)),r.action===`keep-local`&&(y.log(``),y.info(`Keeping local version. No changes made.`),process.exit(0)),r.action===`interactive-cancel`&&process.exit(0),r.action===`interactive`&&(_=r.resolvedContent)}else y.info(`No changes detected in connector configuration.`),process.exit(0)}let ee=et(_).connector,v=ee?.key??f.key,b=ee?.version??p,S=this.#t(r,v,b),C=S;if(S!==m){let e=await this.#n(S);y.log(``),e!==void 0&&(C=e)}await this.#d(C,_),g?y.success(`Connector ${t(v)}@${t(b)} pulled successfully (new connector)`):y.success(`Connector ${t(v)}@${t(b)} updated successfully`);let te=v===f.key?t(v):`${t(f.key)} ${T.whiteBright(`→`)} ${t(v)}`,w=b===p?t(b):`${t(p)} ${T.whiteBright(`→`)} ${t(b)}`,E=C===m?t(C):`${t(m)}\n ${T.whiteBright(`→`)} ${t(C)}`;y.log(`\n${T.blue.inverse(` CONNECTOR DETAILS `)}\n`),y.log(` Provider: ${te}`),y.log(` Version: ${w}`),y.log(` Output file: ${E}`),process.exit(0)}#e(e){let n=et(e),r=n?.errors??[];if(n.success)return n.connector;y.error(`Connector pulled from the registry is not valid`),y.log(`Please make sure you are using the latest version of the StackOne CLI by running ${t(`stackone update`)}`),r.length>0&&x(r,!0),process.exit(1)}#t(e,n,r){let i=`${n}_v${r.replaceAll(`.`,`-`)}.s1.yaml`;return e?(K.existsSync(e)&&(K.statSync(e).isDirectory()||(y.error(`Output path ${t(e)} is not a directory`),y.log(`Please provide a valid directory path to store connectors or use the default path.`),process.exit(1))),je.resolve(e,n,i)):je.resolve(process.cwd(),`connectors`,n,i)}async#n(e){if(!K.existsSync(e))return;let n=je.basename(e),r=je.dirname(e);y.warn(`File ${t(n)} already exists at ${t(r)}`);let i=await Ye({message:`How would you like to proceed?`,options:[{value:`override`,label:`Override existing file`,hint:`Replace the existing file with the new content`},{value:`rename`,label:`Save with a different name`,hint:`Provide a new filename for the connector`},{value:`cancel`,label:`Cancel`,hint:`Abort the pull operation`}]});if((Ke(i)||i===`cancel`)&&(Ue(`Operation cancelled. No local changes were made.`),process.exit(0)),i===`override`)return;let a=await Xe({message:`Enter the new filename:`,placeholder:n,validate:e=>{if(!e||e.trim()===``)return`Filename cannot be empty`;if(!e.endsWith(`.s1.yaml`))return`Filename must end with .s1.yaml`;let t=je.join(r,e.trim());if(K.existsSync(t))return`File ${e} already exists`}});return Ke(a)&&(Ue(`Operation cancelled. No local changes were made.`),process.exit(0)),je.join(r,a.trim())}#r(e){if(!K.existsSync(e))return null;try{return K.readFileSync(e,`utf-8`)}catch{return null}}#i(e,n){try{let r=et(e);if(!r.success){let e=r.errors??[];return{message:`Local connector ${t(je.basename(n))} has validation errors:`,errors:e}}}catch(e){return{message:`Local connector ${t(je.basename(n))} could not be validated: ${e.message}`,errors:[]}}return null}#a(e,t,n){let r=tt(e,t);if(!r.some(e=>e.added||e.removed)){y.info(`No changes detected in connector configuration.`);return}y.log(`${T.blue.inverse(` CHANGES `)}\n`),y.log(T.gray(`--- local: ${n}`)),y.log(T.gray(`+++ remote: StackOne Registry`)),y.log(``);let i=0,a=0;for(let e of r){let t=e.value.split(`
171
- `).filter(e=>e!==``);if(e.added){i+=t.length;for(let e of t)y.log(T.green(`+ ${e}`))}else if(e.removed){a+=t.length;for(let e of t)y.log(T.red(`- ${e}`))}else if(t.length<=6)for(let e of t)y.log(T.gray(` ${e}`));else{for(let e=0;e<3;e++)y.log(T.gray(` ${t[e]}`));y.log(T.gray(` ... (${t.length-6} unchanged lines)`));for(let e=t.length-3;e<t.length;e++)y.log(T.gray(` ${t[e]}`))}}y.log(``),y.log(T.gray(`Summary: ${T.green(`+${i}`)} additions, ${T.red(`-${a}`)} deletions`))}#o(e,t){return tt(e,t).some(e=>e.added||e.removed)}async#s(e,t,n,r,i){y.log(``);let a=await Ye({message:`How would you like to resolve the differences?`,options:[{value:`override`,label:`Override local with remote`,hint:`Replace your local file with the StackOne version`},{value:`keep-local`,label:`Keep local version`,hint:`Cancel the pull and keep your current file`},{value:`interactive`,label:`Resolve conflicts interactively`,hint:`Choose which changes to accept one by one`},{value:`cancel`,label:`Cancel`,hint:`Abort the pull operation`}]});if(Ke(a))return{action:`cancel`};if(a===`override`)return{action:`override`};if(a===`keep-local`)return{action:`keep-local`};if(a===`interactive`){let a=await this.#c(e,t,n,r,i);return a===null?{action:`interactive-cancel`}:{action:`interactive`,resolvedContent:a}}return{action:`cancel`}}async#c(e,t,n,r,i){let a=tt(e,t),o=this.#u(a);if(o.length===0)return y.info(`No conflicts to resolve.`),t;let s=new Nr(o,n,r,i);for(;;){if((await s.resolve()).cancelled)return null;let e=s.getResolvedContent(),t=et(e);if(t.success)return s.renderFinalSummary(),e;let n=await this.#l(t.errors);if(n===`cancel`)return v(),y.info(`Operation cancelled. No changes were made to the local connector.`),null;if(n===`save`)return v(),y.warn(`The connector was saved but it is invalid`),e;s.resetForReResolution()}}async#l(e){let{createInterface:t}=await import(`readline`);return new Promise(n=>{v();let r=(e||[{message:`Unknown validation error`}]).map(e=>` • ${e.message}`).join(`
172
- `);y.box({title:`⚠️ Validation Failed`,message:`The resolved connector configuration is invalid:\n\n${r}`,style:{borderColor:`yellow`,padding:1}}),y.log(``),y.log(T.bold(` Choose an action:`)),y.log(``),y.log(T.cyan(` [B]`)+` ← Go back to conflict resolution`),y.log(T.dim(` Modify your choices to fix the validation errors`)),y.log(``),y.log(T.yellow(` [S]`)+` 💾 Save anyway`),y.log(T.dim(` Save the invalid configuration (not recommended)`)),y.log(``),y.log(T.red(` [C]`)+` ✖ Cancel`),y.log(T.dim(` Discard all changes`)),y.log(``);let i=t({input:process.stdin,output:process.stdout});process.stdin.isTTY&&process.stdin.setRawMode(!0),process.stdin.resume();let a=e=>{let t=e.toString().toLowerCase(),r=()=>{process.stdin.removeListener(`data`,a),process.stdin.isTTY&&process.stdin.setRawMode(!1),i.close()};if(t===``||t===`\x1B`){r(),n(`cancel`);return}switch(t){case`b`:r(),n(`back`);break;case`s`:r(),n(`save`);break;case`c`:case`q`:r(),n(`cancel`);break}};process.stdin.on(`data`,a)})}#u(e){let t=[],n=0;for(;n<e.length;){let r=e[n];if(!r.added&&!r.removed)t.push({type:`unchanged`,content:r.value}),n++;else if(r.removed){let i=e[n+1];i?.added?(t.push({type:`conflict`,local:r.value,remote:i.value}),n+=2):(t.push({type:`conflict`,local:r.value,remote:void 0}),n++)}else r.added&&t.push({type:`conflict`,local:void 0,remote:r.value}),n++}return t}async#d(e,n){let r=je.dirname(e);K.existsSync(r)||K.mkdirSync(r,{recursive:!0});try{K.writeFileSync(e,n,`utf-8`)}catch(n){y.error(`Failed to write connector to file ${t(e)}: ${n.message}`),process.exit(1)}}async#f(e,n,i,a,o){let s=J(`Pulling connector ${t(e)}@${t(a)} from registry...`).start();try{let r=Buffer.from(i).toString(`base64`),c=`${n}/registry/connectors/${e}@${a}${o?`?owner=${encodeURIComponent(o)}`:``}`,l=await fetch(c,{method:`GET`,headers:{Authorization:`Basic ${r}`}});if(s.stop(),l.status===409){o&&(await this.#p(l,e,a),process.exit(1));let i=(await l.json()).availableOwners??[],c=await Or(`${e}@${a}`,i);s.text=`Pulling connector ${t(e)}@${t(a)} from registry...`,s.start();let u=`${n}/registry/connectors/${e}@${a}`,d=await fetch(`${u}?owner=${encodeURIComponent(c)}`,{method:`GET`,headers:{Authorization:`Basic ${r}`}});return s.stop(),d.ok||(await this.#p(d,e,a),process.exit(1)),await d.text()}return l.ok||(await this.#p(l,e,a),process.exit(1)),await l.text()}catch(i){s.stop(),y.error(`Failed to pull connector ${t(e)}@${t(a)} from the registry: ${i.message}`),y.log(`Please ensure that the API at ${r(n)} is reachable and the API key is valid.`),process.exit(1)}}async#p(e,n,r){switch(e.status){case 401:case 403:y.error(`Access denied`),y.log(`Please ensure that your API key is valid and has the ${t(`connectors:read`)} scope required to pull connectors.`);break;case 404:y.error(`Connector ${t(n)}@${t(r)} was not found in the registry`),await this.#m(n);break;case 429:y.error(`Rate limit exceeded`),y.log(`Too many requests. Please wait a moment before trying again.`);break;default:await b(e,`Failed to pull connector ${t(n)}`)}}async#m(e){y.info(`To see available versions, check the connector documentation or contact support.`)}};const Ir=`https://api.stackone.com`;var Lr=class{async execute({profile:e,fileOrDir:n,apiUrl:r,apiKey:i,force:a}={}){if(!e&&!i&&(y.error(`Profile or API key is required`),y.log(`Please provide a profile using the ${t(`--profile`)} option or an API key using the ${t(`--api-key`)} option.`),y.log(`To create a profile, run ${t(`stackone init`)}.`),process.exit(1)),e&&i&&(y.error(`Please provide either a profile or an API key, not both`),process.exit(1)),e&&r&&y.warn(`Specifying ${t(`--api-url`)} with a profile won't have any effect. Using API url from profile.`),e&&!Sr(e)){y.error(`Configuration profile ${t(e)} not found`),y.log(`Run ${t(`stackone init`)} to create a new configuration profile.\n`);let n=wr();n.length>0&&(y.info(`Available configuration profiles:`),n.forEach(e=>{y.log(` - ${T.blue(e)}`)})),process.exit(1)}let o=e?xr(e):{apiUrl:r??Ir,apiKey:i};o?.apiKey||(y.error(`API key is missing`),y.log(`Please provide a valid API key in the profile or via the ${t(`--api-key`)} option.`),process.exit(1)),n||(y.error(`File or directory is required.`),process.exit(1));try{q(n)}catch{y.error(`File or directory not found: ${T.red(n)}`),process.exit(1)}let s=q(n),c=o.apiUrl??Ir;if(s.isDirectory()){let e=Ur(n),t=0;e.length===0?(y.error(`No .s1.yaml connector files found in the directory: ${n}.`),process.exit(1)):(y.start(`Found ${e.length} connector(s) file(s). Pushing to registry...`),y.log(``));for(let n of e)await this.uploadFile(n,c,o.apiKey,a)&&t++;t===0?y.error(`Error while pushing connectors: no files were uploaded`):(y.log(``),y.info(`Upload completed: ${T.green(t)} of ${T.blue(e.length)} file(s) uploaded successfully.`)),process.exit(t>0?0:1)}else n.endsWith(`.s1.yaml`)||(y.error(`Only ${t(`.s1.yaml`)} files are supported for upload`),process.exit(1));let l=await this.uploadFile(n,c,o.apiKey,a);process.exit(l?0:1)}async uploadFile(e,n,i,a){let o=J(`📤 Pushing connector in ${Me(e)}...`).start();try{let r=Hr(e);if(!r)return!1;let s=Me(e),c=new FormData,l=new Blob([r],{type:`application/x-yaml`});c.append(`file`,l,s),a&&c.append(`force`,`true`);let u=Buffer.from(i).toString(`base64`),d=await fetch(`${n}/registry/connectors`,{method:`POST`,headers:{Authorization:`Basic ${u}`},body:c});if(o.stop(),!d.ok)return d.status===409||d.status===422?await this.handleVersionConflict(d,e,n,i,a):(await b(d,`Failed to push connector in ${t(s)} to the registry`),!1);let f=await d.json();return y.success(`Successfully uploaded ${t(s)} with connector ${t(f.provider)}@${t(f.version)}`),!0}catch(i){return o.stop(),y.error(`Failed to upload file ${t(e)}: ${i}`),y.log(`Please ensure that the API at ${r(n)} is reachable and the API key is valid`),!1}}async handleVersionConflict(e,n,r,i,a){let o=await e.text(),s;try{s=JSON.parse(o)}catch{}let c=it.valid(s?.latestVersion);if(!c)return await b(new Response(o,{status:e.status,statusText:e.statusText}),`Failed to push connector in ${t(Me(n))} to the registry`),!1;let l=Oe(n,`utf-8`),u=Rr(l),d=u?`${t(u)}`:``,f=e.status===409?`Version ${d} already exists in the registry. Latest version: ${t(c)}`:`Version ${d} is lower than the latest version in the registry. Latest version: ${t(c)}`;y.error(f);let p=it.inc(c,`patch`)??c,m=it.inc(c,`minor`)??c,h=it.inc(c,`major`)??c,g=await Ye({message:`How would you like to proceed?`,options:[{value:p,label:`Bump patch version (${p})`},{value:m,label:`Bump minor version (${m})`},{value:h,label:`Bump major version (${h})`},{value:`cancel`,label:`Cancel push`}]});return Ke(g)||g===`cancel`?(Ue(`Push cancelled`),!1):(Ae(n,zr(l,g),`utf-8`),y.info(`Updated version to ${t(g)} in ${Me(n)}`),this.uploadFile(n,r,i,a))}};const Rr=e=>e.match(/^\s*version: (\S+)/m)?.[1],zr=(e,t)=>e.replace(/^(\s*version: )\S+/m,`$1${t}`),Br=e=>{try{let t=Qe(e);return t.changelog?.summary?.trim()?null:`has no changelog entry for version ${t.version}`}catch{return null}},Vr=()=>{y.log(`Every published version must record what changed. Add an ${t(`info.changelog`)} block:`),y.log(``),y.log(T.gray(` info:`)),y.log(T.gray(` changelog:`)),y.log(T.gray(` summary: What changed in this version.`)),y.log(T.gray(` labels: [new-actions] # optional, one of: ${rt.join(`, `)}`)),y.log(``)},Hr=e=>{let t=Ze(e),r=et(t),i=r?.errors??[];if(r.success){let r=Br(t);if(r){y.error(`Connector in ${n(e)} ${r}`),Vr();return}return t}else i.length>0?(y.error(`Connector in ${n(e)} is not valid`),x(i,!0)):y.error(`Connector in ${n(e)} is not valid. Please check the file for errors.`)},Ur=e=>{let t=[],n=ke(e,{withFileTypes:!0});for(let r of n){let n=Pe(e,r.name);r.isDirectory()?t.push(...Ur(n)):r.name.endsWith(`.s1.yaml`)&&t.push(n)}return t},Wr=Z.object({provider_key:Z.string().optional(),provider_version:Z.string().optional(),auth_config_key:Z.string(),environment:Z.string().default(`production`),organization_id:Z.string().default(`cli-organization-id`),account_id:Z.string().default(`cli-account-secure-id`),project_id:Z.string().default(`cli-project-secure-id`),credentials:Z.record(Z.string(),Z.any()).default({})}),Gr=Z.record(Z.string(),Z.any()),Kr=Z.object({path:Z.record(Z.string(),Z.any()).default({}),queryParams:Z.record(Z.string(),Z.any()).default({}),header:Z.record(Z.string(),Z.any()).default({}),body:Z.record(Z.string(),Z.any()).default({})}),qr=`https://api.stackone.com`;var Jr=class{async execute({connector:e,action:n,actionId:r,account:i,accountId:a,params:s,credentials:c,profile:l,outputFile:u,debug:d,apiUrl:f,apiKey:p,owner:m}={}){if(!l&&!p&&a&&(y.error(`Profile or API key is required when providing an account ID`),y.log(`Please provide a profile using the ${t(`--profile`)} option or an API key using the ${t(`--api-key`)} option.`),y.log(`To create a profile, run ${t(`stackone init`)}.`),process.exit(1)),l&&p&&(y.error(`Please provide either a profile or an API key, not both`),process.exit(1)),l&&f&&y.warn(`Specifying --api-url with a profile won't have any effect. Using API url from profile.`),l&&!Sr(l)){y.error(`Configuration profile ${t(l)} not found`),y.log(`Run ${t(`stackone init`)} to create a new configuration profile.\n`);let e=wr();e.length>0&&(y.info(`Available configuration profiles:`),e.forEach(e=>{y.log(` - ${T.blue(e)}`)})),process.exit(1)}let h=l?xr(l):{apiUrl:f??qr,apiKey:p};Y(i)&&Y(a)&&(y.error(`A valid account or account ID is required to run an action`),process.exit(1));let g;if(X(e))if(this.#a(e)){!l&&!p&&(y.error(`Profile or API key is required when using a connector identifier`),y.log(`Please provide a profile using the ${t(`--profile`)} option or an API key using the ${t(`--api-key`)} option.`),y.log(`Run ${t(`stackone init`)} to create a new configuration profile.`),process.exit(1));let n=this.#o(e);g=await this.#s(n,h?.apiUrl??qr,h?.apiKey,m)}else g=this.#e(e);else X(a)&&(g=await this.#c(a,h?.apiUrl??qr,h?.apiKey));let _=X(n)?this.#r(n,e):g;Y(_)&&(y.error(`A valid connector is required to run an action.`),process.exit(1));let ee=X(_?.actions)?Object.keys(_?.actions).length:0,v=X(_?.actions)?Object.keys(_.actions)[ee-1]:void 0,b=X(v)?_?.actions?.[v]?.id:void 0,x=(X(r)&&!r?.startsWith(`${_.key}_`)?`${_.key}_${r}`:r)??b;Y(x)&&(y.error(`A valid action ID is required to run an action`),process.exit(1));let S=X(a)?await this.#l(a,h?.apiUrl??qr,h?.apiKey):{},C=X(i)?this.#i(i,_.key??`unknown`,_.version??`unknown`):void 0,te=X(c)?this.#u(c):{},w={...S,...C,credentials:{...S.credentials??{},...te}};Y(w)&&(y.error(`A valid account data is required to run an action.`),process.exit(1));let E=_.actions?.[x];Y(E)&&(y.error(`Action ID ${t(x)} not found in the connector ${t(_.key)}@${t(_.version)}.`),process.exit(1));let ne=X(s)?this.#d(s,x):{path:{},queryParams:{},header:{},body:{}},D=Date.now(),re=await this.#f({connector:_,actionId:x,account:w,queryParams:{...ne.queryParams,...d?{debug:`true`}:{}},pathParams:ne.path,body:ne.body,headers:ne.header}),ie=Date.now()-D;if(X(u))try{K.writeFileSync(u,JSON.stringify(re.output,null,2),`utf-8`),y.info(`Output written to file: ${u}`)}catch(e){y.error(`Failed to write output to file ${u}: ${e.message}`),process.exit(1)}else y.log(`\n${T.blue.inverse(` ACTION OUTPUT `)}`),o(re.output);y.log(``),y.info(`Action ${t(x)} from connector ${t(_?.key)}@${t(_?.version)} finished in ${T.yellowBright((ie/1e3).toFixed(2))} seconds.`),process.exit(0)}#e=e=>{let t=e;try{t=Ze(e)}catch{}return t?this.#n(t):void 0};#t=e=>{try{return Ze(e)}catch(n){y.error(`Failed to load connector file from ${t(e)}: ${n.message}`),process.exit(1)}};#n=e=>{let t=et(e),n=t?.errors??[];if(t.success)return t.connector||(y.error(`Failed to load connector.`),process.exit(1)),t.connector;n.length>0?(y.error(`Connector is not valid`),x(n,!0),process.exit(1)):(y.error(`Connector is not valid. Please check the file for errors.`),process.exit(1))};#r=(e,t)=>{let n=e;try{n=K.readFileSync(e,`utf-8`)}catch{}Y(t)&&(y.error(`A valid connector is required to load an action.`),process.exit(1));let r=`${this.#t(t)} - ${n.split(`
170
+ `))}renderCancelled(){v(),y.log(T.yellow(`Conflict resolution cancelled`)),y.log(``),y.log(`No changes were made to your local connector file.`)}getCurrentConflictIndex(){let e=-1;for(let t=0;t<=this.currentIndex&&t<this.conflicts.length;t++)this.conflicts[t].conflict.type===`conflict`&&e++;return e}moveToNextConflict(){for(let e=this.currentIndex+1;e<this.conflicts.length;e++)if(this.conflicts[e].conflict.type===`conflict`){this.currentIndex=e;return}for(let e=0;e<this.currentIndex;e++)if(this.conflicts[e].conflict.type===`conflict`){this.currentIndex=e;return}}moveToPrevConflict(){for(let e=this.currentIndex-1;e>=0;e--)if(this.conflicts[e].conflict.type===`conflict`){this.currentIndex=e;return}for(let e=this.conflicts.length-1;e>this.currentIndex;e--)if(this.conflicts[e].conflict.type===`conflict`){this.currentIndex=e;return}}moveToNextUnresolved(){for(let e=this.currentIndex+1;e<this.conflicts.length;e++)if(this.conflicts[e].conflict.type===`conflict`&&this.conflicts[e].choice===`pending`){this.currentIndex=e;return}for(let e=0;e<this.currentIndex;e++)if(this.conflicts[e].conflict.type===`conflict`&&this.conflicts[e].choice===`pending`){this.currentIndex=e;return}}setCurrentChoice(e){this.conflicts[this.currentIndex]?.conflict.type===`conflict`&&(this.conflicts[this.currentIndex].choice=e)}allResolved(){return this.conflicts.filter(e=>e.conflict.type===`conflict`).every(e=>e.choice!==`pending`)}acceptAllRemaining(e){for(let t of this.conflicts)t.conflict.type===`conflict`&&t.choice===`pending`&&(t.choice=e)}centerText(e,t){let n=this.stripAnsi(e),r=Math.max(0,Math.floor((t-n.length)/2));return` `.repeat(r)+e}stripAnsi(e){return e.replace(/\x1b\[[0-9;]*m/g,``)}getResolvedContent(){let e=[];for(let t of this.conflicts)if(t.conflict.type===`unchanged`)e.push(t.conflict.content||``);else if(t.conflict.type===`conflict`)switch(t.choice){case`remote`:t.conflict.remote&&e.push(t.conflict.remote);break;case`local`:t.conflict.local&&e.push(t.conflict.local);break;case`both`:t.conflict.local&&e.push(t.conflict.local),t.conflict.remote&&e.push(t.conflict.remote);break;case`pending`:t.conflict.remote&&e.push(t.conflict.remote);break}return e.join(``)}};const Fr=`https://api.stackone.com`;var Ir=class{async execute({profile:e,connector:n,outputPath:r,apiUrl:i,apiKey:a,owner:o}={}){if(Y(n)&&(y.error(`Connector identifier is required`),y.log(`Please provide a connector identifier using the ${t(`--connector`)} option in the format: ${t(`provider_key@version`)} or ${t(`provider_key`)}`),y.log(`If no version is specified, the latest version will be pulled.`),process.exit(1)),!e&&!a&&(y.error(`Profile or API key is required`),y.log(`Please provide a profile using the ${t(`--profile`)} option or an API key using the ${t(`--api-key`)} option.`),y.log(`To create a profile, run ${t(`stackone init`)}.`),process.exit(1)),e&&a&&(y.error(`Please provide either a profile or an API key, not both`),process.exit(1)),e&&i&&y.warn(`Specifying ${t(`--api-url`)} with a profile won't have any effect. Using API url from profile.`),e&&!Cr(e)){y.error(`Configuration profile ${t(e)} not found`),y.log(`Run ${t(`stackone init`)} to create a new configuration profile.\n`);let n=Tr();n.length>0&&(y.info(`Available configuration profiles:`),n.forEach(e=>{y.log(` - ${T.blue(e)}`)})),process.exit(1)}let s=e?Sr(e):{apiUrl:i??Fr,apiKey:a};s?.apiKey||(y.error(`API key is missing`),y.log(`Please provide a valid API key in the profile or via the ${t(`--api-key`)} option.`),process.exit(1));let c=s.apiUrl??Fr,[l,u]=n.split(`@`),d=await this.#f(l,c,s.apiKey,u??`latest`,o),f=this.#e(d),p=f.version??`unknown`,m=this.#t(r,f.key,p),h=this.#r(m),g=h===null,_=d;if(!g){let e=this.#i(h,m);e&&(y.warn(e.message),e.errors.length>0&&x(e.errors,!1),y.log(``));let t=e?void 0:this.#e(h);if(this.#o(h,d)){this.#a(h,d,m);let e=t?.version??`unknown`,r=await this.#s(h,d,n,e,p);r.action===`cancel`&&(Ue(`Pull cancelled`),process.exit(0)),r.action===`keep-local`&&(y.log(``),y.info(`Keeping local version. No changes made.`),process.exit(0)),r.action===`interactive-cancel`&&process.exit(0),r.action===`interactive`&&(_=r.resolvedContent)}else y.info(`No changes detected in connector configuration.`),process.exit(0)}let ee=et(_).connector,v=ee?.key??f.key,b=ee?.version??p,S=this.#t(r,v,b),C=S;if(S!==m){let e=await this.#n(S);y.log(``),e!==void 0&&(C=e)}await this.#d(C,_),g?y.success(`Connector ${t(v)}@${t(b)} pulled successfully (new connector)`):y.success(`Connector ${t(v)}@${t(b)} updated successfully`);let te=v===f.key?t(v):`${t(f.key)} ${T.whiteBright(`→`)} ${t(v)}`,w=b===p?t(b):`${t(p)} ${T.whiteBright(`→`)} ${t(b)}`,E=C===m?t(C):`${t(m)}\n ${T.whiteBright(`→`)} ${t(C)}`;y.log(`\n${T.blue.inverse(` CONNECTOR DETAILS `)}\n`),y.log(` Provider: ${te}`),y.log(` Version: ${w}`),y.log(` Output file: ${E}`),process.exit(0)}#e(e){let n=et(e),r=n?.errors??[];if(n.success)return n.connector;y.error(`Connector pulled from the registry is not valid`),y.log(`Please make sure you are using the latest version of the StackOne CLI by running ${t(`stackone update`)}`),r.length>0&&x(r,!0),process.exit(1)}#t(e,n,r){let i=`${n}_v${r.replaceAll(`.`,`-`)}.s1.yaml`;return e?(K.existsSync(e)&&(K.statSync(e).isDirectory()||(y.error(`Output path ${t(e)} is not a directory`),y.log(`Please provide a valid directory path to store connectors or use the default path.`),process.exit(1))),je.resolve(e,n,i)):je.resolve(process.cwd(),`connectors`,n,i)}async#n(e){if(!K.existsSync(e))return;let n=je.basename(e),r=je.dirname(e);y.warn(`File ${t(n)} already exists at ${t(r)}`);let i=await Ye({message:`How would you like to proceed?`,options:[{value:`override`,label:`Override existing file`,hint:`Replace the existing file with the new content`},{value:`rename`,label:`Save with a different name`,hint:`Provide a new filename for the connector`},{value:`cancel`,label:`Cancel`,hint:`Abort the pull operation`}]});if((Ke(i)||i===`cancel`)&&(Ue(`Operation cancelled. No local changes were made.`),process.exit(0)),i===`override`)return;let a=await Xe({message:`Enter the new filename:`,placeholder:n,validate:e=>{if(!e||e.trim()===``)return`Filename cannot be empty`;if(!e.endsWith(`.s1.yaml`))return`Filename must end with .s1.yaml`;let t=je.join(r,e.trim());if(K.existsSync(t))return`File ${e} already exists`}});return Ke(a)&&(Ue(`Operation cancelled. No local changes were made.`),process.exit(0)),je.join(r,a.trim())}#r(e){if(!K.existsSync(e))return null;try{return K.readFileSync(e,`utf-8`)}catch{return null}}#i(e,n){try{let r=et(e);if(!r.success){let e=r.errors??[];return{message:`Local connector ${t(je.basename(n))} has validation errors:`,errors:e}}}catch(e){return{message:`Local connector ${t(je.basename(n))} could not be validated: ${e.message}`,errors:[]}}return null}#a(e,t,n){let r=tt(e,t);if(!r.some(e=>e.added||e.removed)){y.info(`No changes detected in connector configuration.`);return}y.log(`${T.blue.inverse(` CHANGES `)}\n`),y.log(T.gray(`--- local: ${n}`)),y.log(T.gray(`+++ remote: StackOne Registry`)),y.log(``);let i=0,a=0;for(let e of r){let t=e.value.split(`
171
+ `).filter(e=>e!==``);if(e.added){i+=t.length;for(let e of t)y.log(T.green(`+ ${e}`))}else if(e.removed){a+=t.length;for(let e of t)y.log(T.red(`- ${e}`))}else if(t.length<=6)for(let e of t)y.log(T.gray(` ${e}`));else{for(let e=0;e<3;e++)y.log(T.gray(` ${t[e]}`));y.log(T.gray(` ... (${t.length-6} unchanged lines)`));for(let e=t.length-3;e<t.length;e++)y.log(T.gray(` ${t[e]}`))}}y.log(``),y.log(T.gray(`Summary: ${T.green(`+${i}`)} additions, ${T.red(`-${a}`)} deletions`))}#o(e,t){return tt(e,t).some(e=>e.added||e.removed)}async#s(e,t,n,r,i){y.log(``);let a=await Ye({message:`How would you like to resolve the differences?`,options:[{value:`override`,label:`Override local with remote`,hint:`Replace your local file with the StackOne version`},{value:`keep-local`,label:`Keep local version`,hint:`Cancel the pull and keep your current file`},{value:`interactive`,label:`Resolve conflicts interactively`,hint:`Choose which changes to accept one by one`},{value:`cancel`,label:`Cancel`,hint:`Abort the pull operation`}]});if(Ke(a))return{action:`cancel`};if(a===`override`)return{action:`override`};if(a===`keep-local`)return{action:`keep-local`};if(a===`interactive`){let a=await this.#c(e,t,n,r,i);return a===null?{action:`interactive-cancel`}:{action:`interactive`,resolvedContent:a}}return{action:`cancel`}}async#c(e,t,n,r,i){let a=tt(e,t),o=this.#u(a);if(o.length===0)return y.info(`No conflicts to resolve.`),t;let s=new Pr(o,n,r,i);for(;;){if((await s.resolve()).cancelled)return null;let e=s.getResolvedContent(),t=et(e);if(t.success)return s.renderFinalSummary(),e;let n=await this.#l(t.errors);if(n===`cancel`)return v(),y.info(`Operation cancelled. No changes were made to the local connector.`),null;if(n===`save`)return v(),y.warn(`The connector was saved but it is invalid`),e;s.resetForReResolution()}}async#l(e){let{createInterface:t}=await import(`readline`);return new Promise(n=>{v();let r=(e||[{message:`Unknown validation error`}]).map(e=>` • ${e.message}`).join(`
172
+ `);y.box({title:`⚠️ Validation Failed`,message:`The resolved connector configuration is invalid:\n\n${r}`,style:{borderColor:`yellow`,padding:1}}),y.log(``),y.log(T.bold(` Choose an action:`)),y.log(``),y.log(T.cyan(` [B]`)+` ← Go back to conflict resolution`),y.log(T.dim(` Modify your choices to fix the validation errors`)),y.log(``),y.log(T.yellow(` [S]`)+` 💾 Save anyway`),y.log(T.dim(` Save the invalid configuration (not recommended)`)),y.log(``),y.log(T.red(` [C]`)+` ✖ Cancel`),y.log(T.dim(` Discard all changes`)),y.log(``);let i=t({input:process.stdin,output:process.stdout});process.stdin.isTTY&&process.stdin.setRawMode(!0),process.stdin.resume();let a=e=>{let t=e.toString().toLowerCase(),r=()=>{process.stdin.removeListener(`data`,a),process.stdin.isTTY&&process.stdin.setRawMode(!1),i.close()};if(t===``||t===`\x1B`){r(),n(`cancel`);return}switch(t){case`b`:r(),n(`back`);break;case`s`:r(),n(`save`);break;case`c`:case`q`:r(),n(`cancel`);break}};process.stdin.on(`data`,a)})}#u(e){let t=[],n=0;for(;n<e.length;){let r=e[n];if(!r.added&&!r.removed)t.push({type:`unchanged`,content:r.value}),n++;else if(r.removed){let i=e[n+1];i?.added?(t.push({type:`conflict`,local:r.value,remote:i.value}),n+=2):(t.push({type:`conflict`,local:r.value,remote:void 0}),n++)}else r.added&&t.push({type:`conflict`,local:void 0,remote:r.value}),n++}return t}async#d(e,n){let r=je.dirname(e);K.existsSync(r)||K.mkdirSync(r,{recursive:!0});try{K.writeFileSync(e,n,`utf-8`)}catch(n){y.error(`Failed to write connector to file ${t(e)}: ${n.message}`),process.exit(1)}}async#f(e,n,i,a,o){let s=J(`Pulling connector ${t(e)}@${t(a)} from registry...`).start();try{let r=Buffer.from(i).toString(`base64`),c=`${n}/registry/connectors/${e}@${a}${o?`?owner=${encodeURIComponent(o)}`:``}`,l=await fetch(c,{method:`GET`,headers:{Authorization:`Basic ${r}`}});if(s.stop(),l.status===409){o&&(await this.#p(l,e,a),process.exit(1));let i=(await l.json()).availableOwners??[],c=await kr(`${e}@${a}`,i);s.text=`Pulling connector ${t(e)}@${t(a)} from registry...`,s.start();let u=`${n}/registry/connectors/${e}@${a}`,d=await fetch(`${u}?owner=${encodeURIComponent(c)}`,{method:`GET`,headers:{Authorization:`Basic ${r}`}});return s.stop(),d.ok||(await this.#p(d,e,a),process.exit(1)),await d.text()}return l.ok||(await this.#p(l,e,a),process.exit(1)),await l.text()}catch(i){s.stop(),y.error(`Failed to pull connector ${t(e)}@${t(a)} from the registry: ${i.message}`),y.log(`Please ensure that the API at ${r(n)} is reachable and the API key is valid.`),process.exit(1)}}async#p(e,n,r){switch(e.status){case 401:case 403:y.error(`Access denied`),y.log(`Please ensure that your API key is valid and has the ${t(`connectors:read`)} scope required to pull connectors.`);break;case 404:y.error(`Connector ${t(n)}@${t(r)} was not found in the registry`),await this.#m(n);break;case 429:y.error(`Rate limit exceeded`),y.log(`Too many requests. Please wait a moment before trying again.`);break;default:await b(e,`Failed to pull connector ${t(n)}`)}}async#m(e){y.info(`To see available versions, check the connector documentation or contact support.`)}};const Lr=`https://api.stackone.com`;var Rr=class{async execute({profile:e,fileOrDir:n,apiUrl:r,apiKey:i,force:a}={}){if(!e&&!i&&(y.error(`Profile or API key is required`),y.log(`Please provide a profile using the ${t(`--profile`)} option or an API key using the ${t(`--api-key`)} option.`),y.log(`To create a profile, run ${t(`stackone init`)}.`),process.exit(1)),e&&i&&(y.error(`Please provide either a profile or an API key, not both`),process.exit(1)),e&&r&&y.warn(`Specifying ${t(`--api-url`)} with a profile won't have any effect. Using API url from profile.`),e&&!Cr(e)){y.error(`Configuration profile ${t(e)} not found`),y.log(`Run ${t(`stackone init`)} to create a new configuration profile.\n`);let n=Tr();n.length>0&&(y.info(`Available configuration profiles:`),n.forEach(e=>{y.log(` - ${T.blue(e)}`)})),process.exit(1)}let o=e?Sr(e):{apiUrl:r??Lr,apiKey:i};o?.apiKey||(y.error(`API key is missing`),y.log(`Please provide a valid API key in the profile or via the ${t(`--api-key`)} option.`),process.exit(1)),n||(y.error(`File or directory is required.`),process.exit(1));try{q(n)}catch{y.error(`File or directory not found: ${T.red(n)}`),process.exit(1)}let s=q(n),c=o.apiUrl??Lr;if(s.isDirectory()){let e=Wr(n),t=0;e.length===0?(y.error(`No .s1.yaml connector files found in the directory: ${n}.`),process.exit(1)):(y.start(`Found ${e.length} connector(s) file(s). Pushing to registry...`),y.log(``));for(let n of e)await this.uploadFile(n,c,o.apiKey,a)&&t++;t===0?y.error(`Error while pushing connectors: no files were uploaded`):(y.log(``),y.info(`Upload completed: ${T.green(t)} of ${T.blue(e.length)} file(s) uploaded successfully.`)),process.exit(t>0?0:1)}else n.endsWith(`.s1.yaml`)||(y.error(`Only ${t(`.s1.yaml`)} files are supported for upload`),process.exit(1));let l=await this.uploadFile(n,c,o.apiKey,a);process.exit(l?0:1)}async uploadFile(e,n,i,a){let o=J(`📤 Pushing connector in ${Me(e)}...`).start();try{let r=Ur(e);if(!r)return!1;let s=Me(e),c=new FormData,l=new Blob([r],{type:`application/x-yaml`});c.append(`file`,l,s),a&&c.append(`force`,`true`);let u=Buffer.from(i).toString(`base64`),d=await fetch(`${n}/registry/connectors`,{method:`POST`,headers:{Authorization:`Basic ${u}`},body:c});if(o.stop(),!d.ok)return d.status===409||d.status===422?await this.handleVersionConflict(d,e,n,i,a):(await b(d,`Failed to push connector in ${t(s)} to the registry`),!1);let f=await d.json();return y.success(`Successfully uploaded ${t(s)} with connector ${t(f.provider)}@${t(f.version)}`),!0}catch(i){return o.stop(),y.error(`Failed to upload file ${t(e)}: ${i}`),y.log(`Please ensure that the API at ${r(n)} is reachable and the API key is valid`),!1}}async handleVersionConflict(e,n,r,i,a){let o=await e.text(),s;try{s=JSON.parse(o)}catch{}let c=it.valid(s?.latestVersion);if(!c)return await b(new Response(o,{status:e.status,statusText:e.statusText}),`Failed to push connector in ${t(Me(n))} to the registry`),!1;let l=Oe(n,`utf-8`),u=zr(l),d=u?`${t(u)}`:``,f=e.status===409?`Version ${d} already exists in the registry. Latest version: ${t(c)}`:`Version ${d} is lower than the latest version in the registry. Latest version: ${t(c)}`;y.error(f);let p=it.inc(c,`patch`)??c,m=it.inc(c,`minor`)??c,h=it.inc(c,`major`)??c,g=await Ye({message:`How would you like to proceed?`,options:[{value:p,label:`Bump patch version (${p})`},{value:m,label:`Bump minor version (${m})`},{value:h,label:`Bump major version (${h})`},{value:`cancel`,label:`Cancel push`}]});return Ke(g)||g===`cancel`?(Ue(`Push cancelled`),!1):(Ae(n,Br(l,g),`utf-8`),y.info(`Updated version to ${t(g)} in ${Me(n)}`),this.uploadFile(n,r,i,a))}};const zr=e=>e.match(/^\s*version: (\S+)/m)?.[1],Br=(e,t)=>e.replace(/^(\s*version: )\S+/m,`$1${t}`),Vr=e=>{try{let t=Qe(e);return t.changelog?.summary?.trim()?null:`has no changelog entry for version ${t.version}`}catch{return null}},Hr=()=>{y.log(`Every published version must record what changed. Add an ${t(`info.changelog`)} block:`),y.log(``),y.log(T.gray(` info:`)),y.log(T.gray(` changelog:`)),y.log(T.gray(` summary: What changed in this version.`)),y.log(T.gray(` labels: [new-actions] # optional, one of: ${rt.join(`, `)}`)),y.log(``)},Ur=e=>{let t=Ze(e),r=et(t),i=r?.errors??[];if(r.success){let r=Vr(t);if(r){y.error(`Connector in ${n(e)} ${r}`),Hr();return}return t}else i.length>0?(y.error(`Connector in ${n(e)} is not valid`),x(i,!0)):y.error(`Connector in ${n(e)} is not valid. Please check the file for errors.`)},Wr=e=>{let t=[],n=ke(e,{withFileTypes:!0});for(let r of n){let n=Pe(e,r.name);r.isDirectory()?t.push(...Wr(n)):r.name.endsWith(`.s1.yaml`)&&t.push(n)}return t},Gr=Z.object({provider_key:Z.string().optional(),provider_version:Z.string().optional(),auth_config_key:Z.string(),environment:Z.string().default(`production`),organization_id:Z.string().default(`cli-organization-id`),account_id:Z.string().default(`cli-account-secure-id`),project_id:Z.string().default(`cli-project-secure-id`),credentials:Z.record(Z.string(),Z.any()).default({})}),Kr=Z.record(Z.string(),Z.any()),qr=Z.object({path:Z.record(Z.string(),Z.any()).default({}),queryParams:Z.record(Z.string(),Z.any()).default({}),header:Z.record(Z.string(),Z.any()).default({}),body:Z.record(Z.string(),Z.any()).default({})}),Jr=`https://api.stackone.com`;var Yr=class{async execute({connector:e,action:n,actionId:r,account:i,accountId:a,params:s,credentials:c,profile:l,outputFile:u,debug:d,apiUrl:f,apiKey:p,owner:m}={}){if(!l&&!p&&a&&(y.error(`Profile or API key is required when providing an account ID`),y.log(`Please provide a profile using the ${t(`--profile`)} option or an API key using the ${t(`--api-key`)} option.`),y.log(`To create a profile, run ${t(`stackone init`)}.`),process.exit(1)),l&&p&&(y.error(`Please provide either a profile or an API key, not both`),process.exit(1)),l&&f&&y.warn(`Specifying --api-url with a profile won't have any effect. Using API url from profile.`),l&&!Cr(l)){y.error(`Configuration profile ${t(l)} not found`),y.log(`Run ${t(`stackone init`)} to create a new configuration profile.\n`);let e=Tr();e.length>0&&(y.info(`Available configuration profiles:`),e.forEach(e=>{y.log(` - ${T.blue(e)}`)})),process.exit(1)}let h=l?Sr(l):{apiUrl:f??Jr,apiKey:p};Y(i)&&Y(a)&&(y.error(`A valid account or account ID is required to run an action`),process.exit(1));let g;if(X(e))if(this.#a(e)){!l&&!p&&(y.error(`Profile or API key is required when using a connector identifier`),y.log(`Please provide a profile using the ${t(`--profile`)} option or an API key using the ${t(`--api-key`)} option.`),y.log(`Run ${t(`stackone init`)} to create a new configuration profile.`),process.exit(1));let n=this.#o(e);g=await this.#s(n,h?.apiUrl??Jr,h?.apiKey,m)}else g=this.#e(e);else X(a)&&(g=await this.#c(a,h?.apiUrl??Jr,h?.apiKey));let _=X(n)?this.#r(n,e):g;Y(_)&&(y.error(`A valid connector is required to run an action.`),process.exit(1));let ee=X(_?.actions)?Object.keys(_?.actions).length:0,v=X(_?.actions)?Object.keys(_.actions)[ee-1]:void 0,b=X(v)?_?.actions?.[v]?.id:void 0,x=(X(r)&&!r?.startsWith(`${_.key}_`)?`${_.key}_${r}`:r)??b;Y(x)&&(y.error(`A valid action ID is required to run an action`),process.exit(1));let S=X(a)?await this.#l(a,h?.apiUrl??Jr,h?.apiKey):{},C=X(i)?this.#i(i,_.key??`unknown`,_.version??`unknown`):void 0,te=X(c)?this.#u(c):{},w={...S,...C,credentials:{...S.credentials??{},...te}};Y(w)&&(y.error(`A valid account data is required to run an action.`),process.exit(1));let E=_.actions?.[x];Y(E)&&(y.error(`Action ID ${t(x)} not found in the connector ${t(_.key)}@${t(_.version)}.`),process.exit(1));let ne=X(s)?this.#d(s,x):{path:{},queryParams:{},header:{},body:{}},D=Date.now(),re=await this.#f({connector:_,actionId:x,account:w,queryParams:{...ne.queryParams,...d?{debug:`true`}:{}},pathParams:ne.path,body:ne.body,headers:ne.header}),ie=Date.now()-D;if(X(u))try{K.writeFileSync(u,JSON.stringify(re.output,null,2),`utf-8`),y.info(`Output written to file: ${u}`)}catch(e){y.error(`Failed to write output to file ${u}: ${e.message}`),process.exit(1)}else y.log(`\n${T.blue.inverse(` ACTION OUTPUT `)}`),o(re.output);y.log(``),y.info(`Action ${t(x)} from connector ${t(_?.key)}@${t(_?.version)} finished in ${T.yellowBright((ie/1e3).toFixed(2))} seconds.`),process.exit(0)}#e=e=>{let t=e;try{t=Ze(e)}catch{}return t?this.#n(t):void 0};#t=e=>{try{return Ze(e)}catch(n){y.error(`Failed to load connector file from ${t(e)}: ${n.message}`),process.exit(1)}};#n=e=>{let t=et(e),n=t?.errors??[];if(t.success)return t.connector||(y.error(`Failed to load connector.`),process.exit(1)),t.connector;n.length>0?(y.error(`Connector is not valid`),x(n,!0),process.exit(1)):(y.error(`Connector is not valid. Please check the file for errors.`),process.exit(1))};#r=(e,t)=>{let n=e;try{n=K.readFileSync(e,`utf-8`)}catch{}Y(t)&&(y.error(`A valid connector is required to load an action.`),process.exit(1));let r=`${this.#t(t)} - ${n.split(`
173
173
  `).map((e,t)=>t===0?e:` ${e}`).join(`
174
- `)}`;return this.#n(r)};#i=(e,t,n)=>{let r=e;try{r=K.readFileSync(e,`utf-8`)}catch{}try{let e=Wr.parse(JSON.parse(r));return{providerKey:t,providerVersion:n,authConfigKey:e.auth_config_key,environment:e.environment,organizationId:e.organization_id,secureId:e.account_id,projectSecureId:e.project_id}}catch(e){let t=[];try{t=JSON.parse(e.message)}catch{}y.error(`Failed to parse account information`),x(t,!1),t.length===0&&y.log(e.message),process.exit(1)}};#a=e=>!e.includes(`/`)&&!e.includes(`\\`)&&!e.endsWith(`.yaml`)&&!e.endsWith(`.yml`)?e.includes(`@`)?e.split(`@`).length===2:!0:!1;#o=e=>e.includes(`@`)?e:`${e}@latest`;#s=async(e,n,i,a)=>{(Y(e)||Y(n)||Y(i))&&(y.error(`Connector identifier, API URL, and API key are required to fetch connector from registry.`),process.exit(1));let o=J();try{o.text=`Fetching connector ${t(e)} from registry...`,o.start();let r=Buffer.from(i).toString(`base64`),s=a?`?owner=${encodeURIComponent(a)}`:``,c=await fetch(`${n}/registry/connectors/${e}${s}`,{method:`GET`,headers:{Authorization:`Basic ${r}`}});if(o.stop(),c.status===409){a&&(await b(c,`Failed to fetch connector ${t(e)} from registry`),process.exit(1));let i=await Or(e,(await c.json()).availableOwners??[]);o.text=`Fetching connector ${t(e)} from registry...`,o.start();let s=await fetch(`${n}/registry/connectors/${e}?owner=${encodeURIComponent(i)}`,{method:`GET`,headers:{Authorization:`Basic ${r}`}});o.stop(),s.ok||(await b(s,`Failed to fetch connector ${t(e)} from registry`),process.exit(1));let l=await s.text(),u=this.#n(l);return y.success(`Fetched connector ${t(u.key)}@${t(u.version)} from registry`),u}c.ok||(await b(c,`Failed to fetch connector ${t(e)} from registry`),process.exit(1));let l=await c.text(),u=this.#n(l);return y.success(`Fetched connector ${t(u.key)}@${t(u.version)} from registry`),u}catch(i){o.stop(),y.error(`Failed to fetch connector ${t(e)} from registry: ${i.message}`),y.log(`Please ensure that the API at ${r(n)} is reachable and the API key is valid`),process.exit(1)}};#c=async(e,n,i)=>{(Y(e)||Y(n)||Y(i))&&(y.error(`Account ID, API URL, and API key are required to fetch connector`),process.exit(1));let a=J();try{a.text=`Fetching connector for account ${t(e)} from API...`,a.start();let r=Buffer.from(i).toString(`base64`),o=await fetch(`${n}/accounts/${e}/connector`,{method:`GET`,headers:{Authorization:`Basic ${r}`}});a.stop(),o.ok||(await b(o,`Failed to fetch connector`),process.exit(1));let s=await o.text(),c=this.#n(s);return y.success(`Fetched connector ${t(c.key)}@${t(c.version)} for account ${t(e)}`),c}catch(e){a.stop(),y.error(`Failed to fetch connector: ${e.message}`),y.log(`Please ensure that the API at ${r(n)} is reachable and the API key is valid`),process.exit(1)}};#l=async(e,n,i)=>{(Y(e)||Y(n)||Y(i))&&(y.error(`Account ID, API URL, and API key are required to fetch account information.`),process.exit(1));let a=J();try{a.text=`Fetching account ${t(e)} information from API...`,a.start();let r=Buffer.from(i).toString(`base64`),o=await fetch(`${n}/accounts/${e}/credentials`,{method:`GET`,headers:{Authorization:`Basic ${r}`}});a.stop(),o.ok||(await b(o,`Failed to fetch account ${t(e)} information`),process.exit(1));let s=await o.json();return y.success(`Fetched account ${t(e)} information from project ${t(s.project_id)}`),{providerKey:s.provider_key,providerVersion:s.provider_version,authConfigKey:s.auth_config_key,environment:s.environment,organizationId:s.organization_id,secureId:s.account_id,projectSecureId:s.project_id,credentials:s.credentials}}catch(i){a.stop(),y.error(`Failed to fetch account ${t(e)} information: ${i.message}`),y.log(`Please ensure that the API at ${r(n)} is reachable and the API key is valid`),process.exit(1)}};#u=e=>{let t=e;try{t=K.readFileSync(e,`utf-8`)}catch{}try{return Gr.parse(JSON.parse(t))}catch(e){let t=[];try{t=JSON.parse(e.message)}catch{}y.error(`Failed to parse credentials`),x(t,!1),t.length===0&&y.log(e.message),process.exit(1)}};#d=(e,n)=>{let r=e;try{r=K.readFileSync(e,`utf-8`)}catch{}try{return Kr.parse(JSON.parse(r))}catch(e){let r=[];try{r=JSON.parse(e.message)}catch{}y.error(`Invalid parameters for action ${t(n)}.`),x(r,!1),r.length===0&&y.log(e.message),process.exit(1)}};async#f({connector:e,actionId:n,account:r,pathParams:i={},queryParams:a={},body:s={},headers:c={}}){try{let l=await $e({mode:`action_id`,actionId:n,account:r,connector:e,pathParams:i,queryParams:a,body:s,headers:c,getHttpClient:async()=>new at});if(l.response?.successful){let e={...this.#p(a,l.steps),...He(l.outputs)?l.outputs:{data:l.outputs}};return{statusCode:l.response?.statusCode,output:e}}else{let r=l.response?.message??`An error occurred while processing the request`;y.error(`Action ID ${t(n)} from connector ${t(e.key)}@${t(e.version)} failed with status ${l.response?.statusCode}: ${r}`);let i={...this.#p(a,l.steps)};Object.keys(i).length>0&&(y.log(`${T.yellow.inverse(` EXECUTION DETAILS `)}`),o(i)),process.exit(1)}}catch(e){this.#m(e)}}#p(e,t){return e?.debug===`true`?{debug:{steps:t}}:{}}#m(e){let t=e;switch(Y(t.errorType)&&(y.error(`An unknown error occurred`),y.log(`${e instanceof Error?e.message:String(e)}`),process.exit(1)),t.errorType){case`MISSING_ACTION_ERROR`:y.error(`The specified action was not found: ${t.message}`);break;case`INVALID_ACTION_INPUTS_ERROR`:let e=t;y.error(`Invalid action inputs`),x(e.validationErrors,!1);break;case`INVALID_CURSOR_ERROR`:y.error(`Invalid cursor: ${t.message}`);break;default:y.error(`An error occurred: ${t.message}`)}process.exit(1)}};const Yr=ot(Ce);var Xr=class{constructor(){this.packageName=`@stackone/cli`,this.spinner=J(),this.currentVersion=Kt()}async execute(e={}){this.spinner.text=`Checking for updates...`,this.spinner.start();try{let t=await this.getLatestVersion();this.spinner.stop(),t||(y.error(`Failed to check for updates`),process.exit(1)),this.isNewerVersion(t,this.currentVersion)?(y.box(`New version available: ${T.yellow(this.currentVersion)} → ${T.green(t)}`),await this.performUpdate(t)):e.force?(y.warn(`No updates available, but forcing reinstall...`),await this.performUpdate(t)):y.success(`You are already on the latest version (${this.currentVersion})`),process.exit(0)}catch(e){this.spinner.stop(),y.error(`Error while trying to update StackOne CLI: ${e?.message??`Unknown error`}`),process.exit(1)}}async getLatestVersion(){try{let{stdout:e}=await Yr(`npm view ${this.packageName} version`,{encoding:`utf-8`});return e.trim()}catch{return null}}isNewerVersion(e,t){return it.gt(e,t)}async performUpdate(e){this.spinner.text=`Updating to latest version (${t(e)})...`,this.spinner.start();let n=`npm install -g ${this.packageName}@latest`;try{await Yr(n,{encoding:`utf-8`}),this.spinner.stop(),y.success(`StackOne CLI updated successfully to latest version (${t(e)})`)}catch{throw this.spinner.stop(),Error(`Failed to install update. Please try manually: ${n}`)}}};const Zr=e=>e===null?!0:Object.values(e).some(e=>e!==null),Qr=()=>{y.log(`${T.gray.inverse(` CONNECTORS VALIDATION `)} ${T.yellow.inverse(` WATCH MODE `)}\n`)};var $r=class{async execute(e){let{watchMode:t,fileOrDir:n}=e,r=J(`Watching for file changes... ${T.gray(`(press "q" to quit)`)}`);if(!n)return;let i=Fe(n);try{await ct(i)}catch{y.error(`The specified path does not exist: ${i}\n`),process.exit(1)}if(t){v();let e={},{watch:t}=await import(`chokidar`),n=(await import(`readline`)).createInterface({input:process.stdin,output:process.stdout});process.stdin.setRawMode(!0),process.stdin.resume(),process.stdin.setEncoding(`utf8`);let a=()=>{s.close(),r.stop(),n.close(),y.log(T.grey(`
175
- Exiting watch mode...`)),process.exit(0)};Qr(),y.start(`Validating connectors...`);let o=await ri(i);e=ei(e,o||{}),ti(e,i),r.start();let s=t(i,{persistent:!0,ignoreInitial:!0}),c=async t=>{if(!t.endsWith(`.s1.yaml`)&&!t.endsWith(`s1.partial.yaml`))return;let n=t.endsWith(`s1.partial.yaml`)?await ai(t):[t];if(!(!n||n.length===0)){v(),r.stop(),Qr(),y.log(T.gray(`File change detected: ${t}`)),y.start(`Validating connectors...`);for(let t of n){let n=await ri(t);e=ei(e,n||{})}ti(e,i),r.start()}};s.on(`change`,async e=>await c(e)),process.stdin.on(`data`,e=>{e.toString()===`q`&&a()}),process.on(`SIGINT`,()=>{a()})}else{let e=await ri(i,y);process.exit(Zr(e)?1:0)}}};const ei=(e,t)=>{for(let[n,r]of Object.entries(t))e[n]=r;return e},ti=(e,n)=>{v(),Qr();let r=0,i=0;for(let[n,a]of Object.entries(e))a===null?r++:(y?.error(`Connector ${t(n)} is not valid`),x(a,!0),i++);y.log(``),y.log(T.blue.inverse(` Validation Summary `)),y.log(`Connectors path: ${t(n)}`),y.log(`${r===0?T.red(`0`):T.green(r)} valid, ${i===0?T.green(`0`):T.red(i)} invalid connectors\n`)},ni=async e=>{let t=[],n=await st(e);for(let r of n){let n=Pe(e,r),i=await ct(n);i.isDirectory()?t.push(...await ni(n)):i.isFile()&&r.endsWith(`.s1.yaml`)&&t.push(n)}return t},ri=async(e,r)=>{let i=await ct(e),a={};if(i.isDirectory()){let i=await ni(e);if(i.length===0)return r?.error(`No StackOne connector found in ${n(e)}`),r?.log(`Connector files need to have the extension ${t(`*.s1.yaml`)}`),null;let o=0,s=0;for(let e of i){let t=await ii(e,r);t===null?o++:(r?.log(``),s++),a[e]=t}return r?.log(``),r?.log(T.blue.inverse(` Validation Summary `)),r?.log(`${o===0?T.red(`0`):T.green(o)} valid, ${s===0?T.green(`0`):T.red(s)} invalid connectors`),a}else if(i.isFile()&&e.endsWith(`s1.yaml`))return a[e]=await ii(e,r),a;else if(i.isFile()&&e.endsWith(`partial.yaml`)){r?.error(`Partial connector files cannot be validated directly`),r?.log(`The file ${n(e)} is a partial connector file.`);let i=await ai(e);return i&&i?.length>0&&r?.log(`Did you mean ${t(i[0])}?`),null}else return r?.error(`No StackOne connector found in ${n(e)}`),r?.log(`Connector files need to have the extension ${t(`*.s1.yaml`)}`),null},ii=async(e,n)=>{let r=et(Ze(e)),i=r?.errors??[];if(r.success){let r=e.split(`/`).pop()||e;return n?.success(`Connector ${t(r)} is valid!`),null}else if(i.length>0)return n?.error(`Connector ${t(e)} is not valid`),n&&x(i,!0),i;else return n?.error(`Connector ${t(e)} is not valid. Please check the file for errors`),[]},ai=async e=>{let t=Ne(e);try{return(await st(t)).filter(e=>e.endsWith(`.s1.yaml`))?.map(e=>Pe(t,e))}catch{}};function oi(e){if(!e)return!1;try{let{hostname:t}=new URL(e);return t===`stackone-dev.com`||t.endsWith(`.stackone-dev.com`)}catch{return!1}}function si(){return process.env.AI_TELEMETRY_URL?process.env.AI_TELEMETRY_URL:[process.env.AUTH_SERVER_URL,process.env.STACKONE_API_URL].some(oi)?`https://ai-telemetry.stackone-dev.com`:`https://ai-telemetry.stackone.com`}function ci(){let e=process.env.STACKONE_AGENT_TOKEN,t=process.env.LANGSMITH_PROJECT||`stackone-agent-cli`;if(process.env.AI_TELEMETRY_URL=si(),e)try{ce({apiKey:e,projectName:t}),process.env.VERBOSE&&console.log(`[Telemetry] Initialized for project:`,t)}catch(e){process.env.VERBOSE&&console.error(`[Telemetry] Failed to initialize:`,e)}}const li=R(I(),`.stackone`),ui=R(li,`version-check.json`),di=(e=!1)=>{let t=hi(),n=Date.now();if(e||!t||n-t.lastCheckTime>1728e5){let e=fi();e&&pi(e)&&mi(e),gi({lastCheckTime:n})}},fi=()=>{try{return Ee(`npm view @stackone/cli version`,{encoding:`utf-8`,stdio:[`pipe`,`pipe`,`pipe`],timeout:15e3}).trim()}catch{return null}},pi=e=>{try{let t=Kt();return it.gt(e,t)}catch{return!1}},mi=e=>{let t=Kt(),n=`Update available: ${T.dim(t)} → ${T.green(e)}`,r=`\n\nRun ${T.cyan(`stackone update`)} to update`;y.box(n,r)},hi=()=>{try{if(!N(ui))return null;let e=de(ui,`utf-8`);return JSON.parse(e)}catch{return null}},gi=e=>{try{N(li)||ue(li,{recursive:!0}),me(ui,JSON.stringify(e,null,2),`utf-8`)}catch{}};var _i=class{constructor(e=new ne,t=Kt()){this.program=e,this.version=t,ci(),this.setupProgram(),this.registerCommands()}setupProgram(){this.program.name(`stackone`).description(`StackOne CLI`).version(this.version,`-v, --version`)}registerCommands(){let e=new Mr,t=new Lr,n=new Fr,r=new Er,i=new Ar,a=new $r,o=new xn,s=new mr,c=new an,l=new rn,u=new Cn,d=new hr,f=new vr,p=new Jr,m=new Xr;this.program.configureOutput({writeOut:e=>process.stdout.write(e),writeErr:e=>process.stderr.write(e),outputError:(e,t)=>{t(T.red(e))}}),this.program.command(`init`).option(`-e, --env <environment>`,`Specify the environment for the configuration profile`).description(`Initialize & create a StackOne CLI configuration profile`).action(t=>{e.execute({environment:t.env})}),this.program.command(`push`).option(`-p, --profile <label>`,`Configuration profile to use`).option(`--api-url <api url>`,`API URL`).option(`--api-key <api key>`,`API Key`).option(`--force`,`Force push the connector, bypassing version conflict checks`).addArgument(new E(`<path>`,`Connector file or directory to push`)).description(`Push a connector to the StackOne registry`).action((e,n)=>{t.execute({profile:n.profile,fileOrDir:e,apiUrl:n.apiUrl,apiKey:n.apiKey,force:n.force})}),this.program.command(`drop`).option(`-p, --profile <label>`,`Configuration profile to use`).option(`--api-url <api url>`,`API URL`).option(`--api-key <api key>`,`API Key`).addArgument(new E(`<connector>`,`Connector identifier in format provider_key@version`)).description(`Drop a connector from the StackOne registry`).action((e,t)=>{r.execute({profile:t.profile,connector:e,apiUrl:t.apiUrl,apiKey:t.apiKey})}),this.program.command(`get`).option(`-p, --profile <label>`,`Configuration profile to use`).option(`--api-url <api url>`,`API URL`).option(`--api-key <api key>`,`API Key`).option(`-c, --connector <connector>`,`Connector identifier in format provider_key@version or provider_key (defaults to latest)`).option(`--account-id <account-id>`,`Account ID to fetch connector from`).option(`-f, --format <format>`,`Output format: yaml or json (default: yaml)`,`yaml`).option(`-o, --output-file <output-file>`,`File to write the output to`).option(`--builtin`,`Use the builtin (StackOne) version of the connector`).option(`--custom`,`Use the custom (organization) version of the connector`).option(`--owner <owner>`,`Owner to use for disambiguating connector versions`).description(`Get a connector from the StackOne registry`).action(e=>{[e.builtin,e.custom,e.owner].filter(Boolean).length>1&&(y.error(`--builtin, --custom, and --owner are mutually exclusive. Please provide only one.`),process.exit(1)),i.execute({profile:e.profile,connector:e.connector,accountId:e.accountId,format:e.format,outputFile:e.outputFile,apiUrl:e.apiUrl,apiKey:e.apiKey,owner:e.builtin?`builtin`:e.custom?`custom`:e.owner})}),this.program.command(`pull`).option(`-c, --connector <connector>`,`Connector identifier in format provider_key@version or provider_key`).option(`-p, --profile <label>`,`Configuration profile to use`).option(`--api-url <api url>`,`API URL`).option(`--api-key <api key>`,`API Key`).option(`-o, --output <path>`,`Output directory for the connectors files (default: ./connectors)`).option(`--builtin`,`Use the builtin (StackOne) version of the connector`).option(`--custom`,`Use the custom (organization) version of the connector`).option(`--owner <owner>`,`Owner to use for disambiguating connector versions`).description(`Pull a connector configuration from StackOne registry to local filesystem`).action(e=>{[e.builtin,e.custom,e.owner].filter(Boolean).length>1&&(y.error(`--builtin, --custom, and --owner are mutually exclusive. Please provide only one.`),process.exit(1)),n.execute({profile:e.profile,connector:e.connector,outputPath:e.output,apiUrl:e.apiUrl,apiKey:e.apiKey,owner:e.builtin?`builtin`:e.custom?`custom`:e.owner})}),this.program.command(`validate`).option(`-w, --watch`,`Run in watch mode`).addArgument(new E(`<path>`,`Connector file or directory with connectors to validate`)).description(`Validate a StackOne connector`).action((e,t)=>{a.execute({watchMode:t.watch,fileOrDir:e})}),this.program.command(`run`).option(`--connector <connector>`,`Connector file, inline YAML, or identifier (provider_key@version or provider_key for latest)`).option(`--action <action>`,`Action to execute on the connector (path to file or inline string action code)`).option(`--action-id <action-id>`,`Action ID to execute on the connector`).option(`--account <account>`,`Account details to use for running the connector (path to file or inline string account data)`).option(`--account-id <account-id>`,`Account ID to use for running the connector against (fetches connector from API if --connector not provided)`).option(`--params <params>`,`Action parameters (path to file or inline string with JSON parameters)`).option(`--credentials <credentials>`,`Credentials to use (path to file or inline string with JSON credentials)`).option(`-p, --profile <label>`,`Configuration profile to use`).option(`--api-url <api url>`,`API URL`).option(`--api-key <api key>`,`API Key`).option(`-o, --output-file <output-file>`,`File to write the output to`).option(`-d, --debug`,`Enables debug mode to include more details in the action execution output`).option(`--builtin`,`Use the builtin (StackOne) version of the connector`).option(`--custom`,`Use the custom (organization) version of the connector`).option(`--owner <owner>`,`Owner to use for disambiguating connector versions`).description(`Run a connector action`).action(e=>{[e.builtin,e.custom,e.owner].filter(Boolean).length>1&&(y.error(`--builtin, --custom, and --owner are mutually exclusive. Please provide only one.`),process.exit(1)),p.execute({connector:e.connector,action:e.action,actionId:e.actionId,account:e.account,accountId:e.accountId,params:e.params,credentials:e.credentials,profile:e.profile,outputFile:e.outputFile,debug:e.debug,apiUrl:e.apiUrl,apiKey:e.apiKey,owner:e.builtin?`builtin`:e.custom?`custom`:e.owner})});let h=this.program.command(`agent`).description(`StackOne agent commands`);h.command(`setup`).option(`-g, --global`,`Global only: auth + MCP server (no connector skills/guide)`).option(`-l, --local`,`Local: auth + .mcp.json + connector skills (.claude/) and guide (CLAUDE.md)`).option(`--path <dir>`,`Target project path for local setup (defaults to the current directory)`).option(`--legacy`,`Use email/password login instead of browser-based auth`).option(`--email <email>`,`Email for legacy login (or set STACKONE_EMAIL); requires --legacy`).option(`--password <password>`,`Password for legacy login (or set STACKONE_PASSWORD); requires --legacy. Prefer --password-stdin`).option(`--password-stdin`,`Read password for legacy login from stdin; requires --legacy`).description(`Set up the StackOne agent — prompts for global vs local when neither flag is given`).action(async e=>{e.global&&e.local&&(y.error(`--global and --local are mutually exclusive. Please provide only one.`),process.exit(1));let t=e.email!==void 0,n=e.password!==void 0,r=e.passwordStdin===!0;n&&r&&(y.error(`--password and --password-stdin are mutually exclusive. Please provide only one.`),process.exit(1));let i=t||n||r;i&&!e.legacy&&(y.error(`--email, --password, and --password-stdin require --legacy.`),process.exit(1)),t&&e.email.trim()===``&&(y.error(`--email cannot be empty.`),process.exit(1)),n&&e.password===``&&(y.error(`--password cannot be empty.`),process.exit(1)),r&&(t||process.env.STACKONE_EMAIL?.trim()||(y.error(`--password-stdin requires --email or STACKONE_EMAIL (stdin is consumed for the password, so email cannot be prompted).`),process.exit(1)));let a={email:e.email,password:e.password,passwordFromStdin:r},c=!!process.stdin.isTTY;if(c&&!e.legacy&&!i){let t=await pr({initialMode:e.global?`global`:e.local?`local`:null,pathFlag:e.path});process.exit(t.status===`error`?1:0)}let l=c&&!i;!e.global&&!e.local&&!l&&y.log(T.dim(`No interactive terminal detected — defaulting to global setup. Run in a terminal for the prompt, or pass --local (with --path) / --global.`));let u=Dn(e.global,e.local,l);if(u===null&&(u=await ur()),u===`local`){let t=On(e.path,l);t===null&&(t=await fr(process.cwd())),await s.execute({legacy:!!e.legacy,credentials:a,targetPath:t})}else await o.execute({legacy:!!e.legacy,credentials:a})}),h.command(`cleanup`).description(`Remove all API keys and credentials from configurations`).action(()=>{c.execute()}),h.command(`run`).description(`Run the agent once with a prompt (non-interactive)`).argument(`<prompt>`,`What to do`).option(`-m, --mode <mode>`,`Mode: build, test, or research`,`build`).option(`--max-turns <n>`,`Max agent turns`,`25`).option(`-v, --verbose`,`Verbose output`).action(async(e,t)=>{let n=[`build`,`test`,`research`],r=t.mode??`build`;n.includes(r)||(y.error(`${T.red(`Invalid mode:`)} ${T.white(r)}. Valid modes are: ${n.join(`, `)}.`),process.exit(1));let i=t.maxTurns?parseInt(String(t.maxTurns),10):void 0;await u.execute({prompt:String(e),mode:r,maxTurns:i!==void 0&&!isNaN(i)?i:void 0,verbose:t.verbose})}),h.command(`skills`).description(`List available agent skills and optional recommendations by mode`).option(`-m, --mode <mode>`,`Show skills recommended for this mode`).action(async e=>{await d.execute({mode:e.mode})}),h.command(`sync`).description(`Sync the connector-building skills + guide into this project (.claude/ + CLAUDE.md)`).option(`--check`,`Report drift and exit non-zero instead of writing (CI guard)`).option(`--plugin-dir <path>`,`Override the agent-harness plugin dir (e.g. point at a checkout in CI/benchmarks)`).action(async e=>{await f.execute({check:!!e.check,pluginDir:e.pluginDir})}),h.command(`chat`).option(`-m, --mode <mode>`,`Mode: build, test, or research`,`build`).option(`-c, --connector <name>`,`Connector name`).option(`-a, --action <name>`,`Action name`).option(`-g, --goal <goal>`,`Initial goal/message`).option(`-t, --temperature <number>`,`Temperature (0-1, default: 0.5)`,parseFloat).option(`-v, --verbose`,`Enable verbose logging`).description(`Start an interactive chat session with the agent (use /commands in chat)`).action(async e=>{let t=[`build`,`test`,`research`];e.mode&&!t.includes(e.mode)&&(y.error(`❌ Error: Invalid mode "${e.mode}". Must be one of: ${t.join(`, `)}`),process.exit(1)),e.temperature!==void 0&&(isNaN(e.temperature)&&(y.error(`❌ Error: Temperature must be a valid number`),process.exit(1)),(e.temperature<0||e.temperature>1)&&(y.error(`❌ Error: Temperature must be between 0 and 1`),process.exit(1))),l.execute({mode:e.mode,connector:e.connector,action:e.action,goal:e.goal,temperature:e.temperature,verbose:e.verbose})}),this.program.command(`update`).option(`-f, --force`,`Force reinstall even if already on latest version`).description(`Update the CLI to the latest version`).action(e=>{m.execute({force:e.force})}),this.program.command(`version`).description(`Show version information`).action(async()=>{y.log(`${T.inverse.greenBright(`StackOne`)} ${T.grey(`CLI`)} ${T.whiteBright(this.version)}`),di(!0),process.exit(0)})}run(){process.argv.includes(`version`)||di(),this.program.parse(process.argv)}};export{_i as t};
174
+ `)}`;return this.#n(r)};#i=(e,t,n)=>{let r=e;try{r=K.readFileSync(e,`utf-8`)}catch{}try{let e=Gr.parse(JSON.parse(r));return{providerKey:t,providerVersion:n,authConfigKey:e.auth_config_key,environment:e.environment,organizationId:e.organization_id,secureId:e.account_id,projectSecureId:e.project_id}}catch(e){let t=[];try{t=JSON.parse(e.message)}catch{}y.error(`Failed to parse account information`),x(t,!1),t.length===0&&y.log(e.message),process.exit(1)}};#a=e=>!e.includes(`/`)&&!e.includes(`\\`)&&!e.endsWith(`.yaml`)&&!e.endsWith(`.yml`)?e.includes(`@`)?e.split(`@`).length===2:!0:!1;#o=e=>e.includes(`@`)?e:`${e}@latest`;#s=async(e,n,i,a)=>{(Y(e)||Y(n)||Y(i))&&(y.error(`Connector identifier, API URL, and API key are required to fetch connector from registry.`),process.exit(1));let o=J();try{o.text=`Fetching connector ${t(e)} from registry...`,o.start();let r=Buffer.from(i).toString(`base64`),s=a?`?owner=${encodeURIComponent(a)}`:``,c=await fetch(`${n}/registry/connectors/${e}${s}`,{method:`GET`,headers:{Authorization:`Basic ${r}`}});if(o.stop(),c.status===409){a&&(await b(c,`Failed to fetch connector ${t(e)} from registry`),process.exit(1));let i=await kr(e,(await c.json()).availableOwners??[]);o.text=`Fetching connector ${t(e)} from registry...`,o.start();let s=await fetch(`${n}/registry/connectors/${e}?owner=${encodeURIComponent(i)}`,{method:`GET`,headers:{Authorization:`Basic ${r}`}});o.stop(),s.ok||(await b(s,`Failed to fetch connector ${t(e)} from registry`),process.exit(1));let l=await s.text(),u=this.#n(l);return y.success(`Fetched connector ${t(u.key)}@${t(u.version)} from registry`),u}c.ok||(await b(c,`Failed to fetch connector ${t(e)} from registry`),process.exit(1));let l=await c.text(),u=this.#n(l);return y.success(`Fetched connector ${t(u.key)}@${t(u.version)} from registry`),u}catch(i){o.stop(),y.error(`Failed to fetch connector ${t(e)} from registry: ${i.message}`),y.log(`Please ensure that the API at ${r(n)} is reachable and the API key is valid`),process.exit(1)}};#c=async(e,n,i)=>{(Y(e)||Y(n)||Y(i))&&(y.error(`Account ID, API URL, and API key are required to fetch connector`),process.exit(1));let a=J();try{a.text=`Fetching connector for account ${t(e)} from API...`,a.start();let r=Buffer.from(i).toString(`base64`),o=await fetch(`${n}/accounts/${e}/connector`,{method:`GET`,headers:{Authorization:`Basic ${r}`}});a.stop(),o.ok||(await b(o,`Failed to fetch connector`),process.exit(1));let s=await o.text(),c=this.#n(s);return y.success(`Fetched connector ${t(c.key)}@${t(c.version)} for account ${t(e)}`),c}catch(e){a.stop(),y.error(`Failed to fetch connector: ${e.message}`),y.log(`Please ensure that the API at ${r(n)} is reachable and the API key is valid`),process.exit(1)}};#l=async(e,n,i)=>{(Y(e)||Y(n)||Y(i))&&(y.error(`Account ID, API URL, and API key are required to fetch account information.`),process.exit(1));let a=J();try{a.text=`Fetching account ${t(e)} information from API...`,a.start();let r=Buffer.from(i).toString(`base64`),o=await fetch(`${n}/accounts/${e}/credentials`,{method:`GET`,headers:{Authorization:`Basic ${r}`}});a.stop(),o.ok||(await b(o,`Failed to fetch account ${t(e)} information`),process.exit(1));let s=await o.json();return y.success(`Fetched account ${t(e)} information from project ${t(s.project_id)}`),{providerKey:s.provider_key,providerVersion:s.provider_version,authConfigKey:s.auth_config_key,environment:s.environment,organizationId:s.organization_id,secureId:s.account_id,projectSecureId:s.project_id,credentials:s.credentials}}catch(i){a.stop(),y.error(`Failed to fetch account ${t(e)} information: ${i.message}`),y.log(`Please ensure that the API at ${r(n)} is reachable and the API key is valid`),process.exit(1)}};#u=e=>{let t=e;try{t=K.readFileSync(e,`utf-8`)}catch{}try{return Kr.parse(JSON.parse(t))}catch(e){let t=[];try{t=JSON.parse(e.message)}catch{}y.error(`Failed to parse credentials`),x(t,!1),t.length===0&&y.log(e.message),process.exit(1)}};#d=(e,n)=>{let r=e;try{r=K.readFileSync(e,`utf-8`)}catch{}try{return qr.parse(JSON.parse(r))}catch(e){let r=[];try{r=JSON.parse(e.message)}catch{}y.error(`Invalid parameters for action ${t(n)}.`),x(r,!1),r.length===0&&y.log(e.message),process.exit(1)}};async#f({connector:e,actionId:n,account:r,pathParams:i={},queryParams:a={},body:s={},headers:c={}}){try{let l=await $e({mode:`action_id`,actionId:n,account:r,connector:e,pathParams:i,queryParams:a,body:s,headers:c,getHttpClient:async()=>new at});if(l.response?.successful){let e={...this.#p(a,l.steps),...He(l.outputs)?l.outputs:{data:l.outputs}};return{statusCode:l.response?.statusCode,output:e}}else{let r=l.response?.message??`An error occurred while processing the request`;y.error(`Action ID ${t(n)} from connector ${t(e.key)}@${t(e.version)} failed with status ${l.response?.statusCode}: ${r}`);let i={...this.#p(a,l.steps)};Object.keys(i).length>0&&(y.log(`${T.yellow.inverse(` EXECUTION DETAILS `)}`),o(i)),process.exit(1)}}catch(e){this.#m(e)}}#p(e,t){return e?.debug===`true`?{debug:{steps:t}}:{}}#m(e){let t=e;switch(Y(t.errorType)&&(y.error(`An unknown error occurred`),y.log(`${e instanceof Error?e.message:String(e)}`),process.exit(1)),t.errorType){case`MISSING_ACTION_ERROR`:y.error(`The specified action was not found: ${t.message}`);break;case`INVALID_ACTION_INPUTS_ERROR`:let e=t;y.error(`Invalid action inputs`),x(e.validationErrors,!1);break;case`INVALID_CURSOR_ERROR`:y.error(`Invalid cursor: ${t.message}`);break;default:y.error(`An error occurred: ${t.message}`)}process.exit(1)}};const Xr=ot(Ce);var Zr=class{constructor(){this.packageName=`@stackone/cli`,this.spinner=J(),this.currentVersion=Kt()}async execute(e={}){this.spinner.text=`Checking for updates...`,this.spinner.start();try{let t=await this.getLatestVersion();this.spinner.stop(),t||(y.error(`Failed to check for updates`),process.exit(1)),this.isNewerVersion(t,this.currentVersion)?(y.box(`New version available: ${T.yellow(this.currentVersion)} → ${T.green(t)}`),await this.performUpdate(t)):e.force?(y.warn(`No updates available, but forcing reinstall...`),await this.performUpdate(t)):y.success(`You are already on the latest version (${this.currentVersion})`),process.exit(0)}catch(e){this.spinner.stop(),y.error(`Error while trying to update StackOne CLI: ${e?.message??`Unknown error`}`),process.exit(1)}}async getLatestVersion(){try{let{stdout:e}=await Xr(`npm view ${this.packageName} version`,{encoding:`utf-8`});return e.trim()}catch{return null}}isNewerVersion(e,t){return it.gt(e,t)}async performUpdate(e){this.spinner.text=`Updating to latest version (${t(e)})...`,this.spinner.start();let n=`npm install -g ${this.packageName}@latest`;try{await Xr(n,{encoding:`utf-8`}),this.spinner.stop(),y.success(`StackOne CLI updated successfully to latest version (${t(e)})`)}catch{throw this.spinner.stop(),Error(`Failed to install update. Please try manually: ${n}`)}}};const Qr=e=>e===null?!0:Object.values(e).some(e=>e!==null),$r=()=>{y.log(`${T.gray.inverse(` CONNECTORS VALIDATION `)} ${T.yellow.inverse(` WATCH MODE `)}\n`)};var ei=class{async execute(e){let{watchMode:t,fileOrDir:n}=e,r=J(`Watching for file changes... ${T.gray(`(press "q" to quit)`)}`);if(!n)return;let i=Fe(n);try{await ct(i)}catch{y.error(`The specified path does not exist: ${i}\n`),process.exit(1)}if(t){v();let e={},{watch:t}=await import(`chokidar`),n=(await import(`readline`)).createInterface({input:process.stdin,output:process.stdout});process.stdin.setRawMode(!0),process.stdin.resume(),process.stdin.setEncoding(`utf8`);let a=()=>{s.close(),r.stop(),n.close(),y.log(T.grey(`
175
+ Exiting watch mode...`)),process.exit(0)};$r(),y.start(`Validating connectors...`);let o=await ii(i);e=ti(e,o||{}),ni(e,i),r.start();let s=t(i,{persistent:!0,ignoreInitial:!0}),c=async t=>{if(!t.endsWith(`.s1.yaml`)&&!t.endsWith(`s1.partial.yaml`))return;let n=t.endsWith(`s1.partial.yaml`)?await oi(t):[t];if(!(!n||n.length===0)){v(),r.stop(),$r(),y.log(T.gray(`File change detected: ${t}`)),y.start(`Validating connectors...`);for(let t of n){let n=await ii(t);e=ti(e,n||{})}ni(e,i),r.start()}};s.on(`change`,async e=>await c(e)),process.stdin.on(`data`,e=>{e.toString()===`q`&&a()}),process.on(`SIGINT`,()=>{a()})}else{let e=await ii(i,y);process.exit(Qr(e)?1:0)}}};const ti=(e,t)=>{for(let[n,r]of Object.entries(t))e[n]=r;return e},ni=(e,n)=>{v(),$r();let r=0,i=0;for(let[n,a]of Object.entries(e))a===null?r++:(y?.error(`Connector ${t(n)} is not valid`),x(a,!0),i++);y.log(``),y.log(T.blue.inverse(` Validation Summary `)),y.log(`Connectors path: ${t(n)}`),y.log(`${r===0?T.red(`0`):T.green(r)} valid, ${i===0?T.green(`0`):T.red(i)} invalid connectors\n`)},ri=async e=>{let t=[],n=await st(e);for(let r of n){let n=Pe(e,r),i=await ct(n);i.isDirectory()?t.push(...await ri(n)):i.isFile()&&r.endsWith(`.s1.yaml`)&&t.push(n)}return t},ii=async(e,r)=>{let i=await ct(e),a={};if(i.isDirectory()){let i=await ri(e);if(i.length===0)return r?.error(`No StackOne connector found in ${n(e)}`),r?.log(`Connector files need to have the extension ${t(`*.s1.yaml`)}`),null;let o=0,s=0;for(let e of i){let t=await ai(e,r);t===null?o++:(r?.log(``),s++),a[e]=t}return r?.log(``),r?.log(T.blue.inverse(` Validation Summary `)),r?.log(`${o===0?T.red(`0`):T.green(o)} valid, ${s===0?T.green(`0`):T.red(s)} invalid connectors`),a}else if(i.isFile()&&e.endsWith(`s1.yaml`))return a[e]=await ai(e,r),a;else if(i.isFile()&&e.endsWith(`partial.yaml`)){r?.error(`Partial connector files cannot be validated directly`),r?.log(`The file ${n(e)} is a partial connector file.`);let i=await oi(e);return i&&i?.length>0&&r?.log(`Did you mean ${t(i[0])}?`),null}else return r?.error(`No StackOne connector found in ${n(e)}`),r?.log(`Connector files need to have the extension ${t(`*.s1.yaml`)}`),null},ai=async(e,n)=>{let r=et(Ze(e)),i=r?.errors??[];if(r.success){let r=e.split(`/`).pop()||e;return n?.success(`Connector ${t(r)} is valid!`),null}else if(i.length>0)return n?.error(`Connector ${t(e)} is not valid`),n&&x(i,!0),i;else return n?.error(`Connector ${t(e)} is not valid. Please check the file for errors`),[]},oi=async e=>{let t=Ne(e);try{return(await st(t)).filter(e=>e.endsWith(`.s1.yaml`))?.map(e=>Pe(t,e))}catch{}};function si(e){if(!e)return!1;try{let{hostname:t}=new URL(e);return t===`stackone-dev.com`||t.endsWith(`.stackone-dev.com`)}catch{return!1}}function ci(){return process.env.AI_TELEMETRY_URL?process.env.AI_TELEMETRY_URL:[process.env.AUTH_SERVER_URL,process.env.STACKONE_API_URL].some(si)?`https://ai-telemetry.stackone-dev.com`:`https://ai-telemetry.stackone.com`}function li(){let e=process.env.STACKONE_AGENT_TOKEN,t=process.env.LANGSMITH_PROJECT||`stackone-agent-cli`;if(process.env.AI_TELEMETRY_URL=ci(),e)try{ce({apiKey:e,projectName:t}),process.env.VERBOSE&&console.log(`[Telemetry] Initialized for project:`,t)}catch(e){process.env.VERBOSE&&console.error(`[Telemetry] Failed to initialize:`,e)}}const ui=R(I(),`.stackone`),di=R(ui,`version-check.json`),fi=(e=!1)=>{let t=gi(),n=Date.now();if(e||!t||n-t.lastCheckTime>1728e5){let e=pi();e&&mi(e)&&hi(e),_i({lastCheckTime:n})}},pi=()=>{try{return Ee(`npm view @stackone/cli version`,{encoding:`utf-8`,stdio:[`pipe`,`pipe`,`pipe`],timeout:15e3}).trim()}catch{return null}},mi=e=>{try{let t=Kt();return it.gt(e,t)}catch{return!1}},hi=e=>{let t=Kt(),n=`Update available: ${T.dim(t)} → ${T.green(e)}`,r=`\n\nRun ${T.cyan(`stackone update`)} to update`;y.box(n,r)},gi=()=>{try{if(!N(di))return null;let e=de(di,`utf-8`);return JSON.parse(e)}catch{return null}},_i=e=>{try{N(ui)||ue(ui,{recursive:!0}),me(di,JSON.stringify(e,null,2),`utf-8`)}catch{}};var vi=class{constructor(e=new ne,t=Kt()){this.program=e,this.version=t,li(),this.setupProgram(),this.registerCommands()}setupProgram(){this.program.name(`stackone`).description(`StackOne CLI`).version(this.version,`-v, --version`)}registerCommands(){let e=new Nr,t=new Rr,n=new Ir,r=new Dr,i=new jr,a=new ei,o=new xn,s=new hr,c=new an,l=new rn,u=new Cn,d=new gr,f=new yr,p=new Yr,m=new Zr;this.program.configureOutput({writeOut:e=>process.stdout.write(e),writeErr:e=>process.stderr.write(e),outputError:(e,t)=>{t(T.red(e))}}),this.program.command(`init`).option(`-e, --env <environment>`,`Specify the environment for the configuration profile`).description(`Initialize & create a StackOne CLI configuration profile`).action(t=>{e.execute({environment:t.env})}),this.program.command(`push`).option(`-p, --profile <label>`,`Configuration profile to use`).option(`--api-url <api url>`,`API URL`).option(`--api-key <api key>`,`API Key`).option(`--force`,`Force push the connector, bypassing version conflict checks`).addArgument(new E(`<path>`,`Connector file or directory to push`)).description(`Push a connector to the StackOne registry`).action((e,n)=>{t.execute({profile:n.profile,fileOrDir:e,apiUrl:n.apiUrl,apiKey:n.apiKey,force:n.force})}),this.program.command(`drop`).option(`-p, --profile <label>`,`Configuration profile to use`).option(`--api-url <api url>`,`API URL`).option(`--api-key <api key>`,`API Key`).addArgument(new E(`<connector>`,`Connector identifier in format provider_key@version`)).description(`Drop a connector from the StackOne registry`).action((e,t)=>{r.execute({profile:t.profile,connector:e,apiUrl:t.apiUrl,apiKey:t.apiKey})}),this.program.command(`get`).option(`-p, --profile <label>`,`Configuration profile to use`).option(`--api-url <api url>`,`API URL`).option(`--api-key <api key>`,`API Key`).option(`-c, --connector <connector>`,`Connector identifier in format provider_key@version or provider_key (defaults to latest)`).option(`--account-id <account-id>`,`Account ID to fetch connector from`).option(`-f, --format <format>`,`Output format: yaml or json (default: yaml)`,`yaml`).option(`-o, --output-file <output-file>`,`File to write the output to`).option(`--builtin`,`Use the builtin (StackOne) version of the connector`).option(`--custom`,`Use the custom (organization) version of the connector`).option(`--owner <owner>`,`Owner to use for disambiguating connector versions`).description(`Get a connector from the StackOne registry`).action(e=>{[e.builtin,e.custom,e.owner].filter(Boolean).length>1&&(y.error(`--builtin, --custom, and --owner are mutually exclusive. Please provide only one.`),process.exit(1)),i.execute({profile:e.profile,connector:e.connector,accountId:e.accountId,format:e.format,outputFile:e.outputFile,apiUrl:e.apiUrl,apiKey:e.apiKey,owner:e.builtin?`builtin`:e.custom?`custom`:e.owner})}),this.program.command(`pull`).option(`-c, --connector <connector>`,`Connector identifier in format provider_key@version or provider_key`).option(`-p, --profile <label>`,`Configuration profile to use`).option(`--api-url <api url>`,`API URL`).option(`--api-key <api key>`,`API Key`).option(`-o, --output <path>`,`Output directory for the connectors files (default: ./connectors)`).option(`--builtin`,`Use the builtin (StackOne) version of the connector`).option(`--custom`,`Use the custom (organization) version of the connector`).option(`--owner <owner>`,`Owner to use for disambiguating connector versions`).description(`Pull a connector configuration from StackOne registry to local filesystem`).action(e=>{[e.builtin,e.custom,e.owner].filter(Boolean).length>1&&(y.error(`--builtin, --custom, and --owner are mutually exclusive. Please provide only one.`),process.exit(1)),n.execute({profile:e.profile,connector:e.connector,outputPath:e.output,apiUrl:e.apiUrl,apiKey:e.apiKey,owner:e.builtin?`builtin`:e.custom?`custom`:e.owner})}),this.program.command(`validate`).option(`-w, --watch`,`Run in watch mode`).addArgument(new E(`<path>`,`Connector file or directory with connectors to validate`)).description(`Validate a StackOne connector`).action((e,t)=>{a.execute({watchMode:t.watch,fileOrDir:e})}),this.program.command(`run`).option(`--connector <connector>`,`Connector file, inline YAML, or identifier (provider_key@version or provider_key for latest)`).option(`--action <action>`,`Action to execute on the connector (path to file or inline string action code)`).option(`--action-id <action-id>`,`Action ID to execute on the connector`).option(`--account <account>`,`Account details to use for running the connector (path to file or inline string account data)`).option(`--account-id <account-id>`,`Account ID to use for running the connector against (fetches connector from API if --connector not provided)`).option(`--params <params>`,`Action parameters (path to file or inline string with JSON parameters)`).option(`--credentials <credentials>`,`Credentials to use (path to file or inline string with JSON credentials)`).option(`-p, --profile <label>`,`Configuration profile to use`).option(`--api-url <api url>`,`API URL`).option(`--api-key <api key>`,`API Key`).option(`-o, --output-file <output-file>`,`File to write the output to`).option(`-d, --debug`,`Enables debug mode to include more details in the action execution output`).option(`--builtin`,`Use the builtin (StackOne) version of the connector`).option(`--custom`,`Use the custom (organization) version of the connector`).option(`--owner <owner>`,`Owner to use for disambiguating connector versions`).description(`Run a connector action`).action(e=>{[e.builtin,e.custom,e.owner].filter(Boolean).length>1&&(y.error(`--builtin, --custom, and --owner are mutually exclusive. Please provide only one.`),process.exit(1)),p.execute({connector:e.connector,action:e.action,actionId:e.actionId,account:e.account,accountId:e.accountId,params:e.params,credentials:e.credentials,profile:e.profile,outputFile:e.outputFile,debug:e.debug,apiUrl:e.apiUrl,apiKey:e.apiKey,owner:e.builtin?`builtin`:e.custom?`custom`:e.owner})});let h=this.program.command(`agent`).description(`StackOne agent commands`);h.command(`setup`).option(`-g, --global`,`Global only: auth + MCP server (no connector skills/guide)`).option(`-l, --local`,`Local: auth + .mcp.json + connector skills (.claude/) and guide (CLAUDE.md)`).option(`--path <dir>`,`Target project path for local setup (defaults to the current directory)`).option(`--legacy`,`Use email/password login instead of browser-based auth`).option(`--email <email>`,`Email for legacy login (or set STACKONE_EMAIL); requires --legacy`).option(`--password <password>`,`Password for legacy login (or set STACKONE_PASSWORD); requires --legacy. Prefer --password-stdin`).option(`--password-stdin`,`Read password for legacy login from stdin; requires --legacy`).description(`Set up the StackOne agent — prompts for global vs local when neither flag is given`).action(async e=>{e.global&&e.local&&(y.error(`--global and --local are mutually exclusive. Please provide only one.`),process.exit(1));let t=e.email!==void 0,n=e.password!==void 0,r=e.passwordStdin===!0;n&&r&&(y.error(`--password and --password-stdin are mutually exclusive. Please provide only one.`),process.exit(1));let i=t||n||r;i&&!e.legacy&&(y.error(`--email, --password, and --password-stdin require --legacy.`),process.exit(1)),t&&e.email.trim()===``&&(y.error(`--email cannot be empty.`),process.exit(1)),n&&e.password===``&&(y.error(`--password cannot be empty.`),process.exit(1)),r&&(t||process.env.STACKONE_EMAIL?.trim()||(y.error(`--password-stdin requires --email or STACKONE_EMAIL (stdin is consumed for the password, so email cannot be prompted).`),process.exit(1)));let a={email:e.email,password:e.password,passwordFromStdin:r},c=!!process.stdin.isTTY;if(c&&!e.legacy&&!i){let t=await mr({initialMode:e.global?`global`:e.local?`local`:null,pathFlag:e.path});process.exit(t.status===`error`?1:0)}let l=c&&!i;!e.global&&!e.local&&!l&&y.log(T.dim(`No interactive terminal detected — defaulting to global setup. Run in a terminal for the prompt, or pass --local (with --path) / --global.`));let u=Dn(e.global,e.local,l);if(u===null&&(u=await dr()),u===`local`){let t=On(e.path,l);t===null&&(t=await pr(process.cwd())),await s.execute({legacy:!!e.legacy,credentials:a,targetPath:t})}else await o.execute({legacy:!!e.legacy,credentials:a})}),h.command(`cleanup`).description(`Remove all API keys and credentials from configurations`).action(()=>{c.execute()}),h.command(`run`).description(`Run the agent once with a prompt (non-interactive)`).argument(`<prompt>`,`What to do`).option(`-m, --mode <mode>`,`Mode: build, test, or research`,`build`).option(`--max-turns <n>`,`Max agent turns`,`25`).option(`-v, --verbose`,`Verbose output`).action(async(e,t)=>{let n=[`build`,`test`,`research`],r=t.mode??`build`;n.includes(r)||(y.error(`${T.red(`Invalid mode:`)} ${T.white(r)}. Valid modes are: ${n.join(`, `)}.`),process.exit(1));let i=t.maxTurns?parseInt(String(t.maxTurns),10):void 0;await u.execute({prompt:String(e),mode:r,maxTurns:i!==void 0&&!isNaN(i)?i:void 0,verbose:t.verbose})}),h.command(`skills`).description(`List available agent skills and optional recommendations by mode`).option(`-m, --mode <mode>`,`Show skills recommended for this mode`).action(async e=>{await d.execute({mode:e.mode})}),h.command(`sync`).description(`Sync the connector-building skills + guide into this project (.claude/ + CLAUDE.md)`).option(`--check`,`Report drift and exit non-zero instead of writing (CI guard)`).option(`--plugin-dir <path>`,`Override the agent-harness plugin dir (e.g. point at a checkout in CI/benchmarks)`).action(async e=>{await f.execute({check:!!e.check,pluginDir:e.pluginDir})}),h.command(`chat`).option(`-m, --mode <mode>`,`Mode: build, test, or research`,`build`).option(`-c, --connector <name>`,`Connector name`).option(`-a, --action <name>`,`Action name`).option(`-g, --goal <goal>`,`Initial goal/message`).option(`-t, --temperature <number>`,`Temperature (0-1, default: 0.5)`,parseFloat).option(`-v, --verbose`,`Enable verbose logging`).description(`Start an interactive chat session with the agent (use /commands in chat)`).action(async e=>{let t=[`build`,`test`,`research`];e.mode&&!t.includes(e.mode)&&(y.error(`❌ Error: Invalid mode "${e.mode}". Must be one of: ${t.join(`, `)}`),process.exit(1)),e.temperature!==void 0&&(isNaN(e.temperature)&&(y.error(`❌ Error: Temperature must be a valid number`),process.exit(1)),(e.temperature<0||e.temperature>1)&&(y.error(`❌ Error: Temperature must be between 0 and 1`),process.exit(1))),l.execute({mode:e.mode,connector:e.connector,action:e.action,goal:e.goal,temperature:e.temperature,verbose:e.verbose})}),this.program.command(`update`).option(`-f, --force`,`Force reinstall even if already on latest version`).description(`Update the CLI to the latest version`).action(e=>{m.execute({force:e.force})}),this.program.command(`version`).description(`Show version information`).action(async()=>{y.log(`${T.inverse.greenBright(`StackOne`)} ${T.grey(`CLI`)} ${T.whiteBright(this.version)}`),fi(!0),process.exit(0)})}run(){process.argv.includes(`version`)||fi(),this.program.parse(process.argv)}};export{vi as t};
@@ -138,22 +138,22 @@ Error: `+(t instanceof Error?t.message:String(t)))),process.exit(1)}f?.stop(),e.
138
138
  `))}async executeOrchestratedBuild(t){let{provider:n,category:r,verbose:a}=t,o=r?` (${r})`:``;e.w.log(i.default.bold(`\nOrchestrated build: ${n}${o}\n`));let s=null,c=new Map;try{for await(let e of Ce(t))switch(e.type){case`phase_start`:{let t=Xe[e.phase]||`${e.phase}...`,n=e.model?i.default.dim(` (${N(e.model)})`):``;s?.stop(),s=(0,v.default)(i.default.cyan(`[${e.phase}]${n} ${t}`)).start(),c.set(e.phase,Date.now());break}case`phase_complete`:{let t=c.get(e.phase),n=t===void 0?0:Math.round((Date.now()-t)/1e3);s?.succeed(i.default.green(`[${e.phase}] Done (${n}s)`)),s=null;break}case`phase_error`:s?.fail(i.default.red(`[${e.phase}] ${e.error}`)),s=null;break;case`agent_message`:Qe(e,s,a);break}}catch(t){s?.fail(),e.w.error(i.default.red(`
139
139
  Error: `+(t instanceof Error?t.message:String(t)))),process.exit(1)}s?.stop(),e.w.log(i.default.green(`
140
140
  ✓ Build complete
141
- `))}};const Qe=(t,n,r)=>{let a=t.message;switch(a.type){case`text`:r&&process.stdout.write(a.content??``);break;case`tool_call`:{let e=a.toolName??`unknown tool`;n&&(n.text=i.default.cyan(`[${t.phase}] Tool: ${e}`));break}case`tool_error`:e.w.error(i.default.red(`\n[${t.phase}] Tool error (${a.toolName}): ${a.error??`Unknown error`}`));break;case`error`:e.w.error(i.default.red(`\n[${t.phase}] ${a.error??`Unknown error`}`));break;default:break}};function $e(t,n){switch(t.type){case`text`:n(null),process.stdout.write(t.content??``);break;case`tool_call`:{let e=t.toolName??`unknown tool`;n((0,v.default)(i.default.cyan(`Tool: ${e}`)).start());break}case`tool_result`:n(null);break;case`tool_progress`:{let e=t.progress?.operation||t.toolName||`Working...`;n((0,v.default)(i.default.cyan(`Tool: ${e}`)).start());break}case`tool_error`:n(null),e.w.error(i.default.red(`\nTool error (${t.toolName}): ${t.error??`Unknown error`}`));break;case`error`:n(null),e.w.error(i.default.red(`\n${t.error??`Unknown error`}`));break;case`done`:n(null);break;default:process.env.VERBOSE&&console.warn(`[AgentRun] Unknown message type:`,t.type);break}}const et=e=>{let t=e.trim();return t===`~`?(0,c.homedir)():t.startsWith(`~/`)?(0,l.join)((0,c.homedir)(),t.slice(2)):t},tt=(e,t,n)=>e?`global`:t?`local`:n?null:`global`,nt=(e,t)=>e?.trim()||(t?null:process.cwd()),rt=e=>e.existingConfig?`overwrite`:it(e),it=e=>e.mode===`local`&&e.alreadyAuthed?`work`:`auth`,at=(e,t)=>{switch(e){case`mode`:return t.mode===`local`?t.hasGit?`repo-confirm`:`path-input`:rt(t);case`repo-confirm`:return t.repoAccepted?rt(t):`path-input`;case`path-input`:return rt(t);case`overwrite`:return it(t);case`auth`:return`work`;default:return`done`}},ot=(e,t)=>(0,f.execFileSync)(`git`,[`-C`,e,...t],{encoding:`utf-8`,stdio:[`ignore`,`pipe`,`ignore`]}).trim(),st=e=>{try{let t=ot(e,[`rev-parse`,`--show-toplevel`]);if(!t)return null;let n;try{n=ot(e,[`remote`,`get-url`,`origin`])||void 0}catch{}return{root:t,remoteUrl:n}}catch{return null}},ct=`connector-guide.md`,lt=`<!-- BEGIN stackone-connector-guide -->`,ut=`<!-- END stackone-connector-guide -->`,dt=`.stackone-connector-env.json`,ft=/^[a-z0-9][a-z0-9_-]*$/,pt=e=>e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`),mt=e=>`<!-- Generated by \`stackone agent sync\` from @stackone/agent-harness@${e}. Edit upstream, not here. -->`,ht=e=>{if(e.includes(`..`)||!ft.test(e))throw Error(`Refusing unsafe path segment: ${JSON.stringify(e)}`)},Q=(e,...t)=>{let n=(0,l.resolve)(e),r=(0,l.resolve)(n,...t);if(r!==n&&!r.startsWith(n+l.sep))throw Error(`Refusing path outside ${n}: ${r}`);return r},gt=(e,...t)=>(0,s.readFileSync)(Q(e,...t),`utf-8`),_t=(e,...t)=>(0,s.readFileSync)(Q(e,...t)),vt=`@stackone/agent-harness`,yt=()=>{let e=(0,g.createRequire)(require(`url`).pathToFileURL(__filename).href).resolve(`@stackone/agent-harness`),t=(0,l.dirname)(e);for(let e=0;e<6;e++){if((0,s.existsSync)((0,l.join)(t,`package.json`))&&(0,s.existsSync)((0,l.join)(t,`plugin`)))return t;let e=(0,l.dirname)(t);if(e===t)break;t=e}return(0,l.dirname)((0,l.dirname)(e))},bt=()=>(0,l.join)(yt(),`plugin`),xt=e=>{try{let t=e?(0,l.resolve)(e,`..`):yt();return JSON.parse(gt(t,`package.json`)).version??`unknown`}catch{return`unknown`}},St=e=>{let t=e.charCodeAt(0)===65279?e.slice(1):e,n=t.match(/^---\n[\s\S]*?\n---\n?/);return n&&(t=t.slice(n[0].length)),t=t.replace(/^\s*<!--[\s\S]*?-->\s*/,``),t.trim()},Ct=(e,t,n)=>{let r=[lt,mt(n),``,t,``,ut].join(`
142
- `);if(e.includes(lt)&&e.includes(ut)){let t=RegExp(`${pt(lt)}[\\s\\S]*?${pt(ut)}`);return e.replace(t,r)}let i=e.replace(/\s*$/,``);return i.length>0?`${i}\n\n${r}\n`:`${r}\n`},wt=e=>{let t=[];for(let n of(0,s.readdirSync)(e,{withFileTypes:!0}))if(n.isDirectory()){let r=wt(Q(e,n.name));t.push(...r.map(e=>(0,l.join)(n.name,e)))}else t.push(n.name);return t},Tt=(e,t)=>{if(!(0,s.existsSync)(t))return!1;let n=wt(e).sort(),r=wt(t).sort();return n.length!==r.length||n.some((e,t)=>e!==r[t])?!1:n.every(n=>_t(e,n).equals(_t(t,n)))},Et=(e,t)=>{(0,s.rmSync)(t,{recursive:!0,force:!0}),(0,s.mkdirSync)((0,l.dirname)(t),{recursive:!0}),(0,s.cpSync)(e,t,{recursive:!0})},Dt=e=>(0,s.existsSync)(e)?(0,s.readdirSync)(e,{withFileTypes:!0}).filter(e=>e.isDirectory()&&ft.test(e.name)).filter(t=>(0,s.existsSync)(Q(e,t.name,`SKILL.md`))).map(e=>e.name).sort():[],Ot=()=>({changed:[],unchanged:[],missing:[]}),kt=(e,t,n,r)=>{let i=Ot();for(let a of e){ht(a);let e=Q(t,a);if(!(0,s.existsSync)(e)||!(0,s.statSync)(e).isDirectory()){i.missing.push(a);continue}let o=Q(n,a);if(Tt(e,o)){i.unchanged.push(a);continue}i.changed.push(a),r||Et(e,o)}return i},At=(e,t,n,r)=>{if(!(0,s.existsSync)(Q(e,ct)))return`missing-source`;let i=St(gt(e,ct)),a=Q(t,`CLAUDE.md`),o=(0,s.existsSync)(a)?gt(t,`CLAUDE.md`):``,c=Ct(o,i,n);return c===o?`unchanged`:(r||(0,s.writeFileSync)(a,c),`changed`)},jt=e=>{let t=(0,l.resolve)(e.pluginDir??bt()),n=(0,l.resolve)(e.cwd),r=e.version??xt(t),i=e.check??!1,a=Q(n,`.claude`),o=Q(t,`skills`),c=kt(Dt(o),o,Q(a,`skills`),i),u=At(t,n,r,i),d=c.changed.length>0||u===`changed`,f=u!==`missing-source`||c.changed.length+c.unchanged.length>0;if(!i&&f){(0,s.mkdirSync)(a,{recursive:!0});let e={harnessVersion:r,skills:c.changed.concat(c.unchanged).sort(),guide:u!==`missing-source`};(0,s.writeFileSync)(Q(a,`.stackone-connector-env.json`),`${JSON.stringify(e,null,2)}\n`)}return{skills:c,guide:u,hasChanges:d}},Mt=e=>{try{let t=e??bt();return(0,s.statSync)(t).isDirectory()?e?JSON.parse(gt((0,l.resolve)(t,`..`),`package.json`)).name===`@stackone/agent-harness`:!0:!1}catch{return!1}},Nt=`#00af66`,Pt=({message:e,choices:t,initialIndex:n=0,onSelect:r,onCancel:i})=>{let[a,o]=(0,d.useState)(()=>t.length?Math.min(Math.max(n,0),t.length-1):0);return(0,u.useInput)((e,n)=>{if(t.length===0){n.escape&&i?.();return}n.upArrow?o(e=>(e-1+t.length)%t.length):n.downArrow?o(e=>(e+1)%t.length):n.return?r(t[a].value):n.escape&&i?.()}),t.length===0?null:d.default.createElement(u.Box,{flexDirection:`column`,paddingY:1},d.default.createElement(u.Box,{borderStyle:`round`,borderColor:`cyan`,flexDirection:`column`,paddingX:2,paddingY:1},d.default.createElement(u.Text,{bold:!0},e),d.default.createElement(u.Box,{flexDirection:`column`,marginTop:1},t.map((e,t)=>d.default.createElement(u.Text,{key:e.value,color:t===a?`#00af66`:`white`},t===a?`❯ `:` `,e.label)))),d.default.createElement(u.Box,{marginTop:1},d.default.createElement(u.Text,{dimColor:!0},`↑↓ to navigate • Enter to select`)))},Ft=({message:e,initialValue:t=``,validate:n,onSubmit:r,onCancel:i})=>{let[a,o]=(0,d.useState)(t),[s,c]=(0,d.useState)(null);return(0,u.useInput)((e,t)=>{if(t.return){let e=n?n(a):!0;e===!0?r(a):c(e);return}if(t.escape){i?.();return}if(t.backspace||t.delete){o(e=>e.slice(0,-1)),c(null);return}e&&!t.ctrl&&!t.meta&&!t.tab&&!t.upArrow&&!t.downArrow&&(o(t=>t+e),c(null))}),d.default.createElement(u.Box,{flexDirection:`column`,paddingY:1},d.default.createElement(u.Text,{bold:!0},e),d.default.createElement(u.Box,{marginTop:1},d.default.createElement(u.Text,null,`> `),d.default.createElement(u.Text,null,a),d.default.createElement(u.Text,{inverse:!0},` `)),s&&d.default.createElement(u.Box,{marginTop:1},d.default.createElement(u.Text,{color:`red`},s)),d.default.createElement(u.Box,{marginTop:1},d.default.createElement(u.Text,{dimColor:!0},`Enter to submit • Esc to cancel`)))},It=e=>(0,s.existsSync)(`${e}/CLAUDE.md`)||(0,s.existsSync)(`${e}/.mcp.json`),Lt=e=>{try{return(0,s.statSync)(e).isDirectory()}catch{return!1}},Rt=({initialMode:t,pathFlag:r,startDir:i,onExit:a})=>{let[o,c]=(0,d.useState)(`mode`),[f,m]=(0,d.useState)(null),[h,g]=(0,d.useState)(!1),[_,v]=(0,d.useState)([]),[y,b]=(0,d.useState)(``),[x,S]=(0,d.useState)(t),[C,w]=(0,d.useState)(``),[T,E]=(0,d.useState)(``),[ee,te]=(0,d.useState)(!1),[D,O]=(0,d.useState)(null),k=(0,d.useRef)(0),A=(0,d.useCallback)(e=>{k.current+=1;let t=k.current;v(n=>[...n,{...e,id:t}])},[]),M=(0,d.useCallback)(e=>{m(e)},[]),N=(0,d.useCallback)(async t=>{let n=(0,l.resolve)(et(t));if(!Lt(n)){M({status:`error`,message:(0,s.existsSync)(n)?`Target path is not a directory: ${n}`:`Target path does not exist: ${n}`});return}w(n);let r=It(n),i=e.l(await e.u());te(i),c(at(`path-input`,{mode:`local`,hasGit:!1,repoAccepted:!1,existingConfig:r,alreadyAuthed:i}))},[M]),P=(0,d.useCallback)(e=>{if(S(e),e===`local`){let e=r?.trim();if(e){N(e);return}let t=st(i);t&&(E(`Install the connector setup into this repo? ${t.remoteUrl?`${t.remoteUrl} (${t.root})`:t.root}`),w(t.root)),c(at(`mode`,{mode:`local`,hasGit:!!t,repoAccepted:!1,existingConfig:!1,alreadyAuthed:!1}));return}c(at(`mode`,{mode:`global`,hasGit:!1,repoAccepted:!1,existingConfig:It(i),alreadyAuthed:!1}))},[r,i,N]);(0,d.useEffect)(()=>{t&&P(t)},[]);let ne=(0,d.useCallback)(e=>{e?N(C):c(`path-input`)},[N,C]),re=(0,d.useCallback)(e=>{if(!e){M({status:`cancelled`});return}c(at(`overwrite`,{mode:x??`global`,hasGit:!1,repoAccepted:!1,existingConfig:!0,alreadyAuthed:ee}))},[x,ee,M]);return(0,d.useEffect)(()=>{if(o!==`auth`)return;let e=!1;return b(`Starting browser authentication…`),Ke(t=>{e||b(t)}).then(t=>{e||(O(t),A({icon:`✓`,text:t.email?`Authenticated as ${t.email}`:`Authenticated`,color:j.success}),c(`work`))}).catch(t=>{e||M({status:`error`,message:t instanceof Error?t.message:`Authentication failed`})}),()=>{e=!0}},[o,A,M]),(0,d.useEffect)(()=>{if(o!==`work`)return;let t=!1;return(async()=>{try{let r=D??await e.u();if(!r)throw Error(`Not authenticated — no API key found`);let a=await n.r(x===`local`?C:i,r.apiKey);if(a.migrated&&A({icon:`✓`,text:`Migrated ${a.actions.length} item(s) from a previous setup`,color:j.success}),x===`local`){b(`Creating .mcp.json…`),e.h(e.o(C),e.c(),r.apiKey),A({icon:`✓`,text:`Created .mcp.json`,color:j.success}),b(`Syncing connector-building skills + guide…`);let t=jt({cwd:C});A({icon:`✓`,text:`Connector environment ready (${t.skills.changed.length+t.skills.unchanged.length} skills in .claude/, ${t.guide===`missing-source`?`guide unavailable in this version`:`guide in CLAUDE.md`})`,color:j.success})}else b(`Installing global MCP configuration…`),e.h(e.a(),e.s(),r.apiKey),A({icon:`✓`,text:`Installed to Claude (global)`,color:j.success});if(t)return;b(``),M({status:`done`})}catch(e){if(t)return;M({status:`error`,message:e instanceof Error?e.message:`Setup failed`})}})(),()=>{t=!0}},[o,D,x,C,i,A,M]),(0,d.useEffect)(()=>{if(!f)return;let e=setTimeout(()=>a(f),60);return()=>clearTimeout(e)},[f,a]),d.default.createElement(u.Box,{flexDirection:`column`,padding:1},h?d.default.createElement(le,{wordmark:!0}):d.default.createElement(de,{ready:!0,onComplete:()=>g(!0)}),_.length>0&&d.default.createElement(u.Box,{flexDirection:`column`,marginTop:1},_.map(e=>d.default.createElement(u.Text,{key:e.id,color:e.color},e.icon?`${e.icon} `:``,e.text))),d.default.createElement(u.Box,{marginTop:1},(()=>{if(f)return f.status===`error`?d.default.createElement(u.Text,{color:j.error},`✗ `,f.message??`Setup failed`):f.status===`cancelled`?d.default.createElement(u.Text,{color:j.dim},`Setup cancelled.`):d.default.createElement(u.Box,{flexDirection:`column`},d.default.createElement(u.Text,{color:j.success},`✓ Setup complete!`),d.default.createElement(u.Box,{marginTop:1,flexDirection:`column`},d.default.createElement(u.Text,{color:j.dim},`Verify with `,d.default.createElement(u.Text,{color:j.primary},`claude mcp list`)),d.default.createElement(u.Text,{color:j.dim},`Tip: run`,` `,d.default.createElement(u.Text,{color:j.primary},`claude --dangerously-skip-permissions`),` `,`to skip permission prompts`),x===`local`&&d.default.createElement(u.Text,{color:j.dim},`Refresh skills anytime with`,` `,d.default.createElement(u.Text,{color:j.primary},`stackone agent sync`))));switch(o){case`mode`:return t?null:d.default.createElement(Pt,{message:`How do you want to set up the StackOne agent?`,initialIndex:0,choices:[{label:`Local — this project: auth + .mcp.json + connector skills (.claude/) + guide (CLAUDE.md)`,value:`local`},{label:`Global — any repo: auth + global MCP only (no connector skills/guide)`,value:`global`}],onSelect:e=>P(e),onCancel:()=>M({status:`cancelled`})});case`repo-confirm`:return d.default.createElement(Pt,{message:T,initialIndex:0,choices:[{label:`Yes`,value:`yes`},{label:`No, let me choose a path`,value:`no`}],onSelect:e=>ne(e===`yes`),onCancel:()=>M({status:`cancelled`})});case`path-input`:return d.default.createElement(Ft,{message:`Path to install the connector setup into:`,initialValue:i,validate:e=>{let t=et(e)||i;return(0,s.existsSync)(t)?Lt(t)?!0:`Path is not a directory: ${t}`:`Path does not exist: ${t}`},onSubmit:e=>void N(e.trim()||i),onCancel:()=>M({status:`cancelled`})});case`overwrite`:{let e=x===`local`;return d.default.createElement(Pt,{message:e?`Existing setup found in ${C}. Overwrite it?`:`Local setup detected in ${i} (it won't be modified). Set up the agent globally anyway?`,initialIndex:e?1:0,choices:[{label:e?`Yes, overwrite`:`Yes, set up globally`,value:`yes`},{label:`No, cancel`,value:`no`}],onSelect:e=>re(e===`yes`),onCancel:()=>M({status:`cancelled`})})}case`auth`:case`work`:return d.default.createElement(u.Text,null,d.default.createElement(u.Text,{color:j.primary},d.default.createElement(p.default,{type:`dots`})),` `,y);default:return null}})()))},zt=e=>new Promise(t=>{let{unmount:n}=(0,u.render)(e(e=>{n(),t(e)}))}),Bt=()=>zt(e=>d.default.createElement(Pt,{message:`How do you want to set up the StackOne agent?`,initialIndex:0,choices:[{label:`Local — this project: auth + .mcp.json + connector skills (.claude/) + guide (CLAUDE.md)`,value:`local`},{label:`Global — any repo: auth + global MCP only (no connector skills/guide)`,value:`global`}],onSelect:t=>e(t)})),Vt=(e,t=!0)=>zt(n=>d.default.createElement(Pt,{message:e,initialIndex:t?0:1,choices:[{label:`Yes`,value:`yes`},{label:`No`,value:`no`}],onSelect:e=>n(e===`yes`),onCancel:()=>n(!1)})),Ht=async e=>{let t=st(e);return t&&await Vt(`Install the connector setup into this repo? ${t.remoteUrl?`${t.remoteUrl} (${t.root})`:t.root}`,!0)?t.root:zt(n=>d.default.createElement(Ft,{message:t?`Path to install into:`:`Current directory is not a git repo. Path to install into:`,initialValue:e,validate:t=>{let n=et(t)||e;return(0,s.existsSync)(n)?!0:`Path does not exist: ${n}`},onSubmit:t=>n(et(t)||e)}))},Ut=e=>new Promise(t=>{let{unmount:n}=(0,u.render)(d.default.createElement(Rt,{initialMode:e.initialMode,pathFlag:e.pathFlag,startDir:e.startDir??process.cwd(),onExit:e=>{n(),t(e)}}))});var Wt=class{async execute(t){e.w.log(i.default.blue.bold(`🤖 StackOne Agent Setup - Local Project
141
+ `))}};const Qe=(t,n,r)=>{let a=t.message;switch(a.type){case`text`:r&&process.stdout.write(a.content??``);break;case`tool_call`:{let e=a.toolName??`unknown tool`;n&&(n.text=i.default.cyan(`[${t.phase}] Tool: ${e}`));break}case`tool_error`:e.w.error(i.default.red(`\n[${t.phase}] Tool error (${a.toolName}): ${a.error??`Unknown error`}`));break;case`error`:e.w.error(i.default.red(`\n[${t.phase}] ${a.error??`Unknown error`}`));break;default:break}};function $e(t,n){switch(t.type){case`text`:n(null),process.stdout.write(t.content??``);break;case`tool_call`:{let e=t.toolName??`unknown tool`;n((0,v.default)(i.default.cyan(`Tool: ${e}`)).start());break}case`tool_result`:n(null);break;case`tool_progress`:{let e=t.progress?.operation||t.toolName||`Working...`;n((0,v.default)(i.default.cyan(`Tool: ${e}`)).start());break}case`tool_error`:n(null),e.w.error(i.default.red(`\nTool error (${t.toolName}): ${t.error??`Unknown error`}`));break;case`error`:n(null),e.w.error(i.default.red(`\n${t.error??`Unknown error`}`));break;case`done`:n(null);break;default:process.env.VERBOSE&&console.warn(`[AgentRun] Unknown message type:`,t.type);break}}const et=e=>{let t=e.trim();return t===`~`?(0,c.homedir)():t.startsWith(`~/`)?(0,l.join)((0,c.homedir)(),t.slice(2)):t},tt=(e,t,n)=>e?`global`:t?`local`:n?null:`global`,nt=(e,t)=>e?.trim()||(t?null:process.cwd()),rt=e=>e.existingConfig?`overwrite`:it(e),it=e=>e.mode===`local`&&e.alreadyAuthed?`work`:`auth`,at=(e,t)=>{switch(e){case`mode`:return t.mode===`local`?t.hasGit?`repo-confirm`:`path-input`:rt(t);case`repo-confirm`:return t.repoAccepted?rt(t):`path-input`;case`path-input`:return rt(t);case`overwrite`:return it(t);case`auth`:return`work`;default:return`done`}},ot=(e,t)=>(0,f.execFileSync)(`git`,[`-C`,e,...t],{encoding:`utf-8`,stdio:[`ignore`,`pipe`,`ignore`]}).trim(),st=e=>{try{let t=ot(e,[`rev-parse`,`--show-toplevel`]);if(!t)return null;let n;try{n=ot(e,[`remote`,`get-url`,`origin`])||void 0}catch{}return{root:t,remoteUrl:n}}catch{return null}},ct=`connector-guide.md`,lt=`<!-- BEGIN stackone-connector-guide -->`,ut=`<!-- END stackone-connector-guide -->`,dt=`.stackone-connector-env.json`,ft=/^[a-z0-9][a-z0-9_-]*$/,pt=e=>e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`),mt=e=>`<!-- Generated by \`stackone agent sync\` from @stackone/agent-harness@${e}. Edit upstream, not here. -->`,ht=e=>{if(e.includes(`..`)||!ft.test(e))throw Error(`Refusing unsafe path segment: ${JSON.stringify(e)}`)},gt=e=>{let t=e.split(`/`);if(t.length===0)throw Error(`Refusing empty path: ${JSON.stringify(e)}`);for(let e of t)ht(e)},Q=(e,...t)=>{let n=(0,l.resolve)(e),r=(0,l.resolve)(n,...t);if(r!==n&&!r.startsWith(n+l.sep))throw Error(`Refusing path outside ${n}: ${r}`);return r},_t=(e,...t)=>(0,s.readFileSync)(Q(e,...t),`utf-8`),vt=(e,...t)=>(0,s.readFileSync)(Q(e,...t)),yt=`@stackone/agent-harness`,bt=()=>{let e=(0,g.createRequire)(require(`url`).pathToFileURL(__filename).href).resolve(`@stackone/agent-harness`),t=(0,l.dirname)(e);for(let e=0;e<6;e++){if((0,s.existsSync)((0,l.join)(t,`package.json`))&&(0,s.existsSync)((0,l.join)(t,`plugin`)))return t;let e=(0,l.dirname)(t);if(e===t)break;t=e}return(0,l.dirname)((0,l.dirname)(e))},xt=()=>(0,l.join)(bt(),`plugin`),St=e=>{try{let t=e?(0,l.resolve)(e,`..`):bt();return JSON.parse(_t(t,`package.json`)).version??`unknown`}catch{return`unknown`}},Ct=e=>{let t=e.charCodeAt(0)===65279?e.slice(1):e,n=t.match(/^---\n[\s\S]*?\n---\n?/);return n&&(t=t.slice(n[0].length)),t=t.replace(/^\s*<!--[\s\S]*?-->\s*/,``),t.trim()},wt=(e,t,n)=>{let r=[lt,mt(n),``,t,``,ut].join(`
142
+ `);if(e.includes(lt)&&e.includes(ut)){let t=RegExp(`${pt(lt)}[\\s\\S]*?${pt(ut)}`);return e.replace(t,r)}let i=e.replace(/\s*$/,``);return i.length>0?`${i}\n\n${r}\n`:`${r}\n`},Tt=e=>{let t=[];for(let n of(0,s.readdirSync)(e,{withFileTypes:!0}))if(n.isDirectory()){let r=Tt(Q(e,n.name));t.push(...r.map(e=>(0,l.join)(n.name,e)))}else t.push(n.name);return t},Et=(e,t)=>{if(!(0,s.existsSync)(t))return!1;let n=Tt(e).sort(),r=Tt(t).sort();return n.length!==r.length||n.some((e,t)=>e!==r[t])?!1:n.every(n=>vt(e,n).equals(vt(t,n)))},Dt=(e,t)=>{(0,s.rmSync)(t,{recursive:!0,force:!0}),(0,s.mkdirSync)((0,l.dirname)(t),{recursive:!0}),(0,s.cpSync)(e,t,{recursive:!0})},Ot=(e,t=``)=>{if(!(0,s.existsSync)(e))return[];let n=[];for(let r of(0,s.readdirSync)(e,{withFileTypes:!0})){if(!r.isDirectory()||!ft.test(r.name))continue;let i=t?`${t}/${r.name}`:r.name;if((0,s.existsSync)(Q(e,r.name,`SKILL.md`))){n.push(i);continue}n.push(...Ot(Q(e,r.name),i))}return n.sort()},kt=()=>({changed:[],unchanged:[],missing:[]}),At=(e,t,n,r)=>{let i=kt();for(let a of e){gt(a);let e=Q(t,a);if(!(0,s.existsSync)(e)||!(0,s.statSync)(e).isDirectory()){i.missing.push(a);continue}let o=Q(n,a);if(Et(e,o)){i.unchanged.push(a);continue}i.changed.push(a),r||Dt(e,o)}return i},jt=(e,t,n,r)=>{if(!(0,s.existsSync)(Q(e,ct)))return`missing-source`;let i=Ct(_t(e,ct)),a=Q(t,`CLAUDE.md`),o=(0,s.existsSync)(a)?_t(t,`CLAUDE.md`):``,c=wt(o,i,n);return c===o?`unchanged`:(r||(0,s.writeFileSync)(a,c),`changed`)},Mt=e=>{let t=(0,l.resolve)(e.pluginDir??xt()),n=(0,l.resolve)(e.cwd),r=e.version??St(t),i=e.check??!1,a=Q(n,`.claude`),o=Q(t,`skills`),c=At(Ot(o),o,Q(a,`skills`),i),u=jt(t,n,r,i),d=c.changed.length>0||u===`changed`,f=u!==`missing-source`||c.changed.length+c.unchanged.length>0;if(!i&&f){(0,s.mkdirSync)(a,{recursive:!0});let e={harnessVersion:r,skills:c.changed.concat(c.unchanged).sort(),guide:u!==`missing-source`};(0,s.writeFileSync)(Q(a,`.stackone-connector-env.json`),`${JSON.stringify(e,null,2)}\n`)}return{skills:c,guide:u,hasChanges:d}},Nt=e=>{try{let t=e??xt();return(0,s.statSync)(t).isDirectory()?e?JSON.parse(_t((0,l.resolve)(t,`..`),`package.json`)).name===`@stackone/agent-harness`:!0:!1}catch{return!1}},Pt=`#00af66`,Ft=({message:e,choices:t,initialIndex:n=0,onSelect:r,onCancel:i})=>{let[a,o]=(0,d.useState)(()=>t.length?Math.min(Math.max(n,0),t.length-1):0);return(0,u.useInput)((e,n)=>{if(t.length===0){n.escape&&i?.();return}n.upArrow?o(e=>(e-1+t.length)%t.length):n.downArrow?o(e=>(e+1)%t.length):n.return?r(t[a].value):n.escape&&i?.()}),t.length===0?null:d.default.createElement(u.Box,{flexDirection:`column`,paddingY:1},d.default.createElement(u.Box,{borderStyle:`round`,borderColor:`cyan`,flexDirection:`column`,paddingX:2,paddingY:1},d.default.createElement(u.Text,{bold:!0},e),d.default.createElement(u.Box,{flexDirection:`column`,marginTop:1},t.map((e,t)=>d.default.createElement(u.Text,{key:e.value,color:t===a?`#00af66`:`white`},t===a?`❯ `:` `,e.label)))),d.default.createElement(u.Box,{marginTop:1},d.default.createElement(u.Text,{dimColor:!0},`↑↓ to navigate • Enter to select`)))},It=({message:e,initialValue:t=``,validate:n,onSubmit:r,onCancel:i})=>{let[a,o]=(0,d.useState)(t),[s,c]=(0,d.useState)(null);return(0,u.useInput)((e,t)=>{if(t.return){let e=n?n(a):!0;e===!0?r(a):c(e);return}if(t.escape){i?.();return}if(t.backspace||t.delete){o(e=>e.slice(0,-1)),c(null);return}e&&!t.ctrl&&!t.meta&&!t.tab&&!t.upArrow&&!t.downArrow&&(o(t=>t+e),c(null))}),d.default.createElement(u.Box,{flexDirection:`column`,paddingY:1},d.default.createElement(u.Text,{bold:!0},e),d.default.createElement(u.Box,{marginTop:1},d.default.createElement(u.Text,null,`> `),d.default.createElement(u.Text,null,a),d.default.createElement(u.Text,{inverse:!0},` `)),s&&d.default.createElement(u.Box,{marginTop:1},d.default.createElement(u.Text,{color:`red`},s)),d.default.createElement(u.Box,{marginTop:1},d.default.createElement(u.Text,{dimColor:!0},`Enter to submit • Esc to cancel`)))},Lt=e=>(0,s.existsSync)(`${e}/CLAUDE.md`)||(0,s.existsSync)(`${e}/.mcp.json`),Rt=e=>{try{return(0,s.statSync)(e).isDirectory()}catch{return!1}},zt=({initialMode:t,pathFlag:r,startDir:i,onExit:a})=>{let[o,c]=(0,d.useState)(`mode`),[f,m]=(0,d.useState)(null),[h,g]=(0,d.useState)(!1),[_,v]=(0,d.useState)([]),[y,b]=(0,d.useState)(``),[x,S]=(0,d.useState)(t),[C,w]=(0,d.useState)(``),[T,E]=(0,d.useState)(``),[ee,te]=(0,d.useState)(!1),[D,O]=(0,d.useState)(null),k=(0,d.useRef)(0),A=(0,d.useCallback)(e=>{k.current+=1;let t=k.current;v(n=>[...n,{...e,id:t}])},[]),M=(0,d.useCallback)(e=>{m(e)},[]),N=(0,d.useCallback)(async t=>{let n=(0,l.resolve)(et(t));if(!Rt(n)){M({status:`error`,message:(0,s.existsSync)(n)?`Target path is not a directory: ${n}`:`Target path does not exist: ${n}`});return}w(n);let r=Lt(n),i=e.l(await e.u());te(i),c(at(`path-input`,{mode:`local`,hasGit:!1,repoAccepted:!1,existingConfig:r,alreadyAuthed:i}))},[M]),P=(0,d.useCallback)(e=>{if(S(e),e===`local`){let e=r?.trim();if(e){N(e);return}let t=st(i);t&&(E(`Install the connector setup into this repo? ${t.remoteUrl?`${t.remoteUrl} (${t.root})`:t.root}`),w(t.root)),c(at(`mode`,{mode:`local`,hasGit:!!t,repoAccepted:!1,existingConfig:!1,alreadyAuthed:!1}));return}c(at(`mode`,{mode:`global`,hasGit:!1,repoAccepted:!1,existingConfig:Lt(i),alreadyAuthed:!1}))},[r,i,N]);(0,d.useEffect)(()=>{t&&P(t)},[]);let ne=(0,d.useCallback)(e=>{e?N(C):c(`path-input`)},[N,C]),re=(0,d.useCallback)(e=>{if(!e){M({status:`cancelled`});return}c(at(`overwrite`,{mode:x??`global`,hasGit:!1,repoAccepted:!1,existingConfig:!0,alreadyAuthed:ee}))},[x,ee,M]);return(0,d.useEffect)(()=>{if(o!==`auth`)return;let e=!1;return b(`Starting browser authentication…`),Ke(t=>{e||b(t)}).then(t=>{e||(O(t),A({icon:`✓`,text:t.email?`Authenticated as ${t.email}`:`Authenticated`,color:j.success}),c(`work`))}).catch(t=>{e||M({status:`error`,message:t instanceof Error?t.message:`Authentication failed`})}),()=>{e=!0}},[o,A,M]),(0,d.useEffect)(()=>{if(o!==`work`)return;let t=!1;return(async()=>{try{let r=D??await e.u();if(!r)throw Error(`Not authenticated — no API key found`);let a=await n.r(x===`local`?C:i,r.apiKey);if(a.migrated&&A({icon:`✓`,text:`Migrated ${a.actions.length} item(s) from a previous setup`,color:j.success}),x===`local`){b(`Creating .mcp.json…`),e.h(e.o(C),e.c(),r.apiKey),A({icon:`✓`,text:`Created .mcp.json`,color:j.success}),b(`Syncing connector-building skills + guide…`);let t=Mt({cwd:C});A({icon:`✓`,text:`Connector environment ready (${t.skills.changed.length+t.skills.unchanged.length} skills in .claude/, ${t.guide===`missing-source`?`guide unavailable in this version`:`guide in CLAUDE.md`})`,color:j.success})}else b(`Installing global MCP configuration…`),e.h(e.a(),e.s(),r.apiKey),A({icon:`✓`,text:`Installed to Claude (global)`,color:j.success});if(t)return;b(``),M({status:`done`})}catch(e){if(t)return;M({status:`error`,message:e instanceof Error?e.message:`Setup failed`})}})(),()=>{t=!0}},[o,D,x,C,i,A,M]),(0,d.useEffect)(()=>{if(!f)return;let e=setTimeout(()=>a(f),60);return()=>clearTimeout(e)},[f,a]),d.default.createElement(u.Box,{flexDirection:`column`,padding:1},h?d.default.createElement(le,{wordmark:!0}):d.default.createElement(de,{ready:!0,onComplete:()=>g(!0)}),_.length>0&&d.default.createElement(u.Box,{flexDirection:`column`,marginTop:1},_.map(e=>d.default.createElement(u.Text,{key:e.id,color:e.color},e.icon?`${e.icon} `:``,e.text))),d.default.createElement(u.Box,{marginTop:1},(()=>{if(f)return f.status===`error`?d.default.createElement(u.Text,{color:j.error},`✗ `,f.message??`Setup failed`):f.status===`cancelled`?d.default.createElement(u.Text,{color:j.dim},`Setup cancelled.`):d.default.createElement(u.Box,{flexDirection:`column`},d.default.createElement(u.Text,{color:j.success},`✓ Setup complete!`),d.default.createElement(u.Box,{marginTop:1,flexDirection:`column`},d.default.createElement(u.Text,{color:j.dim},`Verify with `,d.default.createElement(u.Text,{color:j.primary},`claude mcp list`)),d.default.createElement(u.Text,{color:j.dim},`Tip: run`,` `,d.default.createElement(u.Text,{color:j.primary},`claude --dangerously-skip-permissions`),` `,`to skip permission prompts`),x===`local`&&d.default.createElement(u.Text,{color:j.dim},`Refresh skills anytime with`,` `,d.default.createElement(u.Text,{color:j.primary},`stackone agent sync`))));switch(o){case`mode`:return t?null:d.default.createElement(Ft,{message:`How do you want to set up the StackOne agent?`,initialIndex:0,choices:[{label:`Local — this project: auth + .mcp.json + connector skills (.claude/) + guide (CLAUDE.md)`,value:`local`},{label:`Global — any repo: auth + global MCP only (no connector skills/guide)`,value:`global`}],onSelect:e=>P(e),onCancel:()=>M({status:`cancelled`})});case`repo-confirm`:return d.default.createElement(Ft,{message:T,initialIndex:0,choices:[{label:`Yes`,value:`yes`},{label:`No, let me choose a path`,value:`no`}],onSelect:e=>ne(e===`yes`),onCancel:()=>M({status:`cancelled`})});case`path-input`:return d.default.createElement(It,{message:`Path to install the connector setup into:`,initialValue:i,validate:e=>{let t=et(e)||i;return(0,s.existsSync)(t)?Rt(t)?!0:`Path is not a directory: ${t}`:`Path does not exist: ${t}`},onSubmit:e=>void N(e.trim()||i),onCancel:()=>M({status:`cancelled`})});case`overwrite`:{let e=x===`local`;return d.default.createElement(Ft,{message:e?`Existing setup found in ${C}. Overwrite it?`:`Local setup detected in ${i} (it won't be modified). Set up the agent globally anyway?`,initialIndex:e?1:0,choices:[{label:e?`Yes, overwrite`:`Yes, set up globally`,value:`yes`},{label:`No, cancel`,value:`no`}],onSelect:e=>re(e===`yes`),onCancel:()=>M({status:`cancelled`})})}case`auth`:case`work`:return d.default.createElement(u.Text,null,d.default.createElement(u.Text,{color:j.primary},d.default.createElement(p.default,{type:`dots`})),` `,y);default:return null}})()))},Bt=e=>new Promise(t=>{let{unmount:n}=(0,u.render)(e(e=>{n(),t(e)}))}),Vt=()=>Bt(e=>d.default.createElement(Ft,{message:`How do you want to set up the StackOne agent?`,initialIndex:0,choices:[{label:`Local — this project: auth + .mcp.json + connector skills (.claude/) + guide (CLAUDE.md)`,value:`local`},{label:`Global — any repo: auth + global MCP only (no connector skills/guide)`,value:`global`}],onSelect:t=>e(t)})),Ht=(e,t=!0)=>Bt(n=>d.default.createElement(Ft,{message:e,initialIndex:t?0:1,choices:[{label:`Yes`,value:`yes`},{label:`No`,value:`no`}],onSelect:e=>n(e===`yes`),onCancel:()=>n(!1)})),Ut=async e=>{let t=st(e);return t&&await Ht(`Install the connector setup into this repo? ${t.remoteUrl?`${t.remoteUrl} (${t.root})`:t.root}`,!0)?t.root:Bt(n=>d.default.createElement(It,{message:t?`Path to install into:`:`Current directory is not a git repo. Path to install into:`,initialValue:e,validate:t=>{let n=et(t)||e;return(0,s.existsSync)(n)?!0:`Path does not exist: ${n}`},onSubmit:t=>n(et(t)||e)}))},Wt=e=>new Promise(t=>{let{unmount:n}=(0,u.render)(d.default.createElement(zt,{initialMode:e.initialMode,pathFlag:e.pathFlag,startDir:e.startDir??process.cwd(),onExit:e=>{n(),t(e)}}))});var Gt=class{async execute(t){e.w.log(i.default.blue.bold(`🤖 StackOne Agent Setup - Local Project
143
143
  `));try{let r=(0,l.resolve)(et(t?.targetPath??process.cwd()));await(0,y.access)(r).then(()=>!0).catch(()=>!1)||(e.w.error(`Target path does not exist: ${r}`),process.exit(1)),t?.targetPath&&e.w.log(i.default.dim(`Installing into ${r}\n`));let a=await(0,y.access)(`${r}/CLAUDE.md`).then(()=>!0).catch(()=>!1),o=await(0,y.access)(`${r}/.mcp.json`).then(()=>!0).catch(()=>!1);if(a||o){e.w.warn(`Existing local setup detected:`),a&&e.w.log(i.default.dim(` • CLAUDE.md found`)),o&&e.w.log(i.default.dim(` • .mcp.json found`)),e.w.log(``);let n=Y(!!t?.legacy,t?.credentials),r=!!process.stdin.isTTY;n||!r?e.w.log(i.default.dim(n?`Non-interactive credentials detected; proceeding without confirmation.
144
144
  `:`No interactive terminal detected; proceeding without overwrite confirmation.
145
- `)):(await Vt(`Overwrite existing local configuration?`,!1)||(e.w.log(i.default.dim(`
145
+ `)):(await Ht(`Overwrite existing local configuration?`,!1)||(e.w.log(i.default.dim(`
146
146
  Setup cancelled.`)),process.exit(0)),e.w.log(``))}let s=await e.u();(!s||!e.l(s))&&(e.w.warn(`Not authenticated globally.`),e.w.log(i.default.white(`Let's authenticate now...
147
147
  `)),s=await qe(!!t?.legacy,t?.credentials),e.w.log(``)),n.t(await n.r(r,s.apiKey));let c=(0,v.default)(`Creating .mcp.json...`).start();try{e.h(e.o(r),e.c(),s.apiKey),c.succeed(`Created .mcp.json`),e.w.success(`Local setup complete!`),e.w.log(i.default.white(`Files created:`)),e.w.log(i.default.cyan(` • .mcp.json`)),e.w.log(i.default.dim(`Token stored securely in Claude MCP server config.`)),e.w.log(i.default.dim(`
148
148
  💡 The stackone-agent-local MCP server is now available in this project`)),e.w.log(i.default.dim(`
149
149
  💡 Tip: Run Claude without permission prompts:`),i.default.cyan(`claude --dangerously-skip-permissions`)),e.w.log(i.default.blue(`
150
- Verify:`),i.default.cyan(`claude mcp list`)),e.w.log(``)}catch(t){c.fail(`Failed to create .mcp.json`),t instanceof Error&&e.w.error(t.message)}let u=(0,v.default)(`Syncing connector-building skills + guide...`).start();try{let t=jt({cwd:r}),n=t.skills.changed.length+t.skills.unchanged.length,a=t.guide===`missing-source`?`unavailable in this version`:`in CLAUDE.md`;u.succeed(`Connector-building environment ready (${n} skills in .claude/, guide ${a})`),e.w.log(i.default.dim(` Refresh anytime with`),i.default.cyan(`stackone agent sync`))}catch(t){u.fail(`Failed to sync connector-building environment`),t instanceof Error&&e.w.error(t.message)}process.exit(0)}catch(t){t instanceof Error?e.w.error(t.message):e.w.error(`Unknown error occurred`),process.exit(1)}}},Gt=class{async execute(t){let n=(0,o.getAvailableSkillNames)(),r=t?.mode;if(e.w.log(i.default.bold(`
150
+ Verify:`),i.default.cyan(`claude mcp list`)),e.w.log(``)}catch(t){c.fail(`Failed to create .mcp.json`),t instanceof Error&&e.w.error(t.message)}let u=(0,v.default)(`Syncing connector-building skills + guide...`).start();try{let t=Mt({cwd:r}),n=t.skills.changed.length+t.skills.unchanged.length,a=t.guide===`missing-source`?`unavailable in this version`:`in CLAUDE.md`;u.succeed(`Connector-building environment ready (${n} skills in .claude/, guide ${a})`),e.w.log(i.default.dim(` Refresh anytime with`),i.default.cyan(`stackone agent sync`))}catch(t){u.fail(`Failed to sync connector-building environment`),t instanceof Error&&e.w.error(t.message)}process.exit(0)}catch(t){t instanceof Error?e.w.error(t.message):e.w.error(`Unknown error occurred`),process.exit(1)}}},Kt=class{async execute(t){let n=(0,o.getAvailableSkillNames)(),r=t?.mode;if(e.w.log(i.default.bold(`
151
151
  Available skills
152
152
  `)),n.length===0){e.w.log(i.default.dim(` No bundled skills found.
153
- `));return}for(let t of n)e.w.log(` • ${t}`);if(r){let t=(0,o.getSkillsForMode)(r);if(t.length>0){e.w.log(i.default.bold(`\nRecommended for mode "${r}":\n`));for(let r of t){let t=n.includes(r);e.w.log(` • ${r}${t?``:i.default.dim(` (not found)`)}`)}}}e.w.log(``)}};const Kt=(t,n,r)=>{let a=r?`stale`:`synced`;n.changed.length>0&&e.w.log(i.default.cyan(` • ${t} ${a}: ${n.changed.join(`, `)}`)),n.missing.length>0&&e.w.log(i.default.dim(` • ${t} not in this harness version: ${n.missing.join(`, `)}`))},qt=(t,n)=>{t===`missing-source`?e.w.log(i.default.dim(` • connector-guide.md not in this harness version — skipped CLAUDE.md`)):t===`changed`&&e.w.log(i.default.cyan(` • CLAUDE.md guide block ${n?`stale`:`updated`}`))};var Jt=class{async execute(t){let n=!!t?.check,r=t?.pluginDir;Mt(r)||(e.w.error(r?`--plugin-dir is not a valid @stackone/agent-harness plugin dir: ${r}`:`Could not locate the bundled @stackone/agent-harness plugin. Reinstall the CLI and try again.`),process.exit(1));let a=xt(r);e.w.log(i.default.blue.bold(`🧩 ${n?`Checking`:`Syncing`} connector-building environment`)+i.default.dim(` (agent-harness@${a}${r?` [--plugin-dir]`:``})\n`));try{let t=jt({cwd:process.cwd(),check:n,pluginDir:r});Kt(`skills`,t.skills,n),qt(t.guide,n),n&&(t.hasChanges&&(e.w.log(``),e.w.error("Connector-building environment is out of date. Run `stackone agent sync` to update."),process.exit(1)),e.w.success(`Connector-building environment is up to date.`),process.exit(0)),t.hasChanges?(e.w.success(`Connector-building environment synced into .claude/ and CLAUDE.md.`),e.w.log(i.default.dim(`
154
- 💡 Skills and the connector guide are managed by the CLI — `),i.default.dim("re-run `stackone agent sync` after a CLI update."))):e.w.success(`Already up to date — nothing to sync.`),process.exit(0)}catch(t){e.w.error(t instanceof Error?t.message:`Unknown error during sync`),process.exit(1)}}};const Yt={profiles:{}},Xt=()=>{let n=e._.readConfigFile(t.n);if(!n)return Yt;try{return JSON.parse(n)}catch{return Yt}},Zt=e=>Xt().profiles[e],Qt=e=>!!Xt().profiles[e],$t=(n,r)=>{let i=Xt();i.profiles[n]=r,e._.writeConfigFile(t.n,JSON.stringify(i,null,2))},en=()=>{let e=Xt();return Object.keys(e.profiles)},tn=`https://api.stackone.com`;var nn=class{async execute({profile:t,connector:n,apiUrl:r,apiKey:a}={}){if(!t&&!a&&(e.w.error(`Profile or API key is required`),e.w.log(`Please provide a profile using the ${e.C(`--profile`)} option or an API key using the ${e.C(`--api-key`)} option.`),e.w.log(`To create a profile, run ${e.C(`stackone init`)}.`),process.exit(1)),t&&a&&(e.w.error(`Please provide either a profile or an API key, not both`),process.exit(1)),t&&r&&e.w.warn(`Specifying ${e.C(`--api-url`)} with a profile won't have any effect. Using API url from profile.`),t&&!Qt(t)){e.w.error(`Configuration profile ${e.C(t)} not found`),e.w.log(`Run ${e.C(`stackone init`)} to create a new configuration profile.\n`);let n=en();n.length>0&&(e.w.info(`Available configuration profiles:`),n.forEach(t=>{e.w.log(` - ${i.default.blue(t)}`)})),process.exit(1)}let o=t?Zt(t):{apiUrl:r??tn,apiKey:a};o?.apiKey||(e.w.error(`API key is missing`),e.w.log(`Please provide a valid API key in the profile or via the ${e.C(`--api-key`)} option.`),process.exit(1)),n||(e.w.error(`Connector identifier is required in the format provider_key@version.`),process.exit(1));let s=n.split(`@`);(s.length!==2||!s[0]||!s[1])&&(e.w.error(`Invalid connector format ${e.S(n)}. Expected format: ${e.C(`provider_key@version`)}`),process.exit(1));let c=o.apiUrl??tn,l=await this.dropConnector(n,c,o.apiKey);process.exit(l?0:1)}async dropConnector(t,n,r){let i=(0,v.default)(`🗑️ Dropping connector ${e.C(t)}...`).start();try{let a=Buffer.from(r).toString(`base64`),o=await fetch(`${n}/registry/connectors/${t}`,{method:`DELETE`,headers:{Authorization:`Basic ${a}`}});return i.stop(),o.status===204?(e.w.success(`Successfully dropped connector ${e.C(t)} from the registry`),!0):o.status===404?(e.w.error(`Connector ${e.C(t)} not found in the registry`),!1):o.status===401||o.status===403?(e.w.error(`You do not have permission to drop this connector`),!1):o.status===409?(e.w.error(`Connector ${e.C(t)} has associated configs and cannot be dropped`),e.w.log(`Please delete all associated integration configurations before dropping the connector.`),!1):(o.ok||await e.x(o,`Failed to drop connector ${e.C(t)} from the registry`),!1)}catch(r){return i.stop(),e.w.error(`Failed to drop connector ${e.C(t)} from registry: ${r.message}`),e.w.log(`Please ensure that the API at ${e.T(n)} is reachable and the API key is valid`),!1}}};const rn=`stackone`;async function an(t,n){n.length===0&&(e.w.error(`Multiple versions of connector ${e.C(t)} were found but no owner information was returned`),process.exit(1));let r=n.map(e=>({value:e,label:e===rn?`StackOne`:`Custom`,hint:e===rn?`Official StackOne connector`:`Custom connector version created by your organization`}));e.w.warn(`Multiple versions of connector ${e.C(t)} were found. Please select which version to use.`);let i=await(0,w.select)({message:`Which version would you like to use?`,options:r});return(0,w.isCancel)(i)&&(e.w.error(`Operation cancelled.`),process.exit(1)),i}const on=`https://api.stackone.com`;var sn=class{async execute({profile:t,connector:n,accountId:r,format:a,outputFile:o,apiUrl:s,apiKey:c,owner:l}={}){if(!t&&!c&&(e.w.error(`Profile or API key is required`),e.w.log(`Please provide a profile using the ${e.C(`--profile`)} option or an API key using the ${e.C(`--api-key`)} option.`),e.w.log(`To create a profile, run ${e.C(`stackone init`)}.`),process.exit(1)),t&&c&&(e.w.error(`Please provide either a profile or an API key, not both`),process.exit(1)),t&&s&&e.w.warn(`Specifying ${e.C(`--api-url`)} with a profile won't have any effect. Using API url from profile.`),t&&!Qt(t)){e.w.error(`Configuration profile ${e.C(t)} not found`),e.w.log(`Run ${e.C(`stackone init`)} to create a new configuration profile.\n`);let n=en();n.length>0&&(e.w.info(`Available configuration profiles:`),n.forEach(t=>{e.w.log(` - ${i.default.blue(t)}`)})),process.exit(1)}let u=t?Zt(t):{apiUrl:s??on,apiKey:c};u?.apiKey||(e.w.error(`API key is missing`),e.w.log(`Please provide a valid API key in the profile or via the ${e.C(`--api-key`)} option.`),process.exit(1)),(0,C.isMissing)(n)&&(0,C.isMissing)(r)&&(e.w.error(`Either ${e.C(`--connector`)} or ${e.C(`--account-id`)} must be provided`),process.exit(1)),(0,C.notMissing)(n)&&(0,C.notMissing)(r)&&(e.w.error(`Please provide either ${e.C(`--connector`)} or ${e.C(`--account-id`)}, not both.`),process.exit(1)),(0,C.notMissing)(a)&&a!==`yaml`&&a!==`json`&&(e.w.error(`Format must be either ${e.C(`yaml`)} or ${e.C(`json`)}.`),process.exit(1));let d=u.apiUrl??on,f;if((0,C.notMissing)(n)){this.#t(n)||(e.w.error(`Invalid connector format ${e.S(n)}. Expected format: ${e.C(`provider_key@version`)} or ${e.C(`provider_key`)}`),process.exit(1));let t=this.#n(n);f=await this.#r(t,d,u.apiKey,a,l)}else (0,C.notMissing)(r)?f=await this.#i(r,d,u.apiKey,a):(e.w.error(`Either ${e.C(`--connector`)} or ${e.C(`--account-id`)} must be provided`),process.exit(1));if((0,C.notMissing)(o))try{m.default.writeFileSync(o,f,`utf-8`),e.w.success(`Connector written to file: ${e.C(o)}`)}catch(t){e.w.error(`Failed to write connector to file ${e.C(o)}: ${t.message}`),process.exit(1)}else if(e.w.log(`\n${i.default.blue.inverse(` CONNECTOR CONTENT `)}\n`),!a||a===`yaml`)e.w.log(this.#e(f));else if(a===`json`)try{e.b(JSON.parse(f))}catch{e.w.log(f)}else e.w.log(f);process.exit(0)}#e(e){return e.split(`
153
+ `));return}for(let t of n)e.w.log(` • ${t}`);if(r){let t=(0,o.getSkillsForMode)(r);if(t.length>0){e.w.log(i.default.bold(`\nRecommended for mode "${r}":\n`));for(let r of t){let t=n.includes(r);e.w.log(` • ${r}${t?``:i.default.dim(` (not found)`)}`)}}}e.w.log(``)}};const qt=(t,n,r)=>{let a=r?`stale`:`synced`;n.changed.length>0&&e.w.log(i.default.cyan(` • ${t} ${a}: ${n.changed.join(`, `)}`)),n.missing.length>0&&e.w.log(i.default.dim(` • ${t} not in this harness version: ${n.missing.join(`, `)}`))},Jt=(t,n)=>{t===`missing-source`?e.w.log(i.default.dim(` • connector-guide.md not in this harness version — skipped CLAUDE.md`)):t===`changed`&&e.w.log(i.default.cyan(` • CLAUDE.md guide block ${n?`stale`:`updated`}`))};var Yt=class{async execute(t){let n=!!t?.check,r=t?.pluginDir;Nt(r)||(e.w.error(r?`--plugin-dir is not a valid @stackone/agent-harness plugin dir: ${r}`:`Could not locate the bundled @stackone/agent-harness plugin. Reinstall the CLI and try again.`),process.exit(1));let a=St(r);e.w.log(i.default.blue.bold(`🧩 ${n?`Checking`:`Syncing`} connector-building environment`)+i.default.dim(` (agent-harness@${a}${r?` [--plugin-dir]`:``})\n`));try{let t=Mt({cwd:process.cwd(),check:n,pluginDir:r});qt(`skills`,t.skills,n),Jt(t.guide,n),n&&(t.hasChanges&&(e.w.log(``),e.w.error("Connector-building environment is out of date. Run `stackone agent sync` to update."),process.exit(1)),e.w.success(`Connector-building environment is up to date.`),process.exit(0)),t.hasChanges?(e.w.success(`Connector-building environment synced into .claude/ and CLAUDE.md.`),e.w.log(i.default.dim(`
154
+ 💡 Skills and the connector guide are managed by the CLI — `),i.default.dim("re-run `stackone agent sync` after a CLI update."))):e.w.success(`Already up to date — nothing to sync.`),process.exit(0)}catch(t){e.w.error(t instanceof Error?t.message:`Unknown error during sync`),process.exit(1)}}};const Xt={profiles:{}},Zt=()=>{let n=e._.readConfigFile(t.n);if(!n)return Xt;try{return JSON.parse(n)}catch{return Xt}},Qt=e=>Zt().profiles[e],$t=e=>!!Zt().profiles[e],en=(n,r)=>{let i=Zt();i.profiles[n]=r,e._.writeConfigFile(t.n,JSON.stringify(i,null,2))},tn=()=>{let e=Zt();return Object.keys(e.profiles)},nn=`https://api.stackone.com`;var rn=class{async execute({profile:t,connector:n,apiUrl:r,apiKey:a}={}){if(!t&&!a&&(e.w.error(`Profile or API key is required`),e.w.log(`Please provide a profile using the ${e.C(`--profile`)} option or an API key using the ${e.C(`--api-key`)} option.`),e.w.log(`To create a profile, run ${e.C(`stackone init`)}.`),process.exit(1)),t&&a&&(e.w.error(`Please provide either a profile or an API key, not both`),process.exit(1)),t&&r&&e.w.warn(`Specifying ${e.C(`--api-url`)} with a profile won't have any effect. Using API url from profile.`),t&&!$t(t)){e.w.error(`Configuration profile ${e.C(t)} not found`),e.w.log(`Run ${e.C(`stackone init`)} to create a new configuration profile.\n`);let n=tn();n.length>0&&(e.w.info(`Available configuration profiles:`),n.forEach(t=>{e.w.log(` - ${i.default.blue(t)}`)})),process.exit(1)}let o=t?Qt(t):{apiUrl:r??nn,apiKey:a};o?.apiKey||(e.w.error(`API key is missing`),e.w.log(`Please provide a valid API key in the profile or via the ${e.C(`--api-key`)} option.`),process.exit(1)),n||(e.w.error(`Connector identifier is required in the format provider_key@version.`),process.exit(1));let s=n.split(`@`);(s.length!==2||!s[0]||!s[1])&&(e.w.error(`Invalid connector format ${e.S(n)}. Expected format: ${e.C(`provider_key@version`)}`),process.exit(1));let c=o.apiUrl??nn,l=await this.dropConnector(n,c,o.apiKey);process.exit(l?0:1)}async dropConnector(t,n,r){let i=(0,v.default)(`🗑️ Dropping connector ${e.C(t)}...`).start();try{let a=Buffer.from(r).toString(`base64`),o=await fetch(`${n}/registry/connectors/${t}`,{method:`DELETE`,headers:{Authorization:`Basic ${a}`}});return i.stop(),o.status===204?(e.w.success(`Successfully dropped connector ${e.C(t)} from the registry`),!0):o.status===404?(e.w.error(`Connector ${e.C(t)} not found in the registry`),!1):o.status===401||o.status===403?(e.w.error(`You do not have permission to drop this connector`),!1):o.status===409?(e.w.error(`Connector ${e.C(t)} has associated configs and cannot be dropped`),e.w.log(`Please delete all associated integration configurations before dropping the connector.`),!1):(o.ok||await e.x(o,`Failed to drop connector ${e.C(t)} from the registry`),!1)}catch(r){return i.stop(),e.w.error(`Failed to drop connector ${e.C(t)} from registry: ${r.message}`),e.w.log(`Please ensure that the API at ${e.T(n)} is reachable and the API key is valid`),!1}}};const an=`stackone`;async function on(t,n){n.length===0&&(e.w.error(`Multiple versions of connector ${e.C(t)} were found but no owner information was returned`),process.exit(1));let r=n.map(e=>({value:e,label:e===an?`StackOne`:`Custom`,hint:e===an?`Official StackOne connector`:`Custom connector version created by your organization`}));e.w.warn(`Multiple versions of connector ${e.C(t)} were found. Please select which version to use.`);let i=await(0,w.select)({message:`Which version would you like to use?`,options:r});return(0,w.isCancel)(i)&&(e.w.error(`Operation cancelled.`),process.exit(1)),i}const sn=`https://api.stackone.com`;var cn=class{async execute({profile:t,connector:n,accountId:r,format:a,outputFile:o,apiUrl:s,apiKey:c,owner:l}={}){if(!t&&!c&&(e.w.error(`Profile or API key is required`),e.w.log(`Please provide a profile using the ${e.C(`--profile`)} option or an API key using the ${e.C(`--api-key`)} option.`),e.w.log(`To create a profile, run ${e.C(`stackone init`)}.`),process.exit(1)),t&&c&&(e.w.error(`Please provide either a profile or an API key, not both`),process.exit(1)),t&&s&&e.w.warn(`Specifying ${e.C(`--api-url`)} with a profile won't have any effect. Using API url from profile.`),t&&!$t(t)){e.w.error(`Configuration profile ${e.C(t)} not found`),e.w.log(`Run ${e.C(`stackone init`)} to create a new configuration profile.\n`);let n=tn();n.length>0&&(e.w.info(`Available configuration profiles:`),n.forEach(t=>{e.w.log(` - ${i.default.blue(t)}`)})),process.exit(1)}let u=t?Qt(t):{apiUrl:s??sn,apiKey:c};u?.apiKey||(e.w.error(`API key is missing`),e.w.log(`Please provide a valid API key in the profile or via the ${e.C(`--api-key`)} option.`),process.exit(1)),(0,C.isMissing)(n)&&(0,C.isMissing)(r)&&(e.w.error(`Either ${e.C(`--connector`)} or ${e.C(`--account-id`)} must be provided`),process.exit(1)),(0,C.notMissing)(n)&&(0,C.notMissing)(r)&&(e.w.error(`Please provide either ${e.C(`--connector`)} or ${e.C(`--account-id`)}, not both.`),process.exit(1)),(0,C.notMissing)(a)&&a!==`yaml`&&a!==`json`&&(e.w.error(`Format must be either ${e.C(`yaml`)} or ${e.C(`json`)}.`),process.exit(1));let d=u.apiUrl??sn,f;if((0,C.notMissing)(n)){this.#t(n)||(e.w.error(`Invalid connector format ${e.S(n)}. Expected format: ${e.C(`provider_key@version`)} or ${e.C(`provider_key`)}`),process.exit(1));let t=this.#n(n);f=await this.#r(t,d,u.apiKey,a,l)}else (0,C.notMissing)(r)?f=await this.#i(r,d,u.apiKey,a):(e.w.error(`Either ${e.C(`--connector`)} or ${e.C(`--account-id`)} must be provided`),process.exit(1));if((0,C.notMissing)(o))try{m.default.writeFileSync(o,f,`utf-8`),e.w.success(`Connector written to file: ${e.C(o)}`)}catch(t){e.w.error(`Failed to write connector to file ${e.C(o)}: ${t.message}`),process.exit(1)}else if(e.w.log(`\n${i.default.blue.inverse(` CONNECTOR CONTENT `)}\n`),!a||a===`yaml`)e.w.log(this.#e(f));else if(a===`json`)try{e.b(JSON.parse(f))}catch{e.w.log(f)}else e.w.log(f);process.exit(0)}#e(e){return e.split(`
155
155
  `).map(e=>{if(e.trim().startsWith(`#`))return i.default.gray(e);if(e.includes(`:`)){let t=e.indexOf(`:`),n=e.substring(0,t+1),r=e.substring(t+1),a=r,o=r.trim();return o===`true`||o===`false`?a=r.replace(o,i.default.cyan(o)):o===`null`||o===`~`?a=r.replace(o,i.default.gray(o)):/^-?\d+(\.\d+)?$/.test(o)?a=r.replace(o,i.default.green(o)):(o.startsWith(`"`)&&o.endsWith(`"`)||o.startsWith(`'`)&&o.endsWith(`'`)||o&&!o.startsWith(`-`))&&(a=r.replace(o,i.default.yellow(o))),i.default.red(n)+a}return e.trim().startsWith(`-`)?e.replace(`-`,i.default.gray(`-`)):e}).join(`
156
- `)}#t=e=>!e.includes(`/`)&&!e.includes(`\\`)&&!e.endsWith(`.yaml`)&&!e.endsWith(`.yml`)?e.includes(`@`)?e.split(`@`).length===2:!0:!1;#n=e=>e.includes(`@`)?e:`${e}@latest`;async#r(t,n,r,i,a){let o=(0,v.default)(`Getting connector ${e.C(t)} from registry...`).start();try{let s=Buffer.from(r).toString(`base64`),c=i?`?format=${i}`:``,l=a?`${c?`&`:`?`}owner=${encodeURIComponent(a)}`:``,u=await fetch(`${n}/registry/connectors/${t}${c}${l}`,{method:`GET`,headers:{Authorization:`Basic ${s}`}});if(o.stop(),u.status===409){a&&(await e.x(u,`Failed to get connector ${e.C(t)} from the registry`),process.exit(1));let r=await an(t,(await u.json()).availableOwners??[]),i=`${n}/registry/connectors/${t}${c}${c?`&`:`?`}owner=${encodeURIComponent(r)}`;o.text=`Getting connector ${e.C(t)} from registry...`,o.start();let l=await fetch(i,{method:`GET`,headers:{Authorization:`Basic ${s}`}});return o.stop(),l.ok||(await e.x(l,`Failed to get connector ${e.C(t)} from the registry`),process.exit(1)),await l.text()}return u.ok||(await e.x(u,`Failed to get connector ${e.C(t)} from the registry`),process.exit(1)),await u.text()}catch(r){o.stop(),e.w.error(`Failed to get connector ${e.C(t)} from the registry: ${r.message}`),e.w.log(`Please ensure that the API at ${e.T(n)} is reachable and the API key is valid`),process.exit(1)}}async#i(t,n,r,i){let a=(0,v.default)(`Getting connector from account ${e.C(t)}...`).start();try{let o=Buffer.from(r).toString(`base64`),s=i?`?format=${i}`:``,c=await fetch(`${n}/accounts/${t}/connector${s}`,{method:`GET`,headers:{Authorization:`Basic ${o}`}});return a.stop(),c.ok||(await e.x(c,`Failed to get connector from account ${e.C(t)}`),process.exit(1)),await c.text()}catch(r){a.stop(),e.w.error(`Failed to get connector from account ${e.C(t)}: ${r.message}`),e.w.log(`Please ensure that the API at ${e.T(n)} is reachable and the API key is valid`),process.exit(1)}}};const cn=`https://api.stackone.com`,ln=`https://api.stackone-dev.com`,un=`http://localhost:4000`;var dn=class{async execute({environment:t}={}){let n=t?.toLowerCase()??`production`;try{(0,w.intro)(`${i.default.inverse(` Initialize profile `)}`);let t=await(0,w.text)({message:`Profile label`,validate:e=>{if(!e||e.trim().length===0)return`The profile label is required`;if(e.includes(` `))return`The profile label cannot contain spaces`}});if((0,w.isCancel)(t))return(0,w.cancel)(`Configuration profile initialization cancelled`),process.exit(0);if(Qt(t)){let n=await(0,w.confirm)({message:`Configuration profile with name ${e.C(t)} already exists. Do you want to overwrite it?`});if((0,w.isCancel)(n)||!n)return(0,w.cancel)(`Configuration profile initialization cancelled`),process.exit(0)}let r;if(n===`production`)r=`https://api.stackone.com`;else if(n===`staging`)r=`https://api.stackone-dev.com`;else{let e=await(0,w.text)({message:`API URL`,placeholder:un,initialValue:un,validate:e=>{if(!e||e.trim().length===0)return`API URL is required`;try{new URL(e)}catch{return`Please enter a valid URL`}}});if((0,w.isCancel)(e))return(0,w.cancel)(`Configuration profile initialization cancelled`),process.exit(0);r=e}let a=await(0,w.password)({message:`API Key`,validate:e=>{if(!e||e.trim().length===0)return`API Key is required`}});if((0,w.isCancel)(a))return(0,w.cancel)(`Configuration profile initialization cancelled`),process.exit(0);$t(t,{label:t,environment:n,apiUrl:r,apiKey:a}),(0,w.outro)(`${i.default.green(`✔`)} Configuration profile ${e.C(t)} initialized successfully!`),process.exit(0)}catch(t){t?.isTtyError?e.w.error(`Prompt couldn't be rendered in the current environment`):e.w.error(`Failed to initialize configuration profile: ${t}`),process.exit(1)}}};const fn=20,$={pending:`○`,acceptRemote:`●`,acceptLocal:`◐`,acceptBoth:`◑`,current:`◉`,arrow:`→`,check:`✓`,cross:`✗`,warning:`⚠`};var pn=class{constructor(e,t,n,r){this.conflicts=[],this.currentIndex=0,this.totalConflicts=0,this.currentCleanup=null,this.connectorId=t,this.localVersion=n,this.remoteVersion=r,this.conflicts=e.map(e=>({conflict:e,choice:e.type===`unchanged`?`remote`:`pending`})),this.totalConflicts=e.filter(e=>e.type===`conflict`).length}resetForReResolution(){this.currentIndex=0}async resolve(){return this.totalConflicts===0?{cancelled:!1,states:this.conflicts}:(this.moveToNextConflict(),new Promise(e=>{let t=(0,ee.createInterface)({input:process.stdin,output:process.stdout});process.stdin.isTTY&&process.stdin.setRawMode(!0),process.stdin.resume(),this.render();let n=n=>{let r=n.toString();if(r===``){this.cleanup(t),this.renderCancelled(),e({cancelled:!0,states:this.conflicts});return}if(r===`\x1B`&&n.length===1){this.cleanup(t),this.renderCancelled(),e({cancelled:!0,states:this.conflicts});return}if(r.startsWith(`\x1B[`)){switch(r.slice(2)){case`D`:this.moveToPrevConflict(),this.render();break;case`C`:this.moveToNextConflict(),this.render();break}return}switch(r){case`r`:case`R`:this.setCurrentChoice(`remote`),this.advanceAfterChoice(t);break;case`l`:case`L`:this.setCurrentChoice(`local`),this.advanceAfterChoice(t);break;case`b`:case`B`:this.setCurrentChoice(`both`),this.advanceAfterChoice(t);break;case`\r`:case`
156
+ `)}#t=e=>!e.includes(`/`)&&!e.includes(`\\`)&&!e.endsWith(`.yaml`)&&!e.endsWith(`.yml`)?e.includes(`@`)?e.split(`@`).length===2:!0:!1;#n=e=>e.includes(`@`)?e:`${e}@latest`;async#r(t,n,r,i,a){let o=(0,v.default)(`Getting connector ${e.C(t)} from registry...`).start();try{let s=Buffer.from(r).toString(`base64`),c=i?`?format=${i}`:``,l=a?`${c?`&`:`?`}owner=${encodeURIComponent(a)}`:``,u=await fetch(`${n}/registry/connectors/${t}${c}${l}`,{method:`GET`,headers:{Authorization:`Basic ${s}`}});if(o.stop(),u.status===409){a&&(await e.x(u,`Failed to get connector ${e.C(t)} from the registry`),process.exit(1));let r=await on(t,(await u.json()).availableOwners??[]),i=`${n}/registry/connectors/${t}${c}${c?`&`:`?`}owner=${encodeURIComponent(r)}`;o.text=`Getting connector ${e.C(t)} from registry...`,o.start();let l=await fetch(i,{method:`GET`,headers:{Authorization:`Basic ${s}`}});return o.stop(),l.ok||(await e.x(l,`Failed to get connector ${e.C(t)} from the registry`),process.exit(1)),await l.text()}return u.ok||(await e.x(u,`Failed to get connector ${e.C(t)} from the registry`),process.exit(1)),await u.text()}catch(r){o.stop(),e.w.error(`Failed to get connector ${e.C(t)} from the registry: ${r.message}`),e.w.log(`Please ensure that the API at ${e.T(n)} is reachable and the API key is valid`),process.exit(1)}}async#i(t,n,r,i){let a=(0,v.default)(`Getting connector from account ${e.C(t)}...`).start();try{let o=Buffer.from(r).toString(`base64`),s=i?`?format=${i}`:``,c=await fetch(`${n}/accounts/${t}/connector${s}`,{method:`GET`,headers:{Authorization:`Basic ${o}`}});return a.stop(),c.ok||(await e.x(c,`Failed to get connector from account ${e.C(t)}`),process.exit(1)),await c.text()}catch(r){a.stop(),e.w.error(`Failed to get connector from account ${e.C(t)}: ${r.message}`),e.w.log(`Please ensure that the API at ${e.T(n)} is reachable and the API key is valid`),process.exit(1)}}};const ln=`https://api.stackone.com`,un=`https://api.stackone-dev.com`,dn=`http://localhost:4000`;var fn=class{async execute({environment:t}={}){let n=t?.toLowerCase()??`production`;try{(0,w.intro)(`${i.default.inverse(` Initialize profile `)}`);let t=await(0,w.text)({message:`Profile label`,validate:e=>{if(!e||e.trim().length===0)return`The profile label is required`;if(e.includes(` `))return`The profile label cannot contain spaces`}});if((0,w.isCancel)(t))return(0,w.cancel)(`Configuration profile initialization cancelled`),process.exit(0);if($t(t)){let n=await(0,w.confirm)({message:`Configuration profile with name ${e.C(t)} already exists. Do you want to overwrite it?`});if((0,w.isCancel)(n)||!n)return(0,w.cancel)(`Configuration profile initialization cancelled`),process.exit(0)}let r;if(n===`production`)r=`https://api.stackone.com`;else if(n===`staging`)r=`https://api.stackone-dev.com`;else{let e=await(0,w.text)({message:`API URL`,placeholder:dn,initialValue:dn,validate:e=>{if(!e||e.trim().length===0)return`API URL is required`;try{new URL(e)}catch{return`Please enter a valid URL`}}});if((0,w.isCancel)(e))return(0,w.cancel)(`Configuration profile initialization cancelled`),process.exit(0);r=e}let a=await(0,w.password)({message:`API Key`,validate:e=>{if(!e||e.trim().length===0)return`API Key is required`}});if((0,w.isCancel)(a))return(0,w.cancel)(`Configuration profile initialization cancelled`),process.exit(0);en(t,{label:t,environment:n,apiUrl:r,apiKey:a}),(0,w.outro)(`${i.default.green(`✔`)} Configuration profile ${e.C(t)} initialized successfully!`),process.exit(0)}catch(t){t?.isTtyError?e.w.error(`Prompt couldn't be rendered in the current environment`):e.w.error(`Failed to initialize configuration profile: ${t}`),process.exit(1)}}};const pn=20,$={pending:`○`,acceptRemote:`●`,acceptLocal:`◐`,acceptBoth:`◑`,current:`◉`,arrow:`→`,check:`✓`,cross:`✗`,warning:`⚠`};var mn=class{constructor(e,t,n,r){this.conflicts=[],this.currentIndex=0,this.totalConflicts=0,this.currentCleanup=null,this.connectorId=t,this.localVersion=n,this.remoteVersion=r,this.conflicts=e.map(e=>({conflict:e,choice:e.type===`unchanged`?`remote`:`pending`})),this.totalConflicts=e.filter(e=>e.type===`conflict`).length}resetForReResolution(){this.currentIndex=0}async resolve(){return this.totalConflicts===0?{cancelled:!1,states:this.conflicts}:(this.moveToNextConflict(),new Promise(e=>{let t=(0,ee.createInterface)({input:process.stdin,output:process.stdout});process.stdin.isTTY&&process.stdin.setRawMode(!0),process.stdin.resume(),this.render();let n=n=>{let r=n.toString();if(r===``){this.cleanup(t),this.renderCancelled(),e({cancelled:!0,states:this.conflicts});return}if(r===`\x1B`&&n.length===1){this.cleanup(t),this.renderCancelled(),e({cancelled:!0,states:this.conflicts});return}if(r.startsWith(`\x1B[`)){switch(r.slice(2)){case`D`:this.moveToPrevConflict(),this.render();break;case`C`:this.moveToNextConflict(),this.render();break}return}switch(r){case`r`:case`R`:this.setCurrentChoice(`remote`),this.advanceAfterChoice(t);break;case`l`:case`L`:this.setCurrentChoice(`local`),this.advanceAfterChoice(t);break;case`b`:case`B`:this.setCurrentChoice(`both`),this.advanceAfterChoice(t);break;case`\r`:case`
157
157
  `:this.allResolved()?(this.cleanup(t),e({cancelled:!1,states:this.conflicts})):(this.moveToNextUnresolved(),this.render());break;case`q`:case`Q`:this.cleanup(t),this.renderCancelled(),e({cancelled:!0,states:this.conflicts});break;case`a`:case`A`:this.acceptAllRemaining(`remote`),this.render();break;case`u`:case`U`:this.setCurrentChoice(`pending`),this.render();break}};process.stdin.on(`data`,n),this.currentCleanup=()=>{process.stdin.removeListener(`data`,n),process.stdin.isTTY&&process.stdin.setRawMode(!1),t.close()}}))}cleanup(e){this.currentCleanup?(this.currentCleanup(),this.currentCleanup=null):(process.stdin.isTTY&&process.stdin.setRawMode(!1),e.close())}advanceAfterChoice(e){this.allResolved()||this.moveToNextUnresolved(),this.render()}render(){e.v();let t=process.stdout.columns||80;this.renderHeader(t),this.renderProgressBar(t),this.renderCurrentConflict(t),this.renderControls(t)}renderHeader(t){let n=this.connectorId,r=`${this.localVersion} ${$.arrow} ${this.remoteVersion}`,a=Math.max(0,t-17),o=Math.floor(a/2),s=a-o,c=` `.repeat(o)+`CONFLICT RESOLVER`+` `.repeat(s);e.w.log(``),e.w.log(i.default.bgBlue.white.bold(c)),e.w.log(i.default.gray(this.centerText(n,t))),e.w.log(i.default.gray(this.centerText(r,t))),e.w.log(``)}renderProgressBar(t){let n=this.conflicts.filter(e=>e.conflict.type===`conflict`),r=this.getCurrentConflictIndex(),a=n.map((e,t)=>{let n=t===r,a,o;switch(e.choice){case`remote`:a=n?$.current:$.acceptRemote,o=i.default.green;break;case`local`:a=n?$.current:$.acceptLocal,o=i.default.yellow;break;case`both`:a=n?$.current:$.acceptBoth,o=i.default.cyan;break;default:a=n?$.current:$.pending,o=n?i.default.white:i.default.gray}return o(a)}),o=n.filter(e=>e.choice!==`pending`).length,s=` Conflict ${r+1} of ${this.totalConflicts} • ${o}/${this.totalConflicts} resolved `;e.w.log(i.default.gray(this.centerText(s,t))),e.w.log(this.centerText(a.join(` `),t)),e.w.log(``)}renderCurrentConflict(t){let n=this.conflicts[this.currentIndex];if(!n||n.conflict.type!==`conflict`)return;let r=n.conflict;if(e.w.log(i.default.gray(`_`.repeat(t))),e.w.log(`
158
158
 
159
159
  `),r.local){let t=n.choice===`local`||n.choice===`both`?i.default.yellow.bold(`${$.check} LOCAL (keeping)`):i.default.red.bold(`${$.cross} LOCAL (removing)`),a=r.local.split(`
@@ -167,9 +167,9 @@ Available skills
167
167
  `),l=a.length>20?`\n${i.default.gray(`... and ${a.length-20} more lines`)}`:``;e.w.log(`${t}\n\n${c}${l}`)}e.w.log(`
168
168
 
169
169
  `),e.w.log(i.default.gray(`_`.repeat(t))),e.w.log(``)}renderControls(t){let n=[i.default.green(`[R] Accept Remote`),i.default.yellow(`[L] Keep Local`),i.default.cyan(`[B] Keep Both`),i.default.gray(`[U] Undo`)],r=[i.default.gray(`[←/→] Navigate`),i.default.gray(`[A] Accept all remaining`)],a=this.allResolved()?[i.default.green.bold(`[Enter] Apply Changes`),i.default.gray(`[Esc] Cancel`)]:[i.default.gray(`[Enter] Next Unresolved`),i.default.gray(`[Esc] Cancel`)];e.w.log(this.centerText(n.join(` `),t)),e.w.log(``),e.w.log(this.centerText(r.join(` `),t)),e.w.log(``),e.w.log(this.centerText(a.join(` `),t)),this.allResolved()&&(e.w.log(``),e.w.log(i.default.green.bold(this.centerText(`✓ All conflicts resolved!`,t))))}renderFinalSummary(){e.v();let t=this.conflicts.filter(e=>e.conflict.type===`conflict`),n=0,r=0,a=0;for(let e of t)switch(e.choice){case`remote`:n++;break;case`local`:r++;break;case`both`:a++;break}let o=[i.default.green.bold(`Conflict resolution complete`),``,`${i.default.bold(this.totalConflicts)} conflicts resolved:`,``,`${i.default.green($.acceptRemote)} Accepted remote: ${n}`,`${i.default.yellow($.acceptLocal)} Kept local: ${r}`,`${i.default.cyan($.acceptBoth)} Kept both: ${a}`];e.w.box(o.join(`
170
- `))}renderCancelled(){e.v(),e.w.log(i.default.yellow(`Conflict resolution cancelled`)),e.w.log(``),e.w.log(`No changes were made to your local connector file.`)}getCurrentConflictIndex(){let e=-1;for(let t=0;t<=this.currentIndex&&t<this.conflicts.length;t++)this.conflicts[t].conflict.type===`conflict`&&e++;return e}moveToNextConflict(){for(let e=this.currentIndex+1;e<this.conflicts.length;e++)if(this.conflicts[e].conflict.type===`conflict`){this.currentIndex=e;return}for(let e=0;e<this.currentIndex;e++)if(this.conflicts[e].conflict.type===`conflict`){this.currentIndex=e;return}}moveToPrevConflict(){for(let e=this.currentIndex-1;e>=0;e--)if(this.conflicts[e].conflict.type===`conflict`){this.currentIndex=e;return}for(let e=this.conflicts.length-1;e>this.currentIndex;e--)if(this.conflicts[e].conflict.type===`conflict`){this.currentIndex=e;return}}moveToNextUnresolved(){for(let e=this.currentIndex+1;e<this.conflicts.length;e++)if(this.conflicts[e].conflict.type===`conflict`&&this.conflicts[e].choice===`pending`){this.currentIndex=e;return}for(let e=0;e<this.currentIndex;e++)if(this.conflicts[e].conflict.type===`conflict`&&this.conflicts[e].choice===`pending`){this.currentIndex=e;return}}setCurrentChoice(e){this.conflicts[this.currentIndex]?.conflict.type===`conflict`&&(this.conflicts[this.currentIndex].choice=e)}allResolved(){return this.conflicts.filter(e=>e.conflict.type===`conflict`).every(e=>e.choice!==`pending`)}acceptAllRemaining(e){for(let t of this.conflicts)t.conflict.type===`conflict`&&t.choice===`pending`&&(t.choice=e)}centerText(e,t){let n=this.stripAnsi(e),r=Math.max(0,Math.floor((t-n.length)/2));return` `.repeat(r)+e}stripAnsi(e){return e.replace(/\x1b\[[0-9;]*m/g,``)}getResolvedContent(){let e=[];for(let t of this.conflicts)if(t.conflict.type===`unchanged`)e.push(t.conflict.content||``);else if(t.conflict.type===`conflict`)switch(t.choice){case`remote`:t.conflict.remote&&e.push(t.conflict.remote);break;case`local`:t.conflict.local&&e.push(t.conflict.local);break;case`both`:t.conflict.local&&e.push(t.conflict.local),t.conflict.remote&&e.push(t.conflict.remote);break;case`pending`:t.conflict.remote&&e.push(t.conflict.remote);break}return e.join(``)}};const mn=`https://api.stackone.com`,hn=3;var gn=class{async execute({profile:t,connector:n,outputPath:r,apiUrl:a,apiKey:o,owner:s}={}){if((0,C.isMissing)(n)&&(e.w.error(`Connector identifier is required`),e.w.log(`Please provide a connector identifier using the ${e.C(`--connector`)} option in the format: ${e.C(`provider_key@version`)} or ${e.C(`provider_key`)}`),e.w.log(`If no version is specified, the latest version will be pulled.`),process.exit(1)),!t&&!o&&(e.w.error(`Profile or API key is required`),e.w.log(`Please provide a profile using the ${e.C(`--profile`)} option or an API key using the ${e.C(`--api-key`)} option.`),e.w.log(`To create a profile, run ${e.C(`stackone init`)}.`),process.exit(1)),t&&o&&(e.w.error(`Please provide either a profile or an API key, not both`),process.exit(1)),t&&a&&e.w.warn(`Specifying ${e.C(`--api-url`)} with a profile won't have any effect. Using API url from profile.`),t&&!Qt(t)){e.w.error(`Configuration profile ${e.C(t)} not found`),e.w.log(`Run ${e.C(`stackone init`)} to create a new configuration profile.\n`);let n=en();n.length>0&&(e.w.info(`Available configuration profiles:`),n.forEach(t=>{e.w.log(` - ${i.default.blue(t)}`)})),process.exit(1)}let c=t?Zt(t):{apiUrl:a??mn,apiKey:o};c?.apiKey||(e.w.error(`API key is missing`),e.w.log(`Please provide a valid API key in the profile or via the ${e.C(`--api-key`)} option.`),process.exit(1));let l=c.apiUrl??mn,[u,d]=n.split(`@`),f=await this.#f(u,l,c.apiKey,d??`latest`,s),p=this.#e(f),m=p.version??`unknown`,h=this.#t(r,p.key,m),g=this.#r(h),_=g===null,v=f;if(!_){let t=this.#i(g,h);t&&(e.w.warn(t.message),t.errors.length>0&&e.y(t.errors,!1),e.w.log(``));let r=t?void 0:this.#e(g);if(this.#o(g,f)){this.#a(g,f,h);let t=r?.version??`unknown`,i=await this.#s(g,f,n,t,m);i.action===`cancel`&&((0,w.cancel)(`Pull cancelled`),process.exit(0)),i.action===`keep-local`&&(e.w.log(``),e.w.info(`Keeping local version. No changes made.`),process.exit(0)),i.action===`interactive-cancel`&&process.exit(0),i.action===`interactive`&&(v=i.resolvedContent)}else e.w.info(`No changes detected in connector configuration.`),process.exit(0)}let y=(0,T.validateYamlConnector)(v).connector,b=y?.key??p.key,x=y?.version??m,S=this.#t(r,b,x),E=S;if(S!==h){let t=await this.#n(S);e.w.log(``),t!==void 0&&(E=t)}await this.#d(E,v),_?e.w.success(`Connector ${e.C(b)}@${e.C(x)} pulled successfully (new connector)`):e.w.success(`Connector ${e.C(b)}@${e.C(x)} updated successfully`);let ee=b===p.key?e.C(b):`${e.C(p.key)} ${i.default.whiteBright(`→`)} ${e.C(b)}`,te=x===m?e.C(x):`${e.C(m)} ${i.default.whiteBright(`→`)} ${e.C(x)}`,D=E===h?e.C(E):`${e.C(h)}\n ${i.default.whiteBright(`→`)} ${e.C(E)}`;e.w.log(`\n${i.default.blue.inverse(` CONNECTOR DETAILS `)}\n`),e.w.log(` Provider: ${ee}`),e.w.log(` Version: ${te}`),e.w.log(` Output file: ${D}`),process.exit(0)}#e(t){let n=(0,T.validateYamlConnector)(t),r=n?.errors??[];if(n.success)return n.connector;e.w.error(`Connector pulled from the registry is not valid`),e.w.log(`Please make sure you are using the latest version of the StackOne CLI by running ${e.C(`stackone update`)}`),r.length>0&&e.y(r,!0),process.exit(1)}#t(t,n,r){let i=`${n}_v${r.replaceAll(`.`,`-`)}.s1.yaml`;return t?(m.default.existsSync(t)&&(m.default.statSync(t).isDirectory()||(e.w.error(`Output path ${e.C(t)} is not a directory`),e.w.log(`Please provide a valid directory path to store connectors or use the default path.`),process.exit(1))),h.default.resolve(t,n,i)):h.default.resolve(process.cwd(),`connectors`,n,i)}async#n(t){if(!m.default.existsSync(t))return;let n=h.default.basename(t),r=h.default.dirname(t);e.w.warn(`File ${e.C(n)} already exists at ${e.C(r)}`);let i=await(0,w.select)({message:`How would you like to proceed?`,options:[{value:`override`,label:`Override existing file`,hint:`Replace the existing file with the new content`},{value:`rename`,label:`Save with a different name`,hint:`Provide a new filename for the connector`},{value:`cancel`,label:`Cancel`,hint:`Abort the pull operation`}]});if(((0,w.isCancel)(i)||i===`cancel`)&&((0,w.cancel)(`Operation cancelled. No local changes were made.`),process.exit(0)),i===`override`)return;let a=await(0,w.text)({message:`Enter the new filename:`,placeholder:n,validate:e=>{if(!e||e.trim()===``)return`Filename cannot be empty`;if(!e.endsWith(`.s1.yaml`))return`Filename must end with .s1.yaml`;let t=h.default.join(r,e.trim());if(m.default.existsSync(t))return`File ${e} already exists`}});return(0,w.isCancel)(a)&&((0,w.cancel)(`Operation cancelled. No local changes were made.`),process.exit(0)),h.default.join(r,a.trim())}#r(e){if(!m.default.existsSync(e))return null;try{return m.default.readFileSync(e,`utf-8`)}catch{return null}}#i(t,n){try{let r=(0,T.validateYamlConnector)(t);if(!r.success){let t=r.errors??[];return{message:`Local connector ${e.C(h.default.basename(n))} has validation errors:`,errors:t}}}catch(t){return{message:`Local connector ${e.C(h.default.basename(n))} could not be validated: ${t.message}`,errors:[]}}return null}#a(t,n,r){let a=(0,E.diffLines)(t,n);if(!a.some(e=>e.added||e.removed)){e.w.info(`No changes detected in connector configuration.`);return}e.w.log(`${i.default.blue.inverse(` CHANGES `)}\n`),e.w.log(i.default.gray(`--- local: ${r}`)),e.w.log(i.default.gray(`+++ remote: StackOne Registry`)),e.w.log(``);let o=0,s=0;for(let t of a){let n=t.value.split(`
171
- `).filter(e=>e!==``);if(t.added){o+=n.length;for(let t of n)e.w.log(i.default.green(`+ ${t}`))}else if(t.removed){s+=n.length;for(let t of n)e.w.log(i.default.red(`- ${t}`))}else if(n.length<=6)for(let t of n)e.w.log(i.default.gray(` ${t}`));else{for(let t=0;t<3;t++)e.w.log(i.default.gray(` ${n[t]}`));e.w.log(i.default.gray(` ... (${n.length-6} unchanged lines)`));for(let t=n.length-3;t<n.length;t++)e.w.log(i.default.gray(` ${n[t]}`))}}e.w.log(``),e.w.log(i.default.gray(`Summary: ${i.default.green(`+${o}`)} additions, ${i.default.red(`-${s}`)} deletions`))}#o(e,t){return(0,E.diffLines)(e,t).some(e=>e.added||e.removed)}async#s(t,n,r,i,a){e.w.log(``);let o=await(0,w.select)({message:`How would you like to resolve the differences?`,options:[{value:`override`,label:`Override local with remote`,hint:`Replace your local file with the StackOne version`},{value:`keep-local`,label:`Keep local version`,hint:`Cancel the pull and keep your current file`},{value:`interactive`,label:`Resolve conflicts interactively`,hint:`Choose which changes to accept one by one`},{value:`cancel`,label:`Cancel`,hint:`Abort the pull operation`}]});if((0,w.isCancel)(o))return{action:`cancel`};if(o===`override`)return{action:`override`};if(o===`keep-local`)return{action:`keep-local`};if(o===`interactive`){let e=await this.#c(t,n,r,i,a);return e===null?{action:`interactive-cancel`}:{action:`interactive`,resolvedContent:e}}return{action:`cancel`}}async#c(t,n,r,i,a){let o=(0,E.diffLines)(t,n),s=this.#u(o);if(s.length===0)return e.w.info(`No conflicts to resolve.`),n;let c=new pn(s,r,i,a);for(;;){if((await c.resolve()).cancelled)return null;let t=c.getResolvedContent(),n=(0,T.validateYamlConnector)(t);if(n.success)return c.renderFinalSummary(),t;let r=await this.#l(n.errors);if(r===`cancel`)return e.v(),e.w.info(`Operation cancelled. No changes were made to the local connector.`),null;if(r===`save`)return e.v(),e.w.warn(`The connector was saved but it is invalid`),t;c.resetForReResolution()}}async#l(t){let{createInterface:n}=await import(`readline`);return new Promise(r=>{e.v();let a=(t||[{message:`Unknown validation error`}]).map(e=>` • ${e.message}`).join(`
172
- `);e.w.box({title:`⚠️ Validation Failed`,message:`The resolved connector configuration is invalid:\n\n${a}`,style:{borderColor:`yellow`,padding:1}}),e.w.log(``),e.w.log(i.default.bold(` Choose an action:`)),e.w.log(``),e.w.log(i.default.cyan(` [B]`)+` ← Go back to conflict resolution`),e.w.log(i.default.dim(` Modify your choices to fix the validation errors`)),e.w.log(``),e.w.log(i.default.yellow(` [S]`)+` 💾 Save anyway`),e.w.log(i.default.dim(` Save the invalid configuration (not recommended)`)),e.w.log(``),e.w.log(i.default.red(` [C]`)+` ✖ Cancel`),e.w.log(i.default.dim(` Discard all changes`)),e.w.log(``);let o=n({input:process.stdin,output:process.stdout});process.stdin.isTTY&&process.stdin.setRawMode(!0),process.stdin.resume();let s=e=>{let t=e.toString().toLowerCase(),n=()=>{process.stdin.removeListener(`data`,s),process.stdin.isTTY&&process.stdin.setRawMode(!1),o.close()};if(t===``||t===`\x1B`){n(),r(`cancel`);return}switch(t){case`b`:n(),r(`back`);break;case`s`:n(),r(`save`);break;case`c`:case`q`:n(),r(`cancel`);break}};process.stdin.on(`data`,s)})}#u(e){let t=[],n=0;for(;n<e.length;){let r=e[n];if(!r.added&&!r.removed)t.push({type:`unchanged`,content:r.value}),n++;else if(r.removed){let i=e[n+1];i?.added?(t.push({type:`conflict`,local:r.value,remote:i.value}),n+=2):(t.push({type:`conflict`,local:r.value,remote:void 0}),n++)}else r.added&&t.push({type:`conflict`,local:void 0,remote:r.value}),n++}return t}async#d(t,n){let r=h.default.dirname(t);m.default.existsSync(r)||m.default.mkdirSync(r,{recursive:!0});try{m.default.writeFileSync(t,n,`utf-8`)}catch(n){e.w.error(`Failed to write connector to file ${e.C(t)}: ${n.message}`),process.exit(1)}}async#f(t,n,r,i,a){let o=(0,v.default)(`Pulling connector ${e.C(t)}@${e.C(i)} from registry...`).start();try{let s=Buffer.from(r).toString(`base64`),c=`${n}/registry/connectors/${t}@${i}${a?`?owner=${encodeURIComponent(a)}`:``}`,l=await fetch(c,{method:`GET`,headers:{Authorization:`Basic ${s}`}});if(o.stop(),l.status===409){a&&(await this.#p(l,t,i),process.exit(1));let r=(await l.json()).availableOwners??[],c=await an(`${t}@${i}`,r);o.text=`Pulling connector ${e.C(t)}@${e.C(i)} from registry...`,o.start();let u=`${n}/registry/connectors/${t}@${i}`,d=await fetch(`${u}?owner=${encodeURIComponent(c)}`,{method:`GET`,headers:{Authorization:`Basic ${s}`}});return o.stop(),d.ok||(await this.#p(d,t,i),process.exit(1)),await d.text()}return l.ok||(await this.#p(l,t,i),process.exit(1)),await l.text()}catch(r){o.stop(),e.w.error(`Failed to pull connector ${e.C(t)}@${e.C(i)} from the registry: ${r.message}`),e.w.log(`Please ensure that the API at ${e.T(n)} is reachable and the API key is valid.`),process.exit(1)}}async#p(t,n,r){switch(t.status){case 401:case 403:e.w.error(`Access denied`),e.w.log(`Please ensure that your API key is valid and has the ${e.C(`connectors:read`)} scope required to pull connectors.`);break;case 404:e.w.error(`Connector ${e.C(n)}@${e.C(r)} was not found in the registry`),await this.#m(n);break;case 429:e.w.error(`Rate limit exceeded`),e.w.log(`Too many requests. Please wait a moment before trying again.`);break;default:await e.x(t,`Failed to pull connector ${e.C(n)}`)}}async#m(t){e.w.info(`To see available versions, check the connector documentation or contact support.`)}};const _n=`https://api.stackone.com`;var vn=class{async execute({profile:t,fileOrDir:n,apiUrl:r,apiKey:a,force:o}={}){if(!t&&!a&&(e.w.error(`Profile or API key is required`),e.w.log(`Please provide a profile using the ${e.C(`--profile`)} option or an API key using the ${e.C(`--api-key`)} option.`),e.w.log(`To create a profile, run ${e.C(`stackone init`)}.`),process.exit(1)),t&&a&&(e.w.error(`Please provide either a profile or an API key, not both`),process.exit(1)),t&&r&&e.w.warn(`Specifying ${e.C(`--api-url`)} with a profile won't have any effect. Using API url from profile.`),t&&!Qt(t)){e.w.error(`Configuration profile ${e.C(t)} not found`),e.w.log(`Run ${e.C(`stackone init`)} to create a new configuration profile.\n`);let n=en();n.length>0&&(e.w.info(`Available configuration profiles:`),n.forEach(t=>{e.w.log(` - ${i.default.blue(t)}`)})),process.exit(1)}let s=t?Zt(t):{apiUrl:r??_n,apiKey:a};s?.apiKey||(e.w.error(`API key is missing`),e.w.log(`Please provide a valid API key in the profile or via the ${e.C(`--api-key`)} option.`),process.exit(1)),n||(e.w.error(`File or directory is required.`),process.exit(1));try{(0,m.statSync)(n)}catch{e.w.error(`File or directory not found: ${i.default.red(n)}`),process.exit(1)}let c=(0,m.statSync)(n),l=s.apiUrl??_n;if(c.isDirectory()){let t=wn(n),r=0;t.length===0?(e.w.error(`No .s1.yaml connector files found in the directory: ${n}.`),process.exit(1)):(e.w.start(`Found ${t.length} connector(s) file(s). Pushing to registry...`),e.w.log(``));for(let e of t)await this.uploadFile(e,l,s.apiKey,o)&&r++;r===0?e.w.error(`Error while pushing connectors: no files were uploaded`):(e.w.log(``),e.w.info(`Upload completed: ${i.default.green(r)} of ${i.default.blue(t.length)} file(s) uploaded successfully.`)),process.exit(r>0?0:1)}else n.endsWith(`.s1.yaml`)||(e.w.error(`Only ${e.C(`.s1.yaml`)} files are supported for upload`),process.exit(1));let u=await this.uploadFile(n,l,s.apiKey,o);process.exit(u?0:1)}async uploadFile(t,n,r,i){let a=(0,v.default)(`📤 Pushing connector in ${(0,h.basename)(t)}...`).start();try{let o=Cn(t);if(!o)return!1;let s=(0,h.basename)(t),c=new FormData,l=new Blob([o],{type:`application/x-yaml`});c.append(`file`,l,s),i&&c.append(`force`,`true`);let u=Buffer.from(r).toString(`base64`),d=await fetch(`${n}/registry/connectors`,{method:`POST`,headers:{Authorization:`Basic ${u}`},body:c});if(a.stop(),!d.ok)return d.status===409||d.status===422?await this.handleVersionConflict(d,t,n,r,i):(await e.x(d,`Failed to push connector in ${e.C(s)} to the registry`),!1);let f=await d.json();return e.w.success(`Successfully uploaded ${e.C(s)} with connector ${e.C(f.provider)}@${e.C(f.version)}`),!0}catch(r){return a.stop(),e.w.error(`Failed to upload file ${e.C(t)}: ${r}`),e.w.log(`Please ensure that the API at ${e.T(n)} is reachable and the API key is valid`),!1}}async handleVersionConflict(t,n,r,i,a){let o=await t.text(),s;try{s=JSON.parse(o)}catch{}let c=D.default.valid(s?.latestVersion);if(!c)return await e.x(new Response(o,{status:t.status,statusText:t.statusText}),`Failed to push connector in ${e.C((0,h.basename)(n))} to the registry`),!1;let l=(0,m.readFileSync)(n,`utf-8`),u=yn(l),d=u?`${e.C(u)}`:``,f=t.status===409?`Version ${d} already exists in the registry. Latest version: ${e.C(c)}`:`Version ${d} is lower than the latest version in the registry. Latest version: ${e.C(c)}`;e.w.error(f);let p=D.default.inc(c,`patch`)??c,g=D.default.inc(c,`minor`)??c,_=D.default.inc(c,`major`)??c,v=await(0,w.select)({message:`How would you like to proceed?`,options:[{value:p,label:`Bump patch version (${p})`},{value:g,label:`Bump minor version (${g})`},{value:_,label:`Bump major version (${_})`},{value:`cancel`,label:`Cancel push`}]});return(0,w.isCancel)(v)||v===`cancel`?((0,w.cancel)(`Push cancelled`),!1):((0,m.writeFileSync)(n,bn(l,v),`utf-8`),e.w.info(`Updated version to ${e.C(v)} in ${(0,h.basename)(n)}`),this.uploadFile(n,r,i,a))}};const yn=e=>e.match(/^\s*version: (\S+)/m)?.[1],bn=(e,t)=>e.replace(/^(\s*version: )\S+/m,`$1${t}`),xn=e=>{try{let t=(0,T.parseYamlConnector)(e);return t.changelog?.summary?.trim()?null:`has no changelog entry for version ${t.version}`}catch{return null}},Sn=()=>{e.w.log(`Every published version must record what changed. Add an ${e.C(`info.changelog`)} block:`),e.w.log(``),e.w.log(i.default.gray(` info:`)),e.w.log(i.default.gray(` changelog:`)),e.w.log(i.default.gray(` summary: What changed in this version.`)),e.w.log(i.default.gray(` labels: [new-actions] # optional, one of: ${te.ChangelogLabels.join(`, `)}`)),e.w.log(``)},Cn=t=>{let n=(0,T.loadConnector)(t),r=(0,T.validateYamlConnector)(n),i=r?.errors??[];if(r.success){let r=xn(n);if(r){e.w.error(`Connector in ${e.S(t)} ${r}`),Sn();return}return n}else i.length>0?(e.w.error(`Connector in ${e.S(t)} is not valid`),e.y(i,!0)):e.w.error(`Connector in ${e.S(t)} is not valid. Please check the file for errors.`)},wn=e=>{let t=[],n=(0,m.readdirSync)(e,{withFileTypes:!0});for(let r of n){let n=(0,h.join)(e,r.name);r.isDirectory()?t.push(...wn(n)):r.name.endsWith(`.s1.yaml`)&&t.push(n)}return t},Tn=C.z.object({provider_key:C.z.string().optional(),provider_version:C.z.string().optional(),auth_config_key:C.z.string(),environment:C.z.string().default(`production`),organization_id:C.z.string().default(`cli-organization-id`),account_id:C.z.string().default(`cli-account-secure-id`),project_id:C.z.string().default(`cli-project-secure-id`),credentials:C.z.record(C.z.string(),C.z.any()).default({})}),En=C.z.record(C.z.string(),C.z.any()),Dn=C.z.object({path:C.z.record(C.z.string(),C.z.any()).default({}),queryParams:C.z.record(C.z.string(),C.z.any()).default({}),header:C.z.record(C.z.string(),C.z.any()).default({}),body:C.z.record(C.z.string(),C.z.any()).default({})}),On=`https://api.stackone.com`;var kn=class{async execute({connector:t,action:n,actionId:r,account:a,accountId:o,params:s,credentials:c,profile:l,outputFile:u,debug:d,apiUrl:f,apiKey:p,owner:h}={}){if(!l&&!p&&o&&(e.w.error(`Profile or API key is required when providing an account ID`),e.w.log(`Please provide a profile using the ${e.C(`--profile`)} option or an API key using the ${e.C(`--api-key`)} option.`),e.w.log(`To create a profile, run ${e.C(`stackone init`)}.`),process.exit(1)),l&&p&&(e.w.error(`Please provide either a profile or an API key, not both`),process.exit(1)),l&&f&&e.w.warn(`Specifying --api-url with a profile won't have any effect. Using API url from profile.`),l&&!Qt(l)){e.w.error(`Configuration profile ${e.C(l)} not found`),e.w.log(`Run ${e.C(`stackone init`)} to create a new configuration profile.\n`);let t=en();t.length>0&&(e.w.info(`Available configuration profiles:`),t.forEach(t=>{e.w.log(` - ${i.default.blue(t)}`)})),process.exit(1)}let g=l?Zt(l):{apiUrl:f??On,apiKey:p};(0,C.isMissing)(a)&&(0,C.isMissing)(o)&&(e.w.error(`A valid account or account ID is required to run an action`),process.exit(1));let _;if((0,C.notMissing)(t))if(this.#a(t)){!l&&!p&&(e.w.error(`Profile or API key is required when using a connector identifier`),e.w.log(`Please provide a profile using the ${e.C(`--profile`)} option or an API key using the ${e.C(`--api-key`)} option.`),e.w.log(`Run ${e.C(`stackone init`)} to create a new configuration profile.`),process.exit(1));let n=this.#o(t);_=await this.#s(n,g?.apiUrl??On,g?.apiKey,h)}else _=this.#e(t);else (0,C.notMissing)(o)&&(_=await this.#c(o,g?.apiUrl??On,g?.apiKey));let v=(0,C.notMissing)(n)?this.#r(n,t):_;(0,C.isMissing)(v)&&(e.w.error(`A valid connector is required to run an action.`),process.exit(1));let y=(0,C.notMissing)(v?.actions)?Object.keys(v?.actions).length:0,b=(0,C.notMissing)(v?.actions)?Object.keys(v.actions)[y-1]:void 0,x=(0,C.notMissing)(b)?v?.actions?.[b]?.id:void 0,S=((0,C.notMissing)(r)&&!r?.startsWith(`${v.key}_`)?`${v.key}_${r}`:r)??x;(0,C.isMissing)(S)&&(e.w.error(`A valid action ID is required to run an action`),process.exit(1));let w=(0,C.notMissing)(o)?await this.#l(o,g?.apiUrl??On,g?.apiKey):{},T=(0,C.notMissing)(a)?this.#i(a,v.key??`unknown`,v.version??`unknown`):void 0,E=(0,C.notMissing)(c)?this.#u(c):{},ee={...w,...T,credentials:{...w.credentials??{},...E}};(0,C.isMissing)(ee)&&(e.w.error(`A valid account data is required to run an action.`),process.exit(1));let te=v.actions?.[S];(0,C.isMissing)(te)&&(e.w.error(`Action ID ${e.C(S)} not found in the connector ${e.C(v.key)}@${e.C(v.version)}.`),process.exit(1));let D=(0,C.notMissing)(s)?this.#d(s,S):{path:{},queryParams:{},header:{},body:{}},O=Date.now(),k=await this.#f({connector:v,actionId:S,account:ee,queryParams:{...D.queryParams,...d?{debug:`true`}:{}},pathParams:D.path,body:D.body,headers:D.header}),A=Date.now()-O;if((0,C.notMissing)(u))try{m.default.writeFileSync(u,JSON.stringify(k.output,null,2),`utf-8`),e.w.info(`Output written to file: ${u}`)}catch(t){e.w.error(`Failed to write output to file ${u}: ${t.message}`),process.exit(1)}else e.w.log(`\n${i.default.blue.inverse(` ACTION OUTPUT `)}`),e.b(k.output);e.w.log(``),e.w.info(`Action ${e.C(S)} from connector ${e.C(v?.key)}@${e.C(v?.version)} finished in ${i.default.yellowBright((A/1e3).toFixed(2))} seconds.`),process.exit(0)}#e=e=>{let t=e;try{t=(0,T.loadConnector)(e)}catch{}return t?this.#n(t):void 0};#t=t=>{try{return(0,T.loadConnector)(t)}catch(n){e.w.error(`Failed to load connector file from ${e.C(t)}: ${n.message}`),process.exit(1)}};#n=t=>{let n=(0,T.validateYamlConnector)(t),r=n?.errors??[];if(n.success)return n.connector||(e.w.error(`Failed to load connector.`),process.exit(1)),n.connector;r.length>0?(e.w.error(`Connector is not valid`),e.y(r,!0),process.exit(1)):(e.w.error(`Connector is not valid. Please check the file for errors.`),process.exit(1))};#r=(t,n)=>{let r=t;try{r=m.default.readFileSync(t,`utf-8`)}catch{}(0,C.isMissing)(n)&&(e.w.error(`A valid connector is required to load an action.`),process.exit(1));let i=`${this.#t(n)} - ${r.split(`
170
+ `))}renderCancelled(){e.v(),e.w.log(i.default.yellow(`Conflict resolution cancelled`)),e.w.log(``),e.w.log(`No changes were made to your local connector file.`)}getCurrentConflictIndex(){let e=-1;for(let t=0;t<=this.currentIndex&&t<this.conflicts.length;t++)this.conflicts[t].conflict.type===`conflict`&&e++;return e}moveToNextConflict(){for(let e=this.currentIndex+1;e<this.conflicts.length;e++)if(this.conflicts[e].conflict.type===`conflict`){this.currentIndex=e;return}for(let e=0;e<this.currentIndex;e++)if(this.conflicts[e].conflict.type===`conflict`){this.currentIndex=e;return}}moveToPrevConflict(){for(let e=this.currentIndex-1;e>=0;e--)if(this.conflicts[e].conflict.type===`conflict`){this.currentIndex=e;return}for(let e=this.conflicts.length-1;e>this.currentIndex;e--)if(this.conflicts[e].conflict.type===`conflict`){this.currentIndex=e;return}}moveToNextUnresolved(){for(let e=this.currentIndex+1;e<this.conflicts.length;e++)if(this.conflicts[e].conflict.type===`conflict`&&this.conflicts[e].choice===`pending`){this.currentIndex=e;return}for(let e=0;e<this.currentIndex;e++)if(this.conflicts[e].conflict.type===`conflict`&&this.conflicts[e].choice===`pending`){this.currentIndex=e;return}}setCurrentChoice(e){this.conflicts[this.currentIndex]?.conflict.type===`conflict`&&(this.conflicts[this.currentIndex].choice=e)}allResolved(){return this.conflicts.filter(e=>e.conflict.type===`conflict`).every(e=>e.choice!==`pending`)}acceptAllRemaining(e){for(let t of this.conflicts)t.conflict.type===`conflict`&&t.choice===`pending`&&(t.choice=e)}centerText(e,t){let n=this.stripAnsi(e),r=Math.max(0,Math.floor((t-n.length)/2));return` `.repeat(r)+e}stripAnsi(e){return e.replace(/\x1b\[[0-9;]*m/g,``)}getResolvedContent(){let e=[];for(let t of this.conflicts)if(t.conflict.type===`unchanged`)e.push(t.conflict.content||``);else if(t.conflict.type===`conflict`)switch(t.choice){case`remote`:t.conflict.remote&&e.push(t.conflict.remote);break;case`local`:t.conflict.local&&e.push(t.conflict.local);break;case`both`:t.conflict.local&&e.push(t.conflict.local),t.conflict.remote&&e.push(t.conflict.remote);break;case`pending`:t.conflict.remote&&e.push(t.conflict.remote);break}return e.join(``)}};const hn=`https://api.stackone.com`,gn=3;var _n=class{async execute({profile:t,connector:n,outputPath:r,apiUrl:a,apiKey:o,owner:s}={}){if((0,C.isMissing)(n)&&(e.w.error(`Connector identifier is required`),e.w.log(`Please provide a connector identifier using the ${e.C(`--connector`)} option in the format: ${e.C(`provider_key@version`)} or ${e.C(`provider_key`)}`),e.w.log(`If no version is specified, the latest version will be pulled.`),process.exit(1)),!t&&!o&&(e.w.error(`Profile or API key is required`),e.w.log(`Please provide a profile using the ${e.C(`--profile`)} option or an API key using the ${e.C(`--api-key`)} option.`),e.w.log(`To create a profile, run ${e.C(`stackone init`)}.`),process.exit(1)),t&&o&&(e.w.error(`Please provide either a profile or an API key, not both`),process.exit(1)),t&&a&&e.w.warn(`Specifying ${e.C(`--api-url`)} with a profile won't have any effect. Using API url from profile.`),t&&!$t(t)){e.w.error(`Configuration profile ${e.C(t)} not found`),e.w.log(`Run ${e.C(`stackone init`)} to create a new configuration profile.\n`);let n=tn();n.length>0&&(e.w.info(`Available configuration profiles:`),n.forEach(t=>{e.w.log(` - ${i.default.blue(t)}`)})),process.exit(1)}let c=t?Qt(t):{apiUrl:a??hn,apiKey:o};c?.apiKey||(e.w.error(`API key is missing`),e.w.log(`Please provide a valid API key in the profile or via the ${e.C(`--api-key`)} option.`),process.exit(1));let l=c.apiUrl??hn,[u,d]=n.split(`@`),f=await this.#f(u,l,c.apiKey,d??`latest`,s),p=this.#e(f),m=p.version??`unknown`,h=this.#t(r,p.key,m),g=this.#r(h),_=g===null,v=f;if(!_){let t=this.#i(g,h);t&&(e.w.warn(t.message),t.errors.length>0&&e.y(t.errors,!1),e.w.log(``));let r=t?void 0:this.#e(g);if(this.#o(g,f)){this.#a(g,f,h);let t=r?.version??`unknown`,i=await this.#s(g,f,n,t,m);i.action===`cancel`&&((0,w.cancel)(`Pull cancelled`),process.exit(0)),i.action===`keep-local`&&(e.w.log(``),e.w.info(`Keeping local version. No changes made.`),process.exit(0)),i.action===`interactive-cancel`&&process.exit(0),i.action===`interactive`&&(v=i.resolvedContent)}else e.w.info(`No changes detected in connector configuration.`),process.exit(0)}let y=(0,T.validateYamlConnector)(v).connector,b=y?.key??p.key,x=y?.version??m,S=this.#t(r,b,x),E=S;if(S!==h){let t=await this.#n(S);e.w.log(``),t!==void 0&&(E=t)}await this.#d(E,v),_?e.w.success(`Connector ${e.C(b)}@${e.C(x)} pulled successfully (new connector)`):e.w.success(`Connector ${e.C(b)}@${e.C(x)} updated successfully`);let ee=b===p.key?e.C(b):`${e.C(p.key)} ${i.default.whiteBright(`→`)} ${e.C(b)}`,te=x===m?e.C(x):`${e.C(m)} ${i.default.whiteBright(`→`)} ${e.C(x)}`,D=E===h?e.C(E):`${e.C(h)}\n ${i.default.whiteBright(`→`)} ${e.C(E)}`;e.w.log(`\n${i.default.blue.inverse(` CONNECTOR DETAILS `)}\n`),e.w.log(` Provider: ${ee}`),e.w.log(` Version: ${te}`),e.w.log(` Output file: ${D}`),process.exit(0)}#e(t){let n=(0,T.validateYamlConnector)(t),r=n?.errors??[];if(n.success)return n.connector;e.w.error(`Connector pulled from the registry is not valid`),e.w.log(`Please make sure you are using the latest version of the StackOne CLI by running ${e.C(`stackone update`)}`),r.length>0&&e.y(r,!0),process.exit(1)}#t(t,n,r){let i=`${n}_v${r.replaceAll(`.`,`-`)}.s1.yaml`;return t?(m.default.existsSync(t)&&(m.default.statSync(t).isDirectory()||(e.w.error(`Output path ${e.C(t)} is not a directory`),e.w.log(`Please provide a valid directory path to store connectors or use the default path.`),process.exit(1))),h.default.resolve(t,n,i)):h.default.resolve(process.cwd(),`connectors`,n,i)}async#n(t){if(!m.default.existsSync(t))return;let n=h.default.basename(t),r=h.default.dirname(t);e.w.warn(`File ${e.C(n)} already exists at ${e.C(r)}`);let i=await(0,w.select)({message:`How would you like to proceed?`,options:[{value:`override`,label:`Override existing file`,hint:`Replace the existing file with the new content`},{value:`rename`,label:`Save with a different name`,hint:`Provide a new filename for the connector`},{value:`cancel`,label:`Cancel`,hint:`Abort the pull operation`}]});if(((0,w.isCancel)(i)||i===`cancel`)&&((0,w.cancel)(`Operation cancelled. No local changes were made.`),process.exit(0)),i===`override`)return;let a=await(0,w.text)({message:`Enter the new filename:`,placeholder:n,validate:e=>{if(!e||e.trim()===``)return`Filename cannot be empty`;if(!e.endsWith(`.s1.yaml`))return`Filename must end with .s1.yaml`;let t=h.default.join(r,e.trim());if(m.default.existsSync(t))return`File ${e} already exists`}});return(0,w.isCancel)(a)&&((0,w.cancel)(`Operation cancelled. No local changes were made.`),process.exit(0)),h.default.join(r,a.trim())}#r(e){if(!m.default.existsSync(e))return null;try{return m.default.readFileSync(e,`utf-8`)}catch{return null}}#i(t,n){try{let r=(0,T.validateYamlConnector)(t);if(!r.success){let t=r.errors??[];return{message:`Local connector ${e.C(h.default.basename(n))} has validation errors:`,errors:t}}}catch(t){return{message:`Local connector ${e.C(h.default.basename(n))} could not be validated: ${t.message}`,errors:[]}}return null}#a(t,n,r){let a=(0,E.diffLines)(t,n);if(!a.some(e=>e.added||e.removed)){e.w.info(`No changes detected in connector configuration.`);return}e.w.log(`${i.default.blue.inverse(` CHANGES `)}\n`),e.w.log(i.default.gray(`--- local: ${r}`)),e.w.log(i.default.gray(`+++ remote: StackOne Registry`)),e.w.log(``);let o=0,s=0;for(let t of a){let n=t.value.split(`
171
+ `).filter(e=>e!==``);if(t.added){o+=n.length;for(let t of n)e.w.log(i.default.green(`+ ${t}`))}else if(t.removed){s+=n.length;for(let t of n)e.w.log(i.default.red(`- ${t}`))}else if(n.length<=6)for(let t of n)e.w.log(i.default.gray(` ${t}`));else{for(let t=0;t<3;t++)e.w.log(i.default.gray(` ${n[t]}`));e.w.log(i.default.gray(` ... (${n.length-6} unchanged lines)`));for(let t=n.length-3;t<n.length;t++)e.w.log(i.default.gray(` ${n[t]}`))}}e.w.log(``),e.w.log(i.default.gray(`Summary: ${i.default.green(`+${o}`)} additions, ${i.default.red(`-${s}`)} deletions`))}#o(e,t){return(0,E.diffLines)(e,t).some(e=>e.added||e.removed)}async#s(t,n,r,i,a){e.w.log(``);let o=await(0,w.select)({message:`How would you like to resolve the differences?`,options:[{value:`override`,label:`Override local with remote`,hint:`Replace your local file with the StackOne version`},{value:`keep-local`,label:`Keep local version`,hint:`Cancel the pull and keep your current file`},{value:`interactive`,label:`Resolve conflicts interactively`,hint:`Choose which changes to accept one by one`},{value:`cancel`,label:`Cancel`,hint:`Abort the pull operation`}]});if((0,w.isCancel)(o))return{action:`cancel`};if(o===`override`)return{action:`override`};if(o===`keep-local`)return{action:`keep-local`};if(o===`interactive`){let e=await this.#c(t,n,r,i,a);return e===null?{action:`interactive-cancel`}:{action:`interactive`,resolvedContent:e}}return{action:`cancel`}}async#c(t,n,r,i,a){let o=(0,E.diffLines)(t,n),s=this.#u(o);if(s.length===0)return e.w.info(`No conflicts to resolve.`),n;let c=new mn(s,r,i,a);for(;;){if((await c.resolve()).cancelled)return null;let t=c.getResolvedContent(),n=(0,T.validateYamlConnector)(t);if(n.success)return c.renderFinalSummary(),t;let r=await this.#l(n.errors);if(r===`cancel`)return e.v(),e.w.info(`Operation cancelled. No changes were made to the local connector.`),null;if(r===`save`)return e.v(),e.w.warn(`The connector was saved but it is invalid`),t;c.resetForReResolution()}}async#l(t){let{createInterface:n}=await import(`readline`);return new Promise(r=>{e.v();let a=(t||[{message:`Unknown validation error`}]).map(e=>` • ${e.message}`).join(`
172
+ `);e.w.box({title:`⚠️ Validation Failed`,message:`The resolved connector configuration is invalid:\n\n${a}`,style:{borderColor:`yellow`,padding:1}}),e.w.log(``),e.w.log(i.default.bold(` Choose an action:`)),e.w.log(``),e.w.log(i.default.cyan(` [B]`)+` ← Go back to conflict resolution`),e.w.log(i.default.dim(` Modify your choices to fix the validation errors`)),e.w.log(``),e.w.log(i.default.yellow(` [S]`)+` 💾 Save anyway`),e.w.log(i.default.dim(` Save the invalid configuration (not recommended)`)),e.w.log(``),e.w.log(i.default.red(` [C]`)+` ✖ Cancel`),e.w.log(i.default.dim(` Discard all changes`)),e.w.log(``);let o=n({input:process.stdin,output:process.stdout});process.stdin.isTTY&&process.stdin.setRawMode(!0),process.stdin.resume();let s=e=>{let t=e.toString().toLowerCase(),n=()=>{process.stdin.removeListener(`data`,s),process.stdin.isTTY&&process.stdin.setRawMode(!1),o.close()};if(t===``||t===`\x1B`){n(),r(`cancel`);return}switch(t){case`b`:n(),r(`back`);break;case`s`:n(),r(`save`);break;case`c`:case`q`:n(),r(`cancel`);break}};process.stdin.on(`data`,s)})}#u(e){let t=[],n=0;for(;n<e.length;){let r=e[n];if(!r.added&&!r.removed)t.push({type:`unchanged`,content:r.value}),n++;else if(r.removed){let i=e[n+1];i?.added?(t.push({type:`conflict`,local:r.value,remote:i.value}),n+=2):(t.push({type:`conflict`,local:r.value,remote:void 0}),n++)}else r.added&&t.push({type:`conflict`,local:void 0,remote:r.value}),n++}return t}async#d(t,n){let r=h.default.dirname(t);m.default.existsSync(r)||m.default.mkdirSync(r,{recursive:!0});try{m.default.writeFileSync(t,n,`utf-8`)}catch(n){e.w.error(`Failed to write connector to file ${e.C(t)}: ${n.message}`),process.exit(1)}}async#f(t,n,r,i,a){let o=(0,v.default)(`Pulling connector ${e.C(t)}@${e.C(i)} from registry...`).start();try{let s=Buffer.from(r).toString(`base64`),c=`${n}/registry/connectors/${t}@${i}${a?`?owner=${encodeURIComponent(a)}`:``}`,l=await fetch(c,{method:`GET`,headers:{Authorization:`Basic ${s}`}});if(o.stop(),l.status===409){a&&(await this.#p(l,t,i),process.exit(1));let r=(await l.json()).availableOwners??[],c=await on(`${t}@${i}`,r);o.text=`Pulling connector ${e.C(t)}@${e.C(i)} from registry...`,o.start();let u=`${n}/registry/connectors/${t}@${i}`,d=await fetch(`${u}?owner=${encodeURIComponent(c)}`,{method:`GET`,headers:{Authorization:`Basic ${s}`}});return o.stop(),d.ok||(await this.#p(d,t,i),process.exit(1)),await d.text()}return l.ok||(await this.#p(l,t,i),process.exit(1)),await l.text()}catch(r){o.stop(),e.w.error(`Failed to pull connector ${e.C(t)}@${e.C(i)} from the registry: ${r.message}`),e.w.log(`Please ensure that the API at ${e.T(n)} is reachable and the API key is valid.`),process.exit(1)}}async#p(t,n,r){switch(t.status){case 401:case 403:e.w.error(`Access denied`),e.w.log(`Please ensure that your API key is valid and has the ${e.C(`connectors:read`)} scope required to pull connectors.`);break;case 404:e.w.error(`Connector ${e.C(n)}@${e.C(r)} was not found in the registry`),await this.#m(n);break;case 429:e.w.error(`Rate limit exceeded`),e.w.log(`Too many requests. Please wait a moment before trying again.`);break;default:await e.x(t,`Failed to pull connector ${e.C(n)}`)}}async#m(t){e.w.info(`To see available versions, check the connector documentation or contact support.`)}};const vn=`https://api.stackone.com`;var yn=class{async execute({profile:t,fileOrDir:n,apiUrl:r,apiKey:a,force:o}={}){if(!t&&!a&&(e.w.error(`Profile or API key is required`),e.w.log(`Please provide a profile using the ${e.C(`--profile`)} option or an API key using the ${e.C(`--api-key`)} option.`),e.w.log(`To create a profile, run ${e.C(`stackone init`)}.`),process.exit(1)),t&&a&&(e.w.error(`Please provide either a profile or an API key, not both`),process.exit(1)),t&&r&&e.w.warn(`Specifying ${e.C(`--api-url`)} with a profile won't have any effect. Using API url from profile.`),t&&!$t(t)){e.w.error(`Configuration profile ${e.C(t)} not found`),e.w.log(`Run ${e.C(`stackone init`)} to create a new configuration profile.\n`);let n=tn();n.length>0&&(e.w.info(`Available configuration profiles:`),n.forEach(t=>{e.w.log(` - ${i.default.blue(t)}`)})),process.exit(1)}let s=t?Qt(t):{apiUrl:r??vn,apiKey:a};s?.apiKey||(e.w.error(`API key is missing`),e.w.log(`Please provide a valid API key in the profile or via the ${e.C(`--api-key`)} option.`),process.exit(1)),n||(e.w.error(`File or directory is required.`),process.exit(1));try{(0,m.statSync)(n)}catch{e.w.error(`File or directory not found: ${i.default.red(n)}`),process.exit(1)}let c=(0,m.statSync)(n),l=s.apiUrl??vn;if(c.isDirectory()){let t=Tn(n),r=0;t.length===0?(e.w.error(`No .s1.yaml connector files found in the directory: ${n}.`),process.exit(1)):(e.w.start(`Found ${t.length} connector(s) file(s). Pushing to registry...`),e.w.log(``));for(let e of t)await this.uploadFile(e,l,s.apiKey,o)&&r++;r===0?e.w.error(`Error while pushing connectors: no files were uploaded`):(e.w.log(``),e.w.info(`Upload completed: ${i.default.green(r)} of ${i.default.blue(t.length)} file(s) uploaded successfully.`)),process.exit(r>0?0:1)}else n.endsWith(`.s1.yaml`)||(e.w.error(`Only ${e.C(`.s1.yaml`)} files are supported for upload`),process.exit(1));let u=await this.uploadFile(n,l,s.apiKey,o);process.exit(u?0:1)}async uploadFile(t,n,r,i){let a=(0,v.default)(`📤 Pushing connector in ${(0,h.basename)(t)}...`).start();try{let o=wn(t);if(!o)return!1;let s=(0,h.basename)(t),c=new FormData,l=new Blob([o],{type:`application/x-yaml`});c.append(`file`,l,s),i&&c.append(`force`,`true`);let u=Buffer.from(r).toString(`base64`),d=await fetch(`${n}/registry/connectors`,{method:`POST`,headers:{Authorization:`Basic ${u}`},body:c});if(a.stop(),!d.ok)return d.status===409||d.status===422?await this.handleVersionConflict(d,t,n,r,i):(await e.x(d,`Failed to push connector in ${e.C(s)} to the registry`),!1);let f=await d.json();return e.w.success(`Successfully uploaded ${e.C(s)} with connector ${e.C(f.provider)}@${e.C(f.version)}`),!0}catch(r){return a.stop(),e.w.error(`Failed to upload file ${e.C(t)}: ${r}`),e.w.log(`Please ensure that the API at ${e.T(n)} is reachable and the API key is valid`),!1}}async handleVersionConflict(t,n,r,i,a){let o=await t.text(),s;try{s=JSON.parse(o)}catch{}let c=D.default.valid(s?.latestVersion);if(!c)return await e.x(new Response(o,{status:t.status,statusText:t.statusText}),`Failed to push connector in ${e.C((0,h.basename)(n))} to the registry`),!1;let l=(0,m.readFileSync)(n,`utf-8`),u=bn(l),d=u?`${e.C(u)}`:``,f=t.status===409?`Version ${d} already exists in the registry. Latest version: ${e.C(c)}`:`Version ${d} is lower than the latest version in the registry. Latest version: ${e.C(c)}`;e.w.error(f);let p=D.default.inc(c,`patch`)??c,g=D.default.inc(c,`minor`)??c,_=D.default.inc(c,`major`)??c,v=await(0,w.select)({message:`How would you like to proceed?`,options:[{value:p,label:`Bump patch version (${p})`},{value:g,label:`Bump minor version (${g})`},{value:_,label:`Bump major version (${_})`},{value:`cancel`,label:`Cancel push`}]});return(0,w.isCancel)(v)||v===`cancel`?((0,w.cancel)(`Push cancelled`),!1):((0,m.writeFileSync)(n,xn(l,v),`utf-8`),e.w.info(`Updated version to ${e.C(v)} in ${(0,h.basename)(n)}`),this.uploadFile(n,r,i,a))}};const bn=e=>e.match(/^\s*version: (\S+)/m)?.[1],xn=(e,t)=>e.replace(/^(\s*version: )\S+/m,`$1${t}`),Sn=e=>{try{let t=(0,T.parseYamlConnector)(e);return t.changelog?.summary?.trim()?null:`has no changelog entry for version ${t.version}`}catch{return null}},Cn=()=>{e.w.log(`Every published version must record what changed. Add an ${e.C(`info.changelog`)} block:`),e.w.log(``),e.w.log(i.default.gray(` info:`)),e.w.log(i.default.gray(` changelog:`)),e.w.log(i.default.gray(` summary: What changed in this version.`)),e.w.log(i.default.gray(` labels: [new-actions] # optional, one of: ${te.ChangelogLabels.join(`, `)}`)),e.w.log(``)},wn=t=>{let n=(0,T.loadConnector)(t),r=(0,T.validateYamlConnector)(n),i=r?.errors??[];if(r.success){let r=Sn(n);if(r){e.w.error(`Connector in ${e.S(t)} ${r}`),Cn();return}return n}else i.length>0?(e.w.error(`Connector in ${e.S(t)} is not valid`),e.y(i,!0)):e.w.error(`Connector in ${e.S(t)} is not valid. Please check the file for errors.`)},Tn=e=>{let t=[],n=(0,m.readdirSync)(e,{withFileTypes:!0});for(let r of n){let n=(0,h.join)(e,r.name);r.isDirectory()?t.push(...Tn(n)):r.name.endsWith(`.s1.yaml`)&&t.push(n)}return t},En=C.z.object({provider_key:C.z.string().optional(),provider_version:C.z.string().optional(),auth_config_key:C.z.string(),environment:C.z.string().default(`production`),organization_id:C.z.string().default(`cli-organization-id`),account_id:C.z.string().default(`cli-account-secure-id`),project_id:C.z.string().default(`cli-project-secure-id`),credentials:C.z.record(C.z.string(),C.z.any()).default({})}),Dn=C.z.record(C.z.string(),C.z.any()),On=C.z.object({path:C.z.record(C.z.string(),C.z.any()).default({}),queryParams:C.z.record(C.z.string(),C.z.any()).default({}),header:C.z.record(C.z.string(),C.z.any()).default({}),body:C.z.record(C.z.string(),C.z.any()).default({})}),kn=`https://api.stackone.com`;var An=class{async execute({connector:t,action:n,actionId:r,account:a,accountId:o,params:s,credentials:c,profile:l,outputFile:u,debug:d,apiUrl:f,apiKey:p,owner:h}={}){if(!l&&!p&&o&&(e.w.error(`Profile or API key is required when providing an account ID`),e.w.log(`Please provide a profile using the ${e.C(`--profile`)} option or an API key using the ${e.C(`--api-key`)} option.`),e.w.log(`To create a profile, run ${e.C(`stackone init`)}.`),process.exit(1)),l&&p&&(e.w.error(`Please provide either a profile or an API key, not both`),process.exit(1)),l&&f&&e.w.warn(`Specifying --api-url with a profile won't have any effect. Using API url from profile.`),l&&!$t(l)){e.w.error(`Configuration profile ${e.C(l)} not found`),e.w.log(`Run ${e.C(`stackone init`)} to create a new configuration profile.\n`);let t=tn();t.length>0&&(e.w.info(`Available configuration profiles:`),t.forEach(t=>{e.w.log(` - ${i.default.blue(t)}`)})),process.exit(1)}let g=l?Qt(l):{apiUrl:f??kn,apiKey:p};(0,C.isMissing)(a)&&(0,C.isMissing)(o)&&(e.w.error(`A valid account or account ID is required to run an action`),process.exit(1));let _;if((0,C.notMissing)(t))if(this.#a(t)){!l&&!p&&(e.w.error(`Profile or API key is required when using a connector identifier`),e.w.log(`Please provide a profile using the ${e.C(`--profile`)} option or an API key using the ${e.C(`--api-key`)} option.`),e.w.log(`Run ${e.C(`stackone init`)} to create a new configuration profile.`),process.exit(1));let n=this.#o(t);_=await this.#s(n,g?.apiUrl??kn,g?.apiKey,h)}else _=this.#e(t);else (0,C.notMissing)(o)&&(_=await this.#c(o,g?.apiUrl??kn,g?.apiKey));let v=(0,C.notMissing)(n)?this.#r(n,t):_;(0,C.isMissing)(v)&&(e.w.error(`A valid connector is required to run an action.`),process.exit(1));let y=(0,C.notMissing)(v?.actions)?Object.keys(v?.actions).length:0,b=(0,C.notMissing)(v?.actions)?Object.keys(v.actions)[y-1]:void 0,x=(0,C.notMissing)(b)?v?.actions?.[b]?.id:void 0,S=((0,C.notMissing)(r)&&!r?.startsWith(`${v.key}_`)?`${v.key}_${r}`:r)??x;(0,C.isMissing)(S)&&(e.w.error(`A valid action ID is required to run an action`),process.exit(1));let w=(0,C.notMissing)(o)?await this.#l(o,g?.apiUrl??kn,g?.apiKey):{},T=(0,C.notMissing)(a)?this.#i(a,v.key??`unknown`,v.version??`unknown`):void 0,E=(0,C.notMissing)(c)?this.#u(c):{},ee={...w,...T,credentials:{...w.credentials??{},...E}};(0,C.isMissing)(ee)&&(e.w.error(`A valid account data is required to run an action.`),process.exit(1));let te=v.actions?.[S];(0,C.isMissing)(te)&&(e.w.error(`Action ID ${e.C(S)} not found in the connector ${e.C(v.key)}@${e.C(v.version)}.`),process.exit(1));let D=(0,C.notMissing)(s)?this.#d(s,S):{path:{},queryParams:{},header:{},body:{}},O=Date.now(),k=await this.#f({connector:v,actionId:S,account:ee,queryParams:{...D.queryParams,...d?{debug:`true`}:{}},pathParams:D.path,body:D.body,headers:D.header}),A=Date.now()-O;if((0,C.notMissing)(u))try{m.default.writeFileSync(u,JSON.stringify(k.output,null,2),`utf-8`),e.w.info(`Output written to file: ${u}`)}catch(t){e.w.error(`Failed to write output to file ${u}: ${t.message}`),process.exit(1)}else e.w.log(`\n${i.default.blue.inverse(` ACTION OUTPUT `)}`),e.b(k.output);e.w.log(``),e.w.info(`Action ${e.C(S)} from connector ${e.C(v?.key)}@${e.C(v?.version)} finished in ${i.default.yellowBright((A/1e3).toFixed(2))} seconds.`),process.exit(0)}#e=e=>{let t=e;try{t=(0,T.loadConnector)(e)}catch{}return t?this.#n(t):void 0};#t=t=>{try{return(0,T.loadConnector)(t)}catch(n){e.w.error(`Failed to load connector file from ${e.C(t)}: ${n.message}`),process.exit(1)}};#n=t=>{let n=(0,T.validateYamlConnector)(t),r=n?.errors??[];if(n.success)return n.connector||(e.w.error(`Failed to load connector.`),process.exit(1)),n.connector;r.length>0?(e.w.error(`Connector is not valid`),e.y(r,!0),process.exit(1)):(e.w.error(`Connector is not valid. Please check the file for errors.`),process.exit(1))};#r=(t,n)=>{let r=t;try{r=m.default.readFileSync(t,`utf-8`)}catch{}(0,C.isMissing)(n)&&(e.w.error(`A valid connector is required to load an action.`),process.exit(1));let i=`${this.#t(n)} - ${r.split(`
173
173
  `).map((e,t)=>t===0?e:` ${e}`).join(`
174
- `)}`;return this.#n(i)};#i=(t,n,r)=>{let i=t;try{i=m.default.readFileSync(t,`utf-8`)}catch{}try{let e=Tn.parse(JSON.parse(i));return{providerKey:n,providerVersion:r,authConfigKey:e.auth_config_key,environment:e.environment,organizationId:e.organization_id,secureId:e.account_id,projectSecureId:e.project_id}}catch(t){let n=[];try{n=JSON.parse(t.message)}catch{}e.w.error(`Failed to parse account information`),e.y(n,!1),n.length===0&&e.w.log(t.message),process.exit(1)}};#a=e=>!e.includes(`/`)&&!e.includes(`\\`)&&!e.endsWith(`.yaml`)&&!e.endsWith(`.yml`)?e.includes(`@`)?e.split(`@`).length===2:!0:!1;#o=e=>e.includes(`@`)?e:`${e}@latest`;#s=async(t,n,r,i)=>{((0,C.isMissing)(t)||(0,C.isMissing)(n)||(0,C.isMissing)(r))&&(e.w.error(`Connector identifier, API URL, and API key are required to fetch connector from registry.`),process.exit(1));let a=(0,v.default)();try{a.text=`Fetching connector ${e.C(t)} from registry...`,a.start();let o=Buffer.from(r).toString(`base64`),s=i?`?owner=${encodeURIComponent(i)}`:``,c=await fetch(`${n}/registry/connectors/${t}${s}`,{method:`GET`,headers:{Authorization:`Basic ${o}`}});if(a.stop(),c.status===409){i&&(await e.x(c,`Failed to fetch connector ${e.C(t)} from registry`),process.exit(1));let r=await an(t,(await c.json()).availableOwners??[]);a.text=`Fetching connector ${e.C(t)} from registry...`,a.start();let s=await fetch(`${n}/registry/connectors/${t}?owner=${encodeURIComponent(r)}`,{method:`GET`,headers:{Authorization:`Basic ${o}`}});a.stop(),s.ok||(await e.x(s,`Failed to fetch connector ${e.C(t)} from registry`),process.exit(1));let l=await s.text(),u=this.#n(l);return e.w.success(`Fetched connector ${e.C(u.key)}@${e.C(u.version)} from registry`),u}c.ok||(await e.x(c,`Failed to fetch connector ${e.C(t)} from registry`),process.exit(1));let l=await c.text(),u=this.#n(l);return e.w.success(`Fetched connector ${e.C(u.key)}@${e.C(u.version)} from registry`),u}catch(r){a.stop(),e.w.error(`Failed to fetch connector ${e.C(t)} from registry: ${r.message}`),e.w.log(`Please ensure that the API at ${e.T(n)} is reachable and the API key is valid`),process.exit(1)}};#c=async(t,n,r)=>{((0,C.isMissing)(t)||(0,C.isMissing)(n)||(0,C.isMissing)(r))&&(e.w.error(`Account ID, API URL, and API key are required to fetch connector`),process.exit(1));let i=(0,v.default)();try{i.text=`Fetching connector for account ${e.C(t)} from API...`,i.start();let a=Buffer.from(r).toString(`base64`),o=await fetch(`${n}/accounts/${t}/connector`,{method:`GET`,headers:{Authorization:`Basic ${a}`}});i.stop(),o.ok||(await e.x(o,`Failed to fetch connector`),process.exit(1));let s=await o.text(),c=this.#n(s);return e.w.success(`Fetched connector ${e.C(c.key)}@${e.C(c.version)} for account ${e.C(t)}`),c}catch(t){i.stop(),e.w.error(`Failed to fetch connector: ${t.message}`),e.w.log(`Please ensure that the API at ${e.T(n)} is reachable and the API key is valid`),process.exit(1)}};#l=async(t,n,r)=>{((0,C.isMissing)(t)||(0,C.isMissing)(n)||(0,C.isMissing)(r))&&(e.w.error(`Account ID, API URL, and API key are required to fetch account information.`),process.exit(1));let i=(0,v.default)();try{i.text=`Fetching account ${e.C(t)} information from API...`,i.start();let a=Buffer.from(r).toString(`base64`),o=await fetch(`${n}/accounts/${t}/credentials`,{method:`GET`,headers:{Authorization:`Basic ${a}`}});i.stop(),o.ok||(await e.x(o,`Failed to fetch account ${e.C(t)} information`),process.exit(1));let s=await o.json();return e.w.success(`Fetched account ${e.C(t)} information from project ${e.C(s.project_id)}`),{providerKey:s.provider_key,providerVersion:s.provider_version,authConfigKey:s.auth_config_key,environment:s.environment,organizationId:s.organization_id,secureId:s.account_id,projectSecureId:s.project_id,credentials:s.credentials}}catch(r){i.stop(),e.w.error(`Failed to fetch account ${e.C(t)} information: ${r.message}`),e.w.log(`Please ensure that the API at ${e.T(n)} is reachable and the API key is valid`),process.exit(1)}};#u=t=>{let n=t;try{n=m.default.readFileSync(t,`utf-8`)}catch{}try{return En.parse(JSON.parse(n))}catch(t){let n=[];try{n=JSON.parse(t.message)}catch{}e.w.error(`Failed to parse credentials`),e.y(n,!1),n.length===0&&e.w.log(t.message),process.exit(1)}};#d=(t,n)=>{let r=t;try{r=m.default.readFileSync(t,`utf-8`)}catch{}try{return Dn.parse(JSON.parse(r))}catch(t){let r=[];try{r=JSON.parse(t.message)}catch{}e.w.error(`Invalid parameters for action ${e.C(n)}.`),e.y(r,!1),r.length===0&&e.w.log(t.message),process.exit(1)}};async#f({connector:t,actionId:n,account:r,pathParams:a={},queryParams:o={},body:s={},headers:c={}}){try{let l=await(0,T.runAction)({mode:`action_id`,actionId:n,account:r,connector:t,pathParams:a,queryParams:o,body:s,headers:c,getHttpClient:async()=>new O.HttpClient});if(l.response?.successful){let e={...this.#p(o,l.steps),...(0,C.isObject)(l.outputs)?l.outputs:{data:l.outputs}};return{statusCode:l.response?.statusCode,output:e}}else{let r=l.response?.message??`An error occurred while processing the request`;e.w.error(`Action ID ${e.C(n)} from connector ${e.C(t.key)}@${e.C(t.version)} failed with status ${l.response?.statusCode}: ${r}`);let a={...this.#p(o,l.steps)};Object.keys(a).length>0&&(e.w.log(`${i.default.yellow.inverse(` EXECUTION DETAILS `)}`),e.b(a)),process.exit(1)}}catch(e){this.#m(e)}}#p(e,t){return e?.debug===`true`?{debug:{steps:t}}:{}}#m(t){let n=t;switch((0,C.isMissing)(n.errorType)&&(e.w.error(`An unknown error occurred`),e.w.log(`${t instanceof Error?t.message:String(t)}`),process.exit(1)),n.errorType){case`MISSING_ACTION_ERROR`:e.w.error(`The specified action was not found: ${n.message}`);break;case`INVALID_ACTION_INPUTS_ERROR`:let t=n;e.w.error(`Invalid action inputs`),e.y(t.validationErrors,!1);break;case`INVALID_CURSOR_ERROR`:e.w.error(`Invalid cursor: ${n.message}`);break;default:e.w.error(`An error occurred: ${n.message}`)}process.exit(1)}};const An=(0,k.promisify)(f.exec);var jn=class{constructor(){this.packageName=`@stackone/cli`,this.spinner=(0,v.default)(),this.currentVersion=K()}async execute(t={}){this.spinner.text=`Checking for updates...`,this.spinner.start();try{let n=await this.getLatestVersion();this.spinner.stop(),n||(e.w.error(`Failed to check for updates`),process.exit(1)),this.isNewerVersion(n,this.currentVersion)?(e.w.box(`New version available: ${i.default.yellow(this.currentVersion)} → ${i.default.green(n)}`),await this.performUpdate(n)):t.force?(e.w.warn(`No updates available, but forcing reinstall...`),await this.performUpdate(n)):e.w.success(`You are already on the latest version (${this.currentVersion})`),process.exit(0)}catch(t){this.spinner.stop(),e.w.error(`Error while trying to update StackOne CLI: ${t?.message??`Unknown error`}`),process.exit(1)}}async getLatestVersion(){try{let{stdout:e}=await An(`npm view ${this.packageName} version`,{encoding:`utf-8`});return e.trim()}catch{return null}}isNewerVersion(e,t){return D.default.gt(e,t)}async performUpdate(t){this.spinner.text=`Updating to latest version (${e.C(t)})...`,this.spinner.start();let n=`npm install -g ${this.packageName}@latest`;try{await An(n,{encoding:`utf-8`}),this.spinner.stop(),e.w.success(`StackOne CLI updated successfully to latest version (${e.C(t)})`)}catch{throw this.spinner.stop(),Error(`Failed to install update. Please try manually: ${n}`)}}};const Mn=e=>e===null?!0:Object.values(e).some(e=>e!==null),Nn=()=>{e.w.log(`${i.default.gray.inverse(` CONNECTORS VALIDATION `)} ${i.default.yellow.inverse(` WATCH MODE `)}\n`)};var Pn=class{async execute(t){let{watchMode:n,fileOrDir:r}=t,a=(0,v.default)(`Watching for file changes... ${i.default.gray(`(press "q" to quit)`)}`);if(!r)return;let o=(0,h.resolve)(r);try{await(0,A.stat)(o)}catch{e.w.error(`The specified path does not exist: ${o}\n`),process.exit(1)}if(n){e.v();let t={},{watch:n}=await import(`chokidar`),r=(await import(`readline`)).createInterface({input:process.stdin,output:process.stdout});process.stdin.setRawMode(!0),process.stdin.resume(),process.stdin.setEncoding(`utf8`);let s=()=>{l.close(),a.stop(),r.close(),e.w.log(i.default.grey(`
175
- Exiting watch mode...`)),process.exit(0)};Nn(),e.w.start(`Validating connectors...`);let c=await Rn(o);t=Fn(t,c||{}),In(t,o),a.start();let l=n(o,{persistent:!0,ignoreInitial:!0}),u=async n=>{if(!n.endsWith(`.s1.yaml`)&&!n.endsWith(`s1.partial.yaml`))return;let r=n.endsWith(`s1.partial.yaml`)?await Bn(n):[n];if(!(!r||r.length===0)){e.v(),a.stop(),Nn(),e.w.log(i.default.gray(`File change detected: ${n}`)),e.w.start(`Validating connectors...`);for(let e of r){let n=await Rn(e);t=Fn(t,n||{})}In(t,o),a.start()}};l.on(`change`,async e=>await u(e)),process.stdin.on(`data`,e=>{e.toString()===`q`&&s()}),process.on(`SIGINT`,()=>{s()})}else{let t=await Rn(o,e.w);process.exit(Mn(t)?1:0)}}};const Fn=(e,t)=>{for(let[n,r]of Object.entries(t))e[n]=r;return e},In=(t,n)=>{e.v(),Nn();let r=0,a=0;for(let[n,i]of Object.entries(t))i===null?r++:(e.w?.error(`Connector ${e.C(n)} is not valid`),e.y(i,!0),a++);e.w.log(``),e.w.log(i.default.blue.inverse(` Validation Summary `)),e.w.log(`Connectors path: ${e.C(n)}`),e.w.log(`${r===0?i.default.red(`0`):i.default.green(r)} valid, ${a===0?i.default.green(`0`):i.default.red(a)} invalid connectors\n`)},Ln=async e=>{let t=[],n=await(0,A.readdir)(e);for(let r of n){let n=(0,h.join)(e,r),i=await(0,A.stat)(n);i.isDirectory()?t.push(...await Ln(n)):i.isFile()&&r.endsWith(`.s1.yaml`)&&t.push(n)}return t},Rn=async(t,n)=>{let r=await(0,A.stat)(t),a={};if(r.isDirectory()){let r=await Ln(t);if(r.length===0)return n?.error(`No StackOne connector found in ${e.S(t)}`),n?.log(`Connector files need to have the extension ${e.C(`*.s1.yaml`)}`),null;let o=0,s=0;for(let e of r){let t=await zn(e,n);t===null?o++:(n?.log(``),s++),a[e]=t}return n?.log(``),n?.log(i.default.blue.inverse(` Validation Summary `)),n?.log(`${o===0?i.default.red(`0`):i.default.green(o)} valid, ${s===0?i.default.green(`0`):i.default.red(s)} invalid connectors`),a}else if(r.isFile()&&t.endsWith(`s1.yaml`))return a[t]=await zn(t,n),a;else if(r.isFile()&&t.endsWith(`partial.yaml`)){n?.error(`Partial connector files cannot be validated directly`),n?.log(`The file ${e.S(t)} is a partial connector file.`);let r=await Bn(t);return r&&r?.length>0&&n?.log(`Did you mean ${e.C(r[0])}?`),null}else return n?.error(`No StackOne connector found in ${e.S(t)}`),n?.log(`Connector files need to have the extension ${e.C(`*.s1.yaml`)}`),null},zn=async(t,n)=>{let r=(0,T.validateYamlConnector)((0,T.loadConnector)(t)),i=r?.errors??[];if(r.success){let r=t.split(`/`).pop()||t;return n?.success(`Connector ${e.C(r)} is valid!`),null}else if(i.length>0)return n?.error(`Connector ${e.C(t)} is not valid`),n&&e.y(i,!0),i;else return n?.error(`Connector ${e.C(t)} is not valid. Please check the file for errors`),[]},Bn=async e=>{let t=(0,h.dirname)(e);try{return(await(0,A.readdir)(t)).filter(e=>e.endsWith(`.s1.yaml`))?.map(e=>(0,h.join)(t,e))}catch{}},Vn=`https://ai-telemetry.stackone.com`,Hn=`https://ai-telemetry.stackone-dev.com`;function Un(e){if(!e)return!1;try{let{hostname:t}=new URL(e);return t===`stackone-dev.com`||t.endsWith(`.stackone-dev.com`)}catch{return!1}}function Wn(){return process.env.AI_TELEMETRY_URL?process.env.AI_TELEMETRY_URL:[process.env.AUTH_SERVER_URL,process.env.STACKONE_API_URL].some(Un)?`https://ai-telemetry.stackone-dev.com`:`https://ai-telemetry.stackone.com`}function Gn(){let e=process.env.STACKONE_AGENT_TOKEN,t=process.env.LANGSMITH_PROJECT||`stackone-agent-cli`;if(process.env.AI_TELEMETRY_URL=Wn(),e)try{(0,o.initAgentTelemetry)({apiKey:e,projectName:t}),process.env.VERBOSE&&console.log(`[Telemetry] Initialized for project:`,t)}catch(e){process.env.VERBOSE&&console.error(`[Telemetry] Failed to initialize:`,e)}}const Kn=`@stackone/cli`,qn=2880*60*1e3,Jn=(0,l.join)((0,c.homedir)(),`.stackone`),Yn=(0,l.join)(Jn,`version-check.json`),Xn=(e=!1)=>{let t=er(),n=Date.now();if(e||!t||n-t.lastCheckTime>1728e5){let e=Zn();e&&Qn(e)&&$n(e),tr({lastCheckTime:n})}},Zn=()=>{try{return(0,f.execSync)(`npm view @stackone/cli version`,{encoding:`utf-8`,stdio:[`pipe`,`pipe`,`pipe`],timeout:15e3}).trim()}catch{return null}},Qn=e=>{try{let t=K();return D.default.gt(e,t)}catch{return!1}},$n=t=>{let n=K(),r=`Update available: ${i.default.dim(n)} → ${i.default.green(t)}`,a=`\n\nRun ${i.default.cyan(`stackone update`)} to update`;e.w.box(r,a)},er=()=>{try{if(!(0,s.existsSync)(Yn))return null;let e=(0,s.readFileSync)(Yn,`utf-8`);return JSON.parse(e)}catch{return null}},tr=e=>{try{(0,s.existsSync)(Jn)||(0,s.mkdirSync)(Jn,{recursive:!0}),(0,s.writeFileSync)(Yn,JSON.stringify(e,null,2),`utf-8`)}catch{}};var nr=class{constructor(e=new a.Command,t=K()){this.program=e,this.version=t,Gn(),this.setupProgram(),this.registerCommands()}setupProgram(){this.program.name(`stackone`).description(`StackOne CLI`).version(this.version,`-v, --version`)}registerCommands(){let t=new dn,n=new vn,r=new gn,o=new nn,s=new sn,c=new Pn,l=new Ye,u=new Wt,d=new Pe,f=new Ne,p=new Ze,m=new Gt,h=new Jt,g=new kn,_=new jn;this.program.configureOutput({writeOut:e=>process.stdout.write(e),writeErr:e=>process.stderr.write(e),outputError:(e,t)=>{t(i.default.red(e))}}),this.program.command(`init`).option(`-e, --env <environment>`,`Specify the environment for the configuration profile`).description(`Initialize & create a StackOne CLI configuration profile`).action(e=>{t.execute({environment:e.env})}),this.program.command(`push`).option(`-p, --profile <label>`,`Configuration profile to use`).option(`--api-url <api url>`,`API URL`).option(`--api-key <api key>`,`API Key`).option(`--force`,`Force push the connector, bypassing version conflict checks`).addArgument(new a.Argument(`<path>`,`Connector file or directory to push`)).description(`Push a connector to the StackOne registry`).action((e,t)=>{n.execute({profile:t.profile,fileOrDir:e,apiUrl:t.apiUrl,apiKey:t.apiKey,force:t.force})}),this.program.command(`drop`).option(`-p, --profile <label>`,`Configuration profile to use`).option(`--api-url <api url>`,`API URL`).option(`--api-key <api key>`,`API Key`).addArgument(new a.Argument(`<connector>`,`Connector identifier in format provider_key@version`)).description(`Drop a connector from the StackOne registry`).action((e,t)=>{o.execute({profile:t.profile,connector:e,apiUrl:t.apiUrl,apiKey:t.apiKey})}),this.program.command(`get`).option(`-p, --profile <label>`,`Configuration profile to use`).option(`--api-url <api url>`,`API URL`).option(`--api-key <api key>`,`API Key`).option(`-c, --connector <connector>`,`Connector identifier in format provider_key@version or provider_key (defaults to latest)`).option(`--account-id <account-id>`,`Account ID to fetch connector from`).option(`-f, --format <format>`,`Output format: yaml or json (default: yaml)`,`yaml`).option(`-o, --output-file <output-file>`,`File to write the output to`).option(`--builtin`,`Use the builtin (StackOne) version of the connector`).option(`--custom`,`Use the custom (organization) version of the connector`).option(`--owner <owner>`,`Owner to use for disambiguating connector versions`).description(`Get a connector from the StackOne registry`).action(t=>{[t.builtin,t.custom,t.owner].filter(Boolean).length>1&&(e.w.error(`--builtin, --custom, and --owner are mutually exclusive. Please provide only one.`),process.exit(1)),s.execute({profile:t.profile,connector:t.connector,accountId:t.accountId,format:t.format,outputFile:t.outputFile,apiUrl:t.apiUrl,apiKey:t.apiKey,owner:t.builtin?`builtin`:t.custom?`custom`:t.owner})}),this.program.command(`pull`).option(`-c, --connector <connector>`,`Connector identifier in format provider_key@version or provider_key`).option(`-p, --profile <label>`,`Configuration profile to use`).option(`--api-url <api url>`,`API URL`).option(`--api-key <api key>`,`API Key`).option(`-o, --output <path>`,`Output directory for the connectors files (default: ./connectors)`).option(`--builtin`,`Use the builtin (StackOne) version of the connector`).option(`--custom`,`Use the custom (organization) version of the connector`).option(`--owner <owner>`,`Owner to use for disambiguating connector versions`).description(`Pull a connector configuration from StackOne registry to local filesystem`).action(t=>{[t.builtin,t.custom,t.owner].filter(Boolean).length>1&&(e.w.error(`--builtin, --custom, and --owner are mutually exclusive. Please provide only one.`),process.exit(1)),r.execute({profile:t.profile,connector:t.connector,outputPath:t.output,apiUrl:t.apiUrl,apiKey:t.apiKey,owner:t.builtin?`builtin`:t.custom?`custom`:t.owner})}),this.program.command(`validate`).option(`-w, --watch`,`Run in watch mode`).addArgument(new a.Argument(`<path>`,`Connector file or directory with connectors to validate`)).description(`Validate a StackOne connector`).action((e,t)=>{c.execute({watchMode:t.watch,fileOrDir:e})}),this.program.command(`run`).option(`--connector <connector>`,`Connector file, inline YAML, or identifier (provider_key@version or provider_key for latest)`).option(`--action <action>`,`Action to execute on the connector (path to file or inline string action code)`).option(`--action-id <action-id>`,`Action ID to execute on the connector`).option(`--account <account>`,`Account details to use for running the connector (path to file or inline string account data)`).option(`--account-id <account-id>`,`Account ID to use for running the connector against (fetches connector from API if --connector not provided)`).option(`--params <params>`,`Action parameters (path to file or inline string with JSON parameters)`).option(`--credentials <credentials>`,`Credentials to use (path to file or inline string with JSON credentials)`).option(`-p, --profile <label>`,`Configuration profile to use`).option(`--api-url <api url>`,`API URL`).option(`--api-key <api key>`,`API Key`).option(`-o, --output-file <output-file>`,`File to write the output to`).option(`-d, --debug`,`Enables debug mode to include more details in the action execution output`).option(`--builtin`,`Use the builtin (StackOne) version of the connector`).option(`--custom`,`Use the custom (organization) version of the connector`).option(`--owner <owner>`,`Owner to use for disambiguating connector versions`).description(`Run a connector action`).action(t=>{[t.builtin,t.custom,t.owner].filter(Boolean).length>1&&(e.w.error(`--builtin, --custom, and --owner are mutually exclusive. Please provide only one.`),process.exit(1)),g.execute({connector:t.connector,action:t.action,actionId:t.actionId,account:t.account,accountId:t.accountId,params:t.params,credentials:t.credentials,profile:t.profile,outputFile:t.outputFile,debug:t.debug,apiUrl:t.apiUrl,apiKey:t.apiKey,owner:t.builtin?`builtin`:t.custom?`custom`:t.owner})});let v=this.program.command(`agent`).description(`StackOne agent commands`);v.command(`setup`).option(`-g, --global`,`Global only: auth + MCP server (no connector skills/guide)`).option(`-l, --local`,`Local: auth + .mcp.json + connector skills (.claude/) and guide (CLAUDE.md)`).option(`--path <dir>`,`Target project path for local setup (defaults to the current directory)`).option(`--legacy`,`Use email/password login instead of browser-based auth`).option(`--email <email>`,`Email for legacy login (or set STACKONE_EMAIL); requires --legacy`).option(`--password <password>`,`Password for legacy login (or set STACKONE_PASSWORD); requires --legacy. Prefer --password-stdin`).option(`--password-stdin`,`Read password for legacy login from stdin; requires --legacy`).description(`Set up the StackOne agent — prompts for global vs local when neither flag is given`).action(async t=>{t.global&&t.local&&(e.w.error(`--global and --local are mutually exclusive. Please provide only one.`),process.exit(1));let n=t.email!==void 0,r=t.password!==void 0,a=t.passwordStdin===!0;r&&a&&(e.w.error(`--password and --password-stdin are mutually exclusive. Please provide only one.`),process.exit(1));let o=n||r||a;o&&!t.legacy&&(e.w.error(`--email, --password, and --password-stdin require --legacy.`),process.exit(1)),n&&t.email.trim()===``&&(e.w.error(`--email cannot be empty.`),process.exit(1)),r&&t.password===``&&(e.w.error(`--password cannot be empty.`),process.exit(1)),a&&(n||process.env.STACKONE_EMAIL?.trim()||(e.w.error(`--password-stdin requires --email or STACKONE_EMAIL (stdin is consumed for the password, so email cannot be prompted).`),process.exit(1)));let s={email:t.email,password:t.password,passwordFromStdin:a},c=!!process.stdin.isTTY;if(c&&!t.legacy&&!o){let e=await Ut({initialMode:t.global?`global`:t.local?`local`:null,pathFlag:t.path});process.exit(e.status===`error`?1:0)}let d=c&&!o;!t.global&&!t.local&&!d&&e.w.log(i.default.dim(`No interactive terminal detected — defaulting to global setup. Run in a terminal for the prompt, or pass --local (with --path) / --global.`));let f=tt(t.global,t.local,d);if(f===null&&(f=await Bt()),f===`local`){let e=nt(t.path,d);e===null&&(e=await Ht(process.cwd())),await u.execute({legacy:!!t.legacy,credentials:s,targetPath:e})}else await l.execute({legacy:!!t.legacy,credentials:s})}),v.command(`cleanup`).description(`Remove all API keys and credentials from configurations`).action(()=>{d.execute()}),v.command(`run`).description(`Run the agent once with a prompt (non-interactive)`).argument(`<prompt>`,`What to do`).option(`-m, --mode <mode>`,`Mode: build, test, or research`,`build`).option(`--max-turns <n>`,`Max agent turns`,`25`).option(`-v, --verbose`,`Verbose output`).action(async(t,n)=>{let r=[`build`,`test`,`research`],a=n.mode??`build`;r.includes(a)||(e.w.error(`${i.default.red(`Invalid mode:`)} ${i.default.white(a)}. Valid modes are: ${r.join(`, `)}.`),process.exit(1));let o=n.maxTurns?parseInt(String(n.maxTurns),10):void 0;await p.execute({prompt:String(t),mode:a,maxTurns:o!==void 0&&!isNaN(o)?o:void 0,verbose:n.verbose})}),v.command(`skills`).description(`List available agent skills and optional recommendations by mode`).option(`-m, --mode <mode>`,`Show skills recommended for this mode`).action(async e=>{await m.execute({mode:e.mode})}),v.command(`sync`).description(`Sync the connector-building skills + guide into this project (.claude/ + CLAUDE.md)`).option(`--check`,`Report drift and exit non-zero instead of writing (CI guard)`).option(`--plugin-dir <path>`,`Override the agent-harness plugin dir (e.g. point at a checkout in CI/benchmarks)`).action(async e=>{await h.execute({check:!!e.check,pluginDir:e.pluginDir})}),v.command(`chat`).option(`-m, --mode <mode>`,`Mode: build, test, or research`,`build`).option(`-c, --connector <name>`,`Connector name`).option(`-a, --action <name>`,`Action name`).option(`-g, --goal <goal>`,`Initial goal/message`).option(`-t, --temperature <number>`,`Temperature (0-1, default: 0.5)`,parseFloat).option(`-v, --verbose`,`Enable verbose logging`).description(`Start an interactive chat session with the agent (use /commands in chat)`).action(async t=>{let n=[`build`,`test`,`research`];t.mode&&!n.includes(t.mode)&&(e.w.error(`❌ Error: Invalid mode "${t.mode}". Must be one of: ${n.join(`, `)}`),process.exit(1)),t.temperature!==void 0&&(isNaN(t.temperature)&&(e.w.error(`❌ Error: Temperature must be a valid number`),process.exit(1)),(t.temperature<0||t.temperature>1)&&(e.w.error(`❌ Error: Temperature must be between 0 and 1`),process.exit(1))),f.execute({mode:t.mode,connector:t.connector,action:t.action,goal:t.goal,temperature:t.temperature,verbose:t.verbose})}),this.program.command(`update`).option(`-f, --force`,`Force reinstall even if already on latest version`).description(`Update the CLI to the latest version`).action(e=>{_.execute({force:e.force})}),this.program.command(`version`).description(`Show version information`).action(async()=>{e.w.log(`${i.default.inverse.greenBright(`StackOne`)} ${i.default.grey(`CLI`)} ${i.default.whiteBright(this.version)}`),Xn(!0),process.exit(0)})}run(){process.argv.includes(`version`)||Xn(),this.program.parse(process.argv)}};Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return nr}});
174
+ `)}`;return this.#n(i)};#i=(t,n,r)=>{let i=t;try{i=m.default.readFileSync(t,`utf-8`)}catch{}try{let e=En.parse(JSON.parse(i));return{providerKey:n,providerVersion:r,authConfigKey:e.auth_config_key,environment:e.environment,organizationId:e.organization_id,secureId:e.account_id,projectSecureId:e.project_id}}catch(t){let n=[];try{n=JSON.parse(t.message)}catch{}e.w.error(`Failed to parse account information`),e.y(n,!1),n.length===0&&e.w.log(t.message),process.exit(1)}};#a=e=>!e.includes(`/`)&&!e.includes(`\\`)&&!e.endsWith(`.yaml`)&&!e.endsWith(`.yml`)?e.includes(`@`)?e.split(`@`).length===2:!0:!1;#o=e=>e.includes(`@`)?e:`${e}@latest`;#s=async(t,n,r,i)=>{((0,C.isMissing)(t)||(0,C.isMissing)(n)||(0,C.isMissing)(r))&&(e.w.error(`Connector identifier, API URL, and API key are required to fetch connector from registry.`),process.exit(1));let a=(0,v.default)();try{a.text=`Fetching connector ${e.C(t)} from registry...`,a.start();let o=Buffer.from(r).toString(`base64`),s=i?`?owner=${encodeURIComponent(i)}`:``,c=await fetch(`${n}/registry/connectors/${t}${s}`,{method:`GET`,headers:{Authorization:`Basic ${o}`}});if(a.stop(),c.status===409){i&&(await e.x(c,`Failed to fetch connector ${e.C(t)} from registry`),process.exit(1));let r=await on(t,(await c.json()).availableOwners??[]);a.text=`Fetching connector ${e.C(t)} from registry...`,a.start();let s=await fetch(`${n}/registry/connectors/${t}?owner=${encodeURIComponent(r)}`,{method:`GET`,headers:{Authorization:`Basic ${o}`}});a.stop(),s.ok||(await e.x(s,`Failed to fetch connector ${e.C(t)} from registry`),process.exit(1));let l=await s.text(),u=this.#n(l);return e.w.success(`Fetched connector ${e.C(u.key)}@${e.C(u.version)} from registry`),u}c.ok||(await e.x(c,`Failed to fetch connector ${e.C(t)} from registry`),process.exit(1));let l=await c.text(),u=this.#n(l);return e.w.success(`Fetched connector ${e.C(u.key)}@${e.C(u.version)} from registry`),u}catch(r){a.stop(),e.w.error(`Failed to fetch connector ${e.C(t)} from registry: ${r.message}`),e.w.log(`Please ensure that the API at ${e.T(n)} is reachable and the API key is valid`),process.exit(1)}};#c=async(t,n,r)=>{((0,C.isMissing)(t)||(0,C.isMissing)(n)||(0,C.isMissing)(r))&&(e.w.error(`Account ID, API URL, and API key are required to fetch connector`),process.exit(1));let i=(0,v.default)();try{i.text=`Fetching connector for account ${e.C(t)} from API...`,i.start();let a=Buffer.from(r).toString(`base64`),o=await fetch(`${n}/accounts/${t}/connector`,{method:`GET`,headers:{Authorization:`Basic ${a}`}});i.stop(),o.ok||(await e.x(o,`Failed to fetch connector`),process.exit(1));let s=await o.text(),c=this.#n(s);return e.w.success(`Fetched connector ${e.C(c.key)}@${e.C(c.version)} for account ${e.C(t)}`),c}catch(t){i.stop(),e.w.error(`Failed to fetch connector: ${t.message}`),e.w.log(`Please ensure that the API at ${e.T(n)} is reachable and the API key is valid`),process.exit(1)}};#l=async(t,n,r)=>{((0,C.isMissing)(t)||(0,C.isMissing)(n)||(0,C.isMissing)(r))&&(e.w.error(`Account ID, API URL, and API key are required to fetch account information.`),process.exit(1));let i=(0,v.default)();try{i.text=`Fetching account ${e.C(t)} information from API...`,i.start();let a=Buffer.from(r).toString(`base64`),o=await fetch(`${n}/accounts/${t}/credentials`,{method:`GET`,headers:{Authorization:`Basic ${a}`}});i.stop(),o.ok||(await e.x(o,`Failed to fetch account ${e.C(t)} information`),process.exit(1));let s=await o.json();return e.w.success(`Fetched account ${e.C(t)} information from project ${e.C(s.project_id)}`),{providerKey:s.provider_key,providerVersion:s.provider_version,authConfigKey:s.auth_config_key,environment:s.environment,organizationId:s.organization_id,secureId:s.account_id,projectSecureId:s.project_id,credentials:s.credentials}}catch(r){i.stop(),e.w.error(`Failed to fetch account ${e.C(t)} information: ${r.message}`),e.w.log(`Please ensure that the API at ${e.T(n)} is reachable and the API key is valid`),process.exit(1)}};#u=t=>{let n=t;try{n=m.default.readFileSync(t,`utf-8`)}catch{}try{return Dn.parse(JSON.parse(n))}catch(t){let n=[];try{n=JSON.parse(t.message)}catch{}e.w.error(`Failed to parse credentials`),e.y(n,!1),n.length===0&&e.w.log(t.message),process.exit(1)}};#d=(t,n)=>{let r=t;try{r=m.default.readFileSync(t,`utf-8`)}catch{}try{return On.parse(JSON.parse(r))}catch(t){let r=[];try{r=JSON.parse(t.message)}catch{}e.w.error(`Invalid parameters for action ${e.C(n)}.`),e.y(r,!1),r.length===0&&e.w.log(t.message),process.exit(1)}};async#f({connector:t,actionId:n,account:r,pathParams:a={},queryParams:o={},body:s={},headers:c={}}){try{let l=await(0,T.runAction)({mode:`action_id`,actionId:n,account:r,connector:t,pathParams:a,queryParams:o,body:s,headers:c,getHttpClient:async()=>new O.HttpClient});if(l.response?.successful){let e={...this.#p(o,l.steps),...(0,C.isObject)(l.outputs)?l.outputs:{data:l.outputs}};return{statusCode:l.response?.statusCode,output:e}}else{let r=l.response?.message??`An error occurred while processing the request`;e.w.error(`Action ID ${e.C(n)} from connector ${e.C(t.key)}@${e.C(t.version)} failed with status ${l.response?.statusCode}: ${r}`);let a={...this.#p(o,l.steps)};Object.keys(a).length>0&&(e.w.log(`${i.default.yellow.inverse(` EXECUTION DETAILS `)}`),e.b(a)),process.exit(1)}}catch(e){this.#m(e)}}#p(e,t){return e?.debug===`true`?{debug:{steps:t}}:{}}#m(t){let n=t;switch((0,C.isMissing)(n.errorType)&&(e.w.error(`An unknown error occurred`),e.w.log(`${t instanceof Error?t.message:String(t)}`),process.exit(1)),n.errorType){case`MISSING_ACTION_ERROR`:e.w.error(`The specified action was not found: ${n.message}`);break;case`INVALID_ACTION_INPUTS_ERROR`:let t=n;e.w.error(`Invalid action inputs`),e.y(t.validationErrors,!1);break;case`INVALID_CURSOR_ERROR`:e.w.error(`Invalid cursor: ${n.message}`);break;default:e.w.error(`An error occurred: ${n.message}`)}process.exit(1)}};const jn=(0,k.promisify)(f.exec);var Mn=class{constructor(){this.packageName=`@stackone/cli`,this.spinner=(0,v.default)(),this.currentVersion=K()}async execute(t={}){this.spinner.text=`Checking for updates...`,this.spinner.start();try{let n=await this.getLatestVersion();this.spinner.stop(),n||(e.w.error(`Failed to check for updates`),process.exit(1)),this.isNewerVersion(n,this.currentVersion)?(e.w.box(`New version available: ${i.default.yellow(this.currentVersion)} → ${i.default.green(n)}`),await this.performUpdate(n)):t.force?(e.w.warn(`No updates available, but forcing reinstall...`),await this.performUpdate(n)):e.w.success(`You are already on the latest version (${this.currentVersion})`),process.exit(0)}catch(t){this.spinner.stop(),e.w.error(`Error while trying to update StackOne CLI: ${t?.message??`Unknown error`}`),process.exit(1)}}async getLatestVersion(){try{let{stdout:e}=await jn(`npm view ${this.packageName} version`,{encoding:`utf-8`});return e.trim()}catch{return null}}isNewerVersion(e,t){return D.default.gt(e,t)}async performUpdate(t){this.spinner.text=`Updating to latest version (${e.C(t)})...`,this.spinner.start();let n=`npm install -g ${this.packageName}@latest`;try{await jn(n,{encoding:`utf-8`}),this.spinner.stop(),e.w.success(`StackOne CLI updated successfully to latest version (${e.C(t)})`)}catch{throw this.spinner.stop(),Error(`Failed to install update. Please try manually: ${n}`)}}};const Nn=e=>e===null?!0:Object.values(e).some(e=>e!==null),Pn=()=>{e.w.log(`${i.default.gray.inverse(` CONNECTORS VALIDATION `)} ${i.default.yellow.inverse(` WATCH MODE `)}\n`)};var Fn=class{async execute(t){let{watchMode:n,fileOrDir:r}=t,a=(0,v.default)(`Watching for file changes... ${i.default.gray(`(press "q" to quit)`)}`);if(!r)return;let o=(0,h.resolve)(r);try{await(0,A.stat)(o)}catch{e.w.error(`The specified path does not exist: ${o}\n`),process.exit(1)}if(n){e.v();let t={},{watch:n}=await import(`chokidar`),r=(await import(`readline`)).createInterface({input:process.stdin,output:process.stdout});process.stdin.setRawMode(!0),process.stdin.resume(),process.stdin.setEncoding(`utf8`);let s=()=>{l.close(),a.stop(),r.close(),e.w.log(i.default.grey(`
175
+ Exiting watch mode...`)),process.exit(0)};Pn(),e.w.start(`Validating connectors...`);let c=await zn(o);t=In(t,c||{}),Ln(t,o),a.start();let l=n(o,{persistent:!0,ignoreInitial:!0}),u=async n=>{if(!n.endsWith(`.s1.yaml`)&&!n.endsWith(`s1.partial.yaml`))return;let r=n.endsWith(`s1.partial.yaml`)?await Vn(n):[n];if(!(!r||r.length===0)){e.v(),a.stop(),Pn(),e.w.log(i.default.gray(`File change detected: ${n}`)),e.w.start(`Validating connectors...`);for(let e of r){let n=await zn(e);t=In(t,n||{})}Ln(t,o),a.start()}};l.on(`change`,async e=>await u(e)),process.stdin.on(`data`,e=>{e.toString()===`q`&&s()}),process.on(`SIGINT`,()=>{s()})}else{let t=await zn(o,e.w);process.exit(Nn(t)?1:0)}}};const In=(e,t)=>{for(let[n,r]of Object.entries(t))e[n]=r;return e},Ln=(t,n)=>{e.v(),Pn();let r=0,a=0;for(let[n,i]of Object.entries(t))i===null?r++:(e.w?.error(`Connector ${e.C(n)} is not valid`),e.y(i,!0),a++);e.w.log(``),e.w.log(i.default.blue.inverse(` Validation Summary `)),e.w.log(`Connectors path: ${e.C(n)}`),e.w.log(`${r===0?i.default.red(`0`):i.default.green(r)} valid, ${a===0?i.default.green(`0`):i.default.red(a)} invalid connectors\n`)},Rn=async e=>{let t=[],n=await(0,A.readdir)(e);for(let r of n){let n=(0,h.join)(e,r),i=await(0,A.stat)(n);i.isDirectory()?t.push(...await Rn(n)):i.isFile()&&r.endsWith(`.s1.yaml`)&&t.push(n)}return t},zn=async(t,n)=>{let r=await(0,A.stat)(t),a={};if(r.isDirectory()){let r=await Rn(t);if(r.length===0)return n?.error(`No StackOne connector found in ${e.S(t)}`),n?.log(`Connector files need to have the extension ${e.C(`*.s1.yaml`)}`),null;let o=0,s=0;for(let e of r){let t=await Bn(e,n);t===null?o++:(n?.log(``),s++),a[e]=t}return n?.log(``),n?.log(i.default.blue.inverse(` Validation Summary `)),n?.log(`${o===0?i.default.red(`0`):i.default.green(o)} valid, ${s===0?i.default.green(`0`):i.default.red(s)} invalid connectors`),a}else if(r.isFile()&&t.endsWith(`s1.yaml`))return a[t]=await Bn(t,n),a;else if(r.isFile()&&t.endsWith(`partial.yaml`)){n?.error(`Partial connector files cannot be validated directly`),n?.log(`The file ${e.S(t)} is a partial connector file.`);let r=await Vn(t);return r&&r?.length>0&&n?.log(`Did you mean ${e.C(r[0])}?`),null}else return n?.error(`No StackOne connector found in ${e.S(t)}`),n?.log(`Connector files need to have the extension ${e.C(`*.s1.yaml`)}`),null},Bn=async(t,n)=>{let r=(0,T.validateYamlConnector)((0,T.loadConnector)(t)),i=r?.errors??[];if(r.success){let r=t.split(`/`).pop()||t;return n?.success(`Connector ${e.C(r)} is valid!`),null}else if(i.length>0)return n?.error(`Connector ${e.C(t)} is not valid`),n&&e.y(i,!0),i;else return n?.error(`Connector ${e.C(t)} is not valid. Please check the file for errors`),[]},Vn=async e=>{let t=(0,h.dirname)(e);try{return(await(0,A.readdir)(t)).filter(e=>e.endsWith(`.s1.yaml`))?.map(e=>(0,h.join)(t,e))}catch{}},Hn=`https://ai-telemetry.stackone.com`,Un=`https://ai-telemetry.stackone-dev.com`;function Wn(e){if(!e)return!1;try{let{hostname:t}=new URL(e);return t===`stackone-dev.com`||t.endsWith(`.stackone-dev.com`)}catch{return!1}}function Gn(){return process.env.AI_TELEMETRY_URL?process.env.AI_TELEMETRY_URL:[process.env.AUTH_SERVER_URL,process.env.STACKONE_API_URL].some(Wn)?`https://ai-telemetry.stackone-dev.com`:`https://ai-telemetry.stackone.com`}function Kn(){let e=process.env.STACKONE_AGENT_TOKEN,t=process.env.LANGSMITH_PROJECT||`stackone-agent-cli`;if(process.env.AI_TELEMETRY_URL=Gn(),e)try{(0,o.initAgentTelemetry)({apiKey:e,projectName:t}),process.env.VERBOSE&&console.log(`[Telemetry] Initialized for project:`,t)}catch(e){process.env.VERBOSE&&console.error(`[Telemetry] Failed to initialize:`,e)}}const qn=`@stackone/cli`,Jn=2880*60*1e3,Yn=(0,l.join)((0,c.homedir)(),`.stackone`),Xn=(0,l.join)(Yn,`version-check.json`),Zn=(e=!1)=>{let t=tr(),n=Date.now();if(e||!t||n-t.lastCheckTime>1728e5){let e=Qn();e&&$n(e)&&er(e),nr({lastCheckTime:n})}},Qn=()=>{try{return(0,f.execSync)(`npm view @stackone/cli version`,{encoding:`utf-8`,stdio:[`pipe`,`pipe`,`pipe`],timeout:15e3}).trim()}catch{return null}},$n=e=>{try{let t=K();return D.default.gt(e,t)}catch{return!1}},er=t=>{let n=K(),r=`Update available: ${i.default.dim(n)} → ${i.default.green(t)}`,a=`\n\nRun ${i.default.cyan(`stackone update`)} to update`;e.w.box(r,a)},tr=()=>{try{if(!(0,s.existsSync)(Xn))return null;let e=(0,s.readFileSync)(Xn,`utf-8`);return JSON.parse(e)}catch{return null}},nr=e=>{try{(0,s.existsSync)(Yn)||(0,s.mkdirSync)(Yn,{recursive:!0}),(0,s.writeFileSync)(Xn,JSON.stringify(e,null,2),`utf-8`)}catch{}};var rr=class{constructor(e=new a.Command,t=K()){this.program=e,this.version=t,Kn(),this.setupProgram(),this.registerCommands()}setupProgram(){this.program.name(`stackone`).description(`StackOne CLI`).version(this.version,`-v, --version`)}registerCommands(){let t=new fn,n=new yn,r=new _n,o=new rn,s=new cn,c=new Fn,l=new Ye,u=new Gt,d=new Pe,f=new Ne,p=new Ze,m=new Kt,h=new Yt,g=new An,_=new Mn;this.program.configureOutput({writeOut:e=>process.stdout.write(e),writeErr:e=>process.stderr.write(e),outputError:(e,t)=>{t(i.default.red(e))}}),this.program.command(`init`).option(`-e, --env <environment>`,`Specify the environment for the configuration profile`).description(`Initialize & create a StackOne CLI configuration profile`).action(e=>{t.execute({environment:e.env})}),this.program.command(`push`).option(`-p, --profile <label>`,`Configuration profile to use`).option(`--api-url <api url>`,`API URL`).option(`--api-key <api key>`,`API Key`).option(`--force`,`Force push the connector, bypassing version conflict checks`).addArgument(new a.Argument(`<path>`,`Connector file or directory to push`)).description(`Push a connector to the StackOne registry`).action((e,t)=>{n.execute({profile:t.profile,fileOrDir:e,apiUrl:t.apiUrl,apiKey:t.apiKey,force:t.force})}),this.program.command(`drop`).option(`-p, --profile <label>`,`Configuration profile to use`).option(`--api-url <api url>`,`API URL`).option(`--api-key <api key>`,`API Key`).addArgument(new a.Argument(`<connector>`,`Connector identifier in format provider_key@version`)).description(`Drop a connector from the StackOne registry`).action((e,t)=>{o.execute({profile:t.profile,connector:e,apiUrl:t.apiUrl,apiKey:t.apiKey})}),this.program.command(`get`).option(`-p, --profile <label>`,`Configuration profile to use`).option(`--api-url <api url>`,`API URL`).option(`--api-key <api key>`,`API Key`).option(`-c, --connector <connector>`,`Connector identifier in format provider_key@version or provider_key (defaults to latest)`).option(`--account-id <account-id>`,`Account ID to fetch connector from`).option(`-f, --format <format>`,`Output format: yaml or json (default: yaml)`,`yaml`).option(`-o, --output-file <output-file>`,`File to write the output to`).option(`--builtin`,`Use the builtin (StackOne) version of the connector`).option(`--custom`,`Use the custom (organization) version of the connector`).option(`--owner <owner>`,`Owner to use for disambiguating connector versions`).description(`Get a connector from the StackOne registry`).action(t=>{[t.builtin,t.custom,t.owner].filter(Boolean).length>1&&(e.w.error(`--builtin, --custom, and --owner are mutually exclusive. Please provide only one.`),process.exit(1)),s.execute({profile:t.profile,connector:t.connector,accountId:t.accountId,format:t.format,outputFile:t.outputFile,apiUrl:t.apiUrl,apiKey:t.apiKey,owner:t.builtin?`builtin`:t.custom?`custom`:t.owner})}),this.program.command(`pull`).option(`-c, --connector <connector>`,`Connector identifier in format provider_key@version or provider_key`).option(`-p, --profile <label>`,`Configuration profile to use`).option(`--api-url <api url>`,`API URL`).option(`--api-key <api key>`,`API Key`).option(`-o, --output <path>`,`Output directory for the connectors files (default: ./connectors)`).option(`--builtin`,`Use the builtin (StackOne) version of the connector`).option(`--custom`,`Use the custom (organization) version of the connector`).option(`--owner <owner>`,`Owner to use for disambiguating connector versions`).description(`Pull a connector configuration from StackOne registry to local filesystem`).action(t=>{[t.builtin,t.custom,t.owner].filter(Boolean).length>1&&(e.w.error(`--builtin, --custom, and --owner are mutually exclusive. Please provide only one.`),process.exit(1)),r.execute({profile:t.profile,connector:t.connector,outputPath:t.output,apiUrl:t.apiUrl,apiKey:t.apiKey,owner:t.builtin?`builtin`:t.custom?`custom`:t.owner})}),this.program.command(`validate`).option(`-w, --watch`,`Run in watch mode`).addArgument(new a.Argument(`<path>`,`Connector file or directory with connectors to validate`)).description(`Validate a StackOne connector`).action((e,t)=>{c.execute({watchMode:t.watch,fileOrDir:e})}),this.program.command(`run`).option(`--connector <connector>`,`Connector file, inline YAML, or identifier (provider_key@version or provider_key for latest)`).option(`--action <action>`,`Action to execute on the connector (path to file or inline string action code)`).option(`--action-id <action-id>`,`Action ID to execute on the connector`).option(`--account <account>`,`Account details to use for running the connector (path to file or inline string account data)`).option(`--account-id <account-id>`,`Account ID to use for running the connector against (fetches connector from API if --connector not provided)`).option(`--params <params>`,`Action parameters (path to file or inline string with JSON parameters)`).option(`--credentials <credentials>`,`Credentials to use (path to file or inline string with JSON credentials)`).option(`-p, --profile <label>`,`Configuration profile to use`).option(`--api-url <api url>`,`API URL`).option(`--api-key <api key>`,`API Key`).option(`-o, --output-file <output-file>`,`File to write the output to`).option(`-d, --debug`,`Enables debug mode to include more details in the action execution output`).option(`--builtin`,`Use the builtin (StackOne) version of the connector`).option(`--custom`,`Use the custom (organization) version of the connector`).option(`--owner <owner>`,`Owner to use for disambiguating connector versions`).description(`Run a connector action`).action(t=>{[t.builtin,t.custom,t.owner].filter(Boolean).length>1&&(e.w.error(`--builtin, --custom, and --owner are mutually exclusive. Please provide only one.`),process.exit(1)),g.execute({connector:t.connector,action:t.action,actionId:t.actionId,account:t.account,accountId:t.accountId,params:t.params,credentials:t.credentials,profile:t.profile,outputFile:t.outputFile,debug:t.debug,apiUrl:t.apiUrl,apiKey:t.apiKey,owner:t.builtin?`builtin`:t.custom?`custom`:t.owner})});let v=this.program.command(`agent`).description(`StackOne agent commands`);v.command(`setup`).option(`-g, --global`,`Global only: auth + MCP server (no connector skills/guide)`).option(`-l, --local`,`Local: auth + .mcp.json + connector skills (.claude/) and guide (CLAUDE.md)`).option(`--path <dir>`,`Target project path for local setup (defaults to the current directory)`).option(`--legacy`,`Use email/password login instead of browser-based auth`).option(`--email <email>`,`Email for legacy login (or set STACKONE_EMAIL); requires --legacy`).option(`--password <password>`,`Password for legacy login (or set STACKONE_PASSWORD); requires --legacy. Prefer --password-stdin`).option(`--password-stdin`,`Read password for legacy login from stdin; requires --legacy`).description(`Set up the StackOne agent — prompts for global vs local when neither flag is given`).action(async t=>{t.global&&t.local&&(e.w.error(`--global and --local are mutually exclusive. Please provide only one.`),process.exit(1));let n=t.email!==void 0,r=t.password!==void 0,a=t.passwordStdin===!0;r&&a&&(e.w.error(`--password and --password-stdin are mutually exclusive. Please provide only one.`),process.exit(1));let o=n||r||a;o&&!t.legacy&&(e.w.error(`--email, --password, and --password-stdin require --legacy.`),process.exit(1)),n&&t.email.trim()===``&&(e.w.error(`--email cannot be empty.`),process.exit(1)),r&&t.password===``&&(e.w.error(`--password cannot be empty.`),process.exit(1)),a&&(n||process.env.STACKONE_EMAIL?.trim()||(e.w.error(`--password-stdin requires --email or STACKONE_EMAIL (stdin is consumed for the password, so email cannot be prompted).`),process.exit(1)));let s={email:t.email,password:t.password,passwordFromStdin:a},c=!!process.stdin.isTTY;if(c&&!t.legacy&&!o){let e=await Wt({initialMode:t.global?`global`:t.local?`local`:null,pathFlag:t.path});process.exit(e.status===`error`?1:0)}let d=c&&!o;!t.global&&!t.local&&!d&&e.w.log(i.default.dim(`No interactive terminal detected — defaulting to global setup. Run in a terminal for the prompt, or pass --local (with --path) / --global.`));let f=tt(t.global,t.local,d);if(f===null&&(f=await Vt()),f===`local`){let e=nt(t.path,d);e===null&&(e=await Ut(process.cwd())),await u.execute({legacy:!!t.legacy,credentials:s,targetPath:e})}else await l.execute({legacy:!!t.legacy,credentials:s})}),v.command(`cleanup`).description(`Remove all API keys and credentials from configurations`).action(()=>{d.execute()}),v.command(`run`).description(`Run the agent once with a prompt (non-interactive)`).argument(`<prompt>`,`What to do`).option(`-m, --mode <mode>`,`Mode: build, test, or research`,`build`).option(`--max-turns <n>`,`Max agent turns`,`25`).option(`-v, --verbose`,`Verbose output`).action(async(t,n)=>{let r=[`build`,`test`,`research`],a=n.mode??`build`;r.includes(a)||(e.w.error(`${i.default.red(`Invalid mode:`)} ${i.default.white(a)}. Valid modes are: ${r.join(`, `)}.`),process.exit(1));let o=n.maxTurns?parseInt(String(n.maxTurns),10):void 0;await p.execute({prompt:String(t),mode:a,maxTurns:o!==void 0&&!isNaN(o)?o:void 0,verbose:n.verbose})}),v.command(`skills`).description(`List available agent skills and optional recommendations by mode`).option(`-m, --mode <mode>`,`Show skills recommended for this mode`).action(async e=>{await m.execute({mode:e.mode})}),v.command(`sync`).description(`Sync the connector-building skills + guide into this project (.claude/ + CLAUDE.md)`).option(`--check`,`Report drift and exit non-zero instead of writing (CI guard)`).option(`--plugin-dir <path>`,`Override the agent-harness plugin dir (e.g. point at a checkout in CI/benchmarks)`).action(async e=>{await h.execute({check:!!e.check,pluginDir:e.pluginDir})}),v.command(`chat`).option(`-m, --mode <mode>`,`Mode: build, test, or research`,`build`).option(`-c, --connector <name>`,`Connector name`).option(`-a, --action <name>`,`Action name`).option(`-g, --goal <goal>`,`Initial goal/message`).option(`-t, --temperature <number>`,`Temperature (0-1, default: 0.5)`,parseFloat).option(`-v, --verbose`,`Enable verbose logging`).description(`Start an interactive chat session with the agent (use /commands in chat)`).action(async t=>{let n=[`build`,`test`,`research`];t.mode&&!n.includes(t.mode)&&(e.w.error(`❌ Error: Invalid mode "${t.mode}". Must be one of: ${n.join(`, `)}`),process.exit(1)),t.temperature!==void 0&&(isNaN(t.temperature)&&(e.w.error(`❌ Error: Temperature must be a valid number`),process.exit(1)),(t.temperature<0||t.temperature>1)&&(e.w.error(`❌ Error: Temperature must be between 0 and 1`),process.exit(1))),f.execute({mode:t.mode,connector:t.connector,action:t.action,goal:t.goal,temperature:t.temperature,verbose:t.verbose})}),this.program.command(`update`).option(`-f, --force`,`Force reinstall even if already on latest version`).description(`Update the CLI to the latest version`).action(e=>{_.execute({force:e.force})}),this.program.command(`version`).description(`Show version information`).action(async()=>{e.w.log(`${i.default.inverse.greenBright(`StackOne`)} ${i.default.grey(`CLI`)} ${i.default.whiteBright(this.version)}`),Zn(!0),process.exit(0)})}run(){process.argv.includes(`version`)||Zn(),this.program.parse(process.argv)}};Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return rr}});
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- require(`./agentConfig-KBkYYmMr.cjs`);const e=require(`./cliCore-DYlbldYc.cjs`);require(`./setupMigration-rqPZ8MV6.cjs`),require(`./agentApiKey-BDp7EFMI.cjs`),exports.CLI=e.t;
1
+ require(`./agentConfig-KBkYYmMr.cjs`);const e=require(`./cliCore-mMrBxsVZ.cjs`);require(`./setupMigration-rqPZ8MV6.cjs`),require(`./agentApiKey-BDp7EFMI.cjs`),exports.CLI=e.t;
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{t as e}from"./cliCore-DnpNl8Z6.mjs";import"./agentConfig-BWQWMYKQ.mjs";import"./setupMigration-C1ShGzOu.mjs";import"./agentApiKey-CWXxJgCO.mjs";export{e as CLI};
1
+ import{t as e}from"./cliCore-CeD5mOhR.mjs";import"./agentConfig-BWQWMYKQ.mjs";import"./setupMigration-C1ShGzOu.mjs";import"./agentApiKey-CWXxJgCO.mjs";export{e as CLI};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stackone/cli",
3
- "version": "1.43.0",
3
+ "version": "1.43.1",
4
4
  "description": "StackOne Connect CLI tool",
5
5
  "type": "module",
6
6
  "main": "dist/index.mjs",