rightbrain-cli-alpha 0.2.0 → 0.3.0
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/index.js +11 -11
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import Pe,{z}from'zod';import Vr from'http';import*as m from'@clack/prompts';import Bt from'dotenv';import Ot from'dotenv-expand';import re from'fs';import X from'path';import j from'picocolors';import Yr from'strip-json-comments';import eo from'os';import wt from'crypto';import {ClientCredentials}from'simple-oauth2';import {isAxiosError}from'axios';import {inspect}from'util';import {UsersApi,Configuration,OrganizationsApi,ProjectsApi,APIKeysApi,TasksApi,ListingsApi}from'@rightbrain/brain-api-client';import ko from'open';import {parseDocument,isScalar,isMap}from'yaml';import {Eta}from'eta';import fr from'just-camel-case';import Pt from'just-kebab-case';import ur from'just-pascal-case';import mr from'just-snake-case';import {execSync}from'child_process';import {fileTypeFromBuffer}from'file-type';import {Command}from'commander';var _e={name:"rightbrain-cli-alpha",version:"0.
|
|
2
|
+
import Pe,{z}from'zod';import Vr from'http';import*as m from'@clack/prompts';import Bt from'dotenv';import Ot from'dotenv-expand';import re from'fs';import X from'path';import j from'picocolors';import Yr from'strip-json-comments';import eo from'os';import wt from'crypto';import {ClientCredentials}from'simple-oauth2';import {isAxiosError}from'axios';import {inspect}from'util';import {UsersApi,Configuration,OrganizationsApi,ProjectsApi,APIKeysApi,TasksApi,ListingsApi}from'@rightbrain/brain-api-client';import ko from'open';import {parseDocument,isScalar,isMap}from'yaml';import {Eta}from'eta';import fr from'just-camel-case';import Pt from'just-kebab-case';import ur from'just-pascal-case';import mr from'just-snake-case';import {execSync}from'child_process';import {fileTypeFromBuffer}from'file-type';import {Command}from'commander';var _e={name:"rightbrain-cli-alpha",version:"0.3.0",description:"Command line interface for RightBrain AI",type:"module",main:"./dist/index.js",module:"./dist/index.js",types:"./dist/index.d.ts",bin:{rightbrain:"dist/index.js"},files:["dist","README.md","LICENSE"],publishConfig:{access:"public"},keywords:["rightbrain","rightbrainai","ai","cli","interactive","generator"],scripts:{clean:"rm -rf dist",build:"dotenv -e ../../.env -- tsup && chmod +x dist/index.js",dev:"dotenv -e ../../.env -- tsup --watch","type-check":"tsc --noEmit",lint:"eslint .","link:global":"pnpm run build && pnpm link --global",prepublishOnly:"pnpm run build","generate:schema":"pnpm dlx tsx scripts/generate-schema.ts"},dependencies:{"@clack/prompts":"1.0.0-alpha.9","@rightbrain/brain-api-client":"0.0.1-dev.8.6a38b3e",axios:"^1.12.0",commander:"^13.1.0",dotenv:"^16.5.0","dotenv-cli":"^10.0.0","dotenv-expand":"^12.0.2",eslint:"^9.39.2",eta:"^4.5.0","file-type":"21.3.0","just-camel-case":"^6.2.0","just-kebab-case":"^4.2.0","just-pascal-case":"^3.2.0","just-snake-case":"^3.2.0",open:"^11.0.0",picocolors:"^1.1.0","simple-oauth2":"^5.1.0","strip-json-comments":"^5.0.3",yaml:"^2.8.0",zod:"^4.3.6"},devDependencies:{"@rightbrainai/eslint-config":"workspace:*","@rightbrainai/tsconfig":"workspace:*","@types/node":"^20.19.22","@types/simple-oauth2":"^5.0.7",tsup:"^8.3.5",typescript:"5.7.3"}};var De=e=>{let t=new Map;for(let r of e){let o=r.provider;t.has(o)||t.set(o,[]),t.get(o)?.push(r);}return t},H=e=>typeof e=="string"&&/^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/i.test(e);function Be(e){return e instanceof Error?e.message:String(e)}var Nr=Pe.object({CLI_PUBLIC_API_URL:Pe.url().default("https://app.rightbrain.ai/api/v1"),CLI_PUBLIC_RB_OAUTH2_CLIENT_ID:Pe.string().refine(H,{message:"Invalid UUID format"}).default("ae8c4f7f-d12f-4975-98bd-e5e42ff52f8e"),CLI_PUBLIC_RB_OAUTH2_URL:Pe.url().default("https://oauth.rightbrain.ai"),CLI_PUBLIC_TEMPLATES_URL:Pe.url().default("https://app.rightbrain.ai/cli")}),I=Nr.parse({CLI_PUBLIC_API_URL:"https://stag.leftbrain.me/api/v1",CLI_PUBLIC_RB_OAUTH2_CLIENT_ID:"6e50b63e-7256-4269-97ea-69eb0821fff2",CLI_PUBLIC_RB_OAUTH2_URL:"https://oauth.leftbrain.me",CLI_PUBLIC_TEMPLATES_URL:"https://stag.leftbrain.me/cli"});function p(e){try{if(typeof e=="function"){let t=e();return t instanceof Promise?t.then(r=>[r,null]).catch(r=>[null,r]):[t,null]}return e.then(t=>[t,null]).catch(t=>[null,t])}catch(t){return [null,t]}}var St=`
|
|
3
3
|
:root {
|
|
4
4
|
--bg-primary: #ffffff;
|
|
5
5
|
--bg-secondary: #f9fafb;
|
|
@@ -411,17 +411,17 @@ import Pe,{z}from'zod';import Vr from'http';import*as m from'@clack/prompts';imp
|
|
|
411
411
|
<div class="error-message">${Kr(e)}</div>
|
|
412
412
|
</div>
|
|
413
413
|
</body>
|
|
414
|
-
</html>`}function Kr(e){let t={"&":"&","<":"<",">":">",'"':""","'":"'"};return e.replace(/[&<>"']/g,r=>t[r]||r)}var $e=27246;function Ut(){return `http://localhost:${$e}/login`}function gt(){return `http://localhost:${$e}/callback`}async function Wr(e,t){let r=gt(),o=`${J.oauthUrl}${J.tokenPath}`,n=new URLSearchParams({grant_type:"authorization_code",code:e,redirect_uri:r,client_id:J.clientId});t&&n.append("code_verifier",t);let i=await fetch(o,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:n.toString()});if(!i.ok)throw new Error(`Token exchange failed: ${i.status} - ${await i.text()}`);return await i.json()}function Dt(e,t,r){return new Promise(o=>{let n=Vr.createServer(async(s,a)=>{let c=new URL(s.url||"/",`http://localhost:${$e}`);if(c.pathname==="/login"){a.writeHead(302,{Location:r}),a.end();return}if(c.pathname!=="/callback"){a.writeHead(404,{"Content-Type":"text/plain"}),a.end("Not Found");return}let u=c.searchParams.get("code"),l=c.searchParams.get("state"),d=c.searchParams.get("error"),w=c.searchParams.get("error_description");if(d){let h=w||d;a.writeHead(400,{"Content-Type":"text/html"}),a.end(Ae(h)),n.close(),o({success:false,error:h});return}if(l!==e){let h="State mismatch - possible CSRF attack";a.writeHead(400,{"Content-Type":"text/html"}),a.end(Ae(h)),n.close(),o({success:false,error:h});return}if(!u){let h="No authorization code received";a.writeHead(400,{"Content-Type":"text/html"}),a.end(Ae(h)),n.close(),o({success:false,error:h});return}let[b,_]=await p(()=>Wr(u,t));if(_||!b){let h=_ instanceof Error?_.message:"Token exchange failed";a.writeHead(500,{"Content-Type":"text/html"}),a.end(Ae(h)),n.close(),o({success:false,error:h});return}a.writeHead(200,{"Content-Type":"text/html"}),a.end(Rt()),n.close(),o({success:true,token:b});});n.listen($e),n.on("error",s=>{o({success:false,error:`Failed to start callback server on port ${$e}: ${s.message}`});});let i=setTimeout(()=>{n.close(),o({success:false,error:"Login timeout - please try again"});},120*1e3);n.on("close",()=>{clearTimeout(i);});})}var f=!process.stdout.isTTY;var Ne="rightbrain.json",yt=".env",
|
|
415
|
-
Expected a file (e.g., ${Ne}), but received a directory.`)),process.exit(1)),ue=e;}var Zr=z.object({$schema:z.string().optional(),orgId:z.string().refine(H,{message:"Invalid UUID format"}),projectId:z.string().refine(H,{message:"Invalid UUID format"}),envFile:z.string().default(yt).optional(),apiKey:z.string().optional(),generate:z.object({language:z.string(),outputDir:z.string().refine(e=>{if(!e)return true;let t=e.replace(/^\.\//,"").replace(/\/$/,"");return !(t===""||t===".")},{message:'outputDir cannot be project root ("./" or "."). It must be inside the project below rightbrain.json level.'}),taskIds:z.array(z.string().refine(H,{message:"Invalid UUID format"})),hardcodeTaskIds:z.boolean().default(false).optional()}).optional(),clientId:z.string().refine(H,{message:"Invalid UUID format"}).optional(),clientSecret:z.string().optional(),oauthUrl:z.url().optional(),apiUrl:z.url().default(I.CLI_PUBLIC_API_URL).optional()}).refine(e=>{let t=e.clientId&&e.clientSecret,r=!!e.apiKey;return t||r},{message:"Either 'apiKey' or both 'clientId' and 'clientSecret' must be provided to authenticate"});function Gr(){return ue?X.dirname(ue):process.cwd()}function Hr(e=yt,t=false){let r=Gr(),o=X.isAbsolute(e),n=o?e:X.join(r,e);if(re.existsSync(n)){if(!re.statSync(n).isFile())throw new Error(`envFile path "${e}" exists but is not a file (it's a directory).`);Ot.expand(Bt.config({path:n,override:true}));return}if(!o){let i=X.join(r,`${e}.local`);if(re.existsSync(i)){if(!re.statSync(i).isFile())throw new Error(`envFile path "${e}.local" exists but is not a file (it's a directory).`);Ot.expand(Bt.config({path:i,override:true}));return}}if(t){let i=o?[n]:[n,X.join(r,`${e}.local`)];throw new Error(`envFile "${e}" specified in config but not found. Expected at: ${i.join(" or ")}`)}}function Jr(e){let t="",r=0;for(;r<e.length;)if(e[r]==="$"&&e[r+1]==="{"){let o=1,n=r+2,i=false;for(;n<e.length&&o>0;)e[n]==="$"&&e[n+1]==="{"?(i=true,o++,n++):e[n]==="}"&&o--,n++;if(o===0){let s=e.slice(r+2,n-1);if(i)throw new Error(`\${${s}}: bad substitution`);{let a=s.trim();t+=process.env[a]??"",r=n;}}else t+=e[r],r++;}else t+=e[r],r++;return t}function ht(e){if(typeof e=="string")return Jr(e);if(Array.isArray(e))return e.map(ht);if(e!==null&&typeof e=="object"){let t={};for(let[r,o]of Object.entries(e))t[r]=ht(o);return t}return e}function Xr(){if(ue)return ue;let e=X.join(process.cwd(),Ne);return re.existsSync(e)?e:(ue=X.join(process.cwd(),Ne),ue)}function Qr(){let e=Xr();if(!re.existsSync(e))return null;let t=re.readFileSync(e,"utf-8");return {config:JSON.parse(Yr(t)),filepath:e}}var Oe=null;function je(){if(Oe)return Oe;let[e,t]=p(Qr);if(t&&((f?console.error:m.outro)(j.red(`Error loading configuration file: ${t}`)),process.exit(1)),!e)return null;let r=e.config,o=yt,n=false;r&&typeof r=="object"&&r!==null&&"envFile"in r&&typeof r.envFile=="string"&&(o=r.envFile,n=true);let[i]=p(()=>{Hr(o,n);});i&&((f?console.error:m.outro)(j.red(`Error loading env file: ${i}`)),process.exit(1));let[s,a]=p(()=>ht(e.config));a&&((f?console.error:m.outro)(j.red(`Error resolving environment variables: ${a}`)),process.exit(1));let c=Zr.safeParse(s);if(c.success||((f?console.error:m.log.error)("Invalid Configuration: "),(f?console.error:m.log.error)(z.prettifyError(c.error)),(f?console.error:m.outro)(j.red("Please check your configuration file and try again.")),process.exit(1)),c.data.generate?.outputDir){let u=X.dirname(e.filepath),l=c.data.generate.outputDir,d=X.resolve(u,l),w=X.relative(u,d);(w===""||w==="."||w.startsWith(".."))&&((f?console.error:m.log.error)(j.red(`Invalid outputDir: "${l}" resolves to "${w}" which is outside the project or at project root. outputDir must be inside the project below rightbrain.json level.`)),process.exit(1));}return Oe={...c.data,filePath:e.filepath,rawConfig:r},Oe}function zt(){let e=je();return e||((f?console.error:m.outro)(j.red(`No configuration file found. Expected: ${Ne}`)),process.exit(1)),e}var kt=X.join(eo.homedir(),".rightbrain"),we=X.join(kt,"credentials.json"),ke=null;function me(){if(ke)return ke;if(!re.existsSync(we))return null;try{let e=re.readFileSync(we,"utf-8"),t=JSON.parse(e);return t.access_token?(ke=t,ke):null}catch{return null}}function to(){re.existsSync(kt)||re.mkdirSync(kt,{recursive:true,mode:448});}function oe(e,t=false){to();let r=t?e:{...me(),...e};re.writeFileSync(we,JSON.stringify(r,null,2),"utf-8"),re.chmodSync(we,384),ke=r;}function Kt(){re.existsSync(we)&&re.unlinkSync(we),ke=null;}function Vt(e){if(!e.expires_at)return false;let t=300*1e3;return Date.now()>=e.expires_at-t}var ve=null,xe=null,ze=["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F"],Le=0,Wt=process.stderr.isTTY,ro=()=>{Wt&&process.stderr.write("\x1B[?25l");},qe=()=>{Wt&&process.stderr.write("\x1B[?25h");};process.on("exit",qe);process.on("SIGINT",()=>{qe(),process.exit(130);});process.on("SIGTERM",()=>{qe(),process.exit(143);});var oo=()=>{let e=false;return {start:()=>{e||(e=true,Le=0,xe&&clearInterval(xe),ro(),process.stderr.write("\r"+ze[Le]),xe=setInterval(()=>{Le=(Le+1)%ze.length,process.stderr.write("\r"+ze[Le]);},80));},stop:()=>{xe&&(clearInterval(xe),xe=null),e&&(process.stderr.write("\r"+" ".repeat(ze[0].length)+"\r"),qe()),e=false;}}},P=()=>(ve||(ve=oo()),ve),Ke=()=>{ve&&(ve.stop(),ve=null);};async function V(e){let t=e?.loadGlobalConfig?null:je();if(!t){let o=me();if(o)if(Vt(o)){let n=await so(o);if(n)return {accessToken:n.access_token,orgId:n.org_id,projectId:n.project_id}}else return {accessToken:o.access_token,orgId:o.org_id,projectId:o.project_id};Ke(),(f?console.error:m.outro)("Not authenticated. Please run `npx rightbrain login` command to authenticate."),process.exit(1);}return {accessToken:await io(t),orgId:t.orgId,projectId:t.projectId,filePath:t.filePath}}var Ve=null;async function io(e){if(e.apiKey)return e.apiKey;if((!e.clientId||!e.clientSecret)&&(Ke(),(f?console.error:m.outro)(j.red("Client ID and secret are required to authenticate via OAuth")),process.exit(1)),!Ve||Ve.expired()){let t=new ClientCredentials({auth:{tokenHost:e.oauthUrl??I.CLI_PUBLIC_RB_OAUTH2_URL,tokenPath:"/oauth2/token"},client:{id:e.clientId,secret:e.clientSecret},http:{json:"force"}}),[r,o]=await p(()=>t.getToken({}));return (o||!r?.token.access_token)&&(Ke(),(f?console.error:m.outro)(j.red("Failed to obtain access token")),process.exit(1)),Ve=r,r.token.access_token}return Ve.token.access_token}var J={oauthUrl:I.CLI_PUBLIC_RB_OAUTH2_URL,authPath:"/oauth2/auth",tokenPath:"/oauth2/token",clientId:I.CLI_PUBLIC_RB_OAUTH2_CLIENT_ID};async function so(e){if(!e.refresh_token)return null;let t=`${J.oauthUrl}${J.tokenPath}`,r=new URLSearchParams({grant_type:"refresh_token",refresh_token:e.refresh_token,client_id:J.clientId});try{let o=await fetch(t,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:r.toString()});if(!o.ok)return null;let n=await o.json(),i=n.expires_in?Date.now()+n.expires_in*1e3:void 0,s={...e,access_token:n.access_token,refresh_token:n.refresh_token??e.refresh_token,expires_at:i};return oe(s,!0),s}catch{return null}}function Zt(){return wt.randomBytes(32).toString("base64url")}async function Gt(e){return wt.createHash("sha256").update(e).digest().toString("base64url")}function Ht(e,t){let r=gt(),o=new URLSearchParams({client_id:J.clientId,redirect_uri:r,response_type:"code",scope:"offline_access",state:e});return t&&(o.append("code_challenge",t),o.append("code_challenge_method","S256")),`${J.oauthUrl}${J.authPath}?${o.toString()}`}function Jt(){return wt.randomBytes(32).toString("hex")}function M(e){if(f||m.outro("Something went wrong"),isAxiosError(e)){let t=e.response;if(t?.data){t.status===401&&console.error("Unauthorized Access please login again."),console.error("Error:"),console.info(f?JSON.stringify(t.data,null,2):inspect(t.data,{depth:null,colors:true}));return}if(t?.status){console.error(`Error: Request failed with status ${t.status}`);return}}if(e instanceof Error){console.error(e.message);return}(f?console.error:m.outro)("An unexpected error occurred");}async function pe({accessToken:e,orgId:t,projectId:r}){let o=P();if(!t){o.start();let[n,i]=await p(async()=>await new OrganizationsApi(N(e)).listOrganizations().then(a=>a.data.results));if((i||!n)&&(o.stop(),M(i),process.exit(1)),o.stop(),n.length===0&&(m.cancel("No organizations found. Please create one first."),process.exit(1)),n.length===1)t=n[0].id,m.log.info(`Using organization: ${j.cyan(n[0].name)}`);else {let s=await m.select({message:"Select an organization",options:n.map(a=>({value:a.id,label:a.name,hint:a.id}))});m.isCancel(s)&&(m.outro("Select project cancelled"),process.exit(0)),t=s;}}if(!r){o.start();let[n,i]=await p(async()=>await new ProjectsApi(N(e)).listProjects(t).then(a=>a.data.results));if((i||!n)&&(o.stop(),M(i),process.exit(1)),o.stop(),n.length===0&&(m.cancel("No projects found. Please create one first."),process.exit(1)),n.length===1)r=n[0].id,m.log.info(`Using project: ${j.cyan(n[0].name)}`);else {let s=await m.select({message:"Select a project",options:n.map(a=>({value:a.id,label:a.name,hint:a.id}))});m.isCancel(s)&&(m.outro("Select project cancelled"),process.exit(0)),r=s;}}return (typeof t!="string"||typeof r!="string")&&(m.cancel("Failed to select project"),process.exit(1)),{orgId:t,projectId:r}}var N=e=>new Configuration({basePath:I.CLI_PUBLIC_API_URL,accessToken:e}),T=class e{_options;tasksApi;listingsApi;organizationsApi;projectsApi;apiKeysApi;constructor(t){this._options=t;let r=N(t.accessToken);this.tasksApi=new TasksApi(r),this.listingsApi=new ListingsApi(r),this.organizationsApi=new OrganizationsApi(r),this.projectsApi=new ProjectsApi(r),this.apiKeysApi=new APIKeysApi(r);}get orgId(){return this._options.orgId}get projectId(){return this._options.projectId}getTaskUrl(t){return `${I.CLI_PUBLIC_API_URL}/org/${this.orgId}/project/${this.projectId}/task/${t}`}static async fromAuthContext(){let t=await V(),r=await pe(t);return (!t.orgId||!t.projectId)&&oe({access_token:t.accessToken,org_id:r.orgId,project_id:r.projectId}),new e({...t,...r})}static async fromConfig(){let t=await V();return (!t.orgId||!t.projectId)&&((f?console.error:m.outro)("orgId and projectId are required to authenticate."),process.exit(1)),new e({accessToken:t.accessToken,orgId:t.orgId,projectId:t.projectId})}async listModels(){return (await this.listingsApi.getAllModels(this.orgId,this.projectId)).data}async createTask(t){return (await this.tasksApi.createTask(this.orgId,this.projectId,t)).data}async getOrganization(t){return (await this.organizationsApi.getOrganization(t)).data}async getProject(t,r){return (await this.projectsApi.getProject(t,r)).data}async listTasks(){return (await this.tasksApi.listTasks(this.orgId,this.projectId)).data.results}async getTask(t){return (await this.tasksApi.getTask(this.orgId,this.projectId,t,null,true)).data}async runTask({body:t,taskId:r,revisionId:o,useFallbackModel:n=false}){let i=new FormData;if(i.append("task_input",JSON.stringify(t.task_input)),t.task_files&&t.task_files.length>0)for(let c of t.task_files)i.append("task_file",c,c.name);let s=new URLSearchParams;return o&&s.set("revision_id",o),(await this.tasksApi.runTask(this.orgId,this.projectId,r,o,null,null,n,{data:i})).data}async listApiKeys(){return (await this.apiKeysApi.listApiKeys(this.orgId,this.projectId)).data}async createApiKey(t){return (await this.apiKeysApi.createApiKey(this.orgId,this.projectId,{name:t})).data}};var Q=e=>{let{canRunWithOptions:t=true}=e||{};process.env.TERM_PROGRAM?.toLowerCase().includes("mintty")&&(console.warn(`WARNING: It looks like you are using MinTTY, which is non-interactive. This is most likely because you are
|
|
414
|
+
</html>`}function Kr(e){let t={"&":"&","<":"<",">":">",'"':""","'":"'"};return e.replace(/[&<>"']/g,r=>t[r]||r)}var $e=27246;function Ut(){return `http://localhost:${$e}/login`}function gt(){return `http://localhost:${$e}/callback`}async function Wr(e,t){let r=gt(),o=`${J.oauthUrl}${J.tokenPath}`,n=new URLSearchParams({grant_type:"authorization_code",code:e,redirect_uri:r,client_id:J.clientId});t&&n.append("code_verifier",t);let i=await fetch(o,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:n.toString()});if(!i.ok)throw new Error(`Token exchange failed: ${i.status} - ${await i.text()}`);return await i.json()}function Dt(e,t,r){return new Promise(o=>{let n=Vr.createServer(async(s,a)=>{let c=new URL(s.url||"/",`http://localhost:${$e}`);if(c.pathname==="/login"){a.writeHead(302,{Location:r}),a.end();return}if(c.pathname!=="/callback"){a.writeHead(404,{"Content-Type":"text/plain"}),a.end("Not Found");return}let u=c.searchParams.get("code"),l=c.searchParams.get("state"),d=c.searchParams.get("error"),w=c.searchParams.get("error_description");if(d){let h=w||d;a.writeHead(400,{"Content-Type":"text/html"}),a.end(Ae(h)),n.close(),o({success:false,error:h});return}if(l!==e){let h="State mismatch - possible CSRF attack";a.writeHead(400,{"Content-Type":"text/html"}),a.end(Ae(h)),n.close(),o({success:false,error:h});return}if(!u){let h="No authorization code received";a.writeHead(400,{"Content-Type":"text/html"}),a.end(Ae(h)),n.close(),o({success:false,error:h});return}let[b,_]=await p(()=>Wr(u,t));if(_||!b){let h=_ instanceof Error?_.message:"Token exchange failed";a.writeHead(500,{"Content-Type":"text/html"}),a.end(Ae(h)),n.close(),o({success:false,error:h});return}a.writeHead(200,{"Content-Type":"text/html"}),a.end(Rt()),n.close(),o({success:true,token:b});});n.listen($e),n.on("error",s=>{o({success:false,error:`Failed to start callback server on port ${$e}: ${s.message}`});});let i=setTimeout(()=>{n.close(),o({success:false,error:"Login timeout - please try again"});},120*1e3);n.on("close",()=>{clearTimeout(i);});})}var f=!process.stdout.isTTY;var Ne="rightbrain.json",yt=".env",me=null;function Nt(e){re.existsSync(e)||((f?console.error:m.outro)(j.red(`Configuration file not found: ${e}`)),process.exit(1)),re.statSync(e).isDirectory()&&((f?console.error:m.outro)(j.red(`Invalid configuration path: ${e}
|
|
415
|
+
Expected a file (e.g., ${Ne}), but received a directory.`)),process.exit(1)),me=e;}var Zr=z.object({$schema:z.string().optional(),orgId:z.string().refine(H,{message:"Invalid UUID format"}),projectId:z.string().refine(H,{message:"Invalid UUID format"}),envFile:z.string().default(yt).optional(),apiKey:z.string().optional(),generate:z.object({language:z.string(),outputDir:z.string().refine(e=>{if(!e)return true;let t=e.replace(/^\.\//,"").replace(/\/$/,"");return !(t===""||t===".")},{message:'outputDir cannot be project root ("./" or "."). It must be inside the project below rightbrain.json level.'}),taskIds:z.array(z.string().refine(H,{message:"Invalid UUID format"})),hardcodeTaskIds:z.boolean().default(false).optional()}).optional(),clientId:z.string().refine(H,{message:"Invalid UUID format"}).optional(),clientSecret:z.string().optional(),oauthUrl:z.url().optional(),apiUrl:z.url().default(I.CLI_PUBLIC_API_URL).optional()}).refine(e=>{let t=e.clientId&&e.clientSecret,r=!!e.apiKey;return t||r},{message:"Either 'apiKey' or both 'clientId' and 'clientSecret' must be provided to authenticate"});function Gr(){return me?X.dirname(me):process.cwd()}function Hr(e=yt,t=false){let r=Gr(),o=X.isAbsolute(e),n=o?e:X.join(r,e);if(re.existsSync(n)){if(!re.statSync(n).isFile())throw new Error(`envFile path "${e}" exists but is not a file (it's a directory).`);Ot.expand(Bt.config({path:n,override:true}));return}if(!o){let i=X.join(r,`${e}.local`);if(re.existsSync(i)){if(!re.statSync(i).isFile())throw new Error(`envFile path "${e}.local" exists but is not a file (it's a directory).`);Ot.expand(Bt.config({path:i,override:true}));return}}if(t){let i=o?[n]:[n,X.join(r,`${e}.local`)];throw new Error(`envFile "${e}" specified in config but not found. Expected at: ${i.join(" or ")}`)}}function Jr(e){let t="",r=0;for(;r<e.length;)if(e[r]==="$"&&e[r+1]==="{"){let o=1,n=r+2,i=false;for(;n<e.length&&o>0;)e[n]==="$"&&e[n+1]==="{"?(i=true,o++,n++):e[n]==="}"&&o--,n++;if(o===0){let s=e.slice(r+2,n-1);if(i)throw new Error(`\${${s}}: bad substitution`);{let a=s.trim();t+=process.env[a]??"",r=n;}}else t+=e[r],r++;}else t+=e[r],r++;return t}function ht(e){if(typeof e=="string")return Jr(e);if(Array.isArray(e))return e.map(ht);if(e!==null&&typeof e=="object"){let t={};for(let[r,o]of Object.entries(e))t[r]=ht(o);return t}return e}function Xr(){if(me)return me;let e=X.join(process.cwd(),Ne);return re.existsSync(e)?e:(me=X.join(process.cwd(),Ne),me)}function Qr(){let e=Xr();if(!re.existsSync(e))return null;let t=re.readFileSync(e,"utf-8");return {config:JSON.parse(Yr(t)),filepath:e}}var Oe=null;function je(){if(Oe)return Oe;let[e,t]=p(Qr);if(t&&((f?console.error:m.outro)(j.red(`Error loading configuration file: ${t}`)),process.exit(1)),!e)return null;let r=e.config,o=yt,n=false;r&&typeof r=="object"&&r!==null&&"envFile"in r&&typeof r.envFile=="string"&&(o=r.envFile,n=true);let[i]=p(()=>{Hr(o,n);});i&&((f?console.error:m.outro)(j.red(`Error loading env file: ${i}`)),process.exit(1));let[s,a]=p(()=>ht(e.config));a&&((f?console.error:m.outro)(j.red(`Error resolving environment variables: ${a}`)),process.exit(1));let c=Zr.safeParse(s);if(c.success||((f?console.error:m.log.error)("Invalid Configuration: "),(f?console.error:m.log.error)(z.prettifyError(c.error)),(f?console.error:m.outro)(j.red("Please check your configuration file and try again.")),process.exit(1)),c.data.generate?.outputDir){let u=X.dirname(e.filepath),l=c.data.generate.outputDir,d=X.resolve(u,l),w=X.relative(u,d);(w===""||w==="."||w.startsWith(".."))&&((f?console.error:m.log.error)(j.red(`Invalid outputDir: "${l}" resolves to "${w}" which is outside the project or at project root. outputDir must be inside the project below rightbrain.json level.`)),process.exit(1));}return Oe={...c.data,filePath:e.filepath,rawConfig:r},Oe}function zt(){let e=je();return e||((f?console.error:m.outro)(j.red(`No configuration file found. Expected: ${Ne}`)),process.exit(1)),e}var kt=X.join(eo.homedir(),".rightbrain"),xe=X.join(kt,"credentials.json"),we=null;function ge(){if(we)return we;if(!re.existsSync(xe))return null;try{let e=re.readFileSync(xe,"utf-8"),t=JSON.parse(e);return t.access_token?(we=t,we):null}catch{return null}}function to(){re.existsSync(kt)||re.mkdirSync(kt,{recursive:true,mode:448});}function oe(e,t=false){to();let r=t?e:{...ge(),...e};re.writeFileSync(xe,JSON.stringify(r,null,2),"utf-8"),re.chmodSync(xe,384),we=r;}function Kt(){re.existsSync(xe)&&re.unlinkSync(xe),we=null;}function Vt(e){if(!e.expires_at)return false;let t=300*1e3;return Date.now()>=e.expires_at-t}var Ce=null,ve=null,ze=["\u280B","\u2819","\u2839","\u2838","\u283C","\u2834","\u2826","\u2827","\u2807","\u280F"],Le=0,Wt=process.stderr.isTTY,ro=()=>{Wt&&process.stderr.write("\x1B[?25l");},qe=()=>{Wt&&process.stderr.write("\x1B[?25h");};process.on("exit",qe);process.on("SIGINT",()=>{qe(),process.exit(130);});process.on("SIGTERM",()=>{qe(),process.exit(143);});var oo=()=>{let e=false;return {start:()=>{e||(e=true,Le=0,ve&&clearInterval(ve),ro(),process.stderr.write("\r"+ze[Le]),ve=setInterval(()=>{Le=(Le+1)%ze.length,process.stderr.write("\r"+ze[Le]);},80));},stop:()=>{ve&&(clearInterval(ve),ve=null),e&&(process.stderr.write("\r"+" ".repeat(ze[0].length)+"\r"),qe()),e=false;}}},P=()=>(Ce||(Ce=oo()),Ce),Ke=()=>{Ce&&(Ce.stop(),Ce=null);};async function V(e){let t=e?.loadGlobalConfig?null:je();if(!t){let o=ge();if(o)if(Vt(o)){let n=await so(o);if(n)return {accessToken:n.access_token,orgId:n.org_id,projectId:n.project_id}}else return {accessToken:o.access_token,orgId:o.org_id,projectId:o.project_id};Ke(),(f?console.error:m.outro)("Not authenticated. Please run `npx rightbrain login` command to authenticate."),process.exit(1);}return {accessToken:await io(t),orgId:t.orgId,projectId:t.projectId,filePath:t.filePath}}var Ve=null;async function io(e){if(e.apiKey)return e.apiKey;if((!e.clientId||!e.clientSecret)&&(Ke(),(f?console.error:m.outro)(j.red("Client ID and secret are required to authenticate via OAuth")),process.exit(1)),!Ve||Ve.expired()){let t=new ClientCredentials({auth:{tokenHost:e.oauthUrl??I.CLI_PUBLIC_RB_OAUTH2_URL,tokenPath:"/oauth2/token"},client:{id:e.clientId,secret:e.clientSecret},http:{json:"force"}}),[r,o]=await p(()=>t.getToken({}));return (o||!r?.token.access_token)&&(Ke(),(f?console.error:m.outro)(j.red("Failed to obtain access token")),process.exit(1)),Ve=r,r.token.access_token}return Ve.token.access_token}var J={oauthUrl:I.CLI_PUBLIC_RB_OAUTH2_URL,authPath:"/oauth2/auth",tokenPath:"/oauth2/token",clientId:I.CLI_PUBLIC_RB_OAUTH2_CLIENT_ID};async function so(e){if(!e.refresh_token)return null;let t=`${J.oauthUrl}${J.tokenPath}`,r=new URLSearchParams({grant_type:"refresh_token",refresh_token:e.refresh_token,client_id:J.clientId});try{let o=await fetch(t,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:r.toString()});if(!o.ok)return null;let n=await o.json(),i=n.expires_in?Date.now()+n.expires_in*1e3:void 0,s={...e,access_token:n.access_token,refresh_token:n.refresh_token??e.refresh_token,expires_at:i};return oe(s,!0),s}catch{return null}}function Zt(){return wt.randomBytes(32).toString("base64url")}async function Gt(e){return wt.createHash("sha256").update(e).digest().toString("base64url")}function Ht(e,t){let r=gt(),o=new URLSearchParams({client_id:J.clientId,redirect_uri:r,response_type:"code",scope:"offline_access",state:e});return t&&(o.append("code_challenge",t),o.append("code_challenge_method","S256")),`${J.oauthUrl}${J.authPath}?${o.toString()}`}function Jt(){return wt.randomBytes(32).toString("hex")}function M(e){if(f||m.outro("Something went wrong"),isAxiosError(e)){let t=e.response;if(t?.data){t.status===401&&console.error("Unauthorized Access please login again."),console.error("Error:"),console.info(f?JSON.stringify(t.data,null,2):inspect(t.data,{depth:null,colors:true}));return}if(t?.status){console.error(`Error: Request failed with status ${t.status}`);return}}if(e instanceof Error){console.error(e.message);return}(f?console.error:m.outro)("An unexpected error occurred");}async function pe({accessToken:e,orgId:t,projectId:r}){let o=P();if(!t){o.start();let[n,i]=await p(async()=>await new OrganizationsApi(N(e)).listOrganizations().then(a=>a.data.results));if((i||!n)&&(o.stop(),M(i),process.exit(1)),o.stop(),n.length===0&&(m.cancel("No organizations found. Please create one first."),process.exit(1)),n.length===1)t=n[0].id,m.log.info(`Using organization: ${j.cyan(n[0].name)}`);else {let s=await m.select({message:"Select an organization",options:n.map(a=>({value:a.id,label:a.name,hint:a.id}))});m.isCancel(s)&&(m.outro("Select project cancelled"),process.exit(0)),t=s;}}if(!r){o.start();let[n,i]=await p(async()=>await new ProjectsApi(N(e)).listProjects(t).then(a=>a.data.results));if((i||!n)&&(o.stop(),M(i),process.exit(1)),o.stop(),n.length===0&&(m.cancel("No projects found. Please create one first."),process.exit(1)),n.length===1)r=n[0].id,m.log.info(`Using project: ${j.cyan(n[0].name)}`);else {let s=await m.select({message:"Select a project",options:n.map(a=>({value:a.id,label:a.name,hint:a.id}))});m.isCancel(s)&&(m.outro("Select project cancelled"),process.exit(0)),r=s;}}return (typeof t!="string"||typeof r!="string")&&(m.cancel("Failed to select project"),process.exit(1)),{orgId:t,projectId:r}}var N=e=>new Configuration({basePath:I.CLI_PUBLIC_API_URL,accessToken:e}),T=class e{_options;tasksApi;listingsApi;organizationsApi;projectsApi;apiKeysApi;constructor(t){this._options=t;let r=N(t.accessToken);this.tasksApi=new TasksApi(r),this.listingsApi=new ListingsApi(r),this.organizationsApi=new OrganizationsApi(r),this.projectsApi=new ProjectsApi(r),this.apiKeysApi=new APIKeysApi(r);}get orgId(){return this._options.orgId}get projectId(){return this._options.projectId}getTaskUrl(t){return `${I.CLI_PUBLIC_API_URL}/org/${this.orgId}/project/${this.projectId}/task/${t}`}static async fromAuthContext(){let t=await V(),r=await pe(t);return (!t.orgId||!t.projectId)&&oe({access_token:t.accessToken,org_id:r.orgId,project_id:r.projectId}),new e({...t,...r})}static async fromConfig(){let t=await V();return (!t.orgId||!t.projectId)&&((f?console.error:m.outro)("orgId and projectId are required to authenticate."),process.exit(1)),new e({accessToken:t.accessToken,orgId:t.orgId,projectId:t.projectId})}async listModels(){return (await this.listingsApi.getAllModels(this.orgId,this.projectId)).data}async createTask(t){return (await this.tasksApi.createTask(this.orgId,this.projectId,t)).data}async getOrganization(t){return (await this.organizationsApi.getOrganization(t)).data}async getProject(t,r){return (await this.projectsApi.getProject(t,r)).data}async listTasks(){return (await this.tasksApi.listTasks(this.orgId,this.projectId)).data.results}async getTask(t){return (await this.tasksApi.getTask(this.orgId,this.projectId,t,null,true)).data}async runTask({body:t,taskId:r,revisionId:o,useFallbackModel:n=false}){let i=new FormData;if(i.append("task_input",JSON.stringify(t.task_input)),t.task_files&&t.task_files.length>0)for(let c of t.task_files)i.append("task_file",c,c.name);let s=new URLSearchParams;return o&&s.set("revision_id",o),(await this.tasksApi.runTask(this.orgId,this.projectId,r,o,null,null,n,{data:i})).data}async listApiKeys(){return (await this.apiKeysApi.listApiKeys(this.orgId,this.projectId)).data}async createApiKey(t){return (await this.apiKeysApi.createApiKey(this.orgId,this.projectId,{name:t})).data}};var Q=e=>{let{canRunWithOptions:t=true}=e||{};process.env.TERM_PROGRAM?.toLowerCase().includes("mintty")&&(console.warn(`WARNING: It looks like you are using MinTTY, which is non-interactive. This is most likely because you are
|
|
416
416
|
using Git Bash. If that's that case, please use Git Bash from another terminal, such as Windows Terminal.
|
|
417
|
-
`),t&&console.warn("Alternatively, you can provide the arguments from the CLI directly to skip the prompts."),process.exit(1));};var Ye=async e=>{let t=await ko(e);await new Promise(r=>{t?.addListener("exit",()=>{r();}),setTimeout(()=>{r();},3e3);});};function Y(e){return e.startsWith("~/")?X.join(eo.homedir(),e.slice(2)):X.resolve(e)}function xo(e){return re.existsSync(e)&&re.statSync(e).isDirectory()}function Ze(e,t){let r="$SRC/",o="$PWD/",n=X.join(t,"src"),i=xo(n);if(e.startsWith(r)){let s=i?"./src":"./",a=e.slice(r.length);return s+a}return e.startsWith(o)?"./"+e.slice(o.length):e}var Ge=e=>{let t=false,r=()=>{t||(t=true,process.stdin.removeListener("data",o));},o=n=>{let i=n.toString();(i.includes("\r")||i.includes(`
|
|
417
|
+
`),t&&console.warn("Alternatively, you can provide the arguments from the CLI directly to skip the prompts."),process.exit(1));};var Ye=async e=>{let t=await ko(e);await new Promise(r=>{t?.addListener("exit",()=>{r();}),setTimeout(()=>{r();},3e3);});};function Y(e){return e.startsWith("~/")?X.join(eo.homedir(),e.slice(2)):X.resolve(e)}function xo(e){return re.existsSync(e)&&re.statSync(e).isDirectory()}function Ze(e,t){let r="$SRC/",o="$PWD/",n=X.join(t,"src"),i=xo(n);if(e.startsWith(r)){let s=i?"./src/":"./",a=e.slice(r.length);return s+a}return e.startsWith(o)?"./"+e.slice(o.length):e}var Ge=e=>{let t=false,r=()=>{t||(t=true,process.stdin.removeListener("data",o));},o=n=>{let i=n.toString();(i.includes("\r")||i.includes(`
|
|
418
418
|
`))&&(r(),e());};return process.stdin.on("data",o),r};function rr(e){let t=re.readFileSync(e,"utf8");return parseDocument(t).toJS()}function or(e){return !!e.model_params?.temperature}function bt(e,t){let r=re.readFileSync(e,"utf8"),o=parseDocument(r);if(t.model){o.set("llm_model_id",t.model.id);let i=o.get("llm_model_id",true);if(isScalar(i)&&(i.commentBefore=" Selected model: "+t.model.name),or(t.model)){let s=o.get("llm_config",true),a=`Temperature config is not available to selected model
|
|
419
419
|
temperature: `;if(isMap(s)&&s.commentBefore?.startsWith(a)){let c=s.commentBefore.slice(a.length).trim(),u=parseFloat(c);isNaN(u)||s.set("temperature",u),s.commentBefore=void 0;}}else {let s=o.get("llm_config",true);if(isMap(s)&&s.has("temperature")){let a=s.get("temperature");s.commentBefore=`Temperature config is not available to selected model
|
|
420
420
|
temperature: ${a}`,s.delete("temperature");}}}t.taskName&&o.set("name",t.taskName);let n=o.toString();re.writeFileSync(e,n,"utf8");}async function Co(){let[e,t]=await p(()=>T.fromAuthContext());if(t||!e)return null;let[r,o]=await p(()=>e.listModels());if(o||!r)return null;let i=r.filter(a=>!a.replaced_by);return i.length===0?null:i.find(a=>a.provider.toLowerCase()==="openai")||i[0]}async function nr(e){let t=X.dirname(e),[,r]=p(()=>{t&&t!=="."&&!re.existsSync(t)&&re.mkdirSync(t,{recursive:!0});});if(r){let c=r instanceof Error?r.message:String(r);(f?console.error:m.outro)(`Failed to create directory "${t}": ${c}`),process.exit(1);}let o=`${I.CLI_PUBLIC_TEMPLATES_URL}/create-task.yaml`,n=await fetch(o,{headers:{accept:"text/yaml"},redirect:"manual"});n.ok||((f?console.error:m.outro)(`Failed to download template: Server returned ${n.status} ${n.statusText}`),process.exit(1));let i=await n.text(),s=await Co();if(s){let c=parseDocument(i);c.set("llm_model_id",s.id);let u=c.get("llm_model_id",true);if(isScalar(u)&&(u.commentBefore=" Selected model: "+s.name),!or(s)){let l=c.get("llm_config",true);if(isMap(l)&&l.has("temperature")){let d=l.get("temperature");l.commentBefore=`Temperature config is not available to selected model
|
|
421
|
-
temperature: ${d}`,l.delete("temperature");}}i=c.toString();}let[,a]=p(()=>re.writeFileSync(e,i,"utf8"));if(a){let c=a instanceof Error?a.message:String(a);(f?console.error:m.outro)(`Failed to write file "${e}": ${c}`),process.exit(1);}}function sr(e){e.description("Create a new task").option("-f, --file <file>","Create task from a YAML file.").action(Eo);}async function Eo(e){if(ee.start(),await T.fromAuthContext(),ee.stop(),!e.file){Q();let t=await m.confirm({message:"Create tasks directly from the dashboard",initialValue:true});m.isCancel(t)?(m.outro("Create task cancelled"),process.exit(0)):t?await To():await ir(e);return}await ir(e);}var ee=P();async function To(){let e=await T.fromAuthContext();ee.start();let[t]=await p(()=>e.getProject(e.orgId,e.projectId));ee.stop();let r=t?.name||e.projectId;m.log.info(`Opening dashboard to create task in project: ${j.cyan(r)}`);let o=m.spinner();o.start("Press Enter to open dashboard..."),Ge(async()=>{o.message("Opening dashboard...");let{origin:n}=new URL(I.CLI_PUBLIC_TEMPLATES_URL),i=`${n}/server/org/${e.orgId}/project/${e.projectId}/task/create`,[,s]=await p(()=>Ye(i));s&&(o.stop("Could not open browser automatically."),m.outro(`Please open the URL manually: ${j.cyan(i)}`),process.exit(1)),o.stop("Dashboard opened in your browser"),m.outro(j.green("Please create the task in the dashboard.")),process.exit(0);});}var Et="create-task.yaml";async function ir({file:e}){if(e){let n=Y(e),i=null,s=null,a=null;for(;;){ee.start(),a=await T.fromAuthContext();let d=a,[w,b]=p(()=>rr(n)),[_,h]=await p(()=>d.createTask(w));if(ee.stop(),b&&(M(b),process.exit(1)),h){(f||!isAxiosError(h))&&(M(h),process.exit(1));let R=h.response?.data;if(typeof R=="object"&&R!==null&&"detail"in R&&Array.isArray(R.detail)){let E=R.detail;if(Array.isArray(E)&&E.length>0){if(E.find(x=>typeof x=="object"&&x!==null&&"type"in x&&x.type==="invalid_llm_model")){m.log.error("Invalid LLM model ID detected."),ee.start();let[x,C]=await p(()=>d.listModels());ee.stop(),(C||!x)&&(m.cancel(`Error: Failed to fetch available models. Please run ${j.cyan("npx rightbrain list-models")} to see available models.`),process.exit(1));let O=x.filter(G=>!G.replaced_by);O.length===0&&(m.cancel("Error: No available models found."),process.exit(1));let te=De(O),
|
|
422
|
-
${j.cyan(l)}`),m.outro(j.green("Task created successfully!")),process.exit(0);}let t=await m.text({message:"Where would you like to save the task file?",placeholder:Et,defaultValue:Et,validate(n){if(typeof n=="string"&&n.trim()===".")return "File path cannot be empty"}});m.isCancel(t)&&(m.outro("Create task cancelled"),process.exit(0));let r=t||Et,o=Y(r);if(re.existsSync(o)){let n=await m.confirm({message:`File "${r}" already exists. Overwrite?`,initialValue:false});(m.isCancel(n)||!n)&&(m.outro("Create task cancelled"),process.exit(0));}ee.start(),await nr(o),ee.stop(),m.outro(`Edit the file, then run ${j.cyan(`npx rightbrain create-task --file ${r}`)} to create the task.`),process.exit(0);}function cr(e){return e instanceof Error?e.message:String(e)}var lr=P();async function Je(e,t){lr.start();let[r,o]=await p(async()=>{let s=await fetch(e);if(!s.ok)throw new Error(`Failed to fetch ${t}: ${s.status} ${s.statusText}`);return s});if(lr.stop(),o||!r){let s=cr(o);throw m.log.error(j.red(`Failed to fetch ${t}: ${s}`)),new Error(`Failed to fetch ${t}: ${s}`)}let[n,i]=await p(async()=>{let s=await r.text();return JSON.parse(s)});if(i||!n){let s=cr(i);throw m.log.error(j.red(`Failed to parse ${t}: ${s}`)),new Error(`Failed to parse ${t}: ${s}`)}return n}var _t=null;async function Xe(e){if(_t)return _t;let t=await Je(`${e}/discovery.json`,"discovery configuration");return _t=t,t}function Qe(e){let t=e.map(n=>({...n,version:"0"})).sort((n,i)=>n.created.localeCompare(i.created)),r=1,o=1;for(let n=0;n<t.length;n++)if(!t[n].test)t[n].version=`${r}`,r++,o=1;else {let i=r===1?1:r-1;t[n].version=`${i}.${o}`,o++;}return t.reverse()}var et=e=>{if(!e||e.active_revisions.length===0)return;let t=e.active_revisions[0].weight??0,r=0;for(let n=1;n<e.active_revisions.length;n++){let i=e.active_revisions?.[n]?.weight;typeof i=="number"&&i>t&&(t=i,r=n);}return e?.revisions?.find(n=>n.id===e.active_revisions[r].task_revision_id)};var Ie=null;async function Po(e){if(Ie&&Ie[e])return Ie[e];let t=`${I.CLI_PUBLIC_TEMPLATES_URL}/${e}.eta`,r=await fetch(t);if(!r.ok)throw new Error(`Failed to fetch template ${e}: ${r.status} ${r.statusText}`);let o=await r.text();return Ie||(Ie={}),Ie[e]=o,o}async function pr(e){let t=new Eta({autoEscape:false,autoTrim:false,cache:true}),r=await Po(e);return t.loadTemplate("@task-types",r),t}var dr={TASK_TYPES:"@task-types"};function Ao(e,t="kebab-case"){switch(t){case "camel-case":return `${fr(e)}.ts`;case "kebab-case":return `${Pt(e)}.ts`;case "pascal-case":return `${ur(e)}.ts`;case "snake-case":return `${mr(e)}.ts`}return `${Pt(e)}.ts`}function $o(e){let t=e.match(/^\$\{([^}]+)\}$/);return t?t[1].trim():null}function jo(e){let t={};if(e&&typeof e=="object"&&"generate"in e&&e.generate&&typeof e.generate=="object"&&"taskIds"in e.generate&&Array.isArray(e.generate.taskIds)){for(let r of e.generate.taskIds)if(typeof r=="string"){let o=$o(r);if(o){let n=process.env[o];n&&(t[n]=o);}}}return t}function Lo(e){return e&&typeof e=="object"&&"generate"in e&&e.generate&&typeof e.generate=="object"&&"hardcodeTaskIds"in e.generate?e.generate.hardcodeTaskIds===true:false}function Mo(e,t){let r=Qe(e.revisions||[]),o={...e,revisions:r},n=et({...o,revisions:r});if(!n)return null;let i=t?Lo(t):false,a=(t&&!i?jo(t):{})[o.id]||null;return {task:o,activeRevision:n,taskIdEnvVar:a,utils:{camelCase:fr,kebabCase:Pt,pascalCase:ur,snakeCase:mr}}}var tt=class{constructor(t,r){this.language=t;this.languageConfig=r;}eta=null;initialized=false;async initialize(){this.initialized||(this.eta=await pr(this.language),this.initialized=true);}generate(t,r){if(!this.eta)throw new Error("TypeGenerator not initialized. Call initialize() first.");let o=Mo(t,r);if(!o)return null;let n=this.eta.render(dr.TASK_TYPES,o);return {fileName:Ao(t.name,this.languageConfig.filenameCase),content:n}}generateAll(t,r){let o=[];for(let n of t){let i=this.generate(n,r);i&&o.push(i);}return o}};function Se(e){return e instanceof Error?e.message:String(e)}async function ot(e){let{init:t=false}=e||{},r=zt(),o=r.generate?.outputDir;o||(m.cancel(`Error: No generate.outputDir found in ${r.filePath}`),process.exit(1)),o=X.join(o);let n=r.generate?.taskIds||[];n.length===0&&(m.cancel(`Error: No generate.taskIds found in ${r.filePath}`),process.exit(1));let i=r.generate?.language;i||(m.cancel(`Error: No generate.language found in ${r.filePath}`),process.exit(1));let s=X.dirname(r.filePath),a=X.resolve(s,o),[c,u]=await p(()=>Xe(I.CLI_PUBLIC_TEMPLATES_URL));(u||!c)&&(m.cancel(`Failed to fetch discovery: ${Se(u)}`),process.exit(1));let l=c[i];l||(m.cancel(`Language ${i} is not currently supported.`),process.exit(1));let d=m.spinner();d.start("Generating types");let w=new tt(i,l);await w.initialize();let b=await T.fromConfig(),_=new Set(n),h=[];for(let D of _){let[O,te]=await p(()=>b.getTask(D));if(te){d.stop("Something went wrong"),m.log.warn(j.yellow(`Failed to fetch task ${D}: ${Se(te)}`)),d.start("Generating types");continue}O&&h.push(O);}h.length===0&&!t&&(m.cancel("No valid tasks to generate."),process.exit(0));let[R,E]=p(()=>w.generateAll(h,r.rawConfig));R||(d.stop("Something went wrong"),m.cancel(`Failed to generate types: ${Se(E)}`),process.exit(1));let[,x]=await p(()=>re.promises.mkdir(a,{recursive:!0}));x&&(d.stop("Something went wrong"),m.cancel(`Failed to create output directory: ${Se(x)}`),process.exit(1));let C=[];for(let{fileName:D,content:O}of R){let te=X.join(a,D),[,fe]=await p(()=>re.promises.writeFile(te,O,"utf-8"));if(fe){m.log.warn(j.yellow(`Failed to write ${D}: ${Se(fe)}`));continue}C.push(D);}d.stop(`Generated ${j.cyan(C.length.toString())} file(s) at ${j.green(a)}`),t||m.outro(j.green("Done!"));}function hr(e){e.description("Generate task interface for your RightBrain tasks").action(ot);}var yr=P();function kr(e){return re.existsSync(e)&&re.statSync(e).isFile()}function wr(e){return re.existsSync(e)&&re.statSync(e).isDirectory()}function be(e,t,r){if("all"in e)return e.all.every(o=>be(o,t,r));if("any"in e)return e.any.some(o=>be(o,t,r));if("fileExists"in e)return kr(X.join(t,e.fileExists));if("fileNotExists"in e)return !kr(X.join(t,e.fileNotExists));if("dirExists"in e)return wr(X.join(t,e.dirExists));if("dirNotExists"in e)return !wr(X.join(t,e.dirNotExists));if("fileContains"in e){let o=X.join(t,e.fileContains);if(!re.existsSync(o))return false;try{let n=re.readFileSync(o,"utf-8");return new RegExp(e.pattern,e.flags||"").test(n)}catch{return false}}return "environmentExists"in e?r.has(e.environmentExists):"environmentNotExists"in e?!r.has(e.environmentNotExists):false}function vr(e,t){for(let[r,o]of Object.entries(e))if(o.require){let n=new Set;if(be(o.require,t,n))return r}return null}async function nt(e,t){let r=Object.keys(e);if(r.length===0)throw m.log.error(j.red("No languages available in discovery configuration.")),new Error("No languages available");let o=await m.select({message:"Select a language for your project",options:r.map(s=>({value:s,label:s}))});m.isCancel(o)&&(m.outro("Init cancelled."),process.exit(0));let n=o,i=e[n];if(i.require){let s=new Set;if(!be(i.require,t,s)){let c=i.errorMessage||`Your project does not meet the requirements for ${n}.`;m.log.warn(j.yellow(c));let u=await m.confirm({message:"Do you want to continue anyway?",initialValue:false});if(m.isCancel(u)||!u)return nt(e,t)}}return n}async function So(e,t){let r=await Je(`${e}/${t}.json`,`${t} template`),o={};if(r.environments)for(let[n,i]of Object.entries(r.environments))o[n]={require:i.require,files:[]};return {files:r.files||[],environments:o}}async function Fo(e,t,r){let o=`${e}/${t}-${r}.json`;yr.start();let[n,i]=await p(async()=>{let c=await fetch(o);if(!c.ok){if(c.status===404)return null;throw new Error(`Failed to fetch environment template: ${c.status} ${c.statusText}`)}return c});if(yr.stop(),i||!n)return i&&m.log.warn(j.yellow(`Failed to fetch ${t}-${r} template: ${Be(i)}`)),[];let[s,a]=await p(async()=>{let c=await n.text();return JSON.parse(c)});return a||!s?(m.log.warn(j.yellow(`Failed to parse ${t}-${r} template: ${Be(a)}`)),[]):s.files||[]}function At(e,t){return "environmentNotExists"in e?e.environmentNotExists===t:"all"in e||"any"in e?("all"in e?e.all:e.any).some(o=>At(o,t)):false}function $t(e){return "environmentNotExists"in e?true:"all"in e||"any"in e?("all"in e?e.all:e.any).some(r=>$t(r)):false}function Ro(e,t,r){let o=[],n=new Set(r);for(let[c,u]of Object.entries(e.environments))be(u.require,t,n)&&o.push(c);let i=o.sort((c,u)=>{let l=$t(e.environments[c].require),d=$t(e.environments[u].require);return l&&!d?1:!l&&d?-1:0}),s=[],a=new Set(r);for(let c of i){let u=e.environments[c];if(be(u.require,t,a)&&!s.some(d=>At(e.environments[d].require,c))){for(let d=s.length-1;d>=0;d--){let w=s[d];At(u.require,w)&&(s.splice(d,1),a.delete(w));}s.push(c),a.add(c),r.add(c);}}return s}function xr(e,t){for(let r of e){let o=Ze(r.path,t),n=X.join(t,o),i=X.dirname(n);re.existsSync(i)||re.mkdirSync(i,{recursive:true});try{re.writeFileSync(n,r.content,"utf-8");}catch(s){m.log.warn(j.yellow(`Failed to write ${o}: ${Be(s)}`));}}}async function Cr(e,t,r){let o=await So(r,e),n=new Set,i=0;if(o.files.length>0&&(xr(o.files,t),i+=o.files.length),Object.keys(o.environments).length>0){let s=Ro(o,t,n);for(let a of s){let c=await Fo(r,e,a);c.length>0?(xr(c,t),i+=c.length):m.log.warn(j.yellow(`Environment ${a} matched but has no files to apply`));}}i>0&&m.log.success(`Written ${j.cyan(i.toString())} file(s) to quickly get started!`);}var st="rightbrain.json",br=".env";function Er(e){e.description("Initialize RightBrain configuration for your project").action(Wo);}var Ee=P();async function Bo(e){let t=X.join(e,st);if(re.existsSync(t)){m.log.warn(j.yellow(`A ${st} file already exists at ${e}.`));let r=await m.confirm({message:"Do you want to override the existing configuration?",initialValue:false});(m.isCancel(r)||!r)&&(m.outro("Init cancelled."),process.exit(0));}}async function Oo(e){let[t]=p(()=>(execSync("git rev-parse --is-inside-work-tree",{cwd:e,encoding:"utf-8",stdio:"pipe"}),!0));if(t){let[,r]=p(()=>execSync("git diff --quiet",{cwd:e,encoding:"utf-8"})),o=!!r,[n,i]=p(()=>execSync("git status --porcelain",{cwd:e,encoding:"utf-8"})),s=!i&&n&&n.split(`
|
|
421
|
+
temperature: ${d}`,l.delete("temperature");}}i=c.toString();}let[,a]=p(()=>re.writeFileSync(e,i,"utf8"));if(a){let c=a instanceof Error?a.message:String(a);(f?console.error:m.outro)(`Failed to write file "${e}": ${c}`),process.exit(1);}}function sr(e){e.description("Create a new task").option("-f, --file <file>","Create task from a YAML file.").action(Eo);}async function Eo(e){if(ee.start(),await T.fromAuthContext(),ee.stop(),!e.file){Q();let t=await m.confirm({message:"Create tasks directly from the dashboard",initialValue:true});m.isCancel(t)?(m.outro("Create task cancelled"),process.exit(0)):t?await To():await ir(e);return}await ir(e);}var ee=P();async function To(){let e=await T.fromAuthContext();ee.start();let[t]=await p(()=>e.getProject(e.orgId,e.projectId));ee.stop();let r=t?.name||e.projectId;m.log.info(`Opening dashboard to create task in project: ${j.cyan(r)}`);let o=m.spinner();o.start("Press Enter to open dashboard..."),Ge(async()=>{o.message("Opening dashboard...");let{origin:n}=new URL(I.CLI_PUBLIC_TEMPLATES_URL),i=`${n}/server/org/${e.orgId}/project/${e.projectId}/task/create`,[,s]=await p(()=>Ye(i));s&&(o.stop("Could not open browser automatically."),m.outro(`Please open the URL manually: ${j.cyan(i)}`),process.exit(1)),o.stop("Dashboard opened in your browser"),m.outro(j.green("Please create the task in the dashboard.")),process.exit(0);});}var Et="create-task.yaml";async function ir({file:e}){if(e){let n=Y(e),i=null,s=null,a=null;for(;;){ee.start(),a=await T.fromAuthContext();let d=a,[w,b]=p(()=>rr(n)),[_,h]=await p(()=>d.createTask(w));if(ee.stop(),b&&(M(b),process.exit(1)),h){(f||!isAxiosError(h))&&(M(h),process.exit(1));let R=h.response?.data;if(typeof R=="object"&&R!==null&&"detail"in R&&Array.isArray(R.detail)){let E=R.detail;if(Array.isArray(E)&&E.length>0){if(E.find(x=>typeof x=="object"&&x!==null&&"type"in x&&x.type==="invalid_llm_model")){m.log.error("Invalid LLM model ID detected."),ee.start();let[x,C]=await p(()=>d.listModels());ee.stop(),(C||!x)&&(m.cancel(`Error: Failed to fetch available models. Please run ${j.cyan("npx rightbrain list-models")} to see available models.`),process.exit(1));let O=x.filter(G=>!G.replaced_by);O.length===0&&(m.cancel("Error: No available models found."),process.exit(1));let te=De(O),ue=Array.from(te.keys()).sort(),Ue=[];for(let G of ue){let Br=te.get(G);for(let mt of Br)Ue.push({value:mt.id,label:`${mt.alias} (${G})`,hint:mt.id});}let Mt=await m.autocomplete({message:"Please select a valid LLM model:",options:Ue});m.isCancel(Mt)&&(m.outro("Model selection cancelled"),process.exit(0));let ut=O.find(G=>G.id===Mt);ut||(m.cancel("Error: Selected model not found."),process.exit(1));try{bt(n,{model:ut}),m.log.info(`Updated ${j.cyan(e)} with model: ${j.cyan(ut.alias)}`);}catch(G){m.cancel(`Error: Failed to update file: ${G instanceof Error?G.message:String(G)}`),process.exit(1);}continue}if(E.find(x=>typeof x=="object"&&x!==null&&"type"in x&&x.type==="duplicate_task_name")){m.log.error("Duplicate task name detected.");let x=await m.text({message:"Please enter a unique task name:",placeholder:"Enter task name",initialValue:w&&typeof w=="object"&&"name"in w&&typeof w.name=="string"&&w?.name||"",validate(C){if(typeof C=="string"&&C.trim()===".")return "Task name cannot be empty"}});m.isCancel(x)&&(m.outro("Create task cancelled"),process.exit(0));try{bt(n,{taskName:x}),m.log.info(`Updated ${j.cyan(e)} with task name: ${j.cyan(x)}`);}catch(C){m.outro(`Error: Failed to update file: ${C instanceof Error?C.message:String(C)}`),process.exit(1);}continue}}}}i=_,s=h;break}i||(s?M(s):(f?console.error:m.outro)(j.red("Failed to create task")),process.exit(1));let c=i.id,{origin:u}=new URL(I.CLI_PUBLIC_TEMPLATES_URL),l=`${u}/server/org/${a.orgId}/project/${a.projectId}/task/${c}`;f&&(console.info(JSON.stringify(i,null,2)),process.exit(0)),m.log.info(`Run this task with ${j.cyan(`npx rightbrain run-task --task ${c}`)} command.`),m.log.info(`View in dashboard:
|
|
422
|
+
${j.cyan(l)}`),m.outro(j.green("Task created successfully!")),process.exit(0);}let t=await m.text({message:"Where would you like to save the task file?",placeholder:Et,defaultValue:Et,validate(n){if(typeof n=="string"&&n.trim()===".")return "File path cannot be empty"}});m.isCancel(t)&&(m.outro("Create task cancelled"),process.exit(0));let r=t||Et,o=Y(r);if(re.existsSync(o)){let n=await m.confirm({message:`File "${r}" already exists. Overwrite?`,initialValue:false});(m.isCancel(n)||!n)&&(m.outro("Create task cancelled"),process.exit(0));}ee.start(),await nr(o),ee.stop(),m.outro(`Edit the file, then run ${j.cyan(`npx rightbrain create-task --file ${r}`)} to create the task.`),process.exit(0);}function cr(e){return e instanceof Error?e.message:String(e)}var lr=P();async function Je(e,t){lr.start();let[r,o]=await p(async()=>{let s=await fetch(e);if(!s.ok)throw new Error(`Failed to fetch ${t}: ${s.status} ${s.statusText}`);return s});if(lr.stop(),o||!r){let s=cr(o);throw m.log.error(j.red(`Failed to fetch ${t}: ${s}`)),new Error(`Failed to fetch ${t}: ${s}`)}let[n,i]=await p(async()=>{let s=await r.text();return JSON.parse(s)});if(i||!n){let s=cr(i);throw m.log.error(j.red(`Failed to parse ${t}: ${s}`)),new Error(`Failed to parse ${t}: ${s}`)}return n}var _t=null;async function Xe(e){if(_t)return _t;let t=await Je(`${e}/discovery.json`,"discovery configuration");return _t=t,t}function Qe(e){let t=e.map(n=>({...n,version:"0"})).sort((n,i)=>n.created.localeCompare(i.created)),r=1,o=1;for(let n=0;n<t.length;n++)if(!t[n].test)t[n].version=`${r}`,r++,o=1;else {let i=r===1?1:r-1;t[n].version=`${i}.${o}`,o++;}return t.reverse()}var et=e=>{if(!e||e.active_revisions.length===0)return;let t=e.active_revisions[0].weight??0,r=0;for(let n=1;n<e.active_revisions.length;n++){let i=e.active_revisions?.[n]?.weight;typeof i=="number"&&i>t&&(t=i,r=n);}return e?.revisions?.find(n=>n.id===e.active_revisions[r].task_revision_id)};var be=null;async function Po(e){if(be&&be[e])return be[e];let t=`${I.CLI_PUBLIC_TEMPLATES_URL}/${e}.eta`,r=await fetch(t);if(!r.ok)throw new Error(`Failed to fetch template ${e}: ${r.status} ${r.statusText}`);let o=await r.text();return be||(be={}),be[e]=o,o}async function pr(e){let t=new Eta({autoEscape:false,autoTrim:false,cache:true}),r=await Po(e);return t.loadTemplate("@task-types",r),t}var dr={TASK_TYPES:"@task-types"};function Ao(e,t="kebab-case"){switch(t){case "camel-case":return `${fr(e)}.ts`;case "kebab-case":return `${Pt(e)}.ts`;case "pascal-case":return `${ur(e)}.ts`;case "snake-case":return `${mr(e)}.ts`}return `${Pt(e)}.ts`}function $o(e){let t=e.match(/^\$\{([^}]+)\}$/);return t?t[1].trim():null}function jo(e){let t={};if(e&&typeof e=="object"&&"generate"in e&&e.generate&&typeof e.generate=="object"&&"taskIds"in e.generate&&Array.isArray(e.generate.taskIds)){for(let r of e.generate.taskIds)if(typeof r=="string"){let o=$o(r);if(o){let n=process.env[o];n&&(t[n]=o);}}}return t}function Lo(e){return e&&typeof e=="object"&&"generate"in e&&e.generate&&typeof e.generate=="object"&&"hardcodeTaskIds"in e.generate?e.generate.hardcodeTaskIds===true:false}function Mo(e,t){let r=Qe(e.revisions||[]),o={...e,revisions:r},n=et({...o,revisions:r});if(!n)return null;let i=t?Lo(t):false,a=(t&&!i?jo(t):{})[o.id]||null;return {task:o,activeRevision:n,taskIdEnvVar:a,utils:{camelCase:fr,kebabCase:Pt,pascalCase:ur,snakeCase:mr}}}var tt=class{constructor(t,r){this.language=t;this.languageConfig=r;}eta=null;initialized=false;async initialize(){this.initialized||(this.eta=await pr(this.language),this.initialized=true);}generate(t,r){if(!this.eta)throw new Error("TypeGenerator not initialized. Call initialize() first.");let o=Mo(t,r);if(!o)return null;let n=this.eta.render(dr.TASK_TYPES,o);return {fileName:Ao(t.name,this.languageConfig.filenameCase),content:n}}generateAll(t,r){let o=[];for(let n of t){let i=this.generate(n,r);i&&o.push(i);}return o}};function Se(e){return e instanceof Error?e.message:String(e)}async function ot(e){let{init:t=false}=e||{},r=zt(),o=r.generate?.outputDir;o||(m.cancel(`Error: No generate.outputDir found in ${r.filePath}`),process.exit(1)),o=X.join(o);let n=r.generate?.taskIds||[];n.length===0&&(m.cancel(`Error: No generate.taskIds found in ${r.filePath}`),process.exit(1));let i=r.generate?.language;i||(m.cancel(`Error: No generate.language found in ${r.filePath}`),process.exit(1));let s=X.dirname(r.filePath),a=X.resolve(s,o),[c,u]=await p(()=>Xe(I.CLI_PUBLIC_TEMPLATES_URL));(u||!c)&&(m.cancel(`Failed to fetch discovery: ${Se(u)}`),process.exit(1));let l=c[i];l||(m.cancel(`Language ${i} is not currently supported.`),process.exit(1));let d=m.spinner();d.start("Generating types");let w=new tt(i,l);await w.initialize();let b=await T.fromConfig(),_=new Set(n),h=[];for(let D of _){let[O,te]=await p(()=>b.getTask(D));if(te){d.stop("Something went wrong"),m.log.warn(j.yellow(`Failed to fetch task ${D}: ${Se(te)}`)),d.start("Generating types");continue}O&&h.push(O);}h.length===0&&!t&&(m.cancel("No valid tasks to generate."),process.exit(0));let[R,E]=p(()=>w.generateAll(h,r.rawConfig));R||(d.stop("Something went wrong"),m.cancel(`Failed to generate types: ${Se(E)}`),process.exit(1));let[,x]=await p(()=>re.promises.mkdir(a,{recursive:!0}));x&&(d.stop("Something went wrong"),m.cancel(`Failed to create output directory: ${Se(x)}`),process.exit(1));let C=[];for(let{fileName:D,content:O}of R){let te=X.join(a,D),[,ue]=await p(()=>re.promises.writeFile(te,O,"utf-8"));if(ue){m.log.warn(j.yellow(`Failed to write ${D}: ${Se(ue)}`));continue}C.push(D);}d.stop(`Generated ${j.cyan(C.length.toString())} file(s) at ${j.green(a)}`),t||m.outro(j.green("Done!"));}function hr(e){e.description("Generate task interface for your RightBrain tasks").action(ot);}var yr=P();function kr(e){return re.existsSync(e)&&re.statSync(e).isFile()}function wr(e){return re.existsSync(e)&&re.statSync(e).isDirectory()}function Ee(e,t,r){if("all"in e)return e.all.every(o=>Ee(o,t,r));if("any"in e)return e.any.some(o=>Ee(o,t,r));if("fileExists"in e)return kr(X.join(t,e.fileExists));if("fileNotExists"in e)return !kr(X.join(t,e.fileNotExists));if("dirExists"in e)return wr(X.join(t,e.dirExists));if("dirNotExists"in e)return !wr(X.join(t,e.dirNotExists));if("fileContains"in e){let o=X.join(t,e.fileContains);if(!re.existsSync(o))return false;try{let n=re.readFileSync(o,"utf-8");return new RegExp(e.pattern,e.flags||"").test(n)}catch{return false}}return "environmentExists"in e?r.has(e.environmentExists):"environmentNotExists"in e?!r.has(e.environmentNotExists):false}function vr(e,t){for(let[r,o]of Object.entries(e))if(o.require){let n=new Set;if(Ee(o.require,t,n))return r}return null}async function nt(e,t){let r=Object.keys(e);if(r.length===0)throw m.log.error(j.red("No languages available in discovery configuration.")),new Error("No languages available");let o=await m.select({message:"Select a language for your project",options:r.map(s=>({value:s,label:s}))});m.isCancel(o)&&(m.outro("Init cancelled."),process.exit(0));let n=o,i=e[n];if(i.require){let s=new Set;if(!Ee(i.require,t,s)){let c=i.errorMessage||`Your project does not meet the requirements for ${n}.`;m.log.warn(j.yellow(c));let u=await m.confirm({message:"Do you want to continue anyway?",initialValue:false});if(m.isCancel(u)||!u)return nt(e,t)}}return n}async function So(e,t){let r=await Je(`${e}/${t}.json`,`${t} template`),o={};if(r.environments)for(let[n,i]of Object.entries(r.environments))o[n]={require:i.require,files:[]};return {files:r.files||[],environments:o}}async function Fo(e,t,r){let o=`${e}/${t}-${r}.json`;yr.start();let[n,i]=await p(async()=>{let c=await fetch(o);if(!c.ok){if(c.status===404)return null;throw new Error(`Failed to fetch environment template: ${c.status} ${c.statusText}`)}return c});if(yr.stop(),i||!n)return i&&m.log.warn(j.yellow(`Failed to fetch ${t}-${r} template: ${Be(i)}`)),[];let[s,a]=await p(async()=>{let c=await n.text();return JSON.parse(c)});return a||!s?(m.log.warn(j.yellow(`Failed to parse ${t}-${r} template: ${Be(a)}`)),[]):s.files||[]}function At(e,t){return "environmentNotExists"in e?e.environmentNotExists===t:"all"in e||"any"in e?("all"in e?e.all:e.any).some(o=>At(o,t)):false}function $t(e){return "environmentNotExists"in e?true:"all"in e||"any"in e?("all"in e?e.all:e.any).some(r=>$t(r)):false}function Ro(e,t,r){let o=[],n=new Set(r);for(let[c,u]of Object.entries(e.environments))Ee(u.require,t,n)&&o.push(c);let i=o.sort((c,u)=>{let l=$t(e.environments[c].require),d=$t(e.environments[u].require);return l&&!d?1:!l&&d?-1:0}),s=[],a=new Set(r);for(let c of i){let u=e.environments[c];if(Ee(u.require,t,a)&&!s.some(d=>At(e.environments[d].require,c))){for(let d=s.length-1;d>=0;d--){let w=s[d];At(u.require,w)&&(s.splice(d,1),a.delete(w));}s.push(c),a.add(c),r.add(c);}}return s}function xr(e,t){for(let r of e){let o=Ze(r.path,t),n=X.join(t,o),i=X.dirname(n);re.existsSync(i)||re.mkdirSync(i,{recursive:true});try{re.writeFileSync(n,r.content,"utf-8");}catch(s){m.log.warn(j.yellow(`Failed to write ${o}: ${Be(s)}`));}}}async function Cr(e,t,r){let o=await So(r,e),n=new Set,i=0;if(o.files.length>0&&(xr(o.files,t),i+=o.files.length),Object.keys(o.environments).length>0){let s=Ro(o,t,n);for(let a of s){let c=await Fo(r,e,a);c.length>0?(xr(c,t),i+=c.length):m.log.warn(j.yellow(`Environment ${a} matched but has no files to apply`));}}i>0&&m.log.success(`Written ${j.cyan(i.toString())} file(s) to quickly get started!`);}var st="rightbrain.json",br=".env";function Er(e){e.description("Initialize RightBrain configuration for your project").action(Wo);}var de=P();async function Bo(e){let t=X.join(e,st);if(re.existsSync(t)){m.log.warn(j.yellow(`A ${st} file already exists at ${e}.`));let r=await m.confirm({message:"Do you want to override the existing configuration?",initialValue:false});(m.isCancel(r)||!r)&&(m.outro("Init cancelled."),process.exit(0));}}async function Oo(e){let[t]=p(()=>(execSync("git rev-parse --is-inside-work-tree",{cwd:e,encoding:"utf-8",stdio:"pipe"}),!0));if(t){let[,r]=p(()=>execSync("git diff --quiet",{cwd:e,encoding:"utf-8"})),o=!!r,[n,i]=p(()=>execSync("git status --porcelain",{cwd:e,encoding:"utf-8"})),s=!i&&n&&n.split(`
|
|
423
423
|
`).some(a=>a.trim().startsWith("??"));if(o||s){let a=o&&s?"You have unstaged changes and untracked files in your repository.":o?"You have unstaged changes in your repository.":"You have untracked files in your repository.";m.log.warn(j.yellow(a));let c=await m.confirm({message:"Do you want to continue anyway?",initialValue:false});(m.isCancel(c)||!c)&&(m.outro("Init cancelled. Please stage or stash your changes first."),process.exit(0));}}else m.log.warn(j.yellow(`No git repository detected.
|
|
424
|
-
Files generated in the next step will not be tracked.`));}async function No(){let e,t;try{let r=await Xe(I.CLI_PUBLIC_TEMPLATES_URL),o=vr(r,process.cwd());if(o){let i=await m.confirm({message:`Detected ${j.cyan(o)}, do you want to proceed with it?`,initialValue:!0});m.isCancel(i)&&(m.outro("Init cancelled."),process.exit(0)),i?e=o:e=await nt(r,process.cwd());}else e=await nt(r,process.cwd());t=r[e]?.outputDir||"./lib/rightbrain";}catch(r){let o=r instanceof Error?r.message:String(r);m.log.error(j.red(`Language detection failed: ${o}`)),process.exit(1);}return {selectedLanguage:e,outputDir:Ze(t,process.cwd())}}async function zo(){let e=await V({loadGlobalConfig:true});return {selectedProject:await pe({accessToken:e.accessToken}),context:e}}async function Ir(e,t,r){let o=await m.text({message:"Enter a name for the new API key",placeholder:"my-api-key",validate:s=>{if(!s||s.trim().length===0)return "API key name is required"}});m.isCancel(o)&&(m.outro("Init cancelled."),process.exit(0)),
|
|
424
|
+
Files generated in the next step will not be tracked.`));}async function No(){let e,t;try{let r=await Xe(I.CLI_PUBLIC_TEMPLATES_URL),o=vr(r,process.cwd());if(o){let i=await m.confirm({message:`Detected ${j.cyan(o)}, do you want to proceed with it?`,initialValue:!0});m.isCancel(i)&&(m.outro("Init cancelled."),process.exit(0)),i?e=o:e=await nt(r,process.cwd());}else e=await nt(r,process.cwd());t=r[e]?.outputDir||"./lib/rightbrain";}catch(r){let o=r instanceof Error?r.message:String(r);m.log.error(j.red(`Language detection failed: ${o}`)),process.exit(1);}return {selectedLanguage:e,outputDir:Ze(t,process.cwd())}}async function zo(){let e=await V({loadGlobalConfig:true});return {selectedProject:await pe({accessToken:e.accessToken}),context:e}}async function Ir(e,t,r){let o=await m.text({message:"Enter a name for the new API key",placeholder:"my-api-key",validate:s=>{if(!s||s.trim().length===0)return "API key name is required"}});m.isCancel(o)&&(m.outro("Init cancelled."),process.exit(0)),de.start();let[n,i]=await p(async()=>(await e.createApiKey(t,r,{name:o})).data);return de.stop(),i||!n?(m.log.error(j.red("Failed to create API key.")),null):(m.log.success(`Created API key: ${j.cyan(n.name)}`),{id:n.id,name:n.name,key:n.key})}async function qo({selectedProject:e}){let t=await V({loadGlobalConfig:true});de.start();let r=new APIKeysApi(N(t.accessToken)),[o,n]=await p(async()=>(await r.listApiKeys(e.orgId,e.projectId)).data);de.stop();let i=null,s=false;n&&(m.log.warn(j.yellow(`Unable to fetch API keys.
|
|
425
425
|
Visit dashboard to create or retrieve your API key.`)),s=true);let a=(o||[]).filter(c=>!c.revoked);if(a.length>0){let c="__create_new__",u=await m.autocomplete({message:"Select an API key to use",options:[...a.map(l=>({value:l.id,label:l.name,hint:`Created: ${new Date(l.created).toLocaleDateString()}`})),{value:c,label:"Create a new API key",hint:"Generate a new API key for this project"}]});if(m.isCancel(u)&&(m.outro("Init cancelled."),process.exit(0)),u===c)i=await Ir(r,e.orgId,e.projectId);else {let l=a.find(d=>d.id===u);l&&(i={id:l.id,name:l.name,key:l.key});}}else i=await Ir(r,e.orgId,e.projectId);return {selectedApiKey:i,apiKeysFailed:s}}async function Ko({wd:e,configFilePath:t,selectedApiKey:r,selectedProject:o,language:n,outputDir:i}){let s=X.join(e,i);re.existsSync(s)||re.mkdirSync(s,{recursive:true});let a={$schema:I.CLI_PUBLIC_TEMPLATES_URL+"/schema.json",orgId:"${RB_ORG_ID}",projectId:"${RB_PROJECT_ID}",apiKey:"${RB_API_KEY}",generate:{language:n,outputDir:i,taskIds:[]}};re.writeFileSync(t,JSON.stringify(a,null,2)+`
|
|
426
426
|
`,"utf-8");let c=X.join(e,br),u=r?.key||"<YOUR_API_KEY>",l=`# RightBrain Configuration
|
|
427
427
|
RB_ORG_ID="${o.orgId}"
|
|
@@ -429,7 +429,7 @@ Visit dashboard to create or retrieve your API key.`)),s=true);let a=(o||[]).fil
|
|
|
429
429
|
RB_API_KEY="${u}"
|
|
430
430
|
`,d=false;if(re.existsSync(c)){let b=re.readFileSync(c,"utf-8").endsWith(`
|
|
431
431
|
`)?"":`
|
|
432
|
-
`;re.appendFileSync(c,`${b}${l}`,"utf-8"),d=true;}else re.writeFileSync(c,l,"utf-8");return {isEnvFileUpdated:d,configContent:a}}async function Vo({accessToken:e,orgId:t,projectId:r,config:o,configFilePath:n,outputDir:i,language:s}){let a=new TasksApi(N(e));
|
|
432
|
+
`;re.appendFileSync(c,`${b}${l}`,"utf-8"),d=true;}else re.writeFileSync(c,l,"utf-8");return {isEnvFileUpdated:d,configContent:a}}async function Vo({accessToken:e,orgId:t,projectId:r,config:o,configFilePath:n,outputDir:i,language:s}){let a=new TasksApi(N(e));de.start();let[c,u]=await p(async()=>(await a.listTasks(t,r)).data.results);if(de.stop(),u)return m.log.warn(j.yellow(`Unable to fetch tasks.
|
|
433
433
|
You can manually add task IDs to your config later.`)),false;let l=c||[];if(l.length===0)return m.log.info("No tasks found in this project. You can add task IDs later."),false;let d=await m.autocompleteMultiselect({message:"Select tasks for type generation (type to filter, tab to select)",options:l.map(h=>({value:h.id,label:h.name,hint:h.description?h.description.slice(0,50)+(h.description.length>50?"...":""):void 0})),required:false});if(m.isCancel(d)||d.length===0)return m.log.info("No tasks selected. You can add task IDs later."),false;let w=new Map(l.map(h=>[h.id,h.name])),b=d.map(h=>` /* ${w.get(h)} */ "${h}"`).join(`,
|
|
434
434
|
`),_=`{
|
|
435
435
|
"$schema": "${o.$schema}",
|
|
@@ -444,6 +444,6 @@ ${b}
|
|
|
444
444
|
]
|
|
445
445
|
}
|
|
446
446
|
}
|
|
447
|
-
`;return re.writeFileSync(n,_,"utf-8"),m.log.success(`Added ${j.cyan(d.length.toString())} task(s) to configuration`),true}async function Wo(){Q({canRunWithOptions:false}),V({loadGlobalConfig:true}),await Bo(process.cwd()),await Oo(process.cwd());let{selectedLanguage:e,outputDir:t}=await No(),{selectedProject:r,context:o}=await zo(),{selectedApiKey:n,apiKeysFailed:i}=await qo({selectedProject:r});!n&&!i&&(m.cancel("Error: Failed to select or create an API key."),process.exit(1));let s=X.join(process.cwd(),st),{isEnvFileUpdated:a,configContent:c}=await Ko({configFilePath:s,selectedApiKey:n,selectedProject:r,wd:process.cwd(),language:e,outputDir:t});m.log.success(`Generated ${j.cyan(st)}, and ${a?"updated ":""}${j.cyan(br)}`);try{await Cr(e,process.cwd(),I.CLI_PUBLIC_TEMPLATES_URL);}catch(l){let d=l instanceof Error?l.message:String(l);m.log.error(j.red(`Failed to apply templates: ${d}`)),process.exit(1);}await Vo({accessToken:o.accessToken,orgId:r.orgId,projectId:r.projectId,configFilePath:s,outputDir:t,config:c,language:e})&&await ot({init:true}),m.outro(j.green("RightBrain project initialized successfully!"));}function Tr(e){e.description("List available LLM models").option("-p, --provider <name>","Filter by provider (e.g., openai, anthropic)").option("--json","Output as JSON").option("-c, --compact","Compact output (ID and name only)").action(Zo);}var at=P();function Yo(e){return e>=1e6?`${(e/1e6).toFixed(1)}M`:e>=1e3?`${Math.round(e/1e3)}K`:e.toString()}async function Zo(e){at.start();let t=await T.fromAuthContext();at.stop(),at.start();let[r,o]=await p(()=>t.listModels());at.stop(),(o||!r)&&(M(o||new Error("Failed to fetch models")),process.exit(1));let n=r;n.length===0&&((f?console.error:m.outro)(j.red("No models available")),process.exit(0));let i=n.filter(c=>!c.replaced_by);if(e.provider){let c=e.provider.toLowerCase();i=i.filter(u=>u.provider.toLowerCase().includes(c)||u.vendor.toLowerCase().includes(c)),i.length===0&&((f?console.error:m.outro)(j.red(`No models found for provider: ${e.provider}`)),process.exit(0));}(e.json||f)&&(console.info(JSON.stringify(i,null,2)),process.exit(0));let s=De(i),a=Array.from(s.keys()).sort();if(m.log.info(j.bold(`Available Models (${i.length} total)`)),console.info(),e.compact)for(let c of a){let u=s.get(c);console.info(j.bold(j.cyan(`\u25B8 ${c}`)));for(let l of u)console.info(` ${l.alias}`),console.info(` ${j.dim(l.id)}`);console.info();}else for(let c of a){let u=s.get(c);console.info(j.bold(j.cyan(`\u25B8 ${c}`))+j.dim(` (${u.length} models)`)),console.info();for(let l of u){console.info(` ${j.bold(l.alias)}`),console.info(` ${j.dim("ID:")} ${j.green(l.id)}`);let d=[];l.vendor!==l.provider&&d.push(`via ${l.vendor}`),l.description&&d.push(l.description),l.supports_vision&&d.push(j.magenta("\u{1F441} vision")),l.max_context_window&&d.push(`${Yo(l.max_context_window)} ctx`),d.length>0&&console.info(` ${j.dim(d.join(" \xB7 "))}`),console.info();}}(!e.provider||!e.compact)&&console.info(j.dim("\u2500".repeat(40))),e.provider||console.info(j.dim("Use --provider <name> to filter by provider.")),e.compact||console.info(j.dim("Use --compact for a condensed view."));}function _r(e){e.description("Authenticate with RightBrain").action(Ho);}async function Ho(){Q({canRunWithOptions:false});let e=
|
|
448
|
-
${j.cyan(i)}`):a.message("Browser opened. Waiting for authentication...");}let l=await s;(!l.success||!l.token)&&(a.stop("Authentication failed"),m.cancel(`Error: Authentication failed: ${l.error||"Unknown error"}`),process.exit(1));let d=l.token.expires_in?Date.now()+l.token.expires_in*1e3:void 0;oe({access_token:l.token.access_token,refresh_token:l.token.refresh_token,expires_at:d,org_id:void 0,project_id:void 0}),a.stop(j.green("You're now logged in!"));let w=await pe({accessToken:l.token.access_token});oe({org_id:w.orgId,project_id:w.projectId}),m.outro(j.green("Selected organization and project"));}function Pr(e){e.description("Log out from RightBrain").option("-y, --yes","Skip confirmation prompt").action(Qo);}async function Qo(e){Q({canRunWithOptions:false});let t=
|
|
449
|
-
`)+" If you want to switch projects inside a specific project/config-based setup, please update the orgId and projectId values in your configuration file directly."),(e.orgId||e.projectId)&&(e.orgId||(m.cancel("Organization ID (--org-id) is required when specifying a project ID (--project-id)"),process.exit(1)),e.projectId||(m.cancel("Project ID (--project-id) is required when specifying an organization ID (--org-id)"),process.exit(1)));let r;if(e.orgId||e.projectId){dt.start();let i=e.orgId,s=e.projectId,a=new T({accessToken:t.accessToken,orgId:i,projectId:s}),[c,u]=await p(()=>a.getOrganization(i));(u||!c)&&(M(u||new Error("Organization not found")),process.exit(1)),dt.stop(),m.log.info(`\u2713 Organization access confirmed: ${j.cyan(c.name||i)}`),dt.start();let[l,d]=await p(()=>a.getProject(i,s));(d||!l)&&(M(d||new Error("Project not found")),process.exit(1)),dt.stop(),m.log.info(`\u2713 Project access confirmed: ${j.cyan(l.name||s)}`),r={orgId:i,projectId:s},m.log.success(`Switched to organization: ${j.cyan(c.name||i)}, project: ${j.cyan(l.name||s)}`);}else r=await pe({...await V({loadGlobalConfig:true}),orgId:void 0,projectId:void 0}),m.log.success("Switched successfully");let{orgId:o,projectId:n}=r;oe({org_id:o,project_id:n});}function Ur(e){e.description("Display current user information and selected organization/project").action(dn);}var
|
|
447
|
+
`;return re.writeFileSync(n,_,"utf-8"),m.log.success(`Added ${j.cyan(d.length.toString())} task(s) to configuration`),true}async function Wo(){Q({canRunWithOptions:false}),de.start(),await V({loadGlobalConfig:true}),de.stop(),await Bo(process.cwd()),await Oo(process.cwd());let{selectedLanguage:e,outputDir:t}=await No(),{selectedProject:r,context:o}=await zo(),{selectedApiKey:n,apiKeysFailed:i}=await qo({selectedProject:r});!n&&!i&&(m.cancel("Error: Failed to select or create an API key."),process.exit(1));let s=X.join(process.cwd(),st),{isEnvFileUpdated:a,configContent:c}=await Ko({configFilePath:s,selectedApiKey:n,selectedProject:r,wd:process.cwd(),language:e,outputDir:t});m.log.success(`Generated ${j.cyan(st)}, and ${a?"updated ":""}${j.cyan(br)}`);try{await Cr(e,process.cwd(),I.CLI_PUBLIC_TEMPLATES_URL);}catch(l){let d=l instanceof Error?l.message:String(l);m.log.error(j.red(`Failed to apply templates: ${d}`)),process.exit(1);}await Vo({accessToken:o.accessToken,orgId:r.orgId,projectId:r.projectId,configFilePath:s,outputDir:t,config:c,language:e})&&await ot({init:true}),m.outro(j.green("RightBrain project initialized successfully!"));}function Tr(e){e.description("List available LLM models").option("-p, --provider <name>","Filter by provider (e.g., openai, anthropic)").option("--json","Output as JSON").option("-c, --compact","Compact output (ID and name only)").action(Zo);}var at=P();function Yo(e){return e>=1e6?`${(e/1e6).toFixed(1)}M`:e>=1e3?`${Math.round(e/1e3)}K`:e.toString()}async function Zo(e){at.start();let t=await T.fromAuthContext();at.stop(),at.start();let[r,o]=await p(()=>t.listModels());at.stop(),(o||!r)&&(M(o||new Error("Failed to fetch models")),process.exit(1));let n=r;n.length===0&&((f?console.error:m.outro)(j.red("No models available")),process.exit(0));let i=n.filter(c=>!c.replaced_by);if(e.provider){let c=e.provider.toLowerCase();i=i.filter(u=>u.provider.toLowerCase().includes(c)||u.vendor.toLowerCase().includes(c)),i.length===0&&((f?console.error:m.outro)(j.red(`No models found for provider: ${e.provider}`)),process.exit(0));}(e.json||f)&&(console.info(JSON.stringify(i,null,2)),process.exit(0));let s=De(i),a=Array.from(s.keys()).sort();if(m.log.info(j.bold(`Available Models (${i.length} total)`)),console.info(),e.compact)for(let c of a){let u=s.get(c);console.info(j.bold(j.cyan(`\u25B8 ${c}`)));for(let l of u)console.info(` ${l.alias}`),console.info(` ${j.dim(l.id)}`);console.info();}else for(let c of a){let u=s.get(c);console.info(j.bold(j.cyan(`\u25B8 ${c}`))+j.dim(` (${u.length} models)`)),console.info();for(let l of u){console.info(` ${j.bold(l.alias)}`),console.info(` ${j.dim("ID:")} ${j.green(l.id)}`);let d=[];l.vendor!==l.provider&&d.push(`via ${l.vendor}`),l.description&&d.push(l.description),l.supports_vision&&d.push(j.magenta("\u{1F441} vision")),l.max_context_window&&d.push(`${Yo(l.max_context_window)} ctx`),d.length>0&&console.info(` ${j.dim(d.join(" \xB7 "))}`),console.info();}}(!e.provider||!e.compact)&&console.info(j.dim("\u2500".repeat(40))),e.provider||console.info(j.dim("Use --provider <name> to filter by provider.")),e.compact||console.info(j.dim("Use --compact for a condensed view."));}function _r(e){e.description("Authenticate with RightBrain").action(Ho);}async function Ho(){Q({canRunWithOptions:false});let e=ge();if(e){let[b]=await p(async()=>await new UsersApi(N(e.access_token)).getCurrentUser().then(h=>h.data));if(b){let _=await m.confirm({message:`You are already logged in as ${j.cyan(b.email)}. Do you want to login again?`,initialValue:false});(m.isCancel(_)||!_)&&(m.outro("Login cancelled"),process.exit(0));}}let t=Zt(),r=await Gt(t),o=Jt(),n=Ht(o,r),i=Ut(),s=Dt(o,t,n),a=m.spinner();a.start("Press Enter to open browser for authentication...");let c=new Promise(b=>{let _=Ge(b);s.finally(_);});if((await Promise.race([c.then(()=>({type:"enter"})),s.then(()=>({type:"auth"}))])).type==="enter"){a.message("Opening browser for authentication...");let[,b]=await p(()=>Ye(i));b?m.log.warn(`Could not open browser automatically. Please open the URL manually.
|
|
448
|
+
${j.cyan(i)}`):a.message("Browser opened. Waiting for authentication...");}let l=await s;(!l.success||!l.token)&&(a.stop("Authentication failed"),m.cancel(`Error: Authentication failed: ${l.error||"Unknown error"}`),process.exit(1));let d=l.token.expires_in?Date.now()+l.token.expires_in*1e3:void 0;oe({access_token:l.token.access_token,refresh_token:l.token.refresh_token,expires_at:d,org_id:void 0,project_id:void 0}),a.stop(j.green("You're now logged in!"));let w=await pe({accessToken:l.token.access_token});oe({org_id:w.orgId,project_id:w.projectId}),m.outro(j.green("Selected organization and project"));}function Pr(e){e.description("Log out from RightBrain").option("-y, --yes","Skip confirmation prompt").action(Qo);}async function Qo(e){Q({canRunWithOptions:false});let t=ge();if(!t){m.log.info("You are not logged in.");return}if(!e.yes){let[r]=await p(async()=>await new UsersApi(N(t.access_token)).getCurrentUser().then(n=>n.data));if(r){let o=await m.confirm({message:"Are you sure you want to log out?",initialValue:false});(m.isCancel(o)||!o)&&(m.outro("Logout cancelled"),process.exit(0));}}Kt(),m.log.success(j.green("Successfully logged out!"));}var rn=Pe.url(),$r=async(e,{providedInputNames:t,inputs:r,providedInputs:o})=>{if(t.indexOf(e.param_name)!==-1){r[e.param_name]=o[e.param_name],m.log.info(`${e.param_name}: ${j.cyan(o[e.param_name])}`);return}let i=await m.text({message:`${e.param_name} (${e.input_processor==="perplexity_search"?"Perplexity":"Text"}):`,placeholder:e.input_processor==="perplexity_search"?"e.g., Latest news about renewable energy":"e.g., Text that's contextually relevant to the task",validate:s=>{if(!s)return `${e.param_name} is required`}});m.isCancel(i)&&(m.outro("Run task cancelled"),process.exit(0)),r[e.param_name]=i;},jr={"":$r,perplexity_search:$r,url_fetcher:async(e,{providedInputNames:t,inputs:r,providedInputs:o})=>{if(t.indexOf(e.param_name)!==-1){r[e.param_name]=o[e.param_name],m.log.info(`${e.param_name}: ${j.cyan(o[e.param_name])}`);return}let i=await m.text({message:`${e.param_name} (Web crawler):`,placeholder:"e.g., https://docs.rightbrain.ai/llms-full.txt",validate:s=>{if(!s)return "URL is required";if(!rn.safeParse(s).success)return "Invalid URL format"}});m.isCancel(i)&&(m.outro("Run task cancelled"),process.exit(0)),r[e.param_name]=i;},document_content_extractor:async(e,{files:t,providedFileInputNames:r,providedFiles:o})=>{(!e.config||!("filename"in e.config)||typeof e.config.filename!="string")&&(m.outro(j.red(`ERROR: Unable to find input processor for ${e.param_name}`)),process.exit(1));let n=e.config.filename,i=r.indexOf(n);if(i!==-1){t.push(o[i]),m.log.info(`${e.param_name}: ${j.cyan(n)}`);return}let s=await m.text({message:`${e.param_name} (Document):`,placeholder:"path/to/document.pdf",validate:d=>{if(!d)return "File path is required";let w=Y(d);if(!re.existsSync(w))return "File not found"}});m.isCancel(s)&&(m.outro("Run task cancelled"),process.exit(0));let a=Y(s),c=re.readFileSync(a),l=(await fileTypeFromBuffer(c))?.mime||"application/octet-stream";t.push(new File([c],n,{type:l}));}};function nn(e){let t=e.indexOf("=");return t===-1?null:{key:e.slice(0,t),value:e.slice(t+1)}}function Mr(e){e.description("Run a task").option("-t, --task <id>","Task ID to run").option("-r, --revision <id>","Specific revision ID").option("-i, --input <name=value>","Input parameter (repeatable)",(t,r)=>(r.push(t),r),[]).option("-f, --file <name=path>","File to upload (repeatable)",(t,r)=>(r.push(t),r),[]).option("--image <path>","Image to attach (repeatable)",(t,r)=>(r.push(t),r),[]).option("-d, --direct","Run the task directly without fetching resources first. Recommended for production environments where inputs and files are already provided.").option("--use-fallback-model","Use fallback model for the task").action(sn);}var fe=P();async function sn(e){fe.start();let t=await T.fromAuthContext();fe.stop();let r=await(e.direct||f?cn(e):an(e,t)),o=m.spinner();f?fe.start():o.start("Running task...");let[n,i]=await p(()=>t.runTask({...r,useFallbackModel:e.useFallbackModel}));fe.stop(),(f?console.error:o.stop)(i?"Failed to run task":"Task run successfully"),i&&(M(i),process.exit(1)),console.info(f?JSON.stringify(n,null,2):inspect(n,{depth:null,colors:true}));}function pt(e,t="name=value"){let r={};for(let o of e){let n=nn(o);n||((f?console.error:m.outro)(j.red(`Invalid input format: ${o}. Expected ${t}`)),process.exit(1)),r[n.key]=n.value;}return r}async function Sr(e){return await Promise.all(Object.entries(e).map(async([r,o])=>{let n=Y(o);re.existsSync(n)||((f?console.error:m.outro)(j.red(`Error: File not found: ${o}`)),process.exit(1));let i=re.readFileSync(n),a=(await fileTypeFromBuffer(i))?.mime||"application/octet-stream";return new File([i],r,{type:a})}))}async function Fr(e){return await Promise.all(e.map(async r=>{let o=Y(r);re.existsSync(o)||((f?console.error:m.outro)(j.red(`Error: File not found: ${r}`)),process.exit(1));let n=re.readFileSync(o),s=(await fileTypeFromBuffer(n))?.mime||"application/octet-stream",a=X.basename(o);return new File([n],a,{type:s})}))}async function an(e,t){if(!e.task){fe.start();let[E,x]=await p(()=>t.listTasks());fe.stop(),x&&(M(x),process.exit(1));let C=E;if((!C||C.length===0)&&((f?console.error:m.outro)(j.red("No tasks found in this project.")),(f?console.error:m.outro)("Create a task with `npx rightbrain create-task` command."),process.exit(1)),C.length===1)e.task=C[0].id,(f?console.error:m.log.info)(`Using task: ${j.cyan(C[0].name)}`);else {let D=await m.select({message:"Select a task to run",options:C.map(O=>({value:O.id,label:O.name,hint:O.id}))});m.isCancel(D)&&(m.outro("Run task cancelled"),process.exit(0)),e.task=D;}}fe.start();let[r,o]=await p(()=>t.getTask(e.task));fe.stop(),(o||!r)&&(M(o||new Error("Task not found")),process.exit(1));let n={...r,revisions:Qe(r.revisions||[])},i=n.revisions.length===1?n.revisions[0]:void 0;i||(e.revision?(i=n.revisions?.find(E=>E.id===e.revision||E.version===e.revision),i||((f?console.error:m.outro)(j.red(`Error: Revision ${e.revision} not found`)),process.exit(1))):(i=et(n),i?(f?console.error:m.log.info)("Using active revision"):((f?console.error:m.outro)(j.red("Error: No active revision found for this task. Please specify a revision ID.")),process.exit(1))));let s=i.input_params??[],a=i.input_processors??[],c=i.image_required??false,u=pt(e.input||[]),l=Object.keys(u),d=pt(e.file||[],"name=path"),w=Object.keys(d),b=await Sr(d),_={},h=[];for(let E of s){let x=a.find(D=>D.param_name===E)??{param_name:E,input_processor:""},C=jr[x.input_processor];C||((f?console.error:m.outro)(j.red(`ERROR: Unable to find input processor for ${x.param_name}`)),process.exit(1)),await C(x,{files:h,inputs:_,providedFileInputNames:w,providedFiles:b,providedInputNames:l,providedInputs:u});}let R=await Fr(e.image||[]);if(R.length>0&&!f&&m.log.info(`Image${R.length>1?"s":""}: ${j.cyan(R.map(E=>E.name).join(", "))}`),c&&R.length===0){let E=await m.text({message:"Image required - enter path:",placeholder:"path/to/image.jpg",validate:ue=>{if(!ue)return "Path is required";let Ue=Y(ue);if(!re.existsSync(Ue))return "File not found"}});m.isCancel(E)&&(m.outro("Run task cancelled"),process.exit(0));let x=Y(E),C=re.readFileSync(x),D=X.basename(x),te=(await fileTypeFromBuffer(C))?.mime||"application/octet-stream";R.push(new File([C],D,{type:te}));}return {taskId:n.id,revisionId:i.id,body:{task_input:_,task_files:[...R,...h]}}}async function cn(e){e.task||((f?console.error:m.outro)(j.red("Error: Task ID is required when running directly")),process.exit(1)),H(e.task)||((f?console.error:m.outro)(j.red("Error: Task ID must be a valid UUID when running directly")),process.exit(1)),e.revision&&!H(e.revision)&&((f?console.error:m.outro)(j.red("Error: Revision must be a valid UUID when running directly")),process.exit(1));let t=await Fr(e.image||[]),r=await Sr(pt(e.file||[],"name=path"));return {body:{task_input:pt(e.input||[]),task_files:[...t,...r]},taskId:e.task,revisionId:e.revision}}function Rr(e){e.description("Switch to a different organization and project").option("--org-id <orgId>","Organization ID to switch to").option("--project-id <projectId>","Project ID to switch to").action(ln);}var dt=P();async function ln(e){Q();let t=await V();t.filePath&&m.log.info(j.yellow(`\u26A0\uFE0F This command is for updating the global project/organization context used by the CLI.
|
|
449
|
+
`)+" If you want to switch projects inside a specific project/config-based setup, please update the orgId and projectId values in your configuration file directly."),(e.orgId||e.projectId)&&(e.orgId||(m.cancel("Organization ID (--org-id) is required when specifying a project ID (--project-id)"),process.exit(1)),e.projectId||(m.cancel("Project ID (--project-id) is required when specifying an organization ID (--org-id)"),process.exit(1)));let r;if(e.orgId||e.projectId){dt.start();let i=e.orgId,s=e.projectId,a=new T({accessToken:t.accessToken,orgId:i,projectId:s}),[c,u]=await p(()=>a.getOrganization(i));(u||!c)&&(M(u||new Error("Organization not found")),process.exit(1)),dt.stop(),m.log.info(`\u2713 Organization access confirmed: ${j.cyan(c.name||i)}`),dt.start();let[l,d]=await p(()=>a.getProject(i,s));(d||!l)&&(M(d||new Error("Project not found")),process.exit(1)),dt.stop(),m.log.info(`\u2713 Project access confirmed: ${j.cyan(l.name||s)}`),r={orgId:i,projectId:s},m.log.success(`Switched to organization: ${j.cyan(c.name||i)}, project: ${j.cyan(l.name||s)}`);}else r=await pe({...await V({loadGlobalConfig:true}),orgId:void 0,projectId:void 0}),m.log.success("Switched successfully");let{orgId:o,projectId:n}=r;oe({org_id:o,project_id:n});}function Ur(e){e.description("Display current user information and selected organization/project").action(dn);}var ke=P();async function dn(){let e=await V();if(e.filePath){if(e.orgId&&e.projectId){ke.start();let o=await T.fromConfig(),[n]=await p(async()=>o.getOrganization(e.orgId)),[i]=await p(async()=>o.getProject(e.orgId,e.projectId));ke.stop(),m.log.info(j.bold("Selected Organization & Project:")),m.log.info(` Organization: ${j.cyan(n?.name||e.orgId)}`),m.log.info(` Project: ${j.cyan(i?.name||e.projectId)}`);}process.exit(0);}ke.start();let[t,r]=await p(async()=>await new UsersApi(N(e.accessToken)).getCurrentUser().then(n=>n.data));if((r||!t)&&(ke.stop(),m.cancel("Failed to get user information. Please login again."),process.exit(1)),ke.stop(),m.log.info(j.bold("User Information:")),m.log.info(` Email: ${j.cyan(t.email||"N/A")}`),t.name&&m.log.info(` Name: ${j.cyan(t.name)}`),t.id&&m.log.info(` ID: ${j.cyan(t.id)}`),m.log.info(j.bold("Selected Organization & Project:")),e.orgId&&e.projectId){ke.start();let o=await T.fromAuthContext(),[n]=await p(async()=>o.getOrganization(e.orgId)),[i]=await p(async()=>o.getProject(e.orgId,e.projectId));ke.stop(),m.log.info(` Organization: ${j.cyan(n?.name||e.orgId)}`),m.log.info(` Project: ${j.cyan(i?.name||e.projectId)}`);}else m.log.warn(j.yellow(" No organization and project selected")),m.log.info(" Run `npx rightbrain switch-project` command to select an organization and project");}async function un(){let[,e]=p(()=>{let t=new Command;t.name(Object.keys(_e.bin)[0]).description(_e.description).version(_e.version).option("--config <path>","Path to configuration file").hook("preAction",r=>{(f?console.error:m.intro)(j.dim(`RightBrain CLI ${_e.version}`));let o=r.opts();if(o.config&&Nt(o.config),r.args?.[0]!=="init"){let n=je();n&&(f?console.error:m.log.info)(j.dim(`Using configuration file: ${n.filePath}`));}}),_r(t.command("login")),Pr(t.command("logout")),Er(t.command("init")),Rr(t.command("switch-project")),Ur(t.command("whoami")),sr(t.command("create-task")),Mr(t.command("run-task")),Tr(t.command("list-models")),hr(t.command("generate")),t.parse(process.argv);});e&&(e instanceof Error?console.error("Error:",e.message):console.error("Unknown error occurred"),process.exit(1));}un().catch(console.error);
|