@popmelt.com/core 0.5.4 → 0.5.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.
package/dist/cli.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- var Dt=Object.defineProperty,Jt=Object.defineProperties;var Nt=Object.getOwnPropertyDescriptors;var Re=Object.getOwnPropertySymbols;var tt=Object.prototype.hasOwnProperty,nt=Object.prototype.propertyIsEnumerable;var Ze=(o,e)=>(e=Symbol[o])?e:Symbol.for("Symbol."+o);var et=(o,e,n)=>e in o?Dt(o,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):o[e]=n,K=(o,e)=>{for(var n in e||(e={}))tt.call(e,n)&&et(o,n,e[n]);if(Re)for(var n of Re(e))nt.call(e,n)&&et(o,n,e[n]);return o},oe=(o,e)=>Jt(o,Nt(e));var st=(o,e)=>{var n={};for(var t in o)tt.call(o,t)&&e.indexOf(t)<0&&(n[t]=o[t]);if(o!=null&&Re)for(var t of Re(o))e.indexOf(t)<0&&nt.call(o,t)&&(n[t]=o[t]);return n};var le=(o,e,n)=>(e=o[Ze("asyncIterator")])?e.call(o):(o=o[Ze("iterator")](),e={},n=(t,s)=>(s=o[t])&&(e[t]=a=>new Promise((i,c,p)=>(a=s.call(o,a),p=a.done,Promise.resolve(a.value).then(u=>i({value:u,done:p}),c)))),n("next"),n("return"),e);import{spawn as In}from"child_process";import{execFileSync as cn}from"child_process";import{randomUUID as fe}from"crypto";import{mkdir as ln,readdir as dn,stat as un,unlink as pn,writeFile as we}from"fs/promises";import{createServer as hn}from"http";import{tmpdir as fn}from"os";import{join as de}from"path";import{spawn as _t}from"child_process";import{createInterface as Bt}from"readline";function Me(o,e){let{prompt:n,projectRoot:t,maxTurns:s=10,maxBudgetUsd:a=1,allowedTools:i=["Read","Edit","Write","Glob","Grep","Bash"],claudePath:c="claude",resumeSessionId:p,model:u,onEvent:x}=e,G=[];p?G.push("--resume",p,"-p",n):G.push("-p",n),G.push("--output-format","stream-json","--verbose","--max-turns",String(s),"--max-budget-usd",String(a)),u&&G.push("--model",u);for(let I of i)G.push("--allowedTools",I);let w=_t(c,G,{cwd:t,stdio:["ignore","pipe","pipe"],env:oe(K({},process.env),{ANTHROPIC_API_KEY:void 0})}),M=new Promise(I=>{var J;let F,P=[],j=[],Q=!1,ee="",W=Bt({input:w.stdout}),B=new Set;W.on("line",z=>{var $,q,L,X,ke,be,Pe,Te,$e;if(z.trim())try{let Y=JSON.parse(z);Y.session_id&&!F&&(F=Y.session_id);let Je=(q=Y.type)!=null?q:($=Y.event)!=null&&$.type?`event.${Y.event.type}`:"unknown";if(B.add(Je),Y.type==="result"&&Y.result&&P.length===0){let D=typeof Y.result=="string"?Y.result:"";D&&(P.push(D),x==null||x({type:"delta",jobId:o,text:D},o))}if(Y.type==="assistant"&&Array.isArray((L=Y.message)==null?void 0:L.content))for(let D of Y.message.content){if(D.type==="text"&&D.text&&(P.push(D.text),x==null||x({type:"delta",jobId:o,text:D.text},o)),D.type==="tool_use"&&D.name){let ve=((X=D.input)==null?void 0:X.file_path)||((ke=D.input)==null?void 0:ke.path)||void 0;x==null||x(K({type:"tool_use",jobId:o,tool:D.name},ve?{file:ve}:{}),o),D.name==="Edit"&&((be=D.input)!=null&&be.file_path)?j.push({tool:"Edit",file_path:D.input.file_path,old_string:D.input.old_string,new_string:D.input.new_string,replace_all:D.input.replace_all}):D.name==="Write"&&((Pe=D.input)!=null&&Pe.file_path)&&j.push({tool:"Write",file_path:D.input.file_path,content:D.input.content})}D.type==="thinking"&&D.thinking&&(x==null||x({type:"thinking",jobId:o,text:D.thinking},o))}Y.type==="user"&&(($e=(Te=Y.tool_use_result)==null?void 0:Te.file)!=null&&$e.filePath)&&(x==null||x({type:"tool_use",jobId:o,tool:"Read",file:Y.tool_use_result.file.filePath},o))}catch(Y){}});let te=[];(J=w.stderr)==null||J.on("data",z=>{te.push(z.toString())}),w.on("close",z=>{W.close(),z!==0&&z!==null&&(Q=!0,ee=te.join("")||`Claude process exited with code ${z}`),I({sessionId:F,text:P.join(""),success:!Q,error:Q?ee:void 0,fileEdits:j.length>0?j:void 0})}),w.on("error",z=>{Q=!0,ee=z.message,I({sessionId:F,text:P.join(""),success:!1,error:ee,fileEdits:j.length>0?j:void 0})})});return{process:w,result:M}}import{spawn as Ut}from"child_process";import{createInterface as Ft}from"readline";function ot(o,e){let{prompt:n,projectRoot:t,screenshotPath:s,resumeSessionId:a,model:i,onEvent:c}=e,p=[];a?(p.push("exec","resume",a),i&&p.push("-m",i),p.push("--json","--full-auto",n),s&&p.push("--image",s)):(p.push("exec","--json","--full-auto"),i&&p.push("-m",i),p.push(n),s&&p.push("--image",s));let u=Ut("codex",p,{cwd:t,stdio:["ignore","pipe","pipe"],env:K({},process.env)}),x=new Promise(G=>{var ee;let w,M=[],I=!1,F="",P=Ft({input:u.stdout}),j=new Set;P.on("line",W=>{var B,te,J,z;if(W.trim())try{let $=JSON.parse(W),q=(B=$.type)!=null?B:"unknown";if(j.add(q),q==="thread.started"&&$.thread_id&&!w&&(w=$.thread_id),q==="item/agentMessage/delta"&&((te=$.delta)!=null&&te.text)&&(M.push($.delta.text),c==null||c({type:"delta",jobId:o,text:$.delta.text},o)),q==="item/reasoning/delta"&&((J=$.delta)!=null&&J.text)&&(c==null||c({type:"thinking",jobId:o,text:$.delta.text},o)),q==="item/started"&&$.item){let L=$.item.type;if(L==="command_execution")c==null||c({type:"tool_use",jobId:o,tool:"Bash"},o);else if(L==="file_change"){let X=$.item.filename||$.item.path;c==null||c(K({type:"tool_use",jobId:o,tool:"Edit"},X?{file:X}:{}),o)}else if(L==="file_read"){let X=$.item.filename||$.item.path;c==null||c(K({type:"tool_use",jobId:o,tool:"Read"},X?{file:X}:{}),o)}else if(L==="web_search")c==null||c({type:"tool_use",jobId:o,tool:"WebSearch"},o);else if(L==="mcp_tool_call"){let X=$.item.tool_name||$.item.name||"MCP";c==null||c({type:"tool_use",jobId:o,tool:X},o)}}if(q==="item/completed"&&$.item){if($.item.type==="agent_message"){let L=$.item.text;typeof L=="string"&&L&&M.push(L)}else if($.item.type==="reasoning"){let L=$.item.text;typeof L=="string"&&L&&(c==null||c({type:"thinking",jobId:o,text:L},o))}}q==="turn.failed"&&(I=!0,F=((z=$.error)==null?void 0:z.message)||$.message||"Turn failed")}catch($){}});let Q=[];(ee=u.stderr)==null||ee.on("data",W=>{Q.push(W.toString())}),u.on("close",W=>{P.close(),W!==0&&W!==null&&(I=!0,F=Q.join("")||`Codex process exited with code ${W}`),G({sessionId:w,text:M.join(""),success:!I,error:I?F:void 0})}),u.on("error",W=>{I=!0,F=W.message,G({sessionId:w,text:M.join(""),success:!1,error:F})})});return{process:u,result:x}}import{execFile as jt}from"child_process";import{copyFile as rt,mkdir as it,readdir as zt,readFile as Lt,writeFile as Gt}from"fs/promises";import{join as he}from"path";var Oe=class{constructor(e){this.projectRoot=e;let n=he(e,".popmelt");this.decisionsDir=he(n,"decisions"),this.screenshotsDir=he(n,"screenshots")}async persist(e,n,t){try{await it(this.decisionsDir,{recursive:!0}),await it(this.screenshotsDir,{recursive:!0});try{await rt(n,he(this.screenshotsDir,`s-${e.id}.png`))}catch(s){}for(let s=0;s<t.length;s++)try{let a=e.pastedImagePaths[s];a&&await rt(t[s],he(this.screenshotsDir,a.replace("screenshots/","")))}catch(a){}await Gt(he(this.decisionsDir,`d-${e.id}.json`),JSON.stringify(e,null,2))}catch(s){console.error("[DecisionStore] Failed to persist decision record:",s)}}async listDecisionIds(){try{return(await zt(this.decisionsDir)).filter(n=>n.startsWith("d-")&&n.endsWith(".json")).map(n=>n.slice(2,-5))}catch(e){return[]}}async loadDecision(e){try{let n=await Lt(he(this.decisionsDir,`d-${e}.json`),"utf-8");return JSON.parse(n)}catch(n){return null}}async loadDecisions(e){return(await Promise.all(e.map(t=>this.loadDecision(t)))).filter(t=>t!==null)}captureGitDiff(e){return new Promise(n=>{jt("git",["diff","HEAD"],{cwd:e,timeout:5e3,maxBuffer:1024*1024},(t,s)=>{if(t){n(null);return}n(s||null)})})}};import{readFile as at,writeFile as me}from"fs/promises";import{join as _e}from"path";var re="[Materializer]",Ht={version:1,materializedIds:[],lastRunAt:null,lastRunDecisionIds:[],lastRunError:null},Ee=class{constructor(e,n,t={}){this.projectRoot=e;this.decisionStore=n;this.options=t;this.cachedIndex=null;this.running=!1;let s=_e(e,".popmelt");this.indexPath=_e(s,"materialized.json"),this.modelPath=_e(s,"model.json")}get isRunning(){return this.running}async loadModel(){try{let e=await at(this.modelPath,"utf-8");return JSON.parse(e)}catch(e){return null}}async addComponent(e){let n=await this.loadModel();n||(n={tokens:{},components:{},rules:[]}),(!n.components||typeof n.components!="object")&&(n.components={});let t=n.components;return t[e]?{added:!1,alreadyExists:!0}:(t[e]={description:""},await me(this.modelPath,JSON.stringify(n,null,2)),console.log(`${re} Added component "${e}" to model`),{added:!0,alreadyExists:!1})}async updateToken(e,n){let t=await this.loadModel();t||(t={tokens:{},components:{},rules:[]});let s=e.split("."),a=t;for(let p=0;p<s.length-1;p++){let u=s[p];(!a[u]||typeof a[u]!="object")&&(a[u]={}),a=a[u]}let i=s[s.length-1],c;try{c=JSON.parse(n)}catch(p){c=null}if(c&&typeof c=="object"&&c!==null&&"value"in c)a[i]=c;else{let p=a[i];p&&typeof p=="object"&&p!==null&&"value"in p?p.value=n:a[i]=n}return await me(this.modelPath,JSON.stringify(t,null,2)),console.log(`${re} Updated token "${e}" \u2192 "${n.slice(0,80)}"`),{updated:!0}}async removeToken(e){let n=await this.loadModel();if(!n)return{removed:!1};let t=e.split("."),s=n;for(let i=0;i<t.length-1;i++){let c=t[i];if(!s[c]||typeof s[c]!="object")return{removed:!1};s=s[c]}let a=t[t.length-1];return a in s?(delete s[a],await me(this.modelPath,JSON.stringify(n,null,2)),console.log(`${re} Removed token "${e}" from model`),{removed:!0}):{removed:!1}}async removeComponent(e){let n=await this.loadModel();if(!n)return{removed:!1};let t=n.components;return!t||!t[e]?{removed:!1}:(delete t[e],await me(this.modelPath,JSON.stringify(n,null,2)),console.log(`${re} Removed component "${e}" from model`),{removed:!0})}async getUnmaterializedPatternDecisions(){let e=await this.loadIndex(),n=new Set(e.materializedIds),s=(await this.decisionStore.listDecisionIds()).filter(i=>!n.has(i));return s.length===0?[]:(await this.decisionStore.loadDecisions(s)).filter(i=>i.resolutions.some(c=>{var u;let p=(u=c.finalScope)!=null?u:c.inferredScope;return(p==null?void 0:p.breadth)==="pattern"}))}async run(){var e,n,t,s,a,i,c;if(this.running)return{processedIds:[],success:!0,error:"Already running"};this.running=!0;try{let p=await this.getUnmaterializedPatternDecisions();if(p.length===0)return{processedIds:[],success:!0};let u=p.map(P=>P.id);console.log(`${re} Processing ${u.length} pattern-scoped decision(s): ${u.join(", ")}`),(n=(e=this.options).onEvent)==null||n.call(e,{type:"materialize_started",decisionIds:u});let x=await this.loadModel(),G=qt(p,x),w=!0,M;try{let{result:P}=Me(`mat-${Date.now()}`,{prompt:G,projectRoot:this.projectRoot,maxTurns:(t=this.options.maxTurns)!=null?t:5,maxBudgetUsd:(s=this.options.maxBudgetUsd)!=null?s:.5,allowedTools:["Read"],claudePath:(a=this.options.claudePath)!=null?a:"claude"}),j=await P;if(!j.success)w=!1,M=j.error,console.error(`${re} Claude spawn error:`,M);else{let Q=Wt(j.text);Q?(await me(this.modelPath,JSON.stringify(Q,null,2)),console.log(`${re} Successfully materialized ${u.length} decision(s) \u2192 ${this.modelPath}`)):(w=!1,M="No <model> block found in response",console.error(`${re} ${M}`))}}catch(P){w=!1,M=P instanceof Error?P.message:String(P),console.error(`${re} Error:`,M)}let I=await this.loadIndex(),F=new Set(I.materializedIds);for(let P of u)F.add(P);return I.materializedIds=[...F],I.lastRunAt=Date.now(),I.lastRunDecisionIds=u,I.lastRunError=M!=null?M:null,await this.persistIndex(I),(c=(i=this.options).onEvent)==null||c.call(i,{type:"materialize_done",decisionIds:u,success:w,error:M}),{processedIds:u,success:w,error:M}}finally{this.running=!1}}async loadIndex(){if(this.cachedIndex)return this.cachedIndex;try{let e=await at(this.indexPath,"utf-8"),n=JSON.parse(e);return this.cachedIndex=n,n}catch(e){return this.cachedIndex=oe(K({},Ht),{materializedIds:[],lastRunDecisionIds:[]}),this.cachedIndex}}async persistIndex(e){this.cachedIndex=e;try{await me(this.indexPath,JSON.stringify(e,null,2))}catch(n){console.error(`${re} Failed to write index:`,n)}}};function Wt(o){let e=o.match(/<model>\s*([\s\S]*?)\s*<\/model>/);if(!(e!=null&&e[1]))return null;try{let n=JSON.parse(e[1]);return typeof n!="object"||n===null||Array.isArray(n)?null:n}catch(n){return null}}function qt(o,e){let n=o.map(s=>{let i=s.resolutions.filter(u=>{var G;let x=(G=u.finalScope)!=null?G:u.inferredScope;return(x==null?void 0:x.breadth)==="pattern"}).map(u=>{var M,I,F,P;let x=(M=u.finalScope)!=null?M:u.inferredScope,G=(I=x==null?void 0:x.target)!=null?I:"unknown",w=(P=(F=u.filesModified)==null?void 0:F.join(", "))!=null?P:"none";return`- **${u.summary}** [scope: pattern/${G}]
2
+ var Dt=Object.defineProperty,Jt=Object.defineProperties;var Nt=Object.getOwnPropertyDescriptors;var Re=Object.getOwnPropertySymbols;var tt=Object.prototype.hasOwnProperty,nt=Object.prototype.propertyIsEnumerable;var Ze=(o,e)=>(e=Symbol[o])?e:Symbol.for("Symbol."+o);var et=(o,e,n)=>e in o?Dt(o,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):o[e]=n,K=(o,e)=>{for(var n in e||(e={}))tt.call(e,n)&&et(o,n,e[n]);if(Re)for(var n of Re(e))nt.call(e,n)&&et(o,n,e[n]);return o},oe=(o,e)=>Jt(o,Nt(e));var st=(o,e)=>{var n={};for(var t in o)tt.call(o,t)&&e.indexOf(t)<0&&(n[t]=o[t]);if(o!=null&&Re)for(var t of Re(o))e.indexOf(t)<0&&nt.call(o,t)&&(n[t]=o[t]);return n};var le=(o,e,n)=>(e=o[Ze("asyncIterator")])?e.call(o):(o=o[Ze("iterator")](),e={},n=(t,s)=>(s=o[t])&&(e[t]=a=>new Promise((i,c,p)=>(a=s.call(o,a),p=a.done,Promise.resolve(a.value).then(u=>i({value:u,done:p}),c)))),n("next"),n("return"),e);import{spawn as In}from"child_process";import{execFileSync as cn}from"child_process";import{randomUUID as fe}from"crypto";import{mkdir as ln,readdir as dn,stat as un,unlink as pn,writeFile as we}from"fs/promises";import{createServer as hn}from"http";import{tmpdir as fn}from"os";import{join as de}from"path";import{spawn as _t}from"child_process";import{createInterface as Bt}from"readline";function Me(o,e){let{prompt:n,projectRoot:t,maxTurns:s=40,maxBudgetUsd:a=1,allowedTools:i=["Read","Edit","Write","Glob","Grep","Bash"],claudePath:c="claude",resumeSessionId:p,model:u,onEvent:x}=e,G=[];p?G.push("--resume",p,"-p",n):G.push("-p",n),G.push("--output-format","stream-json","--verbose","--max-turns",String(s),"--max-budget-usd",String(a)),u&&G.push("--model",u);for(let I of i)G.push("--allowedTools",I);let w=_t(c,G,{cwd:t,stdio:["ignore","pipe","pipe"],env:oe(K({},process.env),{ANTHROPIC_API_KEY:void 0})}),M=new Promise(I=>{var J;let F,P=[],j=[],Q=!1,ee="",W=Bt({input:w.stdout}),B=new Set;W.on("line",z=>{var $,q,L,X,ke,be,Pe,Te,$e;if(z.trim())try{let Y=JSON.parse(z);Y.session_id&&!F&&(F=Y.session_id);let Je=(q=Y.type)!=null?q:($=Y.event)!=null&&$.type?`event.${Y.event.type}`:"unknown";if(B.add(Je),Y.type==="result"&&Y.result&&P.length===0){let D=typeof Y.result=="string"?Y.result:"";D&&(P.push(D),x==null||x({type:"delta",jobId:o,text:D},o))}if(Y.type==="assistant"&&Array.isArray((L=Y.message)==null?void 0:L.content))for(let D of Y.message.content){if(D.type==="text"&&D.text&&(P.push(D.text),x==null||x({type:"delta",jobId:o,text:D.text},o)),D.type==="tool_use"&&D.name){let ve=((X=D.input)==null?void 0:X.file_path)||((ke=D.input)==null?void 0:ke.path)||void 0;x==null||x(K({type:"tool_use",jobId:o,tool:D.name},ve?{file:ve}:{}),o),D.name==="Edit"&&((be=D.input)!=null&&be.file_path)?j.push({tool:"Edit",file_path:D.input.file_path,old_string:D.input.old_string,new_string:D.input.new_string,replace_all:D.input.replace_all}):D.name==="Write"&&((Pe=D.input)!=null&&Pe.file_path)&&j.push({tool:"Write",file_path:D.input.file_path,content:D.input.content})}D.type==="thinking"&&D.thinking&&(x==null||x({type:"thinking",jobId:o,text:D.thinking},o))}Y.type==="user"&&(($e=(Te=Y.tool_use_result)==null?void 0:Te.file)!=null&&$e.filePath)&&(x==null||x({type:"tool_use",jobId:o,tool:"Read",file:Y.tool_use_result.file.filePath},o))}catch(Y){}});let te=[];(J=w.stderr)==null||J.on("data",z=>{te.push(z.toString())}),w.on("close",z=>{W.close(),z!==0&&z!==null&&(Q=!0,ee=te.join("")||`Claude process exited with code ${z}`),I({sessionId:F,text:P.join(""),success:!Q,error:Q?ee:void 0,fileEdits:j.length>0?j:void 0})}),w.on("error",z=>{Q=!0,ee=z.message,I({sessionId:F,text:P.join(""),success:!1,error:ee,fileEdits:j.length>0?j:void 0})})});return{process:w,result:M}}import{spawn as Ut}from"child_process";import{createInterface as Ft}from"readline";function ot(o,e){let{prompt:n,projectRoot:t,screenshotPath:s,resumeSessionId:a,model:i,onEvent:c}=e,p=[];a?(p.push("exec","resume",a),i&&p.push("-m",i),p.push("--json","--full-auto",n),s&&p.push("--image",s)):(p.push("exec","--json","--full-auto"),i&&p.push("-m",i),p.push(n),s&&p.push("--image",s));let u=Ut("codex",p,{cwd:t,stdio:["ignore","pipe","pipe"],env:K({},process.env)}),x=new Promise(G=>{var ee;let w,M=[],I=!1,F="",P=Ft({input:u.stdout}),j=new Set;P.on("line",W=>{var B,te,J,z;if(W.trim())try{let $=JSON.parse(W),q=(B=$.type)!=null?B:"unknown";if(j.add(q),q==="thread.started"&&$.thread_id&&!w&&(w=$.thread_id),q==="item/agentMessage/delta"&&((te=$.delta)!=null&&te.text)&&(M.push($.delta.text),c==null||c({type:"delta",jobId:o,text:$.delta.text},o)),q==="item/reasoning/delta"&&((J=$.delta)!=null&&J.text)&&(c==null||c({type:"thinking",jobId:o,text:$.delta.text},o)),q==="item/started"&&$.item){let L=$.item.type;if(L==="command_execution")c==null||c({type:"tool_use",jobId:o,tool:"Bash"},o);else if(L==="file_change"){let X=$.item.filename||$.item.path;c==null||c(K({type:"tool_use",jobId:o,tool:"Edit"},X?{file:X}:{}),o)}else if(L==="file_read"){let X=$.item.filename||$.item.path;c==null||c(K({type:"tool_use",jobId:o,tool:"Read"},X?{file:X}:{}),o)}else if(L==="web_search")c==null||c({type:"tool_use",jobId:o,tool:"WebSearch"},o);else if(L==="mcp_tool_call"){let X=$.item.tool_name||$.item.name||"MCP";c==null||c({type:"tool_use",jobId:o,tool:X},o)}}if(q==="item/completed"&&$.item){if($.item.type==="agent_message"){let L=$.item.text;typeof L=="string"&&L&&M.push(L)}else if($.item.type==="reasoning"){let L=$.item.text;typeof L=="string"&&L&&(c==null||c({type:"thinking",jobId:o,text:L},o))}}q==="turn.failed"&&(I=!0,F=((z=$.error)==null?void 0:z.message)||$.message||"Turn failed")}catch($){}});let Q=[];(ee=u.stderr)==null||ee.on("data",W=>{Q.push(W.toString())}),u.on("close",W=>{P.close(),W!==0&&W!==null&&(I=!0,F=Q.join("")||`Codex process exited with code ${W}`),G({sessionId:w,text:M.join(""),success:!I,error:I?F:void 0})}),u.on("error",W=>{I=!0,F=W.message,G({sessionId:w,text:M.join(""),success:!1,error:F})})});return{process:u,result:x}}import{execFile as jt}from"child_process";import{copyFile as rt,mkdir as it,readdir as zt,readFile as Lt,writeFile as Gt}from"fs/promises";import{join as he}from"path";var Oe=class{constructor(e){this.projectRoot=e;let n=he(e,".popmelt");this.decisionsDir=he(n,"decisions"),this.screenshotsDir=he(n,"screenshots")}async persist(e,n,t){try{await it(this.decisionsDir,{recursive:!0}),await it(this.screenshotsDir,{recursive:!0});try{await rt(n,he(this.screenshotsDir,`s-${e.id}.png`))}catch(s){}for(let s=0;s<t.length;s++)try{let a=e.pastedImagePaths[s];a&&await rt(t[s],he(this.screenshotsDir,a.replace("screenshots/","")))}catch(a){}await Gt(he(this.decisionsDir,`d-${e.id}.json`),JSON.stringify(e,null,2))}catch(s){console.error("[DecisionStore] Failed to persist decision record:",s)}}async listDecisionIds(){try{return(await zt(this.decisionsDir)).filter(n=>n.startsWith("d-")&&n.endsWith(".json")).map(n=>n.slice(2,-5))}catch(e){return[]}}async loadDecision(e){try{let n=await Lt(he(this.decisionsDir,`d-${e}.json`),"utf-8");return JSON.parse(n)}catch(n){return null}}async loadDecisions(e){return(await Promise.all(e.map(t=>this.loadDecision(t)))).filter(t=>t!==null)}captureGitDiff(e){return new Promise(n=>{jt("git",["diff","HEAD"],{cwd:e,timeout:5e3,maxBuffer:1024*1024},(t,s)=>{if(t){n(null);return}n(s||null)})})}};import{readFile as at,writeFile as me}from"fs/promises";import{join as _e}from"path";var re="[Materializer]",Ht={version:1,materializedIds:[],lastRunAt:null,lastRunDecisionIds:[],lastRunError:null},Ee=class{constructor(e,n,t={}){this.projectRoot=e;this.decisionStore=n;this.options=t;this.cachedIndex=null;this.running=!1;let s=_e(e,".popmelt");this.indexPath=_e(s,"materialized.json"),this.modelPath=_e(s,"model.json")}get isRunning(){return this.running}async loadModel(){try{let e=await at(this.modelPath,"utf-8");return JSON.parse(e)}catch(e){return null}}async addComponent(e){let n=await this.loadModel();n||(n={tokens:{},components:{},rules:[]}),(!n.components||typeof n.components!="object")&&(n.components={});let t=n.components;return t[e]?{added:!1,alreadyExists:!0}:(t[e]={description:""},await me(this.modelPath,JSON.stringify(n,null,2)),console.log(`${re} Added component "${e}" to model`),{added:!0,alreadyExists:!1})}async updateToken(e,n){let t=await this.loadModel();t||(t={tokens:{},components:{},rules:[]});let s=e.split("."),a=t;for(let p=0;p<s.length-1;p++){let u=s[p];(!a[u]||typeof a[u]!="object")&&(a[u]={}),a=a[u]}let i=s[s.length-1],c;try{c=JSON.parse(n)}catch(p){c=null}if(c&&typeof c=="object"&&c!==null&&"value"in c)a[i]=c;else{let p=a[i];p&&typeof p=="object"&&p!==null&&"value"in p?p.value=n:a[i]=n}return await me(this.modelPath,JSON.stringify(t,null,2)),console.log(`${re} Updated token "${e}" \u2192 "${n.slice(0,80)}"`),{updated:!0}}async removeToken(e){let n=await this.loadModel();if(!n)return{removed:!1};let t=e.split("."),s=n;for(let i=0;i<t.length-1;i++){let c=t[i];if(!s[c]||typeof s[c]!="object")return{removed:!1};s=s[c]}let a=t[t.length-1];return a in s?(delete s[a],await me(this.modelPath,JSON.stringify(n,null,2)),console.log(`${re} Removed token "${e}" from model`),{removed:!0}):{removed:!1}}async removeComponent(e){let n=await this.loadModel();if(!n)return{removed:!1};let t=n.components;return!t||!t[e]?{removed:!1}:(delete t[e],await me(this.modelPath,JSON.stringify(n,null,2)),console.log(`${re} Removed component "${e}" from model`),{removed:!0})}async getUnmaterializedPatternDecisions(){let e=await this.loadIndex(),n=new Set(e.materializedIds),s=(await this.decisionStore.listDecisionIds()).filter(i=>!n.has(i));return s.length===0?[]:(await this.decisionStore.loadDecisions(s)).filter(i=>i.resolutions.some(c=>{var u;let p=(u=c.finalScope)!=null?u:c.inferredScope;return(p==null?void 0:p.breadth)==="pattern"}))}async run(){var e,n,t,s,a,i,c;if(this.running)return{processedIds:[],success:!0,error:"Already running"};this.running=!0;try{let p=await this.getUnmaterializedPatternDecisions();if(p.length===0)return{processedIds:[],success:!0};let u=p.map(P=>P.id);console.log(`${re} Processing ${u.length} pattern-scoped decision(s): ${u.join(", ")}`),(n=(e=this.options).onEvent)==null||n.call(e,{type:"materialize_started",decisionIds:u});let x=await this.loadModel(),G=qt(p,x),w=!0,M;try{let{result:P}=Me(`mat-${Date.now()}`,{prompt:G,projectRoot:this.projectRoot,maxTurns:(t=this.options.maxTurns)!=null?t:5,maxBudgetUsd:(s=this.options.maxBudgetUsd)!=null?s:.5,allowedTools:["Read"],claudePath:(a=this.options.claudePath)!=null?a:"claude"}),j=await P;if(!j.success)w=!1,M=j.error,console.error(`${re} Claude spawn error:`,M);else{let Q=Wt(j.text);Q?(await me(this.modelPath,JSON.stringify(Q,null,2)),console.log(`${re} Successfully materialized ${u.length} decision(s) \u2192 ${this.modelPath}`)):(w=!1,M="No <model> block found in response",console.error(`${re} ${M}`))}}catch(P){w=!1,M=P instanceof Error?P.message:String(P),console.error(`${re} Error:`,M)}let I=await this.loadIndex(),F=new Set(I.materializedIds);for(let P of u)F.add(P);return I.materializedIds=[...F],I.lastRunAt=Date.now(),I.lastRunDecisionIds=u,I.lastRunError=M!=null?M:null,await this.persistIndex(I),(c=(i=this.options).onEvent)==null||c.call(i,{type:"materialize_done",decisionIds:u,success:w,error:M}),{processedIds:u,success:w,error:M}}finally{this.running=!1}}async loadIndex(){if(this.cachedIndex)return this.cachedIndex;try{let e=await at(this.indexPath,"utf-8"),n=JSON.parse(e);return this.cachedIndex=n,n}catch(e){return this.cachedIndex=oe(K({},Ht),{materializedIds:[],lastRunDecisionIds:[]}),this.cachedIndex}}async persistIndex(e){this.cachedIndex=e;try{await me(this.indexPath,JSON.stringify(e,null,2))}catch(n){console.error(`${re} Failed to write index:`,n)}}};function Wt(o){let e=o.match(/<model>\s*([\s\S]*?)\s*<\/model>/);if(!(e!=null&&e[1]))return null;try{let n=JSON.parse(e[1]);return typeof n!="object"||n===null||Array.isArray(n)?null:n}catch(n){return null}}function qt(o,e){let n=o.map(s=>{let i=s.resolutions.filter(u=>{var G;let x=(G=u.finalScope)!=null?G:u.inferredScope;return(x==null?void 0:x.breadth)==="pattern"}).map(u=>{var M,I,F,P;let x=(M=u.finalScope)!=null?M:u.inferredScope,G=(I=x==null?void 0:x.target)!=null?I:"unknown",w=(P=(F=u.filesModified)==null?void 0:F.join(", "))!=null?P:"none";return`- **${u.summary}** [scope: pattern/${G}]
3
3
  Files modified: ${w}`}).join(`
4
4
  `),c=s.annotations.map(u=>u.instruction).filter(Boolean).join(`
5
5
  `),p=s.gitDiff?`
@@ -87,7 +87,7 @@ url = "${o}"
87
87
  `)}function Mt(o){let e=o.match(/<review>\s*([\s\S]*?)\s*<\/review>/);if(!(e!=null&&e[1]))return null;try{let n=JSON.parse(e[1]);return typeof n!="object"||n===null||n.verdict!=="pass"&&n.verdict!=="fail"||typeof n.summary!="string"?null:{verdict:n.verdict,summary:n.summary,issues:Array.isArray(n.issues)?n.issues.filter(t=>typeof t=="string"):void 0}}catch(n){return null}}var Ae=class{constructor(e=5){this.queue=[];this.activeJobs=new Map;this.activeProcesses=new Map;this.listeners=new Set;this.processor=null;this.maxConcurrency=e}setProcessor(e){this.processor=e}get active(){let e=this.activeJobs.values().next();return e.done?null:e.value}get allActive(){return Array.from(this.activeJobs.values())}get activeCount(){return this.activeJobs.size}get depth(){return this.queue.length}get isRunning(){return this.activeJobs.size>0}setActiveProcess(e,n){n?this.activeProcesses.set(e,n):this.activeProcesses.delete(e)}enqueue(e){return this.queue.push(e),this.processNext(),this.queue.length+this.activeJobs.size}addListener(e){return this.listeners.add(e),()=>this.listeners.delete(e)}broadcast(e,n){for(let t of this.listeners)t(e,n)}cancelJob(e){let n=this.activeProcesses.get(e),t=this.activeJobs.get(e);return!n||!t?!1:(n.kill("SIGTERM"),this.activeProcesses.delete(e),this.activeJobs.delete(e),t.status="error",t.error="Cancelled by user",this.broadcast({type:"error",jobId:t.id,message:"Cancelled by user"},t.id),this.processNext(),!0)}cancelActive(){if(this.activeJobs.size===0)return!1;let e=Array.from(this.activeJobs.keys());for(let n of e)this.cancelJob(n);return!0}destroy(){for(let e of this.activeProcesses.values())e.kill("SIGTERM");this.activeProcesses.clear(),this.activeJobs.clear(),this.queue=[],this.listeners.clear()}processNext(){for(;this.activeJobs.size<this.maxConcurrency&&this.queue.length>0&&this.processor;){let e=this.queue.shift();this.activeJobs.set(e.id,e),e.status="running",this.broadcast({type:"job_started",jobId:e.id,position:0},e.id),this.processor(e).catch(n=>{e.status="error",e.error=n instanceof Error?n.message:String(n),this.broadcast({type:"error",jobId:e.id,message:e.error},e.id)}).finally(()=>{this.activeJobs.delete(e.id),this.activeProcesses.delete(e.id),this.processNext(),this.activeJobs.size===0&&this.queue.length===0&&this.broadcast({type:"queue_drained"},e.id)})}}};import{mkdir as tn,readFile as nn,writeFile as sn}from"fs/promises";import{dirname as on,join as rn}from"path";var an={version:1,threads:{}},De=class{constructor(e){this.cache=null;this.writeChain=Promise.resolve();this.filePath=rn(e,".popmelt","threads.json")}async load(){if(this.cache)return this.cache;try{let e=await nn(this.filePath,"utf-8"),n=JSON.parse(e);if(n&&n.version===1&&n.threads)return this.cache=n,this.cache}catch(e){}return this.cache=oe(K({},an),{threads:{}}),this.cache}async getThread(e){var t;return(t=(await this.load()).threads[e])!=null?t:null}async findContinuationThread(e){if(e.length===0)return null;let n=await this.load(),t=new Set(e);for(let s of Object.values(n.threads))if(s.elementIdentifiers.some(i=>t.has(i)))return s;return null}async createThread(e,n){let t=await this.load(),s={id:e,createdAt:Date.now(),updatedAt:Date.now(),elementIdentifiers:n,messages:[]};return t.threads[e]=s,await this.persist(),s}async appendMessage(e,n){let s=(await this.load()).threads[e];s&&(s.messages.push(n),s.updatedAt=Date.now(),await this.persist())}async addElementIdentifiers(e,n){let s=(await this.load()).threads[e];if(!s)return;let a=new Set(s.elementIdentifiers);for(let i of n)a.has(i)||s.elementIdentifiers.push(i);s.updatedAt=Date.now(),await this.persist()}async getThreadHistory(e,n=6){let t=await this.getThread(e);return!t||t.messages.length===0?[]:t.messages.length<=n?t.messages:[t.messages[0],...t.messages.slice(-(n-1))]}async persist(){this.writeChain=this.writeChain.then(async()=>{if(this.cache)try{await tn(on(this.filePath),{recursive:!0}),await sn(this.filePath,JSON.stringify(this.cache,null,2))}catch(e){console.error("[ThreadStore] Failed to persist:",e)}}),await this.writeChain}};var mn=1111,gn=["Read","Edit","Write","Glob","Grep","Bash","WebFetch","WebSearch","Bash(curl:*)"],yn=1800*1e3,wn=3600*1e3;function vn(o){if(!o)return!1;try{let e=new URL(o);return e.hostname==="localhost"||e.hostname==="127.0.0.1"}catch(e){return!1}}function Sn(o,e){let n=o.headers.origin;vn(n)&&(e.setHeader("Access-Control-Allow-Origin",n),e.setHeader("Access-Control-Allow-Methods","GET, POST, PATCH, DELETE, OPTIONS"),e.setHeader("Access-Control-Allow-Headers","Content-Type"))}function g(o,e,n){o.writeHead(e,{"Content-Type":"application/json"}),o.end(JSON.stringify(n))}function xn(o,e){if(!o)return e;let n=o.match(/^#?([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i);if(!n)return e;let[,t,s,a]=n;return`\x1B[38;2;${parseInt(t,16)};${parseInt(s,16)};${parseInt(a,16)}m${e}\x1B[0m`}function Ot(o,e){try{o.res.write(`event: ${e.type}
88
88
  data: ${JSON.stringify(e)}
89
89
 
90
- `)}catch(n){}}async function Ge(o={}){var ve,He,We,qe,Ye,Qe,Ke,Ve;let e=(ve=o.port)!=null?ve:mn,n=(He=o.projectRoot)!=null?He:process.cwd(),t=(We=o.tempDir)!=null?We:de(fn(),"popmelt-bridge"),s=(qe=o.maxTurns)!=null?qe:10,a=(Ye=o.maxBudgetUsd)!=null?Ye:1,i=(Qe=o.allowedTools)!=null?Qe:gn,c=(Ke=o.claudePath)!=null?Ke:"claude",p=(Ve=o.provider)!=null?Ve:"claude",u={};for(let r of["claude","codex"])try{let l=cn("which",[r],{encoding:"utf-8"}).trim();u[r]={available:!0,path:l}}catch(l){u[r]={available:!1,path:null}}let[x,G]=await Promise.all([je(n),ze(n)]);u.claude&&(u.claude.mcp=x),u.codex&&(u.codex.mcp=G),await ln(t,{recursive:!0}),Et(t).catch(()=>{});let w=new Ae(1),M=new Set,I=new De(n),F=new Oe(n),P=new Ee(n,F,{claudePath:c,onEvent:r=>{for(let l of M)Ot(l,r)}}),j=new Map;w.addListener((r,l)=>{for(let h of M)Ot(h,r)}),w.setProcessor(async r=>{var V,se,C,ne,ce,Se,ue;let l=r._replyPrompt,h=r._replyImagePaths,d=(V=r.provider)!=null?V:p,f;if(r.threadId){let R=await I.getThread(r.threadId);if(R){for(let m=R.messages.length-1;m>=0;m--)if(R.messages[m].sessionId){f=R.messages[m].sessionId;break}}}let b;if(f&&l){let R=(se=await I.getThread(r.threadId))==null?void 0:se.messages.filter(O=>O.role==="human").pop();if(b=(R==null?void 0:R.replyToQuestion)||(R==null?void 0:R.feedbackSummary)||"",h&&h.length>0){b+=`
90
+ `)}catch(n){}}async function Ge(o={}){var ve,He,We,qe,Ye,Qe,Ke,Ve;let e=(ve=o.port)!=null?ve:mn,n=(He=o.projectRoot)!=null?He:process.cwd(),t=(We=o.tempDir)!=null?We:de(fn(),"popmelt-bridge"),s=(qe=o.maxTurns)!=null?qe:40,a=(Ye=o.maxBudgetUsd)!=null?Ye:1,i=(Qe=o.allowedTools)!=null?Qe:gn,c=(Ke=o.claudePath)!=null?Ke:"claude",p=(Ve=o.provider)!=null?Ve:"claude",u={};for(let r of["claude","codex"])try{let l=cn("which",[r],{encoding:"utf-8"}).trim();u[r]={available:!0,path:l}}catch(l){u[r]={available:!1,path:null}}let[x,G]=await Promise.all([je(n),ze(n)]);u.claude&&(u.claude.mcp=x),u.codex&&(u.codex.mcp=G),await ln(t,{recursive:!0}),Et(t).catch(()=>{});let w=new Ae(1),M=new Set,I=new De(n),F=new Oe(n),P=new Ee(n,F,{claudePath:c,onEvent:r=>{for(let l of M)Ot(l,r)}}),j=new Map;w.addListener((r,l)=>{for(let h of M)Ot(h,r)}),w.setProcessor(async r=>{var V,se,C,ne,ce,Se,ue;let l=r._replyPrompt,h=r._replyImagePaths,d=(V=r.provider)!=null?V:p,f;if(r.threadId){let R=await I.getThread(r.threadId);if(R){for(let m=R.messages.length-1;m>=0;m--)if(R.messages[m].sessionId){f=R.messages[m].sessionId;break}}}let b;if(f&&l){let R=(se=await I.getThread(r.threadId))==null?void 0:se.messages.filter(O=>O.role==="human").pop();if(b=(R==null?void 0:R.replyToQuestion)||(R==null?void 0:R.feedbackSummary)||"",h&&h.length>0){b+=`
91
91
 
92
92
  The developer attached reference images with their reply:`;for(let O of h)b+=`
93
93
  Attached image: use the Read tool to view the image at: ${O}`}b+=`