opencode-metis 0.1.8 → 0.2.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.
package/dist/plugin.cjs CHANGED
@@ -1,4 +1,4 @@
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)}}
1
+ "use strict";var x=Object.defineProperty;var ot=Object.getOwnPropertyDescriptor;var it=Object.getOwnPropertyNames;var st=Object.prototype.hasOwnProperty;var at=(t,e)=>{for(var n in e)x(t,n,{get:e[n],enumerable:!0})},ct=(t,e,n,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of it(e))!st.call(t,o)&&o!==n&&x(t,o,{get:()=>e[o],enumerable:!(r=ot(e,o))||r.enumerable});return t};var lt=t=>ct(x({},"__esModule",{value:!0}),t);var se={};at(se,{default:()=>et});module.exports=lt(se);var S=require("node:fs");var C=require("node:os"),p=require("node:path"),w=41777,F="127.0.0.1",ut=(0,p.join)((0,C.homedir)(),".config","opencode"),ce=(0,p.join)(ut,"opencode.json"),y=(0,p.join)((0,C.homedir)(),".config","opencode","memory"),pt="memory.db",gt="settings.json",h=(0,p.join)(y,"worker.pid");var le=(0,p.join)(y,pt),R=(0,p.join)(y,gt),ue=(0,p.join)(y,"logs");var b={workerPort:w,workerBind:F,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)(R))return g={...b},g;try{let t=(0,S.readFileSync)(R,"utf-8"),e=JSON.parse(t);return g={...b,...e},g}catch{return g={...b},g}}function A(){let t=m();return`http://${t.workerBind}:${t.workerPort}`}var d=require("node:fs"),M=require("node:os"),_=require("node:path");var $=require("node:child_process");function c(t){process.platform==="darwin"&&m().notificationsEnabled&&(0,$.execFile)("osascript",["-e",`display notification "${t}" with title "opencode"`])}var mt=5e3;function dt(){return process.env.OPENCODE_SESSIONS_DIR??(0,_.join)((0,M.homedir)(),".config","opencode","sessions")}function ft(t){return(0,_.join)(dt(),"sessions",t,"pre-compact-state.json")}function yt(t){let e=["[Memory Context Restored After Compaction]"];return t.activePlan&&e.push(`Active plan: ${t.activePlan}`),t.currentTask&&e.push(`Current task: ${t.currentTask}`),t.status&&e.push(`Status: ${t.status}`),t.summary&&e.push(`Recent context: ${t.summary}`),e.join(`
2
+ `)}async function ht(t,e,n){let r=`${t}/api/context/inject?project=${encodeURIComponent(n)}`,o={};e!==null&&(o.Authorization=`Bearer ${e}`);let i=await fetch(r,{headers:o,signal:AbortSignal.timeout(mt)});return i.ok?(await i.json()).context??null:null}function St(t){let e=ft(t);if(!(0,d.existsSync)(e))return null;try{let n=(0,d.readFileSync)(e,"utf-8"),r=JSON.parse(n);return(0,d.unlinkSync)(e),r}catch{return null}}function j(t,e){t.messages=t.messages??[],t.messages.push({role:"user",content:e})}async function D(t,e,n,r,o){c("Session compacted!");try{let i=null;try{i=await ht(e,n,t.project.name)}catch(a){if(a instanceof TypeError)throw a}if(i){j(o,i);return}let s=St(r.sessionId);if(s){let a=yt(s);j(o,a)}}catch(i){t.client.app.log("warn","Compacted state restore failed",{error:i instanceof Error?i.message:String(i),sessionId:r.sessionId})}}var P=require("node:fs"),N=require("node:os"),T=require("node:path");var Tt=5e3;function Pt(){return process.env.OPENCODE_SESSIONS_DIR??(0,T.join)((0,N.homedir)(),".config","opencode","sessions")}function Et(t){return{sessionId:t.sessionId,activePlan:t.context?.activePlan??null,currentTask:t.context?.currentTask??null,summary:t.context?.summary??null,timestamp:new Date().toISOString(),type:"compaction-state"}}async function xt(t,e,n){try{let r={"Content-Type":"application/json"};return e!==null&&(r.Authorization=`Bearer ${e}`),(await fetch(`${t}/api/memory/save`,{method:"POST",headers:r,body:JSON.stringify(n),signal:AbortSignal.timeout(Tt)})).ok}catch{return!1}}function Ct(t,e){let n=(0,T.join)(Pt(),"sessions",t);(0,P.mkdirSync)(n,{recursive:!0});let r=(0,T.join)(n,"pre-compact-state.json");(0,P.writeFileSync)(r,JSON.stringify(e,null,2),"utf-8")}async function L(t,e,n,r,o){c("Session compacting...");let i=Et(r);if(!await xt(e,n,i))try{Ct(r.sessionId,i)}catch(a){t.client.app.log("warn","Failed to write compaction fallback file",{error:a instanceof Error?a.message:String(a),sessionId:r.sessionId})}}var U=require("node:fs"),l=require("node:path");var Rt=300,bt=500,_t=["*.test.ts","*.spec.ts","*_test.go","test_*.py"];function It(t,e){let n=e.replace(/[.+^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*");return new RegExp(`^${n}$`).test(t)}function Ot(t,e){let n=(0,l.basename)(t);return e.some(r=>It(n,r))}function vt(t,e){let n=(0,l.dirname)(t),r=(0,l.extname)(t),o=(0,l.basename)(t,r),i=[];for(let s of e)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 I(t,e){t.messages=t.messages??[],t.messages.push({role:"system",content:e})}function kt(t,e,n,r){if(Ot(e,n))return;let o=vt(e,n),i=t.project.root;o.some(a=>{let u=a.startsWith("/")?a:(0,l.join)(i,a);return(0,U.existsSync)(u)})||I(r,`\u26A0\uFE0F TDD Warning: No test file found for ${e}. Consider writing tests first (Red-Green-Refactor).`)}function wt(t,e,n,r,o){if(e>r){I(o,`\u{1F6A8} File Length Critical: ${t} has ${e} lines. This file should be refactored.`);return}e>n&&I(o,`\u26A0\uFE0F File Length Warning: ${t} has ${e} lines. Consider splitting this file.`)}async function B(t,e,n,r){try{c(`File edited: ${n.filePath}`);let o=m(),i=n.testFilePatterns??o.testFilePatterns??_t,s=n.fileLengthWarn??o.fileLengthWarn??Rt,a=n.fileLengthCritical??o.fileLengthCritical??bt;kt(t,n.filePath,i,r);let u=n.lineCount??0;wt(n.filePath,u,s,a,r)}catch(o){t.client.app.log("warn","File edited check failed",{error:o instanceof Error?o.message:String(o),filePath:n.filePath})}}var Ft=15e3;function At(t){let{context:e}=t;return e?!!(e.requested||e.investigated||e.learned||e.completed):!1}function $t(t){let e=t.context??{};return["Session Summary:",`Requested: ${e.requested??"Not specified"}`,`Investigated: ${e.investigated??"Not specified"}`,`Learned: ${e.learned??"Not specified"}`,`Completed: ${e.completed??"Not specified"}`].join(`
3
+ `)}async function z(t,e,n,r,o){if(c("Session idle"),!At(r))return;let i={"Content-Type":"application/json"};n!==null&&(i.Authorization=`Bearer ${n}`);try{let s=await fetch(`${e}/api/memory/save`,{method:"POST",headers:i,body:JSON.stringify({type:"session-summary",title:`Session Summary: ${r.sessionId}`,text:$t(r),project:t.project.name}),signal:AbortSignal.timeout(Ft)});s.ok||t.client.app.log("warn","Failed to save session summary",{status:s.status})}catch(s){t.client.app.log("warn","Session summary save failed",{error:s instanceof Error?s.message:String(s)})}}var jt=3e3;function Mt(t){let e={};return t!==null&&(e.Authorization=`Bearer ${t}`),e}async function W(t,e){return fetch(t,{headers:Mt(e),signal:AbortSignal.timeout(jt)})}async function G(t,e,n,r,o,i){c("Session started!");let s=`${e}/api/context/inject?project=${encodeURIComponent(t.project.name)}`;try{let a=await W(s,n);if(a.status===401&&i!==void 0){let E=i();a=await W(s,E)}if(!a.ok){t.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){t.client.app.log("warn","Memory context injection failed",{error:a instanceof Error?a.message:String(a)})}}var Dt=15e3,Nt=200;async function J(t,e,n,r,o,i,s){c(`Tool completed: ${o.tool}`),Lt(t,e,n,r,o,i,s).catch(a=>{t.client.app.log("warn","Observation capture failed",{error:a instanceof Error?a.message:String(a)})})}async function Lt(t,e,n,r,o,i,s){let a=`Tool ${o.tool}: ${Bt(o,i)}`,u=`${o.tool} execution`,E=Ut(o.input),nt=i.output??i.error??"",v={text:r.sanitize(a),title:r.sanitize(u),project:t.project.name,toolName:o.tool,toolInput:r.sanitize(E),toolOutput:r.sanitize(nt)},k=`${e}/api/memory/save`,f=await H(k,v,n);if(f.status===401&&s!==void 0){let rt=s();f=await H(k,v,rt)}f.ok||t.client.app.log("warn","Observation save failed",{status:f.status})}async function H(t,e,n){let r={"Content-Type":"application/json"};return n!==null&&(r.Authorization=`Bearer ${n}`),fetch(t,{method:"POST",headers:r,body:JSON.stringify(e),signal:AbortSignal.timeout(Dt)})}function Ut(t){try{return JSON.stringify(t)}catch{return String(t)}}function Bt(t,e){let n=e.output??e.error??"",r=zt(t.input),o=n.slice(0,Nt).trim();return r&&o?`${r} -> ${o}`:r||o||"(no details)"}function zt(t){let e=Object.entries(t);return e.length===0?"":e.map(([n,r])=>`${n}=${String(r).slice(0,80)}`).join(", ")}function Wt(){let t=process.env.MEMORY_TOOL_REDIRECT_RULES;if(t!==void 0)try{return JSON.parse(t)}catch{return[]}return m().toolRedirectRules}function Gt(t){if(typeof t!="object"||t===null)return!1;let e=t;return typeof e.tool=="string"&&(e.action==="deny"||e.action==="redirect")}function Ht(t){return t.message??`Tool '${t.tool}' is blocked by project configuration.`}function Jt(t){let e=t.message??`Tool '${t.tool}' has been redirected.`;return t.alternative?`${e} Suggested alternative: ${t.alternative}.`:e}function qt(t,e){e.blocked=!0,e.messages=[{role:"user",content:Ht(t)}]}function Kt(t,e){e.messages=[{role:"user",content:Jt(t)}]}async function q(t,e,n,r){c(`Tool executing: ${n.tool}`);let o=Wt();for(let i of o)try{if(!Gt(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"?qt(i,r):Kt(i,r);return}catch(s){t.client.app.log("warn","Tool redirect rule evaluation failed",{error:s instanceof Error?s.message:String(s),rule:JSON.stringify(i)})}}var K=require("node:fs");function Zt(t){return typeof t=="object"&&t!==null&&"token"in t&&typeof t.token=="string"&&"pid"in t&&typeof t.pid=="number"}function Yt(t){try{return process.kill(t,0),!0}catch{return!1}}function O(t){try{let e=(0,K.readFileSync)(t,"utf-8");if(e.trim().length===0)return null;let n=JSON.parse(e);return!Zt(n)||!Yt(n.pid)?null:n.token}catch{return null}}var Z=[{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 Vt(t,e=Z){if(!t)return t;let n=t;for(let{pattern:r}of e)r.lastIndex=0,n=n.replace(r,"[REDACTED]");return n}function Y(t=[]){let e=[...Z,...t];return n=>Vt(n,e)}var Xt=/<private>[\s\S]*?<\/private>/gi;function V(t){return t.replace(Xt,"")}function X(t={}){let{additionalSecretPatterns:e=[],secretDetectionEnabled:n=!0}=t,r=Y(e);return{sanitize(o){let i=V(o);return n?r(i):i}}}function Q(t,e,n){return[Qt(t,e,n),te(t,e,n)]}function Qt(t,e,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=>ee(t,e,n,r)}}function te(t,e,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=>ne(t,e,n,r)}}function tt(t){return t===null?{}:{Authorization:`Bearer ${t}`}}async function ee(t,e,n,r){try{let o=re(e,r),i=await fetch(o,{headers:tt(n),signal:AbortSignal.timeout(1e4)});if(!i.ok)return{result:`Error: Worker returned status ${i.status}`};let s=await i.json();return{result:oe(s.results??[])}}catch(o){return t.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 ne(t,e,n,r){try{let o={text:r.text};r.title!==void 0&&(o.title=r.title);let i={"Content-Type":"application/json",...tt(n)},s=await fetch(`${e}/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:ie(a)}}catch(o){return t.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 re(t,e){let n=new URLSearchParams;return n.set("query",String(e.query??"")),e.limit!==void 0&&n.set("limit",String(e.limit)),e.project!==void 0&&n.set("project",String(e.project)),`${t}/api/search?${n.toString()}`}function oe(t){return t.length===0?"No results found for the given query.":t.map(e=>`[${e.id}] ${e.title} (${e.type}, ${e.project}) \u2014 ${e.summary}`).join(`
4
+ `)}function ie(t){let e=t.id??"unknown",n=t.title??"(untitled)";return`Saved observation #${e}: "${n}"`}async function et(t){let e=A(),n=X(),r=O(h);r===null&&t.client.app.log("warn","Auth token not found in PID file \u2014 requests will be unauthenticated",{pidFilePath:h});function o(){return r=O(h),r}return Q(t,e,r),{"session.created":(i,s)=>G(t,e,r,i,s,o),"tool.execute.after":(i,s)=>J(t,e,r,n,i,s,o),"tool.execute.before":(i,s)=>q(t,e,i,s),"session.idle":(i,s)=>z(t,e,r,i,s),"experimental.session.compacting":(i,s)=>L(t,e,r,i,s),"session.compacted":(i,s)=>D(t,e,r,i,s),"file.edited":(i,s)=>B(t,e,i,s)}}