opencode-metis 0.1.2 → 0.1.4
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 +4 -4
- package/dist/worker.cjs +33 -32
- package/package.json +8 -4
package/dist/plugin.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";var T=Object.defineProperty;var
|
|
2
|
-
`)}async function
|
|
3
|
-
`)}async function
|
|
4
|
-
`)}function
|
|
1
|
+
"use strict";var T=Object.defineProperty;var W=Object.getOwnPropertyDescriptor;var B=Object.getOwnPropertyNames;var G=Object.prototype.hasOwnProperty;var H=(e,t)=>{for(var o in t)T(e,o,{get:t[o],enumerable:!0})},q=(e,t,o,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of B(t))!G.call(e,r)&&r!==o&&T(e,r,{get:()=>t[r],enumerable:!(n=W(t,r))||n.enumerable});return e};var J=e=>q(T({},"__esModule",{value:!0}),e);var Ne={};H(Ne,{MetisPlugin:()=>Ae});module.exports=J(Ne);var b=require("child_process");function a(e){let t=e.replace(/"/g,'\\"');(0,b.exec)(`osascript -e 'display notification "${t}" with title "opencode"'`)}var K=3e3;async function I(e,t,o,n){a("Session started!");let r=`${t}/api/context/inject?project=${encodeURIComponent(e.project.name)}`;try{let i=await fetch(r,{signal:AbortSignal.timeout(K)});if(!i.ok){e.client.app.log("warn","Failed to load memory context",{status:i.status});return}let s=await i.json();s.context&&(n.messages=n.messages??[],n.messages.push({role:"system",content:s.context}))}catch(i){e.client.app.log("warn","Memory context injection failed",{error:i instanceof Error?i.message:String(i)})}}var z=15e3,V=200;async function O(e,t,o,n){a(`Tool completed: ${o.tool}`),X(e,t,o,n).catch(r=>{e.client.app.log("warn","Observation capture failed",{error:r instanceof Error?r.message:String(r)})})}async function X(e,t,o,n){let r={text:`Tool ${o.tool}: ${Y(o,n)}`,title:`${o.tool} execution`,project:e.project.name};await fetch(`${t}/api/memory/save`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(r),signal:AbortSignal.timeout(z)})}function Y(e,t){let o=t.output??t.error??"",n=Q(e.input),r=o.slice(0,V).trim();return n&&r?`${n} -> ${r}`:n||r||"(no details)"}function Q(e){let t=Object.entries(e);return t.length===0?"":t.map(([o,n])=>`${o}=${String(n).slice(0,80)}`).join(", ")}var f=require("fs");var x=require("os"),l=require("path"),_=41777,v="127.0.0.1",Z=(0,l.join)((0,x.homedir)(),".config","opencode"),qe=(0,l.join)(Z,"opencode.json"),p=(0,l.join)((0,x.homedir)(),".config","opencode","memory"),ee="memory.db",te="settings.json",Je=(0,l.join)(p,"worker.pid");var Ke=(0,l.join)(p,ee),C=(0,l.join)(p,te),ze=(0,l.join)(p,"logs"),Ve=(0,l.join)(p,"models"),Xe=(0,l.join)(p,"vector-db");var E={workerPort:_,workerBind:v,chromaDbUrl:"http://localhost:8000",recencyWindowDays:90,retentionDays:365,tddEnabled:!0,fileLengthWarn:300,fileLengthCritical:500,testFilePatterns:["*.test.ts","*.spec.ts","*_test.go","test_*.py"],toolRedirectRules:[]},m=null;function g(){if(m!==null)return m;if(!(0,f.existsSync)(C))return m={...E},m;try{let e=(0,f.readFileSync)(C,"utf-8"),t=JSON.parse(e);return m={...E,...t},m}catch{return m={...E},m}}function w(){let e=g();return`http://${e.workerBind}:${e.workerPort}`}function oe(){let e=process.env.MEMORY_TOOL_REDIRECT_RULES;if(e!==void 0)try{return JSON.parse(e)}catch{return[]}return g().toolRedirectRules}function ne(e){if(typeof e!="object"||e===null)return!1;let t=e;return typeof t.tool=="string"&&(t.action==="deny"||t.action==="redirect")}function re(e){return e.message??`Tool '${e.tool}' is blocked by project configuration.`}function ie(e){let t=e.message??`Tool '${e.tool}' has been redirected.`;return e.alternative?`${t} Suggested alternative: ${e.alternative}.`:t}function se(e,t){t.blocked=!0,t.messages=[{role:"user",content:re(e)}]}function ae(e,t){t.messages=[{role:"user",content:ie(e)}]}async function $(e,t,o,n){a(`Tool executing: ${o.tool}`);let r=oe();for(let i of r)try{if(!ne(i))throw new Error("Invalid rule: tool must be a string and action must be 'deny' or 'redirect'");if(i.tool!==o.tool)continue;i.action==="deny"?se(i,n):ae(i,n);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 ce=15e3;function le(e){let{context:t}=e;return t?!!(t.requested||t.investigated||t.learned||t.completed):!1}function ue(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(`
|
|
2
|
+
`)}async function k(e,t,o,n){if(a("Session idle"),!!le(o))try{let r=await fetch(`${t}/api/memory/save`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({type:"session-summary",title:`Session Summary: ${o.sessionId}`,text:ue(o),project:e.project.name}),signal:AbortSignal.timeout(ce)});r.ok||e.client.app.log("warn","Failed to save session summary",{status:r.status})}catch(r){e.client.app.log("warn","Session summary save failed",{error:r instanceof Error?r.message:String(r)})}}var S=require("fs"),y=require("path"),j=require("os");var me=5e3;function pe(){return process.env.OPENCODE_SESSIONS_DIR??(0,y.join)((0,j.homedir)(),".config","opencode","sessions")}function de(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 ge(e,t){try{return(await fetch(`${e}/api/memory/save`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t),signal:AbortSignal.timeout(me)})).ok}catch{return!1}}function fe(e,t){let o=(0,y.join)(pe(),"sessions",e);(0,S.mkdirSync)(o,{recursive:!0});let n=(0,y.join)(o,"pre-compact-state.json");(0,S.writeFileSync)(n,JSON.stringify(t,null,2),"utf-8")}async function F(e,t,o,n){a("Session compacting...");let r=de(o);if(!await ge(t,r))try{fe(o.sessionId,r)}catch(s){e.client.app.log("warn","Failed to write compaction fallback file",{error:s instanceof Error?s.message:String(s),sessionId:o.sessionId})}}var d=require("fs"),R=require("path"),D=require("os");var ye=5e3;function Se(){return process.env.OPENCODE_SESSIONS_DIR??(0,R.join)((0,D.homedir)(),".config","opencode","sessions")}function he(e){return(0,R.join)(Se(),"sessions",e,"pre-compact-state.json")}function Te(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(`
|
|
3
|
+
`)}async function xe(e,t){let o=`${e}/api/context/inject?project=${encodeURIComponent(t)}`,n=await fetch(o,{signal:AbortSignal.timeout(ye)});return n.ok?(await n.json()).context??null:null}function Ce(e){let t=he(e);if(!(0,d.existsSync)(t))return null;try{let o=(0,d.readFileSync)(t,"utf-8"),n=JSON.parse(o);return(0,d.unlinkSync)(t),n}catch{return null}}function M(e,t){e.messages=e.messages??[],e.messages.push({role:"user",content:t})}async function A(e,t,o,n){a("Session compacted!");try{let r=null;try{r=await xe(t,e.project.name)}catch(s){if(s instanceof TypeError)throw s}if(r){M(n,r);return}let i=Ce(o.sessionId);if(i){let s=Te(i);M(n,s)}}catch(r){e.client.app.log("warn","Compacted state restore failed",{error:r instanceof Error?r.message:String(r),sessionId:o.sessionId})}}var N=require("fs"),c=require("path");var Ee=300,Re=500,Pe=["*.test.ts","*.spec.ts","*_test.go","test_*.py"];function be(e,t){let o=t.replace(/[.+^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*");return new RegExp(`^${o}$`).test(e)}function Ie(e,t){let o=(0,c.basename)(e);return t.some(n=>be(o,n))}function Oe(e,t){let o=(0,c.dirname)(e),n=(0,c.extname)(e),r=(0,c.basename)(e,n),i=[];for(let s of t)if(s.startsWith("*.")){let u=s.slice(1);i.push((0,c.join)(o,`${r}${u}`))}else if(s.endsWith("*")){let u=s.slice(0,-1);i.push((0,c.join)(o,`${u}${r}${n}`))}return i}function P(e,t){e.messages=e.messages??[],e.messages.push({role:"system",content:t})}function _e(e,t,o,n){if(Ie(t,o))return;let r=Oe(t,o),i=e.project.root;r.some(u=>{let h=u.startsWith("/")?u:(0,c.join)(i,u);return(0,N.existsSync)(h)})||P(n,`\u26A0\uFE0F TDD Warning: No test file found for ${t}. Consider writing tests first (Red-Green-Refactor).`)}function ve(e,t,o,n,r){if(t>n){P(r,`\u{1F6A8} File Length Critical: ${e} has ${t} lines. This file should be refactored.`);return}t>o&&P(r,`\u26A0\uFE0F File Length Warning: ${e} has ${t} lines. Consider splitting this file.`)}async function L(e,t,o,n){try{a(`File edited: ${o.filePath}`);let r=g(),i=o.testFilePatterns??r.testFilePatterns??Pe,s=o.fileLengthWarn??r.fileLengthWarn??Ee,u=o.fileLengthCritical??r.fileLengthCritical??Re;_e(e,o.filePath,i,n);let h=o.lineCount??0;ve(o.filePath,h,s,u,n)}catch(r){e.client.app.log("warn","File edited check failed",{error:r instanceof Error?r.message:String(r),filePath:o.filePath})}}function U(e,t){return[we(e,t),$e(e,t)]}function we(e,t){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:o=>ke(e,t,o)}}function $e(e,t){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:o=>je(e,t,o)}}async function ke(e,t,o){try{let n=Fe(t,o),r=await fetch(n,{signal:AbortSignal.timeout(1e4)});if(!r.ok)return{result:`Error: Worker returned status ${r.status}`};let i=await r.json();return{result:Me(i.results??[])}}catch(n){return e.client.app.log("warn","memory_search failed",{error:n instanceof Error?n.message:String(n)}),{result:`Error: ${n instanceof Error?n.message:String(n)}`}}}async function je(e,t,o){try{let n={text:o.text};o.title!==void 0&&(n.title=o.title);let r=await fetch(`${t}/api/memory/save`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n),signal:AbortSignal.timeout(1e4)});if(!r.ok)return{result:`Error: Worker returned status ${r.status}`};let i=await r.json();return{result:De(i)}}catch(n){return e.client.app.log("warn","memory_save failed",{error:n instanceof Error?n.message:String(n)}),{result:`Error: ${n instanceof Error?n.message:String(n)}`}}}function Fe(e,t){let o=new URLSearchParams;return o.set("query",String(t.query??"")),t.limit!==void 0&&o.set("limit",String(t.limit)),t.project!==void 0&&o.set("project",String(t.project)),`${e}/api/search?${o.toString()}`}function Me(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 De(e){let t=e.id??"unknown",o=e.title??"(untitled)";return`Saved observation #${t}: "${o}"`}var Ae=async function(t){let o=w();return U(t,o),{"session.created":(n,r)=>I(t,o,n,r),"tool.execute.after":(n,r)=>O(t,o,n,r),"tool.execute.before":(n,r)=>$(t,o,n,r),"session.idle":(n,r)=>k(t,o,n,r),"experimental.session.compacting":(n,r)=>F(t,o,n,r),"session.compacted":(n,r)=>A(t,o,n,r),"file.edited":(n,r)=>L(t,o,n,r)}};0&&(module.exports={MetisPlugin});
|