tenicli 0.3.3 → 0.3.4

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 +78 -78
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import{createRequire as t0}from"node:module";var n0=Object.defineProperty;var o0=(Z)=>Z;function r0(Z,$){this[Z]=o0.bind(null,$)}var O0=(Z,$)=>{for(var Q in $)n0(Z,Q,{get:$[Q],enumerable:!0,configurable:!0,set:r0.bind($,Q)})};var C=(Z,$)=>()=>(Z&&($=Z(Z=0)),$);var Z0=t0(import.meta.url);import{existsSync as a,readFileSync as Q0,writeFileSync as s0,mkdirSync as e0}from"fs";import{join as h}from"path";function G0(){let Z=process.env.HOME||process.env.USERPROFILE||"";return h(Z,".tenicli")}function $0(){return h(G0(),"config.json")}function i(){try{if(a($0()))return JSON.parse(Q0($0(),"utf8"))}catch{}return{}}function c(Z){let $=G0();if(!a($))e0($,{recursive:!0});let Q=i(),V={...Q,...Z,keys:{...Q.keys,...Z.keys},baseUrls:{...Q.baseUrls,...Z.baseUrls}};s0($0(),JSON.stringify(V,null,2),"utf8")}function n(){let Z=process.cwd();F0(h(Z,".tenicli.env")),F0(h(Z,".env"));let $=i(),Q=process.env,V=Q.TENICLI_MODEL||$.activeModel||u[0].id,Y=u.find((W)=>W.id===V)?.provider||Q.TENICLI_PROVIDER||"anthropic",J=Z1(Y,$,Q),K=Y==="openai"?"https://api.openai.com":"https://api.anthropic.com",X=Q.TENICLI_BASE_URL||$.baseUrls?.[Y]||K;return{provider:{type:Y,baseUrl:X,apiKey:J,model:V},maxTokens:parseInt(Q.TENICLI_MAX_TOKENS||"8192"),systemPrompt:$1(Z),cwd:Z}}function Z1(Z,$,Q){if(Z==="anthropic")return Q.TENICLI_API_KEY||Q.ANTHROPIC_API_KEY||$.keys?.anthropic||"";if(Z==="openai")return Q.TENICLI_API_KEY||Q.OPENAI_API_KEY||$.keys?.openai||"";return Q.TENICLI_API_KEY||""}function F0(Z){try{if(!a(Z))return;for(let $ of Q0(Z,"utf8").split(`
3
- `)){let Q=$.trim();if(!Q||Q.startsWith("#"))continue;let V=Q.indexOf("=");if(V===-1)continue;let z=Q.slice(0,V).trim(),Y=Q.slice(V+1).trim();if(Y.startsWith('"')&&Y.endsWith('"')||Y.startsWith("'")&&Y.endsWith("'"))Y=Y.slice(1,-1);if(!process.env[z])process.env[z]=Y}}catch{}}function $1(Z){for(let $ of[h(Z,"TENICLI.md"),h(G0(),"TENICLI.md")])if(a($))return Q0($,"utf8");return Q1}var u,Q1=`You are TeniCLI, a fast AI coding assistant in the terminal.
2
+ import{createRequire as Z1}from"node:module";var t0=Object.defineProperty;var s0=(Z)=>Z;function e0(Z,$){this[Z]=s0.bind(null,$)}var O0=(Z,$)=>{for(var Q in $)t0(Z,Q,{get:$[Q],enumerable:!0,configurable:!0,set:e0.bind($,Q)})};var T=(Z,$)=>()=>(Z&&($=Z(Z=0)),$);var Q0=Z1(import.meta.url);import{existsSync as a,readFileSync as z0,writeFileSync as $1,mkdirSync as Q1}from"fs";import{join as y}from"path";function G0(){let Z=process.env.HOME||process.env.USERPROFILE||"";return y(Z,".tenicli")}function V0(){return y(G0(),"config.json")}function i(){try{if(a(V0()))return JSON.parse(z0(V0(),"utf8"))}catch{}return{}}function c(Z){let $=G0();if(!a($))Q1($,{recursive:!0});let Q=i(),z={...Q,...Z,keys:{...Q.keys,...Z.keys},baseUrls:{...Q.baseUrls,...Z.baseUrls}};$1(V0(),JSON.stringify(z,null,2),"utf8")}function n(){let Z=process.cwd();F0(y(Z,".tenicli.env")),F0(y(Z,".env"));let $=i(),Q=process.env,z=Q.TENICLI_MODEL||$.activeModel||u[0].id,Y=u.find((W)=>W.id===z)?.provider||Q.TENICLI_PROVIDER||"anthropic",J=V1(Y,$,Q),K=Y==="openai"?"https://api.openai.com":"https://api.anthropic.com",X=Q.TENICLI_BASE_URL||$.baseUrls?.[Y]||K;return{provider:{type:Y,baseUrl:X,apiKey:J,model:z},maxTokens:parseInt(Q.TENICLI_MAX_TOKENS||"8192"),systemPrompt:z1(Z),cwd:Z}}function V1(Z,$,Q){if(Z==="anthropic")return Q.TENICLI_API_KEY||Q.ANTHROPIC_API_KEY||$.keys?.anthropic||"";if(Z==="openai")return Q.TENICLI_API_KEY||Q.OPENAI_API_KEY||$.keys?.openai||"";return Q.TENICLI_API_KEY||""}function F0(Z){try{if(!a(Z))return;for(let $ of z0(Z,"utf8").split(`
3
+ `)){let Q=$.trim();if(!Q||Q.startsWith("#"))continue;let z=Q.indexOf("=");if(z===-1)continue;let G=Q.slice(0,z).trim(),Y=Q.slice(z+1).trim();if(Y.startsWith('"')&&Y.endsWith('"')||Y.startsWith("'")&&Y.endsWith("'"))Y=Y.slice(1,-1);if(!process.env[G])process.env[G]=Y}}catch{}}function z1(Z){for(let $ of[y(Z,"TENICLI.md"),y(G0(),"TENICLI.md")])if(a($))return z0($,"utf8");return G1}var u,G1=`You are TeniCLI, a fast AI coding assistant in the terminal.
4
4
 
5
5
  TOOLS: read/write files, execute commands, search code, list directories.
6
6
 
@@ -9,45 +9,45 @@ RULES:
9
9
  - Use tools proactively — read before edit, verify after changes.
10
10
  - Ask before destructive operations (delete, overwrite).
11
11
  - The user may write in Vietnamese — respond in the same language they use.
