opencode-metis 0.2.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/plugin.cjs +5 -4
- package/package.json +1 -1
package/dist/plugin.cjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
"use strict";var
|
|
2
|
-
`)}async function ht(t,e,n){let r=`${t}/api/context/inject?project=${encodeURIComponent(n)}`,o={};e!==null&&(o.Authorization=`Bearer ${e}`);let s=await fetch(r,{headers:o,signal:AbortSignal.timeout(mt)});return s.ok?(await s.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 s=null;try{s=await ht(e,n,t.project.name)}catch(a){if(a instanceof TypeError)throw a}if(s){j(o,s);return}let i=St(r.sessionId);if(i){let a=yt(i);j(o,a)}}catch(s){t.client.app.log("warn","Compacted state restore failed",{error:s instanceof Error?s.message:String(s),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
|
|
3
|
-
`)}async function
|
|
4
|
-
`)}function
|
|
1
|
+
"use strict";var E=Object.defineProperty;var ot=Object.getOwnPropertyDescriptor;var it=Object.getOwnPropertyNames;var st=Object.prototype.hasOwnProperty;var at=(t,e)=>{for(var n in e)E(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&&E(t,o,{get:()=>e[o],enumerable:!(r=ot(e,o))||r.enumerable});return t};var lt=t=>ct(E({},"__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,A="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:A,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 F(){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 s=await fetch(r,{headers:o,signal:AbortSignal.timeout(mt)});return s.ok?(await s.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 s=null;try{s=await ht(e,n,t.project.name)}catch(a){if(a instanceof TypeError)throw a}if(s){j(o,s);return}let i=St(r.sessionId);if(i){let a=yt(i);j(o,a)}}catch(s){t.client.app.log("warn","Compacted state restore failed",{error:s instanceof Error?s.message:String(s),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 xt(t,e){let n=[];return t.context?.activePlan&&n.push(`Active plan: ${t.context.activePlan}`),t.context?.currentTask&&n.push(`Current task: ${t.context.currentTask}`),t.context?.summary&&n.push(`Summary: ${t.context.summary}`),{text:n.length>0?n.join(`
|
|
3
|
+
`):`Session ${t.sessionId} compaction at ${new Date().toISOString()}`,title:`Compaction State: ${t.sessionId}`,project:e,skipAiCompression:!0}}async function Et(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 s=xt(r,t.project.name);if(!await Et(e,n,s))try{Ct(r.sessionId,s)}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 kt(t,e){let n=e.replace(/[.+^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*");return new RegExp(`^${n}$`).test(t)}function It(t,e){let n=(0,l.basename)(t);return e.some(r=>kt(n,r))}function vt(t,e){let n=(0,l.dirname)(t),r=(0,l.extname)(t),o=(0,l.basename)(t,r),s=[];for(let i of e)if(i.startsWith("*.")){let a=i.slice(1);s.push((0,l.join)(n,`${o}${a}`))}else if(i.endsWith("*")){let a=i.slice(0,-1);s.push((0,l.join)(n,`${a}${o}${r}`))}return s}function k(t,e){t.messages=t.messages??[],t.messages.push({role:"system",content:e})}function Ot(t,e,n,r){if(It(e,n))return;let o=vt(e,n),s=t.project.root;o.some(a=>{let u=a.startsWith("/")?a:(0,l.join)(s,a);return(0,U.existsSync)(u)})||k(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){k(o,`\u{1F6A8} File Length Critical: ${t} has ${e} lines. This file should be refactored.`);return}e>n&&k(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(),s=n.testFilePatterns??o.testFilePatterns??_t,i=n.fileLengthWarn??o.fileLengthWarn??Rt,a=n.fileLengthCritical??o.fileLengthCritical??bt;Ot(t,n.filePath,s,r);let u=n.lineCount??0;wt(n.filePath,u,i,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 At=15e3;function Ft(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(`
|
|
4
|
+
`)}async function z(t,e,n,r,o){if(c("Session idle"),!Ft(r))return;let s={"Content-Type":"application/json"};n!==null&&(s.Authorization=`Bearer ${n}`);try{let i=await fetch(`${e}/api/memory/save`,{method:"POST",headers:s,body:JSON.stringify({type:"session-summary",title:`Session Summary: ${r.sessionId}`,text:$t(r),project:t.project.name}),signal:AbortSignal.timeout(At)});i.ok||t.client.app.log("warn","Failed to save session summary",{status:i.status})}catch(i){t.client.app.log("warn","Session summary save failed",{error:i instanceof Error?i.message:String(i)})}}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,s){c("Session started!");let i=`${e}/api/context/inject?project=${encodeURIComponent(t.project.name)}`;try{let a=await W(i,n);if(a.status===401&&s!==void 0){let x=s();a=await W(i,x)}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,s,i){c(`Tool completed: ${o.tool}`),Lt(t,e,n,r,o,s,i).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,s,i){let a=`Tool ${o.tool}: ${Bt(o,s)}`,u=`${o.tool} execution`,x=Ut(o.input),nt=s.output??s.error??"",v={text:r.sanitize(a),title:r.sanitize(u),project:t.project.name,toolName:o.tool,toolInput:r.sanitize(x),toolOutput:r.sanitize(nt)},O=`${e}/api/memory/save`,f=await H(O,v,n);if(f.status===401&&i!==void 0){let rt=i();f=await H(O,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 s of o)try{if(!Gt(s))throw new Error("Invalid rule: tool must be a string and action must be 'deny' or 'redirect'");if(s.tool!==n.tool)continue;s.action==="deny"?qt(s,r):Kt(s,r);return}catch(i){t.client.app.log("warn","Tool redirect rule evaluation failed",{error:i instanceof Error?i.message:String(i),rule:JSON.stringify(s)})}}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 I(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 s=V(o);return n?r(s):s}}}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),s=await fetch(o,{headers:tt(n()),signal:AbortSignal.timeout(1e4)});if(!s.ok)return{result:`Error: Worker returned status ${s.status}`};let i=await s.json();return{result:oe(i.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 s={"Content-Type":"application/json",...tt(n())},i=await fetch(`${e}/api/memory/save`,{method:"POST",headers:s,body:JSON.stringify(o),signal:AbortSignal.timeout(1e4)});if(!i.ok)return{result:`Error: Worker returned status ${i.status}`};let a=await i.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(`
|
|
5
|
+
`)}function ie(t){let e=t.id??"unknown",n=t.title??"(untitled)";return`Saved observation #${e}: "${n}"`}async function et(t){let e=F(),n=X(),r=I(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=I(h),r}return Q(t,e,()=>r),{"session.created":(i,a)=>G(t,e,r,i,a,o),"tool.execute.after":(i,a)=>J(t,e,r,n,i,a,o),"tool.execute.before":(i,a)=>q(t,e,i,a),"session.idle":(i,a)=>z(t,e,r,i,a),"experimental.session.compacting":(i,a)=>L(t,e,r,i,a),"session.compacted":(i,a)=>D(t,e,r,i,a),"file.edited":(i,a)=>B(t,e,i,a)}}
|