jiranimo 1.5.0 → 1.7.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,4 +1,4 @@
1
1
  {
2
- "builtAt": "2026-04-06T19:16:27.517Z",
2
+ "builtAt": "2026-04-07T07:17:50.614Z",
3
3
  "target": "node24"
4
4
  }
package/dist/index.js CHANGED
@@ -434,7 +434,7 @@ data:
434
434
  `;return n&&(o+=`id: ${n}
435
435
  `),o+=`data: ${JSON.stringify(i)}
436
436
 
437
- `,e.enqueue(r.encode(o)),!0}catch(o){return this.onerror?.(o),!1}}handleUnsupportedRequest(){return this.onerror?.(new Error("Method not allowed.")),new Response(JSON.stringify({jsonrpc:"2.0",error:{code:-32e3,message:"Method not allowed."},id:null}),{status:405,headers:{Allow:"GET, POST, DELETE","Content-Type":"application/json"}})}async handlePostRequest(e,r){try{let i=e.headers.get("accept");if(!i?.includes("application/json")||!i.includes("text/event-stream"))return this.onerror?.(new Error("Not Acceptable: Client must accept both application/json and text/event-stream")),this.createJsonErrorResponse(406,-32e3,"Not Acceptable: Client must accept both application/json and text/event-stream");let n=e.headers.get("content-type");if(!n||!n.includes("application/json"))return this.onerror?.(new Error("Unsupported Media Type: Content-Type must be application/json")),this.createJsonErrorResponse(415,-32e3,"Unsupported Media Type: Content-Type must be application/json");let o={headers:Object.fromEntries(e.headers.entries()),url:new URL(e.url)},a;if(r?.parsedBody!==void 0)a=r.parsedBody;else try{a=await e.json()}catch{return this.onerror?.(new Error("Parse error: Invalid JSON")),this.createJsonErrorResponse(400,-32700,"Parse error: Invalid JSON")}let s;try{Array.isArray(a)?s=a.map(x=>Cy.parse(x)):s=[Cy.parse(a)]}catch{return this.onerror?.(new Error("Parse error: Invalid JSON-RPC message")),this.createJsonErrorResponse(400,-32700,"Parse error: Invalid JSON-RPC message")}let c=s.some(Ay);if(c){if(this._initialized&&this.sessionId!==void 0)return this.onerror?.(new Error("Invalid Request: Server already initialized")),this.createJsonErrorResponse(400,-32600,"Invalid Request: Server already initialized");if(s.length>1)return this.onerror?.(new Error("Invalid Request: Only one initialization request is allowed")),this.createJsonErrorResponse(400,-32600,"Invalid Request: Only one initialization request is allowed");this.sessionId=this.sessionIdGenerator?.(),this._initialized=!0,this.sessionId&&this._onsessioninitialized&&await Promise.resolve(this._onsessioninitialized(this.sessionId))}if(!c){let x=this.validateSession(e);if(x)return x;let $=this.validateProtocolVersion(e);if($)return $}if(!s.some(zn)){for(let x of s)this.onmessage?.(x,{authInfo:r?.authInfo,requestInfo:o});return new Response(null,{status:202})}let l=crypto.randomUUID(),p=s.find(x=>Ay(x)),d=p?p.params.protocolVersion:e.headers.get("mcp-protocol-version")??hS;if(this._enableJsonResponse)return new Promise(x=>{this._streamMapping.set(l,{resolveJson:x,cleanup:()=>{this._streamMapping.delete(l)}});for(let $ of s)zn($)&&this._requestToStreamMapping.set($.id,l);for(let $ of s)this.onmessage?.($,{authInfo:r?.authInfo,requestInfo:o})});let f=new TextEncoder,m,h=new ReadableStream({start:x=>{m=x},cancel:()=>{this._streamMapping.delete(l)}}),g={"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"};this.sessionId!==void 0&&(g["mcp-session-id"]=this.sessionId);for(let x of s)zn(x)&&(this._streamMapping.set(l,{controller:m,encoder:f,cleanup:()=>{this._streamMapping.delete(l);try{m.close()}catch{}}}),this._requestToStreamMapping.set(x.id,l));await this.writePrimingEvent(m,f,l,d);for(let x of s){let $,w;zn(x)&&this._eventStore&&d>="2025-11-25"&&($=()=>{this.closeSSEStream(x.id)},w=()=>{this.closeStandaloneSSEStream()}),this.onmessage?.(x,{authInfo:r?.authInfo,requestInfo:o,closeSSEStream:$,closeStandaloneSSEStream:w})}return new Response(h,{status:200,headers:g})}catch(i){return this.onerror?.(i),this.createJsonErrorResponse(400,-32700,"Parse error",{data:String(i)})}}async handleDeleteRequest(e){let r=this.validateSession(e);if(r)return r;let i=this.validateProtocolVersion(e);return i||(await Promise.resolve(this._onsessionclosed?.(this.sessionId)),await this.close(),new Response(null,{status:200}))}validateSession(e){if(this.sessionIdGenerator===void 0)return;if(!this._initialized)return this.onerror?.(new Error("Bad Request: Server not initialized")),this.createJsonErrorResponse(400,-32e3,"Bad Request: Server not initialized");let r=e.headers.get("mcp-session-id");if(!r)return this.onerror?.(new Error("Bad Request: Mcp-Session-Id header is required")),this.createJsonErrorResponse(400,-32e3,"Bad Request: Mcp-Session-Id header is required");if(r!==this.sessionId)return this.onerror?.(new Error("Session not found")),this.createJsonErrorResponse(404,-32001,"Session not found")}validateProtocolVersion(e){let r=e.headers.get("mcp-protocol-version");if(r!==null&&!Do.includes(r))return this.onerror?.(new Error(`Bad Request: Unsupported protocol version: ${r} (supported versions: ${Do.join(", ")})`)),this.createJsonErrorResponse(400,-32e3,`Bad Request: Unsupported protocol version: ${r} (supported versions: ${Do.join(", ")})`)}async close(){this._streamMapping.forEach(({cleanup:e})=>{e()}),this._streamMapping.clear(),this._requestResponseMap.clear(),this.onclose?.()}closeSSEStream(e){let r=this._requestToStreamMapping.get(e);if(!r)return;let i=this._streamMapping.get(r);i&&i.cleanup()}closeStandaloneSSEStream(){let e=this._streamMapping.get(this._standaloneSseStreamId);e&&e.cleanup()}async send(e,r){let i=r?.relatedRequestId;if((Vr(e)||Uo(e))&&(i=e.id),i===void 0){if(Vr(e)||Uo(e))throw new Error("Cannot send a response on a standalone SSE stream unless resuming a previous client request");let a;this._eventStore&&(a=await this._eventStore.storeEvent(this._standaloneSseStreamId,e));let s=this._streamMapping.get(this._standaloneSseStreamId);if(s===void 0)return;s.controller&&s.encoder&&this.writeSSEEvent(s.controller,s.encoder,e,a);return}let n=this._requestToStreamMapping.get(i);if(!n)throw new Error(`No connection established for request ID: ${String(i)}`);let o=this._streamMapping.get(n);if(!this._enableJsonResponse&&o?.controller&&o?.encoder){let a;this._eventStore&&(a=await this._eventStore.storeEvent(n,e)),this.writeSSEEvent(o.controller,o.encoder,e,a)}if(Vr(e)||Uo(e)){this._requestResponseMap.set(i,e);let a=Array.from(this._requestToStreamMapping.entries()).filter(([c,u])=>u===n).map(([c])=>c);if(a.every(c=>this._requestResponseMap.has(c))){if(!o)throw new Error(`No connection established for request ID: ${String(i)}`);if(this._enableJsonResponse&&o.resolveJson){let c={"Content-Type":"application/json"};this.sessionId!==void 0&&(c["mcp-session-id"]=this.sessionId);let u=a.map(l=>this._requestResponseMap.get(l));u.length===1?o.resolveJson(new Response(JSON.stringify(u[0]),{status:200,headers:c})):o.resolveJson(new Response(JSON.stringify(u),{status:200,headers:c}))}else o.cleanup();for(let c of a)this._requestResponseMap.delete(c),this._requestToStreamMapping.delete(c)}}}};var Kf=class{constructor(e={}){this._requestContext=new WeakMap,this._webStandardTransport=new Wf(e),this._requestListener=e0(async r=>{let i=this._requestContext.get(r);return this._webStandardTransport.handleRequest(r,{authInfo:i?.authInfo,parsedBody:i?.parsedBody})},{overrideGlobalObjects:!1})}get sessionId(){return this._webStandardTransport.sessionId}set onclose(e){this._webStandardTransport.onclose=e}get onclose(){return this._webStandardTransport.onclose}set onerror(e){this._webStandardTransport.onerror=e}get onerror(){return this._webStandardTransport.onerror}set onmessage(e){this._webStandardTransport.onmessage=e}get onmessage(){return this._webStandardTransport.onmessage}async start(){return this._webStandardTransport.start()}async close(){return this._webStandardTransport.close()}async send(e,r){return this._webStandardTransport.send(e,r)}async handleRequest(e,r,i){let n=e.auth;await e0(async a=>this._webStandardTransport.handleRequest(a,{authInfo:n,parsedBody:i}),{overrideGlobalObjects:!1})(e,r)}closeSSEStream(e){this._webStandardTransport.closeSSEStream(e)}closeStandaloneSSEStream(){this._webStandardTransport.closeStandaloneSSEStream()}};import{writeFileSync as pZ,unlinkSync as dZ,readFileSync as fZ}from"node:fs";import{join as mI}from"node:path";var mZ="7922f663cfcfe9b4b0c3119c2b61b7d8";async function hZ(t){let r=fZ(t).toString("base64"),i=new URLSearchParams({key:mZ,image:r}),n=await fetch("https://api.imgbb.com/1/upload",{method:"POST",body:i});if(!n.ok)throw new Error(`imgbb upload failed: ${n.status} ${await n.text()}`);return(await n.json()).data.url}function hI(t){return async(e,r)=>{let i=new Vf({name:"jiranimo",version:"1.5.0"});i.tool("jiranimo_progress",{task_key:G.string(),message:G.string()},async({task_key:o,message:a})=>(t.reportProgress(o,a),{content:[{type:"text",text:"ok"}]})),i.tool("jiranimo_report_pr",{task_key:G.string(),pr_url:G.string(),pr_number:G.number().int(),branch_name:G.string()},async({task_key:o,pr_url:a,pr_number:s,branch_name:c})=>(t.reportPr(o,a,s,c),{content:[{type:"text",text:"PR recorded"}]})),i.tool("jiranimo_complete",{task_key:G.string(),summary:G.string()},async({task_key:o,summary:a})=>(t.completeViaAgent(o,a),{content:[{type:"text",text:"Task marked complete"}]})),i.tool("jiranimo_fail",{task_key:G.string(),error_message:G.string()},async({task_key:o,error_message:a})=>(t.failViaAgent(o,a),{content:[{type:"text",text:"Task marked failed"}]})),i.tool("jiranimo_screenshot_failed",{task_key:G.string(),reason:G.string()},async({task_key:o,reason:a})=>(t.reportScreenshotFailed(o,a),{content:[{type:"text",text:"Screenshot failure recorded"}]})),i.tool("jiranimo_upload_screenshot",{file_path:G.string()},async({file_path:o})=>({content:[{type:"text",text:await hZ(o)}]}));let n=new Kf({sessionIdGenerator:void 0});await i.connect(n),await n.handleRequest(e,r,e.body),r.on("close",()=>{n.close(),i.close()})}}function gI(t,e){let r={mcpServers:{jiranimo:{type:"http",url:`http://127.0.0.1:${e}/mcp`},playwright:{type:"stdio",command:"npx",args:["@playwright/mcp@latest","--headless"]}}};pZ(mI(t,".mcp.json"),JSON.stringify(r,null,2))}function vI(t){try{dZ(mI(t,".mcp.json"))}catch{}}import{appendFileSync as gZ,mkdirSync as vZ}from"node:fs";import{homedir as yZ}from"node:os";import{dirname as xZ,join as bZ,resolve as _Z}from"node:path";var wZ={level:"info",logHttpRequests:!1,logHttpBodies:!1,logClaudeRawOutput:!1},yI={debug:10,info:20,warn:30,error:40},t0=class t{config;filePath;scope;constructor(e,r){this.config=Lc(e);let i=e?.logsDir??_Z(yZ(),".jiranimo","logs");vZ(i,{recursive:!0}),this.filePath=bZ(i,"server.log"),this.scope=r}child(e){let r=this.scope?`${this.scope}:${e}`:e;return new t({logsDir:xZ(this.filePath),logging:this.config},r)}debug(e,r){this.write("debug",e,r)}info(e,r){this.write("info",e,r)}warn(e,r){this.write("warn",e,r)}error(e,r){this.write("error",e,r)}isConsoleLevelEnabled(e){return yI[e]>=yI[this.config.level]}getConfig(){return this.config}write(e,r,i){if(!this.isConsoleLevelEnabled(e))return;let n=kZ(e,this.scope,r,i),o=$Z(n);try{gZ(this.filePath,`${o}
437
+ `,e.enqueue(r.encode(o)),!0}catch(o){return this.onerror?.(o),!1}}handleUnsupportedRequest(){return this.onerror?.(new Error("Method not allowed.")),new Response(JSON.stringify({jsonrpc:"2.0",error:{code:-32e3,message:"Method not allowed."},id:null}),{status:405,headers:{Allow:"GET, POST, DELETE","Content-Type":"application/json"}})}async handlePostRequest(e,r){try{let i=e.headers.get("accept");if(!i?.includes("application/json")||!i.includes("text/event-stream"))return this.onerror?.(new Error("Not Acceptable: Client must accept both application/json and text/event-stream")),this.createJsonErrorResponse(406,-32e3,"Not Acceptable: Client must accept both application/json and text/event-stream");let n=e.headers.get("content-type");if(!n||!n.includes("application/json"))return this.onerror?.(new Error("Unsupported Media Type: Content-Type must be application/json")),this.createJsonErrorResponse(415,-32e3,"Unsupported Media Type: Content-Type must be application/json");let o={headers:Object.fromEntries(e.headers.entries()),url:new URL(e.url)},a;if(r?.parsedBody!==void 0)a=r.parsedBody;else try{a=await e.json()}catch{return this.onerror?.(new Error("Parse error: Invalid JSON")),this.createJsonErrorResponse(400,-32700,"Parse error: Invalid JSON")}let s;try{Array.isArray(a)?s=a.map(x=>Cy.parse(x)):s=[Cy.parse(a)]}catch{return this.onerror?.(new Error("Parse error: Invalid JSON-RPC message")),this.createJsonErrorResponse(400,-32700,"Parse error: Invalid JSON-RPC message")}let c=s.some(Ay);if(c){if(this._initialized&&this.sessionId!==void 0)return this.onerror?.(new Error("Invalid Request: Server already initialized")),this.createJsonErrorResponse(400,-32600,"Invalid Request: Server already initialized");if(s.length>1)return this.onerror?.(new Error("Invalid Request: Only one initialization request is allowed")),this.createJsonErrorResponse(400,-32600,"Invalid Request: Only one initialization request is allowed");this.sessionId=this.sessionIdGenerator?.(),this._initialized=!0,this.sessionId&&this._onsessioninitialized&&await Promise.resolve(this._onsessioninitialized(this.sessionId))}if(!c){let x=this.validateSession(e);if(x)return x;let $=this.validateProtocolVersion(e);if($)return $}if(!s.some(zn)){for(let x of s)this.onmessage?.(x,{authInfo:r?.authInfo,requestInfo:o});return new Response(null,{status:202})}let l=crypto.randomUUID(),p=s.find(x=>Ay(x)),d=p?p.params.protocolVersion:e.headers.get("mcp-protocol-version")??hS;if(this._enableJsonResponse)return new Promise(x=>{this._streamMapping.set(l,{resolveJson:x,cleanup:()=>{this._streamMapping.delete(l)}});for(let $ of s)zn($)&&this._requestToStreamMapping.set($.id,l);for(let $ of s)this.onmessage?.($,{authInfo:r?.authInfo,requestInfo:o})});let f=new TextEncoder,m,h=new ReadableStream({start:x=>{m=x},cancel:()=>{this._streamMapping.delete(l)}}),g={"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"};this.sessionId!==void 0&&(g["mcp-session-id"]=this.sessionId);for(let x of s)zn(x)&&(this._streamMapping.set(l,{controller:m,encoder:f,cleanup:()=>{this._streamMapping.delete(l);try{m.close()}catch{}}}),this._requestToStreamMapping.set(x.id,l));await this.writePrimingEvent(m,f,l,d);for(let x of s){let $,w;zn(x)&&this._eventStore&&d>="2025-11-25"&&($=()=>{this.closeSSEStream(x.id)},w=()=>{this.closeStandaloneSSEStream()}),this.onmessage?.(x,{authInfo:r?.authInfo,requestInfo:o,closeSSEStream:$,closeStandaloneSSEStream:w})}return new Response(h,{status:200,headers:g})}catch(i){return this.onerror?.(i),this.createJsonErrorResponse(400,-32700,"Parse error",{data:String(i)})}}async handleDeleteRequest(e){let r=this.validateSession(e);if(r)return r;let i=this.validateProtocolVersion(e);return i||(await Promise.resolve(this._onsessionclosed?.(this.sessionId)),await this.close(),new Response(null,{status:200}))}validateSession(e){if(this.sessionIdGenerator===void 0)return;if(!this._initialized)return this.onerror?.(new Error("Bad Request: Server not initialized")),this.createJsonErrorResponse(400,-32e3,"Bad Request: Server not initialized");let r=e.headers.get("mcp-session-id");if(!r)return this.onerror?.(new Error("Bad Request: Mcp-Session-Id header is required")),this.createJsonErrorResponse(400,-32e3,"Bad Request: Mcp-Session-Id header is required");if(r!==this.sessionId)return this.onerror?.(new Error("Session not found")),this.createJsonErrorResponse(404,-32001,"Session not found")}validateProtocolVersion(e){let r=e.headers.get("mcp-protocol-version");if(r!==null&&!Do.includes(r))return this.onerror?.(new Error(`Bad Request: Unsupported protocol version: ${r} (supported versions: ${Do.join(", ")})`)),this.createJsonErrorResponse(400,-32e3,`Bad Request: Unsupported protocol version: ${r} (supported versions: ${Do.join(", ")})`)}async close(){this._streamMapping.forEach(({cleanup:e})=>{e()}),this._streamMapping.clear(),this._requestResponseMap.clear(),this.onclose?.()}closeSSEStream(e){let r=this._requestToStreamMapping.get(e);if(!r)return;let i=this._streamMapping.get(r);i&&i.cleanup()}closeStandaloneSSEStream(){let e=this._streamMapping.get(this._standaloneSseStreamId);e&&e.cleanup()}async send(e,r){let i=r?.relatedRequestId;if((Vr(e)||Uo(e))&&(i=e.id),i===void 0){if(Vr(e)||Uo(e))throw new Error("Cannot send a response on a standalone SSE stream unless resuming a previous client request");let a;this._eventStore&&(a=await this._eventStore.storeEvent(this._standaloneSseStreamId,e));let s=this._streamMapping.get(this._standaloneSseStreamId);if(s===void 0)return;s.controller&&s.encoder&&this.writeSSEEvent(s.controller,s.encoder,e,a);return}let n=this._requestToStreamMapping.get(i);if(!n)throw new Error(`No connection established for request ID: ${String(i)}`);let o=this._streamMapping.get(n);if(!this._enableJsonResponse&&o?.controller&&o?.encoder){let a;this._eventStore&&(a=await this._eventStore.storeEvent(n,e)),this.writeSSEEvent(o.controller,o.encoder,e,a)}if(Vr(e)||Uo(e)){this._requestResponseMap.set(i,e);let a=Array.from(this._requestToStreamMapping.entries()).filter(([c,u])=>u===n).map(([c])=>c);if(a.every(c=>this._requestResponseMap.has(c))){if(!o)throw new Error(`No connection established for request ID: ${String(i)}`);if(this._enableJsonResponse&&o.resolveJson){let c={"Content-Type":"application/json"};this.sessionId!==void 0&&(c["mcp-session-id"]=this.sessionId);let u=a.map(l=>this._requestResponseMap.get(l));u.length===1?o.resolveJson(new Response(JSON.stringify(u[0]),{status:200,headers:c})):o.resolveJson(new Response(JSON.stringify(u),{status:200,headers:c}))}else o.cleanup();for(let c of a)this._requestResponseMap.delete(c),this._requestToStreamMapping.delete(c)}}}};var Kf=class{constructor(e={}){this._requestContext=new WeakMap,this._webStandardTransport=new Wf(e),this._requestListener=e0(async r=>{let i=this._requestContext.get(r);return this._webStandardTransport.handleRequest(r,{authInfo:i?.authInfo,parsedBody:i?.parsedBody})},{overrideGlobalObjects:!1})}get sessionId(){return this._webStandardTransport.sessionId}set onclose(e){this._webStandardTransport.onclose=e}get onclose(){return this._webStandardTransport.onclose}set onerror(e){this._webStandardTransport.onerror=e}get onerror(){return this._webStandardTransport.onerror}set onmessage(e){this._webStandardTransport.onmessage=e}get onmessage(){return this._webStandardTransport.onmessage}async start(){return this._webStandardTransport.start()}async close(){return this._webStandardTransport.close()}async send(e,r){return this._webStandardTransport.send(e,r)}async handleRequest(e,r,i){let n=e.auth;await e0(async a=>this._webStandardTransport.handleRequest(a,{authInfo:n,parsedBody:i}),{overrideGlobalObjects:!1})(e,r)}closeSSEStream(e){this._webStandardTransport.closeSSEStream(e)}closeStandaloneSSEStream(){this._webStandardTransport.closeStandaloneSSEStream()}};import{writeFileSync as pZ,unlinkSync as dZ,readFileSync as fZ}from"node:fs";import{join as mI}from"node:path";var mZ="7922f663cfcfe9b4b0c3119c2b61b7d8";async function hZ(t){let r=fZ(t).toString("base64"),i=new URLSearchParams({key:mZ,image:r}),n=await fetch("https://api.imgbb.com/1/upload",{method:"POST",body:i});if(!n.ok)throw new Error(`imgbb upload failed: ${n.status} ${await n.text()}`);return(await n.json()).data.url}function hI(t){return async(e,r)=>{let i=new Vf({name:"jiranimo",version:"1.7.0"});i.tool("jiranimo_progress",{task_key:G.string(),message:G.string()},async({task_key:o,message:a})=>(t.reportProgress(o,a),{content:[{type:"text",text:"ok"}]})),i.tool("jiranimo_report_pr",{task_key:G.string(),pr_url:G.string(),pr_number:G.number().int(),branch_name:G.string()},async({task_key:o,pr_url:a,pr_number:s,branch_name:c})=>(t.reportPr(o,a,s,c),{content:[{type:"text",text:"PR recorded"}]})),i.tool("jiranimo_complete",{task_key:G.string(),summary:G.string()},async({task_key:o,summary:a})=>(t.completeViaAgent(o,a),{content:[{type:"text",text:"Task marked complete"}]})),i.tool("jiranimo_fail",{task_key:G.string(),error_message:G.string()},async({task_key:o,error_message:a})=>(t.failViaAgent(o,a),{content:[{type:"text",text:"Task marked failed"}]})),i.tool("jiranimo_screenshot_failed",{task_key:G.string(),reason:G.string()},async({task_key:o,reason:a})=>(t.reportScreenshotFailed(o,a),{content:[{type:"text",text:"Screenshot failure recorded"}]})),i.tool("jiranimo_upload_screenshot",{file_path:G.string()},async({file_path:o})=>({content:[{type:"text",text:await hZ(o)}]}));let n=new Kf({sessionIdGenerator:void 0});await i.connect(n),await n.handleRequest(e,r,e.body),r.on("close",()=>{n.close(),i.close()})}}function gI(t,e){let r={mcpServers:{jiranimo:{type:"http",url:`http://127.0.0.1:${e}/mcp`},playwright:{type:"stdio",command:"npx",args:["@playwright/mcp@latest","--headless"]}}};pZ(mI(t,".mcp.json"),JSON.stringify(r,null,2))}function vI(t){try{dZ(mI(t,".mcp.json"))}catch{}}import{appendFileSync as gZ,mkdirSync as vZ}from"node:fs";import{homedir as yZ}from"node:os";import{dirname as xZ,join as bZ,resolve as _Z}from"node:path";var wZ={level:"info",logHttpRequests:!1,logHttpBodies:!1,logClaudeRawOutput:!1},yI={debug:10,info:20,warn:30,error:40},t0=class t{config;filePath;scope;constructor(e,r){this.config=Lc(e);let i=e?.logsDir??_Z(yZ(),".jiranimo","logs");vZ(i,{recursive:!0}),this.filePath=bZ(i,"server.log"),this.scope=r}child(e){let r=this.scope?`${this.scope}:${e}`:e;return new t({logsDir:xZ(this.filePath),logging:this.config},r)}debug(e,r){this.write("debug",e,r)}info(e,r){this.write("info",e,r)}warn(e,r){this.write("warn",e,r)}error(e,r){this.write("error",e,r)}isConsoleLevelEnabled(e){return yI[e]>=yI[this.config.level]}getConfig(){return this.config}write(e,r,i){if(!this.isConsoleLevelEnabled(e))return;let n=kZ(e,this.scope,r,i),o=$Z(n);try{gZ(this.filePath,`${o}
438
438
  `,"utf-8")}catch{}if(e==="error"){console.error(n);return}if(e==="warn"){console.warn(n);return}console.log(n)}};function $Z(t){return t.replace(/\u001B\[[0-9;]*m/g,"")}function Ln(t,e){return new t0(t,e)}function Lc(t){return{...wZ,...t?.logging??{}}}function xI(t){return[/chrome\/updater\//i,/GoogleUpdater/i,/VERBOSE\d?:chrome\//i].some(e=>e.test(t))}function kZ(t,e,r,i){let n=[new Date().toISOString(),t.toUpperCase()];e&&n.push(`[${e}]`),n.push(r);let o=SZ(i);return o&&n.push(o),n.join(" ")}function SZ(t){if(!t)return"";let e=Object.entries(t).filter(([,r])=>r!==void 0);return e.length===0?"":JSON.stringify(Object.fromEntries(e))}import{execFile as EZ}from"node:child_process";var TZ=10*1024*1024;function IZ(t){let e;try{e=new URL(t)}catch{throw new Error(`Invalid PR URL: ${t}`)}let r=e.pathname.match(/^\/([^/]+)\/([^/]+)\/pull\/(\d+)(?:\/|$)/);if(!r)throw new Error(`Unsupported PR URL: ${t}`);return{owner:r[1],repo:r[2],prNumber:Number(r[3])}}function _I(t,e){if(typeof e.id!="number")return;let r=e.updated_at??e.created_at;return r?`${t}:${e.id}:${r}`:void 0}function PZ(t){if(typeof t.id!="number"||typeof t.body!="string"||t.body.trim().length===0)return;let e=_I("review",t);if(e)return{id:t.id,fingerprint:e,kind:"review",author:t.user?.login||"unknown",body:t.body,path:typeof t.path=="string"?t.path:void 0,line:typeof t.line=="number"?t.line:typeof t.original_line=="number"?t.original_line:void 0,url:typeof t.html_url=="string"?t.html_url:void 0,created:typeof t.created_at=="string"?t.created_at:void 0,updated:typeof t.updated_at=="string"?t.updated_at:void 0}}function zZ(t){if(typeof t.id!="number"||typeof t.body!="string"||t.body.trim().length===0)return;let e=_I("conversation",t);if(e)return{id:t.id,fingerprint:e,kind:"conversation",author:t.user?.login||"unknown",body:t.body,url:typeof t.html_url=="string"?t.html_url:void 0,created:typeof t.created_at=="string"?t.created_at:void 0,updated:typeof t.updated_at=="string"?t.updated_at:void 0}}async function bI(t){let e=await new Promise((n,o)=>{EZ("gh",["api",t,"--paginate","--slurp"],{maxBuffer:TZ},(a,s)=>{if(a){o(a);return}n(s)})}),r=JSON.parse(e);return(Array.isArray(r)?r:[]).flatMap(n=>Array.isArray(n)?n:[])}async function r0(t,e=[]){let{owner:r,repo:i,prNumber:n}=IZ(t),o=new Set(e),[a,s]=await Promise.all([bI(`repos/${r}/${i}/pulls/${n}/comments`),bI(`repos/${r}/${i}/issues/${n}/comments`)]);return[...a.map(PZ),...s.map(zZ)].filter(c=>!!c&&!o.has(c.fingerprint)).sort((c,u)=>{let l=c.updated??c.created??"",p=u.updated??u.created??"";return l.localeCompare(p)})}var n0=2e4;async function i0(t,e,r,i){let n=jZ(t);if(!n.trim())return"No conversation content found in log.";let o=["You are summarizing an AI agent execution log for a developer following task progress.",`Task: "${e}"`,"","Write a concise but sufficiently detailed summary that covers:","1. The main steps the agent took","2. Important findings, decisions, or deviations","3. Any problems or failures encountered","4. The final outcome","","Rules:","- Use 5-12 bullet points.","- Focus on task-specific implementation details, not filler.","- Prefer what changed in the repo, what was discovered, and how the task was solved.","- Do not spend bullets on routine workflow boilerplate such as worktree setup/cleanup, generic git add/commit/push, PR creation, or Jira status/reporting unless something unusual happened there.","- Mention concrete files, commands, tools, or errors when they materially explain the implementation.","- Do not mention token usage, compaction, or transcript mechanics.","- Do not invent details that are not in the log.","","Execution log:",OZ(n)].join(`
439
439
  `),a=await qr({prompt:o,cwd:i,config:r});if(!a.resultText.trim())throw new Error("No compact log generated");return a.resultText.trim()}function jZ(t){let e=t.split(`
440
440
  `).filter(i=>i.trim()),r=[];for(let i of e){let n;try{n=JSON.parse(i)}catch{continue}switch(n.type){case"assistant":{let o=n.message?.content??[];for(let a of o)if(a.type==="text"&&a.text)r.push(`[Claude] ${a.text}`);else if(a.type==="tool_use"){let s=a.name??"unknown";if(CZ(s,a.input))continue;let c=RZ(a.input);r.push(`[Tool] ${s}${c?`(${c})`:""}`)}break}case"result":{let o=typeof n.cost_usd=="number"?` (cost: $${n.cost_usd.toFixed(4)})`:"",a=n.result?`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jiranimo",
3
- "version": "1.5.0",
3
+ "version": "1.7.0",
4
4
  "type": "module",
5
5
  "description": "Local automation server for the Jiranimo Jira extension",
6
6
  "main": "./dist/index.js",