opencode-metis 0.1.7 → 0.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/plugin.cjs CHANGED
@@ -1,4 +1,4 @@
1
- "use strict";var P=Object.defineProperty;var X=Object.getOwnPropertyDescriptor;var Q=Object.getOwnPropertyNames;var ee=Object.prototype.hasOwnProperty;var te=(e,t)=>{for(var n in t)P(e,n,{get:t[n],enumerable:!0})},ne=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of Q(t))!ee.call(e,o)&&o!==n&&P(e,o,{get:()=>t[o],enumerable:!(r=X(t,o))||r.enumerable});return e};var re=e=>ne(P({},"__esModule",{value:!0}),e);var Xe={};te(Xe,{default:()=>V});module.exports=re(Xe);var S=require("node:fs");var x=require("node:os"),u=require("node:path"),v=41777,O="127.0.0.1",oe=(0,u.join)((0,x.homedir)(),".config","opencode"),et=(0,u.join)(oe,"opencode.json"),d=(0,u.join)((0,x.homedir)(),".config","opencode","memory"),ie="memory.db",se="settings.json",h=(0,u.join)(d,"worker.pid");var tt=(0,u.join)(d,ie),C=(0,u.join)(d,se),nt=(0,u.join)(d,"logs"),rt=(0,u.join)(d,"models"),ot=(0,u.join)(d,"vector-db");var R={workerPort:v,workerBind:O,chromaDbUrl:"http://localhost:8000",chromaDbEnabled:!0,recencyWindowDays:90,retentionDays:365,tddEnabled:!0,fileLengthWarn:300,fileLengthCritical:500,testFilePatterns:["*.test.ts","*.spec.ts","*_test.go","test_*.py"],toolRedirectRules:[],aiProvider:null,aiModel:null,aiCompressionTimeoutMs:15e3,aiCompressionMaxRetries:3,aiSkipTools:[],secretDetectionEnabled:!0,secretPatterns:[],contextTokenBudget:2e3,notificationsEnabled:!1},g=null;function m(){if(g!==null)return g;if(!(0,S.existsSync)(C))return g={...R},g;try{let e=(0,S.readFileSync)(C,"utf-8"),t=JSON.parse(e);return g={...R,...t},g}catch{return g={...R},g}}function k(){let e=m();return`http://${e.workerBind}:${e.workerPort}`}var f=require("node:fs"),A=require("node:os"),b=require("node:path");var F=require("node:child_process");function c(e){process.platform==="darwin"&&m().notificationsEnabled&&(0,F.execFile)("osascript",["-e",`display notification "${e}" with title "opencode"`])}var ae=5e3;function ce(){return process.env.OPENCODE_SESSIONS_DIR??(0,b.join)((0,A.homedir)(),".config","opencode","sessions")}function le(e){return(0,b.join)(ce(),"sessions",e,"pre-compact-state.json")}function ue(e){let t=["[Memory Context Restored After Compaction]"];return e.activePlan&&t.push(`Active plan: ${e.activePlan}`),e.currentTask&&t.push(`Current task: ${e.currentTask}`),e.status&&t.push(`Status: ${e.status}`),e.summary&&t.push(`Recent context: ${e.summary}`),t.join(`
2
- `)}async function pe(e,t,n){let r=`${e}/api/context/inject?project=${encodeURIComponent(n)}`,o={};t!==null&&(o.Authorization=`Bearer ${t}`);let i=await fetch(r,{headers:o,signal:AbortSignal.timeout(ae)});return i.ok?(await i.json()).context??null:null}function ge(e){let t=le(e);if(!(0,f.existsSync)(t))return null;try{let n=(0,f.readFileSync)(t,"utf-8"),r=JSON.parse(n);return(0,f.unlinkSync)(t),r}catch{return null}}function w(e,t){e.messages=e.messages??[],e.messages.push({role:"user",content:t})}async function $(e,t,n,r,o){c("Session compacted!");try{let i=null;try{i=await pe(t,n,e.project.name)}catch(a){if(a instanceof TypeError)throw a}if(i){w(o,i);return}let s=ge(r.sessionId);if(s){let a=ue(s);w(o,a)}}catch(i){e.client.app.log("warn","Compacted state restore failed",{error:i instanceof Error?i.message:String(i),sessionId:r.sessionId})}}var E=require("node:fs"),j=require("node:os"),T=require("node:path");var me=5e3;function de(){return process.env.OPENCODE_SESSIONS_DIR??(0,T.join)((0,j.homedir)(),".config","opencode","sessions")}function fe(e){return{sessionId:e.sessionId,activePlan:e.context?.activePlan??null,currentTask:e.context?.currentTask??null,summary:e.context?.summary??null,timestamp:new Date().toISOString(),type:"compaction-state"}}async function ye(e,t,n){try{let r={"Content-Type":"application/json"};return t!==null&&(r.Authorization=`Bearer ${t}`),(await fetch(`${e}/api/memory/save`,{method:"POST",headers:r,body:JSON.stringify(n),signal:AbortSignal.timeout(me)})).ok}catch{return!1}}function he(e,t){let n=(0,T.join)(de(),"sessions",e);(0,E.mkdirSync)(n,{recursive:!0});let r=(0,T.join)(n,"pre-compact-state.json");(0,E.writeFileSync)(r,JSON.stringify(t,null,2),"utf-8")}async function D(e,t,n,r,o){c("Session compacting...");let i=fe(r);if(!await ye(t,n,i))try{he(r.sessionId,i)}catch(a){e.client.app.log("warn","Failed to write compaction fallback file",{error:a instanceof Error?a.message:String(a),sessionId:r.sessionId})}}var M=require("node:fs"),l=require("node:path");var Se=300,Te=500,Ee=["*.test.ts","*.spec.ts","*_test.go","test_*.py"];function Pe(e,t){let n=t.replace(/[.+^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*");return new RegExp(`^${n}$`).test(e)}function xe(e,t){let n=(0,l.basename)(e);return t.some(r=>Pe(n,r))}function Ce(e,t){let n=(0,l.dirname)(e),r=(0,l.extname)(e),o=(0,l.basename)(e,r),i=[];for(let s of t)if(s.startsWith("*.")){let a=s.slice(1);i.push((0,l.join)(n,`${o}${a}`))}else if(s.endsWith("*")){let a=s.slice(0,-1);i.push((0,l.join)(n,`${a}${o}${r}`))}return i}function _(e,t){e.messages=e.messages??[],e.messages.push({role:"system",content:t})}function Re(e,t,n,r){if(xe(t,n))return;let o=Ce(t,n),i=e.project.root;o.some(a=>{let p=a.startsWith("/")?a:(0,l.join)(i,a);return(0,M.existsSync)(p)})||_(r,`\u26A0\uFE0F TDD Warning: No test file found for ${t}. Consider writing tests first (Red-Green-Refactor).`)}function be(e,t,n,r,o){if(t>r){_(o,`\u{1F6A8} File Length Critical: ${e} has ${t} lines. This file should be refactored.`);return}t>n&&_(o,`\u26A0\uFE0F File Length Warning: ${e} has ${t} lines. Consider splitting this file.`)}async function N(e,t,n,r){try{c(`File edited: ${n.filePath}`);let o=m(),i=n.testFilePatterns??o.testFilePatterns??Ee,s=n.fileLengthWarn??o.fileLengthWarn??Se,a=n.fileLengthCritical??o.fileLengthCritical??Te;Re(e,n.filePath,i,r);let p=n.lineCount??0;be(n.filePath,p,s,a,r)}catch(o){e.client.app.log("warn","File edited check failed",{error:o instanceof Error?o.message:String(o),filePath:n.filePath})}}var _e=15e3;function Ie(e){let{context:t}=e;return t?!!(t.requested||t.investigated||t.learned||t.completed):!1}function ve(e){let t=e.context??{};return["Session Summary:",`Requested: ${t.requested??"Not specified"}`,`Investigated: ${t.investigated??"Not specified"}`,`Learned: ${t.learned??"Not specified"}`,`Completed: ${t.completed??"Not specified"}`].join(`
3
- `)}async function L(e,t,n,r,o){if(c("Session idle"),!Ie(r))return;let i={"Content-Type":"application/json"};n!==null&&(i.Authorization=`Bearer ${n}`);try{let s=await fetch(`${t}/api/memory/save`,{method:"POST",headers:i,body:JSON.stringify({type:"session-summary",title:`Session Summary: ${r.sessionId}`,text:ve(r),project:e.project.name}),signal:AbortSignal.timeout(_e)});s.ok||e.client.app.log("warn","Failed to save session summary",{status:s.status})}catch(s){e.client.app.log("warn","Session summary save failed",{error:s instanceof Error?s.message:String(s)})}}var Oe=3e3;function ke(e){let t={};return e!==null&&(t.Authorization=`Bearer ${e}`),t}async function U(e,t){return fetch(e,{headers:ke(t),signal:AbortSignal.timeout(Oe)})}async function B(e,t,n,r,o,i){c("Session started!");let s=`${t}/api/context/inject?project=${encodeURIComponent(e.project.name)}`;try{let a=await U(s,n);if(a.status===401&&i!==void 0){let y=i();a=await U(s,y)}if(!a.ok){e.client.app.log("warn","Failed to load memory context",{status:a.status});return}let p=await a.json();p.context&&(o.messages=o.messages??[],o.messages.push({role:"system",content:p.context}))}catch(a){e.client.app.log("warn","Memory context injection failed",{error:a instanceof Error?a.message:String(a)})}}var Fe=15e3,we=200;async function z(e,t,n,r,o,i){c(`Tool completed: ${o.tool}`),Ae(e,t,n,r,o,i).catch(s=>{e.client.app.log("warn","Observation capture failed",{error:s instanceof Error?s.message:String(s)})})}async function Ae(e,t,n,r,o,i){let s=`Tool ${o.tool}: ${$e(o,i)}`,a=`${o.tool} execution`,p={text:r.sanitize(s),title:r.sanitize(a),project:e.project.name},y={"Content-Type":"application/json"};n!==null&&(y.Authorization=`Bearer ${n}`),await fetch(`${t}/api/memory/save`,{method:"POST",headers:y,body:JSON.stringify(p),signal:AbortSignal.timeout(Fe)})}function $e(e,t){let n=t.output??t.error??"",r=je(e.input),o=n.slice(0,we).trim();return r&&o?`${r} -> ${o}`:r||o||"(no details)"}function je(e){let t=Object.entries(e);return t.length===0?"":t.map(([n,r])=>`${n}=${String(r).slice(0,80)}`).join(", ")}function De(){let e=process.env.MEMORY_TOOL_REDIRECT_RULES;if(e!==void 0)try{return JSON.parse(e)}catch{return[]}return m().toolRedirectRules}function Me(e){if(typeof e!="object"||e===null)return!1;let t=e;return typeof t.tool=="string"&&(t.action==="deny"||t.action==="redirect")}function Ne(e){return e.message??`Tool '${e.tool}' is blocked by project configuration.`}function Le(e){let t=e.message??`Tool '${e.tool}' has been redirected.`;return e.alternative?`${t} Suggested alternative: ${e.alternative}.`:t}function Ue(e,t){t.blocked=!0,t.messages=[{role:"user",content:Ne(e)}]}function Be(e,t){t.messages=[{role:"user",content:Le(e)}]}async function W(e,t,n,r){c(`Tool executing: ${n.tool}`);let o=De();for(let i of o)try{if(!Me(i))throw new Error("Invalid rule: tool must be a string and action must be 'deny' or 'redirect'");if(i.tool!==n.tool)continue;i.action==="deny"?Ue(i,r):Be(i,r);return}catch(s){e.client.app.log("warn","Tool redirect rule evaluation failed",{error:s instanceof Error?s.message:String(s),rule:JSON.stringify(i)})}}var H=require("node:fs");function ze(e){return typeof e=="object"&&e!==null&&"token"in e&&typeof e.token=="string"}function I(e){try{let t=(0,H.readFileSync)(e,"utf-8");if(t.trim().length===0)return null;let n=JSON.parse(t);return ze(n)?n.token:null}catch{return null}}var G=[{name:"aws_access_key",pattern:/AKIA[0-9A-Z]{16}/g},{name:"github_pat",pattern:/ghp_[a-zA-Z0-9]{36}/g},{name:"github_oauth",pattern:/gho_[a-zA-Z0-9]{36}/g},{name:"anthropic_key",pattern:/sk-ant-[a-zA-Z0-9\-_]{20,}/g},{name:"openai_key",pattern:/sk-[a-zA-Z0-9]{20,}/g},{name:"jwt_token",pattern:/eyJ[a-zA-Z0-9_-]+\.eyJ[a-zA-Z0-9_-]+\.[a-zA-Z0-9_-]+/g},{name:"pem_private_key",pattern:/-----BEGIN (RSA |EC |OPENSSH )?PRIVATE KEY-----/g},{name:"generic_api_key",pattern:/(?:api[_-]?key|token|secret|password)\s*[:=]\s*['"]?([a-zA-Z0-9\-_]{20,})['"]?/gi}];function We(e,t=G){if(!e)return e;let n=e;for(let{pattern:r}of t)r.lastIndex=0,n=n.replace(r,"[REDACTED]");return n}function J(e=[]){let t=[...G,...e];return n=>We(n,t)}var He=/<private>[\s\S]*?<\/private>/gi;function q(e){return e.replace(He,"")}function K(e={}){let{additionalSecretPatterns:t=[],secretDetectionEnabled:n=!0}=e,r=J(t);return{sanitize(o){let i=q(o);return n?r(i):i}}}function Z(e,t,n){return[Ge(e,t,n),Je(e,t,n)]}function Ge(e,t,n){return{name:"memory_search",description:"Search memory observations by topic or keyword",parameters:{query:{type:"string",description:"The search query or topic to look up in memory",required:!0},limit:{type:"number",description:"Maximum number of results to return (default 20)"},project:{type:"string",description:"Filter results to a specific project name"}},execute:r=>qe(e,t,n,r)}}function Je(e,t,n){return{name:"memory_save",description:"Save an observation to memory for future reference",parameters:{text:{type:"string",description:"The observation text to save to memory",required:!0},title:{type:"string",description:"Optional short title summarising the observation"}},execute:r=>Ke(e,t,n,r)}}function Y(e){return e===null?{}:{Authorization:`Bearer ${e}`}}async function qe(e,t,n,r){try{let o=Ze(t,r),i=await fetch(o,{headers:Y(n),signal:AbortSignal.timeout(1e4)});if(!i.ok)return{result:`Error: Worker returned status ${i.status}`};let s=await i.json();return{result:Ye(s.results??[])}}catch(o){return e.client.app.log("warn","memory_search failed",{error:o instanceof Error?o.message:String(o)}),{result:`Error: ${o instanceof Error?o.message:String(o)}`}}}async function Ke(e,t,n,r){try{let o={text:r.text};r.title!==void 0&&(o.title=r.title);let i={"Content-Type":"application/json",...Y(n)},s=await fetch(`${t}/api/memory/save`,{method:"POST",headers:i,body:JSON.stringify(o),signal:AbortSignal.timeout(1e4)});if(!s.ok)return{result:`Error: Worker returned status ${s.status}`};let a=await s.json();return{result:Ve(a)}}catch(o){return e.client.app.log("warn","memory_save failed",{error:o instanceof Error?o.message:String(o)}),{result:`Error: ${o instanceof Error?o.message:String(o)}`}}}function Ze(e,t){let n=new URLSearchParams;return n.set("query",String(t.query??"")),t.limit!==void 0&&n.set("limit",String(t.limit)),t.project!==void 0&&n.set("project",String(t.project)),`${e}/api/search?${n.toString()}`}function Ye(e){return e.length===0?"No results found for the given query.":e.map(t=>`[${t.id}] ${t.title} (${t.type}, ${t.project}) \u2014 ${t.summary}`).join(`
4
- `)}function Ve(e){let t=e.id??"unknown",n=e.title??"(untitled)";return`Saved observation #${t}: "${n}"`}async function V(e){let t=k(),n=K(),r=I(h);r===null&&e.client.app.log("warn","Auth token not found in PID file \u2014 requests will be unauthenticated",{pidFilePath:h});function o(){return r=I(h),r}return Z(e,t,r),{"session.created":(i,s)=>B(e,t,r,i,s,o),"tool.execute.after":(i,s)=>z(e,t,r,n,i,s),"tool.execute.before":(i,s)=>W(e,t,i,s),"session.idle":(i,s)=>L(e,t,r,i,s),"experimental.session.compacting":(i,s)=>D(e,t,r,i,s),"session.compacted":(i,s)=>$(e,t,r,i,s),"file.edited":(i,s)=>N(e,t,i,s)}}
1
+ "use strict";var E=Object.defineProperty;var X=Object.getOwnPropertyDescriptor;var Q=Object.getOwnPropertyNames;var ee=Object.prototype.hasOwnProperty;var te=(e,t)=>{for(var n in t)E(e,n,{get:t[n],enumerable:!0})},ne=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of Q(t))!ee.call(e,o)&&o!==n&&E(e,o,{get:()=>t[o],enumerable:!(r=X(t,o))||r.enumerable});return e};var re=e=>ne(E({},"__esModule",{value:!0}),e);var Xe={};te(Xe,{default:()=>V});module.exports=re(Xe);var S=require("node:fs");var x=require("node:os"),p=require("node:path"),v=41777,O="127.0.0.1",oe=(0,p.join)((0,x.homedir)(),".config","opencode"),et=(0,p.join)(oe,"opencode.json"),y=(0,p.join)((0,x.homedir)(),".config","opencode","memory"),ie="memory.db",se="settings.json",h=(0,p.join)(y,"worker.pid");var tt=(0,p.join)(y,ie),C=(0,p.join)(y,se),nt=(0,p.join)(y,"logs");var R={workerPort:v,workerBind:O,chromaDbUrl:"http://localhost:8000",chromaDbEnabled:!0,recencyWindowDays:90,retentionDays:365,tddEnabled:!0,fileLengthWarn:300,fileLengthCritical:500,testFilePatterns:["*.test.ts","*.spec.ts","*_test.go","test_*.py"],toolRedirectRules:[],aiProvider:null,aiModel:null,aiCompressionTimeoutMs:15e3,aiCompressionMaxRetries:3,aiSkipTools:[],secretDetectionEnabled:!0,secretPatterns:[],contextTokenBudget:2e3,notificationsEnabled:!1},g=null;function m(){if(g!==null)return g;if(!(0,S.existsSync)(C))return g={...R},g;try{let e=(0,S.readFileSync)(C,"utf-8"),t=JSON.parse(e);return g={...R,...t},g}catch{return g={...R},g}}function k(){let e=m();return`http://${e.workerBind}:${e.workerPort}`}var d=require("node:fs"),A=require("node:os"),b=require("node:path");var F=require("node:child_process");function c(e){process.platform==="darwin"&&m().notificationsEnabled&&(0,F.execFile)("osascript",["-e",`display notification "${e}" with title "opencode"`])}var ae=5e3;function ce(){return process.env.OPENCODE_SESSIONS_DIR??(0,b.join)((0,A.homedir)(),".config","opencode","sessions")}function le(e){return(0,b.join)(ce(),"sessions",e,"pre-compact-state.json")}function ue(e){let t=["[Memory Context Restored After Compaction]"];return e.activePlan&&t.push(`Active plan: ${e.activePlan}`),e.currentTask&&t.push(`Current task: ${e.currentTask}`),e.status&&t.push(`Status: ${e.status}`),e.summary&&t.push(`Recent context: ${e.summary}`),t.join(`
2
+ `)}async function pe(e,t,n){let r=`${e}/api/context/inject?project=${encodeURIComponent(n)}`,o={};t!==null&&(o.Authorization=`Bearer ${t}`);let i=await fetch(r,{headers:o,signal:AbortSignal.timeout(ae)});return i.ok?(await i.json()).context??null:null}function ge(e){let t=le(e);if(!(0,d.existsSync)(t))return null;try{let n=(0,d.readFileSync)(t,"utf-8"),r=JSON.parse(n);return(0,d.unlinkSync)(t),r}catch{return null}}function w(e,t){e.messages=e.messages??[],e.messages.push({role:"user",content:t})}async function $(e,t,n,r,o){c("Session compacted!");try{let i=null;try{i=await pe(t,n,e.project.name)}catch(a){if(a instanceof TypeError)throw a}if(i){w(o,i);return}let s=ge(r.sessionId);if(s){let a=ue(s);w(o,a)}}catch(i){e.client.app.log("warn","Compacted state restore failed",{error:i instanceof Error?i.message:String(i),sessionId:r.sessionId})}}var P=require("node:fs"),j=require("node:os"),T=require("node:path");var me=5e3;function de(){return process.env.OPENCODE_SESSIONS_DIR??(0,T.join)((0,j.homedir)(),".config","opencode","sessions")}function fe(e){return{sessionId:e.sessionId,activePlan:e.context?.activePlan??null,currentTask:e.context?.currentTask??null,summary:e.context?.summary??null,timestamp:new Date().toISOString(),type:"compaction-state"}}async function ye(e,t,n){try{let r={"Content-Type":"application/json"};return t!==null&&(r.Authorization=`Bearer ${t}`),(await fetch(`${e}/api/memory/save`,{method:"POST",headers:r,body:JSON.stringify(n),signal:AbortSignal.timeout(me)})).ok}catch{return!1}}function he(e,t){let n=(0,T.join)(de(),"sessions",e);(0,P.mkdirSync)(n,{recursive:!0});let r=(0,T.join)(n,"pre-compact-state.json");(0,P.writeFileSync)(r,JSON.stringify(t,null,2),"utf-8")}async function M(e,t,n,r,o){c("Session compacting...");let i=fe(r);if(!await ye(t,n,i))try{he(r.sessionId,i)}catch(a){e.client.app.log("warn","Failed to write compaction fallback file",{error:a instanceof Error?a.message:String(a),sessionId:r.sessionId})}}var D=require("node:fs"),l=require("node:path");var Se=300,Te=500,Pe=["*.test.ts","*.spec.ts","*_test.go","test_*.py"];function Ee(e,t){let n=t.replace(/[.+^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*");return new RegExp(`^${n}$`).test(e)}function xe(e,t){let n=(0,l.basename)(e);return t.some(r=>Ee(n,r))}function Ce(e,t){let n=(0,l.dirname)(e),r=(0,l.extname)(e),o=(0,l.basename)(e,r),i=[];for(let s of t)if(s.startsWith("*.")){let a=s.slice(1);i.push((0,l.join)(n,`${o}${a}`))}else if(s.endsWith("*")){let a=s.slice(0,-1);i.push((0,l.join)(n,`${a}${o}${r}`))}return i}function _(e,t){e.messages=e.messages??[],e.messages.push({role:"system",content:t})}function Re(e,t,n,r){if(xe(t,n))return;let o=Ce(t,n),i=e.project.root;o.some(a=>{let u=a.startsWith("/")?a:(0,l.join)(i,a);return(0,D.existsSync)(u)})||_(r,`\u26A0\uFE0F TDD Warning: No test file found for ${t}. Consider writing tests first (Red-Green-Refactor).`)}function be(e,t,n,r,o){if(t>r){_(o,`\u{1F6A8} File Length Critical: ${e} has ${t} lines. This file should be refactored.`);return}t>n&&_(o,`\u26A0\uFE0F File Length Warning: ${e} has ${t} lines. Consider splitting this file.`)}async function N(e,t,n,r){try{c(`File edited: ${n.filePath}`);let o=m(),i=n.testFilePatterns??o.testFilePatterns??Pe,s=n.fileLengthWarn??o.fileLengthWarn??Se,a=n.fileLengthCritical??o.fileLengthCritical??Te;Re(e,n.filePath,i,r);let u=n.lineCount??0;be(n.filePath,u,s,a,r)}catch(o){e.client.app.log("warn","File edited check failed",{error:o instanceof Error?o.message:String(o),filePath:n.filePath})}}var _e=15e3;function Ie(e){let{context:t}=e;return t?!!(t.requested||t.investigated||t.learned||t.completed):!1}function ve(e){let t=e.context??{};return["Session Summary:",`Requested: ${t.requested??"Not specified"}`,`Investigated: ${t.investigated??"Not specified"}`,`Learned: ${t.learned??"Not specified"}`,`Completed: ${t.completed??"Not specified"}`].join(`
3
+ `)}async function L(e,t,n,r,o){if(c("Session idle"),!Ie(r))return;let i={"Content-Type":"application/json"};n!==null&&(i.Authorization=`Bearer ${n}`);try{let s=await fetch(`${t}/api/memory/save`,{method:"POST",headers:i,body:JSON.stringify({type:"session-summary",title:`Session Summary: ${r.sessionId}`,text:ve(r),project:e.project.name}),signal:AbortSignal.timeout(_e)});s.ok||e.client.app.log("warn","Failed to save session summary",{status:s.status})}catch(s){e.client.app.log("warn","Session summary save failed",{error:s instanceof Error?s.message:String(s)})}}var Oe=3e3;function ke(e){let t={};return e!==null&&(t.Authorization=`Bearer ${e}`),t}async function U(e,t){return fetch(e,{headers:ke(t),signal:AbortSignal.timeout(Oe)})}async function B(e,t,n,r,o,i){c("Session started!");let s=`${t}/api/context/inject?project=${encodeURIComponent(e.project.name)}`;try{let a=await U(s,n);if(a.status===401&&i!==void 0){let f=i();a=await U(s,f)}if(!a.ok){e.client.app.log("warn","Failed to load memory context",{status:a.status});return}let u=await a.json();u.context&&(o.messages=o.messages??[],o.messages.push({role:"system",content:u.context}))}catch(a){e.client.app.log("warn","Memory context injection failed",{error:a instanceof Error?a.message:String(a)})}}var Fe=15e3,we=200;async function z(e,t,n,r,o,i){c(`Tool completed: ${o.tool}`),Ae(e,t,n,r,o,i).catch(s=>{e.client.app.log("warn","Observation capture failed",{error:s instanceof Error?s.message:String(s)})})}async function Ae(e,t,n,r,o,i){let s=`Tool ${o.tool}: ${$e(o,i)}`,a=`${o.tool} execution`,u={text:r.sanitize(s),title:r.sanitize(a),project:e.project.name},f={"Content-Type":"application/json"};n!==null&&(f.Authorization=`Bearer ${n}`),await fetch(`${t}/api/memory/save`,{method:"POST",headers:f,body:JSON.stringify(u),signal:AbortSignal.timeout(Fe)})}function $e(e,t){let n=t.output??t.error??"",r=je(e.input),o=n.slice(0,we).trim();return r&&o?`${r} -> ${o}`:r||o||"(no details)"}function je(e){let t=Object.entries(e);return t.length===0?"":t.map(([n,r])=>`${n}=${String(r).slice(0,80)}`).join(", ")}function Me(){let e=process.env.MEMORY_TOOL_REDIRECT_RULES;if(e!==void 0)try{return JSON.parse(e)}catch{return[]}return m().toolRedirectRules}function De(e){if(typeof e!="object"||e===null)return!1;let t=e;return typeof t.tool=="string"&&(t.action==="deny"||t.action==="redirect")}function Ne(e){return e.message??`Tool '${e.tool}' is blocked by project configuration.`}function Le(e){let t=e.message??`Tool '${e.tool}' has been redirected.`;return e.alternative?`${t} Suggested alternative: ${e.alternative}.`:t}function Ue(e,t){t.blocked=!0,t.messages=[{role:"user",content:Ne(e)}]}function Be(e,t){t.messages=[{role:"user",content:Le(e)}]}async function W(e,t,n,r){c(`Tool executing: ${n.tool}`);let o=Me();for(let i of o)try{if(!De(i))throw new Error("Invalid rule: tool must be a string and action must be 'deny' or 'redirect'");if(i.tool!==n.tool)continue;i.action==="deny"?Ue(i,r):Be(i,r);return}catch(s){e.client.app.log("warn","Tool redirect rule evaluation failed",{error:s instanceof Error?s.message:String(s),rule:JSON.stringify(i)})}}var G=require("node:fs");function ze(e){return typeof e=="object"&&e!==null&&"token"in e&&typeof e.token=="string"}function I(e){try{let t=(0,G.readFileSync)(e,"utf-8");if(t.trim().length===0)return null;let n=JSON.parse(t);return ze(n)?n.token:null}catch{return null}}var H=[{name:"aws_access_key",pattern:/AKIA[0-9A-Z]{16}/g},{name:"github_pat",pattern:/ghp_[a-zA-Z0-9]{36}/g},{name:"github_oauth",pattern:/gho_[a-zA-Z0-9]{36}/g},{name:"anthropic_key",pattern:/sk-ant-[a-zA-Z0-9\-_]{20,}/g},{name:"openai_key",pattern:/sk-[a-zA-Z0-9]{20,}/g},{name:"jwt_token",pattern:/eyJ[a-zA-Z0-9_-]+\.eyJ[a-zA-Z0-9_-]+\.[a-zA-Z0-9_-]+/g},{name:"pem_private_key",pattern:/-----BEGIN (RSA |EC |OPENSSH )?PRIVATE KEY-----/g},{name:"generic_api_key",pattern:/(?:api[_-]?key|token|secret|password)\s*[:=]\s*['"]?([a-zA-Z0-9\-_]{20,})['"]?/gi}];function We(e,t=H){if(!e)return e;let n=e;for(let{pattern:r}of t)r.lastIndex=0,n=n.replace(r,"[REDACTED]");return n}function J(e=[]){let t=[...H,...e];return n=>We(n,t)}var Ge=/<private>[\s\S]*?<\/private>/gi;function q(e){return e.replace(Ge,"")}function K(e={}){let{additionalSecretPatterns:t=[],secretDetectionEnabled:n=!0}=e,r=J(t);return{sanitize(o){let i=q(o);return n?r(i):i}}}function Z(e,t,n){return[He(e,t,n),Je(e,t,n)]}function He(e,t,n){return{name:"memory_search",description:"Search memory observations by topic or keyword",parameters:{query:{type:"string",description:"The search query or topic to look up in memory",required:!0},limit:{type:"number",description:"Maximum number of results to return (default 20)"},project:{type:"string",description:"Filter results to a specific project name"}},execute:r=>qe(e,t,n,r)}}function Je(e,t,n){return{name:"memory_save",description:"Save an observation to memory for future reference",parameters:{text:{type:"string",description:"The observation text to save to memory",required:!0},title:{type:"string",description:"Optional short title summarising the observation"}},execute:r=>Ke(e,t,n,r)}}function Y(e){return e===null?{}:{Authorization:`Bearer ${e}`}}async function qe(e,t,n,r){try{let o=Ze(t,r),i=await fetch(o,{headers:Y(n),signal:AbortSignal.timeout(1e4)});if(!i.ok)return{result:`Error: Worker returned status ${i.status}`};let s=await i.json();return{result:Ye(s.results??[])}}catch(o){return e.client.app.log("warn","memory_search failed",{error:o instanceof Error?o.message:String(o)}),{result:`Error: ${o instanceof Error?o.message:String(o)}`}}}async function Ke(e,t,n,r){try{let o={text:r.text};r.title!==void 0&&(o.title=r.title);let i={"Content-Type":"application/json",...Y(n)},s=await fetch(`${t}/api/memory/save`,{method:"POST",headers:i,body:JSON.stringify(o),signal:AbortSignal.timeout(1e4)});if(!s.ok)return{result:`Error: Worker returned status ${s.status}`};let a=await s.json();return{result:Ve(a)}}catch(o){return e.client.app.log("warn","memory_save failed",{error:o instanceof Error?o.message:String(o)}),{result:`Error: ${o instanceof Error?o.message:String(o)}`}}}function Ze(e,t){let n=new URLSearchParams;return n.set("query",String(t.query??"")),t.limit!==void 0&&n.set("limit",String(t.limit)),t.project!==void 0&&n.set("project",String(t.project)),`${e}/api/search?${n.toString()}`}function Ye(e){return e.length===0?"No results found for the given query.":e.map(t=>`[${t.id}] ${t.title} (${t.type}, ${t.project}) \u2014 ${t.summary}`).join(`
4
+ `)}function Ve(e){let t=e.id??"unknown",n=e.title??"(untitled)";return`Saved observation #${t}: "${n}"`}async function V(e){let t=k(),n=K(),r=I(h);r===null&&e.client.app.log("warn","Auth token not found in PID file \u2014 requests will be unauthenticated",{pidFilePath:h});function o(){return r=I(h),r}return Z(e,t,r),{"session.created":(i,s)=>B(e,t,r,i,s,o),"tool.execute.after":(i,s)=>z(e,t,r,n,i,s),"tool.execute.before":(i,s)=>W(e,t,i,s),"session.idle":(i,s)=>L(e,t,r,i,s),"experimental.session.compacting":(i,s)=>M(e,t,r,i,s),"session.compacted":(i,s)=>$(e,t,r,i,s),"file.edited":(i,s)=>N(e,t,i,s)}}