opencode-metis 0.1.4 → 0.1.5

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.
Files changed (2) hide show
  1. package/dist/plugin.cjs +4 -4
  2. package/package.json +1 -1
package/dist/plugin.cjs CHANGED
@@ -1,4 +1,4 @@
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});
1
+ "use strict";var T=Object.defineProperty;var B=Object.getOwnPropertyDescriptor;var G=Object.getOwnPropertyNames;var H=Object.prototype.hasOwnProperty;var q=(e,t)=>{for(var o in t)T(e,o,{get:t[o],enumerable:!0})},J=(e,t,o,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of G(t))!H.call(e,r)&&r!==o&&T(e,r,{get:()=>t[r],enumerable:!(n=B(t,r))||n.enumerable});return e};var K=e=>J(T({},"__esModule",{value:!0}),e);var Ne={};q(Ne,{default:()=>W});module.exports=K(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 z=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(z)});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 V=15e3,X=200;async function O(e,t,o,n){a(`Tool completed: ${o.tool}`),Y(e,t,o,n).catch(r=>{e.client.app.log("warn","Observation capture failed",{error:r instanceof Error?r.message:String(r)})})}async function Y(e,t,o,n){let r={text:`Tool ${o.tool}: ${Q(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(V)})}function Q(e,t){let o=t.output??t.error??"",n=Z(e.input),r=o.slice(0,X).trim();return n&&r?`${n} -> ${r}`:n||r||"(no details)"}function Z(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",ee=(0,l.join)((0,x.homedir)(),".config","opencode"),qe=(0,l.join)(ee,"opencode.json"),p=(0,l.join)((0,x.homedir)(),".config","opencode","memory"),te="memory.db",oe="settings.json",Je=(0,l.join)(p,"worker.pid");var Ke=(0,l.join)(p,te),C=(0,l.join)(p,oe),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 ne(){let e=process.env.MEMORY_TOOL_REDIRECT_RULES;if(e!==void 0)try{return JSON.parse(e)}catch{return[]}return g().toolRedirectRules}function re(e){if(typeof e!="object"||e===null)return!1;let t=e;return typeof t.tool=="string"&&(t.action==="deny"||t.action==="redirect")}function ie(e){return e.message??`Tool '${e.tool}' is blocked by project configuration.`}function se(e){let t=e.message??`Tool '${e.tool}' has been redirected.`;return e.alternative?`${t} Suggested alternative: ${e.alternative}.`:t}function ae(e,t){t.blocked=!0,t.messages=[{role:"user",content:ie(e)}]}function ce(e,t){t.messages=[{role:"user",content:se(e)}]}async function $(e,t,o,n){a(`Tool executing: ${o.tool}`);let r=ne();for(let i of r)try{if(!re(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"?ae(i,n):ce(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 le=15e3;function ue(e){let{context:t}=e;return t?!!(t.requested||t.investigated||t.learned||t.completed):!1}function me(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"),!!ue(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:me(o),project:e.project.name}),signal:AbortSignal.timeout(le)});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 pe=5e3;function de(){return process.env.OPENCODE_SESSIONS_DIR??(0,y.join)((0,j.homedir)(),".config","opencode","sessions")}function ge(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 fe(e,t){try{return(await fetch(`${e}/api/memory/save`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t),signal:AbortSignal.timeout(pe)})).ok}catch{return!1}}function ye(e,t){let o=(0,y.join)(de(),"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=ge(o);if(!await fe(t,r))try{ye(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 Se=5e3;function he(){return process.env.OPENCODE_SESSIONS_DIR??(0,R.join)((0,D.homedir)(),".config","opencode","sessions")}function Te(e){return(0,R.join)(he(),"sessions",e,"pre-compact-state.json")}function xe(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 Ce(e,t){let o=`${e}/api/context/inject?project=${encodeURIComponent(t)}`,n=await fetch(o,{signal:AbortSignal.timeout(Se)});return n.ok?(await n.json()).context??null:null}function Ee(e){let t=Te(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 Ce(t,e.project.name)}catch(s){if(s instanceof TypeError)throw s}if(r){M(n,r);return}let i=Ee(o.sessionId);if(i){let s=xe(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 Re=300,Pe=500,be=["*.test.ts","*.spec.ts","*_test.go","test_*.py"];function Ie(e,t){let o=t.replace(/[.+^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*");return new RegExp(`^${o}$`).test(e)}function Oe(e,t){let o=(0,c.basename)(e);return t.some(n=>Ie(o,n))}function _e(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 ve(e,t,o,n){if(Oe(t,o))return;let r=_e(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 we(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??be,s=o.fileLengthWarn??r.fileLengthWarn??Re,u=o.fileLengthCritical??r.fileLengthCritical??Pe;ve(e,o.filePath,i,n);let h=o.lineCount??0;we(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[$e(e,t),ke(e,t)]}function $e(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=>je(e,t,o)}}function ke(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=>Fe(e,t,o)}}async function je(e,t,o){try{let n=Me(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:De(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 Fe(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:Ae(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 Me(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 De(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 Ae(e){let t=e.id??"unknown",o=e.title??"(untitled)";return`Saved observation #${t}: "${o}"`}async function W(e){let t=w();return U(e,t),{"session.created":(o,n)=>I(e,t,o,n),"tool.execute.after":(o,n)=>O(e,t,o,n),"tool.execute.before":(o,n)=>$(e,t,o,n),"session.idle":(o,n)=>k(e,t,o,n),"experimental.session.compacting":(o,n)=>F(e,t,o,n),"session.compacted":(o,n)=>A(e,t,o,n),"file.edited":(o,n)=>L(e,t,o,n)}}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-metis",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "type": "module",
5
5
  "description": "Persistent memory system for OpenCode sessions",
6
6
  "license": "MIT",