tenicli 0.3.1 → 0.3.2

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 +57 -54
  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 r0}from"node:module";var n0=Object.defineProperty;var c0=(Z)=>Z;function o0(Z,$){this[Z]=c0.bind(null,$)}var R0=(Z,$)=>{for(var Q in $)n0(Z,Q,{get:$[Q],enumerable:!0,configurable:!0,set:o0.bind($,Q)})};var L=(Z,$)=>()=>(Z&&($=Z(Z=0)),$);var Z0=r0(import.meta.url);import{existsSync as a,readFileSync as Q0,writeFileSync as t0,mkdirSync as s0}from"fs";import{join as x}from"path";function G0(){let Z=process.env.HOME||process.env.USERPROFILE||"";return x(Z,".tenicli")}function $0(){return x(G0(),"config.json")}function i(){try{if(a($0()))return JSON.parse(Q0($0(),"utf8"))}catch{}return{}}function n(Z){let $=G0();if(!a($))s0($,{recursive:!0});let Q=i(),K={...Q,...Z,keys:{...Q.keys,...Z.keys},baseUrls:{...Q.baseUrls,...Z.baseUrls}};t0($0(),JSON.stringify(K,null,2),"utf8")}function c(){let Z=process.cwd();O0(x(Z,".tenicli.env")),O0(x(Z,".env"));let $=i(),Q=process.env,K=Q.TENICLI_MODEL||$.activeModel||g[0].id,Y=g.find((W)=>W.id===K)?.provider||Q.TENICLI_PROVIDER||"anthropic",X=e0(Y,$,Q),z=Y==="openai"?"https://api.openai.com":"https://api.anthropic.com",J=Q.TENICLI_BASE_URL||$.baseUrls?.[Y]||z;return{provider:{type:Y,baseUrl:J,apiKey:X,model:K},maxTokens:parseInt(Q.TENICLI_MAX_TOKENS||"8192"),systemPrompt:Z1(Z),cwd:Z}}function e0(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 O0(Z){try{if(!a(Z))return;for(let $ of Q0(Z,"utf8").split(`
3
- `)){let Q=$.trim();if(!Q||Q.startsWith("#"))continue;let K=Q.indexOf("=");if(K===-1)continue;let V=Q.slice(0,K).trim(),Y=Q.slice(K+1).trim();if(Y.startsWith('"')&&Y.endsWith('"')||Y.startsWith("'")&&Y.endsWith("'"))Y=Y.slice(1,-1);if(!process.env[V])process.env[V]=Y}}catch{}}function Z1(Z){for(let $ of[x(Z,"TENICLI.md"),x(G0(),"TENICLI.md")])if(a($))return Q0($,"utf8");return $1}var g,$1=`You are TeniCLI, a fast AI coding assistant in the terminal.
2
+ import{createRequire as r0}from"node:module";var c0=Object.defineProperty;var n0=(Z)=>Z;function o0(Z,$){this[Z]=n0.bind(null,$)}var R0=(Z,$)=>{for(var Q in $)c0(Z,Q,{get:$[Q],enumerable:!0,configurable:!0,set:o0.bind($,Q)})};var C=(Z,$)=>()=>(Z&&($=Z(Z=0)),$);var Z0=r0(import.meta.url);import{existsSync as a,readFileSync as Q0,writeFileSync as t0,mkdirSync as s0}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($))s0($,{recursive:!0});let Q=i(),K={...Q,...Z,keys:{...Q.keys,...Z.keys},baseUrls:{...Q.baseUrls,...Z.baseUrls}};t0($0(),JSON.stringify(K,null,2),"utf8")}function n(){let Z=process.cwd();O0(h(Z,".tenicli.env")),O0(h(Z,".env"));let $=i(),Q=process.env,K=Q.TENICLI_MODEL||$.activeModel||u[0].id,Y=u.find((W)=>W.id===K)?.provider||Q.TENICLI_PROVIDER||"anthropic",z=e0(Y,$,Q),J=Y==="openai"?"https://api.openai.com":"https://api.anthropic.com",X=Q.TENICLI_BASE_URL||$.baseUrls?.[Y]||J;return{provider:{type:Y,baseUrl:X,apiKey:z,model:K},maxTokens:parseInt(Q.TENICLI_MAX_TOKENS||"8192"),systemPrompt:Z1(Z),cwd:Z}}function e0(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 O0(Z){try{if(!a(Z))return;for(let $ of Q0(Z,"utf8").split(`
3
+ `)){let Q=$.trim();if(!Q||Q.startsWith("#"))continue;let K=Q.indexOf("=");if(K===-1)continue;let V=Q.slice(0,K).trim(),Y=Q.slice(K+1).trim();if(Y.startsWith('"')&&Y.endsWith('"')||Y.startsWith("'")&&Y.endsWith("'"))Y=Y.slice(1,-1);if(!process.env[V])process.env[V]=Y}}catch{}}function Z1(Z){for(let $ of[h(Z,"TENICLI.md"),h(G0(),"TENICLI.md")])if(a($))return Q0($,"utf8");return $1}var u,$1=`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,42 +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 K0=L(()=>{g=[{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,K,V){if(Z.type==="openai")yield*G1(Z,$,Q,K,V);else yield*Q1(Z,$,Q,K,V)}async function*Q1(Z,$,Q,K,V){let Y=`${Z.baseUrl.replace(/\/$/,"")}/v1/messages`,X={model:Z.model,max_tokens:V,system:Q,messages:$,stream:!0};if(K.length)X.tools=K;let z=await j0(Y,X,{"anthropic-version":"2023-06-01","x-api-key":Z.apiKey,authorization:`Bearer ${Z.apiKey}`});for await(let J of F0(z))switch(J.type){case"message_start":if(J.message?.usage)yield{type:"usage",input:J.message.usage.input_tokens||0,output:0};break;case"content_block_start":if(J.content_block?.type==="text")yield{type:"text",text:""};else if(J.content_block?.type==="tool_use")yield{type:"tool_start",id:J.content_block.id,name:J.content_block.name};break;case"content_block_delta":if(J.delta?.type==="text_delta")yield{type:"text",text:J.delta.text};else if(J.delta?.type==="input_json_delta")yield{type:"tool_input",partial:J.delta.partial_json};break;case"content_block_stop":yield{type:"tool_end"};break;case"message_delta":if(J.usage)yield{type:"usage",input:0,output:J.usage.output_tokens||0};yield{type:"done",stopReason:J.delta?.stop_reason||"end_turn"};break}}async function*G1(Z,$,Q,K,V){let Y=`${Z.baseUrl.replace(/\/$/,"")}/v1/chat/completions`,X=K1($,Q),z=K.map((_)=>({type:"function",function:{name:_.name,description:_.description,parameters:_.input_schema}})),J={model:Z.model,max_tokens:V,messages:X,stream:!0,stream_options:{include_usage:!0}};if(z.length)J.tools=z;let W=await j0(Y,J,{authorization:`Bearer ${Z.apiKey}`}),N=new Map;for await(let _ of F0(W)){let q=_.choices?.[0];if(!q){if(_.usage)yield{type:"usage",input:_.usage.prompt_tokens||0,output:_.usage.completion_tokens||0};continue}let H=q.delta||{};if(H.content)yield{type:"text",text:H.content};if(H.tool_calls)for(let U of H.tool_calls){if(U.id)N.set(U.index,{id:U.id,name:U.function?.name||"",args:""}),yield{type:"tool_start",id:U.id,name:U.function?.name||""};if(U.function?.arguments){let D=N.get(U.index);if(D)D.args+=U.function.arguments;yield{type:"tool_input",partial:U.function.arguments}}}if(q.finish_reason){for(let[,U]of N)yield{type:"tool_end"};yield{type:"done",stopReason:q.finish_reason==="tool_calls"?"tool_use":q.finish_reason}}}}function K1(Z,$){let Q=[{role:"system",content:$}];for(let K of Z)if(K.role==="user")if(typeof K.content==="string")Q.push({role:"user",content:K.content});else{let V=K.content;for(let Y of V)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 K.content==="string")Q.push({role:"assistant",content:K.content});else{let V=K.content,Y=V.filter((z)=>z.type==="tool_use"),X=V.filter((z)=>z.type==="text").map((z)=>z.text).join("");if(Y.length)Q.push({role:"assistant",content:X||null,tool_calls:Y.map((z)=>({id:z.id,type:"function",function:{name:z.name,arguments:JSON.stringify(z.input||{})}}))});else Q.push({role:"assistant",content:X})}return Q}async function j0(Z,$,Q){let K=await fetch(Z,{method:"POST",headers:{"content-type":"application/json",...Q},body:JSON.stringify($)});if(!K.ok){let E=await K.text();throw Error(`API ${K.status}: ${E.slice(0,300)}`)}let V={},Y=K.headers.get("anthropic-ratelimit-requests-limit");if(Y)V.requestsLimit=parseInt(Y);let X=K.headers.get("anthropic-ratelimit-requests-remaining");if(X)V.requestsRemaining=parseInt(X);let z=K.headers.get("anthropic-ratelimit-requests-reset");if(z)V.requestsReset=z;let J=K.headers.get("anthropic-ratelimit-tokens-limit");if(J)V.tokensLimit=parseInt(J);let W=K.headers.get("anthropic-ratelimit-tokens-remaining");if(W)V.tokensRemaining=parseInt(W);let N=K.headers.get("anthropic-ratelimit-tokens-reset");if(N)V.tokensReset=N;let _=K.headers.get("x-ratelimit-limit-requests");if(_)V.requestsLimit=parseInt(_);let q=K.headers.get("x-ratelimit-remaining-requests");if(q)V.requestsRemaining=parseInt(q);let H=K.headers.get("x-ratelimit-reset-requests");if(H)V.requestsReset=H;let U=K.headers.get("x-ratelimit-limit-tokens");if(U)V.tokensLimit=parseInt(U);let D=K.headers.get("x-ratelimit-remaining-tokens");if(D)V.tokensRemaining=parseInt(D);let R=K.headers.get("x-ratelimit-reset-tokens");if(R)V.tokensReset=R;if(Object.keys(V).length>0)V0=V;return K}async function*F0(Z){let $=Z.body.getReader(),Q=new TextDecoder,K="";while(!0){let{done:V,value:Y}=await $.read();if(V)break;K+=Q.decode(Y,{stream:!0});let X=K.split(`
13
- `);K=X.pop();for(let z of X)if(z.startsWith("data: ")){let J=z.slice(6).trim();if(J==="[DONE]")return;try{yield JSON.parse(J)}catch{}}}}var V0;var z0=L(()=>{V0={}});function V1(){let Z=[" ██ ██ ","██████████","███ ██ █","██████████","██████████"," ██ ██ ██ "],$={T:["█████"," █ "," █ "," █ "," █ "],E:["████ ","█ ","███ ","█ ","████ "],N:["█ █ ","██ █ ","█ ██ ","█ █ ","█ █ "],I:["███"," █ "," █ "," █ ","███"],space:[" "," "," "," "," "],C:[" ███","█ ","█ ","█ "," ███"],L:["█ ","█ ","█ ","█ ","████"]},Q=[$.T,$.E,$.N,$.I,$.space,$.C,$.L,$.I],K=["","","","",""];for(let X=0;X<5;X++)K[X]=Q.map((z)=>z[X]).join(" ");let V=Z.map((X)=>G.cyan(X.padEnd(14," "))),Y=[" ".repeat(K[0].length),...K].map((X)=>G.blue(X));return V.map((X,z)=>`${X} ${Y[z]||""}`).join(`
14
- `)}function f(Z,$=60){let Q=(K,V)=>{let Y=K.replace(/\x1b\[[0-9;]*m/g,""),X=V-Y.length;return X>0?K+" ".repeat(X):K};console.log(G.gray(` ${j.tl}${j.line($)}${j.tr}`));for(let K of Z)console.log(G.gray(` ${j.v}`)+` ${Q(K,$-2)} `+G.gray(j.v));console.log(G.gray(` ${j.bl}${j.line($)}${j.br}`))}function P0(Z="0.0.0"){console.clear(),console.log(),console.log(V1()),console.log(),f([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 C(Z,$=!1){return new Promise((Q,K)=>{if(process.stdout.write(Z),!$||!process.stdin.isTTY){let U="",D=(E)=>{let B=typeof E==="string"?E:E.toString("utf8");if(B.charCodeAt(0)===3)process.stdout.write(`
15
- `),process.exit(0);if(B.charCodeAt(0)===4){R(),K(Error("EOF"));return}U+=B;let O=U.indexOf(`
16
- `);if(O!==-1)R(),Q(U.slice(0,O).replace(/\r$/,""))},R=()=>{process.stdin.removeListener("data",D)};if(!process.stdin.readableEncoding)process.stdin.setEncoding("utf8");process.stdin.on("data",D),process.stdin.resume();return}let V="",Y=0,X=0,z=process.stdin.isRaw;if(process.stdin.setRawMode(!0),!process.stdin.readableEncoding)process.stdin.setEncoding("utf8");process.stdin.resume();let J=()=>{if(!V.startsWith("/")||V.length<1)return[];return X1.filter((U)=>U.cmd.startsWith(V))},W=()=>{if(Y>0){for(let U=0;U<Y;U++)process.stdout.write("\x1B[1B"),process.stdout.write("\x1B[2K");process.stdout.write(`\x1B[${Y}A`),Y=0}process.stdout.write("\x1B[0K")},N=()=>{W();let U=J();if(U.length===0)return;if(X>=U.length)X=U.length-1;if(X<0)X=0;let D=Z.replace(/\x1b\[[0-9;]*m/g,"").length;for(let R=0;R<U.length;R++){process.stdout.write(`
17
- \x1B[2K\r`);let E=U[R];if(R===X)process.stdout.write(` ${G.blue(G.bold(E.cmd))} ${G.gray(E.desc)}`);else process.stdout.write(` ${G.gray(E.cmd)} ${G.gray(G.dim(E.desc))}`)}Y=U.length,process.stdout.write(`\x1B[${Y}A\r\x1B[${D+V.length}C`)},_="",q=(U)=>{let D=typeof U==="string"?U:U.toString("utf8");for(let R=0;R<D.length;R++){let E=D[R],B=E.charCodeAt(0);if(_.length>0||B===27){if(_+=E,_.length===1)continue;if(_.length===2&&_[1]==="[")continue;if(_.length>=3){let O=J();if(_==="\x1B[A"&&O.length>0)X=(X-1+O.length)%O.length,N();else if(_==="\x1B[B"&&O.length>0)X=(X+1)%O.length,N();_="";continue}continue}if(B===3)W(),process.stdin.setRawMode(z),process.stdout.write(`
18
- `),process.exit(0);if(B===4){W(),process.stdin.setRawMode(z),H(),K(Error("EOF"));return}if(B===13||B===10){let O=J();if(O.length>0&&V!==O[X].cmd){W();let k=O[X].cmd;process.stdout.write("\b \b".repeat(V.length)),V=k,process.stdout.write(V)}W(),process.stdin.setRawMode(z),process.stdout.write(`
19
- `),H(),Q(V);return}if(B===127||B===8){if(V.length>0)W(),V=V.slice(0,-1),process.stdout.write("\b \b"),X=0,N();continue}if(B===9){let O=J();if(O.length>0){W();let k=O[X].cmd,e=k.slice(V.length);V=k,process.stdout.write(e),N()}continue}if(B<32)continue;W(),V+=E,process.stdout.write(E),X=0,N()}},H=()=>{process.stdin.removeListener("data",q)};process.stdin.on("data",q)})}async function I0(){let Z=[],$=!0;while(!0){let Q=$?`
20
- ${G.gray(j.tl+j.line(3))} ${A.prompt} `:` ${G.gray(j.v)} `,K=await C(Q,$);if($=!1,K.endsWith("\\"))Z.push(K.slice(0,-1));else{Z.push(K);break}}return Z.join(`
12
+ - Write production-quality code matching the project's style.`;var K0=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*z0(Z,$,Q,K,V){if(Z.type==="openai")yield*G1(Z,$,Q,K,V);else yield*Q1(Z,$,Q,K,V)}async function*Q1(Z,$,Q,K,V){let Y=`${Z.baseUrl.replace(/\/$/,"")}/v1/messages`,z={model:Z.model,max_tokens:V,system:Q,messages:$,stream:!0};if(K.length)z.tools=K;let J=await F0(Y,z,{"anthropic-version":"2023-06-01","x-api-key":Z.apiKey,authorization:`Bearer ${Z.apiKey}`});for await(let X of M0(J))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*G1(Z,$,Q,K,V){let Y=`${Z.baseUrl.replace(/\/$/,"")}/v1/chat/completions`,z=K1($,Q),J=K.map((U)=>({type:"function",function:{name:U.name,description:U.description,parameters:U.input_schema}})),X={model:Z.model,max_tokens:V,messages:z,stream:!0,stream_options:{include_usage:!0}};if(J.length)X.tools=J;let W=await F0(Y,X,{authorization:`Bearer ${Z.apiKey}`}),_=new Map;for await(let U of M0(W)){let N=U.choices?.[0];if(!N){if(U.usage)yield{type:"usage",input:U.usage.prompt_tokens||0,output:U.usage.completion_tokens||0};continue}let D=N.delta||{};if(D.content)yield{type:"text",text:D.content};if(D.tool_calls)for(let q of D.tool_calls){if(q.id)_.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 A=_.get(q.index);if(A)A.args+=q.function.arguments;yield{type:"tool_input",partial:q.function.arguments}}}if(N.finish_reason){for(let[,q]of _)yield{type:"tool_end"};yield{type:"done",stopReason:N.finish_reason==="tool_calls"?"tool_use":N.finish_reason}}}}function K1(Z,$){let Q=[{role:"system",content:$}];for(let K of Z)if(K.role==="user")if(typeof K.content==="string")Q.push({role:"user",content:K.content});else{let V=K.content;for(let Y of V)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 K.content==="string")Q.push({role:"assistant",content:K.content});else{let V=K.content,Y=V.filter((J)=>J.type==="tool_use"),z=V.filter((J)=>J.type==="text").map((J)=>J.text).join("");if(Y.length)Q.push({role:"assistant",content:z||null,tool_calls:Y.map((J)=>({id:J.id,type:"function",function:{name:J.name,arguments:JSON.stringify(J.input||{})}}))});else Q.push({role:"assistant",content:z})}return Q}async function F0(Z,$,Q){let K=await fetch(Z,{method:"POST",headers:{"content-type":"application/json",...Q},body:JSON.stringify($)});if(!K.ok){let B=await K.text();throw Error(`API ${K.status}: ${B.slice(0,300)}`)}let V={},Y=K.headers.get("anthropic-ratelimit-requests-limit");if(Y)V.requestsLimit=parseInt(Y);let z=K.headers.get("anthropic-ratelimit-requests-remaining");if(z)V.requestsRemaining=parseInt(z);let J=K.headers.get("anthropic-ratelimit-requests-reset");if(J)V.requestsReset=J;let X=K.headers.get("anthropic-ratelimit-tokens-limit");if(X)V.tokensLimit=parseInt(X);let W=K.headers.get("anthropic-ratelimit-tokens-remaining");if(W)V.tokensRemaining=parseInt(W);let _=K.headers.get("anthropic-ratelimit-tokens-reset");if(_)V.tokensReset=_;let U=K.headers.get("x-ratelimit-limit-requests");if(U)V.requestsLimit=parseInt(U);let N=K.headers.get("x-ratelimit-remaining-requests");if(N)V.requestsRemaining=parseInt(N);let D=K.headers.get("x-ratelimit-reset-requests");if(D)V.requestsReset=D;let q=K.headers.get("x-ratelimit-limit-tokens");if(q)V.tokensLimit=parseInt(q);let A=K.headers.get("x-ratelimit-remaining-tokens");if(A)V.tokensRemaining=parseInt(A);let E=K.headers.get("x-ratelimit-reset-tokens");if(E)V.tokensReset=E;if(Object.keys(V).length>0)V0=V;return K}async function*M0(Z){let $=Z.body.getReader(),Q=new TextDecoder,K="";while(!0){let{done:V,value:Y}=await $.read();if(V)break;K+=Q.decode(Y,{stream:!0});let z=K.split(`
13
+ `);K=z.pop();for(let J of z)if(J.startsWith("data: ")){let X=J.slice(6).trim();if(X==="[DONE]")return;try{yield JSON.parse(X)}catch{}}}}var V0;var J0=C(()=>{V0={}});function V1(){let Z=[" ██ ██ ","██████████","███ ██ █","██████████","██████████"," ██ ██ ██ "],$={T:["█████"," █ "," █ "," █ "," █ "],E:["████ ","█ ","███ ","█ ","████ "],N:["█ █ ","██ █ ","█ ██ ","█ █ ","█ █ "],I:["███"," █ "," █ "," █ ","███"],space:[" "," "," "," "," "],C:[" ███","█ ","█ ","█ "," ███"],L:["█ ","█ ","█ ","█ ","████"]},Q=[$.T,$.E,$.N,$.I,$.space,$.C,$.L,$.I],K=["","","","",""];for(let z=0;z<5;z++)K[z]=Q.map((J)=>J[z]).join(" ");let V=Z.map((z)=>G.cyan(z.padEnd(14," "))),Y=[" ".repeat(K[0].length),...K].map((z)=>G.blue(z));return V.map((z,J)=>`${z} ${Y[J]||""}`).join(`
14
+ `)}function p(Z,$=60){let Q=(K,V)=>{let Y=K.replace(/\x1b\[[0-9;]*m/g,""),z=V-Y.length;return z>0?K+" ".repeat(z):K};console.log(G.gray(` ${F.tl}${F.line($)}${F.tr}`));for(let K of Z)console.log(G.gray(` ${F.v}`)+` ${Q(K,$-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(V1()),console.log(),p([G.gray("type to chat")+` ${H.dot} `+G.gray("/help for commands")+` ${H.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(H.spinner[this.i%H.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,K)=>{if(process.stdout.write(Z),!$||!process.stdin.isTTY){let q="",A=(B)=>{let R=typeof B==="string"?B:B.toString("utf8");if(R.charCodeAt(0)===3)process.stdout.write(`
15
+ `),process.exit(0);if(R.charCodeAt(0)===4){E(),K(Error("EOF"));return}q+=R;let O=q.indexOf(`
16
+ `);if(O!==-1)E(),Q(q.slice(0,O).replace(/\r$/,""))},E=()=>{process.stdin.removeListener("data",A)};if(!process.stdin.readableEncoding)process.stdin.setEncoding("utf8");process.stdin.on("data",A),process.stdin.resume();return}let V="",Y=0,z=0,J=process.stdin.isRaw;if(process.stdin.setRawMode(!0),!process.stdin.readableEncoding)process.stdin.setEncoding("utf8");process.stdin.resume();let X=()=>{if(!V.startsWith("/")||V.length<1)return[];return z1.filter((q)=>q.cmd.startsWith(V))},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")},_=()=>{W();let q=X();if(q.length===0)return;if(z>=q.length)z=q.length-1;if(z<0)z=0;let A=Z.replace(/\x1b\[[0-9;]*m/g,"").length;for(let E=0;E<q.length;E++){process.stdout.write(`
17
+ \x1B[2K\r`);let B=q[E];if(E===z)process.stdout.write(` ${G.blue(G.bold(B.cmd))} ${G.gray(B.desc)}`);else process.stdout.write(` ${G.gray(B.cmd)} ${G.gray(G.dim(B.desc))}`)}Y=q.length,process.stdout.write(`\x1B[${Y}A\r\x1B[${A+V.length}C`)},U="",N=(q)=>{let A=typeof q==="string"?q:q.toString("utf8");for(let E=0;E<A.length;E++){let B=A[E],R=B.charCodeAt(0);if(U.length>0||R===27){if(U+=B,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)z=(z-1+O.length)%O.length,_();else if(U==="\x1B[B"&&O.length>0)z=(z+1)%O.length,_();U="";continue}continue}if(R===3)W(),process.stdin.setRawMode(J),process.stdout.write(`
18
+ `),process.exit(0);if(R===4){W(),process.stdin.setRawMode(J),D(),K(Error("EOF"));return}if(R===13||R===10){let O=X();if(O.length>0&&V!==O[z].cmd){W();let x=O[z].cmd;process.stdout.write("\b \b".repeat(V.length)),V=x,process.stdout.write(V)}W(),process.stdin.setRawMode(J),process.stdout.write(`
19
+ `),D(),Q(V);return}if(R===127||R===8){if(V.length>0)W(),V=V.slice(0,-1),process.stdout.write("\b \b"),z=0,_();continue}if(R===9){let O=X();if(O.length>0){W();let x=O[z].cmd,e=x.slice(V.length);V=x,process.stdout.write(e),_()}continue}if(R<32)continue;W(),V+=B,process.stdout.write(B),z=0,_()}},D=()=>{process.stdin.removeListener("data",N)};process.stdin.on("data",N)})}async function I0(){let Z=[],$=!0;while(!0){let Q=$?`
20
+ ${G.gray(F.tl+F.line(3))} ${H.prompt} `:` ${G.gray(F.v)} `,K=await L(Q,$);if($=!1,K.endsWith("\\"))Z.push(K.slice(0,-1));else{Z.push(K);break}}return Z.join(`
21
21
  `)}async function b(Z,$){console.log(`
22
- ${G.bold(Z)}`),$.forEach((Q,K)=>{let V=G.blue(` ${K+1}.`),Y=Q.desc?G.gray(` (${Q.desc})`):"";console.log(`${V} ${Q.label}${Y}`)}),console.log(` ${G.gray(" 0. Cancel")}`);while(!0){let K=(await C(`
23
- ${G.gray("choose")} ${G.blue("❯")} `)).trim().toLowerCase();if(K==="0"||K==="q"||K==="cancel"||K==="exit"||K==="")return-1;let V=parseInt(K);if(V>=1&&V<=$.length)return V-1;console.log(` ${A.warn} enter 1-${$.length} or 0 to cancel`)}}function w(Z,$){console.log(`
24
- ${A.tool} ${G.yellow(Z)} ${G.gray($)}`)}function P(Z){console.error(` ${A.err} ${G.pink(Z)}`)}var M0=(Z)=>`\x1B[${Z}m`,o=(Z,$)=>(Q)=>`${M0(Z)}${Q}${M0($)}`,M=(Z)=>($)=>`\x1B[38;5;${Z}m${$}\x1B[39m`,G,A,j,X1;var t=L(()=>{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:["⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"]};j={h:"─",v:"│",tl:"╭",tr:"╮",bl:"╰",br:"╯",line:(Z)=>"─".repeat(Z)};X1=[{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 u,writeFileSync as Y0,existsSync as m,readdirSync as p,statSync as C0,mkdirSync as T0,unlinkSync as J0}from"fs";import{resolve as z1,relative as h,join as T,dirname as J1}from"path";import{spawn as x0}from"child_process";class b0{snapshotDir;sessionWrites=[];constructor(Z){let $=Z||process.cwd();if(this.snapshotDir=T($,".tenicli","snapshots"),!m(this.snapshotDir))T0(this.snapshotDir,{recursive:!0});this.loadFromDisk()}loadFromDisk(){try{let Z=p(this.snapshotDir).filter(($)=>$.endsWith(".json")).sort();for(let $ of Z)try{let Q=u(T(this.snapshotDir,$),"utf8"),K=JSON.parse(Q);this.sessionWrites.push(K)}catch{}}catch{}}saveEntry(Z){let Q=`${Date.now()}.json`,K=T(this.snapshotDir,Q);return Y0(K,JSON.stringify(Z),"utf8"),Q}removeEntry(Z){try{let $=p(this.snapshotDir).filter((Q)=>Q.endsWith(".json")).sort();for(let Q=$.length-1;Q>=0;Q--)try{let K=u(T(this.snapshotDir,$[Q]),"utf8"),V=JSON.parse(K);if(V.path===Z.path&&V.time===Z.time){J0(T(this.snapshotDir,$[Q]));return}}catch{}}catch{}}recordWrite(Z,$){let Q=m(Z)?u(Z,"utf8"):null,K={path:Z,backup:Q,newLines:$.split(`
25
- `).length,time:new Date().toISOString(),label:Q===null?`create ${h(process.cwd(),Z)}`:`modify ${h(process.cwd(),Z)}`};this.sessionWrites.push(K),this.saveEntry(K)}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{J0(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=p(this.snapshotDir).filter(($)=>$.endsWith(".json"));for(let $ of Z)try{J0(T(this.snapshotDir,$))}catch{}}catch{}this.sessionWrites=[]}}async function k0(Z,$,Q){try{let K;switch(Z){case"read_file":K=W1($,Q),w("read_file",G.dim(h(Q,S($.path,Q))));break;case"write_file":K=N1($,Q),w("write_file",G.dim(h(Q,S($.path,Q))));break;case"list_dir":K=_1($,Q),w("list_dir",G.dim($.path||"."));break;case"search_files":K=await U1($,Q),w("search_files",G.dim(`"${$.pattern}"`));break;case"exec_command":K=await q1($,Q),w("exec_command",G.dim(L0($.command,60)));break;default:K=`Unknown tool: ${Z}`}return{type:"tool_result",content:L0(K,Y1)}}catch(K){return{type:"tool_result",content:`Error: ${K.message}`,is_error:!0}}}function S(Z,$){return z1($,Z)}function W1(Z,$){let Q=S(Z.path,$);if(!m(Q))return`File not found: ${Z.path}`;let K=u(Q,"utf8"),V=K.split(`
26
- `);if(Z.start_line||Z.end_line){let Y=Math.max(1,Z.start_line||1)-1,X=Math.min(V.length,Z.end_line||V.length);return V.slice(Y,X).map((z,J)=>`${Y+J+1}: ${z}`).join(`
27
- `)}if(V.length>50)return V.map((Y,X)=>`${X+1}: ${Y}`).join(`
28
- `);return K}function N1(Z,$){let Q=S(Z.path,$),K=J1(Q);if(!m(K))T0(K,{recursive:!0});return F.recordWrite(Q,Z.content),Y0(Q,Z.content,"utf8"),`Written ${Z.content.split(`
29
- `).length} lines to ${Z.path}`}function _1(Z,$){let Q=S(Z.path||".",$);if(!m(Q))return`Directory not found: ${Z.path||"."}`;let K=Z.depth||1,V=[];function Y(X,z){if(z>K)return;try{let J=p(X);for(let W of J){if(W.startsWith(".")||W==="node_modules")continue;let N=T(X,W),_=h(Q,N);try{let q=C0(N),H=" ".repeat(z);if(q.isDirectory())V.push(`${H}${_}/`),Y(N,z+1);else{let U=q.size>1024?`${(q.size/1024).toFixed(1)}KB`:`${q.size}B`;V.push(`${H}${_} (${U})`)}}catch{}}}catch{}}return Y(Q,0),V.length>0?V.join(`
30
- `):"(empty directory)"}async function U1(Z,$){let Q=S(Z.path||".",$),K=Z.pattern;try{let X=["-n","--max-count=50","--no-heading"];if(Z.include)X.push("--glob",Z.include);return X.push(K,Q),await new Promise((J,W)=>{let N=x0("rg",X,{shell:!0}),_="";N.stdout.on("data",(q)=>_+=q.toString()),N.on("close",(q)=>{if(q===0||q===1)J(_.trim()||"No matches found.");else W(Error("rg failed"))}),N.on("error",W)})}catch{}let V=[];function Y(X){try{for(let z of p(X)){if(z.startsWith(".")||z==="node_modules")continue;let J=T(X,z);try{let W=C0(J);if(W.isDirectory()){Y(J);continue}if(W.size>500000)continue;if(Z.include&&!A1(z,Z.include))continue;let _=u(J,"utf8").split(`
31
- `);for(let q=0;q<_.length;q++)if(_[q].includes(K)){if(V.push(`${h($,J)}:${q+1}: ${_[q].trim()}`),V.length>=50)return}}catch{}}}catch{}}return Y(Q),V.length>0?V.join(`
32
- `):"No matches found."}async function q1(Z,$){let Q=S(Z.cwd||".",$),K=process.platform==="win32",V=K?"cmd":"sh",Y=K?"/c":"-c";return new Promise((X)=>{let z=x0(V,[Y,Z.command],{cwd:Q,env:{...process.env,PAGER:"cat"}}),J="",W="";z.stdout.on("data",(_)=>J+=_.toString()),z.stderr.on("data",(_)=>W+=_.toString());let N=setTimeout(()=>z.kill(),30000);z.on("close",(_)=>{clearTimeout(N);let q="";if(J.trim())q+=J.trim();if(W.trim())q+=(q?`
33
- `:"")+`[stderr] ${W.trim()}`;q+=`
34
- [exit code: ${_}]`,X(q)}),z.on("error",(_)=>{clearTimeout(N),X(`[error] Failed to start process: ${_.message}`)})})}function L0(Z,$){if(Z.length<=$)return Z;return Z.slice(0,$)+`
35
- ... (truncated, ${Z.length-$} chars omitted)`}function A1(Z,$){if($.startsWith("*."))return Z.endsWith($.slice(1));return Z.includes($.replace(/\*/g,""))}var F,S0,Y1=30000;var W0=L(()=>{t();F=new b0,S0=[{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"]}}]});class y{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+`
36
- `});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((V)=>V.type==="tool_use"),K=[];for(let V of Q){if(!this.autoMode&&(V.name==="write_file"||V.name==="exec_command")){let X=V.name==="write_file"?V.input?.path:V.input?.command?.slice(0,80),z="y";if(this.onConfirm)z=await this.onConfirm(V.id,V.name,X||"");else this.log(`
37
- ${A.warn} ${G.yellow(V.name)} ${G.gray(X||"")}`),z=(await C(` ${G.gray("allow?")} ${G.blue("[y/n/auto]")} `)).trim().toLowerCase();if(z==="auto")this.autoMode=!0;else if(z!=="y"&&z!=="yes"&&z!==""){K.push({type:"tool_result",tool_use_id:V.id,content:"User denied this action.",is_error:!0});continue}}this.emit({type:"tool",name:V.name,detail:JSON.stringify(V.input||{}).slice(0,200)});let Y=await k0(V.name,V.input,this.cfg.cwd);this.emit({type:"tool_result",name:V.name,content:(Y.content||"").slice(0,500),is_error:!!Y.is_error}),K.push({type:"tool_result",tool_use_id:V.id,content:Y.content,is_error:Y.is_error})}this.messages.push({role:"assistant",content:Z.content}),this.messages.push({role:"user",content:K});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(`
38
- ${G.gray(`tokens: ${this.tokens.input} ${this.tokens.output}↓`)}`)}async streamResponse(){let Z=!this.onOutput,$=Z?new r("Thinking").start():null,Q=[],K="",V="",Y="",X="",z="end_turn",J=!1;try{let W=X0(this.cfg.provider,this.messages,this.cfg.systemPrompt,S0,this.cfg.maxTokens);for await(let N of W)switch(N.type){case"text":if(!J){if($?.stop(),J=!0,Z)process.stdout.write(`
39
- ${A.ai} `)}if(N.text)this.write(N.text);K+=N.text;break;case"tool_start":if(!J)$?.stop(),J=!0;if(K)Q.push({type:"text",text:K}),K="";V=N.id,Y=N.name,X="";break;case"tool_input":X+=N.partial;break;case"tool_end":if(V){let _={};try{_=JSON.parse(X)}catch{}Q.push({type:"tool_use",id:V,name:Y,input:_}),V="",X=""}break;case"usage":this.tokens.input+=N.input,this.tokens.output+=N.output;break;case"done":z=N.stopReason;break}}catch(W){if($?.stop(),Z)console.log();let N=W.message||String(W);if(this.emit({type:"error",message:N}),Z)P(N);return{content:[],stopReason:"error"}}if(K){if(Q.push({type:"text",text:K}),this.emit({type:"text_done"}),Z)process.stdout.write(`
40
- `)}if(!J)$?.stop();return{content:Q,stopReason:z}}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 X of this.messages)if(typeof X.content==="string")$+=`${X.role}: ${X.content.slice(0,500)}
41
- `;else{let z=X.content.filter((W)=>W.type==="text").map((W)=>W.text?.slice(0,300)).join(" ");if(z)$+=`${X.role}: ${z}
42
- `;let J=X.content.filter((W)=>W.type==="tool_use").map((W)=>`[tool: ${W.name}]`).join(", ");if(J)$+=` tools: ${J}
22
+ ${G.bold(Z)}`),$.forEach((Q,K)=>{let V=G.blue(` ${K+1}.`),Y=Q.desc?G.gray(` (${Q.desc})`):"";console.log(`${V} ${Q.label}${Y}`)}),console.log(` ${G.gray(" 0. Cancel")}`);while(!0){let K=(await L(`
23
+ ${G.gray("choose")} ${G.blue("❯")} `)).trim().toLowerCase();if(K==="0"||K==="q"||K==="cancel"||K==="exit"||K==="")return-1;let V=parseInt(K);if(V>=1&&V<=$.length)return V-1;console.log(` ${H.warn} enter 1-${$.length} or 0 to cancel`)}}function w(Z,$){console.log(`
24
+ ${H.tool} ${G.yellow(Z)} ${G.gray($)}`)}function P(Z){console.error(` ${H.err} ${G.pink(Z)}`)}var j0=(Z)=>`\x1B[${Z}m`,o=(Z,$)=>(Q)=>`${j0(Z)}${Q}${j0($)}`,j=(Z)=>($)=>`\x1B[38;5;${Z}m${$}\x1B[39m`,G,H,F,z1;var t=C(()=>{G={bold:o("1","22"),dim:o("2","22"),italic:o("3","23"),under:o("4","24"),blue:j(111),purple:j(141),green:j(149),yellow:j(179),pink:j(210),cyan:j(117),gray:j(60),text:j(146),orange:j(215)},H={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)};z1=[{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 y,writeFileSync as Y0,existsSync as v,readdirSync as m,statSync as L0,mkdirSync as T0,unlinkSync as X0}from"fs";import{resolve as J1,relative as S,join as T,dirname as X1}from"path";import{spawn as x0}from"child_process";class b0{snapshotDir;sessionWrites=[];constructor(Z){let $=Z||process.cwd();if(this.snapshotDir=T($,".tenicli","snapshots"),!v(this.snapshotDir))T0(this.snapshotDir,{recursive:!0});this.loadFromDisk()}loadFromDisk(){try{let Z=m(this.snapshotDir).filter(($)=>$.endsWith(".json")).sort();for(let $ of Z)try{let Q=y(T(this.snapshotDir,$),"utf8"),K=JSON.parse(Q);this.sessionWrites.push(K)}catch{}}catch{}}saveEntry(Z){let Q=`${Date.now()}.json`,K=T(this.snapshotDir,Q);return Y0(K,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 K=y(T(this.snapshotDir,$[Q]),"utf8"),V=JSON.parse(K);if(V.path===Z.path&&V.time===Z.time){X0(T(this.snapshotDir,$[Q]));return}}catch{}}catch{}}recordWrite(Z,$){let Q=v(Z)?y(Z,"utf8"):null,K={path:Z,backup:Q,newLines:$.split(`
25
+ `).length,time:new Date().toISOString(),label:Q===null?`create ${S(process.cwd(),Z)}`:`modify ${S(process.cwd(),Z)}`};this.sessionWrites.push(K),this.saveEntry(K)}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=[]}}async function k0(Z,$,Q){try{let K;switch(Z){case"read_file":K=W1($,Q),w("read_file",G.dim(S(Q,k($.path,Q))));break;case"write_file":K=q1($,Q),w("write_file",G.dim(S(Q,k($.path,Q))));break;case"list_dir":K=N1($,Q),w("list_dir",G.dim($.path||"."));break;case"search_files":K=await A1($,Q),w("search_files",G.dim(`"${$.pattern}"`));break;case"exec_command":K=await H1($,Q),w("exec_command",G.dim(C0($.command,60)));break;default:K=`Unknown tool: ${Z}`}return{type:"tool_result",content:C0(K,Y1)}}catch(K){return{type:"tool_result",content:`Error: ${K.message}`,is_error:!0}}}function k(Z,$){return J1($,Z)}function W1(Z,$){let Q=k(Z.path,$);if(!v(Q))return`File not found: ${Z.path}`;let K=y(Q,"utf8"),V=K.split(`
26
+ `);if(Z.start_line||Z.end_line){let Y=Math.max(1,Z.start_line||1)-1,z=Math.min(V.length,Z.end_line||V.length);return V.slice(Y,z).map((J,X)=>`${Y+X+1}: ${J}`).join(`
27
+ `)}if(V.length>50)return V.map((Y,z)=>`${z+1}: ${Y}`).join(`
28
+ `);return K}function _1(Z,$){let Q=Z.length,K=$.length;if(Q*K>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 V=Array.from({length:Q+1},()=>Array(K+1).fill(0));for(let X=1;X<=Q;X++)for(let W=1;W<=K;W++)V[X][W]=Z[X-1]===$[W-1]?V[X-1][W-1]+1:Math.max(V[X-1][W],V[X][W-1]);let Y=[],z=Q,J=K;while(z>0||J>0)if(z>0&&J>0&&Z[z-1]===$[J-1])Y.push({type:"same",line:Z[z-1]}),z--,J--;else if(J>0&&(z===0||V[z][J-1]>=V[z-1][J]))Y.push({type:"add",line:$[J-1]}),J--;else Y.push({type:"del",line:Z[z-1]}),z--;return Y.reverse()}function U1(Z,$,Q,K){let V=S(K,Z),Y=` ${G.dim("──")} ${G.cyan(V)} ${G.dim("─".repeat(Math.max(2,50-V.length)))}`;if(console.log(Y),$===null){let A=Q.split(`
29
+ `).length;console.log(` ${G.green(`+ (new file, ${A} lines)`)}`),console.log();return}let z=$.split(`
30
+ `),J=Q.split(`
31
+ `),X=_1(z,J),W=3,_=new Set;if(X.forEach((A,E)=>{if(A.type!=="same")_.add(E)}),_.size===0){console.log(` ${G.gray("(no changes)")}`),console.log();return}let U=new Set;for(let A of _)for(let E=Math.max(0,A-W);E<=Math.min(X.length-1,A+W);E++)U.add(E);let N=-1,D=0,q=0;for(let A=0;A<X.length;A++){if(!U.has(A))continue;if(N!==-1&&A-N>1)console.log(G.gray(" ..."));let E=X[A];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}`)}`);N=A}console.log(` ${G.green(`+${D}`)} ${G.pink(`-${q}`)}`),console.log()}function q1(Z,$){let Q=k(Z.path,$),K=X1(Q);if(!v(K))T0(K,{recursive:!0});let V=v(Q)?y(Q,"utf8"):null;return M.recordWrite(Q,Z.content),Y0(Q,Z.content,"utf8"),U1(Q,V,Z.content,$),`Written ${Z.content.split(`
32
+ `).length} lines to ${Z.path}`}function N1(Z,$){let Q=k(Z.path||".",$);if(!v(Q))return`Directory not found: ${Z.path||"."}`;let K=Z.depth||1,V=[];function Y(z,J){if(J>K)return;try{let X=m(z);for(let W of X){if(W.startsWith(".")||W==="node_modules")continue;let _=T(z,W),U=S(Q,_);try{let N=L0(_),D=" ".repeat(J);if(N.isDirectory())V.push(`${D}${U}/`),Y(_,J+1);else{let q=N.size>1024?`${(N.size/1024).toFixed(1)}KB`:`${N.size}B`;V.push(`${D}${U} (${q})`)}}catch{}}}catch{}}return Y(Q,0),V.length>0?V.join(`
33
+ `):"(empty directory)"}async function A1(Z,$){let Q=k(Z.path||".",$),K=Z.pattern;try{let z=["-n","--max-count=50","--no-heading"];if(Z.include)z.push("--glob",Z.include);return z.push(K,Q),await new Promise((X,W)=>{let _=x0("rg",z,{shell:!0}),U="";_.stdout.on("data",(N)=>U+=N.toString()),_.on("close",(N)=>{if(N===0||N===1)X(U.trim()||"No matches found.");else W(Error("rg failed"))}),_.on("error",W)})}catch{}let V=[];function Y(z){try{for(let J of m(z)){if(J.startsWith(".")||J==="node_modules")continue;let X=T(z,J);try{let W=L0(X);if(W.isDirectory()){Y(X);continue}if(W.size>500000)continue;if(Z.include&&!E1(J,Z.include))continue;let U=y(X,"utf8").split(`
34
+ `);for(let N=0;N<U.length;N++)if(U[N].includes(K)){if(V.push(`${S($,X)}:${N+1}: ${U[N].trim()}`),V.length>=50)return}}catch{}}}catch{}}return Y(Q),V.length>0?V.join(`
35
+ `):"No matches found."}async function H1(Z,$){let Q=k(Z.cwd||".",$),K=process.platform==="win32",V=K?"cmd":"sh",Y=K?"/c":"-c";return new Promise((z)=>{let J=x0(V,[Y,Z.command],{cwd:Q,env:{...process.env,PAGER:"cat"}}),X="",W="";J.stdout.on("data",(U)=>X+=U.toString()),J.stderr.on("data",(U)=>W+=U.toString());let _=setTimeout(()=>J.kill(),30000);J.on("close",(U)=>{clearTimeout(_);let N="";if(X.trim())N+=X.trim();if(W.trim())N+=(N?`
36
+ `:"")+`[stderr] ${W.trim()}`;N+=`
37
+ [exit code: ${U}]`,z(N)}),J.on("error",(U)=>{clearTimeout(_),z(`[error] Failed to start process: ${U.message}`)})})}function C0(Z,$){if(Z.length<=$)return Z;return Z.slice(0,$)+`
38
+ ... (truncated, ${Z.length-$} chars omitted)`}function E1(Z,$){if($.startsWith("*."))return Z.endsWith($.slice(1));return Z.includes($.replace(/\*/g,""))}var M,S0,Y1=30000;var W0=C(()=>{t();M=new b0,S0=[{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"]}}]});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((V)=>V.type==="tool_use"),K=[];for(let V of Q){if(!this.autoMode&&(V.name==="write_file"||V.name==="exec_command")){let z=V.name==="write_file"?V.input?.path:V.input?.command?.slice(0,80),J="y";if(this.onConfirm)J=await this.onConfirm(V.id,V.name,z||"");else this.log(`
40
+ ${H.warn} ${G.yellow(V.name)} ${G.gray(z||"")}`),J=(await L(` ${G.gray("allow?")} ${G.blue("[y/n/auto]")} `)).trim().toLowerCase();if(J==="auto")this.autoMode=!0;else if(J!=="y"&&J!=="yes"&&J!==""){K.push({type:"tool_result",tool_use_id:V.id,content:"User denied this action.",is_error:!0});continue}}this.emit({type:"tool",name:V.name,detail:JSON.stringify(V.input||{}).slice(0,200)});let Y=await k0(V.name,V.input,this.cfg.cwd);this.emit({type:"tool_result",name:V.name,content:(Y.content||"").slice(0,500),is_error:!!Y.is_error}),K.push({type:"tool_result",tool_use_id:V.id,content:Y.content,is_error:Y.is_error})}this.messages.push({role:"assistant",content:Z.content}),this.messages.push({role:"user",content:K});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=[],K="",V="",Y="",z="",J="end_turn",X=!1;try{let W=z0(this.cfg.provider,this.messages,this.cfg.systemPrompt,S0,this.cfg.maxTokens);for await(let _ of W)switch(_.type){case"text":if(!X){if($?.stop(),X=!0,Z)process.stdout.write(`
42
+ ${H.ai} `)}if(_.text)this.write(_.text);K+=_.text;break;case"tool_start":if(!X)$?.stop(),X=!0;if(K)Q.push({type:"text",text:K}),K="";V=_.id,Y=_.name,z="";break;case"tool_input":z+=_.partial;break;case"tool_end":if(V){let U={};try{U=JSON.parse(z)}catch{}Q.push({type:"tool_use",id:V,name:Y,input:U}),V="",z=""}break;case"usage":this.tokens.input+=_.input,this.tokens.output+=_.output;break;case"done":J=_.stopReason;break}}catch(W){if($?.stop(),Z)console.log();let _=W.message||String(W);if(this.emit({type:"error",message:_}),Z)P(_);return{content:[],stopReason:"error"}}if(K){if(Q.push({type:"text",text:K}),this.emit({type:"text_done"}),Z)process.stdout.write(`
43
+ `)}if(!X)$?.stop();return{content:Q,stopReason:J}}async compact(){if(this.messages.length<4){this.log(` ${H.warn} Not enough messages to compact.`);return}let Z=!this.onOutput?new r("Compacting").start():null;try{let $="";for(let z of this.messages)if(typeof z.content==="string")$+=`${z.role}: ${z.content.slice(0,500)}
44
+ `;else{let J=z.content.filter((W)=>W.type==="text").map((W)=>W.text?.slice(0,300)).join(" ");if(J)$+=`${z.role}: ${J}
45
+ `;let X=z.content.filter((W)=>W.type==="tool_use").map((W)=>`[tool: ${W.name}]`).join(", ");if(X)$+=` tools: ${X}
43
46
  `}let Q=this.messages.length,K=`Summarize this conversation concisely. Keep key decisions, file changes, and current state. Be brief:
44
47
 
45
- ${$.slice(0,6000)}`;this.messages=[{role:"user",content:K},{role:"assistant",content:`[Conversation compacted from ${Q} messages. Summary of what happened:]`}];let V=X0(this.cfg.provider,[{role:"user",content:K}],"You are a conversation summarizer. Create a brief summary preserving key facts, decisions, and file changes.",[],this.cfg.maxTokens),Y="";for await(let X of V){if(X.type==="text"&&X.text)Y+=X.text;if(X.type==="usage")this.tokens.input+=X.input,this.tokens.output+=X.output}this.messages=[{role:"user",content:`[Previous conversation summary]
46
- ${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)P(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 N0=L(()=>{z0();W0();t()});var l;var U0=L(()=>{l={name:"tenicli",version:"0.3.1",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 m0={};R0(m0,{renderQR:()=>O1,getLocalIPs:()=>j1});function O1(Z){let $=[],Q=Math.max(Z.length+4,30),K="██",V=" ";for(let X=0;X<7;X++){let z="";for(let J=0;J<7;J++)z+=q0.FINDER[X][J]?"██":" ";z+=" ";for(let J=0;J<Q-15;J++)z+=X===6&&J%2===0?"██":X===6?" ":" ";z+=" ";for(let J=0;J<7;J++)z+=q0.FINDER[X][J]?"██":" ";$.push(z)}$.push(" ".repeat(Q/2+1));let Y=5;for(let X=0;X<Y;X++){let z="";for(let J=0;J<Q+1;J++){if(J===6){z+=X%2===0?"██":" ";continue}z+=(J+X*3+J*X)%3===0?"██":" "}$.push(z)}$.push(" ".repeat(Q/2+1));for(let X=0;X<7;X++){let z="";for(let J=0;J<7;J++)z+=q0.FINDER[X][J]?"██":" ";z+=" ";for(let J=0;J<Q-14;J++)z+=(J+X*5)%3===0?"██":" ";$.push(z)}return $.map((X)=>" "+X).join(`
47
- `)}function j1(){try{let{networkInterfaces:Z}=Z0("os"),$=Z(),Q=[];for(let K of Object.keys($))for(let V of $[K])if(V.family==="IPv4"&&!V.internal)Q.push(V.address);return Q}catch{return[]}}var q0;var d0=L(()=>{q0={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={};R0(E0,{startServer:()=>b1,getActiveServers:()=>P1});import{createServer as F1}from"http";import{createHash as M1}from"crypto";function P1(){return A0}function I1(Z){if(Z.length<2)return null;let $=Z[0]&15,Q=(Z[1]&128)!==0,K=Z[1]&127,V=2;if(K===126){if(Z.length<4)return null;K=Z.readUInt16BE(2),V=4}else if(K===127){if(Z.length<10)return null;K=Number(Z.readBigUInt64BE(2)),V=10}let X=V+(Q?4:0)+K;if(Z.length<X)return null;if(Q){let z=Z.slice(V,V+4),J=Buffer.alloc(K);for(let W=0;W<K;W++)J[W]=Z[V+4+W]^z[W%4];return{opcode:$,payload:J,totalSize:X}}return{opcode:$,payload:Z.slice(V,V+K),totalSize:X}}function L1(Z){let $=Buffer.from(Z,"utf8"),Q=$.length,K;if(Q<126)K=Buffer.alloc(2),K[0]=129,K[1]=Q;else if(Q<65536)K=Buffer.alloc(4),K[0]=129,K[1]=126,K.writeUInt16BE(Q,2);else K=Buffer.alloc(10),K[0]=129,K[1]=127,K.writeBigUInt64BE(BigInt(Q),2);return Buffer.concat([K,$])}function C1(Z){let $=Buffer.alloc(2);$[0]=137,$[1]=0,Z.write($)}function T1(Z,$){return`<!DOCTYPE html>
48
+ ${$.slice(0,6000)}`;this.messages=[{role:"user",content:K},{role:"assistant",content:`[Conversation compacted from ${Q} messages. Summary of what happened:]`}];let V=z0(this.cfg.provider,[{role:"user",content:K}],"You are a conversation summarizer. Create a brief summary preserving key facts, decisions, and file changes.",[],this.cfg.maxTokens),Y="";for await(let z of V){if(z.type==="text"&&z.text)Y+=z.text;if(z.type==="usage")this.tokens.input+=z.input,this.tokens.output+=z.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(` ${H.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)P(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(()=>{J0();W0();t()});var l;var q0=C(()=>{l={name:"tenicli",version:"0.3.2",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 m0={};R0(m0,{renderQR:()=>M1,getLocalIPs:()=>j1});function M1(Z){let $=[],Q=Math.max(Z.length+4,30),K="██",V=" ";for(let z=0;z<7;z++){let J="";for(let X=0;X<7;X++)J+=N0.FINDER[z][X]?"██":" ";J+=" ";for(let X=0;X<Q-15;X++)J+=z===6&&X%2===0?"██":z===6?" ":" ";J+=" ";for(let X=0;X<7;X++)J+=N0.FINDER[z][X]?"██":" ";$.push(J)}$.push(" ".repeat(Q/2+1));let Y=5;for(let z=0;z<Y;z++){let J="";for(let X=0;X<Q+1;X++){if(X===6){J+=z%2===0?"██":" ";continue}J+=(X+z*3+X*z)%3===0?"██":" "}$.push(J)}$.push(" ".repeat(Q/2+1));for(let z=0;z<7;z++){let J="";for(let X=0;X<7;X++)J+=N0.FINDER[z][X]?"██":" ";J+=" ";for(let X=0;X<Q-14;X++)J+=(X+z*5)%3===0?"██":" ";$.push(J)}return $.map((z)=>" "+z).join(`
50
+ `)}function j1(){try{let{networkInterfaces:Z}=Z0("os"),$=Z(),Q=[];for(let K of Object.keys($))for(let V of $[K])if(V.family==="IPv4"&&!V.internal)Q.push(V.address);return Q}catch{return[]}}var N0;var d0=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 H0={};R0(H0,{startServer:()=>k1,getActiveServers:()=>C1});import{createServer as P1}from"http";import{createHash as I1}from"crypto";function C1(){return A0}function L1(Z){if(Z.length<2)return null;let $=Z[0]&15,Q=(Z[1]&128)!==0,K=Z[1]&127,V=2;if(K===126){if(Z.length<4)return null;K=Z.readUInt16BE(2),V=4}else if(K===127){if(Z.length<10)return null;K=Number(Z.readBigUInt64BE(2)),V=10}let z=V+(Q?4:0)+K;if(Z.length<z)return null;if(Q){let J=Z.slice(V,V+4),X=Buffer.alloc(K);for(let W=0;W<K;W++)X[W]=Z[V+4+W]^J[W%4];return{opcode:$,payload:X,totalSize:z}}return{opcode:$,payload:Z.slice(V,V+K),totalSize:z}}function T1(Z){let $=Buffer.from(Z,"utf8"),Q=$.length,K;if(Q<126)K=Buffer.alloc(2),K[0]=129,K[1]=Q;else if(Q<65536)K=Buffer.alloc(4),K[0]=129,K[1]=126,K.writeUInt16BE(Q,2);else K=Buffer.alloc(10),K[0]=129,K[1]=127,K.writeBigUInt64BE(BigInt(Q),2);return Buffer.concat([K,$])}function b1(Z){let $=Buffer.alloc(2);$[0]=137,$[1]=0,Z.write($)}function S1(Z,$){return`<!DOCTYPE html>
48
51
  <html lang="en">
49
52
  <head>
50
53
  <meta charset="utf-8">
@@ -289,14 +292,14 @@ ${Y}`},{role:"assistant",content:"Understood. I have the context from our previo
289
292
  })();
290
293
  </script>
291
294
  </body>
292
- </html>`}function b1(Z,$){let Q=c(),K=new Map,V=new Map,Y=F1((z,J)=>{if(new URL(z.url||"/",`http://${z.headers.host||"localhost"}`).pathname==="/health"){J.writeHead(200,{"content-type":"application/json","access-control-allow-origin":"*"}),J.end(JSON.stringify({status:"ok",sessions:K.size,version:l.version}));return}J.writeHead(200,{"content-type":"text/html; charset=utf-8","cache-control":"no-cache"}),J.end(T1(l.version,$))});Y.on("upgrade",(z,J)=>{if(new URL(z.url||"/",`http://${z.headers.host||"localhost"}`).searchParams.get("token")!==$){J.write(`HTTP/1.1 401 Unauthorized\r
295
+ </html>`}function k1(Z,$){let Q=n(),K=new Map,V=new Map,Y=P1((J,X)=>{if(new URL(J.url||"/",`http://${J.headers.host||"localhost"}`).pathname==="/health"){X.writeHead(200,{"content-type":"application/json","access-control-allow-origin":"*"}),X.end(JSON.stringify({status:"ok",sessions:K.size,version:l.version}));return}X.writeHead(200,{"content-type":"text/html; charset=utf-8","cache-control":"no-cache"}),X.end(S1(l.version,$))});Y.on("upgrade",(J,X)=>{if(new URL(J.url||"/",`http://${J.headers.host||"localhost"}`).searchParams.get("token")!==$){X.write(`HTTP/1.1 401 Unauthorized\r
293
296
  \r
294
- `),J.destroy();return}let _=z.headers["sec-websocket-key"];if(!_){J.destroy();return}let q=M1("sha1").update(_+"258EAFA5-E914-47DA-95CA-5ABB5C0A2C15").digest("base64");J.write(`HTTP/1.1 101 Switching Protocols\r
297
+ `),X.destroy();return}let U=J.headers["sec-websocket-key"];if(!U){X.destroy();return}let N=I1("sha1").update(U+"258EAFA5-E914-47DA-95CA-5ABB5C0A2C15").digest("base64");X.write(`HTTP/1.1 101 Switching Protocols\r
295
298
  Upgrade: websocket\r
296
299
  Connection: Upgrade\r
297
- Sec-WebSocket-Accept: `+q+`\r
300
+ Sec-WebSocket-Accept: `+N+`\r
298
301
  \r
299
- `);let H=Buffer.alloc(0),U=(R)=>{try{J.write(L1(JSON.stringify(R)))}catch{}};J.on("data",(R)=>{H=Buffer.concat([H,R]);while(H.length>0){let E=I1(H);if(!E)break;if(H=H.slice(E.totalSize),E.opcode===8){J.end();return}if(E.opcode===9){let B=Buffer.alloc(2+E.payload.length);B[0]=138,B[1]=E.payload.length,E.payload.copy(B,2),J.write(B);continue}if(E.opcode===10)continue;try{let B=JSON.parse(E.payload.toString("utf8"));S1(B,U,K,V,Q)}catch{}}});let D=setInterval(()=>{try{C1(J)}catch{clearInterval(D)}},30000);J.on("close",()=>{clearInterval(D);for(let[R,E]of K)if(E.send===U)K.delete(R)}),J.on("error",()=>{try{J.destroy()}catch{}})});let X=()=>{Y.close(),A0.delete(Z)};return Y.listen(Z,"0.0.0.0",()=>{A0.set(Z,{password:$,close:X})}),{close:X}}function S1(Z,$,Q,K,V){switch(Z.type){case"new_session":{let Y={...V,provider:{...V.provider}},X=new y(Y);X.autoMode=!0,X.onOutput=(z)=>{$({...z,sessionId:Z.sessionId})},X.onConfirm=(z,J,W)=>{return new Promise((N)=>{$({type:"confirm",sessionId:Z.sessionId,id:z,tool:J,preview:W}),K.set(z,N),setTimeout(()=>{if(K.has(z))K.delete(z),N("y")},60000)})},Q.set(Z.sessionId,{id:Z.sessionId,chat:X,send:$,alive:!0});break}case"close_session":Q.delete(Z.sessionId);break;case"message":{let Y=Q.get(Z.sessionId);if(!Y)return;let X=Z.text?.trim();if(!X)return;if(X==="/clear"){Y.chat.clear(),$({type:"system",sessionId:Z.sessionId,text:"Conversation cleared"});return}if(X==="/compact"){Y.chat.compact();return}if(X==="/cost"){let z=Y.chat.stats;$({type:"tokens",sessionId:Z.sessionId,input:z.input,output:z.output,messages:Y.chat.messageCount});return}Y.chat.send(X).catch((z)=>{$({type:"error",sessionId:Z.sessionId,message:z.message})});break}case"confirm_response":{let Y=K.get(Z.id);if(Y)K.delete(Z.id),Y(Z.answer);break}}}var A0;var H0=L(()=>{N0();K0();U0();A0=new Map});K0();N0();z0();W0();t();import{writeFileSync as k1,existsSync as x1}from"fs";import{join as w1,relative as I}from"path";import{randomBytes as l0}from"crypto";import{existsSync as h0,readFileSync as y0,writeFileSync as v0,mkdirSync as E1,readdirSync as H1,unlinkSync as g0}from"fs";import{join as v}from"path";var w0=20;function d(){let Z=process.env.HOME||process.env.USERPROFILE||"",$=v(Z,".tenicli","history");if(!h0($))E1($,{recursive:!0});return $}function D1(){return Date.now().toString(36)+Math.random().toString(36).slice(2,6)}function f0(Z){let $=v(d(),`${Z.id}.json`);v0($,JSON.stringify(Z,null,0),"utf8"),B1()}function _0(){let Z=d();try{return H1(Z).filter(($)=>$.endsWith(".json")).map(($)=>{try{return JSON.parse(y0(v(Z,$),"utf8"))}catch{return null}}).filter(($)=>$!==null).sort(($,Q)=>Q.updatedAt.localeCompare($.updatedAt))}catch{return[]}}function B1(){let Z=_0();if(Z.length<=w0)return;let $=d();for(let Q of Z.slice(w0))try{g0(v($,`${Q.id}.json`))}catch{}}function s(Z){let $=new Date().toISOString();return{id:D1(),title:"New conversation",model:Z,createdAt:$,updatedAt:$,messages:[],tokens:{input:0,output:0}}}function u0(Z){let $=v(d(),"__resume__.json");return v0($,JSON.stringify(Z,null,0),"utf8"),$}function p0(){let Z=v(d(),"__resume__.json");try{if(h0(Z)){let $=JSON.parse(y0(Z,"utf8"));return g0(Z),$}}catch{}return null}U0();var D0=l.version;function h1(Z){let $={command:"chat",prompt:"",print:!1,json:!1,yes:!1,quiet:!1},Q=0;if(Z[0]&&!Z[0].startsWith("-")){let K=Z[0].toLowerCase();if(["run","diff","undo","log","chat","remote","serve"].includes(K))$.command=K,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${D0}`),process.exit(0);case"-h":case"--help":y1(),process.exit(0);default:if(!Z[Q].startsWith("-"))$.prompt=Z.slice(Q).join(" "),Q=Z.length}Q++}return $}function y1(){console.log(`
302
+ `);let D=Buffer.alloc(0),q=(E)=>{try{X.write(T1(JSON.stringify(E)))}catch{}};X.on("data",(E)=>{D=Buffer.concat([D,E]);while(D.length>0){let B=L1(D);if(!B)break;if(D=D.slice(B.totalSize),B.opcode===8){X.end();return}if(B.opcode===9){let R=Buffer.alloc(2+B.payload.length);R[0]=138,R[1]=B.payload.length,B.payload.copy(R,2),X.write(R);continue}if(B.opcode===10)continue;try{let R=JSON.parse(B.payload.toString("utf8"));x1(R,q,K,V,Q)}catch{}}});let A=setInterval(()=>{try{b1(X)}catch{clearInterval(A)}},30000);X.on("close",()=>{clearInterval(A);for(let[E,B]of K)if(B.send===q)K.delete(E)}),X.on("error",()=>{try{X.destroy()}catch{}})});let z=()=>{Y.close(),A0.delete(Z)};return Y.listen(Z,"0.0.0.0",()=>{A0.set(Z,{password:$,close:z})}),{close:z}}function x1(Z,$,Q,K,V){switch(Z.type){case"new_session":{let Y={...V,provider:{...V.provider}},z=new g(Y);z.autoMode=!0,z.onOutput=(J)=>{$({...J,sessionId:Z.sessionId})},z.onConfirm=(J,X,W)=>{return new Promise((_)=>{$({type:"confirm",sessionId:Z.sessionId,id:J,tool:X,preview:W}),K.set(J,_),setTimeout(()=>{if(K.has(J))K.delete(J),_("y")},60000)})},Q.set(Z.sessionId,{id:Z.sessionId,chat:z,send:$,alive:!0});break}case"close_session":Q.delete(Z.sessionId);break;case"message":{let Y=Q.get(Z.sessionId);if(!Y)return;let z=Z.text?.trim();if(!z)return;if(z==="/clear"){Y.chat.clear(),$({type:"system",sessionId:Z.sessionId,text:"Conversation cleared"});return}if(z==="/compact"){Y.chat.compact();return}if(z==="/cost"){let J=Y.chat.stats;$({type:"tokens",sessionId:Z.sessionId,input:J.input,output:J.output,messages:Y.chat.messageCount});return}Y.chat.send(z).catch((J)=>{$({type:"error",sessionId:Z.sessionId,message:J.message})});break}case"confirm_response":{let Y=K.get(Z.id);if(Y)K.delete(Z.id),Y(Z.answer);break}}}var A0;var E0=C(()=>{_0();K0();q0();A0=new Map});K0();_0();J0();W0();t();import{writeFileSync as h1,existsSync as w1}from"fs";import{join as y1,relative as I}from"path";import{randomBytes as l0}from"crypto";import{existsSync as w0,readFileSync as y0,writeFileSync as v0,mkdirSync as D1,readdirSync as B1,unlinkSync as g0}from"fs";import{join as f}from"path";var h0=20;function d(){let Z=process.env.HOME||process.env.USERPROFILE||"",$=f(Z,".tenicli","history");if(!w0($))D1($,{recursive:!0});return $}function R1(){return Date.now().toString(36)+Math.random().toString(36).slice(2,6)}function f0(Z){let $=f(d(),`${Z.id}.json`);v0($,JSON.stringify(Z,null,0),"utf8"),O1()}function U0(){let Z=d();try{return B1(Z).filter(($)=>$.endsWith(".json")).map(($)=>{try{return JSON.parse(y0(f(Z,$),"utf8"))}catch{return null}}).filter(($)=>$!==null).sort(($,Q)=>Q.updatedAt.localeCompare($.updatedAt))}catch{return[]}}function O1(){let Z=U0();if(Z.length<=h0)return;let $=d();for(let Q of Z.slice(h0))try{g0(f($,`${Q.id}.json`))}catch{}}function s(Z){let $=new Date().toISOString();return{id:R1(),title:"New conversation",model:Z,createdAt:$,updatedAt:$,messages:[],tokens:{input:0,output:0}}}function u0(Z){let $=f(d(),"__resume__.json");return v0($,JSON.stringify(Z,null,0),"utf8"),$}function p0(){let Z=f(d(),"__resume__.json");try{if(w0(Z)){let $=JSON.parse(y0(Z,"utf8"));return g0(Z),$}}catch{}return null}q0();var D0=l.version;function v1(Z){let $={command:"chat",prompt:"",print:!1,json:!1,yes:!1,quiet:!1},Q=0;if(Z[0]&&!Z[0].startsWith("-")){let K=Z[0].toLowerCase();if(["run","diff","undo","log","chat","remote","serve"].includes(K))$.command=K,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${D0}`),process.exit(0);case"-h":case"--help":g1(),process.exit(0);default:if(!Z[Q].startsWith("-"))$.prompt=Z.slice(Q).join(" "),Q=Z.length}Q++}return $}function g1(){console.log(`
300
303
  ${G.bold(G.blue("TeniCLI"))} v${D0} — Lightweight AI Coding Agent
301
304
 
302
305
  ${G.bold("COMMANDS")}
@@ -335,10 +338,10 @@ ${G.bold("EXIT CODES")}
335
338
  1 API/runtime error
336
339
  2 User abort
337
340
  3 Tool execution failure
338
- `)}async function v1(Z,$){switch(Z.toLowerCase().split(" ")[0]){case"/exit":case"/quit":case"/q":console.log(`
341
+ `)}async function f1(Z,$){switch(Z.toLowerCase().split(" ")[0]){case"/exit":case"/quit":case"/q":console.log(`
339
342
  ${G.gray("Bye!")} \uD83D\uDC4B
340
- `),process.exit(0);case"/clear":return $.clear(),F.clear(),console.log(` ${A.ok} Conversation cleared`),!0;case"/compact":return await $.compact(),!0;case"/diff":{let Q=F.getChanges();if(Q.length===0)console.log(` ${G.gray("No files changed in this session.")}`);else{console.log(`
341
- ${G.bold("Files changed this session:")}`);for(let K of Q){let V=I($.cfg.cwd,K.path),Y=K.isNew?G.green("[NEW]"):G.yellow("[MOD]");console.log(` ${Y} ${G.cyan(V)} ${G.gray(`(${K.lines} lines)`)}`)}console.log(` ${G.gray(`total: ${Q.length} files`)}`)}return!0}case"/undo":{let Q=F.undo();if(!Q)console.log(` ${G.gray("Nothing to undo.")}`);else{let K=I($.cfg.cwd,Q.path);if(Q.restored)console.log(` ${A.ok} Restored: ${G.cyan(K)}`);else console.log(` ${A.ok} Deleted (was new): ${G.cyan(K)}`)}return!0}case"/init":{let Q=w1($.cfg.cwd,"TENICLI.md");if(x1(Q))console.log(` ${A.warn} TENICLI.md already exists.`);else k1(Q,f1,"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(),K=Q.customModels||[],V=[...g.map((z)=>({id:z.id,name:z.name,provider:z.provider,speed:z.speed,custom:!1})),...K.map((z)=>({id:z.id,name:z.id,provider:z.provider,speed:"custom",custom:!0}))],Y=V.map((z)=>({label:`${z.name} ${$.cfg.provider.model===z.id?G.green("●"):""}`,desc:`${z.provider} • ${z.speed}`}));Y.push({label:"Custom model...",desc:"type model ID"});let X=await b("Select model",Y);if(X===-1)return console.log(` ${G.gray("Cancelled")}`),!0;if(X<V.length){let z=V[X];$.cfg.provider.model=z.id,$.cfg.provider.type=z.provider;let J=z.provider==="openai"?process.env.OPENAI_API_KEY||Q.keys?.openai||"":process.env.ANTHROPIC_API_KEY||Q.keys?.anthropic||"";if(J)$.cfg.provider.apiKey=J;if(!Q.baseUrls?.[z.provider])$.cfg.provider.baseUrl=z.provider==="openai"?"https://api.openai.com":"https://api.anthropic.com";n({activeModel:z.id}),console.log(` ${A.ok} Model: ${G.blue(z.name)}`)}else{let z=await b("Provider for custom model",[{label:"Anthropic",desc:"Claude-compatible"},{label:"OpenAI",desc:"GPT-compatible"}]);if(z===-1)return console.log(` ${G.gray("Cancelled")}`),!0;let J=z===0?"anthropic":"openai",W=await C(` ${G.gray("model ID")} ${G.blue("❯")} `);if(!W.trim())return console.log(` ${G.gray("Cancelled")}`),!0;let N=W.trim();$.cfg.provider.model=N,$.cfg.provider.type=J;let _=K.filter((H)=>H.id!==N);_.push({id:N,provider:J}),n({activeModel:N,customModels:_});let q=J==="openai"?process.env.OPENAI_API_KEY||Q.keys?.openai||"":process.env.ANTHROPIC_API_KEY||Q.keys?.anthropic||"";if(q)$.cfg.provider.apiKey=q;console.log(` ${A.ok} Model: ${G.blue(N)} ${G.gray("(saved to list)")}`)}return!0}case"/auth":{let Q=await b("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 V=["anthropic","openai","anthropic"][Q],Y=await C(` ${G.gray("API Key")} ${G.blue("❯")} `);if(!Y.trim())return console.log(` ${A.warn} Cancelled`),!0;let X={[V]:Y.trim()},z={};if(Q===2){let J=await C(` ${G.gray("Base URL")} ${G.blue("❯")} `);if(J.trim())z[V]=J.trim()}if(n({keys:X,baseUrls:z}),$.cfg.provider.apiKey=Y.trim(),$.cfg.provider.type=V,z[V])$.cfg.provider.baseUrl=z[V];return console.log(` ${A.ok} ${V} key saved to ~/.tenicli/config.json`),!0}case"/help":return console.log(`
343
+ `),process.exit(0);case"/clear":return $.clear(),M.clear(),console.log(` ${H.ok} Conversation cleared`),!0;case"/compact":return await $.compact(),!0;case"/diff":{let Q=M.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 K of Q){let V=I($.cfg.cwd,K.path),Y=K.isNew?G.green("[NEW]"):G.yellow("[MOD]");console.log(` ${Y} ${G.cyan(V)} ${G.gray(`(${K.lines} lines)`)}`)}console.log(` ${G.gray(`total: ${Q.length} files`)}`)}return!0}case"/undo":{let Q=M.undo();if(!Q)console.log(` ${G.gray("Nothing to undo.")}`);else{let K=I($.cfg.cwd,Q.path);if(Q.restored)console.log(` ${H.ok} Restored: ${G.cyan(K)}`);else console.log(` ${H.ok} Deleted (was new): ${G.cyan(K)}`)}return!0}case"/init":{let Q=y1($.cfg.cwd,"TENICLI.md");if(w1(Q))console.log(` ${H.warn} TENICLI.md already exists.`);else h1(Q,p1,"utf8"),console.log(` ${H.ok} Created ${G.cyan("TENICLI.md")}`);return!0}case"/mode":{$.autoMode=!$.autoMode;let Q=$.autoMode?G.yellow("auto"):G.green("ask");return console.log(` ${H.ok} Mode: ${Q} ${G.gray($.autoMode?"(tools run without asking)":"(confirm write/exec)")}`),!0}case"/cost":{let Q=$.stats;return console.log(` ${H.ai} ${G.blue(String(Q.input))}↑ input ${G.blue(String(Q.output))}↓ output ${G.gray(`(${$.messageCount} msgs)`)}`),!0}case"/model":{let Q=i(),K=Q.customModels||[],V=[...u.map((J)=>({id:J.id,name:J.name,provider:J.provider,speed:J.speed,custom:!1})),...K.map((J)=>({id:J.id,name:J.id,provider:J.provider,speed:"custom",custom:!0}))],Y=V.map((J)=>({label:`${J.name} ${$.cfg.provider.model===J.id?G.green("●"):""}`,desc:`${J.provider} • ${J.speed}`}));Y.push({label:"Custom model...",desc:"type model ID"});let z=await b("Select model",Y);if(z===-1)return console.log(` ${G.gray("Cancelled")}`),!0;if(z<V.length){let J=V[z];$.cfg.provider.model=J.id,$.cfg.provider.type=J.provider;let X=J.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?.[J.provider])$.cfg.provider.baseUrl=J.provider==="openai"?"https://api.openai.com":"https://api.anthropic.com";c({activeModel:J.id}),console.log(` ${H.ok} Model: ${G.blue(J.name)}`)}else{let J=await b("Provider for custom model",[{label:"Anthropic",desc:"Claude-compatible"},{label:"OpenAI",desc:"GPT-compatible"}]);if(J===-1)return console.log(` ${G.gray("Cancelled")}`),!0;let X=J===0?"anthropic":"openai",W=await L(` ${G.gray("model ID")} ${G.blue("❯")} `);if(!W.trim())return console.log(` ${G.gray("Cancelled")}`),!0;let _=W.trim();$.cfg.provider.model=_,$.cfg.provider.type=X;let U=K.filter((D)=>D.id!==_);U.push({id:_,provider:X}),c({activeModel:_,customModels:U});let N=X==="openai"?process.env.OPENAI_API_KEY||Q.keys?.openai||"":process.env.ANTHROPIC_API_KEY||Q.keys?.anthropic||"";if(N)$.cfg.provider.apiKey=N;console.log(` ${H.ok} Model: ${G.blue(_)} ${G.gray("(saved to list)")}`)}return!0}case"/auth":{let Q=await b("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 V=["anthropic","openai","anthropic"][Q],Y=await L(` ${G.gray("API Key")} ${G.blue("❯")} `);if(!Y.trim())return console.log(` ${H.warn} Cancelled`),!0;let z={[V]:Y.trim()},J={};if(Q===2){let X=await L(` ${G.gray("Base URL")} ${G.blue("❯")} `);if(X.trim())J[V]=X.trim()}if(c({keys:z,baseUrls:J}),$.cfg.provider.apiKey=Y.trim(),$.cfg.provider.type=V,J[V])$.cfg.provider.baseUrl=J[V];return console.log(` ${H.ok} ${V} key saved to ~/.tenicli/config.json`),!0}case"/help":return console.log(`
342
345
  ${G.bold("Commands")}
343
346
  ${G.blue("/model")} Select AI model
344
347
  ${G.blue("/auth")} Set API key
@@ -354,20 +357,20 @@ ${G.bold("EXIT CODES")}
354
357
  ${G.blue("/clear")} New conversation
355
358
  ${G.blue("/cost")} Show token usage
356
359
  ${G.blue("/exit")} Quit
357
- ${G.gray("\\\\")} Continue on next line`),!0;case"/remote":{let{getLocalIPs:Q,renderQR:K}=await Promise.resolve().then(() => (d0(),m0)),{startServer:V,getActiveServers:Y}=await Promise.resolve().then(() => (H0(),E0)),X=Y();if(X.size>0){let q=Array.from(X.entries()).map(([U,D])=>({label:`Port ${U} ${G.green("●")}`,desc:`password: ${D.password}`}));q.push({label:G.cyan("+ New server"),desc:"start on random port"}),q.push({label:G.yellow("Stop all"),desc:"close all remote servers"});let H=await b("Remote servers",q);if(H===-1)return console.log(` ${G.gray("Cancelled")}`),!0;if(H<X.size){let U=Array.from(X.entries())[H],D=U[0],R=await b(`Server on port ${D}`,[{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(R===0){let O=`http://${Q()[0]||"localhost"}:${D}`;console.log(`
358
- ${G.gray("URL:")} ${G.cyan(O)}`),console.log(` ${G.gray("Password:")} ${G.yellow(U[1].password)}
359
- `),console.log(K(O)),console.log()}else if(R===1){console.log(`
360
- ${A.tool} ${G.yellow("Starting localtunnel...")}`);try{let{spawn:E}=await import("child_process"),B=E(/^win/.test(process.platform)?"npx.cmd":"npx",["--yes","localtunnel","--port",String(D)]);B.unref(),await new Promise((O,k)=>{let e=setTimeout(()=>{k(Error("Localtunnel timed out"))},1e4);B.stdout.on("data",(a0)=>{let B0=a0.toString();if(B0.includes("your url is:")){clearTimeout(e);let i0=B0.split("your url is:")[1].trim();console.log(` ${A.ok} ${G.green("Published to Internet!")}
361
- `),console.log(` ${G.gray("Public URL:")} ${G.cyan(i0)}`),console.log(` ${G.gray("Password:")} ${G.yellow(U[1].password)}
362
- `),console.log(` ${G.gray("Note: The tunnel runs in the background.")}`),O()}}),B.stderr.on("data",()=>{})}),U[1].tunnel=B}catch(E){console.log(` ${A.warn} ${G.pink(`Failed to publish: ${E.message}`)}`)}}else if(R===2){if(U[1].close(),U[1].tunnel)try{U[1].tunnel.kill()}catch{}console.log(` ${A.ok} Stopped server on port ${D}`)}return!0}else if(H===X.size);else{for(let[U,D]of X)if(D.close(),D.tunnel)try{D.tunnel.kill()}catch{}return console.log(` ${A.ok} All remote servers stopped`),!0}}let z=3000+Math.floor(Math.random()*7000),J=l0(6).toString("hex"),_=`http://${Q()[0]||"localhost"}:${z}`;return V(z,J),console.log(),f([G.bold(G.green("Remote Access Enabled")),"",`${G.gray("URL:")} ${G.cyan(_)}`,`${G.gray("Password:")} ${G.yellow(J)}`,`${G.gray("Port:")} ${G.blue(String(z))}`,"",G.gray("Use /remote again to manage or publish this server.")],58),console.log(),console.log(K(_)),console.log(),!0}case"/quota":{let Q=V0;if(!Q.requestsLimit&&!Q.tokensLimit)return console.log(` ${G.gray("No rate limit data yet. Send a message first.")}`),!0;let K=[G.bold("API Rate Limits"),""];if(Q.requestsLimit!==void 0){let V=Q.requestsLimit-(Q.requestsRemaining||0),Y=Math.round((Q.requestsRemaining||0)/Q.requestsLimit*100),X=Y>50?G.green:Y>20?G.yellow:G.pink;K.push(`${G.gray("Requests:")} ${X(String(Q.requestsRemaining))}/${Q.requestsLimit} remaining ${G.gray(`(${Y}%)`)}`)}if(Q.tokensLimit!==void 0){let V=Math.round((Q.tokensRemaining||0)/Q.tokensLimit*100),Y=V>50?G.green:V>20?G.yellow:G.pink;K.push(`${G.gray("Tokens:")} ${Y(String(Q.tokensRemaining?.toLocaleString()))}/${Q.tokensLimit.toLocaleString()} remaining ${G.gray(`(${V}%)`)}`)}if(Q.requestsReset){let V=new Date(Q.requestsReset);K.push(`${G.gray("Resets at:")} ${G.cyan(V.toLocaleTimeString())}`)}return console.log(),f(K,58),!0}case"/history":{let Q=_0();if(Q.length===0)return console.log(` ${G.gray("No saved conversations.")}`),!0;let K=Q.slice(0,10).map((X)=>({label:X.title.slice(0,40),desc:`${X.model} • ${new Date(X.updatedAt).toLocaleDateString()}`})),V=await b("Resume conversation",K);if(V===-1)return console.log(` ${G.gray("Cancelled")}`),!0;let Y=Q[V];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(`
363
- ${A.tool} ${G.yellow("Updating tenicli...")}`);try{let Q=$.exportState(),K=s($.cfg.provider.model);K.title=$.getTitle(),K.messages=Q.messages,K.tokens=Q.tokens,u0(K);let{execSync:V,spawn:Y}=await import("child_process");return V("npm i -g tenicli@latest 2>&1",{encoding:"utf8"}),console.log(` ${A.ok} ${G.green("Updated! Restarting...")}
364
- `),Y(process.execPath,process.argv.slice(1),{stdio:"inherit",detached:!1}).on("exit",(z)=>process.exit(z||0)),!0}catch(Q){P(`Update failed: ${Q.message}`)}return!0}default:return console.log(` ${A.warn} Unknown: ${Z.split(" ")[0]} — try /help`),!0}}async function g1(){let Z=h1(process.argv.slice(2)),$=c();if(Z.model)$.provider.model=Z.model;if(Z.baseUrl)$.provider.baseUrl=Z.baseUrl;switch(Z.command){case"remote":{let W=Z.port||3000,N=Z.password||l0(6).toString("hex"),{startServer:_}=await Promise.resolve().then(() => (H0(),E0));_(W,N);return}case"run":{if(!Z.prompt)P('Usage: teni run "<prompt>"'),process.exit(1);if(!$.provider.apiKey)P("No API key. Run: teni then /auth"),process.exit(1);let W=new y($);if(Z.yes)W.autoMode=!0;if(await W.send(Z.prompt),Z.json){let N=F.getChanges();console.log(JSON.stringify({ok:!0,tokens:W.stats,filesChanged:N.map((_)=>({path:I($.cwd,_.path),isNew:_.isNew,lines:_.lines}))}))}process.exit(0)}case"diff":{let W=F.getChanges();if(Z.json)console.log(JSON.stringify({files:W.map((N)=>({path:I($.cwd,N.path),isNew:N.isNew,lines:N.lines}))}));else if(W.length===0)console.log(` ${G.gray("No files changed in this session.")}`);else{console.log(`
365
- ${G.bold("Files changed this session:")}`);for(let N of W){let _=I($.cwd,N.path),q=N.isNew?G.green("[NEW]"):G.yellow("[MOD]");console.log(` ${q} ${G.cyan(_)} ${G.gray(`(${N.lines} lines)`)}`)}console.log(` ${G.gray(`total: ${W.length} files`)}`)}process.exit(0)}case"undo":{if(Z.all){let W=F.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=F.undo();if(Z.json)console.log(JSON.stringify({ok:!!W,file:W?I($.cwd,W.path):null}));else if(!W)console.log(` ${G.gray("Nothing to undo.")}`);else{let N=I($.cwd,W.path);console.log(W.restored?` ${A.ok} Restored: ${G.cyan(N)}`:` ${A.ok} Deleted (was new): ${G.cyan(N)}`)}}process.exit(0)}case"log":{let W=F.getTimeline();if(Z.json)console.log(JSON.stringify({actions:W.map((N)=>({path:I($.cwd,N.path),label:N.label,lines:N.lines,time:N.time.toISOString()}))}));else if(W.length===0)console.log(` ${G.gray("No AI actions recorded.")}`);else{console.log(`
366
- ${G.bold("AI Action Timeline:")} ${G.gray(`(${W.length} snapshots)`)}`);for(let N=0;N<W.length;N++){let _=W[N],q=I($.cwd,_.path),H=_.isNew?G.green("CREATE"):G.yellow("MODIFY"),U=_.time.toLocaleTimeString();console.log(` ${G.gray(`#${N+1}`)} ${G.gray(U)} ${H} ${G.cyan(q)} ${G.gray(`(${_.lines} lines)`)}`)}}process.exit(0)}}let Q=new y($);if(Z.yes)Q.autoMode=!0;P0(D0);let K=g.find((W)=>W.id===$.provider.model)?.name||$.provider.model,V=Q.autoMode?G.yellow("auto"):G.green("ask"),Y=[`${G.gray("model")} ${G.blue(K)} ${G.gray("mode")} ${V} ${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.")}`);f(Y,60),console.log();let X=p0(),z=s($.provider.model);if(X)Q.importState({messages:X.messages,tokens:X.tokens}),z=X,console.log(` ${A.ok} ${G.green("Session restored after update")} ${G.gray(`(${X.messages.length} msgs)`)}`),console.log();let J=()=>{if(Q.messageCount===0)return;let W=Q.exportState();z.title=Q.getTitle(),z.messages=W.messages,z.tokens=W.tokens,z.model=$.provider.model,z.updatedAt=new Date().toISOString(),f0(z)};if(process.on("SIGINT",()=>{J(),console.log(`
360
+ ${G.gray("\\\\")} Continue on next line`),!0;case"/remote":{let{getLocalIPs:Q,renderQR:K}=await Promise.resolve().then(() => (d0(),m0)),{startServer:V,getActiveServers:Y}=await Promise.resolve().then(() => (E0(),H0)),z=Y();if(z.size>0){let N=Array.from(z.entries()).map(([q,A])=>({label:`Port ${q} ${G.green("●")}`,desc:`password: ${A.password}`}));N.push({label:G.cyan("+ New server"),desc:"start on random port"}),N.push({label:G.yellow("Stop all"),desc:"close all remote servers"});let D=await b("Remote servers",N);if(D===-1)return console.log(` ${G.gray("Cancelled")}`),!0;if(D<z.size){let q=Array.from(z.entries())[D],A=q[0],E=await b(`Server on port ${A}`,[{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"}:${A}`;console.log(`
361
+ ${G.gray("URL:")} ${G.cyan(O)}`),console.log(` ${G.gray("Password:")} ${G.yellow(q[1].password)}
362
+ `),console.log(K(O)),console.log()}else if(E===1){console.log(`
363
+ ${H.tool} ${G.yellow("Starting localtunnel...")}`);try{let{spawn:B}=await import("child_process"),R=B(/^win/.test(process.platform)?"npx.cmd":"npx",["--yes","localtunnel","--port",String(A)]);R.unref(),await new Promise((O,x)=>{let e=setTimeout(()=>{x(Error("Localtunnel timed out"))},1e4);R.stdout.on("data",(a0)=>{let B0=a0.toString();if(B0.includes("your url is:")){clearTimeout(e);let i0=B0.split("your url is:")[1].trim();console.log(` ${H.ok} ${G.green("Published to Internet!")}
364
+ `),console.log(` ${G.gray("Public URL:")} ${G.cyan(i0)}`),console.log(` ${G.gray("Password:")} ${G.yellow(q[1].password)}
365
+ `),console.log(` ${G.gray("Note: The tunnel runs in the background.")}`),O()}}),R.stderr.on("data",()=>{})}),q[1].tunnel=R}catch(B){console.log(` ${H.warn} ${G.pink(`Failed to publish: ${B.message}`)}`)}}else if(E===2){if(q[1].close(),q[1].tunnel)try{q[1].tunnel.kill()}catch{}console.log(` ${H.ok} Stopped server on port ${A}`)}return!0}else if(D===z.size);else{for(let[q,A]of z)if(A.close(),A.tunnel)try{A.tunnel.kill()}catch{}return console.log(` ${H.ok} All remote servers stopped`),!0}}let J=3000+Math.floor(Math.random()*7000),X=l0(6).toString("hex"),U=`http://${Q()[0]||"localhost"}:${J}`;return V(J,X),console.log(),p([G.bold(G.green("Remote Access Enabled")),"",`${G.gray("URL:")} ${G.cyan(U)}`,`${G.gray("Password:")} ${G.yellow(X)}`,`${G.gray("Port:")} ${G.blue(String(J))}`,"",G.gray("Use /remote again to manage or publish this server.")],58),console.log(),console.log(K(U)),console.log(),!0}case"/quota":{let Q=V0;if(!Q.requestsLimit&&!Q.tokensLimit)return console.log(` ${G.gray("No rate limit data yet. Send a message first.")}`),!0;let K=[G.bold("API Rate Limits"),""];if(Q.requestsLimit!==void 0){let V=Q.requestsLimit-(Q.requestsRemaining||0),Y=Math.round((Q.requestsRemaining||0)/Q.requestsLimit*100),z=Y>50?G.green:Y>20?G.yellow:G.pink;K.push(`${G.gray("Requests:")} ${z(String(Q.requestsRemaining))}/${Q.requestsLimit} remaining ${G.gray(`(${Y}%)`)}`)}if(Q.tokensLimit!==void 0){let V=Math.round((Q.tokensRemaining||0)/Q.tokensLimit*100),Y=V>50?G.green:V>20?G.yellow:G.pink;K.push(`${G.gray("Tokens:")} ${Y(String(Q.tokensRemaining?.toLocaleString()))}/${Q.tokensLimit.toLocaleString()} remaining ${G.gray(`(${V}%)`)}`)}if(Q.requestsReset){let V=new Date(Q.requestsReset);K.push(`${G.gray("Resets at:")} ${G.cyan(V.toLocaleTimeString())}`)}return console.log(),p(K,58),!0}case"/history":{let Q=U0();if(Q.length===0)return console.log(` ${G.gray("No saved conversations.")}`),!0;let K=Q.slice(0,10).map((z)=>({label:z.title.slice(0,40),desc:`${z.model} • ${new Date(z.updatedAt).toLocaleDateString()}`})),V=await b("Resume conversation",K);if(V===-1)return console.log(` ${G.gray("Cancelled")}`),!0;let Y=Q[V];return $.clear(),$.importState({messages:Y.messages,tokens:Y.tokens}),$.__convId=Y.id,console.log(` ${H.ok} Restored: ${G.blue(Y.title)} ${G.gray(`(${Y.messages.length} msgs)`)}`),!0}case"/update":{console.log(`
366
+ ${H.tool} ${G.yellow("Updating tenicli...")}`);try{let Q=$.exportState(),K=s($.cfg.provider.model);K.title=$.getTitle(),K.messages=Q.messages,K.tokens=Q.tokens,u0(K);let{execSync:V,spawn:Y}=await import("child_process");return V("npm i -g tenicli@latest 2>&1",{encoding:"utf8"}),console.log(` ${H.ok} ${G.green("Updated! Restarting...")}
367
+ `),Y(process.execPath,process.argv.slice(1),{stdio:"inherit",detached:!1}).on("exit",(J)=>process.exit(J||0)),!0}catch(Q){P(`Update failed: ${Q.message}`)}return!0}default:return console.log(` ${H.warn} Unknown: ${Z.split(" ")[0]} — try /help`),!0}}async function u1(){let Z=v1(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,_=Z.password||l0(6).toString("hex"),{startServer:U}=await Promise.resolve().then(() => (E0(),H0));U(W,_);return}case"run":{if(!Z.prompt)P('Usage: teni run "<prompt>"'),process.exit(1);if(!$.provider.apiKey)P("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 _=M.getChanges();console.log(JSON.stringify({ok:!0,tokens:W.stats,filesChanged:_.map((U)=>({path:I($.cwd,U.path),isNew:U.isNew,lines:U.lines}))}))}process.exit(0)}case"diff":{let W=M.getChanges();if(Z.json)console.log(JSON.stringify({files:W.map((_)=>({path:I($.cwd,_.path),isNew:_.isNew,lines:_.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 _ of W){let U=I($.cwd,_.path),N=_.isNew?G.green("[NEW]"):G.yellow("[MOD]");console.log(` ${N} ${G.cyan(U)} ${G.gray(`(${_.lines} lines)`)}`)}console.log(` ${G.gray(`total: ${W.length} files`)}`)}process.exit(0)}case"undo":{if(Z.all){let W=M.undoAll();if(Z.json)console.log(JSON.stringify({ok:!0,reverted:W}));else console.log(W>0?` ${H.ok} Reverted ${W} file changes`:` ${G.gray("Nothing to undo.")}`)}else{let W=M.undo();if(Z.json)console.log(JSON.stringify({ok:!!W,file:W?I($.cwd,W.path):null}));else if(!W)console.log(` ${G.gray("Nothing to undo.")}`);else{let _=I($.cwd,W.path);console.log(W.restored?` ${H.ok} Restored: ${G.cyan(_)}`:` ${H.ok} Deleted (was new): ${G.cyan(_)}`)}}process.exit(0)}case"log":{let W=M.getTimeline();if(Z.json)console.log(JSON.stringify({actions:W.map((_)=>({path:I($.cwd,_.path),label:_.label,lines:_.lines,time:_.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 _=0;_<W.length;_++){let U=W[_],N=I($.cwd,U.path),D=U.isNew?G.green("CREATE"):G.yellow("MODIFY"),q=U.time.toLocaleTimeString();console.log(` ${G.gray(`#${_+1}`)} ${G.gray(q)} ${D} ${G.cyan(N)} ${G.gray(`(${U.lines} lines)`)}`)}}process.exit(0)}}let Q=new g($);if(Z.yes)Q.autoMode=!0;P0(D0);let K=u.find((W)=>W.id===$.provider.model)?.name||$.provider.model,V=Q.autoMode?G.yellow("auto"):G.green("ask"),Y=[`${G.gray("model")} ${G.blue(K)} ${G.gray("mode")} ${V} ${G.gray("cwd")} ${G.cyan($.cwd)}`];if(!$.provider.apiKey)Y.push(""),Y.push(`${H.warn} ${G.yellow("No API key configured. Run /auth to set one.")}`);p(Y,60),console.log();let z=p0(),J=s($.provider.model);if(z)Q.importState({messages:z.messages,tokens:z.tokens}),J=z,console.log(` ${H.ok} ${G.green("Session restored after update")} ${G.gray(`(${z.messages.length} msgs)`)}`),console.log();let X=()=>{if(Q.messageCount===0)return;let W=Q.exportState();J.title=Q.getTitle(),J.messages=W.messages,J.tokens=W.tokens,J.model=$.provider.model,J.updatedAt=new Date().toISOString(),f0(J)};if(process.on("SIGINT",()=>{X(),console.log(`
367
370
  ${G.gray("Bye!")} \uD83D\uDC4B
368
- `),process.exit(0)}),Z.prompt){if(console.log(` ${A.prompt} ${Z.prompt}`),$.provider.apiKey)await Q.send(Z.prompt);J()}while(!0)try{let N=(await I0()).trim();if(!N)continue;if(N.startsWith("/")){if(N==="/clear")J(),z=s($.provider.model);await v1(N,Q);continue}if(!Q.cfg.provider.apiKey){console.log(` ${A.warn} ${G.yellow("No API key. Run /auth first.")}`);continue}await Q.send(N),J()}catch(W){if(W.message==="EOF")J(),console.log(`
371
+ `),process.exit(0)}),Z.prompt){if(console.log(` ${H.prompt} ${Z.prompt}`),$.provider.apiKey)await Q.send(Z.prompt);X()}while(!0)try{let _=(await I0()).trim();if(!_)continue;if(_.startsWith("/")){if(_==="/clear")X(),J=s($.provider.model);await f1(_,Q);continue}if(!Q.cfg.provider.apiKey){console.log(` ${H.warn} ${G.yellow("No API key. Run /auth first.")}`);continue}await Q.send(_),X()}catch(W){if(W.message==="EOF")X(),console.log(`
369
372
  ${G.gray("Bye!")} \uD83D\uDC4B
370
- `),process.exit(0);P(W.message)}}g1().catch((Z)=>{P(Z.message),process.exit(1)});var f1=`# Project Instructions
373
+ `),process.exit(0);P(W.message)}}u1().catch((Z)=>{P(Z.message),process.exit(1)});var p1=`# Project Instructions
371
374
 
372
375
  ## Overview
373
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.1",
3
+ "version": "0.3.2",
4
4
  "description": "Lightweight AI coding CLI — fast, compact, multi-provider",
5
5
  "type": "module",
6
6
  "bin": {