opencode-prompt-recorder 1.8.1 → 1.8.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/index.js CHANGED
@@ -1,17 +1,21 @@
1
- import{mkdir as j,appendFile as ee,writeFile as q,readFile as te,rename as Q}from"fs/promises";import{join as l,dirname as ne,basename as Ee}from"path";import{fileURLToPath as Ae}from"url";import{readFile as ye,rm as we}from"fs/promises";import{basename as $,dirname as w,join as U}from"path";import{fileURLToPath as he}from"url";var ke="opencode-prompt-recorder",K=!1;function Y(s,e){if(!e||K)return;K=!0;let n=new AbortController,o=setTimeout(()=>n.abort(),1e4);$e(n.signal).then(i=>{i.updated&&setTimeout(()=>{s.client.tui.showToast({body:{title:"Prompt Recorder \u66F4\u65B0",message:`${i.name} \u5DF2\u4ECE ${i.current} \u66F4\u65B0\u5230 ${i.latest}\uFF0C\u91CD\u542F OpenCode \u5B8C\u6210\u66F4\u65B0`,variant:"info"}})},5e3)}).catch(i=>{console.error("[prompt-recorder] auto-update check failed:",i)}).finally(()=>clearTimeout(o))}async function $e(s){let e=await be(ke);if(!e)return{updated:!1};let n=await F(U(e,"package.json"));if(!n?.name||!n.version)return{updated:!1};let o=await Pe(n.name,s);if(!o||!ve(o,n.version))return{updated:!1};let i=await De(e,n.name);if(!i)return{updated:!1};try{await we(i,{recursive:!0,force:!0})}catch{return{updated:!1,error:"remove_failed",name:n.name,current:n.version,latest:o}}return{updated:!0,name:n.name,current:n.version,latest:o}}async function be(s){let e=w(he(import.meta.url));for(;;){if((await F(U(e,"package.json")))?.name===s)return $(e)==="dist"?w(e):e;let o=w(e);if(o===e)return;e=o}}async function De(s,e){let n=w(s),o=$(n).startsWith("@")?w(n):n;if($(o)!=="node_modules")return;let i=w(o),c=await F(U(i,"package.json")),u=Me(i,e)??c?.dependencies?.[e];if(!(!u||!Se(u)))return i}function Me(s,e){if(e.startsWith("@")){let[i,c]=e.split("/");if(!i||!c||$(w(s))!==i)return;let u=`${c}@`,g=$(s);return g.startsWith(u)?g.slice(u.length):void 0}let n=`${e}@`,o=$(s);return o.startsWith(n)?o.slice(n.length):void 0}function Se(s){let e=s.trim();return e?!!(e==="latest"||e==="*"||/^[~^]/.test(e)||/^(?:>=|>|<=|<)/.test(e)||/\s+(?:\|\||-|[<>=])\s+/.test(e)):!1}async function F(s){try{let e=JSON.parse(await ye(s,"utf-8"));return e&&typeof e=="object"?e:void 0}catch{return}}async function Pe(s,e){try{let n=await fetch(`https://registry.npmjs.org/${encodeURIComponent(s)}/latest`,{signal:e});if(!n.ok)return;let o=await n.json();if(!o||typeof o!="object")return;let i=o.version;return typeof i=="string"?i:void 0}catch{return}}function ve(s,e){let n=Z(s),o=Z(e);if(!n||!o)return!1;for(let i=0;i<3;i++)if(n.parts[i]!==o.parts[i])return n.parts[i]>o.parts[i];if(!n.pre.length&&o.pre.length)return!0;if(n.pre.length&&!o.pre.length)return!1;for(let i=0;i<Math.max(n.pre.length,o.pre.length);i++){let c=n.pre[i],u=o.pre[i];if(c===void 0)return!1;if(u===void 0)return!0;if(c===u)continue;let g=/^\d+$/.test(c)?Number(c):void 0,y=/^\d+$/.test(u)?Number(u):void 0;return g!==void 0&&y!==void 0?g>y:g!==void 0?!1:y!==void 0?!0:c>u}return!1}function Z(s){let e=s.match(/^v?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+.+)?$/);if(e)return{parts:[Number(e[1]),Number(e[2]),Number(e[3])],pre:e[4]?.split(".")??[]}}var _e=ne(Ae(import.meta.url));async function L(s,e){if(process.env.PROMPT_RECORDER_DEBUG!=="1"&&process.env.PROMPT_RECORDER_DEBUG!=="true")return;let o=`[${new Date().toISOString()}] ${e}
2
- `;try{let i=l(s,".agent","prompts-log");await j(i,{recursive:!0}),await ee(l(i,"log.txt"),o)}catch(i){console.error("debugLog failed:",i)}}var I="";async function Ie(){if(I)return I;try{return I=JSON.parse(await te(l(_e,"package.json"),"utf-8")).version||"unknown",I}catch{return"unknown"}}var Re=/[<>:"/\\|?*\x00-\x1f\u200B-\u200F\u2028-\u202E\uFEFF]/g;function N(s){return s.split(`
3
- `)[0].trim().replace(/<[^>]*>/g,"").replace(/\s+/g," ").trim().replace(Re,"").substring(0,40).trim()||"untitled"}function Te(s){let e=s.trimStart();return e.startsWith("<system-reminder>")||e.startsWith("<system>")}function xe(s){let e=s.getFullYear().toString(),n=String(s.getMonth()+1).padStart(2,"0"),o=String(s.getDate()).padStart(2,"0"),i=String(s.getHours()).padStart(2,"0"),c=String(s.getMinutes()).padStart(2,"0"),u=String(s.getSeconds()).padStart(2,"0");return{yyyy:e,MM:n,dd:o,HH:i,mm:c,ss:u}}var Ce=async s=>{Y(s,!0);let{directory:e}=s;ue();let n=new Map,o=new Map,i=new Map,c=new Map,u=1440*60*1e3,g=200,y=2e3,M=1440*60*1e3,re=3600*1e3,m=new Map,h=new Map,R=".txt",T=new Map;function ie(){if(m.size<g)return;let a=Date.now();for(let[t,r]of m)a-r.time>u&&m.delete(t)}function se(){let a=Date.now();if(i.size>y)for(let[t,r]of i)a-r>M&&i.delete(t);if(o.size>y)for(let[t,r]of o)a-r.time>M&&o.delete(t);if(c.size>y)for(let[t,r]of c)a-r>M&&c.delete(t);if(n.size>y)for(let[t,r]of n)a-r.time>M&&n.delete(t);if(h.size>0)for(let[t,r]of h)a-r.time>re&&h.delete(t)}async function S(a,t){let r=ne(a.filepath),d=Ee(a.filepath).match(/^(\d{10})-/);if(!d)return;let f=l(r,`${d[1]}-${N(t)}${R}`);if(f!==a.filepath)try{await Q(a.filepath,f),a.filepath=f}catch{let P=crypto.randomUUID().slice(0,8),v=l(r,`${d[1]}-${N(t)}-${P}${R}`);try{await Q(a.filepath,v),a.filepath=v}catch(k){console.error(`[prompt-recorder] rename failed: ${a.filepath}`,k)}}}async function oe(a){let t=a.properties.info,r=t?.id,p=t?.role||t?.message?.role;r&&p==="user"&&o.set(r,{role:p,time:Date.now()})}async function ae(a){let t=a.properties.part;if(t?.type==="tool"&&t?.tool==="task"){let b=t.state?.metadata??t.metadata;if(b){let D=b.sessionId??b.sessionID;D&&(c.set(D,Date.now()),await L(e,`[prompt-recorder] tracked task session: ${D}`))}}if(t?.type!=="text"||!t?.text||t.synthetic||t.ignored)return;let r=t.sessionID,p=t.messageID,d=t.text,f=o.get(p)?.role;if(f||(f=t.message?.role),f||(f=a.properties.info?.role),f||(f=a.properties.info?.message?.role),f!=="user"||!d||!r)return;if(Te(d)){await L(e,`[prompt-recorder] filtered system-injected: sessionID=${r}`);return}let P=p?`${p}:${d}`:`${r}:${d}`;if(i.has(P))return;i.set(P,Date.now()),se(),await L(e,`[prompt-recorder] event=${a.type}, role=${f}, sessionID=${r}, textLength=${d.length}, textPreview=${d.substring(0,50)}`);let v=new Date,{yyyy:k,MM:E,dd:A,HH:O,mm:H,ss:pe}=xe(v),z=l(e,".agent","prompts"),J=c.has(r)?l(z,"task",k,E,A):l(z,k,E,A);await j(J,{recursive:!0});let fe=k.slice(-2),G=`============ ${k}-${E}-${A} ${O}:${H}:${pe} ============`,x=m.get(r);if(x)x.time=Date.now(),await ee(x.filepath,`
1
+ import{mkdir as H,appendFile as z,writeFile as ee,readFile as J,rename as te,readdir as ve}from"fs/promises";import{join as p,dirname as ne,basename as Ee}from"path";import{fileURLToPath as Ae}from"url";import{readFile as ge,rm as ye}from"fs/promises";import{basename as P,dirname as h,join as L}from"path";import{fileURLToPath as we}from"url";var he="opencode-prompt-recorder",Y=!1;function Q(s,e){if(!e||Y)return;Y=!0;let n=new AbortController,o=setTimeout(()=>n.abort(),1e4);$e(n.signal).then(r=>{r.updated&&setTimeout(()=>{s.client.tui.showToast({body:{title:"Prompt Recorder \u66F4\u65B0",message:`${r.name} \u5DF2\u4ECE ${r.current} \u66F4\u65B0\u5230 ${r.latest}\uFF0C\u91CD\u542F OpenCode \u5B8C\u6210\u66F4\u65B0`,variant:"info"}})},5e3)}).catch(r=>{console.error("[prompt-recorder] auto-update check failed:",r)}).finally(()=>clearTimeout(o))}async function $e(s){let e=await ke(he);if(!e)return{updated:!1};let n=await N(L(e,"package.json"));if(!n?.name||!n.version)return{updated:!1};let o=await Se(n.name,s);if(!o||!Me(o,n.version))return{updated:!1};let r=await be(e,n.name);if(!r)return{updated:!1};try{await ye(r,{recursive:!0,force:!0})}catch{return{updated:!1,error:"remove_failed",name:n.name,current:n.version,latest:o}}return{updated:!0,name:n.name,current:n.version,latest:o}}async function ke(s){let e=h(we(import.meta.url));for(;;){if((await N(L(e,"package.json")))?.name===s)return P(e)==="dist"?h(e):e;let o=h(e);if(o===e)return;e=o}}async function be(s,e){let n=h(s),o=P(n).startsWith("@")?h(n):n;if(P(o)!=="node_modules")return;let r=h(o),c=await N(L(r,"package.json")),u=De(r,e)??c?.dependencies?.[e];if(!(!u||!Pe(u)))return r}function De(s,e){if(e.startsWith("@")){let[r,c]=e.split("/");if(!r||!c||P(h(s))!==r)return;let u=`${c}@`,g=P(s);return g.startsWith(u)?g.slice(u.length):void 0}let n=`${e}@`,o=P(s);return o.startsWith(n)?o.slice(n.length):void 0}function Pe(s){let e=s.trim();return e?!!(e==="latest"||e==="*"||/^[~^]/.test(e)||/^(?:>=|>|<=|<)/.test(e)||/\s+(?:\|\||-|[<>=])\s+/.test(e)):!1}async function N(s){try{let e=JSON.parse(await ge(s,"utf-8"));return e&&typeof e=="object"?e:void 0}catch{return}}async function Se(s,e){try{let n=await fetch(`https://registry.npmjs.org/${encodeURIComponent(s)}/latest`,{signal:e});if(!n.ok)return;let o=await n.json();if(!o||typeof o!="object")return;let r=o.version;return typeof r=="string"?r:void 0}catch{return}}function Me(s,e){let n=q(s),o=q(e);if(!n||!o)return!1;for(let r=0;r<3;r++)if(n.parts[r]!==o.parts[r])return n.parts[r]>o.parts[r];if(!n.pre.length&&o.pre.length)return!0;if(n.pre.length&&!o.pre.length)return!1;for(let r=0;r<Math.max(n.pre.length,o.pre.length);r++){let c=n.pre[r],u=o.pre[r];if(c===void 0)return!1;if(u===void 0)return!0;if(c===u)continue;let g=/^\d+$/.test(c)?Number(c):void 0,y=/^\d+$/.test(u)?Number(u):void 0;return g!==void 0&&y!==void 0?g>y:g!==void 0?!1:y!==void 0?!0:c>u}return!1}function q(s){let e=s.match(/^v?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+.+)?$/);if(e)return{parts:[Number(e[1]),Number(e[2]),Number(e[3])],pre:e[4]?.split(".")??[]}}var _e=ne(Ae(import.meta.url));async function j(s,e){if(process.env.PROMPT_RECORDER_DEBUG!=="1"&&process.env.PROMPT_RECORDER_DEBUG!=="true")return;let o=`[${new Date().toISOString()}] ${e}
2
+ `;try{let r=p(s,".agent","prompts-log");await H(r,{recursive:!0}),await z(p(r,"log.txt"),o)}catch(r){console.error("debugLog failed:",r)}}var T="";async function Ie(){if(T)return T;try{return T=JSON.parse(await J(p(_e,"package.json"),"utf-8")).version||"unknown",T}catch{return"unknown"}}var Re=/[<>:"/\\|?*\x00-\x1f\u200B-\u200F\u2028-\u202E\uFEFF]/g;function O(s){return s.split(`
3
+ `)[0].trim().replace(/<[^>]*>/g,"").replace(/\s+/g," ").trim().replace(Re,"").substring(0,40).trim()||"untitled"}function Te(s){let e=s.trimStart();return e.startsWith("<system-reminder>")||e.startsWith("<system>")}function xe(s){let e=s.getFullYear().toString(),n=String(s.getMonth()+1).padStart(2,"0"),o=String(s.getDate()).padStart(2,"0"),r=String(s.getHours()).padStart(2,"0"),c=String(s.getMinutes()).padStart(2,"0"),u=String(s.getSeconds()).padStart(2,"0");return{yyyy:e,MM:n,dd:o,HH:r,mm:c,ss:u}}var x=".txt";async function Fe(s,e){return re(p(s,".agent","prompts"),e)}async function re(s,e){let n;try{n=await ve(s)}catch{return}for(let o of n){let r=p(s,o);try{if((await J(r,"utf-8")).includes(`SessionID: ${e}`))return r}catch{if(o.endsWith(x))continue;let c=await re(r,e);if(c)return c}}}var Ce=async s=>{Q(s,!0);let{directory:e}=s;fe();let n=new Map,o=new Map,r=new Map,c=new Map,u=1440*60*1e3,g=200,y=2e3,S=1440*60*1e3,ie=3600*1e3,m=new Map,$=new Map,F=new Map;function se(){if(m.size<g)return;let a=Date.now();for(let[t,i]of m)a-i.time>u&&m.delete(t)}function oe(){let a=Date.now();if(r.size>y)for(let[t,i]of r)a-i>S&&r.delete(t);if(o.size>y)for(let[t,i]of o)a-i.time>S&&o.delete(t);if(c.size>y)for(let[t,i]of c)a-i>S&&c.delete(t);if(n.size>y)for(let[t,i]of n)a-i.time>S&&n.delete(t);if($.size>0)for(let[t,i]of $)a-i.time>ie&&$.delete(t)}async function M(a,t){let i=ne(a.filepath),f=Ee(a.filepath).match(/^(\d{10})-/);if(!f)return;let l=p(i,`${f[1]}-${O(t)}${x}`);if(l!==a.filepath)try{await te(a.filepath,l),a.filepath=l}catch{let v=crypto.randomUUID().slice(0,8),E=p(i,`${f[1]}-${O(t)}-${v}${x}`);try{await te(a.filepath,E),a.filepath=E}catch(k){console.error(`[prompt-recorder] rename failed: ${a.filepath}`,k)}}}async function ae(a){let t=a.properties.info,i=t?.id,d=t?.role||t?.message?.role;i&&d==="user"&&o.set(i,{role:d,time:Date.now()})}async function ce(a){let t=a.properties.part;if(t?.type==="tool"&&t?.tool==="task"){let w=t.state?.metadata??t.metadata;if(w){let b=w.sessionId??w.sessionID;b&&(c.set(b,Date.now()),await j(e,`[prompt-recorder] tracked task session: ${b}`))}}if(t?.type!=="text"||!t?.text||t.synthetic||t.ignored)return;let i=t.sessionID,d=t.messageID,f=t.text,l=o.get(d)?.role;if(l||(l=t.message?.role),l||(l=a.properties.info?.role),l||(l=a.properties.info?.message?.role),l!=="user"||!f||!i)return;if(Te(f)){await j(e,`[prompt-recorder] filtered system-injected: sessionID=${i}`);return}let v=d?`${d}:${f}`:`${i}:${f}`;if(r.has(v))return;r.set(v,Date.now()),oe(),await j(e,`[prompt-recorder] event=${a.type}, role=${l}, sessionID=${i}, textLength=${f.length}, textPreview=${f.substring(0,50)}`);let E=new Date,{yyyy:k,MM:A,dd:_,HH:W,mm:G,ss:pe}=xe(E),V=p(e,".agent","prompts"),X=c.has(i)?p(V,"task",k,A,_):p(V,k,A,_);await H(X,{recursive:!0});let le=k.slice(-2),C=`============ ${k}-${A}-${_} ${W}:${G}:${pe} ============`,U=m.get(i);if(U)U.time=Date.now(),await z(U.filepath,`
4
4
 
5
- ${G}
5
+ ${C}
6
6
 
7
- ${d}`);else{let b=N(n.get(r)?.title??d),D=`${fe}${E}${A}${O}${H}-${b}${R}`,W=l(J,D),le=`============ SessionID: ${r} ============`;await q(W,`${le}
7
+ ${f}`);else{let w=await Fe(e,i);if(w)m.set(i,{filepath:w,time:Date.now()}),await z(w,`
8
8
 
9
- ${G}
9
+ ${C}
10
10
 
11
- ${d}`),m.set(r,{filepath:W,time:Date.now()}),ie();let V=h.get(r);if(V){h.delete(r);let C=m.get(r);C&&await S(C,V.title)}let X=T.get(r);X&&clearTimeout(X);let me=setTimeout(async()=>{T.delete(r);try{let _=(await s.client.session.get({path:{id:r}}))?.data?.title;if(!_)return;let ge=n.get(r)?.title;if(_===ge)return;n.set(r,{title:_,time:Date.now()});let B=m.get(r);B&&await S(B,_)}catch{}},5e3);T.set(r,me)}}async function ce(a){let t=a.properties.info;if(t?.id&&t?.title){n.set(t.id,{title:t.title,time:Date.now()});let r=m.get(t.id);r&&await S(r,t.title)}}async function ue(){try{let a=await Ie(),t=l(e,".agent"),r=l(t,"opencode-prompt-recorder-readme.txt"),p=`# OpenCode Prompt Recorder
11
+ ${f}`);else{let B=O(n.get(i)?.title??f),D=`${le}${A}${_}${W}${G}-${B}${x}`,I=p(X,D),R=`============ SessionID: ${i} ============`;await ee(I,`${R}
12
+
13
+ ${C}
14
+
15
+ ${f}`),m.set(i,{filepath:I,time:Date.now()}),se();let K=$.get(i);if(K){$.delete(i);let Z=m.get(i);Z&&await M(Z,K.title)}}let b=F.get(i);b&&clearTimeout(b);let me=setTimeout(async()=>{F.delete(i);try{let D=(await s.client.session.get({path:{id:i}}))?.data?.title;if(!D)return;let I=n.get(i)?.title;if(D===I)return;n.set(i,{title:D,time:Date.now()});let R=m.get(i);R&&await M(R,D)}catch{}},5e3);F.set(i,me)}}async function ue(a){let t=a.properties.info;if(t?.id&&t?.title){n.set(t.id,{title:t.title,time:Date.now()});let i=m.get(t.id);i&&await M(i,t.title)}}async function fe(){try{let a=await Ie(),t=p(e,".agent"),i=p(t,"opencode-prompt-recorder-readme.txt"),d=`# OpenCode Prompt Recorder
12
16
 
13
17
  \u81EA\u52A8\u8BB0\u5F55\u7528\u6237\u63D0\u793A\u8BCD\u5230 .agent/prompts \u76EE\u5F55\u7684\u63D2\u4EF6\u3002
14
18
 
15
19
  \u7248\u672C\uFF1A${a}
16
20
  \u4F5C\u8005\uFF1Aanarckk
17
- \u9879\u76EE\u5730\u5740\uFF1Ahttps://github.com/anarckk/opencode-prompt-recorder`;try{if(await te(r,"utf-8")===p)return}catch{}await j(t,{recursive:!0}),await q(r,p)}catch{}}async function de(a){let t=a.properties.info;if(t?.id&&t?.title){let r=n.get(t.id)?.title;if(n.set(t.id,{title:t.title,time:Date.now()}),r!==t.title){let p=m.get(t.id);p?await S(p,t.title):h.set(t.id,{title:t.title,time:Date.now()})}}}return{event:async({event:a})=>{switch(a.type){case"message.updated":await oe(a);break;case"message.part.updated":await ae(a);break;case"session.created":await ce(a);break;case"session.updated":await de(a);break}}}},Ge=Ce;export{Ge as default};
21
+ \u9879\u76EE\u5730\u5740\uFF1Ahttps://github.com/anarckk/opencode-prompt-recorder`;try{if(await J(i,"utf-8")===d)return}catch{}await H(t,{recursive:!0}),await ee(i,d)}catch{}}async function de(a){let t=a.properties.info;if(t?.id&&t?.title){let i=n.get(t.id)?.title;if(n.set(t.id,{title:t.title,time:Date.now()}),i!==t.title){let d=m.get(t.id);d?await M(d,t.title):$.set(t.id,{title:t.title,time:Date.now()})}}}return{event:async({event:a})=>{switch(a.type){case"message.updated":await ae(a);break;case"message.part.updated":await ce(a);break;case"session.created":await ue(a);break;case"session.updated":await de(a);break}}}},Ge=Ce;export{Ge as default};
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-prompt-recorder",
3
- "version": "1.8.1",
3
+ "version": "1.8.2",
4
4
  "description": "OpenCode plugin for recording user prompts. Automatically saves user messages to a local file system with organized directory structure.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-prompt-recorder",
3
- "version": "1.8.1",
3
+ "version": "1.8.2",
4
4
  "description": "OpenCode plugin for recording user prompts. Automatically saves user messages to a local file system with organized directory structure.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",