tako-cli 0.1.4 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +1 -1
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -50,4 +50,4 @@ ${o.default.gray(R)} ${r}
50
50
  `)}
51
51
  `)},info:(r)=>{l.message(r,{symbol:o.default.blue(lm)})},success:(r)=>{l.message(r,{symbol:o.default.green(dm)})},step:(r)=>{l.message(r,{symbol:o.default.green(h$)})},warn:(r)=>{l.message(r,{symbol:o.default.yellow(gm)})},warning:(r)=>{l.warn(r)},error:(r)=>{l.message(r,{symbol:o.default.red(vm)})}},W=()=>{let r=c$?["\u25D2","\u25D0","\u25D3","\u25D1"]:["\u2022","o","O","0"],m=c$?80:120,e,a,t=!1,s="",$=(d="")=>{t=!0,e=u$(),s=d.replace(/\.+$/,""),process.stdout.write(`${o.default.gray(x)}
52
52
  `);let h=0,v=0;a=setInterval(()=>{let G=o.default.magenta(r[h]),B=".".repeat(Math.floor(v)).slice(0,3);process.stdout.write(Y.cursor.move(-999,0)),process.stdout.write(Y.erase.down(1)),process.stdout.write(`${G} ${s}${B}`),h=h+1<r.length?h+1:0,v=v<r.length?v+0.125:0},m)},i=(d="",h=0)=>{s=d??s,t=!1,clearInterval(a);let v=h===0?o.default.green(h$):h===1?o.default.red(F$):o.default.red(D$);process.stdout.write(Y.cursor.move(-999,0)),process.stdout.write(Y.erase.down(1)),process.stdout.write(`${v} ${s}
53
- `),e()},b=(d="")=>{s=d??s},c=(d)=>{let h=d>1?"Something went wrong":"Canceled";t&&i(h,d)};return process.on("uncaughtExceptionMonitor",()=>c(2)),process.on("unhandledRejection",()=>c(2)),process.on("SIGINT",()=>c(1)),process.on("SIGTERM",()=>c(1)),process.on("exit",c),{start:$,stop:i,message:b}};function wm(r){return r.startsWith("cr_")&&r.length>10}async function ym(r){try{let e=await(await fetch(`${M}/apiStats/api/get-key-id`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKey:r})})).json();if(e.success&&e.data?.id)return{valid:!0,apiId:e.data.id};return{valid:!1,error:e.error||"Key \u9A8C\u8BC1\u5931\u8D25"}}catch(m){return{valid:!1,error:m instanceof Error?m.message:"\u7F51\u7EDC\u8BF7\u6C42\u5931\u8D25"}}}async function mr(r){if(!wm(r))return{success:!1,error:"Key \u683C\u5F0F\u4E0D\u6B63\u786E\uFF0C\u5FC5\u987B\u4EE5 cr_ \u5F00\u5934"};let m=await ym(r);if(!m.valid)return{success:!1,error:m.error};return await T({apiKey:r,apiId:m.apiId}),{success:!0}}import{join as sr}from"path";var N=null,l$={cn:{npm:"https://registry.npmmirror.com",bun:"https://bun.sh/install",bunMirror:"https://registry.npmmirror.com/-/binary/bun"},global:{npm:"https://registry.npmjs.org",bun:"https://bun.sh/install",bunMirror:null}};async function d$(){if(N)return N;let r=[pm,Sm,Mm];for(let m of r)try{let e=await Promise.race([m(),new Promise((a,t)=>setTimeout(()=>t(Error("timeout")),3000))]);if(e)return N=e,e}catch{}return N="cn","cn"}async function pm(){try{let r=await fetch("http://ip-api.com/json/?fields=countryCode",{signal:AbortSignal.timeout(2000)});if(!r.ok)return null;return(await r.json()).countryCode==="CN"?"cn":"global"}catch{return null}}async function Sm(){try{let r=await fetch("https://ipinfo.io/json",{signal:AbortSignal.timeout(2000)});if(!r.ok)return null;return(await r.json()).country==="CN"?"cn":"global"}catch{return null}}async function Mm(){try{let r=await fetch("https://api.ip.sb/geoip",{signal:AbortSignal.timeout(2000)});if(!r.ok)return null;return(await r.json()).country_code==="CN"?"cn":"global"}catch{return null}}async function fm(){let r=await d$();return l$[r]}async function j(){return(await fm()).npm}async function er(){if(await d$()==="cn")return`curl -fsSL https://bun.sh/install | BUN_INSTALL_MIRROR="${l$.cn.bunMirror}" bash`;return"curl -fsSL https://bun.sh/install | bash"}async function ar(){let r=await d$(),m=l$[r];if(r==="cn")l.info("\u68C0\u6D4B\u5230\u4E2D\u56FD\u5927\u9646\u7F51\u7EDC\uFF0C\u4F7F\u7528\u56FD\u5185\u955C\u50CF\u6E90"),l.message(` npm: ${m.npm}`);else l.info("\u4F7F\u7528\u56FD\u9645\u6E90")}var z=null;function qm(r){return r.startsWith(Q)}async function or(){try{if(!await Bun.file(p).exists())return!1;let m=Bun.spawn([p,"--version"],{stdout:"pipe",stderr:"pipe"});return await m.exited,m.exitCode===0}catch{return!1}}async function Wm(){try{let m=Bun.spawn(["which","unzip"],{stdout:"pipe",stderr:"pipe"});if(await m.exited,m.exitCode===0)return!0}catch{}l.warn("\u6B63\u5728\u5B89\u88C5\u7CFB\u7EDF\u4F9D\u8D56 (unzip)...");let r=["apt-get update -qq && apt-get install -y -qq unzip","yum install -y -q unzip","dnf install -y -q unzip","pacman -S --noconfirm unzip","apk add --quiet unzip"];for(let m of r)try{let e=Bun.spawn(["bash","-c",`sudo ${m} 2>/dev/null || ${m}`],{stdout:"pipe",stderr:"pipe"});if(await e.exited,e.exitCode===0)return!0}catch{}return!1}async function Gm(){let r=W();if(!await Wm())return l.error("\u8BF7\u5148\u624B\u52A8\u5B89\u88C5 unzip: apt install unzip / yum install unzip"),!1;await ar(),r.start("\u6B63\u5728\u5B89\u88C5 Tako \u4E13\u5C5E Bun \u8FD0\u884C\u65F6...");try{await(await import("fs/promises")).mkdir(Q,{recursive:!0});let e=await er(),a=`BUN_INSTALL="${Q}" ${e}`;if(await Bun.spawn(["bash","-c",a],{stdout:"inherit",stderr:"inherit"}).exited!==0)return r.stop("Bun \u5B89\u88C5\u5931\u8D25"),!1;return z=p,r.stop("Tako \u4E13\u5C5E Bun \u5B89\u88C5\u5B8C\u6210"),l.info(`\u5B89\u88C5\u4F4D\u7F6E: ${Q}`),!0}catch(m){return r.stop("Bun \u5B89\u88C5\u5931\u8D25"),!1}}async function Zm(){if(await or())return z=p,!0;return l.warn("\u672A\u68C0\u6D4B\u5230 Tako \u4E13\u5C5E Bun\uFF0C\u6B63\u5728\u81EA\u52A8\u5B89\u88C5..."),l.info("\uFF08\u4E0D\u4F1A\u5F71\u54CD\u60A8\u7CFB\u7EDF\u4E2D\u5DF2\u5B89\u88C5\u7684 Node.js \u6216 Bun\uFF09"),await Gm()}async function g$(){if(z){if(!qm(z))z=p;return z}if(await or())return z=p,p;return p}async function ir(r){try{let m=await j(),e=await fetch(`${m}/${r}/latest`);if(!e.ok)return null;return(await e.json()).version}catch{return null}}async function zm(r){return(await Z()).installedClients[r.id]?.version||null}async function cr(r){let m=P(r.id),e=sr(m,"package.json");try{return await Bun.file(e).exists()}catch{return!1}}async function hr(r){let m=await zm(r);if(!m)return!0;let e=await ir(r.package);if(!e)return!1;return m!==e}async function tr(r,m=!1){let e=W(),a=P(r.id);try{if(!await Zm())return{success:!1,error:"Tako \u4E13\u5C5E Bun \u5B89\u88C5\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u7F51\u7EDC\u6216\u624B\u52A8\u5220\u9664 ~/.tako/bun \u76EE\u5F55\u540E\u91CD\u8BD5"};let t=await cr(r),s=m||await hr(r);if(t&&!s)return{success:!0};let $=t?"\u66F4\u65B0":"\u5B89\u88C5";e.start(`\u6B63\u5728${$} ${r.name}...`),await(await import("fs/promises")).mkdir(a,{recursive:!0});let b=sr(a,"package.json");if(!await Bun.file(b).exists())await Bun.write(b,JSON.stringify({name:`tako-${r.id}`,private:!0,dependencies:{}},null,2));let d=await g$(),h=await j(),v=Bun.spawn([d,"add",r.package,"--registry",h],{cwd:a,stdout:"pipe",stderr:"pipe"});if(await v.exited!==0){let k=await new Response(v.stderr).text();return e.stop(`${$} ${r.name} \u5931\u8D25`),{success:!1,error:k}}let B=await ir(r.package);if(B){let k=await Z();k.installedClients[r.id]={version:B,installedAt:new Date().toISOString()},await T(k)}return e.stop(`${r.name} ${$}\u5B8C\u6210`),{success:!0}}catch(t){return e.stop("\u64CD\u4F5C\u5931\u8D25"),{success:!1,error:t instanceof Error?t.message:"\u672A\u77E5\u9519\u8BEF"}}}async function br(r){if(!await cr(r))return await tr(r);if(await hr(r))return await tr(r,!0);return{success:!0}}async function nr(r){try{let m=await br(r);if(!m.success)return m;let e=await f$();if(!e)return{success:!1,error:"\u672A\u914D\u7F6E API Key"};if(r.setupConfigFiles)await r.setupConfigFiles(e);let a=Z$(r);if(!await Bun.file(a).exists())return{success:!1,error:`\u627E\u4E0D\u5230\u53EF\u6267\u884C\u6587\u4EF6: ${a}`};let s=r.getEnvVars(e),$={...process.env,...s};l.info(`\u542F\u52A8 ${r.name}...`);let i;if(r.runtime==="bun")i=[await g$(),a];else i=[a];return await Bun.spawn(i,{env:$,stdio:["inherit","inherit","inherit"],cwd:process.cwd()}).exited,{success:!0}}catch(m){return{success:!1,error:m instanceof Error?m.message:"\u542F\u52A8\u5931\u8D25"}}}async function lr(){try{let r=await q$();if(!r)return{success:!1,error:"\u672A\u627E\u5230 API ID\uFF0C\u8BF7\u91CD\u65B0\u914D\u7F6E Key"};let e=await(await fetch(`${M}/apiStats/api/user-stats`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiId:r})})).json(),t=await(await fetch(`${M}/apiStats/api/user-model-stats`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiId:r,period:"daily"})})).json();if(!e.success)return{success:!1,error:e.error||e.message||"\u83B7\u53D6\u7EDF\u8BA1\u5931\u8D25"};let s=(t.data||[]).map(($)=>({model:$.model,requests:$.requests,cost:$.formatted?.total||"$0.00"}));return{success:!0,data:{totalRequests:e.data?.usage?.total?.requests||0,totalCost:e.data?.usage?.total?.formattedCost||"$0.00",todayCost:`$${(e.data?.limits?.currentDailyCost||0).toFixed(2)}`,modelStats:s}}}catch(r){return{success:!1,error:r instanceof Error?r.message:"\u7F51\u7EDC\u8BF7\u6C42\u5931\u8D25"}}}function v$(r){return r.toLocaleString("en-US")}var dr="tako-cli",H="0.1.4";function Jm(r,m){let e=r.split(".").map(Number),a=m.split(".").map(Number);for(let t=0;t<3;t++){let s=e[t]||0,$=a[t]||0;if(s>$)return 1;if(s<$)return-1}return 0}async function Qm(){try{let r=await j(),m=await fetch(`${r}/${dr}/latest`,{signal:AbortSignal.timeout(5000)});if(!m.ok)return null;return(await m.json()).version||null}catch{return null}}async function Ym(){let r=await Qm();if(!r)return{hasUpdate:!1,currentVersion:H};return{hasUpdate:Jm(r,H)>0,latestVersion:r,currentVersion:H}}async function jm(r){let m=W();m.start(`\u6B63\u5728\u66F4\u65B0\u5230 v${r}...`);try{let e=await j(),a=Bun.spawn([p,"add","-g",`${dr}@latest`],{stdout:"pipe",stderr:"pipe",env:{...process.env,npm_config_registry:e}});if(await a.exited,a.exitCode===0)return m.stop(`\u66F4\u65B0\u6210\u529F\uFF01\u5DF2\u66F4\u65B0\u5230 v${r}`),!0;else{let t=await new Response(a.stderr).text();return m.stop(`\u66F4\u65B0\u5931\u8D25: ${t||"\u672A\u77E5\u9519\u8BEF"}`),!1}}catch(e){return m.stop(`\u66F4\u65B0\u5931\u8D25: ${e instanceof Error?e.message:"\u672A\u77E5\u9519\u8BEF"}`),!1}}async function gr(){try{let r=await Ym();if(r.hasUpdate&&r.latestVersion){if(l.warn(`\u53D1\u73B0\u65B0\u7248\u672C v${r.latestVersion}\uFF08\u5F53\u524D v${H}\uFF09`),await jm(r.latestVersion))l.info("\u8BF7\u91CD\u65B0\u542F\u52A8 Tako CLI \u4EE5\u4F7F\u7528\u65B0\u7248\u672C"),process.exit(0)}}catch{}}function Hm(){console.log(),console.log(` \uD83D\uDC19 Tako CLI v${H}`),console.log(" \x1B[90m\u6B22\u8FCE\u4F7F\u7528\uFF01\x1B[0m"),console.log()}async function vr(r=!1){if(!r)l.warn("\u672A\u68C0\u6D4B\u5230 API Key"),console.log();let m=await b$({message:r?"\u8BF7\u8F93\u5165\u65B0\u7684 API Key (cr_xxx):":"\u8BF7\u8F93\u5165\u4F60\u7684 API Key (cr_xxx):",placeholder:"cr_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",validate(t){if(!t)return"\u8BF7\u8F93\u5165 API Key";if(!t.startsWith("cr_"))return"Key \u5FC5\u987B\u4EE5 cr_ \u5F00\u5934";if(t.length<10)return"Key \u683C\u5F0F\u4E0D\u6B63\u786E"}});if(X(m))return!1;let e=W();e.start("\u9A8C\u8BC1 Key \u4E2D...");let a=await mr(m);if(a.success)return e.stop("Key \u9A8C\u8BC1\u6210\u529F\uFF01\u5DF2\u4FDD\u5B58\u5230\u914D\u7F6E\u6587\u4EF6"),!0;else return e.stop(`\u9A8C\u8BC1\u5931\u8D25: ${a.error}`),!1}async function Lm(){let r=W();r.start("\u83B7\u53D6\u7528\u91CF\u7EDF\u8BA1...");let m=await lr();if(!m.success){r.stop(`\u83B7\u53D6\u5931\u8D25: ${m.error}`);return}if(r.stop("\u7528\u91CF\u7EDF\u8BA1"),console.log(),console.log(" \uD83D\uDCCA \u7528\u91CF\u7EDF\u8BA1"),console.log(),console.log(` \u603B\u8C03\u7528\u6B21\u6570: ${v$(m.data.totalRequests)} \u6B21`),console.log(` \u603B\u6D88\u8D39: ${m.data.totalCost}`),console.log(` \u4ECA\u65E5\u6D88\u8D39: ${m.data.todayCost}`),m.data.modelStats.length>0)console.log(),console.log(" \u6A21\u578B\u4F7F\u7528\u5206\u5E03 (\u4ECA\u65E5):"),m.data.modelStats.forEach((e,a)=>{let t=a===m.data.modelStats.length-1?"\u2514\u2500":"\u251C\u2500",s=e.model.length>25?e.model.slice(0,22)+"...":e.model;console.log(` ${t} ${s.padEnd(25)} ${v$(e.requests).padStart(6)} \u6B21 ${e.cost.padStart(8)}`)});console.log(),await b$({message:"\u6309\u56DE\u8F66\u952E\u8FD4\u56DE...",placeholder:"",defaultValue:""})}async function Vm(){let m=[...J$().map((a)=>({value:{type:"launch",client:a},label:`\u542F\u52A8 ${a.name}`,hint:a.package})),{value:{type:"stats"},label:"\u67E5\u770B\u7528\u91CF\u7EDF\u8BA1"},{value:{type:"config"},label:"\u914D\u7F6E API Key"},{value:{type:"exit"},label:"\u9000\u51FA"}],e=await rr({message:"\u8BF7\u9009\u62E9\u64CD\u4F5C:",options:m});if(X(e))return null;return e}async function Xm(r){switch(r.type){case"launch":let m=await nr(r.client);if(!m.success)l.error(m.error||"\u542F\u52A8\u5931\u8D25");return!0;case"stats":return await Lm(),!0;case"config":return await vr(!0),!0;case"exit":return!1}}async function xr(){if(Hm(),!await M$()){if(!await vr()){n$("\u518D\u89C1\uFF01");return}}while(!0){let m=await Vm();if(m===null)break;if(!await Xm(m))break}n$("\u518D\u89C1\uFF01")}async function Bm(){await gr(),await xr()}Bm().catch((r)=>{console.error("Tako CLI \u53D1\u751F\u9519\u8BEF:",r),process.exit(1)});
53
+ `),e()},b=(d="")=>{s=d??s},c=(d)=>{let h=d>1?"Something went wrong":"Canceled";t&&i(h,d)};return process.on("uncaughtExceptionMonitor",()=>c(2)),process.on("unhandledRejection",()=>c(2)),process.on("SIGINT",()=>c(1)),process.on("SIGTERM",()=>c(1)),process.on("exit",c),{start:$,stop:i,message:b}};function wm(r){return r.startsWith("cr_")&&r.length>10}async function ym(r){try{let e=await(await fetch(`${M}/apiStats/api/get-key-id`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKey:r})})).json();if(e.success&&e.data?.id)return{valid:!0,apiId:e.data.id};return{valid:!1,error:e.error||"Key \u9A8C\u8BC1\u5931\u8D25"}}catch(m){return{valid:!1,error:m instanceof Error?m.message:"\u7F51\u7EDC\u8BF7\u6C42\u5931\u8D25"}}}async function mr(r){if(!wm(r))return{success:!1,error:"Key \u683C\u5F0F\u4E0D\u6B63\u786E\uFF0C\u5FC5\u987B\u4EE5 cr_ \u5F00\u5934"};let m=await ym(r);if(!m.valid)return{success:!1,error:m.error};return await T({apiKey:r,apiId:m.apiId}),{success:!0}}import{join as sr}from"path";var N=null,l$={cn:{npm:"https://registry.npmmirror.com",bun:"https://bun.sh/install",bunMirror:"https://registry.npmmirror.com/-/binary/bun"},global:{npm:"https://registry.npmjs.org",bun:"https://bun.sh/install",bunMirror:null}};async function d$(){if(N)return N;let r=[pm,Sm,Mm];for(let m of r)try{let e=await Promise.race([m(),new Promise((a,t)=>setTimeout(()=>t(Error("timeout")),3000))]);if(e)return N=e,e}catch{}return N="cn","cn"}async function pm(){try{let r=await fetch("http://ip-api.com/json/?fields=countryCode",{signal:AbortSignal.timeout(2000)});if(!r.ok)return null;return(await r.json()).countryCode==="CN"?"cn":"global"}catch{return null}}async function Sm(){try{let r=await fetch("https://ipinfo.io/json",{signal:AbortSignal.timeout(2000)});if(!r.ok)return null;return(await r.json()).country==="CN"?"cn":"global"}catch{return null}}async function Mm(){try{let r=await fetch("https://api.ip.sb/geoip",{signal:AbortSignal.timeout(2000)});if(!r.ok)return null;return(await r.json()).country_code==="CN"?"cn":"global"}catch{return null}}async function fm(){let r=await d$();return l$[r]}async function j(){return(await fm()).npm}async function er(){if(await d$()==="cn")return`curl -fsSL https://bun.sh/install | BUN_INSTALL_MIRROR="${l$.cn.bunMirror}" bash`;return"curl -fsSL https://bun.sh/install | bash"}async function ar(){let r=await d$(),m=l$[r];if(r==="cn")l.info("\u68C0\u6D4B\u5230\u4E2D\u56FD\u5927\u9646\u7F51\u7EDC\uFF0C\u4F7F\u7528\u56FD\u5185\u955C\u50CF\u6E90"),l.message(` npm: ${m.npm}`);else l.info("\u4F7F\u7528\u56FD\u9645\u6E90")}var z=null;function qm(r){return r.startsWith(Q)}async function or(){try{if(!await Bun.file(p).exists())return!1;let m=Bun.spawn([p,"--version"],{stdout:"pipe",stderr:"pipe"});return await m.exited,m.exitCode===0}catch{return!1}}async function Wm(){try{let m=Bun.spawn(["which","unzip"],{stdout:"pipe",stderr:"pipe"});if(await m.exited,m.exitCode===0)return!0}catch{}l.warn("\u6B63\u5728\u5B89\u88C5\u7CFB\u7EDF\u4F9D\u8D56 (unzip)...");let r=["apt-get update -qq && apt-get install -y -qq unzip","yum install -y -q unzip","dnf install -y -q unzip","pacman -S --noconfirm unzip","apk add --quiet unzip"];for(let m of r)try{let e=Bun.spawn(["bash","-c",`sudo ${m} 2>/dev/null || ${m}`],{stdout:"pipe",stderr:"pipe"});if(await e.exited,e.exitCode===0)return!0}catch{}return!1}async function Gm(){let r=W();if(!await Wm())return l.error("\u8BF7\u5148\u624B\u52A8\u5B89\u88C5 unzip: apt install unzip / yum install unzip"),!1;await ar(),r.start("\u6B63\u5728\u5B89\u88C5 Tako \u4E13\u5C5E Bun \u8FD0\u884C\u65F6...");try{await(await import("fs/promises")).mkdir(Q,{recursive:!0});let e=await er(),a=`BUN_INSTALL="${Q}" ${e}`;if(await Bun.spawn(["bash","-c",a],{stdout:"inherit",stderr:"inherit"}).exited!==0)return r.stop("Bun \u5B89\u88C5\u5931\u8D25"),!1;return z=p,r.stop("Tako \u4E13\u5C5E Bun \u5B89\u88C5\u5B8C\u6210"),l.info(`\u5B89\u88C5\u4F4D\u7F6E: ${Q}`),!0}catch(m){return r.stop("Bun \u5B89\u88C5\u5931\u8D25"),!1}}async function Zm(){if(await or())return z=p,!0;return l.warn("\u672A\u68C0\u6D4B\u5230 Tako \u4E13\u5C5E Bun\uFF0C\u6B63\u5728\u81EA\u52A8\u5B89\u88C5..."),l.info("\uFF08\u4E0D\u4F1A\u5F71\u54CD\u60A8\u7CFB\u7EDF\u4E2D\u5DF2\u5B89\u88C5\u7684 Node.js \u6216 Bun\uFF09"),await Gm()}async function g$(){if(z){if(!qm(z))z=p;return z}if(await or())return z=p,p;return p}async function ir(r){try{let m=await j(),e=await fetch(`${m}/${r}/latest`);if(!e.ok)return null;return(await e.json()).version}catch{return null}}async function zm(r){return(await Z()).installedClients[r.id]?.version||null}async function cr(r){let m=P(r.id),e=sr(m,"package.json");try{return await Bun.file(e).exists()}catch{return!1}}async function hr(r){let m=await zm(r);if(!m)return!0;let e=await ir(r.package);if(!e)return!1;return m!==e}async function tr(r,m=!1){let e=W(),a=P(r.id);try{if(!await Zm())return{success:!1,error:"Tako \u4E13\u5C5E Bun \u5B89\u88C5\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u7F51\u7EDC\u6216\u624B\u52A8\u5220\u9664 ~/.tako/bun \u76EE\u5F55\u540E\u91CD\u8BD5"};let t=await cr(r),s=m||await hr(r);if(t&&!s)return{success:!0};let $=t?"\u66F4\u65B0":"\u5B89\u88C5";e.start(`\u6B63\u5728${$} ${r.name}...`),await(await import("fs/promises")).mkdir(a,{recursive:!0});let b=sr(a,"package.json");if(!await Bun.file(b).exists())await Bun.write(b,JSON.stringify({name:`tako-${r.id}`,private:!0,dependencies:{}},null,2));let d=await g$(),h=await j(),v=Bun.spawn([d,"add",r.package,"--registry",h],{cwd:a,stdout:"pipe",stderr:"pipe"});if(await v.exited!==0){let k=await new Response(v.stderr).text();return e.stop(`${$} ${r.name} \u5931\u8D25`),{success:!1,error:k}}let B=await ir(r.package);if(B){let k=await Z();k.installedClients[r.id]={version:B,installedAt:new Date().toISOString()},await T(k)}return e.stop(`${r.name} ${$}\u5B8C\u6210`),{success:!0}}catch(t){return e.stop("\u64CD\u4F5C\u5931\u8D25"),{success:!1,error:t instanceof Error?t.message:"\u672A\u77E5\u9519\u8BEF"}}}async function br(r){if(!await cr(r))return await tr(r);if(await hr(r))return await tr(r,!0);return{success:!0}}async function nr(r){try{let m=await br(r);if(!m.success)return m;let e=await f$();if(!e)return{success:!1,error:"\u672A\u914D\u7F6E API Key"};if(r.setupConfigFiles)await r.setupConfigFiles(e);let a=Z$(r);if(!await Bun.file(a).exists())return{success:!1,error:`\u627E\u4E0D\u5230\u53EF\u6267\u884C\u6587\u4EF6: ${a}`};let s=r.getEnvVars(e),$={...process.env,...s};l.info(`\u542F\u52A8 ${r.name}...`);let i;if(r.runtime==="bun")i=[await g$(),a];else i=[a];return await Bun.spawn(i,{env:$,stdio:["inherit","inherit","inherit"],cwd:process.cwd()}).exited,{success:!0}}catch(m){return{success:!1,error:m instanceof Error?m.message:"\u542F\u52A8\u5931\u8D25"}}}async function lr(){try{let r=await q$();if(!r)return{success:!1,error:"\u672A\u627E\u5230 API ID\uFF0C\u8BF7\u91CD\u65B0\u914D\u7F6E Key"};let e=await(await fetch(`${M}/apiStats/api/user-stats`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiId:r})})).json(),t=await(await fetch(`${M}/apiStats/api/user-model-stats`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiId:r,period:"daily"})})).json();if(!e.success)return{success:!1,error:e.error||e.message||"\u83B7\u53D6\u7EDF\u8BA1\u5931\u8D25"};let s=(t.data||[]).map(($)=>({model:$.model,requests:$.requests,cost:$.formatted?.total||"$0.00"}));return{success:!0,data:{totalRequests:e.data?.usage?.total?.requests||0,totalCost:e.data?.usage?.total?.formattedCost||"$0.00",todayCost:`$${(e.data?.limits?.currentDailyCost||0).toFixed(2)}`,modelStats:s}}}catch(r){return{success:!1,error:r instanceof Error?r.message:"\u7F51\u7EDC\u8BF7\u6C42\u5931\u8D25"}}}function v$(r){return r.toLocaleString("en-US")}var dr="tako-cli",H="0.1.5";function Jm(r,m){let e=r.split(".").map(Number),a=m.split(".").map(Number);for(let t=0;t<3;t++){let s=e[t]||0,$=a[t]||0;if(s>$)return 1;if(s<$)return-1}return 0}async function Qm(){try{let r=await j(),m=await fetch(`${r}/${dr}/latest`,{signal:AbortSignal.timeout(5000)});if(!m.ok)return null;return(await m.json()).version||null}catch{return null}}async function Ym(){let r=await Qm();if(!r)return{hasUpdate:!1,currentVersion:H};return{hasUpdate:Jm(r,H)>0,latestVersion:r,currentVersion:H}}async function jm(r){let m=W();m.start(`\u6B63\u5728\u66F4\u65B0\u5230 v${r}...`);try{let e=await j(),a=Bun.spawn([p,"add","-g",`${dr}@latest`,"--registry",e],{stdout:"pipe",stderr:"pipe"});if(await a.exited,a.exitCode===0)return m.stop(`\u66F4\u65B0\u6210\u529F\uFF01\u5DF2\u66F4\u65B0\u5230 v${r}`),!0;else{let t=await new Response(a.stderr).text();return m.stop(`\u66F4\u65B0\u5931\u8D25: ${t||"\u672A\u77E5\u9519\u8BEF"}`),!1}}catch(e){return m.stop(`\u66F4\u65B0\u5931\u8D25: ${e instanceof Error?e.message:"\u672A\u77E5\u9519\u8BEF"}`),!1}}async function gr(){try{let r=await Ym();if(r.hasUpdate&&r.latestVersion){if(l.warn(`\u53D1\u73B0\u65B0\u7248\u672C v${r.latestVersion}\uFF08\u5F53\u524D v${H}\uFF09`),await jm(r.latestVersion))l.info("\u8BF7\u91CD\u65B0\u542F\u52A8 Tako CLI \u4EE5\u4F7F\u7528\u65B0\u7248\u672C"),process.exit(0)}}catch{}}function Hm(){console.log(),console.log(` \uD83D\uDC19 Tako CLI v${H}`),console.log(" \x1B[90m\u6B22\u8FCE\u4F7F\u7528\uFF01\x1B[0m"),console.log()}async function vr(r=!1){if(!r)l.warn("\u672A\u68C0\u6D4B\u5230 API Key"),console.log();let m=await b$({message:r?"\u8BF7\u8F93\u5165\u65B0\u7684 API Key (cr_xxx):":"\u8BF7\u8F93\u5165\u4F60\u7684 API Key (cr_xxx):",placeholder:"cr_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",validate(t){if(!t)return"\u8BF7\u8F93\u5165 API Key";if(!t.startsWith("cr_"))return"Key \u5FC5\u987B\u4EE5 cr_ \u5F00\u5934";if(t.length<10)return"Key \u683C\u5F0F\u4E0D\u6B63\u786E"}});if(X(m))return!1;let e=W();e.start("\u9A8C\u8BC1 Key \u4E2D...");let a=await mr(m);if(a.success)return e.stop("Key \u9A8C\u8BC1\u6210\u529F\uFF01\u5DF2\u4FDD\u5B58\u5230\u914D\u7F6E\u6587\u4EF6"),!0;else return e.stop(`\u9A8C\u8BC1\u5931\u8D25: ${a.error}`),!1}async function Lm(){let r=W();r.start("\u83B7\u53D6\u7528\u91CF\u7EDF\u8BA1...");let m=await lr();if(!m.success){r.stop(`\u83B7\u53D6\u5931\u8D25: ${m.error}`);return}if(r.stop("\u7528\u91CF\u7EDF\u8BA1"),console.log(),console.log(" \uD83D\uDCCA \u7528\u91CF\u7EDF\u8BA1"),console.log(),console.log(` \u603B\u8C03\u7528\u6B21\u6570: ${v$(m.data.totalRequests)} \u6B21`),console.log(` \u603B\u6D88\u8D39: ${m.data.totalCost}`),console.log(` \u4ECA\u65E5\u6D88\u8D39: ${m.data.todayCost}`),m.data.modelStats.length>0)console.log(),console.log(" \u6A21\u578B\u4F7F\u7528\u5206\u5E03 (\u4ECA\u65E5):"),m.data.modelStats.forEach((e,a)=>{let t=a===m.data.modelStats.length-1?"\u2514\u2500":"\u251C\u2500",s=e.model.length>25?e.model.slice(0,22)+"...":e.model;console.log(` ${t} ${s.padEnd(25)} ${v$(e.requests).padStart(6)} \u6B21 ${e.cost.padStart(8)}`)});console.log(),await b$({message:"\u6309\u56DE\u8F66\u952E\u8FD4\u56DE...",placeholder:"",defaultValue:""})}async function Vm(){let m=[...J$().map((a)=>({value:{type:"launch",client:a},label:`\u542F\u52A8 ${a.name}`,hint:a.package})),{value:{type:"stats"},label:"\u67E5\u770B\u7528\u91CF\u7EDF\u8BA1"},{value:{type:"config"},label:"\u914D\u7F6E API Key"},{value:{type:"exit"},label:"\u9000\u51FA"}],e=await rr({message:"\u8BF7\u9009\u62E9\u64CD\u4F5C:",options:m});if(X(e))return null;return e}async function Xm(r){switch(r.type){case"launch":let m=await nr(r.client);if(!m.success)l.error(m.error||"\u542F\u52A8\u5931\u8D25");return!0;case"stats":return await Lm(),!0;case"config":return await vr(!0),!0;case"exit":return!1}}async function xr(){if(Hm(),!await M$()){if(!await vr()){n$("\u518D\u89C1\uFF01");return}}while(!0){let m=await Vm();if(m===null)break;if(!await Xm(m))break}n$("\u518D\u89C1\uFF01")}async function Bm(){await gr(),await xr()}Bm().catch((r)=>{console.error("Tako CLI \u53D1\u751F\u9519\u8BEF:",r),process.exit(1)});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tako-cli",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "Tako CLI - AI coding tools launcher",
5
5
  "type": "module",
6
6
  "bin": {