tako-cli 0.1.15 → 0.1.16
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 +1 -1
- package/install.ps1 +37 -15
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -50,6 +50,6 @@ ${s.default.gray(C)} ${r}
|
|
|
50
50
|
`)}
|
|
51
51
|
`)},info:(r)=>{g.message(r,{symbol:s.default.blue(xm)})},success:(r)=>{g.message(r,{symbol:s.default.green(gm)})},step:(r)=>{g.message(r,{symbol:s.default.green(i$)})},warn:(r)=>{g.message(r,{symbol:s.default.yellow(lm)})},warning:(r)=>{g.warn(r)},error:(r)=>{g.message(r,{symbol:s.default.red(dm)})}},f=()=>{let r=o$?["\u25D2","\u25D0","\u25D3","\u25D1"]:["\u2022","o","O","0"],m=o$?80:120,a,e,t=!1,h="",$=(v="")=>{t=!0,a=u$(),h=v.replace(/\.+$/,""),process.stdout.write(`${s.default.gray(y)}
|
|
52
52
|
`);let o=0,d=0;e=setInterval(()=>{let G=s.default.magenta(r[o]),B=".".repeat(Math.floor(d)).slice(0,3);process.stdout.write(j.cursor.move(-999,0)),process.stdout.write(j.erase.down(1)),process.stdout.write(`${G} ${h}${B}`),o=o+1<r.length?o+1:0,d=d<r.length?d+0.125:0},m)},b=(v="",o=0)=>{h=v??h,t=!1,clearInterval(e);let d=o===0?s.default.green(i$):o===1?s.default.red(F$):s.default.red(D$);process.stdout.write(j.cursor.move(-999,0)),process.stdout.write(j.erase.down(1)),process.stdout.write(`${d} ${h}
|
|
53
|
-
`),a()},i=(v="")=>{h=v??h},c=(v)=>{let o=v>1?"Something went wrong":"Canceled";t&&b(o,v)};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:b,message:i}};function wm(r){return r.startsWith("cr_")&&r.length>10}async function nm(r){try{let a=await(await fetch(`${M}/apiStats/api/get-key-id`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKey:r})})).json();if(a.success&&a.data?.id)return{valid:!0,apiId:a.data.id};return{valid:!1,error:a.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 ar(r){if(!wm(r))return{success:!1,error:"Key \u683C\u5F0F\u4E0D\u6B63\u786E\uFF0C\u5FC5\u987B\u4EE5 cr_ \u5F00\u5934"};let m=await nm(r);if(!m.valid)return{success:!1,error:m.error};return await P({apiKey:r,apiId:m.apiId}),{success:!0}}import{join as sr}from"path";var _=null,x$={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 k(){if(_)return _;let r=[pm,Sm,Mm];for(let m of r)try{let a=await Promise.race([m(),new Promise((e,t)=>setTimeout(()=>t(Error("timeout")),3000))]);if(a)return _=a,a}catch{}return _="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 qm(){let r=await k();return x$[r]}async function Y(){return(await qm()).npm}async function er(){if(await k()==="cn")return`curl -fsSL https://bun.sh/install | BUN_INSTALL_MIRROR="${x$.cn.bunMirror}" bash`;return"curl -fsSL https://bun.sh/install | bash"}async function tr(){let r=await k(),m=x$[r];if(r==="cn")g.info("\u68C0\u6D4B\u5230\u4E2D\u56FD\u5927\u9646\u7F51\u7EDC\uFF0C\u4F7F\u7528\u56FD\u5185\u955C\u50CF\u6E90"),g.message(` npm: ${m.npm}`);else g.info("\u4F7F\u7528\u56FD\u9645\u6E90")}var J=null;function Wm(r){return r.startsWith(Z)}async function br(){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 fm(){if(process.platform==="win32")return!0;try{let m=Bun.spawn(["which","unzip"],{stdout:"pipe",stderr:"pipe"});if(await m.exited,m.exitCode===0)return!0}catch{}g.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 a=Bun.spawn(["bash","-c",`sudo ${m} 2>/dev/null || ${m}`],{stdout:"pipe",stderr:"pipe"});if(await a.exited,a.exitCode===0)return!0}catch{}return!1}async function Gm(){let r=f();if(!await fm())return g.error("\u8BF7\u5148\u624B\u52A8\u5B89\u88C5 unzip: apt install unzip / yum install unzip"),!1;await tr(),r.start("\u6B63\u5728\u5B89\u88C5 Tako \u4E13\u5C5E Bun \u8FD0\u884C\u65F6...");try{await(await import("fs/promises")).mkdir(Z,{recursive:!0});let a;if(process.platform==="win32"){let t=await k()==="cn"?'$env:BUN_INSTALL_MIRROR="https://registry.npmmirror.com/-/binary/bun"; ':"",h=`$env:BUN_INSTALL="${Z}"; ${t}irm bun.sh/install.ps1 | iex`;a=await Bun.spawn(["powershell","-Command",h],{stdout:"inherit",stderr:"inherit"}).exited}else{let e=await er(),t=`BUN_INSTALL="${Z}" ${e}`;a=await Bun.spawn(["bash","-c",t],{stdout:"inherit",stderr:"inherit"}).exited}if(a!==0)return r.stop("Bun \u5B89\u88C5\u5931\u8D25"),!1;return J=p,r.stop("Tako \u4E13\u5C5E Bun \u5B89\u88C5\u5B8C\u6210"),g.info(`\u5B89\u88C5\u4F4D\u7F6E: ${Z}`),!0}catch(m){return r.stop("Bun \u5B89\u88C5\u5931\u8D25"),!1}}async function Zm(){if(await br())return J=p,!0;return g.warn("\u672A\u68C0\u6D4B\u5230 Tako \u4E13\u5C5E Bun\uFF0C\u6B63\u5728\u81EA\u52A8\u5B89\u88C5..."),g.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(J){if(!Wm(J))J=p;return J}if(await br())return J=p,p;return p}async function cr(r){try{let m=await Y(),a=await fetch(`${m}/${r}/latest`);if(!a.ok)return null;return(await a.json()).version}catch{return null}}async function zm(r){return(await z()).installedClients[r.id]?.version||null}async function or(r){let m=I(r.id),a=sr(m,"package.json");try{return await Bun.file(a).exists()}catch{return!1}}async function ir(r){let m=await zm(r);if(!m)return!0;let a=await cr(r.package);if(!a)return!1;return m!==a}async function hr(r,m=!1){let a=f(),e=I(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 or(r),h=m||await ir(r);if(t&&!h)return{success:!0};let $=t?"\u66F4\u65B0":"\u5B89\u88C5";a.start(`\u6B63\u5728${$} ${r.name}...`),await(await import("fs/promises")).mkdir(e,{recursive:!0});let i=sr(e,"package.json");if(!await Bun.file(i).exists())await Bun.write(i,JSON.stringify({name:`tako-${r.id}`,private:!0,dependencies:{}},null,2));let v=await g$(),o=await Y(),d=Bun.spawn([v,"add",r.package,"--registry",o],{cwd:e,stdout:"pipe",stderr:"pipe"});if(await d.exited!==0){let E=await new Response(d.stderr).text();return a.stop(`${$} ${r.name} \u5931\u8D25`),{success:!1,error:E}}let B=await cr(r.package);if(B){let E=await z();E.installedClients[r.id]={version:B,installedAt:new Date().toISOString()},await P(E)}return a.stop(`${r.name} ${$}\u5B8C\u6210`),{success:!0}}catch(t){return a.stop("\u64CD\u4F5C\u5931\u8D25"),{success:!1,error:t instanceof Error?t.message:"\u672A\u77E5\u9519\u8BEF"}}}async function vr(r){if(!await or(r))return await hr(r);if(await ir(r))return await hr(r,!0);return{success:!0}}async function xr(r){try{let m=await vr(r);if(!m.success)return m;let a=await q$();if(!a)return{success:!1,error:"\u672A\u914D\u7F6E API Key"};if(r.setupConfigFiles)await r.setupConfigFiles(a);let e=Z$(r);if(!await Bun.file(e).exists())return{success:!1,error:`\u627E\u4E0D\u5230\u53EF\u6267\u884C\u6587\u4EF6: ${e}`};let h=r.getEnvVars(a),$={...process.env,...h};g.info(`\u542F\u52A8 ${r.name}...`);let b;if(r.runtime==="native")b=[e];else b=[await g$(),e];return await Bun.spawn(b,{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 l$(){try{let r=await W$();if(!r)return{success:!1,error:"\u672A\u627E\u5230 API ID\uFF0C\u8BF7\u91CD\u65B0\u914D\u7F6E Key"};let a=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(!a.success)return{success:!1,error:a.error||a.message||"\u83B7\u53D6\u7EDF\u8BA1\u5931\u8D25"};let h=(t.data||[]).map(($)=>({model:$.model,requests:$.requests,cost:$.formatted?.total||"$0.00"}));return{success:!0,data:{totalRequests:a.data?.usage?.total?.requests||0,totalCost:a.data?.usage?.total?.formattedCost||"$0.00",todayCost:`$${(a.data?.limits?.currentDailyCost||0).toFixed(2)}`,modelStats:h}}}catch(r){return{success:!1,error:r instanceof Error?r.message:"\u7F51\u7EDC\u8BF7\u6C42\u5931\u8D25"}}}function d$(r){return r.toLocaleString("en-US")}var gr="tako-cli",H="0.1.15";function Jm(r,m){let a=r.split(".").map(Number),e=m.split(".").map(Number);for(let t=0;t<3;t++){let h=a[t]||0,$=e[t]||0;if(h>$)return 1;if(h<$)return-1}return 0}async function Qm(){try{let r=await Y(),m=await fetch(`${r}/${gr}/latest`,{signal:AbortSignal.timeout(5000)});if(!m.ok)return null;return(await m.json()).version||null}catch{return null}}async function jm(){let r=await Qm();if(!r)return{hasUpdate:!1,currentVersion:H};return{hasUpdate:Jm(r,H)>0,latestVersion:r,currentVersion:H}}async function Ym(r){let m=f();m.start(`\u6B63\u5728\u66F4\u65B0\u5230 v${r}...`);try{let a=await Y(),e=Bun.spawn([p,"add","-g",`${gr}@latest`,"--registry",a],{stdout:"pipe",stderr:"pipe"});if(await e.exited,e.exitCode===0)return m.stop(`\u66F4\u65B0\u6210\u529F\uFF01\u5DF2\u66F4\u65B0\u5230 v${r}`),!0;else{let t=await new Response(e.stderr).text();return m.stop(`\u66F4\u65B0\u5931\u8D25: ${t||"\u672A\u77E5\u9519\u8BEF"}`),!1}}catch(a){return m.stop(`\u66F4\u65B0\u5931\u8D25: ${a instanceof Error?a.message:"\u672A\u77E5\u9519\u8BEF"}`),!1}}async function lr(){try{let r=await jm();if(r.hasUpdate&&r.latestVersion){if(g.warn(`\u53D1\u73B0\u65B0\u7248\u672C v${r.latestVersion}\uFF08\u5F53\u524D v${H}\uFF09`),await Ym(r.latestVersion))g.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 dr(r=!1){if(!r)g.warn("\u672A\u68C0\u6D4B\u5230 API Key"),console.log();let m=await rr({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 a=f();a.start("\u9A8C\u8BC1 Key \u4E2D...");let e=await ar(m);if(e.success)return a.stop("Key \u9A8C\u8BC1\u6210\u529F\uFF01\u5DF2\u4FDD\u5B58\u5230\u914D\u7F6E\u6587\u4EF6"),!0;else return a.stop(`\u9A8C\u8BC1\u5931\u8D25: ${e.error}`),!1}function Lm(r,m){let a=[];if(a.push(""),a.push(" \uD83D\uDCCA \u7528\u91CF\u7EDF\u8BA1"),a.push(""),a.push(` \u603B\u8C03\u7528\u6B21\u6570: ${d$(r.totalRequests)} \u6B21`),a.push(` \u603B\u6D88\u8D39: ${r.totalCost}`),a.push(` \u4ECA\u65E5\u6D88\u8D39: ${r.todayCost}`),r.modelStats.length>0)a.push(""),a.push(" \u6A21\u578B\u4F7F\u7528\u5206\u5E03 (\u4ECA\u65E5):"),r.modelStats.forEach((e,t)=>{let h=t===r.modelStats.length-1?"\u2514\u2500":"\u251C\u2500",$=e.model.length>25?e.model.slice(0,22)+"...":e.model;a.push(` ${h} ${$.padEnd(25)} ${d$(e.requests).padStart(6)} \u6B21 ${e.cost.padStart(8)}`)});return a.push(""),a.push(` \x1B[90m${m}s \u540E\u5237\u65B0 | \u6309\u4EFB\u610F\u952E\u8FD4\u56DE\x1B[0m`),a.join(`
|
|
53
|
+
`),a()},i=(v="")=>{h=v??h},c=(v)=>{let o=v>1?"Something went wrong":"Canceled";t&&b(o,v)};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:b,message:i}};function wm(r){return r.startsWith("cr_")&&r.length>10}async function nm(r){try{let a=await(await fetch(`${M}/apiStats/api/get-key-id`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiKey:r})})).json();if(a.success&&a.data?.id)return{valid:!0,apiId:a.data.id};return{valid:!1,error:a.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 ar(r){if(!wm(r))return{success:!1,error:"Key \u683C\u5F0F\u4E0D\u6B63\u786E\uFF0C\u5FC5\u987B\u4EE5 cr_ \u5F00\u5934"};let m=await nm(r);if(!m.valid)return{success:!1,error:m.error};return await P({apiKey:r,apiId:m.apiId}),{success:!0}}import{join as sr}from"path";var _=null,x$={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 k(){if(_)return _;let r=[pm,Sm,Mm];for(let m of r)try{let a=await Promise.race([m(),new Promise((e,t)=>setTimeout(()=>t(Error("timeout")),3000))]);if(a)return _=a,a}catch{}return _="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 qm(){let r=await k();return x$[r]}async function Y(){return(await qm()).npm}async function er(){if(await k()==="cn")return`curl -fsSL https://bun.sh/install | BUN_INSTALL_MIRROR="${x$.cn.bunMirror}" bash`;return"curl -fsSL https://bun.sh/install | bash"}async function tr(){let r=await k(),m=x$[r];if(r==="cn")g.info("\u68C0\u6D4B\u5230\u4E2D\u56FD\u5927\u9646\u7F51\u7EDC\uFF0C\u4F7F\u7528\u56FD\u5185\u955C\u50CF\u6E90"),g.message(` npm: ${m.npm}`);else g.info("\u4F7F\u7528\u56FD\u9645\u6E90")}var J=null;function Wm(r){return r.startsWith(Z)}async function br(){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 fm(){if(process.platform==="win32")return!0;try{let m=Bun.spawn(["which","unzip"],{stdout:"pipe",stderr:"pipe"});if(await m.exited,m.exitCode===0)return!0}catch{}g.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 a=Bun.spawn(["bash","-c",`sudo ${m} 2>/dev/null || ${m}`],{stdout:"pipe",stderr:"pipe"});if(await a.exited,a.exitCode===0)return!0}catch{}return!1}async function Gm(){let r=f();if(!await fm())return g.error("\u8BF7\u5148\u624B\u52A8\u5B89\u88C5 unzip: apt install unzip / yum install unzip"),!1;await tr(),r.start("\u6B63\u5728\u5B89\u88C5 Tako \u4E13\u5C5E Bun \u8FD0\u884C\u65F6...");try{await(await import("fs/promises")).mkdir(Z,{recursive:!0});let a;if(process.platform==="win32"){let t=await k()==="cn"?'$env:BUN_INSTALL_MIRROR="https://registry.npmmirror.com/-/binary/bun"; ':"",h=`$env:BUN_INSTALL="${Z}"; ${t}irm bun.sh/install.ps1 | iex`;a=await Bun.spawn(["powershell","-Command",h],{stdout:"inherit",stderr:"inherit"}).exited}else{let e=await er(),t=`BUN_INSTALL="${Z}" ${e}`;a=await Bun.spawn(["bash","-c",t],{stdout:"inherit",stderr:"inherit"}).exited}if(a!==0)return r.stop("Bun \u5B89\u88C5\u5931\u8D25"),!1;return J=p,r.stop("Tako \u4E13\u5C5E Bun \u5B89\u88C5\u5B8C\u6210"),g.info(`\u5B89\u88C5\u4F4D\u7F6E: ${Z}`),!0}catch(m){return r.stop("Bun \u5B89\u88C5\u5931\u8D25"),!1}}async function Zm(){if(await br())return J=p,!0;return g.warn("\u672A\u68C0\u6D4B\u5230 Tako \u4E13\u5C5E Bun\uFF0C\u6B63\u5728\u81EA\u52A8\u5B89\u88C5..."),g.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(J){if(!Wm(J))J=p;return J}if(await br())return J=p,p;return p}async function cr(r){try{let m=await Y(),a=await fetch(`${m}/${r}/latest`);if(!a.ok)return null;return(await a.json()).version}catch{return null}}async function zm(r){return(await z()).installedClients[r.id]?.version||null}async function or(r){let m=I(r.id),a=sr(m,"package.json");try{return await Bun.file(a).exists()}catch{return!1}}async function ir(r){let m=await zm(r);if(!m)return!0;let a=await cr(r.package);if(!a)return!1;return m!==a}async function hr(r,m=!1){let a=f(),e=I(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 or(r),h=m||await ir(r);if(t&&!h)return{success:!0};let $=t?"\u66F4\u65B0":"\u5B89\u88C5";a.start(`\u6B63\u5728${$} ${r.name}...`),await(await import("fs/promises")).mkdir(e,{recursive:!0});let i=sr(e,"package.json");if(!await Bun.file(i).exists())await Bun.write(i,JSON.stringify({name:`tako-${r.id}`,private:!0,dependencies:{}},null,2));let v=await g$(),o=await Y(),d=Bun.spawn([v,"add",r.package,"--registry",o],{cwd:e,stdout:"pipe",stderr:"pipe"});if(await d.exited!==0){let E=await new Response(d.stderr).text();return a.stop(`${$} ${r.name} \u5931\u8D25`),{success:!1,error:E}}let B=await cr(r.package);if(B){let E=await z();E.installedClients[r.id]={version:B,installedAt:new Date().toISOString()},await P(E)}return a.stop(`${r.name} ${$}\u5B8C\u6210`),{success:!0}}catch(t){return a.stop("\u64CD\u4F5C\u5931\u8D25"),{success:!1,error:t instanceof Error?t.message:"\u672A\u77E5\u9519\u8BEF"}}}async function vr(r){if(!await or(r))return await hr(r);if(await ir(r))return await hr(r,!0);return{success:!0}}async function xr(r){try{let m=await vr(r);if(!m.success)return m;let a=await q$();if(!a)return{success:!1,error:"\u672A\u914D\u7F6E API Key"};if(r.setupConfigFiles)await r.setupConfigFiles(a);let e=Z$(r);if(!await Bun.file(e).exists())return{success:!1,error:`\u627E\u4E0D\u5230\u53EF\u6267\u884C\u6587\u4EF6: ${e}`};let h=r.getEnvVars(a),$={...process.env,...h};g.info(`\u542F\u52A8 ${r.name}...`);let b;if(r.runtime==="native")b=[e];else b=[await g$(),e];return await Bun.spawn(b,{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 l$(){try{let r=await W$();if(!r)return{success:!1,error:"\u672A\u627E\u5230 API ID\uFF0C\u8BF7\u91CD\u65B0\u914D\u7F6E Key"};let a=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(!a.success)return{success:!1,error:a.error||a.message||"\u83B7\u53D6\u7EDF\u8BA1\u5931\u8D25"};let h=(t.data||[]).map(($)=>({model:$.model,requests:$.requests,cost:$.formatted?.total||"$0.00"}));return{success:!0,data:{totalRequests:a.data?.usage?.total?.requests||0,totalCost:a.data?.usage?.total?.formattedCost||"$0.00",todayCost:`$${(a.data?.limits?.currentDailyCost||0).toFixed(2)}`,modelStats:h}}}catch(r){return{success:!1,error:r instanceof Error?r.message:"\u7F51\u7EDC\u8BF7\u6C42\u5931\u8D25"}}}function d$(r){return r.toLocaleString("en-US")}var gr="tako-cli",H="0.1.16";function Jm(r,m){let a=r.split(".").map(Number),e=m.split(".").map(Number);for(let t=0;t<3;t++){let h=a[t]||0,$=e[t]||0;if(h>$)return 1;if(h<$)return-1}return 0}async function Qm(){try{let r=await Y(),m=await fetch(`${r}/${gr}/latest`,{signal:AbortSignal.timeout(5000)});if(!m.ok)return null;return(await m.json()).version||null}catch{return null}}async function jm(){let r=await Qm();if(!r)return{hasUpdate:!1,currentVersion:H};return{hasUpdate:Jm(r,H)>0,latestVersion:r,currentVersion:H}}async function Ym(r){let m=f();m.start(`\u6B63\u5728\u66F4\u65B0\u5230 v${r}...`);try{let a=await Y(),e=Bun.spawn([p,"add","-g",`${gr}@latest`,"--registry",a],{stdout:"pipe",stderr:"pipe"});if(await e.exited,e.exitCode===0)return m.stop(`\u66F4\u65B0\u6210\u529F\uFF01\u5DF2\u66F4\u65B0\u5230 v${r}`),!0;else{let t=await new Response(e.stderr).text();return m.stop(`\u66F4\u65B0\u5931\u8D25: ${t||"\u672A\u77E5\u9519\u8BEF"}`),!1}}catch(a){return m.stop(`\u66F4\u65B0\u5931\u8D25: ${a instanceof Error?a.message:"\u672A\u77E5\u9519\u8BEF"}`),!1}}async function lr(){try{let r=await jm();if(r.hasUpdate&&r.latestVersion){if(g.warn(`\u53D1\u73B0\u65B0\u7248\u672C v${r.latestVersion}\uFF08\u5F53\u524D v${H}\uFF09`),await Ym(r.latestVersion))g.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 dr(r=!1){if(!r)g.warn("\u672A\u68C0\u6D4B\u5230 API Key"),console.log();let m=await rr({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 a=f();a.start("\u9A8C\u8BC1 Key \u4E2D...");let e=await ar(m);if(e.success)return a.stop("Key \u9A8C\u8BC1\u6210\u529F\uFF01\u5DF2\u4FDD\u5B58\u5230\u914D\u7F6E\u6587\u4EF6"),!0;else return a.stop(`\u9A8C\u8BC1\u5931\u8D25: ${e.error}`),!1}function Lm(r,m){let a=[];if(a.push(""),a.push(" \uD83D\uDCCA \u7528\u91CF\u7EDF\u8BA1"),a.push(""),a.push(` \u603B\u8C03\u7528\u6B21\u6570: ${d$(r.totalRequests)} \u6B21`),a.push(` \u603B\u6D88\u8D39: ${r.totalCost}`),a.push(` \u4ECA\u65E5\u6D88\u8D39: ${r.todayCost}`),r.modelStats.length>0)a.push(""),a.push(" \u6A21\u578B\u4F7F\u7528\u5206\u5E03 (\u4ECA\u65E5):"),r.modelStats.forEach((e,t)=>{let h=t===r.modelStats.length-1?"\u2514\u2500":"\u251C\u2500",$=e.model.length>25?e.model.slice(0,22)+"...":e.model;a.push(` ${h} ${$.padEnd(25)} ${d$(e.requests).padStart(6)} \u6B21 ${e.cost.padStart(8)}`)});return a.push(""),a.push(` \x1B[90m${m}s \u540E\u5237\u65B0 | \u6309\u4EFB\u610F\u952E\u8FD4\u56DE\x1B[0m`),a.join(`
|
|
54
54
|
`)}async function Vm(){let m=f();m.start("\u83B7\u53D6\u7528\u91CF\u7EDF\u8BA1...");let a=await l$();if(!a.success){m.stop(`\u83B7\u53D6\u5931\u8D25: ${a.error}`);return}m.stop("");let e=10,t="",h=()=>{if(t){let b=t.split(`
|
|
55
55
|
`).length;process.stdout.write(`\x1B[${b}A\x1B[0J`)}t=Lm(a.data,e),console.log(t)};h();let $=process.stdin.isRaw;if(process.stdin.isTTY)process.stdin.setRawMode(!0);return process.stdin.resume(),new Promise((b)=>{let i=!0,c=()=>{if(!i)return;i=!1,o(),b()},v=setInterval(async()=>{if(!i)return;if(e--,e<=0){e=10;let d=await l$();if(d.success)a=d}h()},1000),o=()=>{if(clearInterval(v),process.stdin.removeListener("data",c),process.stdin.isTTY)process.stdin.setRawMode($??!1);process.stdin.pause()};process.stdin.on("data",c)})}async function Xm(){let m=[...J$().map((e)=>({value:{type:"launch",client:e},label:`\u542F\u52A8 ${e.name}`,hint:e.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"}],a=await mr({message:"\u8BF7\u9009\u62E9\u64CD\u4F5C:",options:m});if(X(a))return null;return a}async function km(r){switch(r.type){case"launch":let m=await xr(r.client);if(!m.success)g.error(m.error||"\u542F\u52A8\u5931\u8D25");return!0;case"stats":return await Vm(),!0;case"config":return await dr(!0),!0;case"exit":return!1}}async function yr(){if(Hm(),!await M$()){if(!await dr()){v$("\u518D\u89C1\uFF01");return}}while(!0){let m=await Xm();if(m===null)break;if(!await km(m))break}v$("\u518D\u89C1\uFF01")}async function Bm(){await lr(),await yr()}Bm().catch((r)=>{console.error("Tako CLI \u53D1\u751F\u9519\u8BEF:",r),process.exit(1)});
|
package/install.ps1
CHANGED
|
@@ -144,19 +144,24 @@ function Create-Command {
|
|
|
144
144
|
New-Item -ItemType Directory -Force -Path $TAKO_BIN_DIR | Out-Null
|
|
145
145
|
|
|
146
146
|
# 创建 tako.cmd 批处理文件
|
|
147
|
-
|
|
147
|
+
# 使用单引号 here-string 防止变量展开,然后手动替换
|
|
148
|
+
$cmdTemplate = @'
|
|
148
149
|
@echo off
|
|
149
|
-
"
|
|
150
|
-
|
|
151
|
-
$cmdContent
|
|
150
|
+
"{{BUN_PATH}}" "{{TAKO_ENTRY}}" %*
|
|
151
|
+
'@
|
|
152
|
+
$cmdContent = $cmdTemplate.Replace("{{BUN_PATH}}", $bun).Replace("{{TAKO_ENTRY}}", $TakoEntry)
|
|
153
|
+
[System.IO.File]::WriteAllText("$TAKO_BIN_DIR\tako.cmd", $cmdContent)
|
|
152
154
|
|
|
153
155
|
# 创建 tako.ps1 PowerShell 脚本(可选)
|
|
154
|
-
$
|
|
155
|
-
& "
|
|
156
|
-
|
|
157
|
-
$ps1Content
|
|
158
|
-
|
|
159
|
-
|
|
156
|
+
$ps1Template = @'
|
|
157
|
+
& "{{BUN_PATH}}" "{{TAKO_ENTRY}}" @args
|
|
158
|
+
'@
|
|
159
|
+
$ps1Content = $ps1Template.Replace("{{BUN_PATH}}", $bun).Replace("{{TAKO_ENTRY}}", $TakoEntry)
|
|
160
|
+
[System.IO.File]::WriteAllText("$TAKO_BIN_DIR\tako.ps1", $ps1Content, [System.Text.Encoding]::UTF8)
|
|
161
|
+
|
|
162
|
+
Write-Info "tako 命令已创建:"
|
|
163
|
+
Write-Info " - $TAKO_BIN_DIR\tako.cmd"
|
|
164
|
+
Write-Info " - $TAKO_BIN_DIR\tako.ps1"
|
|
160
165
|
}
|
|
161
166
|
|
|
162
167
|
# 配置 PATH 环境变量
|
|
@@ -182,22 +187,39 @@ function Setup-Path {
|
|
|
182
187
|
|
|
183
188
|
# 验证安装
|
|
184
189
|
function Verify-Installation {
|
|
185
|
-
#
|
|
190
|
+
# 刷新当前会话的环境变量
|
|
186
191
|
$env:Path = "$TAKO_BIN_DIR;$env:Path"
|
|
187
192
|
|
|
188
193
|
$takoCmd = "$TAKO_BIN_DIR\tako.cmd"
|
|
194
|
+
$takoCmdPs1 = "$TAKO_BIN_DIR\tako.ps1"
|
|
189
195
|
|
|
190
196
|
if (Test-Path $takoCmd) {
|
|
191
197
|
Write-Host ""
|
|
192
|
-
Write-
|
|
198
|
+
Write-Host " ✓ 安装成功!" -ForegroundColor Green
|
|
193
199
|
Write-Host ""
|
|
194
200
|
Write-Host " 运行 'tako' 开始使用" -ForegroundColor Cyan
|
|
195
201
|
Write-Host ""
|
|
196
|
-
|
|
197
|
-
|
|
202
|
+
|
|
203
|
+
# 测试 tako 命令是否可用
|
|
204
|
+
try {
|
|
205
|
+
$testResult = & $takoCmd --version 2>&1
|
|
206
|
+
if ($LASTEXITCODE -eq 0 -or $testResult) {
|
|
207
|
+
Write-Host " ✓ tako 命令已可用" -ForegroundColor Green
|
|
208
|
+
}
|
|
209
|
+
} catch {
|
|
210
|
+
Write-Host " 注意: 如果 'tako' 命令无法识别,请尝试:" -ForegroundColor Yellow
|
|
211
|
+
Write-Host ""
|
|
212
|
+
Write-Host " 1. 重新打开终端窗口 (推荐)" -ForegroundColor Cyan
|
|
213
|
+
Write-Host ""
|
|
214
|
+
Write-Host " 2. 或在当前终端运行:" -ForegroundColor Cyan
|
|
215
|
+
Write-Host " `$env:Path = `"$TAKO_BIN_DIR;`$env:Path`"" -ForegroundColor Gray
|
|
216
|
+
Write-Host ""
|
|
217
|
+
Write-Host " 3. 或直接使用完整路径:" -ForegroundColor Cyan
|
|
218
|
+
Write-Host " $takoCmd" -ForegroundColor Gray
|
|
219
|
+
}
|
|
198
220
|
Write-Host ""
|
|
199
221
|
} else {
|
|
200
|
-
Write-Err "
|
|
222
|
+
Write-Err "安装验证失败: tako.cmd 文件不存在"
|
|
201
223
|
}
|
|
202
224
|
}
|
|
203
225
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tako-cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.16",
|
|
4
4
|
"description": "Tako CLI - AI coding tools launcher",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"scripts": {
|
|
15
15
|
"build": "bun run scripts/build.ts",
|
|
16
16
|
"bump": "bun scripts/bump.ts",
|
|
17
|
-
"release": "bun scripts/bump.ts patch && npm publish",
|
|
17
|
+
"release": "bun scripts/bump.ts patch && npm publish && bun scripts/sync-gitee.ts",
|
|
18
18
|
"prepublishOnly": "bun run build"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|