12
- - Write production-quality code matching the project's style.`;var V0=C(()=>{u=[{id:"claude-sonnet-4-20250514",name:"Claude Sonnet 4",provider:"anthropic",speed:"fast"},{id:"claude-haiku-3-5-20241022",name:"Claude Haiku 3.5",provider:"anthropic",speed:"fast"},{id:"claude-opus-4-20250514",name:"Claude Opus 4",provider:"anthropic",speed:"slow"},{id:"gpt-4o",name:"GPT-4o",provider:"openai",speed:"fast"},{id:"gpt-4o-mini",name:"GPT-4o Mini",provider:"openai",speed:"fast"},{id:"o3-mini",name:"o3-mini",provider:"openai",speed:"normal"}]});async function*J0(Z,$,Q,V,z){if(Z.type==="openai")yield*V1(Z,$,Q,V,z);else yield*G1(Z,$,Q,V,z)}async function*G1(Z,$,Q,V,z){let Y=`${Z.baseUrl.replace(/\/$/,"")}/v1/messages`,J={model:Z.model,max_tokens:z,system:Q,messages:$,stream:!0};if(V.length)J.tools=V;let K=await j0(Y,J,{"anthropic-version":"2023-06-01","x-api-key":Z.apiKey,authorization:`Bearer ${Z.apiKey}`});for await(let X of M0(K))switch(X.type){case"message_start":if(X.message?.usage)yield{type:"usage",input:X.message.usage.input_tokens||0,output:0};break;case"content_block_start":if(X.content_block?.type==="text")yield{type:"text",text:""};else if(X.content_block?.type==="tool_use")yield{type:"tool_start",id:X.content_block.id,name:X.content_block.name};break;case"content_block_delta":if(X.delta?.type==="text_delta")yield{type:"text",text:X.delta.text};else if(X.delta?.type==="input_json_delta")yield{type:"tool_input",partial:X.delta.partial_json};break;case"content_block_stop":yield{type:"tool_end"};break;case"message_delta":if(X.usage)yield{type:"usage",input:0,output:X.usage.output_tokens||0};yield{type:"done",stopReason:X.delta?.stop_reason||"end_turn"};break}}async function*V1(Z,$,Q,V,z){let Y=`${Z.baseUrl.replace(/\/$/,"")}/v1/chat/completions`,J=z1($,Q),K=V.map((_)=>({type:"function",function:{name:_.name,description:_.description,parameters:_.input_schema}})),X={model:Z.model,max_tokens:z,messages:J,stream:!0,stream_options:{include_usage:!0}};if(K.length)X.tools=K;let W=await j0(Y,X,{authorization:`Bearer ${Z.apiKey}`}),U=new Map;for await(let _ of M0(W)){let H=_.choices?.[0];if(!H){if(_.usage)yield{type:"usage",input:_.usage.prompt_tokens||0,output:_.usage.completion_tokens||0};continue}let D=H.delta||{};if(D.content)yield{type:"text",text:D.content};if(D.tool_calls)for(let q of D.tool_calls){if(q.id)U.set(q.index,{id:q.id,name:q.function?.name||"",args:""}),yield{type:"tool_start",id:q.id,name:q.function?.name||""};if(q.function?.arguments){let N=U.get(q.index);if(N)N.args+=q.function.arguments;yield{type:"tool_input",partial:q.function.arguments}}}if(H.finish_reason){for(let[,q]of U)yield{type:"tool_end"};yield{type:"done",stopReason:H.finish_reason==="tool_calls"?"tool_use":H.finish_reason}}}}function z1(Z,$){let Q=[{role:"system",content:$}];for(let V of Z)if(V.role==="user")if(typeof V.content==="string")Q.push({role:"user",content:V.content});else{let z=V.content;for(let Y of z)if(Y.type==="tool_result")Q.push({role:"tool",tool_call_id:Y.tool_use_id,content:Y.content||""});else Q.push({role:"user",content:Y.text||""})}else if(typeof V.content==="string")Q.push({role:"assistant",content:V.content});else{let z=V.content,Y=z.filter((K)=>K.type==="tool_use"),J=z.filter((K)=>K.type==="text").map((K)=>K.text).join("");if(Y.length)Q.push({role:"assistant",content:J||null,tool_calls:Y.map((K)=>({id:K.id,type:"function",function:{name:K.name,arguments:JSON.stringify(K.input||{})}}))});else Q.push({role:"assistant",content:J})}return Q}async function j0(Z,$,Q){let V=await fetch(Z,{method:"POST",headers:{"content-type":"application/json",...Q},body:JSON.stringify($)});if(!V.ok){let R=await V.text();throw Error(`API ${V.status}: ${R.slice(0,300)}`)}let z={},Y=V.headers.get("anthropic-ratelimit-requests-limit");if(Y)z.requestsLimit=parseInt(Y);let J=V.headers.get("anthropic-ratelimit-requests-remaining");if(J)z.requestsRemaining=parseInt(J);let K=V.headers.get("anthropic-ratelimit-requests-reset");if(K)z.requestsReset=K;let X=V.headers.get("anthropic-ratelimit-tokens-limit");if(X)z.tokensLimit=parseInt(X);let W=V.headers.get("anthropic-ratelimit-tokens-remaining");if(W)z.tokensRemaining=parseInt(W);let U=V.headers.get("anthropic-ratelimit-tokens-reset");if(U)z.tokensReset=U;let _=V.headers.get("x-ratelimit-limit-requests");if(_)z.requestsLimit=parseInt(_);let H=V.headers.get("x-ratelimit-remaining-requests");if(H)z.requestsRemaining=parseInt(H);let D=V.headers.get("x-ratelimit-reset-requests");if(D)z.requestsReset=D;let q=V.headers.get("x-ratelimit-limit-tokens");if(q)z.tokensLimit=parseInt(q);let N=V.headers.get("x-ratelimit-remaining-tokens");if(N)z.tokensRemaining=parseInt(N);let E=V.headers.get("x-ratelimit-reset-tokens");if(E)z.tokensReset=E;if(Object.keys(z).length>0)z0=z;return V}async function*M0(Z){let $=Z.body.getReader(),Q=new TextDecoder,V="";while(!0){let{done:z,value:Y}=await $.read();if(z)break;V+=Q.decode(Y,{stream:!0});let J=V.split(`
13
- `);V=J.pop();for(let K of J)if(K.startsWith("data: ")){let X=K.slice(6).trim();if(X==="[DONE]")return;try{yield JSON.parse(X)}catch{}}}}var z0;var K0=C(()=>{z0={}});function J1(){let Z=[" ██ ██ ","██████████","███ ██ █","██████████","██████████"," ██ ██ ██ "],$={T:["█████"," █ "," █ "," █ "," █ "],E:["████ ","█ ","███ ","█ ","████ "],N:["█ █ ","██ █ ","█ ██ ","█ █ ","█ █ "],I:["███"," █ "," █ "," █ ","███"],space:[" "," "," "," "," "],C:[" ███","█ ","█ ","█ "," ███"],L:["█ ","█ ","█ ","█ ","████"]},Q=[$.T,$.E,$.N,$.I,$.space,$.C,$.L,$.I],V=["","","","",""];for(let J=0;J<5;J++)V[J]=Q.map((K)=>K[J]).join(" ");let z=Z.map((J)=>G.cyan(J.padEnd(14," "))),Y=[" ".repeat(V[0].length),...V].map((J)=>G.blue(J));return z.map((J,K)=>`${J} ${Y[K]||""}`).join(`
14
- `)}function p(Z,$=60){let Q=(V,z)=>{let Y=V.replace(/\x1b\[[0-9;]*m/g,""),J=z-Y.length;return J>0?V+" ".repeat(J):V};console.log(G.gray(` ${F.tl}${F.line($)}${F.tr}`));for(let V of Z)console.log(G.gray(` ${F.v}`)+` ${Q(V,$-2)} `+G.gray(F.v));console.log(G.gray(` ${F.bl}${F.line($)}${F.br}`))}function P0(Z="0.0.0"){console.clear(),console.log(),console.log(J1()),console.log(),p([G.gray("type to chat")+` ${A.dot} `+G.gray("/help for commands")+` ${A.dot} `+G.gray(`v${Z}`)],60),console.log()}class r{i=0;timer=null;msg;constructor(Z="Thinking"){this.msg=Z}start(){return this.timer=setInterval(()=>{process.stdout.write(`\x1B[2K\r ${G.blue(A.spinner[this.i%A.spinner.length])} ${G.gray(this.msg)}`),this.i++},80),this}stop(){if(this.timer)clearInterval(this.timer),this.timer=null;process.stdout.write("\x1B[2K\r")}}function L(Z,$=!1){return new Promise((Q,V)=>{if(process.stdout.write(Z),!$||!process.stdin.isTTY){let q="",N=(R)=>{let B=typeof R==="string"?R:R.toString("utf8");if(B.charCodeAt(0)===3)process.stdout.write(`
15
- `),process.exit(0);if(B.charCodeAt(0)===4){E(),V(Error("EOF"));return}q+=B;let O=q.indexOf(`
16
- `);if(O!==-1)E(),Q(q.slice(0,O).replace(/\r$/,""))},E=()=>{process.stdin.removeListener("data",N)};if(!process.stdin.readableEncoding)process.stdin.setEncoding("utf8");process.stdin.on("data",N),process.stdin.resume();return}let z="",Y=0,J=0,K=process.stdin.isRaw;if(process.stdin.setRawMode(!0),!process.stdin.readableEncoding)process.stdin.setEncoding("utf8");process.stdin.resume();let X=()=>{if(!z.startsWith("/")||z.length<1)return[];return K1.filter((q)=>q.cmd.startsWith(z))},W=()=>{if(Y>0){for(let q=0;q<Y;q++)process.stdout.write("\x1B[1B"),process.stdout.write("\x1B[2K");process.stdout.write(`\x1B[${Y}A`),Y=0}process.stdout.write("\x1B[0K")},U=()=>{W();let q=X();if(q.length===0)return;if(J>=q.length)J=q.length-1;if(J<0)J=0;let N=Z.replace(/\x1b\[[0-9;]*m/g,"").length;for(let E=0;E<q.length;E++){process.stdout.write(`
17
- \x1B[2K\r`);let R=q[E];if(E===J)process.stdout.write(` ${G.blue(G.bold(R.cmd))} ${G.gray(R.desc)}`);else process.stdout.write(` ${G.gray(R.cmd)} ${G.gray(G.dim(R.desc))}`)}Y=q.length,process.stdout.write(`\x1B[${Y}A\r\x1B[${N+z.length}C`)},_="",H=(q)=>{let N=typeof q==="string"?q:q.toString("utf8");for(let E=0;E<N.length;E++){let R=N[E],B=R.charCodeAt(0);if(_.length>0||B===27){if(_+=R,_.length===1)continue;if(_.length===2&&_[1]==="[")continue;if(_.length>=3){let O=X();if(_==="\x1B[A"&&O.length>0)J=(J-1+O.length)%O.length,U();else if(_==="\x1B[B"&&O.length>0)J=(J+1)%O.length,U();_="";continue}continue}if(B===3)W(),process.stdin.setRawMode(K),process.stdout.write(`
18
- `),process.exit(0);if(B===4){W(),process.stdin.setRawMode(K),D(),V(Error("EOF"));return}if(B===13||B===10){let O=X();if(O.length>0&&z!==O[J].cmd){W();let x=O[J].cmd;process.stdout.write("\b \b".repeat(z.length)),z=x,process.stdout.write(z)}W(),process.stdin.setRawMode(K),process.stdout.write(`
19
- `),D(),Q(z);return}if(B===127||B===8){if(z.length>0)W(),z=z.slice(0,-1),process.stdout.write("\b \b"),J=0,U();continue}if(B===9){let O=X();if(O.length>0){W();let x=O[J].cmd,e=x.slice(z.length);z=x,process.stdout.write(e),U()}continue}if(B<32)continue;W(),z+=R,process.stdout.write(R),J=0,U()}},D=()=>{process.stdin.removeListener("data",H)};process.stdin.on("data",H)})}async function C0(){let Z=[],$=!0;while(!0){let Q=$?`
20
- ${G.gray(F.tl+F.line(3))} ${A.prompt} `:` ${G.gray(F.v)} `,V=await L(Q,$);if($=!1,V.endsWith("\\"))Z.push(V.slice(0,-1));else{Z.push(V);break}}return Z.join(`
12
+ - Write production-quality code matching the project's style.`;var J0=T(()=>{u=[{id:"claude-sonnet-4-20250514",name:"Claude Sonnet 4",provider:"anthropic",speed:"fast"},{id:"claude-haiku-3-5-20241022",name:"Claude Haiku 3.5",provider:"anthropic",speed:"fast"},{id:"claude-opus-4-20250514",name:"Claude Opus 4",provider:"anthropic",speed:"slow"},{id:"gpt-4o",name:"GPT-4o",provider:"openai",speed:"fast"},{id:"gpt-4o-mini",name:"GPT-4o Mini",provider:"openai",speed:"fast"},{id:"o3-mini",name:"o3-mini",provider:"openai",speed:"normal"}]});async function*X0(Z,$,Q,z,G){if(Z.type==="openai")yield*K1(Z,$,Q,z,G);else yield*J1(Z,$,Q,z,G)}async function*J1(Z,$,Q,z,G){let Y=`${Z.baseUrl.replace(/\/$/,"")}/v1/messages`,J={model:Z.model,max_tokens:G,system:Q,messages:$,stream:!0};if(z.length)J.tools=z;let K=await j0(Y,J,{"anthropic-version":"2023-06-01","x-api-key":Z.apiKey,authorization:`Bearer ${Z.apiKey}`});for await(let X of M0(K))switch(X.type){case"message_start":if(X.message?.usage)yield{type:"usage",input:X.message.usage.input_tokens||0,output:0};break;case"content_block_start":if(X.content_block?.type==="text")yield{type:"text",text:""};else if(X.content_block?.type==="tool_use")yield{type:"tool_start",id:X.content_block.id,name:X.content_block.name};break;case"content_block_delta":if(X.delta?.type==="text_delta")yield{type:"text",text:X.delta.text};else if(X.delta?.type==="input_json_delta")yield{type:"tool_input",partial:X.delta.partial_json};break;case"content_block_stop":yield{type:"tool_end"};break;case"message_delta":if(X.usage)yield{type:"usage",input:0,output:X.usage.output_tokens||0};yield{type:"done",stopReason:X.delta?.stop_reason||"end_turn"};break}}async function*K1(Z,$,Q,z,G){let Y=`${Z.baseUrl.replace(/\/$/,"")}/v1/chat/completions`,J=X1($,Q),K=z.map((U)=>({type:"function",function:{name:U.name,description:U.description,parameters:U.input_schema}})),X={model:Z.model,max_tokens:G,messages:J,stream:!0,stream_options:{include_usage:!0}};if(K.length)X.tools=K;let W=await j0(Y,X,{authorization:`Bearer ${Z.apiKey}`}),q=new Map;for await(let U of M0(W)){let _=U.choices?.[0];if(!_){if(U.usage)yield{type:"usage",input:U.usage.prompt_tokens||0,output:U.usage.completion_tokens||0};continue}let E=_.delta||{};if(E.content)yield{type:"text",text:E.content};if(E.tool_calls)for(let H of E.tool_calls){if(H.id)q.set(H.index,{id:H.id,name:H.function?.name||"",args:""}),yield{type:"tool_start",id:H.id,name:H.function?.name||""};if(H.function?.arguments){let R=q.get(H.index);if(R)R.args+=H.function.arguments;yield{type:"tool_input",partial:H.function.arguments}}}if(_.finish_reason){for(let[,H]of q)yield{type:"tool_end"};yield{type:"done",stopReason:_.finish_reason==="tool_calls"?"tool_use":_.finish_reason}}}}function X1(Z,$){let Q=[{role:"system",content:$}];for(let z of Z)if(z.role==="user")if(typeof z.content==="string")Q.push({role:"user",content:z.content});else{let G=z.content;for(let Y of G)if(Y.type==="tool_result")Q.push({role:"tool",tool_call_id:Y.tool_use_id,content:Y.content||""});else Q.push({role:"user",content:Y.text||""})}else if(typeof z.content==="string")Q.push({role:"assistant",content:z.content});else{let G=z.content,Y=G.filter((K)=>K.type==="tool_use"),J=G.filter((K)=>K.type==="text").map((K)=>K.text).join("");if(Y.length)Q.push({role:"assistant",content:J||null,tool_calls:Y.map((K)=>({id:K.id,type:"function",function:{name:K.name,arguments:JSON.stringify(K.input||{})}}))});else Q.push({role:"assistant",content:J})}return Q}async function j0(Z,$,Q){let z=await fetch(Z,{method:"POST",headers:{"content-type":"application/json",...Q},body:JSON.stringify($)});if(!z.ok){let N=await z.text();throw Error(`API ${z.status}: ${N.slice(0,300)}`)}let G={},Y=z.headers.get("anthropic-ratelimit-requests-limit");if(Y)G.requestsLimit=parseInt(Y);let J=z.headers.get("anthropic-ratelimit-requests-remaining");if(J)G.requestsRemaining=parseInt(J);let K=z.headers.get("anthropic-ratelimit-requests-reset");if(K)G.requestsReset=K;let X=z.headers.get("anthropic-ratelimit-tokens-limit");if(X)G.tokensLimit=parseInt(X);let W=z.headers.get("anthropic-ratelimit-tokens-remaining");if(W)G.tokensRemaining=parseInt(W);let q=z.headers.get("anthropic-ratelimit-tokens-reset");if(q)G.tokensReset=q;let U=z.headers.get("x-ratelimit-limit-requests");if(U)G.requestsLimit=parseInt(U);let _=z.headers.get("x-ratelimit-remaining-requests");if(_)G.requestsRemaining=parseInt(_);let E=z.headers.get("x-ratelimit-reset-requests");if(E)G.requestsReset=E;let H=z.headers.get("x-ratelimit-limit-tokens");if(H)G.tokensLimit=parseInt(H);let R=z.headers.get("x-ratelimit-remaining-tokens");if(R)G.tokensRemaining=parseInt(R);let D=z.headers.get("x-ratelimit-reset-tokens");if(D)G.tokensReset=D;if(Object.keys(G).length>0)K0=G;return z}async function*M0(Z){let $=Z.body.getReader(),Q=new TextDecoder,z="";while(!0){let{done:G,value:Y}=await $.read();if(G)break;z+=Q.decode(Y,{stream:!0});let J=z.split(`
13
+ `);z=J.pop();for(let K of J)if(K.startsWith("data: ")){let X=K.slice(6).trim();if(X==="[DONE]")return;try{yield JSON.parse(X)}catch{}}}}var K0;var Y0=T(()=>{K0={}});function Y1(){let Z=[" ██ ██ ","██████████","███ ██ █","██████████","██████████"," ██ ██ ██ "],$={T:["█████"," █ "," █ "," █ "," █ "],E:["████ ","█ ","███ ","█ ","████ "],N:["█ █ ","██ █ ","█ ██ ","█ █ ","█ █ "],I:["███"," █ "," █ "," █ ","███"],space:[" "," "," "," "," "],C:[" ███","█ ","█ ","█ "," ███"],L:["█ ","█ ","█ ","█ ","████"]},Q=[$.T,$.E,$.N,$.I,$.space,$.C,$.L,$.I],z=["","","","",""];for(let J=0;J<5;J++)z[J]=Q.map((K)=>K[J]).join(" ");let G=Z.map((J)=>V.cyan(J.padEnd(14," "))),Y=[" ".repeat(z[0].length),...z].map((J)=>V.blue(J));return G.map((J,K)=>`${J} ${Y[K]||""}`).join(`
14
+ `)}function p(Z,$=60){let Q=(z,G)=>{let Y=z.replace(/\x1b\[[0-9;]*m/g,""),J=G-Y.length;return J>0?z+" ".repeat(J):z};console.log(V.gray(` ${F.tl}${F.line($)}${F.tr}`));for(let z of Z)console.log(V.gray(` ${F.v}`)+` ${Q(z,$-2)} `+V.gray(F.v));console.log(V.gray(` ${F.bl}${F.line($)}${F.br}`))}function P0(Z="0.0.0"){console.clear(),console.log(),console.log(Y1()),console.log(),p([V.gray("type to chat")+` ${A.dot} `+V.gray("/help for commands")+` ${A.dot} `+V.gray(`v${Z}`)],60),console.log()}class r{i=0;timer=null;msg;constructor(Z="Thinking"){this.msg=Z}start(){return this.timer=setInterval(()=>{process.stdout.write(`\x1B[2K\r ${V.blue(A.spinner[this.i%A.spinner.length])} ${V.gray(this.msg)}`),this.i++},80),this}stop(){if(this.timer)clearInterval(this.timer),this.timer=null;process.stdout.write("\x1B[2K\r")}}function b(Z,$=!1){return new Promise((Q,z)=>{if(process.stdout.write(Z),!$||!process.stdin.isTTY){let H="",R=(N)=>{let B=typeof N==="string"?N:N.toString("utf8");if(B.charCodeAt(0)===3)process.stdout.write(`
15
+ `),process.exit(0);if(B.charCodeAt(0)===4){D(),z(Error("EOF"));return}H+=B;let O=H.indexOf(`
16
+ `);if(O!==-1)D(),Q(H.slice(0,O).replace(/\r$/,""))},D=()=>{process.stdin.removeListener("data",R)};if(!process.stdin.readableEncoding)process.stdin.setEncoding("utf8");process.stdin.on("data",R),process.stdin.resume();return}let G="",Y=0,J=0,K=process.stdin.isRaw;if(process.stdin.setRawMode(!0),!process.stdin.readableEncoding)process.stdin.setEncoding("utf8");process.stdin.resume();let X=()=>{if(!G.startsWith("/")||G.length<1)return[];return W1.filter((H)=>H.cmd.startsWith(G))},W=()=>{if(Y>0){for(let H=0;H<Y;H++)process.stdout.write("\x1B[1B"),process.stdout.write("\x1B[2K");process.stdout.write(`\x1B[${Y}A`),Y=0}process.stdout.write("\x1B[0K")},q=()=>{W();let H=X();if(H.length===0)return;if(J>=H.length)J=H.length-1;if(J<0)J=0;let R=Z.replace(/\x1b\[[0-9;]*m/g,"").length;for(let D=0;D<H.length;D++){process.stdout.write(`
17
+ \x1B[2K\r`);let N=H[D];if(D===J)process.stdout.write(` ${V.blue(V.bold(N.cmd))} ${V.gray(N.desc)}`);else process.stdout.write(` ${V.gray(N.cmd)} ${V.gray(V.dim(N.desc))}`)}Y=H.length,process.stdout.write(`\x1B[${Y}A\r\x1B[${R+G.length}C`)},U="",_=(H)=>{let R=typeof H==="string"?H:H.toString("utf8");for(let D=0;D<R.length;D++){let N=R[D],B=N.charCodeAt(0);if(U.length>0||B===27){if(U+=N,U.length===1)continue;if(U.length===2&&U[1]==="[")continue;if(U.length>=3){let O=X();if(U==="\x1B[A"&&O.length>0)J=(J-1+O.length)%O.length,q();else if(U==="\x1B[B"&&O.length>0)J=(J+1)%O.length,q();U="";continue}continue}if(B===3)W(),process.stdin.setRawMode(K),process.stdout.write(`
18
+ `),process.exit(0);if(B===4){W(),process.stdin.setRawMode(K),E(),z(Error("EOF"));return}if(B===13||B===10){let O=X();if(O.length>0&&G!==O[J].cmd){W();let L=O[J].cmd;process.stdout.write("\b \b".repeat(G.length)),G=L,process.stdout.write(G)}W(),process.stdin.setRawMode(K),process.stdout.write(`
19
+ `),E(),Q(G);return}if(B===127||B===8){if(G.length>0)W(),G=G.slice(0,-1),process.stdout.write("\b \b"),J=0,q();continue}if(B===9){let O=X();if(O.length>0){W();let L=O[J].cmd,$0=L.slice(G.length);G=L,process.stdout.write($0),q()}continue}if(B<32)continue;W(),G+=N,process.stdout.write(N),J=0,q()}},E=()=>{process.stdin.removeListener("data",_)};process.stdin.on("data",_)})}async function C0(){let Z=[],$=!0;while(!0){let Q=$?`
20
+ ${V.gray(F.tl+F.line(3))} ${A.prompt} `:` ${V.gray(F.v)} `,z=await b(Q,$);if($=!1,z.endsWith("\\"))Z.push(z.slice(0,-1));else{Z.push(z);break}}return Z.join(`
21
21
  `)}async function S(Z,$){console.log(`
22
- ${G.bold(Z)}`),$.forEach((Q,V)=>{let z=G.blue(` ${V+1}.`),Y=Q.desc?G.gray(` (${Q.desc})`):"";console.log(`${z} ${Q.label}${Y}`)}),console.log(` ${G.gray(" 0. Cancel")}`);while(!0){let V=(await L(`
23
- ${G.gray("choose")} ${G.blue("❯")} `)).trim().toLowerCase();if(V==="0"||V==="q"||V==="cancel"||V==="exit"||V==="")return-1;let z=parseInt(V);if(z>=1&&z<=$.length)return z-1;console.log(` ${A.warn} enter 1-${$.length} or 0 to cancel`)}}function y(Z,$){console.log(`
24
- ${A.tool} ${G.yellow(Z)} ${G.gray($)}`)}function I(Z){console.error(` ${A.err} ${G.pink(Z)}`)}var I0=(Z)=>`\x1B[${Z}m`,o=(Z,$)=>(Q)=>`${I0(Z)}${Q}${I0($)}`,M=(Z)=>($)=>`\x1B[38;5;${Z}m${$}\x1B[39m`,G,A,F,K1;var t=C(()=>{G={bold:o("1","22"),dim:o("2","22"),italic:o("3","23"),under:o("4","24"),blue:M(111),purple:M(141),green:M(149),yellow:M(179),pink:M(210),cyan:M(117),gray:M(60),text:M(146),orange:M(215)},A={prompt:G.blue("❯"),ai:G.purple("◆"),tool:G.yellow("⚙"),ok:G.green("✓"),err:G.pink("✗"),warn:G.yellow("⚠"),arrow:G.gray("→"),dot:G.gray("•"),spinner:["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"]};F={h:"─",v:"│",tl:"╭",tr:"╮",bl:"╰",br:"╯",line:(Z)=>"─".repeat(Z)};K1=[{cmd:"/model",desc:"switch AI model"},{cmd:"/auth",desc:"set API key"},{cmd:"/mode",desc:"toggle mode"},{cmd:"/compact",desc:"toggle compact"},{cmd:"/diff",desc:"show file changes"},{cmd:"/undo",desc:"revert last change"},{cmd:"/init",desc:"init project context"},{cmd:"/remote",desc:"start web remote"},{cmd:"/history",desc:"past conversations"},{cmd:"/quota",desc:"API rate limits"},{cmd:"/update",desc:"update tenicli"},{cmd:"/clear",desc:"clear screen"},{cmd:"/cost",desc:"show token usage"},{cmd:"/help",desc:"list commands"},{cmd:"/exit",desc:"quit"}]});import{readFileSync as w,writeFileSync as Y0,existsSync as v,readdirSync as m,statSync as T0,mkdirSync as S0,unlinkSync as X0}from"fs";import{resolve as W0,relative as b,join as T,dirname as X1}from"path";import{spawn as h0}from"child_process";class b0{snapshotDir;sessionWrites=[];constructor(Z){let $=Z||process.cwd();if(this.snapshotDir=T($,".tenicli","snapshots"),!v(this.snapshotDir))S0(this.snapshotDir,{recursive:!0});this.loadFromDisk()}loadFromDisk(){try{let Z=m(this.snapshotDir).filter(($)=>$.endsWith(".json")).sort();for(let $ of Z)try{let Q=w(T(this.snapshotDir,$),"utf8"),V=JSON.parse(Q);this.sessionWrites.push(V)}catch{}}catch{}}saveEntry(Z){let Q=`${Date.now()}.json`,V=T(this.snapshotDir,Q);return Y0(V,JSON.stringify(Z),"utf8"),Q}removeEntry(Z){try{let $=m(this.snapshotDir).filter((Q)=>Q.endsWith(".json")).sort();for(let Q=$.length-1;Q>=0;Q--)try{let V=w(T(this.snapshotDir,$[Q]),"utf8"),z=JSON.parse(V);if(z.path===Z.path&&z.time===Z.time){X0(T(this.snapshotDir,$[Q]));return}}catch{}}catch{}}recordWrite(Z,$){let Q=v(Z)?w(Z,"utf8"):null,V={path:Z,backup:Q,newLines:$.split(`
25
- `).length,time:new Date().toISOString(),label:Q===null?`create ${b(process.cwd(),Z)}`:`modify ${b(process.cwd(),Z)}`};this.sessionWrites.push(V),this.saveEntry(V)}getChanges(){let Z=new Map;for(let $ of this.sessionWrites)Z.set($.path,{isNew:$.backup===null,lines:$.newLines,time:new Date($.time)});return Array.from(Z.entries()).map(([$,Q])=>({path:$,...Q}))}getTimeline(){return this.sessionWrites.map((Z)=>({path:Z.path,isNew:Z.backup===null,lines:Z.newLines,time:new Date(Z.time),label:Z.label}))}undo(){let Z=this.sessionWrites.pop();if(!Z)return null;if(this.removeEntry(Z),Z.backup!==null)return Y0(Z.path,Z.backup,"utf8"),{path:Z.path,restored:!0};else{try{X0(Z.path)}catch{}return{path:Z.path,restored:!1}}}undoAll(){let Z=0;while(this.sessionWrites.length>0)this.undo(),Z++;return Z}get count(){return this.sessionWrites.length}clear(){this.sessionWrites=[]}purge(){try{let Z=m(this.snapshotDir).filter(($)=>$.endsWith(".json"));for(let $ of Z)try{X0(T(this.snapshotDir,$))}catch{}}catch{}this.sessionWrites=[]}}function W1(Z){let $=Z.toLowerCase().trim();return Y1.some((Q)=>$.startsWith(Q)||$.includes(Q))}function U1(Z,$){let Q=W0(Z),V=W0($);return Q.startsWith(V)}async function x0(Z,$,Q){try{let V;switch(Z){case"read_file":V=q1($,Q),y("read_file",G.dim(b(Q,k($.path,Q))));break;case"write_file":V=A1($,Q),y("write_file",G.dim(b(Q,k($.path,Q))));break;case"list_dir":V=E1($,Q),y("list_dir",G.dim($.path||"."));break;case"search_files":V=await D1($,Q),y("search_files",G.dim(`"${$.pattern}"`));break;case"exec_command":V=await R1($,Q),y("exec_command",G.dim(L0($.command,60)));break;default:V=`Unknown tool: ${Z}`}return{type:"tool_result",content:L0(V,_1)}}catch(V){return{type:"tool_result",content:`Error: ${V.message}`,is_error:!0}}}function k(Z,$){return W0($,Z)}function q1(Z,$){let Q=k(Z.path,$);if(!v(Q))return`File not found: ${Z.path}`;let V=w(Q,"utf8"),z=V.split(`
26
- `);if(Z.start_line||Z.end_line){let Y=Math.max(1,Z.start_line||1)-1,J=Math.min(z.length,Z.end_line||z.length);return z.slice(Y,J).map((K,X)=>`${Y+X+1}: ${K}`).join(`
27
- `)}if(z.length>50)return z.map((Y,J)=>`${J+1}: ${Y}`).join(`
28
- `);return V}function H1(Z,$){let Q=Z.length,V=$.length;if(Q*V>2000000){let X=[];for(let W of Z)X.push({type:"del",line:W});for(let W of $)X.push({type:"add",line:W});return X}let z=Array.from({length:Q+1},()=>Array(V+1).fill(0));for(let X=1;X<=Q;X++)for(let W=1;W<=V;W++)z[X][W]=Z[X-1]===$[W-1]?z[X-1][W-1]+1:Math.max(z[X-1][W],z[X][W-1]);let Y=[],J=Q,K=V;while(J>0||K>0)if(J>0&&K>0&&Z[J-1]===$[K-1])Y.push({type:"same",line:Z[J-1]}),J--,K--;else if(K>0&&(J===0||z[J][K-1]>=z[J-1][K]))Y.push({type:"add",line:$[K-1]}),K--;else Y.push({type:"del",line:Z[J-1]}),J--;return Y.reverse()}function N1(Z,$,Q,V){let z=b(V,Z),Y=` ${G.dim("──")} ${G.cyan(z)} ${G.dim("─".repeat(Math.max(2,50-z.length)))}`;if(console.log(Y),$===null){let N=Q.split(`
29
- `).length;console.log(` ${G.green(`+ (new file, ${N} lines)`)}`),console.log();return}let J=$.split(`
22
+ ${V.bold(Z)}`),$.forEach((Q,z)=>{let G=V.blue(` ${z+1}.`),Y=Q.desc?V.gray(` (${Q.desc})`):"";console.log(`${G} ${Q.label}${Y}`)}),console.log(` ${V.gray(" 0. Cancel")}`);while(!0){let z=(await b(`
23
+ ${V.gray("choose")} ${V.blue("❯")} `)).trim().toLowerCase();if(z==="0"||z==="q"||z==="cancel"||z==="exit"||z==="")return-1;let G=parseInt(z);if(G>=1&&G<=$.length)return G-1;console.log(` ${A.warn} enter 1-${$.length} or 0 to cancel`)}}function v(Z,$){console.log(`
24
+ ${A.tool} ${V.yellow(Z)} ${V.gray($)}`)}function I(Z){console.error(` ${A.err} ${V.pink(Z)}`)}var I0=(Z)=>`\x1B[${Z}m`,o=(Z,$)=>(Q)=>`${I0(Z)}${Q}${I0($)}`,M=(Z)=>($)=>`\x1B[38;5;${Z}m${$}\x1B[39m`,V,A,F,W1;var t=T(()=>{V={bold:o("1","22"),dim:o("2","22"),italic:o("3","23"),under:o("4","24"),blue:M(111),purple:M(141),green:M(149),yellow:M(179),pink:M(210),cyan:M(117),gray:M(60),text:M(146),orange:M(215)},A={prompt:V.blue("❯"),ai:V.purple("◆"),tool:V.yellow("⚙"),ok:V.green("✓"),err:V.pink("✗"),warn:V.yellow("⚠"),arrow:V.gray("→"),dot:V.gray("•"),spinner:["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"]};F={h:"─",v:"│",tl:"╭",tr:"╮",bl:"╰",br:"╯",line:(Z)=>"─".repeat(Z)};W1=[{cmd:"/model",desc:"switch AI model"},{cmd:"/auth",desc:"set API key"},{cmd:"/mode",desc:"toggle mode"},{cmd:"/compact",desc:"toggle compact"},{cmd:"/diff",desc:"show file changes"},{cmd:"/undo",desc:"revert last change"},{cmd:"/init",desc:"init project context"},{cmd:"/remote",desc:"start web remote"},{cmd:"/history",desc:"past conversations"},{cmd:"/quota",desc:"API rate limits"},{cmd:"/update",desc:"update tenicli"},{cmd:"/clear",desc:"clear screen"},{cmd:"/cost",desc:"show token usage"},{cmd:"/help",desc:"list commands"},{cmd:"/exit",desc:"quit"}]});import{readFileSync as x,writeFileSync as e,existsSync as P,readdirSync as m,statSync as k0,mkdirSync as S0,unlinkSync as s}from"fs";import{resolve as W0,relative as h,join as k,dirname as x0}from"path";import{realpathSync as L0,lstatSync as T0}from"fs";import{spawn as v0}from"child_process";class h0{snapshotDir;sessionWrites=[];constructor(Z){let $=Z||process.cwd();if(this.snapshotDir=k($,".tenicli","snapshots"),!P(this.snapshotDir))S0(this.snapshotDir,{recursive:!0});this.loadFromDisk()}loadFromDisk(){try{let Z=m(this.snapshotDir).filter(($)=>$.endsWith(".json")).sort();for(let $ of Z)try{let Q=x(k(this.snapshotDir,$),"utf8"),z=JSON.parse(Q);this.sessionWrites.push(z)}catch{}}catch{}}saveEntry(Z){let Q=`${Date.now()}.json`,z=k(this.snapshotDir,Q);return e(z,JSON.stringify(Z),"utf8"),Q}removeEntry(Z){try{let $=m(this.snapshotDir).filter((Q)=>Q.endsWith(".json")).sort();for(let Q=$.length-1;Q>=0;Q--)try{let z=x(k(this.snapshotDir,$[Q]),"utf8"),G=JSON.parse(z);if(G.path===Z.path&&G.time===Z.time){s(k(this.snapshotDir,$[Q]));return}}catch{}}catch{}}recordWrite(Z,$){let Q=P(Z)?x(Z,"utf8"):null,z={path:Z,backup:Q,newContent:$,newLines:$.split(`
25
+ `).length,time:new Date().toISOString(),label:Q===null?`create ${h(process.cwd(),Z)}`:`modify ${h(process.cwd(),Z)}`};this.sessionWrites.push(z),this.saveEntry(z)}getChanges(){let Z=new Map;for(let $ of this.sessionWrites)Z.set($.path,{isNew:$.backup===null,lines:$.newLines,time:new Date($.time)});return Array.from(Z.entries()).map(([$,Q])=>({path:$,...Q}))}getTimeline(){return this.sessionWrites.map((Z)=>({path:Z.path,isNew:Z.backup===null,lines:Z.newLines,time:new Date(Z.time),label:Z.label}))}undo(){let Z=this.sessionWrites.pop();if(!Z)return null;if(this.removeEntry(Z),P(Z.path)){if(x(Z.path,"utf8")!==Z.newContent)if(Z.backup!==null)return e(Z.path,Z.backup,"utf8"),{path:Z.path,restored:!0,warning:"File was modified externally since AI edit. Restoring anyway."};else{try{s(Z.path)}catch{}return{path:Z.path,restored:!1,warning:"File was modified externally since AI edit. Restoring anyway."}}}if(Z.backup!==null)return e(Z.path,Z.backup,"utf8"),{path:Z.path,restored:!0};else{try{s(Z.path)}catch{}return{path:Z.path,restored:!1}}}undoAll(){let Z=0;while(this.sessionWrites.length>0)this.undo(),Z++;return Z}get count(){return this.sessionWrites.length}clear(){this.sessionWrites=[]}purge(){try{let Z=m(this.snapshotDir).filter(($)=>$.endsWith(".json"));for(let $ of Z)try{s(k(this.snapshotDir,$))}catch{}}catch{}this.sessionWrites=[]}}function H1(Z){let $=Z.toLowerCase().trim();if(q1.some((Q)=>$.startsWith(Q)||$.includes(Q)))return!0;if(U1.some((Q)=>Q.test(Z)))return!0;return!1}function _1(Z,$){let Q=W0(Z),z=W0($);if(!Q.startsWith(z))return!1;try{if(P(Z)){if(T0(Z).isSymbolicLink()){if(!L0(Z).startsWith(z))return!1}}let G=x0(Q);if(P(G)){if(T0(G).isSymbolicLink()){if(!L0(G).startsWith(z))return!1}}}catch{}return!0}async function y0(Z,$,Q){try{let z;switch(Z){case"read_file":z=A1($,Q),v("read_file",V.dim(h(Q,w($.path,Q))));break;case"write_file":z=R1($,Q),v("write_file",V.dim(h(Q,w($.path,Q))));break;case"list_dir":z=D1($,Q),v("list_dir",V.dim($.path||"."));break;case"search_files":z=await O1($,Q),v("search_files",V.dim(`"${$.pattern}"`));break;case"exec_command":z=await F1($,Q),v("exec_command",V.dim(b0($.command,60)));break;default:z=`Unknown tool: ${Z}`}return{type:"tool_result",content:b0(z,N1)}}catch(z){return{type:"tool_result",content:`Error: ${z.message}`,is_error:!0}}}function w(Z,$){return W0($,Z)}function A1(Z,$){let Q=w(Z.path,$);if(!P(Q))return`File not found: ${Z.path}`;let z=x(Q,"utf8"),G=z.split(`
26
+ `);if(Z.start_line||Z.end_line){let Y=Math.max(1,Z.start_line||1)-1,J=Math.min(G.length,Z.end_line||G.length);return G.slice(Y,J).map((K,X)=>`${Y+X+1}: ${K}`).join(`
27
+ `)}if(G.length>50)return G.map((Y,J)=>`${J+1}: ${Y}`).join(`
28
+ `);return z}function B1(Z,$){let Q=Z.length,z=$.length;if(Q*z>2000000){let X=[];for(let W of Z)X.push({type:"del",line:W});for(let W of $)X.push({type:"add",line:W});return X}let G=Array.from({length:Q+1},()=>Array(z+1).fill(0));for(let X=1;X<=Q;X++)for(let W=1;W<=z;W++)G[X][W]=Z[X-1]===$[W-1]?G[X-1][W-1]+1:Math.max(G[X-1][W],G[X][W-1]);let Y=[],J=Q,K=z;while(J>0||K>0)if(J>0&&K>0&&Z[J-1]===$[K-1])Y.push({type:"same",line:Z[J-1]}),J--,K--;else if(K>0&&(J===0||G[J][K-1]>=G[J-1][K]))Y.push({type:"add",line:$[K-1]}),K--;else Y.push({type:"del",line:Z[J-1]}),J--;return Y.reverse()}function E1(Z,$,Q,z){let G=h(z,Z),Y=` ${V.dim("──")} ${V.cyan(G)} ${V.dim("─".repeat(Math.max(2,50-G.length)))}`;if(console.log(Y),$===null){let N=Q.split(`
29
+ `).length;console.log(` ${V.green(`+ (new file, ${N} lines)`)}`),console.log();return}let J=$.split(`
30
30
  `),K=Q.split(`
31
- `),X=H1(J,K),W=3,U=new Set;if(X.forEach((N,E)=>{if(N.type!=="same")U.add(E)}),U.size===0){console.log(` ${G.gray("(no changes)")}`),console.log();return}let _=new Set;for(let N of U)for(let E=Math.max(0,N-W);E<=Math.min(X.length-1,N+W);E++)_.add(E);let H=-1,D=0,q=0;for(let N=0;N<X.length;N++){if(!_.has(N))continue;if(H!==-1&&N-H>1)console.log(G.gray(" ..."));let E=X[N];if(E.type==="del")console.log(` ${G.pink(`- ${E.line}`)}`),q++;else if(E.type==="add")console.log(` ${G.green(`+ ${E.line}`)}`),D++;else console.log(` ${G.gray(` ${E.line}`)}`);H=N}console.log(` ${G.green(`+${D}`)} ${G.pink(`-${q}`)}`),console.log()}function A1(Z,$){let Q=k(Z.path,$);if(!U1(Q,$)){let Y=`BLOCKED: Cannot write outside project root. Path "${Z.path}" resolves outside "${$}"`;return console.log(` ${G.pink(`⛔ ${Y}`)}`),Y}let V=X1(Q);if(!v(V))S0(V,{recursive:!0});let z=v(Q)?w(Q,"utf8"):null;return j.recordWrite(Q,Z.content),Y0(Q,Z.content,"utf8"),N1(Q,z,Z.content,$),`Written ${Z.content.split(`
32
- `).length} lines to ${Z.path}`}function E1(Z,$){let Q=k(Z.path||".",$);if(!v(Q))return`Directory not found: ${Z.path||"."}`;let V=Z.depth||1,z=[];function Y(J,K){if(K>V)return;try{let X=m(J);for(let W of X){if(W.startsWith(".")||W==="node_modules")continue;let U=T(J,W),_=b(Q,U);try{let H=T0(U),D=" ".repeat(K);if(H.isDirectory())z.push(`${D}${_}/`),Y(U,K+1);else{let q=H.size>1024?`${(H.size/1024).toFixed(1)}KB`:`${H.size}B`;z.push(`${D}${_} (${q})`)}}catch{}}}catch{}}return Y(Q,0),z.length>0?z.join(`
33
- `):"(empty directory)"}async function D1(Z,$){let Q=k(Z.path||".",$),V=Z.pattern;try{let J=["-n","--max-count=50","--no-heading"];if(Z.include)J.push("--glob",Z.include);return J.push(V,Q),await new Promise((X,W)=>{let U=h0("rg",J,{shell:!0}),_="";U.stdout.on("data",(H)=>_+=H.toString()),U.on("close",(H)=>{if(H===0||H===1)X(_.trim()||"No matches found.");else W(Error("rg failed"))}),U.on("error",W)})}catch{}let z=[];function Y(J){try{for(let K of m(J)){if(K.startsWith(".")||K==="node_modules")continue;let X=T(J,K);try{let W=T0(X);if(W.isDirectory()){Y(X);continue}if(W.size>500000)continue;if(Z.include&&!B1(K,Z.include))continue;let _=w(X,"utf8").split(`
34
- `);for(let H=0;H<_.length;H++)if(_[H].includes(V)){if(z.push(`${b($,X)}:${H+1}: ${_[H].trim()}`),z.length>=50)return}}catch{}}}catch{}}return Y(Q),z.length>0?z.join(`
35
- `):"No matches found."}async function R1(Z,$){if(W1(Z.command)){let J=`BLOCKED: Dangerous command rejected: "${Z.command}"`;return console.log(` ${G.pink(`⛔ ${J}`)}`),J}let Q=k(Z.cwd||".",$),V=process.platform==="win32",z=V?"cmd":"sh",Y=V?"/c":"-c";return new Promise((J)=>{let K=h0(z,[Y,Z.command],{cwd:Q,env:{...process.env,PAGER:"cat"}}),X="",W="";K.stdout.on("data",(_)=>X+=_.toString()),K.stderr.on("data",(_)=>W+=_.toString());let U=setTimeout(()=>K.kill(),30000);K.on("close",(_)=>{clearTimeout(U);let H="";if(X.trim())H+=X.trim();if(W.trim())H+=(H?`
36
- `:"")+`[stderr] ${W.trim()}`;H+=`
37
- [exit code: ${_}]`,J(H)}),K.on("error",(_)=>{clearTimeout(U),J(`[error] Failed to start process: ${_.message}`)})})}function L0(Z,$){if(Z.length<=$)return Z;return Z.slice(0,$)+`
38
- ... (truncated, ${Z.length-$} chars omitted)`}function B1(Z,$){if($.startsWith("*."))return Z.endsWith($.slice(1));return Z.includes($.replace(/\*/g,""))}var j,k0,Y1,_1=30000;var U0=C(()=>{t();j=new b0,k0=[{name:"read_file",description:"Read contents of a file. Returns the file text.",input_schema:{type:"object",properties:{path:{type:"string",description:"File path (relative to cwd or absolute)"},start_line:{type:"number",description:"Optional: start line (1-indexed)"},end_line:{type:"number",description:"Optional: end line (1-indexed, inclusive)"}},required:["path"]}},{name:"write_file",description:"Write content to a file. Creates parent directories if needed.",input_schema:{type:"object",properties:{path:{type:"string",description:"File path"},content:{type:"string",description:"Full file content to write"}},required:["path","content"]}},{name:"list_dir",description:"List files and directories in a path. Returns names with type indicators.",input_schema:{type:"object",properties:{path:{type:"string",description:"Directory path (default: cwd)"},depth:{type:"number",description:"Max depth (default: 1)"}},required:[]}},{name:"search_files",description:"Search for text in files using pattern matching (like grep). Returns matching lines with file paths.",input_schema:{type:"object",properties:{pattern:{type:"string",description:"Text or regex pattern to search for"},path:{type:"string",description:"Directory to search in (default: cwd)"},include:{type:"string",description:'Glob pattern to filter files, e.g. "*.ts"'}},required:["pattern"]}},{name:"exec_command",description:"Execute a shell command. Returns stdout and stderr.",input_schema:{type:"object",properties:{command:{type:"string",description:"Shell command to execute"},cwd:{type:"string",description:"Working directory (default: project cwd)"}},required:["command"]}}],Y1=["rm -rf /","rm -rf ~","rm -rf *","del /s /q c:","del /s /q d:","format c:","format d:","mkfs","dd if=","shutdown","reboot",":(){:|:&};:","chmod -R 777 /","> /dev/sda","mv / ","mv ~ "]});class g{messages=[];tokens={input:0,output:0};cfg;autoMode=!1;onOutput;onConfirm;constructor(Z){this.cfg=Z}emit(Z){this.onOutput?.(Z)}write(Z){if(this.onOutput)this.emit({type:"text",text:Z});else process.stdout.write(Z)}log(Z){if(this.onOutput)this.emit({type:"text",text:Z+`
39
- `});else console.log(Z)}async send(Z){this.messages.push({role:"user",content:Z}),await this.agentLoop()}async agentLoop(){while(!0){let Z=await this.streamResponse();if(Z.stopReason==="error")break;if(Z.stopReason==="tool_use"){let Q=Z.content.filter((z)=>z.type==="tool_use"),V=[];for(let z of Q){if(!this.autoMode&&(z.name==="write_file"||z.name==="exec_command")){let J=z.name==="write_file"?z.input?.path:z.input?.command?.slice(0,80),K="y";if(this.onConfirm)K=await this.onConfirm(z.id,z.name,J||"");else this.log(`
40
- ${A.warn} ${G.yellow(z.name)} ${G.gray(J||"")}`),K=(await L(` ${G.gray("allow?")} ${G.blue("[y/n/auto]")} `)).trim().toLowerCase();if(K==="auto")this.autoMode=!0;else if(K!=="y"&&K!=="yes"&&K!==""){V.push({type:"tool_result",tool_use_id:z.id,content:"User denied this action.",is_error:!0});continue}}this.emit({type:"tool",name:z.name,detail:JSON.stringify(z.input||{}).slice(0,200)});let Y=await x0(z.name,z.input,this.cfg.cwd);this.emit({type:"tool_result",name:z.name,content:(Y.content||"").slice(0,500),is_error:!!Y.is_error}),V.push({type:"tool_result",tool_use_id:z.id,content:Y.content,is_error:Y.is_error})}this.messages.push({role:"assistant",content:Z.content}),this.messages.push({role:"user",content:V});continue}let $=Z.content.filter((Q)=>Q.type==="text").map((Q)=>Q.text).join("");if($)this.messages.push({role:"assistant",content:$});break}if(this.emit({type:"tokens",input:this.tokens.input,output:this.tokens.output,messages:this.messages.length}),!this.onOutput)console.log(`
41
- ${G.gray(`tokens: ${this.tokens.input}↑ ${this.tokens.output}↓`)}`)}async streamResponse(){let Z=!this.onOutput,$=Z?new r("Thinking").start():null,Q=[],V="",z="",Y="",J="",K="end_turn",X=!1;try{let W=J0(this.cfg.provider,this.messages,this.cfg.systemPrompt,k0,this.cfg.maxTokens);for await(let U of W)switch(U.type){case"text":if(!X){if($?.stop(),X=!0,Z)process.stdout.write(`
42
- ${A.ai} `)}if(U.text)this.write(U.text);V+=U.text;break;case"tool_start":if(!X)$?.stop(),X=!0;if(V)Q.push({type:"text",text:V}),V="";z=U.id,Y=U.name,J="";break;case"tool_input":J+=U.partial;break;case"tool_end":if(z){let _={};try{_=JSON.parse(J)}catch{}Q.push({type:"tool_use",id:z,name:Y,input:_}),z="",J=""}break;case"usage":this.tokens.input+=U.input,this.tokens.output+=U.output;break;case"done":K=U.stopReason;break}}catch(W){if($?.stop(),Z)console.log();let U=W.message||String(W);if(this.emit({type:"error",message:U}),Z)I(U);return{content:[],stopReason:"error"}}if(V){if(Q.push({type:"text",text:V}),this.emit({type:"text_done"}),Z)process.stdout.write(`
31
+ `),X=B1(J,K),W=3,q=new Set;if(X.forEach((N,B)=>{if(N.type!=="same")q.add(B)}),q.size===0){console.log(` ${V.gray("(no changes)")}`),console.log();return}let U=new Set;for(let N of q)for(let B=Math.max(0,N-W);B<=Math.min(X.length-1,N+W);B++)U.add(B);let _=-1,E=0,H=0,R=200,D=0;for(let N=0;N<X.length;N++){if(!U.has(N))continue;if(D>=R){let O=Array.from(U).filter((L)=>L>N).length;console.log(V.gray(` ... (${O+q.size-E-H} more lines, diff capped at ${R})`));break}if(_!==-1&&N-_>1)console.log(V.gray(" ..."));let B=X[N];if(B.type==="del")console.log(` ${V.pink(`- ${B.line}`)}`),H++;else if(B.type==="add")console.log(` ${V.green(`+ ${B.line}`)}`),E++;else console.log(` ${V.gray(` ${B.line}`)}`);_=N,D++}console.log(` ${V.green(`+${E}`)} ${V.pink(`-${H}`)}`),console.log()}function R1(Z,$){let Q=w(Z.path,$);if(!_1(Q,$)){let Y=`BLOCKED: Cannot write outside project root. Path "${Z.path}" resolves outside "${$}"`;return console.log(` ${V.pink(`⛔ ${Y}`)}`),Y}let z=x0(Q);if(!P(z))S0(z,{recursive:!0});let G=P(Q)?x(Q,"utf8"):null;return j.recordWrite(Q,Z.content),e(Q,Z.content,"utf8"),E1(Q,G,Z.content,$),`Written ${Z.content.split(`
32
+ `).length} lines to ${Z.path}`}function D1(Z,$){let Q=w(Z.path||".",$);if(!P(Q))return`Directory not found: ${Z.path||"."}`;let z=Z.depth||1,G=[];function Y(J,K){if(K>z)return;try{let X=m(J);for(let W of X){if(W.startsWith(".")||W==="node_modules")continue;let q=k(J,W),U=h(Q,q);try{let _=k0(q),E=" ".repeat(K);if(_.isDirectory())G.push(`${E}${U}/`),Y(q,K+1);else{let H=_.size>1024?`${(_.size/1024).toFixed(1)}KB`:`${_.size}B`;G.push(`${E}${U} (${H})`)}}catch{}}}catch{}}return Y(Q,0),G.length>0?G.join(`
33
+ `):"(empty directory)"}async function O1(Z,$){let Q=w(Z.path||".",$),z=Z.pattern;try{let J=["-n","--max-count=50","--no-heading"];if(Z.include)J.push("--glob",Z.include);return J.push(z,Q),await new Promise((X,W)=>{let q=v0("rg",J,{shell:!0}),U="";q.stdout.on("data",(_)=>U+=_.toString()),q.on("close",(_)=>{if(_===0||_===1)X(U.trim()||"No matches found.");else W(Error("rg failed"))}),q.on("error",W)})}catch{}let G=[];function Y(J){try{for(let K of m(J)){if(K.startsWith(".")||K==="node_modules")continue;let X=k(J,K);try{let W=k0(X);if(W.isDirectory()){Y(X);continue}if(W.size>500000)continue;if(Z.include&&!j1(K,Z.include))continue;let U=x(X,"utf8").split(`
34
+ `);for(let _=0;_<U.length;_++)if(U[_].includes(z)){if(G.push(`${h($,X)}:${_+1}: ${U[_].trim()}`),G.length>=50)return}}catch{}}}catch{}}return Y(Q),G.length>0?G.join(`
35
+ `):"No matches found."}async function F1(Z,$){if(H1(Z.command)){let J=`BLOCKED: Dangerous command rejected: "${Z.command}"`;return console.log(` ${V.pink(`⛔ ${J}`)}`),J}let Q=w(Z.cwd||".",$),z=process.platform==="win32",G=z?"cmd":"sh",Y=z?"/c":"-c";return new Promise((J)=>{let K=v0(G,[Y,Z.command],{cwd:Q,env:{...process.env,PAGER:"cat"}}),X="",W="";K.stdout.on("data",(U)=>X+=U.toString()),K.stderr.on("data",(U)=>W+=U.toString());let q=setTimeout(()=>K.kill(),30000);K.on("close",(U)=>{clearTimeout(q);let _="";if(X.trim())_+=X.trim();if(W.trim())_+=(_?`
36
+ `:"")+`[stderr] ${W.trim()}`;_+=`
37
+ [exit code: ${U}]`,J(_)}),K.on("error",(U)=>{clearTimeout(q),J(`[error] Failed to start process: ${U.message}`)})})}function b0(Z,$){if(Z.length<=$)return Z;return Z.slice(0,$)+`
38
+ ... (truncated, ${Z.length-$} chars omitted)`}function j1(Z,$){if($.startsWith("*."))return Z.endsWith($.slice(1));return Z.includes($.replace(/\*/g,""))}var j,w0,q1,U1,N1=30000;var q0=T(()=>{t();j=new h0,w0=[{name:"read_file",description:"Read contents of a file. Returns the file text.",input_schema:{type:"object",properties:{path:{type:"string",description:"File path (relative to cwd or absolute)"},start_line:{type:"number",description:"Optional: start line (1-indexed)"},end_line:{type:"number",description:"Optional: end line (1-indexed, inclusive)"}},required:["path"]}},{name:"write_file",description:"Write content to a file. Creates parent directories if needed.",input_schema:{type:"object",properties:{path:{type:"string",description:"File path"},content:{type:"string",description:"Full file content to write"}},required:["path","content"]}},{name:"list_dir",description:"List files and directories in a path. Returns names with type indicators.",input_schema:{type:"object",properties:{path:{type:"string",description:"Directory path (default: cwd)"},depth:{type:"number",description:"Max depth (default: 1)"}},required:[]}},{name:"search_files",description:"Search for text in files using pattern matching (like grep). Returns matching lines with file paths.",input_schema:{type:"object",properties:{pattern:{type:"string",description:"Text or regex pattern to search for"},path:{type:"string",description:"Directory to search in (default: cwd)"},include:{type:"string",description:'Glob pattern to filter files, e.g. "*.ts"'}},required:["pattern"]}},{name:"exec_command",description:"Execute a shell command. Returns stdout and stderr.",input_schema:{type:"object",properties:{command:{type:"string",description:"Shell command to execute"},cwd:{type:"string",description:"Working directory (default: project cwd)"}},required:["command"]}}],q1=["rm -rf /","rm -rf ~","rm -rf *","del /s /q c:","del /s /q d:","format c:","format d:","mkfs","dd if=","shutdown","reboot",":(){:|:&};:","chmod -R 777 /","> /dev/sda","mv / ","mv ~ "],U1=[/\$\(.*\b(rm|del|format|mkfs|dd|shutdown|reboot)\b/i,/`.*\b(rm|del|format|mkfs|dd|shutdown|reboot)\b/i,/\|\s*(sh|bash|cmd|powershell)/i,/\beval\s/i]});class g{messages=[];tokens={input:0,output:0};cfg;autoMode=!1;onOutput;onConfirm;constructor(Z){this.cfg=Z}emit(Z){this.onOutput?.(Z)}write(Z){if(this.onOutput)this.emit({type:"text",text:Z});else process.stdout.write(Z)}log(Z){if(this.onOutput)this.emit({type:"text",text:Z+`
39
+ `});else console.log(Z)}async send(Z){this.messages.push({role:"user",content:Z}),await this.agentLoop()}async agentLoop(){while(!0){let Z=await this.streamResponse();if(Z.stopReason==="error")break;if(Z.stopReason==="tool_use"){let Q=Z.content.filter((G)=>G.type==="tool_use"),z=[];for(let G of Q){if(!this.autoMode&&(G.name==="write_file"||G.name==="exec_command")){let J=G.name==="write_file"?G.input?.path:G.input?.command?.slice(0,80),K="y";if(this.onConfirm)K=await this.onConfirm(G.id,G.name,J||"");else this.log(`
40
+ ${A.warn} ${V.yellow(G.name)} ${V.gray(J||"")}`),K=(await b(` ${V.gray("allow?")} ${V.blue("[y/n/auto]")} `)).trim().toLowerCase();if(K==="auto")this.autoMode=!0;else if(K!=="y"&&K!=="yes"&&K!==""){z.push({type:"tool_result",tool_use_id:G.id,content:"User denied this action.",is_error:!0});continue}}this.emit({type:"tool",name:G.name,detail:JSON.stringify(G.input||{}).slice(0,200)});let Y=await y0(G.name,G.input,this.cfg.cwd);this.emit({type:"tool_result",name:G.name,content:(Y.content||"").slice(0,500),is_error:!!Y.is_error}),z.push({type:"tool_result",tool_use_id:G.id,content:Y.content,is_error:Y.is_error})}this.messages.push({role:"assistant",content:Z.content}),this.messages.push({role:"user",content:z});continue}let $=Z.content.filter((Q)=>Q.type==="text").map((Q)=>Q.text).join("");if($)this.messages.push({role:"assistant",content:$});break}if(this.emit({type:"tokens",input:this.tokens.input,output:this.tokens.output,messages:this.messages.length}),!this.onOutput)console.log(`
41
+ ${V.gray(`tokens: ${this.tokens.input}↑ ${this.tokens.output}↓`)}`)}async streamResponse(){let Z=!this.onOutput,$=Z?new r("Thinking").start():null,Q=[],z="",G="",Y="",J="",K="end_turn",X=!1;try{let W=X0(this.cfg.provider,this.messages,this.cfg.systemPrompt,w0,this.cfg.maxTokens);for await(let q of W)switch(q.type){case"text":if(!X){if($?.stop(),X=!0,Z)process.stdout.write(`
42
+ ${A.ai} `)}if(q.text)this.write(q.text);z+=q.text;break;case"tool_start":if(!X)$?.stop(),X=!0;if(z)Q.push({type:"text",text:z}),z="";G=q.id,Y=q.name,J="";break;case"tool_input":J+=q.partial;break;case"tool_end":if(G){let U={};try{U=JSON.parse(J)}catch{}Q.push({type:"tool_use",id:G,name:Y,input:U}),G="",J=""}break;case"usage":this.tokens.input+=q.input,this.tokens.output+=q.output;break;case"done":K=q.stopReason;break}}catch(W){if($?.stop(),Z)console.log();let q=W.message||String(W);if(this.emit({type:"error",message:q}),Z)I(q);return{content:[],stopReason:"error"}}if(z){if(Q.push({type:"text",text:z}),this.emit({type:"text_done"}),Z)process.stdout.write(`
43
43
  `)}if(!X)$?.stop();return{content:Q,stopReason:K}}async compact(){if(this.messages.length<4){this.log(` ${A.warn} Not enough messages to compact.`);return}let Z=!this.onOutput?new r("Compacting").start():null;try{let $="";for(let J of this.messages)if(typeof J.content==="string")$+=`${J.role}: ${J.content.slice(0,500)}
44
44
  `;else{let K=J.content.filter((W)=>W.type==="text").map((W)=>W.text?.slice(0,300)).join(" ");if(K)$+=`${J.role}: ${K}
45
45
  `;let X=J.content.filter((W)=>W.type==="tool_use").map((W)=>`[tool: ${W.name}]`).join(", ");if(X)$+=` tools: ${X}
46
- `}let Q=this.messages.length,V=`Summarize this conversation concisely. Keep key decisions, file changes, and current state. Be brief:
46
+ `}let Q=this.messages.length,z=`Summarize this conversation concisely. Keep key decisions, file changes, and current state. Be brief:
47
47
 
48
- ${$.slice(0,6000)}`;this.messages=[{role:"user",content:V},{role:"assistant",content:`[Conversation compacted from ${Q} messages. Summary of what happened:]`}];let z=J0(this.cfg.provider,[{role:"user",content:V}],"You are a conversation summarizer. Create a brief summary preserving key facts, decisions, and file changes.",[],this.cfg.maxTokens),Y="";for await(let J of z){if(J.type==="text"&&J.text)Y+=J.text;if(J.type==="usage")this.tokens.input+=J.input,this.tokens.output+=J.output}this.messages=[{role:"user",content:`[Previous conversation summary]
49
- ${Y}`},{role:"assistant",content:"Understood. I have the context from our previous conversation. How can I continue helping you?"}],Z?.stop(),this.log(` ${A.ok} Compacted ${Q} messages → 2 ${G.gray(`(saved ~${Math.round($.length/4)} tokens)`)}`)}catch($){Z?.stop();let Q=`Compact failed: ${$.message}`;if(this.emit({type:"error",message:Q}),!this.onOutput)I(Q)}}get stats(){return this.tokens}get messageCount(){return this.messages.length}clear(){this.messages=[],this.tokens={input:0,output:0}}exportState(){return{messages:this.messages,tokens:{...this.tokens},autoMode:this.autoMode}}importState(Z){if(Z.messages)this.messages=Z.messages;if(Z.tokens)this.tokens=Z.tokens;if(Z.autoMode!==void 0)this.autoMode=Z.autoMode}getTitle(){let Z=this.messages.find(($)=>$.role==="user"&&typeof $.content==="string");if(Z)return Z.content.slice(0,50);return"New conversation"}}var _0=C(()=>{K0();U0();t()});var l;var H0=C(()=>{l={name:"tenicli",version:"0.3.3",description:"Lightweight AI coding CLI — fast, compact, multi-provider",type:"module",bin:{teni:"./dist/index.js"},files:["dist/","README.md","LICENSE"],scripts:{dev:"bun run src/index.ts","build:npm":"bun build src/index.ts --outfile dist/index.js --target node --minify",build:"bun build --compile --minify src/index.ts --outfile teni","build:win":"bun build --compile --minify --target=bun-windows-x64 src/index.ts --outfile teni.exe","build:linux":"bun build --compile --minify --target=bun-linux-x64 src/index.ts --outfile teni","build:mac":"bun build --compile --minify --target=bun-darwin-x64 src/index.ts --outfile teni",prepublishOnly:"bun run build:npm"},keywords:["ai","cli","coding","agent","anthropic","openai","terminal"],author:"Yan Tenica",license:"MIT",repository:{type:"git",url:"https://github.com/Nhqvu2005/TeniCli.git"},homepage:"https://github.com/Nhqvu2005/TeniCli",engines:{node:">=18"},dependencies:{},devDependencies:{"@types/bun":"latest","@types/figlet":"^1.7.0",figlet:"^1.11.0"}}});var d0={};O0(d0,{renderQR:()=>P1,getLocalIPs:()=>C1});function P1(Z){let $=[],Q=Math.max(Z.length+4,30),V="██",z=" ";for(let J=0;J<7;J++){let K="";for(let X=0;X<7;X++)K+=N0.FINDER[J][X]?"██":" ";K+=" ";for(let X=0;X<Q-15;X++)K+=J===6&&X%2===0?"██":J===6?" ":" ";K+=" ";for(let X=0;X<7;X++)K+=N0.FINDER[J][X]?"██":" ";$.push(K)}$.push(" ".repeat(Q/2+1));let Y=5;for(let J=0;J<Y;J++){let K="";for(let X=0;X<Q+1;X++){if(X===6){K+=J%2===0?"██":" ";continue}K+=(X+J*3+X*J)%3===0?"██":" "}$.push(K)}$.push(" ".repeat(Q/2+1));for(let J=0;J<7;J++){let K="";for(let X=0;X<7;X++)K+=N0.FINDER[J][X]?"██":" ";K+=" ";for(let X=0;X<Q-14;X++)K+=(X+J*5)%3===0?"██":" ";$.push(K)}return $.map((J)=>" "+J).join(`
50
- `)}function C1(){try{let{networkInterfaces:Z}=Z0("os"),$=Z(),Q=[];for(let V of Object.keys($))for(let z of $[V])if(z.family==="IPv4"&&!z.internal)Q.push(z.address);return Q}catch{return[]}}var N0;var l0=C(()=>{N0={FINDER:[[1,1,1,1,1,1,1],[1,0,0,0,0,0,1],[1,0,1,1,1,0,1],[1,0,1,1,1,0,1],[1,0,1,1,1,0,1],[1,0,0,0,0,0,1],[1,1,1,1,1,1,1]]}});var E0={};O0(E0,{startServer:()=>y1,getActiveServers:()=>S1});import{createServer as L1}from"http";import{createHash as T1}from"crypto";function S1(){return A0}function b1(Z){if(Z.length<2)return null;let $=Z[0]&15,Q=(Z[1]&128)!==0,V=Z[1]&127,z=2;if(V===126){if(Z.length<4)return null;V=Z.readUInt16BE(2),z=4}else if(V===127){if(Z.length<10)return null;V=Number(Z.readBigUInt64BE(2)),z=10}let J=z+(Q?4:0)+V;if(Z.length<J)return null;if(Q){let K=Z.slice(z,z+4),X=Buffer.alloc(V);for(let W=0;W<V;W++)X[W]=Z[z+4+W]^K[W%4];return{opcode:$,payload:X,totalSize:J}}return{opcode:$,payload:Z.slice(z,z+V),totalSize:J}}function k1(Z){let $=Buffer.from(Z,"utf8"),Q=$.length,V;if(Q<126)V=Buffer.alloc(2),V[0]=129,V[1]=Q;else if(Q<65536)V=Buffer.alloc(4),V[0]=129,V[1]=126,V.writeUInt16BE(Q,2);else V=Buffer.alloc(10),V[0]=129,V[1]=127,V.writeBigUInt64BE(BigInt(Q),2);return Buffer.concat([V,$])}function x1(Z){let $=Buffer.alloc(2);$[0]=137,$[1]=0,Z.write($)}function h1(Z,$){return`<!DOCTYPE html>
48
+ ${$.slice(0,6000)}`;this.messages=[{role:"user",content:z},{role:"assistant",content:`[Conversation compacted from ${Q} messages. Summary of what happened:]`}];let G=X0(this.cfg.provider,[{role:"user",content:z}],"You are a conversation summarizer. Create a brief summary preserving key facts, decisions, and file changes.",[],this.cfg.maxTokens),Y="";for await(let J of G){if(J.type==="text"&&J.text)Y+=J.text;if(J.type==="usage")this.tokens.input+=J.input,this.tokens.output+=J.output}this.messages=[{role:"user",content:`[Previous conversation summary]
49
+ ${Y}`},{role:"assistant",content:"Understood. I have the context from our previous conversation. How can I continue helping you?"}],Z?.stop(),this.log(` ${A.ok} Compacted ${Q} messages → 2 ${V.gray(`(saved ~${Math.round($.length/4)} tokens)`)}`)}catch($){Z?.stop();let Q=`Compact failed: ${$.message}`;if(this.emit({type:"error",message:Q}),!this.onOutput)I(Q)}}get stats(){return this.tokens}get messageCount(){return this.messages.length}clear(){this.messages=[],this.tokens={input:0,output:0}}exportState(){return{messages:this.messages,tokens:{...this.tokens},autoMode:this.autoMode}}importState(Z){if(Z.messages)this.messages=Z.messages;if(Z.tokens)this.tokens=Z.tokens;if(Z.autoMode!==void 0)this.autoMode=Z.autoMode}getTitle(){let Z=this.messages.find(($)=>$.role==="user"&&typeof $.content==="string");if(Z)return Z.content.slice(0,50);return"New conversation"}}var U0=T(()=>{Y0();q0();t()});var l;var _0=T(()=>{l={name:"tenicli",version:"0.3.4",description:"Lightweight AI coding CLI — fast, compact, multi-provider",type:"module",bin:{teni:"./dist/index.js"},files:["dist/","README.md","LICENSE"],scripts:{dev:"bun run src/index.ts","build:npm":"bun build src/index.ts --outfile dist/index.js --target node --minify",build:"bun build --compile --minify src/index.ts --outfile teni","build:win":"bun build --compile --minify --target=bun-windows-x64 src/index.ts --outfile teni.exe","build:linux":"bun build --compile --minify --target=bun-linux-x64 src/index.ts --outfile teni","build:mac":"bun build --compile --minify --target=bun-darwin-x64 src/index.ts --outfile teni",prepublishOnly:"bun run build:npm"},keywords:["ai","cli","coding","agent","anthropic","openai","terminal"],author:"Yan Tenica",license:"MIT",repository:{type:"git",url:"https://github.com/Nhqvu2005/TeniCli.git"},homepage:"https://github.com/Nhqvu2005/TeniCli",engines:{node:">=18"},dependencies:{},devDependencies:{"@types/bun":"latest","@types/figlet":"^1.7.0",figlet:"^1.11.0"}}});var i0={};O0(i0,{renderQR:()=>T1,getLocalIPs:()=>b1});function T1(Z){let $=[],Q=Math.max(Z.length+4,30),z="██",G=" ";for(let J=0;J<7;J++){let K="";for(let X=0;X<7;X++)K+=N0.FINDER[J][X]?"██":" ";K+=" ";for(let X=0;X<Q-15;X++)K+=J===6&&X%2===0?"██":J===6?" ":" ";K+=" ";for(let X=0;X<7;X++)K+=N0.FINDER[J][X]?"██":" ";$.push(K)}$.push(" ".repeat(Q/2+1));let Y=5;for(let J=0;J<Y;J++){let K="";for(let X=0;X<Q+1;X++){if(X===6){K+=J%2===0?"██":" ";continue}K+=(X+J*3+X*J)%3===0?"██":" "}$.push(K)}$.push(" ".repeat(Q/2+1));for(let J=0;J<7;J++){let K="";for(let X=0;X<7;X++)K+=N0.FINDER[J][X]?"██":" ";K+=" ";for(let X=0;X<Q-14;X++)K+=(X+J*5)%3===0?"██":" ";$.push(K)}return $.map((J)=>" "+J).join(`
50
+ `)}function b1(){try{let{networkInterfaces:Z}=Q0("os"),$=Z(),Q=[];for(let z of Object.keys($))for(let G of $[z])if(G.family==="IPv4"&&!G.internal)Q.push(G.address);return Q}catch{return[]}}var N0;var c0=T(()=>{N0={FINDER:[[1,1,1,1,1,1,1],[1,0,0,0,0,0,1],[1,0,1,1,1,0,1],[1,0,1,1,1,0,1],[1,0,1,1,1,0,1],[1,0,0,0,0,0,1],[1,1,1,1,1,1,1]]}});var B0={};O0(B0,{startServer:()=>g1,getActiveServers:()=>x1});import{createServer as k1}from"http";import{createHash as S1}from"crypto";function x1(){return A0}function h1(Z){if(Z.length<2)return null;let $=Z[0]&15,Q=(Z[1]&128)!==0,z=Z[1]&127,G=2;if(z===126){if(Z.length<4)return null;z=Z.readUInt16BE(2),G=4}else if(z===127){if(Z.length<10)return null;z=Number(Z.readBigUInt64BE(2)),G=10}let J=G+(Q?4:0)+z;if(Z.length<J)return null;if(Q){let K=Z.slice(G,G+4),X=Buffer.alloc(z);for(let W=0;W<z;W++)X[W]=Z[G+4+W]^K[W%4];return{opcode:$,payload:X,totalSize:J}}return{opcode:$,payload:Z.slice(G,G+z),totalSize:J}}function w1(Z){let $=Buffer.from(Z,"utf8"),Q=$.length,z;if(Q<126)z=Buffer.alloc(2),z[0]=129,z[1]=Q;else if(Q<65536)z=Buffer.alloc(4),z[0]=129,z[1]=126,z.writeUInt16BE(Q,2);else z=Buffer.alloc(10),z[0]=129,z[1]=127,z.writeBigUInt64BE(BigInt(Q),2);return Buffer.concat([z,$])}function y1(Z){let $=Buffer.alloc(2);$[0]=137,$[1]=0,Z.write($)}function v1(Z,$){return`<!DOCTYPE html>
51
51
  <html lang="en">
52
52
  <head>
53
53
  <meta charset="utf-8">
@@ -292,17 +292,17 @@ ${Y}`},{role:"assistant",content:"Understood. I have the context from our previo
292
292
  })();
293
293
  </script>
294
294
  </body>
295
- </html>`}function y1(Z,$){let Q=n(),V=new Map,z=new Map,Y=L1((K,X)=>{if(new URL(K.url||"/",`http://${K.headers.host||"localhost"}`).pathname==="/health"){X.writeHead(200,{"content-type":"application/json","access-control-allow-origin":"*"}),X.end(JSON.stringify({status:"ok",sessions:V.size,version:l.version}));return}X.writeHead(200,{"content-type":"text/html; charset=utf-8","cache-control":"no-cache"}),X.end(h1(l.version,$))});Y.on("upgrade",(K,X)=>{if(new URL(K.url||"/",`http://${K.headers.host||"localhost"}`).searchParams.get("token")!==$){X.write(`HTTP/1.1 401 Unauthorized\r
295
+ </html>`}function g1(Z,$){let Q=n(),z=new Map,G=new Map,Y=k1((K,X)=>{if(new URL(K.url||"/",`http://${K.headers.host||"localhost"}`).pathname==="/health"){X.writeHead(200,{"content-type":"application/json","access-control-allow-origin":"*"}),X.end(JSON.stringify({status:"ok",sessions:z.size,version:l.version}));return}X.writeHead(200,{"content-type":"text/html; charset=utf-8","cache-control":"no-cache"}),X.end(v1(l.version,$))});Y.on("upgrade",(K,X)=>{if(new URL(K.url||"/",`http://${K.headers.host||"localhost"}`).searchParams.get("token")!==$){X.write(`HTTP/1.1 401 Unauthorized\r
296
296
  \r
297
- `),X.destroy();return}let _=K.headers["sec-websocket-key"];if(!_){X.destroy();return}let H=T1("sha1").update(_+"258EAFA5-E914-47DA-95CA-5ABB5C0A2C15").digest("base64");X.write(`HTTP/1.1 101 Switching Protocols\r
297
+ `),X.destroy();return}let U=K.headers["sec-websocket-key"];if(!U){X.destroy();return}let _=S1("sha1").update(U+"258EAFA5-E914-47DA-95CA-5ABB5C0A2C15").digest("base64");X.write(`HTTP/1.1 101 Switching Protocols\r
298
298
  Upgrade: websocket\r
299
299
  Connection: Upgrade\r
300
- Sec-WebSocket-Accept: `+H+`\r
300
+ Sec-WebSocket-Accept: `+_+`\r
301
301
  \r
302
- `);let D=Buffer.alloc(0),q=(E)=>{try{X.write(k1(JSON.stringify(E)))}catch{}};X.on("data",(E)=>{D=Buffer.concat([D,E]);while(D.length>0){let R=b1(D);if(!R)break;if(D=D.slice(R.totalSize),R.opcode===8){X.end();return}if(R.opcode===9){let B=Buffer.alloc(2+R.payload.length);B[0]=138,B[1]=R.payload.length,R.payload.copy(B,2),X.write(B);continue}if(R.opcode===10)continue;try{let B=JSON.parse(R.payload.toString("utf8"));w1(B,q,V,z,Q)}catch{}}});let N=setInterval(()=>{try{x1(X)}catch{clearInterval(N)}},30000);X.on("close",()=>{clearInterval(N);for(let[E,R]of V)if(R.send===q)V.delete(E)}),X.on("error",()=>{try{X.destroy()}catch{}})});let J=()=>{Y.close(),A0.delete(Z)};return Y.listen(Z,"0.0.0.0",()=>{A0.set(Z,{password:$,close:J})}),{close:J}}function w1(Z,$,Q,V,z){switch(Z.type){case"new_session":{let Y={...z,provider:{...z.provider}},J=new g(Y);J.autoMode=!0,J.onOutput=(K)=>{$({...K,sessionId:Z.sessionId})},J.onConfirm=(K,X,W)=>{return new Promise((U)=>{$({type:"confirm",sessionId:Z.sessionId,id:K,tool:X,preview:W}),V.set(K,U),setTimeout(()=>{if(V.has(K))V.delete(K),U("y")},60000)})},Q.set(Z.sessionId,{id:Z.sessionId,chat:J,send:$,alive:!0});break}case"close_session":Q.delete(Z.sessionId);break;case"message":{let Y=Q.get(Z.sessionId);if(!Y)return;let J=Z.text?.trim();if(!J)return;if(J==="/clear"){Y.chat.clear(),$({type:"system",sessionId:Z.sessionId,text:"Conversation cleared"});return}if(J==="/compact"){Y.chat.compact();return}if(J==="/cost"){let K=Y.chat.stats;$({type:"tokens",sessionId:Z.sessionId,input:K.input,output:K.output,messages:Y.chat.messageCount});return}Y.chat.send(J).catch((K)=>{$({type:"error",sessionId:Z.sessionId,message:K.message})});break}case"confirm_response":{let Y=V.get(Z.id);if(Y)V.delete(Z.id),Y(Z.answer);break}}}var A0;var D0=C(()=>{_0();V0();H0();A0=new Map});V0();_0();K0();U0();t();import{writeFileSync as v1,existsSync as g1}from"fs";import{join as f1,relative as P}from"path";import{randomBytes as a0}from"crypto";import{existsSync as w0,readFileSync as v0,writeFileSync as g0,mkdirSync as O1,readdirSync as F1,unlinkSync as f0}from"fs";import{join as f}from"path";var y0=20;function d(){let Z=process.env.HOME||process.env.USERPROFILE||"",$=f(Z,".tenicli","history");if(!w0($))O1($,{recursive:!0});return $}function j1(){return Date.now().toString(36)+Math.random().toString(36).slice(2,6)}function u0(Z){let $=f(d(),`${Z.id}.json`);g0($,JSON.stringify(Z,null,0),"utf8"),M1()}function q0(){let Z=d();try{return F1(Z).filter(($)=>$.endsWith(".json")).map(($)=>{try{return JSON.parse(v0(f(Z,$),"utf8"))}catch{return null}}).filter(($)=>$!==null).sort(($,Q)=>Q.updatedAt.localeCompare($.updatedAt))}catch{return[]}}function M1(){let Z=q0();if(Z.length<=y0)return;let $=d();for(let Q of Z.slice(y0))try{f0(f($,`${Q.id}.json`))}catch{}}function s(Z){let $=new Date().toISOString();return{id:j1(),title:"New conversation",model:Z,createdAt:$,updatedAt:$,messages:[],tokens:{input:0,output:0}}}function p0(Z){let $=f(d(),"__resume__.json");return g0($,JSON.stringify(Z,null,0),"utf8"),$}function m0(){let Z=f(d(),"__resume__.json");try{if(w0(Z)){let $=JSON.parse(v0(Z,"utf8"));return f0(Z),$}}catch{}return null}H0();var R0=l.version;function u1(Z){let $={command:"chat",prompt:"",print:!1,json:!1,yes:!1,quiet:!1},Q=0;if(Z[0]&&!Z[0].startsWith("-")){let V=Z[0].toLowerCase();if(["run","diff","undo","log","chat","remote","serve"].includes(V))$.command=V,Q=1}while(Q<Z.length){switch(Z[Q]){case"serve":case"remote":$.command="remote";break;case"--port":$.port=parseInt(Z[++Q]);break;case"--password":$.password=Z[++Q];break;case"-p":case"--print":if($.print=!0,$.command="run",Q+1<Z.length&&!Z[Q+1].startsWith("-"))$.prompt=Z[++Q];break;case"-m":case"--model":$.model=Z[++Q];break;case"--base-url":$.baseUrl=Z[++Q];break;case"--json":$.json=!0;break;case"-y":case"--yes":$.yes=!0;break;case"-q":case"--quiet":$.quiet=!0;break;case"--all":$.all=!0;break;case"-v":case"--version":console.log(`teni v${R0}`),process.exit(0);case"-h":case"--help":p1(),process.exit(0);default:if(!Z[Q].startsWith("-"))$.prompt=Z.slice(Q).join(" "),Q=Z.length}Q++}return $}function p1(){console.log(`
303
- ${G.bold(G.blue("TeniCLI"))} v${R0} — Lightweight AI Coding Agent
302
+ `);let E=Buffer.alloc(0),H=(D)=>{try{X.write(w1(JSON.stringify(D)))}catch{}};X.on("data",(D)=>{E=Buffer.concat([E,D]);while(E.length>0){let N=h1(E);if(!N)break;if(E=E.slice(N.totalSize),N.opcode===8){X.end();return}if(N.opcode===9){let B=Buffer.alloc(2+N.payload.length);B[0]=138,B[1]=N.payload.length,N.payload.copy(B,2),X.write(B);continue}if(N.opcode===10)continue;try{let B=JSON.parse(N.payload.toString("utf8"));f1(B,H,z,G,Q)}catch{}}});let R=setInterval(()=>{try{y1(X)}catch{clearInterval(R)}},30000);X.on("close",()=>{clearInterval(R);for(let[D,N]of z)if(N.send===H)z.delete(D)}),X.on("error",()=>{try{X.destroy()}catch{}})});let J=()=>{Y.close(),A0.delete(Z)};return Y.listen(Z,"0.0.0.0",()=>{A0.set(Z,{password:$,close:J})}),{close:J}}function f1(Z,$,Q,z,G){switch(Z.type){case"new_session":{let Y={...G,provider:{...G.provider}},J=new g(Y);J.autoMode=!0,J.onOutput=(K)=>{$({...K,sessionId:Z.sessionId})},J.onConfirm=(K,X,W)=>{return new Promise((q)=>{$({type:"confirm",sessionId:Z.sessionId,id:K,tool:X,preview:W}),z.set(K,q),setTimeout(()=>{if(z.has(K))z.delete(K),q("y")},60000)})},Q.set(Z.sessionId,{id:Z.sessionId,chat:J,send:$,alive:!0});break}case"close_session":Q.delete(Z.sessionId);break;case"message":{let Y=Q.get(Z.sessionId);if(!Y)return;let J=Z.text?.trim();if(!J)return;if(J==="/clear"){Y.chat.clear(),$({type:"system",sessionId:Z.sessionId,text:"Conversation cleared"});return}if(J==="/compact"){Y.chat.compact();return}if(J==="/cost"){let K=Y.chat.stats;$({type:"tokens",sessionId:Z.sessionId,input:K.input,output:K.output,messages:Y.chat.messageCount});return}Y.chat.send(J).catch((K)=>{$({type:"error",sessionId:Z.sessionId,message:K.message})});break}case"confirm_response":{let Y=z.get(Z.id);if(Y)z.delete(Z.id),Y(Z.answer);break}}}var A0;var E0=T(()=>{U0();J0();_0();A0=new Map});J0();U0();Y0();q0();t();import{writeFileSync as u1,existsSync as p1}from"fs";import{join as m1,relative as C}from"path";import{randomBytes as n0}from"crypto";import{existsSync as f0,readFileSync as u0,writeFileSync as p0,mkdirSync as M1,readdirSync as I1,unlinkSync as m0}from"fs";import{join as f}from"path";var g0=20;function d(){let Z=process.env.HOME||process.env.USERPROFILE||"",$=f(Z,".tenicli","history");if(!f0($))M1($,{recursive:!0});return $}function P1(){return Date.now().toString(36)+Math.random().toString(36).slice(2,6)}function d0(Z){let $=f(d(),`${Z.id}.json`);p0($,JSON.stringify(Z,null,0),"utf8"),C1()}function H0(){let Z=d();try{return I1(Z).filter(($)=>$.endsWith(".json")).map(($)=>{try{return JSON.parse(u0(f(Z,$),"utf8"))}catch{return null}}).filter(($)=>$!==null).sort(($,Q)=>Q.updatedAt.localeCompare($.updatedAt))}catch{return[]}}function C1(){let Z=H0();if(Z.length<=g0)return;let $=d();for(let Q of Z.slice(g0))try{m0(f($,`${Q.id}.json`))}catch{}}function Z0(Z){let $=new Date().toISOString();return{id:P1(),title:"New conversation",model:Z,createdAt:$,updatedAt:$,messages:[],tokens:{input:0,output:0}}}function l0(Z){let $=f(d(),"__resume__.json");return p0($,JSON.stringify(Z,null,0),"utf8"),$}function a0(){let Z=f(d(),"__resume__.json");try{if(f0(Z)){let $=JSON.parse(u0(Z,"utf8"));return m0(Z),$}}catch{}return null}_0();var R0=l.version;function d1(Z){let $={command:"chat",prompt:"",print:!1,json:!1,yes:!1,quiet:!1},Q=0;if(Z[0]&&!Z[0].startsWith("-")){let z=Z[0].toLowerCase();if(["run","diff","undo","log","chat","remote","serve"].includes(z))$.command=z,Q=1}while(Q<Z.length){switch(Z[Q]){case"serve":case"remote":$.command="remote";break;case"--port":$.port=parseInt(Z[++Q]);break;case"--password":$.password=Z[++Q];break;case"-p":case"--print":if($.print=!0,$.command="run",Q+1<Z.length&&!Z[Q+1].startsWith("-"))$.prompt=Z[++Q];break;case"-m":case"--model":$.model=Z[++Q];break;case"--base-url":$.baseUrl=Z[++Q];break;case"--json":$.json=!0;break;case"-y":case"--yes":$.yes=!0;break;case"-q":case"--quiet":$.quiet=!0;break;case"--all":$.all=!0;break;case"-v":case"--version":console.log(`teni v${R0}`),process.exit(0);case"-h":case"--help":l1(),process.exit(0);default:if(!Z[Q].startsWith("-"))$.prompt=Z.slice(Q).join(" "),Q=Z.length}Q++}return $}function l1(){console.log(`
303
+ ${V.bold(V.blue("TeniCLI"))} v${R0} — Lightweight AI Coding Agent
304
304
 
305
- ${G.bold("COMMANDS")}
305
+ ${V.bold("COMMANDS")}
306
306
  teni Interactive chat (default)
307
307
  teni chat Same as above
308
308
  teni run "<prompt>" Non-interactive: execute and exit
@@ -311,7 +311,7 @@ ${G.bold("COMMANDS")}
311
311
  teni log List all AI actions with timestamps
312
312
  teni remote Start web remote server
313
313
 
314
- ${G.bold("GLOBAL FLAGS")}
314
+ ${V.bold("GLOBAL FLAGS")}
315
315
  -m, --model <model> Override model
316
316
  --base-url <url> Override API base URL
317
317
  --json Machine-readable JSON output
@@ -320,11 +320,11 @@ ${G.bold("GLOBAL FLAGS")}
320
320
  -v, --version Show version
321
321
  -h, --help Show help
322
322
 
323
- ${G.bold("REMOTE FLAGS")}
323
+ ${V.bold("REMOTE FLAGS")}
324
324
  --port <port> Server port (default: 3000)
325
325
  --password <pw> Access password (auto-generated if omitted)
326
326
 
327
- ${G.bold("IN-CHAT COMMANDS")}
327
+ ${V.bold("IN-CHAT COMMANDS")}
328
328
  /model Change model /auth Set API key
329
329
  /mode Ask/Auto toggle /compact Summarize chat
330
330
  /diff Files changed /undo Revert last write
@@ -333,44 +333,44 @@ ${G.bold("IN-CHAT COMMANDS")}
333
333
  /remote Remote access /quota API rate limits
334
334
  /exit Quit
335
335
 
336
- ${G.bold("EXIT CODES")}
336
+ ${V.bold("EXIT CODES")}
337
337
  0 Success
338
338
  1 API/runtime error
339
339
  2 User abort
340
340
  3 Tool execution failure
341
- `)}async function m1(Z,$){switch(Z.toLowerCase().split(" ")[0]){case"/exit":case"/quit":case"/q":console.log(`
342
- ${G.gray("Bye!")} \uD83D\uDC4B
343
- `),process.exit(0);case"/clear":return $.clear(),j.clear(),console.log(` ${A.ok} Conversation cleared`),!0;case"/compact":return await $.compact(),!0;case"/diff":{let Q=j.getChanges();if(Q.length===0)console.log(` ${G.gray("No files changed in this session.")}`);else{console.log(`
344
- ${G.bold("Files changed this session:")}`);for(let V of Q){let z=P($.cfg.cwd,V.path),Y=V.isNew?G.green("[NEW]"):G.yellow("[MOD]");console.log(` ${Y} ${G.cyan(z)} ${G.gray(`(${V.lines} lines)`)}`)}console.log(` ${G.gray(`total: ${Q.length} files`)}`)}return!0}case"/undo":{let Q=j.undo();if(!Q)console.log(` ${G.gray("Nothing to undo.")}`);else{let V=P($.cfg.cwd,Q.path);if(Q.restored)console.log(` ${A.ok} Restored: ${G.cyan(V)}`);else console.log(` ${A.ok} Deleted (was new): ${G.cyan(V)}`)}return!0}case"/init":{let Q=f1($.cfg.cwd,"TENICLI.md");if(g1(Q))console.log(` ${A.warn} TENICLI.md already exists.`);else v1(Q,l1,"utf8"),console.log(` ${A.ok} Created ${G.cyan("TENICLI.md")}`);return!0}case"/mode":{$.autoMode=!$.autoMode;let Q=$.autoMode?G.yellow("auto"):G.green("ask");return console.log(` ${A.ok} Mode: ${Q} ${G.gray($.autoMode?"(tools run without asking)":"(confirm write/exec)")}`),!0}case"/cost":{let Q=$.stats;return console.log(` ${A.ai} ${G.blue(String(Q.input))}↑ input ${G.blue(String(Q.output))}↓ output ${G.gray(`(${$.messageCount} msgs)`)}`),!0}case"/model":{let Q=i(),V=Q.customModels||[],z=[...u.map((K)=>({id:K.id,name:K.name,provider:K.provider,speed:K.speed,custom:!1})),...V.map((K)=>({id:K.id,name:K.id,provider:K.provider,speed:"custom",custom:!0}))],Y=z.map((K)=>({label:`${K.name} ${$.cfg.provider.model===K.id?G.green("●"):""}`,desc:`${K.provider} • ${K.speed}`}));Y.push({label:"Custom model...",desc:"type model ID"});let J=await S("Select model",Y);if(J===-1)return console.log(` ${G.gray("Cancelled")}`),!0;if(J<z.length){let K=z[J];$.cfg.provider.model=K.id,$.cfg.provider.type=K.provider;let X=K.provider==="openai"?process.env.OPENAI_API_KEY||Q.keys?.openai||"":process.env.ANTHROPIC_API_KEY||Q.keys?.anthropic||"";if(X)$.cfg.provider.apiKey=X;if(!Q.baseUrls?.[K.provider])$.cfg.provider.baseUrl=K.provider==="openai"?"https://api.openai.com":"https://api.anthropic.com";c({activeModel:K.id}),console.log(` ${A.ok} Model: ${G.blue(K.name)}`)}else{let K=await S("Provider for custom model",[{label:"Anthropic",desc:"Claude-compatible"},{label:"OpenAI",desc:"GPT-compatible"}]);if(K===-1)return console.log(` ${G.gray("Cancelled")}`),!0;let X=K===0?"anthropic":"openai",W=await L(` ${G.gray("model ID")} ${G.blue("❯")} `);if(!W.trim())return console.log(` ${G.gray("Cancelled")}`),!0;let U=W.trim();$.cfg.provider.model=U,$.cfg.provider.type=X;let _=V.filter((D)=>D.id!==U);_.push({id:U,provider:X}),c({activeModel:U,customModels:_});let H=X==="openai"?process.env.OPENAI_API_KEY||Q.keys?.openai||"":process.env.ANTHROPIC_API_KEY||Q.keys?.anthropic||"";if(H)$.cfg.provider.apiKey=H;console.log(` ${A.ok} Model: ${G.blue(U)} ${G.gray("(saved to list)")}`)}return!0}case"/auth":{let Q=await S("Provider",[{label:"Anthropic",desc:"Claude models"},{label:"OpenAI",desc:"GPT models"},{label:"Custom",desc:"Anthropic-compatible proxy"}]);if(Q===-1)return console.log(` ${G.gray("Cancelled")}`),!0;let z=["anthropic","openai","anthropic"][Q],Y=await L(` ${G.gray("API Key")} ${G.blue("❯")} `);if(!Y.trim())return console.log(` ${A.warn} Cancelled`),!0;let J={[z]:Y.trim()},K={};if(Q===2){let X=await L(` ${G.gray("Base URL")} ${G.blue("❯")} `);if(X.trim())K[z]=X.trim()}if(c({keys:J,baseUrls:K}),$.cfg.provider.apiKey=Y.trim(),$.cfg.provider.type=z,K[z])$.cfg.provider.baseUrl=K[z];return console.log(` ${A.ok} ${z} key saved to ~/.tenicli/config.json`),!0}case"/help":return console.log(`
345
- ${G.bold("Commands")}
346
- ${G.blue("/model")} Select AI model
347
- ${G.blue("/auth")} Set API key
348
- ${G.blue("/mode")} Toggle ask/auto ${G.gray("(confirm before write/exec)")}
349
- ${G.blue("/compact")} Summarize conversation ${G.gray("(save tokens)")}
350
- ${G.blue("/diff")} List files changed this session
351
- ${G.blue("/undo")} Revert last file write
352
- ${G.blue("/init")} Create TENICLI.md template
353
- ${G.blue("/remote")} Start web remote access
354
- ${G.blue("/history")} Browse past conversations
355
- ${G.blue("/quota")} Show API rate limits
356
- ${G.blue("/update")} Update to latest version
357
- ${G.blue("/clear")} New conversation
358
- ${G.blue("/cost")} Show token usage
359
- ${G.blue("/exit")} Quit
360
- ${G.gray("\\\\")} Continue on next line`),!0;case"/remote":{let{getLocalIPs:Q,renderQR:V}=await Promise.resolve().then(() => (l0(),d0)),{startServer:z,getActiveServers:Y}=await Promise.resolve().then(() => (D0(),E0)),J=Y();if(J.size>0){let H=Array.from(J.entries()).map(([q,N])=>({label:`Port ${q} ${G.green("●")}`,desc:`password: ${N.password}`}));H.push({label:G.cyan("+ New server"),desc:"start on random port"}),H.push({label:G.yellow("Stop all"),desc:"close all remote servers"});let D=await S("Remote servers",H);if(D===-1)return console.log(` ${G.gray("Cancelled")}`),!0;if(D<J.size){let q=Array.from(J.entries())[D],N=q[0],E=await S(`Server on port ${N}`,[{label:"Show QR & Local URL",desc:"display QR code for Wi-Fi access"},{label:"Publish to Internet",desc:"use localtunnel (free public URL)"},{label:"Stop server",desc:"close this port"}]);if(E===0){let O=`http://${Q()[0]||"localhost"}:${N}`;console.log(`
361
- ${G.gray("URL:")} ${G.cyan(O)}`),console.log(` ${G.gray("Password:")} ${G.yellow(q[1].password)}
362
- `),console.log(V(O)),console.log()}else if(E===1){console.log(`
363
- ${A.tool} ${G.yellow("Starting localtunnel...")}`);try{let{spawn:R}=await import("child_process"),B=R(/^win/.test(process.platform)?"npx.cmd":"npx",["--yes","localtunnel","--port",String(N)]);B.unref(),await new Promise((O,x)=>{let e=setTimeout(()=>{x(Error("Localtunnel timed out"))},1e4);B.stdout.on("data",(i0)=>{let B0=i0.toString();if(B0.includes("your url is:")){clearTimeout(e);let c0=B0.split("your url is:")[1].trim();console.log(` ${A.ok} ${G.green("Published to Internet!")}
364
- `),console.log(` ${G.gray("Public URL:")} ${G.cyan(c0)}`),console.log(` ${G.gray("Password:")} ${G.yellow(q[1].password)}
365
- `),console.log(` ${G.gray("Note: The tunnel runs in the background.")}`),O()}}),B.stderr.on("data",()=>{})}),q[1].tunnel=B}catch(R){console.log(` ${A.warn} ${G.pink(`Failed to publish: ${R.message}`)}`)}}else if(E===2){if(q[1].close(),q[1].tunnel)try{q[1].tunnel.kill()}catch{}console.log(` ${A.ok} Stopped server on port ${N}`)}return!0}else if(D===J.size);else{for(let[q,N]of J)if(N.close(),N.tunnel)try{N.tunnel.kill()}catch{}return console.log(` ${A.ok} All remote servers stopped`),!0}}let K=3000+Math.floor(Math.random()*7000),X=a0(6).toString("hex"),_=`http://${Q()[0]||"localhost"}:${K}`;return z(K,X),console.log(),p([G.bold(G.green("Remote Access Enabled")),"",`${G.gray("URL:")} ${G.cyan(_)}`,`${G.gray("Password:")} ${G.yellow(X)}`,`${G.gray("Port:")} ${G.blue(String(K))}`,"",G.gray("Use /remote again to manage or publish this server.")],58),console.log(),console.log(V(_)),console.log(),!0}case"/quota":{let Q=z0;if(!Q.requestsLimit&&!Q.tokensLimit)return console.log(` ${G.gray("No rate limit data yet. Send a message first.")}`),!0;let V=[G.bold("API Rate Limits"),""];if(Q.requestsLimit!==void 0){let z=Q.requestsLimit-(Q.requestsRemaining||0),Y=Math.round((Q.requestsRemaining||0)/Q.requestsLimit*100),J=Y>50?G.green:Y>20?G.yellow:G.pink;V.push(`${G.gray("Requests:")} ${J(String(Q.requestsRemaining))}/${Q.requestsLimit} remaining ${G.gray(`(${Y}%)`)}`)}if(Q.tokensLimit!==void 0){let z=Math.round((Q.tokensRemaining||0)/Q.tokensLimit*100),Y=z>50?G.green:z>20?G.yellow:G.pink;V.push(`${G.gray("Tokens:")} ${Y(String(Q.tokensRemaining?.toLocaleString()))}/${Q.tokensLimit.toLocaleString()} remaining ${G.gray(`(${z}%)`)}`)}if(Q.requestsReset){let z=new Date(Q.requestsReset);V.push(`${G.gray("Resets at:")} ${G.cyan(z.toLocaleTimeString())}`)}return console.log(),p(V,58),!0}case"/history":{let Q=q0();if(Q.length===0)return console.log(` ${G.gray("No saved conversations.")}`),!0;let V=Q.slice(0,10).map((J)=>({label:J.title.slice(0,40),desc:`${J.model} • ${new Date(J.updatedAt).toLocaleDateString()}`})),z=await S("Resume conversation",V);if(z===-1)return console.log(` ${G.gray("Cancelled")}`),!0;let Y=Q[z];return $.clear(),$.importState({messages:Y.messages,tokens:Y.tokens}),$.__convId=Y.id,console.log(` ${A.ok} Restored: ${G.blue(Y.title)} ${G.gray(`(${Y.messages.length} msgs)`)}`),!0}case"/update":{console.log(`
366
- ${A.tool} ${G.yellow("Updating tenicli...")}`);try{let Q=$.exportState(),V=s($.cfg.provider.model);V.title=$.getTitle(),V.messages=Q.messages,V.tokens=Q.tokens,p0(V);let{execSync:z,spawn:Y}=await import("child_process");return z("npm i -g tenicli@latest 2>&1",{encoding:"utf8"}),console.log(` ${A.ok} ${G.green("Updated! Restarting...")}
367
- `),Y(process.execPath,process.argv.slice(1),{stdio:"inherit",detached:!1}).on("exit",(K)=>process.exit(K||0)),!0}catch(Q){I(`Update failed: ${Q.message}`)}return!0}default:return console.log(` ${A.warn} Unknown: ${Z.split(" ")[0]} — try /help`),!0}}async function d1(){let Z=u1(process.argv.slice(2)),$=n();if(Z.model)$.provider.model=Z.model;if(Z.baseUrl)$.provider.baseUrl=Z.baseUrl;switch(Z.command){case"remote":{let W=Z.port||3000,U=Z.password||a0(6).toString("hex"),{startServer:_}=await Promise.resolve().then(() => (D0(),E0));_(W,U);return}case"run":{if(!Z.prompt)I('Usage: teni run "<prompt>"'),process.exit(1);if(!$.provider.apiKey)I("No API key. Run: teni then /auth"),process.exit(1);let W=new g($);if(Z.yes)W.autoMode=!0;if(await W.send(Z.prompt),Z.json){let U=j.getChanges();console.log(JSON.stringify({ok:!0,tokens:W.stats,filesChanged:U.map((_)=>({path:P($.cwd,_.path),isNew:_.isNew,lines:_.lines}))}))}process.exit(0)}case"diff":{let W=j.getChanges();if(Z.json)console.log(JSON.stringify({files:W.map((U)=>({path:P($.cwd,U.path),isNew:U.isNew,lines:U.lines}))}));else if(W.length===0)console.log(` ${G.gray("No files changed in this session.")}`);else{console.log(`
368
- ${G.bold("Files changed this session:")}`);for(let U of W){let _=P($.cwd,U.path),H=U.isNew?G.green("[NEW]"):G.yellow("[MOD]");console.log(` ${H} ${G.cyan(_)} ${G.gray(`(${U.lines} lines)`)}`)}console.log(` ${G.gray(`total: ${W.length} files`)}`)}process.exit(0)}case"undo":{if(Z.all){let W=j.undoAll();if(Z.json)console.log(JSON.stringify({ok:!0,reverted:W}));else console.log(W>0?` ${A.ok} Reverted ${W} file changes`:` ${G.gray("Nothing to undo.")}`)}else{let W=j.undo();if(Z.json)console.log(JSON.stringify({ok:!!W,file:W?P($.cwd,W.path):null}));else if(!W)console.log(` ${G.gray("Nothing to undo.")}`);else{let U=P($.cwd,W.path);console.log(W.restored?` ${A.ok} Restored: ${G.cyan(U)}`:` ${A.ok} Deleted (was new): ${G.cyan(U)}`)}}process.exit(0)}case"log":{let W=j.getTimeline();if(Z.json)console.log(JSON.stringify({actions:W.map((U)=>({path:P($.cwd,U.path),label:U.label,lines:U.lines,time:U.time.toISOString()}))}));else if(W.length===0)console.log(` ${G.gray("No AI actions recorded.")}`);else{console.log(`
369
- ${G.bold("AI Action Timeline:")} ${G.gray(`(${W.length} snapshots)`)}`);for(let U=0;U<W.length;U++){let _=W[U],H=P($.cwd,_.path),D=_.isNew?G.green("CREATE"):G.yellow("MODIFY"),q=_.time.toLocaleTimeString();console.log(` ${G.gray(`#${U+1}`)} ${G.gray(q)} ${D} ${G.cyan(H)} ${G.gray(`(${_.lines} lines)`)}`)}}process.exit(0)}}let Q=new g($);if(Z.yes)Q.autoMode=!0;P0(R0);let V=u.find((W)=>W.id===$.provider.model)?.name||$.provider.model,z=Q.autoMode?G.yellow("auto"):G.green("ask"),Y=[`${G.gray("model")} ${G.blue(V)} ${G.gray("mode")} ${z} ${G.gray("cwd")} ${G.cyan($.cwd)}`];if(!$.provider.apiKey)Y.push(""),Y.push(`${A.warn} ${G.yellow("No API key configured. Run /auth to set one.")}`);p(Y,60),console.log();let J=m0(),K=s($.provider.model);if(J)Q.importState({messages:J.messages,tokens:J.tokens}),K=J,console.log(` ${A.ok} ${G.green("Session restored after update")} ${G.gray(`(${J.messages.length} msgs)`)}`),console.log();let X=()=>{if(Q.messageCount===0)return;let W=Q.exportState();K.title=Q.getTitle(),K.messages=W.messages,K.tokens=W.tokens,K.model=$.provider.model,K.updatedAt=new Date().toISOString(),u0(K)};if(process.on("SIGINT",()=>{X(),console.log(`
370
- ${G.gray("Bye!")} \uD83D\uDC4B
371
- `),process.exit(0)}),Z.prompt){if(console.log(` ${A.prompt} ${Z.prompt}`),$.provider.apiKey)await Q.send(Z.prompt);X()}while(!0)try{let U=(await C0()).trim();if(!U)continue;if(U.startsWith("/")){if(U==="/clear")X(),K=s($.provider.model);await m1(U,Q);continue}if(!Q.cfg.provider.apiKey){console.log(` ${A.warn} ${G.yellow("No API key. Run /auth first.")}`);continue}await Q.send(U),X()}catch(W){if(W.message==="EOF")X(),console.log(`
372
- ${G.gray("Bye!")} \uD83D\uDC4B
373
- `),process.exit(0);I(W.message)}}d1().catch((Z)=>{I(Z.message),process.exit(1)});var l1=`# Project Instructions
341
+ `)}async function a1(Z,$){switch(Z.toLowerCase().split(" ")[0]){case"/exit":case"/quit":case"/q":console.log(`
342
+ ${V.gray("Bye!")} \uD83D\uDC4B
343
+ `),process.exit(0);case"/clear":return $.clear(),j.clear(),console.log(` ${A.ok} Conversation cleared`),!0;case"/compact":return await $.compact(),!0;case"/diff":{let Q=j.getChanges();if(Q.length===0)console.log(` ${V.gray("No files changed in this session.")}`);else{console.log(`
344
+ ${V.bold("Files changed this session:")}`);for(let z of Q){let G=C($.cfg.cwd,z.path),Y=z.isNew?V.green("[NEW]"):V.yellow("[MOD]");console.log(` ${Y} ${V.cyan(G)} ${V.gray(`(${z.lines} lines)`)}`)}console.log(` ${V.gray(`total: ${Q.length} files`)}`)}return!0}case"/undo":{let Q=j.undo();if(!Q)console.log(` ${V.gray("Nothing to undo.")}`);else{let z=C($.cfg.cwd,Q.path);if(Q.restored)console.log(` ${A.ok} Restored: ${V.cyan(z)}`);else console.log(` ${A.ok} Deleted (was new): ${V.cyan(z)}`)}return!0}case"/init":{let Q=m1($.cfg.cwd,"TENICLI.md");if(p1(Q))console.log(` ${A.warn} TENICLI.md already exists.`);else u1(Q,c1,"utf8"),console.log(` ${A.ok} Created ${V.cyan("TENICLI.md")}`);return!0}case"/mode":{$.autoMode=!$.autoMode;let Q=$.autoMode?V.yellow("auto"):V.green("ask");return console.log(` ${A.ok} Mode: ${Q} ${V.gray($.autoMode?"(tools run without asking)":"(confirm write/exec)")}`),!0}case"/cost":{let Q=$.stats;return console.log(` ${A.ai} ${V.blue(String(Q.input))}↑ input ${V.blue(String(Q.output))}↓ output ${V.gray(`(${$.messageCount} msgs)`)}`),!0}case"/model":{let Q=i(),z=Q.customModels||[],G=[...u.map((K)=>({id:K.id,name:K.name,provider:K.provider,speed:K.speed,custom:!1})),...z.map((K)=>({id:K.id,name:K.id,provider:K.provider,speed:"custom",custom:!0}))],Y=G.map((K)=>({label:`${K.name} ${$.cfg.provider.model===K.id?V.green("●"):""}`,desc:`${K.provider} • ${K.speed}`}));Y.push({label:"Custom model...",desc:"type model ID"});let J=await S("Select model",Y);if(J===-1)return console.log(` ${V.gray("Cancelled")}`),!0;if(J<G.length){let K=G[J];$.cfg.provider.model=K.id,$.cfg.provider.type=K.provider;let X=K.provider==="openai"?process.env.OPENAI_API_KEY||Q.keys?.openai||"":process.env.ANTHROPIC_API_KEY||Q.keys?.anthropic||"";if(X)$.cfg.provider.apiKey=X;if(!Q.baseUrls?.[K.provider])$.cfg.provider.baseUrl=K.provider==="openai"?"https://api.openai.com":"https://api.anthropic.com";c({activeModel:K.id}),console.log(` ${A.ok} Model: ${V.blue(K.name)}`)}else{let K=await S("Provider for custom model",[{label:"Anthropic",desc:"Claude-compatible"},{label:"OpenAI",desc:"GPT-compatible"}]);if(K===-1)return console.log(` ${V.gray("Cancelled")}`),!0;let X=K===0?"anthropic":"openai",W=await b(` ${V.gray("model ID")} ${V.blue("❯")} `);if(!W.trim())return console.log(` ${V.gray("Cancelled")}`),!0;let q=W.trim();$.cfg.provider.model=q,$.cfg.provider.type=X;let U=z.filter((E)=>E.id!==q);U.push({id:q,provider:X}),c({activeModel:q,customModels:U});let _=X==="openai"?process.env.OPENAI_API_KEY||Q.keys?.openai||"":process.env.ANTHROPIC_API_KEY||Q.keys?.anthropic||"";if(_)$.cfg.provider.apiKey=_;console.log(` ${A.ok} Model: ${V.blue(q)} ${V.gray("(saved to list)")}`)}return!0}case"/auth":{let Q=await S("Provider",[{label:"Anthropic",desc:"Claude models"},{label:"OpenAI",desc:"GPT models"},{label:"Custom",desc:"Anthropic-compatible proxy"}]);if(Q===-1)return console.log(` ${V.gray("Cancelled")}`),!0;let G=["anthropic","openai","anthropic"][Q],Y=await b(` ${V.gray("API Key")} ${V.blue("❯")} `);if(!Y.trim())return console.log(` ${A.warn} Cancelled`),!0;let J={[G]:Y.trim()},K={};if(Q===2){let X=await b(` ${V.gray("Base URL")} ${V.blue("❯")} `);if(X.trim())K[G]=X.trim()}if(c({keys:J,baseUrls:K}),$.cfg.provider.apiKey=Y.trim(),$.cfg.provider.type=G,K[G])$.cfg.provider.baseUrl=K[G];return console.log(` ${A.ok} ${G} key saved to ~/.tenicli/config.json`),!0}case"/help":return console.log(`
345
+ ${V.bold("Commands")}
346
+ ${V.blue("/model")} Select AI model
347
+ ${V.blue("/auth")} Set API key
348
+ ${V.blue("/mode")} Toggle ask/auto ${V.gray("(confirm before write/exec)")}
349
+ ${V.blue("/compact")} Summarize conversation ${V.gray("(save tokens)")}
350
+ ${V.blue("/diff")} List files changed this session
351
+ ${V.blue("/undo")} Revert last file write
352
+ ${V.blue("/init")} Create TENICLI.md template
353
+ ${V.blue("/remote")} Start web remote access
354
+ ${V.blue("/history")} Browse past conversations
355
+ ${V.blue("/quota")} Show API rate limits
356
+ ${V.blue("/update")} Update to latest version
357
+ ${V.blue("/clear")} New conversation
358
+ ${V.blue("/cost")} Show token usage
359
+ ${V.blue("/exit")} Quit
360
+ ${V.gray("\\\\")} Continue on next line`),!0;case"/remote":{let{getLocalIPs:Q,renderQR:z}=await Promise.resolve().then(() => (c0(),i0)),{startServer:G,getActiveServers:Y}=await Promise.resolve().then(() => (E0(),B0)),J=Y();if(J.size>0){let _=Array.from(J.entries()).map(([H,R])=>({label:`Port ${H} ${V.green("●")}`,desc:`password: ${R.password}`}));_.push({label:V.cyan("+ New server"),desc:"start on random port"}),_.push({label:V.yellow("Stop all"),desc:"close all remote servers"});let E=await S("Remote servers",_);if(E===-1)return console.log(` ${V.gray("Cancelled")}`),!0;if(E<J.size){let H=Array.from(J.entries())[E],R=H[0],D=await S(`Server on port ${R}`,[{label:"Show QR & Local URL",desc:"display QR code for Wi-Fi access"},{label:"Publish to Internet",desc:"use localtunnel (free public URL)"},{label:"Stop server",desc:"close this port"}]);if(D===0){let O=`http://${Q()[0]||"localhost"}:${R}`;console.log(`
361
+ ${V.gray("URL:")} ${V.cyan(O)}`),console.log(` ${V.gray("Password:")} ${V.yellow(H[1].password)}
362
+ `),console.log(z(O)),console.log()}else if(D===1){console.log(`
363
+ ${A.tool} ${V.yellow("Starting localtunnel...")}`);try{let{spawn:N}=await import("child_process"),B=N(/^win/.test(process.platform)?"npx.cmd":"npx",["--yes","localtunnel","--port",String(R)]);B.unref(),await new Promise((O,L)=>{let $0=setTimeout(()=>{L(Error("Localtunnel timed out"))},1e4);B.stdout.on("data",(o0)=>{let D0=o0.toString();if(D0.includes("your url is:")){clearTimeout($0);let r0=D0.split("your url is:")[1].trim();console.log(` ${A.ok} ${V.green("Published to Internet!")}
364
+ `),console.log(` ${V.gray("Public URL:")} ${V.cyan(r0)}`),console.log(` ${V.gray("Password:")} ${V.yellow(H[1].password)}
365
+ `),console.log(` ${V.gray("Note: The tunnel runs in the background.")}`),O()}}),B.stderr.on("data",()=>{})}),H[1].tunnel=B}catch(N){console.log(` ${A.warn} ${V.pink(`Failed to publish: ${N.message}`)}`)}}else if(D===2){if(H[1].close(),H[1].tunnel)try{H[1].tunnel.kill()}catch{}console.log(` ${A.ok} Stopped server on port ${R}`)}return!0}else if(E===J.size);else{for(let[H,R]of J)if(R.close(),R.tunnel)try{R.tunnel.kill()}catch{}return console.log(` ${A.ok} All remote servers stopped`),!0}}let K=3000+Math.floor(Math.random()*7000),X=n0(6).toString("hex"),U=`http://${Q()[0]||"localhost"}:${K}`;return G(K,X),console.log(),p([V.bold(V.green("Remote Access Enabled")),"",`${V.gray("URL:")} ${V.cyan(U)}`,`${V.gray("Password:")} ${V.yellow(X)}`,`${V.gray("Port:")} ${V.blue(String(K))}`,"",V.gray("Use /remote again to manage or publish this server.")],58),console.log(),console.log(z(U)),console.log(),!0}case"/quota":{let Q=K0;if(!Q.requestsLimit&&!Q.tokensLimit)return console.log(` ${V.gray("No rate limit data yet. Send a message first.")}`),!0;let z=[V.bold("API Rate Limits"),""];if(Q.requestsLimit!==void 0){let G=Q.requestsLimit-(Q.requestsRemaining||0),Y=Math.round((Q.requestsRemaining||0)/Q.requestsLimit*100),J=Y>50?V.green:Y>20?V.yellow:V.pink;z.push(`${V.gray("Requests:")} ${J(String(Q.requestsRemaining))}/${Q.requestsLimit} remaining ${V.gray(`(${Y}%)`)}`)}if(Q.tokensLimit!==void 0){let G=Math.round((Q.tokensRemaining||0)/Q.tokensLimit*100),Y=G>50?V.green:G>20?V.yellow:V.pink;z.push(`${V.gray("Tokens:")} ${Y(String(Q.tokensRemaining?.toLocaleString()))}/${Q.tokensLimit.toLocaleString()} remaining ${V.gray(`(${G}%)`)}`)}if(Q.requestsReset){let G=new Date(Q.requestsReset);z.push(`${V.gray("Resets at:")} ${V.cyan(G.toLocaleTimeString())}`)}return console.log(),p(z,58),!0}case"/history":{let Q=H0();if(Q.length===0)return console.log(` ${V.gray("No saved conversations.")}`),!0;let z=Q.slice(0,10).map((J)=>({label:J.title.slice(0,40),desc:`${J.model} • ${new Date(J.updatedAt).toLocaleDateString()}`})),G=await S("Resume conversation",z);if(G===-1)return console.log(` ${V.gray("Cancelled")}`),!0;let Y=Q[G];return $.clear(),$.importState({messages:Y.messages,tokens:Y.tokens}),$.__convId=Y.id,console.log(` ${A.ok} Restored: ${V.blue(Y.title)} ${V.gray(`(${Y.messages.length} msgs)`)}`),!0}case"/update":{console.log(`
366
+ ${A.tool} ${V.yellow("Updating tenicli...")}`);try{let Q=$.exportState(),z=Z0($.cfg.provider.model);z.title=$.getTitle(),z.messages=Q.messages,z.tokens=Q.tokens,l0(z);let{execSync:G,spawn:Y}=await import("child_process");return G("npm i -g tenicli@latest 2>&1",{encoding:"utf8"}),console.log(` ${A.ok} ${V.green("Updated! Restarting...")}
367
+ `),Y(process.execPath,process.argv.slice(1),{stdio:"inherit",detached:!1}).on("exit",(K)=>process.exit(K||0)),!0}catch(Q){I(`Update failed: ${Q.message}`)}return!0}default:return console.log(` ${A.warn} Unknown: ${Z.split(" ")[0]} — try /help`),!0}}async function i1(){let Z=d1(process.argv.slice(2)),$=n();if(Z.model)$.provider.model=Z.model;if(Z.baseUrl)$.provider.baseUrl=Z.baseUrl;switch(Z.command){case"remote":{let W=Z.port||3000,q=Z.password||n0(6).toString("hex"),{startServer:U}=await Promise.resolve().then(() => (E0(),B0));U(W,q);return}case"run":{if(!Z.prompt)I('Usage: teni run "<prompt>"'),process.exit(1);if(!$.provider.apiKey)I("No API key. Run: teni then /auth"),process.exit(1);let W=new g($);if(Z.yes)W.autoMode=!0;if(await W.send(Z.prompt),Z.json){let q=j.getChanges();console.log(JSON.stringify({ok:!0,tokens:W.stats,filesChanged:q.map((U)=>({path:C($.cwd,U.path),isNew:U.isNew,lines:U.lines}))}))}process.exit(0)}case"diff":{let W=j.getChanges();if(Z.json)console.log(JSON.stringify({files:W.map((q)=>({path:C($.cwd,q.path),isNew:q.isNew,lines:q.lines}))}));else if(W.length===0)console.log(` ${V.gray("No files changed in this session.")}`);else{console.log(`
368
+ ${V.bold("Files changed this session:")}`);for(let q of W){let U=C($.cwd,q.path),_=q.isNew?V.green("[NEW]"):V.yellow("[MOD]");console.log(` ${_} ${V.cyan(U)} ${V.gray(`(${q.lines} lines)`)}`)}console.log(` ${V.gray(`total: ${W.length} files`)}`)}process.exit(0)}case"undo":{if(Z.all){let W=j.undoAll();if(Z.json)console.log(JSON.stringify({ok:!0,reverted:W}));else console.log(W>0?` ${A.ok} Reverted ${W} file changes`:` ${V.gray("Nothing to undo.")}`)}else{let W=j.undo();if(Z.json)console.log(JSON.stringify({ok:!!W,file:W?C($.cwd,W.path):null,warning:W?.warning||null}));else if(!W)console.log(` ${V.gray("Nothing to undo.")}`);else{let q=C($.cwd,W.path);if(W.warning)console.log(` ${A.warn} ${V.yellow(W.warning)}`);console.log(W.restored?` ${A.ok} Restored: ${V.cyan(q)}`:` ${A.ok} Deleted (was new): ${V.cyan(q)}`)}}process.exit(0)}case"log":{let W=j.getTimeline();if(Z.json)console.log(JSON.stringify({actions:W.map((q)=>({path:C($.cwd,q.path),label:q.label,lines:q.lines,time:q.time.toISOString()}))}));else if(W.length===0)console.log(` ${V.gray("No AI actions recorded.")}`);else{console.log(`
369
+ ${V.bold("AI Action Timeline:")} ${V.gray(`(${W.length} snapshots)`)}`);for(let q=0;q<W.length;q++){let U=W[q],_=C($.cwd,U.path),E=U.isNew?V.green("CREATE"):V.yellow("MODIFY"),H=U.time.toLocaleTimeString();console.log(` ${V.gray(`#${q+1}`)} ${V.gray(H)} ${E} ${V.cyan(_)} ${V.gray(`(${U.lines} lines)`)}`)}}process.exit(0)}}let Q=new g($);if(Z.yes)Q.autoMode=!0;P0(R0);let z=u.find((W)=>W.id===$.provider.model)?.name||$.provider.model,G=Q.autoMode?V.yellow("auto"):V.green("ask"),Y=[`${V.gray("model")} ${V.blue(z)} ${V.gray("mode")} ${G} ${V.gray("cwd")} ${V.cyan($.cwd)}`];if(!$.provider.apiKey)Y.push(""),Y.push(`${A.warn} ${V.yellow("No API key configured. Run /auth to set one.")}`);p(Y,60),console.log();let J=a0(),K=Z0($.provider.model);if(J)Q.importState({messages:J.messages,tokens:J.tokens}),K=J,console.log(` ${A.ok} ${V.green("Session restored after update")} ${V.gray(`(${J.messages.length} msgs)`)}`),console.log();let X=()=>{if(Q.messageCount===0)return;let W=Q.exportState();K.title=Q.getTitle(),K.messages=W.messages,K.tokens=W.tokens,K.model=$.provider.model,K.updatedAt=new Date().toISOString(),d0(K)};if(process.on("SIGINT",()=>{X(),console.log(`
370
+ ${V.gray("Bye!")} \uD83D\uDC4B
371
+ `),process.exit(0)}),Z.prompt){if(console.log(` ${A.prompt} ${Z.prompt}`),$.provider.apiKey)await Q.send(Z.prompt);X()}while(!0)try{let q=(await C0()).trim();if(!q)continue;if(q.startsWith("/")){if(q==="/clear")X(),K=Z0($.provider.model);await a1(q,Q);continue}if(!Q.cfg.provider.apiKey){console.log(` ${A.warn} ${V.yellow("No API key. Run /auth first.")}`);continue}await Q.send(q),X()}catch(W){if(W.message==="EOF")X(),console.log(`
372
+ ${V.gray("Bye!")} \uD83D\uDC4B
373
+ `),process.exit(0);I(W.message)}}i1().catch((Z)=>{I(Z.message),process.exit(1)});var c1=`# Project Instructions
374
374
 
375
375
  ## Overview
376
376
  Describe your project here so the AI understands the context.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tenicli",
3
- "version": "0.3.3",
3
+ "version": "0.3.4",
4
4
  "description": "Lightweight AI coding CLI — fast, compact, multi-provider",
5
5
  "type": "module",
6
6
  "bin": {