hankweave 0.3.3 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
- import{readFileSync as le}from"fs";import{dirname as ce,join as me}from"path";import{fileURLToPath as ue}from"url";import{spawn as G}from"child_process";import{createWriteStream as T}from"fs";import{mkdir as Y}from"fs/promises";import{isAbsolute as O,resolve as g}from"path";import{createInterface as re}from"readline";var S=class{constructor(e){this.options=e;this.verbose=e.verbose}process=null;verbose;rawEventStream=null;stderrStream=null;stderrBuffer="";currentSessionId="unknown";static async isInstalled(){return new Promise(e=>{let t=process.platform==="win32",i=G(t?"where":"which",["gemini"],{shell:t}),a="";i.stdout?.on("data",c=>{a+=c.toString()}),i.on("close",c=>{if(c===0&&a.trim()){let l=G("gemini",["--version"],{shell:t}),r="";l.stdout?.on("data",m=>{r+=m.toString()}),l.on("close",()=>{e({found:!0,path:a.trim(),version:r.trim()})})}else e({found:!1})})})}async initializeDebugStreams(e){if(this.options.debugDir)try{let t=O(this.options.debugDir)?this.options.debugDir:g(this.options.cwd,this.options.debugDir);await Y(t,{recursive:!0});let o=g(t,`session-${e}.raw.jsonl`);this.rawEventStream=T(o,{flags:"a",encoding:"utf8"});let i=g(t,`session-${e}.raw.log`);this.stderrStream=T(i,{flags:"a",encoding:"utf8"}),this.stderrBuffer&&(this.stderrStream.write(this.stderrBuffer),this.stderrBuffer=""),this.currentSessionId=e}catch(t){throw new Error(`Failed to create debug log files in ${this.options.debugDir}: ${t instanceof Error?t.message:String(t)}`)}}async renameDebugStreams(e){if(!(!this.options.debugDir||this.currentSessionId===e))try{let t=O(this.options.debugDir)?this.options.debugDir:g(this.options.cwd,this.options.debugDir);await this.closeDebugStreams();let{rename:o}=await import("fs/promises"),i=g(t,`session-${this.currentSessionId}.raw.jsonl`),a=g(t,`session-${e}.raw.jsonl`),c=g(t,`session-${this.currentSessionId}.raw.log`),l=g(t,`session-${e}.raw.log`);try{await o(i,a)}catch(r){this.verbose&&console.error(`[gemini-cli-shim] Could not rename ${i}:`,r)}try{await o(c,l)}catch(r){this.verbose&&console.error(`[gemini-cli-shim] Could not rename ${c}:`,r)}await this.initializeDebugStreams(e)}catch(t){throw new Error(`Failed to rename debug log files: ${t instanceof Error?t.message:String(t)}`)}}writeRawEvent(e){this.rawEventStream&&this.rawEventStream.write(`${JSON.stringify(e)}
3
- `)}writeStderr(e){this.options.debugDir&&(this.stderrStream?this.stderrStream.write(e):this.stderrBuffer+=e)}async closeDebugStreams(){let e=[];if(this.stderrBuffer&&!this.stderrStream&&this.options.debugDir)try{let t=O(this.options.debugDir)?this.options.debugDir:g(this.options.cwd,this.options.debugDir);await Y(t,{recursive:!0});let o=g(t,`session-${this.currentSessionId}.raw.log`),i=T(o,{flags:"a",encoding:"utf8"});await new Promise((a,c)=>{i.write(this.stderrBuffer,l=>{l?c(l):i.end(r=>{r?c(r):a()})})}),this.stderrBuffer=""}catch(t){console.error("[gemini-cli-shim] Error flushing buffered stderr:",t)}this.rawEventStream&&(e.push(new Promise((t,o)=>{this.rawEventStream?.end(i=>{i?o(i):t()})})),this.rawEventStream=null),this.stderrStream&&(e.push(new Promise((t,o)=>{this.stderrStream?.end(i=>{i?o(i):t()})})),this.stderrStream=null),await Promise.all(e)}async spawn(e){let t=["--model",this.options.model,"--output-format","stream-json","--yolo"];this.options.resume&&t.push("--resume",this.options.resume),this.verbose&&console.error("[gemini-cli-shim] Spawning gemini:",t.join(" "));let o=process.platform==="win32";this.process=G("gemini",t,{cwd:this.options.cwd,stdio:["pipe","pipe","pipe"],env:{...process.env},shell:o}),this.options.debugDir&&await this.initializeDebugStreams("unknown");let i=this.options.appendSystemPrompt?`${e}
2
+ import{readFileSync as de}from"fs";import{dirname as pe,join as ge}from"path";import{fileURLToPath as fe}from"url";function Y(s,e){let t={model:"",verbose:!1,idleTimeout:120,selfTest:!1,version:!1,help:!1};for(let i=0;i<s.length;i++){let r=s[i];if(r.includes("=")){let[a,l]=r.split("=",2);s.splice(i,1,a,l),r=a}switch(e&&r in e&&(r=e[r]),r){case"--model":t.model=s[++i];break;case"--resume":t.resume=s[++i];break;case"--verbose":t.verbose=!0;break;case"--append-system-prompt":t.appendSystemPrompt=s[++i];break;case"--debug-dir":t.debugDir=s[++i];break;case"--idle-timeout":{let a=Number(s[++i]);(!Number.isFinite(a)||a<=0)&&(console.error("Invalid --idle-timeout value: must be a positive number"),process.exit(1)),t.idleTimeout=a;break}case"--self-test":t.selfTest=!0;break;case"--version":t.version=!0;break;case"--help":t.help=!0;break}}return t}import{spawn as A}from"child_process";import{createWriteStream as O}from"fs";import{mkdir as J}from"fs/promises";import{isAbsolute as G,resolve as h}from"path";import{createInterface as ae}from"readline";var _=class{constructor(e){this.options=e;this.verbose=e.verbose}process=null;verbose;rawEventStream=null;stderrStream=null;stderrBuffer="";currentSessionId="unknown";static async isInstalled(){return new Promise(e=>{let t=process.platform==="win32",r=A(t?"where":"which",["gemini"],{shell:t}),a="";r.stdout?.on("data",l=>{a+=l.toString()}),r.on("close",l=>{if(l===0&&a.trim()){let c=A("gemini",["--version"],{shell:t}),o="";c.stdout?.on("data",m=>{o+=m.toString()}),c.on("close",()=>{e({found:!0,path:a.trim(),version:o.trim()})})}else e({found:!1})})})}async initializeDebugStreams(e){if(this.options.debugDir)try{let t=G(this.options.debugDir)?this.options.debugDir:h(this.options.cwd,this.options.debugDir);await J(t,{recursive:!0});let i=h(t,`session-${e}.raw.jsonl`);this.rawEventStream=O(i,{flags:"a",encoding:"utf8"});let r=h(t,`session-${e}.raw.log`);this.stderrStream=O(r,{flags:"a",encoding:"utf8"}),this.stderrBuffer&&(this.stderrStream.write(this.stderrBuffer),this.stderrBuffer=""),this.currentSessionId=e}catch(t){throw new Error(`Failed to create debug log files in ${this.options.debugDir}: ${t instanceof Error?t.message:String(t)}`)}}async renameDebugStreams(e){if(!(!this.options.debugDir||this.currentSessionId===e))try{let t=G(this.options.debugDir)?this.options.debugDir:h(this.options.cwd,this.options.debugDir);await this.closeDebugStreams();let{rename:i}=await import("fs/promises"),r=h(t,`session-${this.currentSessionId}.raw.jsonl`),a=h(t,`session-${e}.raw.jsonl`),l=h(t,`session-${this.currentSessionId}.raw.log`),c=h(t,`session-${e}.raw.log`);try{await i(r,a)}catch(o){this.verbose&&console.error(`[gemini-cli-shim] Could not rename ${r}:`,o)}try{await i(l,c)}catch(o){this.verbose&&console.error(`[gemini-cli-shim] Could not rename ${l}:`,o)}await this.initializeDebugStreams(e)}catch(t){throw new Error(`Failed to rename debug log files: ${t instanceof Error?t.message:String(t)}`)}}writeRawEvent(e){this.rawEventStream&&this.rawEventStream.write(`${JSON.stringify(e)}
3
+ `)}writeStderr(e){this.options.debugDir&&(this.stderrStream?this.stderrStream.write(e):this.stderrBuffer+=e)}async closeDebugStreams(){let e=[];if(this.stderrBuffer&&!this.stderrStream&&this.options.debugDir)try{let t=G(this.options.debugDir)?this.options.debugDir:h(this.options.cwd,this.options.debugDir);await J(t,{recursive:!0});let i=h(t,`session-${this.currentSessionId}.raw.log`),r=O(i,{flags:"a",encoding:"utf8"});await new Promise((a,l)=>{r.write(this.stderrBuffer,c=>{c?l(c):r.end(o=>{o?l(o):a()})})}),this.stderrBuffer=""}catch(t){console.error("[gemini-cli-shim] Error flushing buffered stderr:",t)}this.rawEventStream&&(e.push(new Promise((t,i)=>{this.rawEventStream?.end(r=>{r?i(r):t()})})),this.rawEventStream=null),this.stderrStream&&(e.push(new Promise((t,i)=>{this.stderrStream?.end(r=>{r?i(r):t()})})),this.stderrStream=null),await Promise.all(e)}async spawn(e){let t=["--model",this.options.model,"--output-format","stream-json","--yolo"];this.options.resume&&t.push("--resume",this.options.resume),this.verbose&&console.error("[gemini-cli-shim] Spawning gemini:",t.join(" "));let i=process.platform==="win32";this.process=A("gemini",t,{cwd:this.options.cwd,stdio:["pipe","pipe","pipe"],env:{...process.env},shell:i}),this.options.debugDir&&await this.initializeDebugStreams("unknown");let r=this.options.appendSystemPrompt?`${e}
4
4
 
5
- Additional instructions: ${this.options.appendSystemPrompt}`:e;return this.process.stdin?.write(i),this.process.stdin?.end(),this.createEventStream()}async*createEventStream(){if(!this.process||!this.process.stdout||!this.process.stderr)throw new Error("Process not spawned");let e="",t=!1,o=!1,i="",a=null;this.process.stderr.on("data",l=>{let r=l.toString();e+=r,this.writeStderr(r),!o&&(r.includes("Error resuming session:")||r.includes("Invalid session identifier"))&&(t=!0,o=!0,this.verbose&&console.error("[gemini-cli-shim] Session error detected, killing process"),this.process&&this.process.kill("SIGKILL")),this.verbose&&console.error("[gemini stderr]",r)});let c=re({input:this.process.stdout,crlfDelay:1/0});if(t)throw new Error("Invalid session ID");try{for await(let l of c){let r=l.trim();if(t)throw new Error("Invalid session ID");if(r)try{let m=JSON.parse(r);m.type==="init"&&m.session_id&&(i=m.session_id,this.options.debugDir&&this.currentSessionId==="unknown"&&await this.renameDebugStreams(i)),this.writeRawEvent(m),this.verbose&&console.error("[gemini event]",JSON.stringify(m)),yield m}catch(m){this.verbose&&(console.error("[gemini-cli-shim] Failed to parse line:",r),console.error("[gemini-cli-shim] Error:",m))}}}catch(l){throw t?new Error("Invalid session ID"):l}if(t)throw new Error("Invalid session ID");await new Promise((l,r)=>{if(!this.process){t?r(new Error("Invalid session ID")):l();return}let m=setTimeout(()=>{this.verbose&&console.error("[gemini-cli-shim] Process exit timeout, forcing kill"),this.kill(),r(t?new Error("Invalid session ID"):new Error("Process did not exit within timeout"))},2e3);this.process.on("close",async d=>{clearTimeout(m),a=d;try{await this.closeDebugStreams()}catch(b){console.error("[gemini-cli-shim] Error closing debug streams:",b)}t?r(new Error("Invalid session ID")):d===0||d===null?l():r(new Error(`Gemini CLI exited with code ${d}`))}),this.process.on("error",async d=>{clearTimeout(m);try{await this.closeDebugStreams()}catch(b){console.error("[gemini-cli-shim] Error closing debug streams:",b)}r(t?new Error("Invalid session ID"):d)})})}kill(){this.process&&(this.process.kill("SIGTERM"),this.process=null)}};import{readFileSync as ne}from"fs";import{resolve as ae}from"path";function z(s){let e={model:"",verbose:!1,selfTest:!1,version:!1,help:!1};for(let t=2;t<s.length;t++){let o=s[t];if(o.includes("=")){let[i,a]=o.split("=",2);switch(i){case"--model":e.model=a;break;case"--resume":e.resume=a;break;case"--append-system-prompt":e.appendSystemPrompt=a;break;case"--debug-dir":e.debugDir=a;break}continue}switch(o){case"--model":case"-m":t+1<s.length&&(e.model=s[++t]);break;case"--resume":case"-r":t+1<s.length&&(e.resume=s[++t]);break;case"--append-system-prompt":t+1<s.length&&(e.appendSystemPrompt=s[++t]);break;case"--debug-dir":t+1<s.length&&(e.debugDir=s[++t]);break;case"--verbose":case"-v":e.verbose=!0;break;case"--self-test":e.selfTest=!0;break;case"--version":e.version=!0;break;case"--help":case"-h":e.help=!0;break;case"-p":break;default:break}}return e}var F={sonnet:"anthropic/claude-sonnet-4-20250514",haiku:"anthropic/claude-3-haiku",opus:"anthropic/claude-opus-4-5-20251101",flash:"google/gemini-2.0-flash",pro:"google/gemini-2.0-pro"};function J(s){if(!s){let e=process.env.MODEL;e?s=e:s="flash"}if(F[s]){let e=F[s];return e.startsWith("google/")?e.replace("google/",""):e}if(s.includes("/")){let[e,t]=s.split("/",2);return e==="google"?t:s}return s}function _(s){return s.startsWith("anthropic/")?s.replace("anthropic/",""):!s.includes("/")&&(s.startsWith("gemini-")||s==="flash"||s==="pro")?`google/${s}`:s}import{randomBytes as j}from"crypto";function L(){let s=Date.now().toString(36),e=j(5).toString("hex");return`msg_${s}${e}`}function $(){let s=Date.now().toString(36),e=j(6).toString("hex");return`toolu_${s}${e}`}var I="00000000-0000-0000-0000-000000000000";var ie={read_file:"Read",readFile:"Read",file_read:"Read",write_file:"Write",writeFile:"Write",file_write:"Write",edit_file:"Edit",editFile:"Edit",str_replace_editor:"Edit",run_shell_command:"Bash",bash:"Bash",shell:"Bash",execute_bash:"Bash",list_directory:"LS",ls:"LS",list:"LS",list_dir:"LS",glob:"Glob",find_files:"Glob",grep:"Grep",search_files:"Grep",search:"Grep"};function H(s){return ie[s]||s}function oe(s){return s.replace(/[A-Z]/g,e=>`_${e.toLowerCase()}`)}function q(s){if(!s)return s;let e={};for(let[t,o]of Object.entries(s))e[oe(t)]=o;return e}function D(){return["Read","Write","Edit","Bash","Glob","Grep","LS"]}function f(s){console.log(JSON.stringify(s))}function R(){return process.env.GOOGLE_API_KEY?"GOOGLE_API_KEY":process.env.GEMINI_API_KEY?"GEMINI_API_KEY":"none"}async function V(s,e){let t=Date.now(),o=0,i=0,a="",c=0,l={input_tokens:0,output_tokens:0},r=!1,m="",d=!1;if(e.debugDir)try{let{mkdirSync:p}=await import("fs");p(e.debugDir,{recursive:!0})}catch{}let b="Always repeat the results of your tool calls (like file contents or command output) in your text response. This is critical for verification.",X=e.appendSystemPrompt?`${b}
6
- ${e.appendSystemPrompt}`:b,ee={...e,appendSystemPrompt:X},C=new Set,N=new Map,U=new Map,h=[],M=L(),E=!1,w="";try{let P=await new S(ee).spawn(s);for await(let n of P)switch(n.type){case"init":{a=n.session_id,d=!0;let u={type:"system",subtype:"init",cwd:e.cwd,session_id:a,tools:D(),model:_(e.model),permissionMode:"bypassPermissions",apiKeySource:R(),mcp_servers:[]};f(u),o=Date.now();break}case"message":{if(n.role==="assistant"){if(n.delta)E=!0,w+=n.content,h.push({type:"text",text:n.content});else if(!E)h.push({type:"text",text:n.content}),w=n.content;else if(n.content.length>w.length&&n.content.startsWith(w)){let u=n.content.slice(w.length);u.trim()&&(h.push({type:"text",text:u}),w=n.content)}}break}case"tool_use":{if(!C.has(n.tool_id)){C.add(n.tool_id);let u=$();N.set(n.tool_id,u);let v=H(n.tool_name),y=q(n.parameters);U.set(n.tool_id,{name:v,params:n.parameters}),h.push({type:"tool_use",id:u,name:v,input:y});let K={type:"assistant",message:{id:M,type:"message",role:"assistant",model:_(e.model),content:h,stop_reason:"tool_use"}};f(K),h=[],M=L(),E=!1,w="",c++}break}case"tool_result":{let u=N.get(n.tool_id)||$(),v=U.get(n.tool_id),y="";if(n.status==="error")y={is_error:!0,error:n.error||"Unknown error"};else{let B=n;if(y=n.output!==void 0?n.output:B.result||B.content||"",v?.name==="Read"&&y===""){let A=v.params?.file_path||v.params?.filePath||v.params?.path;if(A&&typeof A=="string")try{let W=ae(e.cwd,A);y=ne(W,"utf-8")}catch{}}}f({type:"user",message:{role:"user",content:[{type:"tool_result",tool_use_id:u,content:y}]}}),E=!1,w="";break}case"result":{if(i=Date.now(),h.length>0){let u={type:"assistant",message:{id:M,type:"message",role:"assistant",model:_(e.model),content:h,stop_reason:"end_turn"}};f(u),c++}l.input_tokens=(l.input_tokens||0)+(n.stats.input_tokens||0),l.output_tokens=(l.output_tokens||0)+(n.stats.output_tokens||0),r=n.status==="error",m=r?"Error completing request":"Request completed successfully";break}}}catch(p){let P=p instanceof Error?p.message:String(p);if(P.includes("Invalid session ID"))throw p;if(r=!0,m=`Agent Error: ${P}`,!d){let u={type:"system",subtype:"init",cwd:e.cwd,session_id:a||I,tools:D(),model:_(e.model),permissionMode:"bypassPermissions",apiKeySource:R(),mcp_servers:[]};f(u),d=!0}f({type:"assistant",message:{id:I,type:"message",role:"assistant",model:"<synthetic>",content:[{type:"text",text:m}]}})}let se=Date.now(),te={type:"result",subtype:r?"error":"success",is_error:r,duration_ms:se-t,duration_api_ms:i>0?i-o:0,num_turns:c,result:m,session_id:a,usage:l};return f(te),await new Promise(p=>{process.stdout.write("",()=>p())}),{exitCode:r?1:0,sessionId:a}}async function Z(s,e){let t={type:"system",subtype:"init",cwd:process.cwd(),session_id:e||I,tools:D(),model:"<unknown>",permissionMode:"bypassPermissions",apiKeySource:R(),mcp_servers:[]};f(t);let o={type:"assistant",message:{id:I,type:"message",role:"assistant",model:"<synthetic>",content:[{type:"text",text:`API Error: ${s}`}]}};f(o),f({type:"result",subtype:"error",is_error:!0,duration_ms:0,duration_api_ms:0,num_turns:0,result:s,session_id:e}),await new Promise(a=>{process.stdout.write("",()=>a())})}var de=ue(import.meta.url),pe=ce(de);async function ge(){let s=[];for await(let e of process.stdin)s.push(Buffer.from(e));return Buffer.concat(s).toString("utf-8").trim()}function Q(){console.error(`
5
+ Additional instructions: ${this.options.appendSystemPrompt}`:e;return this.process.stdin?.write(r),this.process.stdin?.end(),this.createEventStream()}async*createEventStream(){if(!this.process||!this.process.stdout||!this.process.stderr)throw new Error("Process not spawned");let e="",t=!1,i=!1,r="",a=null;this.process.stderr.on("data",c=>{let o=c.toString();e+=o,this.writeStderr(o),!i&&(o.includes("Error resuming session:")||o.includes("Invalid session identifier"))&&(t=!0,i=!0,this.verbose&&console.error("[gemini-cli-shim] Session error detected, killing process"),this.process&&this.process.kill("SIGKILL")),this.verbose&&console.error("[gemini stderr]",o)});let l=ae({input:this.process.stdout,crlfDelay:1/0});if(t)throw new Error("Invalid session ID");try{for await(let c of l){let o=c.trim();if(t)throw new Error("Invalid session ID");if(o)try{let m=JSON.parse(o);m.type==="init"&&m.session_id&&(r=m.session_id,this.options.debugDir&&this.currentSessionId==="unknown"&&await this.renameDebugStreams(r)),this.writeRawEvent(m),this.verbose&&console.error("[gemini event]",JSON.stringify(m)),yield m}catch(m){this.verbose&&(console.error("[gemini-cli-shim] Failed to parse line:",o),console.error("[gemini-cli-shim] Error:",m))}}}catch(c){throw t?new Error("Invalid session ID"):c}if(t)throw new Error("Invalid session ID");await new Promise((c,o)=>{if(!this.process){t?o(new Error("Invalid session ID")):c();return}let m=setTimeout(()=>{this.verbose&&console.error("[gemini-cli-shim] Process exit timeout, forcing kill"),this.kill(),o(t?new Error("Invalid session ID"):new Error("Process did not exit within timeout"))},2e3);this.process.on("close",async d=>{clearTimeout(m),a=d;try{await this.closeDebugStreams()}catch(I){console.error("[gemini-cli-shim] Error closing debug streams:",I)}t?o(new Error("Invalid session ID")):d===0||d===null?c():o(new Error(`Gemini CLI exited with code ${d}`))}),this.process.on("error",async d=>{clearTimeout(m);try{await this.closeDebugStreams()}catch(I){console.error("[gemini-cli-shim] Error closing debug streams:",I)}o(t?new Error("Invalid session ID"):d)})})}kill(){this.process&&(this.process.kill("SIGTERM"),this.process=null)}};import{readFileSync as me}from"fs";import{resolve as ue}from"path";import{randomUUID as Ge}from"crypto";import Ne from"fs";import Ce from"path";var R=class extends Error{timeoutMs;constructor(e){super(`Idle timeout: no events received for ${e}ms`),this.name="IdleTimeoutError",this.timeoutMs=e}};async function*z(s,e){let t=s[Symbol.asyncIterator]();try{for(;;){let i;try{let r=await Promise.race([t.next(),new Promise((a,l)=>{i=setTimeout(()=>{l(new R(e))},e)})]);if(r.done)break;yield r.value}finally{clearTimeout(i)}}}finally{t.return?.()}}var q=["Read","Write","Edit","Bash","Glob","Grep","LS"];var H={sonnet:"anthropic/claude-sonnet-4-20250514",haiku:"anthropic/claude-3-haiku",opus:"anthropic/claude-opus-4-5-20251101",flash:"google/gemini-2.0-flash",pro:"google/gemini-2.0-pro"};function V(s){if(!s){let e=process.env.MODEL;e?s=e:s="flash"}if(H[s]){let e=H[s];return e.startsWith("google/")?e.replace("google/",""):e}if(s.includes("/")){let[e,t]=s.split("/",2);return e==="google"?t:s}return s}function E(s){return s.startsWith("anthropic/")?s.replace("anthropic/",""):!s.includes("/")&&(s.startsWith("gemini-")||s==="flash"||s==="pro")?`google/${s}`:s}import{randomBytes as Z}from"crypto";function N(){let s=Date.now().toString(36),e=Z(5).toString("hex");return`msg_${s}${e}`}function $(){let s=Date.now().toString(36),e=Z(6).toString("hex");return`toolu_${s}${e}`}var x="00000000-0000-0000-0000-000000000000";var le={read_file:"Read",readFile:"Read",file_read:"Read",write_file:"Write",writeFile:"Write",file_write:"Write",edit_file:"Edit",editFile:"Edit",str_replace_editor:"Edit",run_shell_command:"Bash",bash:"Bash",shell:"Bash",execute_bash:"Bash",list_directory:"LS",ls:"LS",list:"LS",list_dir:"LS",glob:"Glob",find_files:"Glob",grep:"Grep",search_files:"Grep",search:"Grep"};function Q(s){return le[s]||s}function ce(s){return s.replace(/[A-Z]/g,e=>`_${e.toLowerCase()}`)}function X(s){if(!s)return s;let e={};for(let[t,i]of Object.entries(s))e[ce(t)]=i;return e}function k(){return[...q]}function y(s){console.log(JSON.stringify(s))}function C(){return process.env.GOOGLE_API_KEY?"GOOGLE_API_KEY":process.env.GEMINI_API_KEY?"GEMINI_API_KEY":"none"}async function ee(s,e){let t=Date.now(),i=0,r=0,a="",l=0,c={input_tokens:0,output_tokens:0},o=!1,m="",d=!1;if(e.debugDir)try{let{mkdirSync:p}=await import("fs");p(e.debugDir,{recursive:!0})}catch{}let I="Always repeat the results of your tool calls (like file contents or command output) in your text response. This is critical for verification.",re=e.appendSystemPrompt?`${I}
6
+ ${e.appendSystemPrompt}`:I,ie={...e,appendSystemPrompt:re},L=new Set,U=new Map,B=new Map,w=[],T=N(),D=!1,v="";try{let P=await new _(ie).spawn(s),K=z(P,e.idleTimeout*1e3);for await(let n of K)switch(n.type){case"init":{a=n.session_id,d=!0;let u={type:"system",subtype:"init",cwd:e.cwd,session_id:a,tools:k(),model:E(e.model),permissionMode:"bypassPermissions",apiKeySource:C(),mcp_servers:[]};y(u),i=Date.now();break}case"message":{if(n.role==="assistant"){if(n.delta)D=!0,v+=n.content,w.push({type:"text",text:n.content});else if(!D)w.push({type:"text",text:n.content}),v=n.content;else if(n.content.length>v.length&&n.content.startsWith(v)){let u=n.content.slice(v.length);u.trim()&&(w.push({type:"text",text:u}),v=n.content)}}break}case"tool_use":{if(!L.has(n.tool_id)){L.add(n.tool_id);let u=$();U.set(n.tool_id,u);let S=Q(n.tool_name),b=X(n.parameters);B.set(n.tool_id,{name:S,params:n.parameters}),w.push({type:"tool_use",id:u,name:S,input:b});let j={type:"assistant",message:{id:T,type:"message",role:"assistant",model:E(e.model),content:w,stop_reason:"tool_use"}};y(j),w=[],T=N(),D=!1,v="",l++}break}case"tool_result":{let u=U.get(n.tool_id)||$(),S=B.get(n.tool_id),b="";if(n.status==="error")b={is_error:!0,error:n.error||"Unknown error"};else{let F=n;if(b=n.output!==void 0?n.output:F.result||F.content||"",S?.name==="Read"&&b===""){let M=S.params?.file_path||S.params?.filePath||S.params?.path;if(M&&typeof M=="string")try{let W=ue(e.cwd,M);b=me(W,"utf-8")}catch{}}}y({type:"user",message:{role:"user",content:[{type:"tool_result",tool_use_id:u,content:b}]}}),D=!1,v="";break}case"result":{if(r=Date.now(),w.length>0){let u={type:"assistant",message:{id:T,type:"message",role:"assistant",model:E(e.model),content:w,stop_reason:"end_turn"}};y(u),l++}c.input_tokens=(c.input_tokens||0)+(n.stats.input_tokens||0),c.output_tokens=(c.output_tokens||0)+(n.stats.output_tokens||0),o=n.status==="error",m=o?"Error completing request":"Request completed successfully";break}}}catch(p){let P=p instanceof Error?p.message:String(p);if(P.includes("Invalid session ID"))throw p;if(o=!0,m=`Agent Error: ${P}`,!d){let n={type:"system",subtype:"init",cwd:e.cwd,session_id:a||x,tools:k(),model:E(e.model),permissionMode:"bypassPermissions",apiKeySource:C(),mcp_servers:[]};y(n),d=!0}y({type:"assistant",message:{id:x,type:"message",role:"assistant",model:"<synthetic>",content:[{type:"text",text:m}]}})}let oe=Date.now(),ne={type:"result",subtype:o?"error":"success",is_error:o,duration_ms:oe-t,duration_api_ms:r>0?r-i:0,num_turns:l,result:m,session_id:a,usage:c};return y(ne),await new Promise(p=>{process.stdout.write("",()=>p())}),{exitCode:o?1:0,sessionId:a}}async function se(s,e){let t={type:"system",subtype:"init",cwd:process.cwd(),session_id:e||x,tools:k(),model:"<unknown>",permissionMode:"bypassPermissions",apiKeySource:C(),mcp_servers:[]};y(t);let i={type:"assistant",message:{id:x,type:"message",role:"assistant",model:"<synthetic>",content:[{type:"text",text:`API Error: ${s}`}]}};y(i),y({type:"result",subtype:"error",is_error:!0,duration_ms:0,duration_api_ms:0,num_turns:0,result:s,session_id:e}),await new Promise(a=>{process.stdout.write("",()=>a())})}var he=fe(import.meta.url),ye=pe(he);async function we(){let s=[];for await(let e of process.stdin)s.push(Buffer.from(e));return Buffer.concat(s).toString("utf-8").trim()}function te(){console.error(`
7
7
  Gemini CLI Shim - Translate Gemini CLI to standardized JSONL output
8
8
 
9
9
  Usage: gemini-cli-shim [options]
@@ -16,6 +16,7 @@ Optional Arguments:
16
16
  --resume <session_id> Session ID to continue
17
17
  --verbose Enable verbose logging to stderr
18
18
  --append-system-prompt <txt> Additional system prompt to append
19
+ --idle-timeout <seconds> Max seconds between agent events before aborting (default: 120)
19
20
  --debug-dir <path> Directory for debug logs and session data
20
21
  --self-test Run environment verification
21
22
  --version Print version and exit
@@ -26,4 +27,4 @@ Examples:
26
27
  echo "Continue" | gemini-cli-shim --model pro --resume <session_id>
27
28
  echo "Debug" | gemini-cli-shim --model flash --debug-dir ./debug
28
29
  gemini-cli-shim --self-test
29
- `)}function fe(){try{let s=me(pe,"..","package.json"),e=JSON.parse(le(s,"utf-8"));console.error(`gemini-cli-shim v${e.version}`)}catch{console.error("gemini-cli-shim (version unknown)")}}async function he(){let s=[],e=await S.isInstalled();s.push({name:"gemini_cli_found",passed:e.found,message:e.found?`Gemini CLI found at ${e.path} (${e.version})`:"Gemini CLI not found in PATH"});let t=!!(process.env.GOOGLE_API_KEY||process.env.GEMINI_API_KEY);s.push({name:"api_key",passed:t,message:t?"API key found in environment":"No GOOGLE_API_KEY or GEMINI_API_KEY found"});let o=s.every(a=>a.passed),i={shim:{name:"gemini-cli-shim",version:"1.0.0"},agent:{name:"gemini-cli",version:e.version||"unknown",found:e.found},checks:s,overall:{passed:o,message:o?"All checks passed":"Some checks failed"}};console.log(JSON.stringify(i,null,2)),process.exit(o?0:1)}async function we(){let s=z(process.argv);if(s.help&&(Q(),process.exit(0)),s.version&&(fe(),process.exit(0)),s.selfTest){await he();return}s.model||(console.error("Error: --model is required"),Q(),process.exit(1));let e=await ge();e||process.exit(0);let t=J(s.model);(await S.isInstalled()).found||(console.error("Error: Gemini CLI not found in PATH"),console.error("Please install Gemini CLI: https://geminicli.com/docs/"),process.exit(1)),!process.env.GOOGLE_API_KEY&&!process.env.GEMINI_API_KEY&&(console.error("Error: No API key found"),console.error("Set GOOGLE_API_KEY or GEMINI_API_KEY environment variable"),process.exit(1));let i=!1,a=()=>{i||(i=!0,s.verbose&&console.error("[gemini-cli-shim] Received interrupt signal, exiting gracefully"),process.exit(0))};process.on("SIGINT",a),process.on("SIGTERM",a);try{let c=await V(e,{model:t,resume:s.resume,verbose:s.verbose,cwd:process.cwd(),appendSystemPrompt:s.appendSystemPrompt,debugDir:s.debugDir});process.exit(c.exitCode)}catch(c){let l=c instanceof Error?c.message:String(c);l.includes("Invalid session ID")&&(console.error(`Error: Session not found: ${s.resume}`),console.error("Use a valid session ID to resume"),process.exit(1)),await Z(l),process.exit(1)}}we().catch(s=>{console.error("Fatal error:",s),process.exit(1)});
30
+ `)}function ve(){try{let s=ge(ye,"..","package.json"),e=JSON.parse(de(s,"utf-8"));console.error(`gemini-cli-shim v${e.version}`)}catch{console.error("gemini-cli-shim (version unknown)")}}async function Se(){let s=[],e=await _.isInstalled();s.push({name:"gemini_cli_found",passed:e.found,message:e.found?`Gemini CLI found at ${e.path} (${e.version})`:"Gemini CLI not found in PATH"});let t=!!(process.env.GOOGLE_API_KEY||process.env.GEMINI_API_KEY);s.push({name:"api_key",passed:t,message:t?"API key found in environment":"No GOOGLE_API_KEY or GEMINI_API_KEY found"});let i=s.every(a=>a.passed),r={shim:{name:"gemini-cli-shim",version:"1.0.0"},agent:{name:"gemini-cli",version:e.version||"unknown",found:e.found},checks:s,overall:{passed:i,message:i?"All checks passed":"Some checks failed"}};console.log(JSON.stringify(r,null,2)),process.exit(i?0:1)}async function be(){let s=Y(process.argv.slice(2),{"-m":"--model","-r":"--resume","-v":"--verbose","-h":"--help"});if(s.help&&(te(),process.exit(0)),s.version&&(ve(),process.exit(0)),s.selfTest){await Se();return}s.model||(console.error("Error: --model is required"),te(),process.exit(1));let e=await we();e||process.exit(0);let t=V(s.model);(await _.isInstalled()).found||(console.error("Error: Gemini CLI not found in PATH"),console.error("Please install Gemini CLI: https://geminicli.com/docs/"),process.exit(1)),!process.env.GOOGLE_API_KEY&&!process.env.GEMINI_API_KEY&&(console.error("Error: No API key found"),console.error("Set GOOGLE_API_KEY or GEMINI_API_KEY environment variable"),process.exit(1));let r=!1,a=()=>{r||(r=!0,s.verbose&&console.error("[gemini-cli-shim] Received interrupt signal, exiting gracefully"),process.exit(0))};process.on("SIGINT",a),process.on("SIGTERM",a);try{let l=await ee(e,{model:t,resume:s.resume,verbose:s.verbose,cwd:process.cwd(),appendSystemPrompt:s.appendSystemPrompt,debugDir:s.debugDir,idleTimeout:s.idleTimeout});process.exit(l.exitCode)}catch(l){let c=l instanceof Error?l.message:String(l);c.includes("Invalid session ID")&&(console.error(`Error: Session not found: ${s.resume}`),console.error("Use a valid session ID to resume"),process.exit(1)),await se(c),process.exit(1)}}be().catch(s=>{console.error("Fatal error:",s),process.exit(1)});