@popmelt.com/core 0.7.3 → 0.7.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/bridge-entry.mjs +1 -1
- package/dist/cli.mjs +2 -2
- package/dist/index.mjs +20 -20
- package/dist/plugin-astro.mjs +1 -1
- package/dist/plugin-vite.mjs +1 -1
- package/dist/{server-5Q2HPNSJ.mjs → server-X7YF2NX2.mjs} +1 -1
- package/dist/server.mjs +1 -1
- package/package.json +1 -1
package/dist/bridge-entry.mjs
CHANGED
|
@@ -328,7 +328,7 @@ url = "${s}"
|
|
|
328
328
|
`)}function cn(s){return s.match(/<question>\s*([\s\S]*?)\s*<\/question>/)?.[1]??null}function ln(s,t,n,e){let o=[];o.push("You are continuing work on a UI based on the developer's reply to your question."),o.push(""),n!=="codex"&&o.push(`IMPORTANT: First, use the Read tool to view the screenshot at: ${s}`);let i=t.find(c=>c.role==="human"&&c.feedbackContext);if(i?.feedbackContext&&(o.push(""),o.push(i.feedbackContext)),t.length>0){o.push(""),o.push("## Conversation History");let c=0;for(let a of t)a.role==="human"?(c++,a.replyToQuestion?(o.push(`### Round ${c} (human) \u2014 reply`),o.push(`"${a.replyToQuestion}"`)):(o.push(`### Round ${c} (human)`),a.feedbackSummary&&o.push(`Annotations: ${a.feedbackSummary}`))):a.question?(o.push(`### Round ${c} (assistant) \u2014 question`),o.push(`"${a.question}"`)):(o.push(`### Round ${c} (assistant)`),a.responseText&&o.push(`Response: ${a.responseText}`))}if(o.push(""),o.push("The developer answered your question. Continue working based on their reply."),o.push("Follow their instructions \u2014 apply code changes only if requested. The dev server has HMR so changes appear immediately."),o.push(""),o.push("IMPORTANT: If any elements you modify have a `data-pm` attribute, preserve it in the source. This attribute tracks annotation positions."),e&&e.length>0){o.push(""),o.push("## Attached Images"),o.push("The developer attached reference images with their reply:");for(let c of e)o.push(`Attached image: use the Read tool to view the image at: ${c}`)}return o.push(""),o.push("## Resolution"),o.push("After completing all work, output a resolution block listing what you did for each annotation:"),o.push("<resolution>"),o.push('[{"annotationId":"<id>","status":"resolved","summary":"<what you did>","filesModified":["<file>"],"declaredScope":{"breadth":"...","target":"..."},"inferredScope":{"breadth":"...","target":"..."}}]'),o.push("</resolution>"),o.push(`Use status "resolved" when the change is complete, or "needs_review" if you're unsure about the result.`),o.push(""),o.push("### Scope classification"),o.push("Each resolution MUST include scope fields:"),o.push("- `declaredScope`: What scope the user's instruction text implies. null if no signal."),o.push("- `inferredScope`: What scope the change actually has, based on what you modified."),o.push("Scope has two dimensions:"),o.push('- `breadth`: "instance" (just this occurrence) or "pattern" (all similar occurrences)'),o.push('- `target`: "element" (a specific DOM element), "component" (a React/UI component), or "token" (a design token \u2014 color, spacing, typography)'),o.push('Note: "instance" + "token" is invalid \u2014 tokens are inherently patterns.'),o.push("If you cannot confidently determine scope, set it to null."),o.push('If the developer\'s reply corrects a prior scope classification (e.g., "this should apply everywhere" or "only fix this one"), set `finalScope` on your resolution to reflect their correction and apply the change at the corrected scope.'),o.push(""),o.push("## Questions"),o.push("If you still need clarification, output:"),o.push("<question>Your question here</question>"),o.push("You may output BOTH a <resolution> and a <question> in the same response."),o.join(`
|
|
329
329
|
`)}function no(s){if(typeof s!="object"||s===null)return!1;let t=s;return(t.breadth==="instance"||t.breadth==="pattern")&&(t.target==="element"||t.target==="component"||t.target==="token")}function so(s){if(typeof s!="object"||s===null||typeof s.annotationId!="string"||s.status!=="resolved"&&s.status!=="needs_review"||typeof s.summary!="string")return!1;let t=s;for(let n of["declaredScope","inferredScope","finalScope"])if(t[n]!==void 0&&t[n]!==null&&!no(t[n]))return!1;return!0}function dn(s){let t=s.match(/<resolution>\s*([\s\S]*?)\s*<\/resolution>/);if(!t||!t[1])return[];try{let n=JSON.parse(t[1]);return Array.isArray(n)?n.filter(so):[]}catch{return[]}}function un(s){let t=s.match(/<novel>\s*([\s\S]*?)\s*<\/novel>/);if(!t?.[1])return[];try{let n=JSON.parse(t[1]);return Array.isArray(n)?n.filter(e=>{if(typeof e!="object"||e===null)return!1;let o=e;return(o.category==="token"||o.category==="component"||o.category==="element")&&typeof o.element=="string"&&typeof o.decision=="string"&&typeof o.reason=="string"}):[]}catch{return[]}}import{execFile as oo}from"child_process";import{readdir as ro,readFile as io,stat as ao}from"fs/promises";import{homedir as Ce}from"os";import{join as me}from"path";var Ye=[{id:"claude-opus-4-6",label:"Opus 4.6",source:"static"},{id:"claude-sonnet-4-6",label:"Sonn 4.6",source:"static"}],$e=[{id:"gpt-5.4",label:"GPT 5.4",source:"static"},{id:"gpt-5.3-codex",label:"Codex 5.3",source:"static"},{id:"gpt-5.3-codex-spark",label:"Spark 5.3",source:"static"}],_e={id:"",label:"Default",source:"cli"},co=/^\s*-\s+"([^"]+)"/;function lo(s){let t=[],n=!1;for(let e of s.split(`
|
|
330
330
|
`)){if(/^\s*`model`:/.test(e)){n=!0;continue}if(n&&/^\s*`[^`]+`:/.test(e))break;if(!n)continue;let o=e.match(co);if(!o?.[1])continue;let i=o[1];t.push({id:i,label:ht(i),source:"cli"})}return Ke([_e,...t])}function uo(s){let t=JSON.parse(s);return(Array.isArray(t.models)?t.models:[]).filter(e=>e.visibility===void 0||e.visibility==="list").sort((e,o)=>{let i=typeof e.priority=="number"?e.priority:Number.MAX_SAFE_INTEGER,c=typeof o.priority=="number"?o.priority:Number.MAX_SAFE_INTEGER;return i-c}).flatMap(e=>{let o=typeof e.slug=="string"?e.slug:typeof e.id=="string"?e.id:"";if(!o)return[];let i=typeof e.display_name=="string"&&e.display_name.trim()?e.display_name.trim():ht(o);return[{id:o,label:i,source:"cli"}]})}function po(s){let t=s.match(/\bclaude-[a-z0-9]+(?:[-.][a-z0-9]+)*\b/gi)??[];return Ke(t.map(n=>({id:n,label:ht(n),source:"cli"})))}function ht(s){if(!s)return"Default";let t={"gpt-5.5":"GPT 5.5","gpt-5.4":"GPT 5.4","gpt-5.4-mini":"Mini 5.4","gpt-5.3-codex":"Codex 5.3","gpt-5.3-codex-spark":"Spark 5.3","gpt-5.2-codex":"Codex 5.2","gpt-5.2":"GPT 5.2","gpt-5.1":"GPT 5.1","gpt-5-mini":"Mini 5","gpt-4.1":"GPT 4.1","claude-opus-4.7":"Opus 4.7","claude-opus-4.6":"Opus 4.6","claude-opus-4.6-fast":"Opus 4.6 Fast","claude-opus-4.5":"Opus 4.5","claude-sonnet-4.6":"Sonn 4.6","claude-sonnet-4.5":"Sonn 4.5","claude-sonnet-4":"Sonn 4","claude-haiku-4.5":"Haiku 4.5","claude-fable":"Fable"},n=s.replace(/-\d{8,}$/,"");if(t[s])return t[s];if(t[n])return t[n];let e=n.match(/^claude-(opus|sonnet|haiku|fable)(?:-(\d+)[-.](\d+))?(?:-(fast))?$/);if(e){let i=e[1]==="sonnet"?"Sonn":go(e[1]),c=e[2]&&e[3]?` ${e[2]}.${e[3]}`:"";return`${i}${c}${e[4]?" Fast":""}`}let o=n.match(/^gpt-(\d+)(?:[.-](\d+))?(?:-(mini|codex|spark))?$/);if(o){let i=o[2]?`${o[1]}.${o[2]}`:o[1];return o[3]==="mini"?`Mini ${i}`:o[3]==="codex"?`Codex ${i}`:o[3]==="spark"?`Spark ${i}`:`GPT ${i}`}return n}async function pn(s="copilot"){let t=await qe(s,["help","config"]),n=lo(t);return n.length>1?n:[_e]}async function fn(s="codex"){let t=await qe(s,["debug","models"]).catch(async()=>{let e=process.env.CODEX_HOME||me(Ce(),".codex");return mn(me(e,"models_cache.json"))}),n=uo(t);return n.length>0?Ke([...n,...$e]):$e}async function hn(s="claude"){let t=me(Ce(),".claude"),n=[me(Ce(),".claude","stats-cache.json"),me(Ce(),".claude","settings.json"),me(Ce(),".claude.json"),me(t,"cache","changelog.md")],[e,o,i]=await Promise.all([qe(s,["--help"]).catch(()=>""),qe(s,["--version"]).catch(()=>""),fo(t).catch(()=>[])]),c=mo([...n,...i]),a=await Promise.all(c.map(P=>mn(P).catch(()=>""))),m=po([e,o,...a].join(`
|
|
331
|
-
`));return Ke([...Ye,...m])}function qe(s,t,n=5e3){return new Promise((e,o)=>{oo(s,t,{encoding:"utf-8",timeout:n},(i,c)=>{if(i){o(i);return}e(c)})})}async function mn(s){return io(s,"utf-8")}async function fo(s){let t=[me(s,"projects"),me(s,"telemetry")],n=[];for(let e of t)await gn(e,n,4);return n.sort((e,o)=>o.mtimeMs-e.mtimeMs).slice(0,80).map(e=>e.path)}async function gn(s,t,n){if(n<0)return;let e;try{e=await ro(s,{withFileTypes:!0})}catch{return}await Promise.all(e.map(async o=>{let i=me(s,o.name);if(o.isDirectory()){await gn(i,t,n-1);return}if(!(!o.isFile()||!ho(o.name)))try{let c=await ao(i);if(c.size>2e6)return;t.push({path:i,mtimeMs:c.mtimeMs})}catch{}}))}function ho(s){return s.endsWith(".json")||s.endsWith(".jsonl")||s.endsWith(".md")||s.endsWith(".txt")}function Ke(s){let t=new Set,n=[];for(let e of s)t.has(e.id)||(t.add(e.id),n.push(e));return n}function mo(s){return[...new Set(s)]}function go(s){return s.charAt(0).toUpperCase()+s.slice(1)}var Qe=class{constructor(t=5){this.queue=[];this.activeJobs=new Map;this.activeProcesses=new Map;this.listeners=new Set;this.processor=null;this.eventBuffers=new Map;this.accumulators=new Map;this.cleanupTimers=new Map;this.maxConcurrency=t}setProcessor(t){this.processor=t}get active(){let t=this.activeJobs.values().next();return t.done?null:t.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(t,n){n?this.activeProcesses.set(t,n):this.activeProcesses.delete(t)}enqueue(t){return this.queue.push(t),this.processNext(),this.queue.length+this.activeJobs.size}addListener(t){return this.listeners.add(t),()=>this.listeners.delete(t)}broadcast(t,n,e){let o=this.bufferEvent(n,t);for(let i of this.listeners)i(o,n,e)}bufferEvent(t,n){let e=this.eventBuffers.get(t);e||(e={events:[],nextSeq:0},this.eventBuffers.set(t,e));let o={...n,seq:e.nextSeq++};return e.events.push(o),e.events.length>1e4&&e.events.splice(0,e.events.length-1e4),o}getBufferedEvents(t,n=-1){let e=this.eventBuffers.get(t),o=this.accumulators.get(t)??{response:"",thinking:""},i=this.activeJobs.has(t);if(!e)return null;let c=n<0?e.events:e.events.filter(a=>a.seq>n);return{jobId:t,events:c,currentSeq:e.nextSeq-1,accumulated:{...o},jobActive:i}}accumulateText(t,n,e){let o=this.accumulators.get(t);o||(o={response:"",thinking:""},this.accumulators.set(t,o)),o[n]+=e}getAccumulated(t){return this.accumulators.get(t)??null}scheduleBufferCleanup(t){let n=this.cleanupTimers.get(t);n&&clearTimeout(n);let e=setTimeout(()=>{this.eventBuffers.delete(t),this.accumulators.delete(t),this.cleanupTimers.delete(t)},6e4);this.cleanupTimers.set(t,e)}cancelJob(t){let n=this.activeProcesses.get(t),e=this.activeJobs.get(t);return!n||!e?!1:(n.kill("SIGTERM"),this.activeProcesses.delete(t),this.activeJobs.delete(t),e.status="error",e.error="Cancelled by user",this.broadcast({type:"error",jobId:e.id,threadId:e.threadId,message:"Cancelled by user",cancelled:!0,provider:e.provider,model:e.model},e.id,e.sourceId),this.processNext(),!0)}cancelActive(){if(this.activeJobs.size===0)return!1;let t=Array.from(this.activeJobs.keys());for(let n of t)this.cancelJob(n);return!0}destroy(){for(let t of this.activeProcesses.values())t.kill("SIGTERM");this.activeProcesses.clear(),this.activeJobs.clear(),this.queue=[],this.listeners.clear(),this.eventBuffers.clear(),this.accumulators.clear();for(let t of this.cleanupTimers.values())clearTimeout(t);this.cleanupTimers.clear()}async destroyAsync(t=1e4){let n=Array.from(this.activeProcesses.values());if(this.queue=[],this.listeners.clear(),n.length===0){this.activeProcesses.clear(),this.activeJobs.clear();return}for(let e of n)try{e.kill("SIGTERM")}catch{}await Promise.all(n.map(e=>new Promise(o=>{let i=!1,c=()=>{i||(i=!0,o())};e.on("exit",c),e.on("error",c),setTimeout(()=>{if(!i){try{e.kill("SIGKILL")}catch{}setTimeout(c,500)}},t)}))),this.activeProcesses.clear(),this.activeJobs.clear(),this.eventBuffers.clear(),this.accumulators.clear();for(let e of this.cleanupTimers.values())clearTimeout(e);this.cleanupTimers.clear()}processNext(){for(;this.activeJobs.size<this.maxConcurrency&&this.queue.length>0&&this.processor;){let t=this.queue.shift();this.activeJobs.set(t.id,t),t.status="running",this.broadcast({type:"job_started",jobId:t.id,position:0,threadId:t.threadId},t.id,t.sourceId),this.processor(t).catch(n=>{t.status="error",t.error=n instanceof Error?n.message:String(n),this.broadcast({type:"error",jobId:t.id,threadId:t.threadId,message:t.error,provider:t.provider,model:t.model},t.id,t.sourceId)}).finally(()=>{this.activeJobs.delete(t.id),this.activeProcesses.delete(t.id),this.scheduleBufferCleanup(t.id),this.processNext(),this.activeJobs.size===0&&this.queue.length===0&&this.broadcast({type:"queue_drained"},t.id)})}}};import{mkdir as vo,readFile as yo,writeFile as wo}from"fs/promises";import{dirname as So,join as bo}from"path";var xo={version:1,threads:{}},Ve=class{constructor(t){this.cache=null;this.writeChain=Promise.resolve();this.filePath=bo(t,".popmelt","threads.json")}async load(){if(this.cache)return this.cache;try{let t=await yo(this.filePath,"utf-8"),n=JSON.parse(t);if(n&&n.version===1&&n.threads)return this.cache=n,this.cache}catch{}return this.cache={...xo,threads:{}},this.cache}async getThread(t){return(await this.load()).threads[t]??null}async findContinuationThread(t){if(t.length===0)return null;let n=await this.load(),e=new Set(t);for(let o of Object.values(n.threads))if(o.elementIdentifiers.some(c=>e.has(c)))return o;return null}async createThread(t,n){let e=await this.load(),o={id:t,createdAt:Date.now(),updatedAt:Date.now(),elementIdentifiers:n,messages:[]};return e.threads[t]=o,await this.persist(),o}async appendMessage(t,n){let o=(await this.load()).threads[t];o&&(o.messages.push(n),o.updatedAt=Date.now(),await this.persist())}async addElementIdentifiers(t,n){let o=(await this.load()).threads[t];if(!o)return;let i=new Set(o.elementIdentifiers);for(let c of n)i.has(c)||o.elementIdentifiers.push(c);o.updatedAt=Date.now(),await this.persist()}async listRecent(t=5){let n=await this.load(),e=Object.values(n.threads);return e.sort((o,i)=>i.updatedAt-o.updatedAt),e.slice(0,t).map(o=>{let c=o.messages.find(a=>a.role==="human")?.feedbackSummary||"[thread]";return{id:o.id,createdAt:o.createdAt,updatedAt:o.updatedAt,preview:c,messageCount:o.messages.length,elementIdentifiers:o.elementIdentifiers}})}async getThreadHistory(t,n=6){let e=await this.getThread(t);return!e||e.messages.length===0?[]:e.messages.length<=n?e.messages:[e.messages[0],...e.messages.slice(-(n-1))]}async persist(){this.writeChain=this.writeChain.then(async()=>{if(this.cache)try{await vo(So(this.filePath),{recursive:!0}),await wo(this.filePath,JSON.stringify(this.cache,null,2))}catch(t){console.error("[ThreadStore] Failed to persist:",t)}}),await this.writeChain}};var vn="0.7.
|
|
331
|
+
`));return Ke([...Ye,...m])}function qe(s,t,n=5e3){return new Promise((e,o)=>{oo(s,t,{encoding:"utf-8",timeout:n},(i,c)=>{if(i){o(i);return}e(c)})})}async function mn(s){return io(s,"utf-8")}async function fo(s){let t=[me(s,"projects"),me(s,"telemetry")],n=[];for(let e of t)await gn(e,n,4);return n.sort((e,o)=>o.mtimeMs-e.mtimeMs).slice(0,80).map(e=>e.path)}async function gn(s,t,n){if(n<0)return;let e;try{e=await ro(s,{withFileTypes:!0})}catch{return}await Promise.all(e.map(async o=>{let i=me(s,o.name);if(o.isDirectory()){await gn(i,t,n-1);return}if(!(!o.isFile()||!ho(o.name)))try{let c=await ao(i);if(c.size>2e6)return;t.push({path:i,mtimeMs:c.mtimeMs})}catch{}}))}function ho(s){return s.endsWith(".json")||s.endsWith(".jsonl")||s.endsWith(".md")||s.endsWith(".txt")}function Ke(s){let t=new Set,n=[];for(let e of s)t.has(e.id)||(t.add(e.id),n.push(e));return n}function mo(s){return[...new Set(s)]}function go(s){return s.charAt(0).toUpperCase()+s.slice(1)}var Qe=class{constructor(t=5){this.queue=[];this.activeJobs=new Map;this.activeProcesses=new Map;this.listeners=new Set;this.processor=null;this.eventBuffers=new Map;this.accumulators=new Map;this.cleanupTimers=new Map;this.maxConcurrency=t}setProcessor(t){this.processor=t}get active(){let t=this.activeJobs.values().next();return t.done?null:t.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(t,n){n?this.activeProcesses.set(t,n):this.activeProcesses.delete(t)}enqueue(t){return this.queue.push(t),this.processNext(),this.queue.length+this.activeJobs.size}addListener(t){return this.listeners.add(t),()=>this.listeners.delete(t)}broadcast(t,n,e){let o=this.bufferEvent(n,t);for(let i of this.listeners)i(o,n,e)}bufferEvent(t,n){let e=this.eventBuffers.get(t);e||(e={events:[],nextSeq:0},this.eventBuffers.set(t,e));let o={...n,seq:e.nextSeq++};return e.events.push(o),e.events.length>1e4&&e.events.splice(0,e.events.length-1e4),o}getBufferedEvents(t,n=-1){let e=this.eventBuffers.get(t),o=this.accumulators.get(t)??{response:"",thinking:""},i=this.activeJobs.has(t);if(!e)return null;let c=n<0?e.events:e.events.filter(a=>a.seq>n);return{jobId:t,events:c,currentSeq:e.nextSeq-1,accumulated:{...o},jobActive:i}}accumulateText(t,n,e){let o=this.accumulators.get(t);o||(o={response:"",thinking:""},this.accumulators.set(t,o)),o[n]+=e}getAccumulated(t){return this.accumulators.get(t)??null}scheduleBufferCleanup(t){let n=this.cleanupTimers.get(t);n&&clearTimeout(n);let e=setTimeout(()=>{this.eventBuffers.delete(t),this.accumulators.delete(t),this.cleanupTimers.delete(t)},6e4);this.cleanupTimers.set(t,e)}cancelJob(t){let n=this.activeProcesses.get(t),e=this.activeJobs.get(t);return!n||!e?!1:(n.kill("SIGTERM"),this.activeProcesses.delete(t),this.activeJobs.delete(t),e.status="error",e.error="Cancelled by user",this.broadcast({type:"error",jobId:e.id,threadId:e.threadId,message:"Cancelled by user",cancelled:!0,provider:e.provider,model:e.model},e.id,e.sourceId),this.processNext(),!0)}cancelActive(){if(this.activeJobs.size===0)return!1;let t=Array.from(this.activeJobs.keys());for(let n of t)this.cancelJob(n);return!0}destroy(){for(let t of this.activeProcesses.values())t.kill("SIGTERM");this.activeProcesses.clear(),this.activeJobs.clear(),this.queue=[],this.listeners.clear(),this.eventBuffers.clear(),this.accumulators.clear();for(let t of this.cleanupTimers.values())clearTimeout(t);this.cleanupTimers.clear()}async destroyAsync(t=1e4){let n=Array.from(this.activeProcesses.values());if(this.queue=[],this.listeners.clear(),n.length===0){this.activeProcesses.clear(),this.activeJobs.clear();return}for(let e of n)try{e.kill("SIGTERM")}catch{}await Promise.all(n.map(e=>new Promise(o=>{let i=!1,c=()=>{i||(i=!0,o())};e.on("exit",c),e.on("error",c),setTimeout(()=>{if(!i){try{e.kill("SIGKILL")}catch{}setTimeout(c,500)}},t)}))),this.activeProcesses.clear(),this.activeJobs.clear(),this.eventBuffers.clear(),this.accumulators.clear();for(let e of this.cleanupTimers.values())clearTimeout(e);this.cleanupTimers.clear()}processNext(){for(;this.activeJobs.size<this.maxConcurrency&&this.queue.length>0&&this.processor;){let t=this.queue.shift();this.activeJobs.set(t.id,t),t.status="running",this.broadcast({type:"job_started",jobId:t.id,position:0,threadId:t.threadId},t.id,t.sourceId),this.processor(t).catch(n=>{t.status="error",t.error=n instanceof Error?n.message:String(n),this.broadcast({type:"error",jobId:t.id,threadId:t.threadId,message:t.error,provider:t.provider,model:t.model},t.id,t.sourceId)}).finally(()=>{this.activeJobs.delete(t.id),this.activeProcesses.delete(t.id),this.scheduleBufferCleanup(t.id),this.processNext(),this.activeJobs.size===0&&this.queue.length===0&&this.broadcast({type:"queue_drained"},t.id)})}}};import{mkdir as vo,readFile as yo,writeFile as wo}from"fs/promises";import{dirname as So,join as bo}from"path";var xo={version:1,threads:{}},Ve=class{constructor(t){this.cache=null;this.writeChain=Promise.resolve();this.filePath=bo(t,".popmelt","threads.json")}async load(){if(this.cache)return this.cache;try{let t=await yo(this.filePath,"utf-8"),n=JSON.parse(t);if(n&&n.version===1&&n.threads)return this.cache=n,this.cache}catch{}return this.cache={...xo,threads:{}},this.cache}async getThread(t){return(await this.load()).threads[t]??null}async findContinuationThread(t){if(t.length===0)return null;let n=await this.load(),e=new Set(t);for(let o of Object.values(n.threads))if(o.elementIdentifiers.some(c=>e.has(c)))return o;return null}async createThread(t,n){let e=await this.load(),o={id:t,createdAt:Date.now(),updatedAt:Date.now(),elementIdentifiers:n,messages:[]};return e.threads[t]=o,await this.persist(),o}async appendMessage(t,n){let o=(await this.load()).threads[t];o&&(o.messages.push(n),o.updatedAt=Date.now(),await this.persist())}async addElementIdentifiers(t,n){let o=(await this.load()).threads[t];if(!o)return;let i=new Set(o.elementIdentifiers);for(let c of n)i.has(c)||o.elementIdentifiers.push(c);o.updatedAt=Date.now(),await this.persist()}async listRecent(t=5){let n=await this.load(),e=Object.values(n.threads);return e.sort((o,i)=>i.updatedAt-o.updatedAt),e.slice(0,t).map(o=>{let c=o.messages.find(a=>a.role==="human")?.feedbackSummary||"[thread]";return{id:o.id,createdAt:o.createdAt,updatedAt:o.updatedAt,preview:c,messageCount:o.messages.length,elementIdentifiers:o.elementIdentifiers}})}async getThreadHistory(t,n=6){let e=await this.getThread(t);return!e||e.messages.length===0?[]:e.messages.length<=n?e.messages:[e.messages[0],...e.messages.slice(-(n-1))]}async persist(){this.writeChain=this.writeChain.then(async()=>{if(this.cache)try{await vo(So(this.filePath),{recursive:!0}),await wo(this.filePath,JSON.stringify(this.cache,null,2))}catch(t){console.error("[ThreadStore] Failed to persist:",t)}}),await this.writeChain}};var vn="0.7.4";var $o=1111,_o=["Read","Edit","Write","Glob","Grep","Bash","WebFetch","WebSearch","Bash(curl:*)"],Oo=1800*1e3,Ao=3600*1e3;function kn(s){if(!s)return!1;try{let t=new URL(s);return t.hostname==="localhost"||t.hostname.endsWith(".localhost")||t.hostname==="127.0.0.1"||t.hostname==="::1"||t.hostname==="[::1]"}catch{return!1}}function Do(s){let t=[];for(let n of s)if(n.type==="delta"){let e=n.text;if(!e)continue;let o=t[t.length-1];o&&o.kind==="text"?o.text+=e:t.push({kind:"text",text:e})}else if(n.type==="tool_use"){let e=n.tool||"",o=n.file??void 0,i=n.content??void 0,c=o?o.split("/").pop()??o:void 0,a;switch(e){case"Read":a=c?`Reading ${c}`:"Reading file";break;case"Edit":a=c?`Editing ${c}`:"Editing file";break;case"Write":a=c?`Writing ${c}`:"Writing file";break;case"Bash":a=i?i.split(`
|
|
332
332
|
`)[0].trim().slice(0,60):"Running command";break;case"Glob":a="Searching files";break;case"Grep":a="Searching code";break;case"WebFetch":a="Fetching page";break;case"WebSearch":a="Searching web";break;default:a=e?`Using ${e}`:"tool";break}let m=o??i??void 0,P=t[t.length-1];P&&P.kind==="tool_group"&&P.tool===e?P.items.push({label:a,detail:m}):t.push({kind:"tool_group",tool:e,items:[{label:a,detail:m}]})}return t}function No(s,t){let n=s.headers.origin;kn(n)&&(t.setHeader("Access-Control-Allow-Origin",n),t.setHeader("Access-Control-Allow-Methods","GET, POST, PATCH, DELETE, OPTIONS"),t.setHeader("Access-Control-Allow-Headers","Content-Type, X-Popmelt-Project-Id"))}function y(s,t,n){s.writeHead(t,{"Content-Type":"application/json"}),s.end(JSON.stringify(n))}function Jo(s,t){let n=s.headers["x-popmelt-project-id"];return(Array.isArray(n)?n[0]:n)||t.searchParams.get("projectId")||null}function Fo(s,t){if(!s)return t;let n=s.match(/^#?([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i);if(!n)return t;let[,e,o,i]=n;return`\x1B[38;2;${parseInt(e,16)};${parseInt(o,16)};${parseInt(i,16)}m${t}\x1B[0m`}function gt(s,t){try{s.res.write(`event: ${t.type}
|
|
333
333
|
data: ${JSON.stringify(t)}
|
|
334
334
|
|
package/dist/cli.mjs
CHANGED
|
@@ -329,7 +329,7 @@ url = "${s}"
|
|
|
329
329
|
`)}function dn(s){return s.match(/<question>\s*([\s\S]*?)\s*<\/question>/)?.[1]??null}function un(s,t,n,e){let o=[];o.push("You are continuing work on a UI based on the developer's reply to your question."),o.push(""),n!=="codex"&&o.push(`IMPORTANT: First, use the Read tool to view the screenshot at: ${s}`);let i=t.find(a=>a.role==="human"&&a.feedbackContext);if(i?.feedbackContext&&(o.push(""),o.push(i.feedbackContext)),t.length>0){o.push(""),o.push("## Conversation History");let a=0;for(let c of t)c.role==="human"?(a++,c.replyToQuestion?(o.push(`### Round ${a} (human) \u2014 reply`),o.push(`"${c.replyToQuestion}"`)):(o.push(`### Round ${a} (human)`),c.feedbackSummary&&o.push(`Annotations: ${c.feedbackSummary}`))):c.question?(o.push(`### Round ${a} (assistant) \u2014 question`),o.push(`"${c.question}"`)):(o.push(`### Round ${a} (assistant)`),c.responseText&&o.push(`Response: ${c.responseText}`))}if(o.push(""),o.push("The developer answered your question. Continue working based on their reply."),o.push("Follow their instructions \u2014 apply code changes only if requested. The dev server has HMR so changes appear immediately."),o.push(""),o.push("IMPORTANT: If any elements you modify have a `data-pm` attribute, preserve it in the source. This attribute tracks annotation positions."),e&&e.length>0){o.push(""),o.push("## Attached Images"),o.push("The developer attached reference images with their reply:");for(let a of e)o.push(`Attached image: use the Read tool to view the image at: ${a}`)}return o.push(""),o.push("## Resolution"),o.push("After completing all work, output a resolution block listing what you did for each annotation:"),o.push("<resolution>"),o.push('[{"annotationId":"<id>","status":"resolved","summary":"<what you did>","filesModified":["<file>"],"declaredScope":{"breadth":"...","target":"..."},"inferredScope":{"breadth":"...","target":"..."}}]'),o.push("</resolution>"),o.push(`Use status "resolved" when the change is complete, or "needs_review" if you're unsure about the result.`),o.push(""),o.push("### Scope classification"),o.push("Each resolution MUST include scope fields:"),o.push("- `declaredScope`: What scope the user's instruction text implies. null if no signal."),o.push("- `inferredScope`: What scope the change actually has, based on what you modified."),o.push("Scope has two dimensions:"),o.push('- `breadth`: "instance" (just this occurrence) or "pattern" (all similar occurrences)'),o.push('- `target`: "element" (a specific DOM element), "component" (a React/UI component), or "token" (a design token \u2014 color, spacing, typography)'),o.push('Note: "instance" + "token" is invalid \u2014 tokens are inherently patterns.'),o.push("If you cannot confidently determine scope, set it to null."),o.push('If the developer\'s reply corrects a prior scope classification (e.g., "this should apply everywhere" or "only fix this one"), set `finalScope` on your resolution to reflect their correction and apply the change at the corrected scope.'),o.push(""),o.push("## Questions"),o.push("If you still need clarification, output:"),o.push("<question>Your question here</question>"),o.push("You may output BOTH a <resolution> and a <question> in the same response."),o.join(`
|
|
330
330
|
`)}function Vs(s){if(typeof s!="object"||s===null)return!1;let t=s;return(t.breadth==="instance"||t.breadth==="pattern")&&(t.target==="element"||t.target==="component"||t.target==="token")}function Zs(s){if(typeof s!="object"||s===null||typeof s.annotationId!="string"||s.status!=="resolved"&&s.status!=="needs_review"||typeof s.summary!="string")return!1;let t=s;for(let n of["declaredScope","inferredScope","finalScope"])if(t[n]!==void 0&&t[n]!==null&&!Vs(t[n]))return!1;return!0}function pn(s){let t=s.match(/<resolution>\s*([\s\S]*?)\s*<\/resolution>/);if(!t||!t[1])return[];try{let n=JSON.parse(t[1]);return Array.isArray(n)?n.filter(Zs):[]}catch{return[]}}function fn(s){let t=s.match(/<novel>\s*([\s\S]*?)\s*<\/novel>/);if(!t?.[1])return[];try{let n=JSON.parse(t[1]);return Array.isArray(n)?n.filter(e=>{if(typeof e!="object"||e===null)return!1;let o=e;return(o.category==="token"||o.category==="component"||o.category==="element")&&typeof o.element=="string"&&typeof o.decision=="string"&&typeof o.reason=="string"}):[]}catch{return[]}}import{execFile as eo}from"child_process";import{readdir as to,readFile as no,stat as so}from"fs/promises";import{homedir as $e}from"os";import{join as ge}from"path";var Ke=[{id:"claude-opus-4-6",label:"Opus 4.6",source:"static"},{id:"claude-sonnet-4-6",label:"Sonn 4.6",source:"static"}],_e=[{id:"gpt-5.4",label:"GPT 5.4",source:"static"},{id:"gpt-5.3-codex",label:"Codex 5.3",source:"static"},{id:"gpt-5.3-codex-spark",label:"Spark 5.3",source:"static"}],Oe={id:"",label:"Default",source:"cli"},oo=/^\s*-\s+"([^"]+)"/;function ro(s){let t=[],n=!1;for(let e of s.split(`
|
|
331
331
|
`)){if(/^\s*`model`:/.test(e)){n=!0;continue}if(n&&/^\s*`[^`]+`:/.test(e))break;if(!n)continue;let o=e.match(oo);if(!o?.[1])continue;let i=o[1];t.push({id:i,label:mt(i),source:"cli"})}return Qe([Oe,...t])}function io(s){let t=JSON.parse(s);return(Array.isArray(t.models)?t.models:[]).filter(e=>e.visibility===void 0||e.visibility==="list").sort((e,o)=>{let i=typeof e.priority=="number"?e.priority:Number.MAX_SAFE_INTEGER,a=typeof o.priority=="number"?o.priority:Number.MAX_SAFE_INTEGER;return i-a}).flatMap(e=>{let o=typeof e.slug=="string"?e.slug:typeof e.id=="string"?e.id:"";if(!o)return[];let i=typeof e.display_name=="string"&&e.display_name.trim()?e.display_name.trim():mt(o);return[{id:o,label:i,source:"cli"}]})}function ao(s){let t=s.match(/\bclaude-[a-z0-9]+(?:[-.][a-z0-9]+)*\b/gi)??[];return Qe(t.map(n=>({id:n,label:mt(n),source:"cli"})))}function mt(s){if(!s)return"Default";let t={"gpt-5.5":"GPT 5.5","gpt-5.4":"GPT 5.4","gpt-5.4-mini":"Mini 5.4","gpt-5.3-codex":"Codex 5.3","gpt-5.3-codex-spark":"Spark 5.3","gpt-5.2-codex":"Codex 5.2","gpt-5.2":"GPT 5.2","gpt-5.1":"GPT 5.1","gpt-5-mini":"Mini 5","gpt-4.1":"GPT 4.1","claude-opus-4.7":"Opus 4.7","claude-opus-4.6":"Opus 4.6","claude-opus-4.6-fast":"Opus 4.6 Fast","claude-opus-4.5":"Opus 4.5","claude-sonnet-4.6":"Sonn 4.6","claude-sonnet-4.5":"Sonn 4.5","claude-sonnet-4":"Sonn 4","claude-haiku-4.5":"Haiku 4.5","claude-fable":"Fable"},n=s.replace(/-\d{8,}$/,"");if(t[s])return t[s];if(t[n])return t[n];let e=n.match(/^claude-(opus|sonnet|haiku|fable)(?:-(\d+)[-.](\d+))?(?:-(fast))?$/);if(e){let i=e[1]==="sonnet"?"Sonn":po(e[1]),a=e[2]&&e[3]?` ${e[2]}.${e[3]}`:"";return`${i}${a}${e[4]?" Fast":""}`}let o=n.match(/^gpt-(\d+)(?:[.-](\d+))?(?:-(mini|codex|spark))?$/);if(o){let i=o[2]?`${o[1]}.${o[2]}`:o[1];return o[3]==="mini"?`Mini ${i}`:o[3]==="codex"?`Codex ${i}`:o[3]==="spark"?`Spark ${i}`:`GPT ${i}`}return n}async function hn(s="copilot"){let t=await Ye(s,["help","config"]),n=ro(t);return n.length>1?n:[Oe]}async function mn(s="codex"){let t=await Ye(s,["debug","models"]).catch(async()=>{let e=process.env.CODEX_HOME||ge($e(),".codex");return vn(ge(e,"models_cache.json"))}),n=io(t);return n.length>0?Qe([...n,..._e]):_e}async function gn(s="claude"){let t=ge($e(),".claude"),n=[ge($e(),".claude","stats-cache.json"),ge($e(),".claude","settings.json"),ge($e(),".claude.json"),ge(t,"cache","changelog.md")],[e,o,i]=await Promise.all([Ye(s,["--help"]).catch(()=>""),Ye(s,["--version"]).catch(()=>""),co(t).catch(()=>[])]),a=uo([...n,...i]),c=await Promise.all(a.map(P=>vn(P).catch(()=>""))),m=ao([e,o,...c].join(`
|
|
332
|
-
`));return Qe([...Ke,...m])}function Ye(s,t,n=5e3){return new Promise((e,o)=>{eo(s,t,{encoding:"utf-8",timeout:n},(i,a)=>{if(i){o(i);return}e(a)})})}async function vn(s){return no(s,"utf-8")}async function co(s){let t=[ge(s,"projects"),ge(s,"telemetry")],n=[];for(let e of t)await yn(e,n,4);return n.sort((e,o)=>o.mtimeMs-e.mtimeMs).slice(0,80).map(e=>e.path)}async function yn(s,t,n){if(n<0)return;let e;try{e=await to(s,{withFileTypes:!0})}catch{return}await Promise.all(e.map(async o=>{let i=ge(s,o.name);if(o.isDirectory()){await yn(i,t,n-1);return}if(!(!o.isFile()||!lo(o.name)))try{let a=await so(i);if(a.size>2e6)return;t.push({path:i,mtimeMs:a.mtimeMs})}catch{}}))}function lo(s){return s.endsWith(".json")||s.endsWith(".jsonl")||s.endsWith(".md")||s.endsWith(".txt")}function Qe(s){let t=new Set,n=[];for(let e of s)t.has(e.id)||(t.add(e.id),n.push(e));return n}function uo(s){return[...new Set(s)]}function po(s){return s.charAt(0).toUpperCase()+s.slice(1)}var Ve=class{constructor(t=5){this.queue=[];this.activeJobs=new Map;this.activeProcesses=new Map;this.listeners=new Set;this.processor=null;this.eventBuffers=new Map;this.accumulators=new Map;this.cleanupTimers=new Map;this.maxConcurrency=t}setProcessor(t){this.processor=t}get active(){let t=this.activeJobs.values().next();return t.done?null:t.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(t,n){n?this.activeProcesses.set(t,n):this.activeProcesses.delete(t)}enqueue(t){return this.queue.push(t),this.processNext(),this.queue.length+this.activeJobs.size}addListener(t){return this.listeners.add(t),()=>this.listeners.delete(t)}broadcast(t,n,e){let o=this.bufferEvent(n,t);for(let i of this.listeners)i(o,n,e)}bufferEvent(t,n){let e=this.eventBuffers.get(t);e||(e={events:[],nextSeq:0},this.eventBuffers.set(t,e));let o={...n,seq:e.nextSeq++};return e.events.push(o),e.events.length>1e4&&e.events.splice(0,e.events.length-1e4),o}getBufferedEvents(t,n=-1){let e=this.eventBuffers.get(t),o=this.accumulators.get(t)??{response:"",thinking:""},i=this.activeJobs.has(t);if(!e)return null;let a=n<0?e.events:e.events.filter(c=>c.seq>n);return{jobId:t,events:a,currentSeq:e.nextSeq-1,accumulated:{...o},jobActive:i}}accumulateText(t,n,e){let o=this.accumulators.get(t);o||(o={response:"",thinking:""},this.accumulators.set(t,o)),o[n]+=e}getAccumulated(t){return this.accumulators.get(t)??null}scheduleBufferCleanup(t){let n=this.cleanupTimers.get(t);n&&clearTimeout(n);let e=setTimeout(()=>{this.eventBuffers.delete(t),this.accumulators.delete(t),this.cleanupTimers.delete(t)},6e4);this.cleanupTimers.set(t,e)}cancelJob(t){let n=this.activeProcesses.get(t),e=this.activeJobs.get(t);return!n||!e?!1:(n.kill("SIGTERM"),this.activeProcesses.delete(t),this.activeJobs.delete(t),e.status="error",e.error="Cancelled by user",this.broadcast({type:"error",jobId:e.id,threadId:e.threadId,message:"Cancelled by user",cancelled:!0,provider:e.provider,model:e.model},e.id,e.sourceId),this.processNext(),!0)}cancelActive(){if(this.activeJobs.size===0)return!1;let t=Array.from(this.activeJobs.keys());for(let n of t)this.cancelJob(n);return!0}destroy(){for(let t of this.activeProcesses.values())t.kill("SIGTERM");this.activeProcesses.clear(),this.activeJobs.clear(),this.queue=[],this.listeners.clear(),this.eventBuffers.clear(),this.accumulators.clear();for(let t of this.cleanupTimers.values())clearTimeout(t);this.cleanupTimers.clear()}async destroyAsync(t=1e4){let n=Array.from(this.activeProcesses.values());if(this.queue=[],this.listeners.clear(),n.length===0){this.activeProcesses.clear(),this.activeJobs.clear();return}for(let e of n)try{e.kill("SIGTERM")}catch{}await Promise.all(n.map(e=>new Promise(o=>{let i=!1,a=()=>{i||(i=!0,o())};e.on("exit",a),e.on("error",a),setTimeout(()=>{if(!i){try{e.kill("SIGKILL")}catch{}setTimeout(a,500)}},t)}))),this.activeProcesses.clear(),this.activeJobs.clear(),this.eventBuffers.clear(),this.accumulators.clear();for(let e of this.cleanupTimers.values())clearTimeout(e);this.cleanupTimers.clear()}processNext(){for(;this.activeJobs.size<this.maxConcurrency&&this.queue.length>0&&this.processor;){let t=this.queue.shift();this.activeJobs.set(t.id,t),t.status="running",this.broadcast({type:"job_started",jobId:t.id,position:0,threadId:t.threadId},t.id,t.sourceId),this.processor(t).catch(n=>{t.status="error",t.error=n instanceof Error?n.message:String(n),this.broadcast({type:"error",jobId:t.id,threadId:t.threadId,message:t.error,provider:t.provider,model:t.model},t.id,t.sourceId)}).finally(()=>{this.activeJobs.delete(t.id),this.activeProcesses.delete(t.id),this.scheduleBufferCleanup(t.id),this.processNext(),this.activeJobs.size===0&&this.queue.length===0&&this.broadcast({type:"queue_drained"},t.id)})}}};import{mkdir as fo,readFile as ho,writeFile as mo}from"fs/promises";import{dirname as go,join as vo}from"path";var yo={version:1,threads:{}},Ze=class{constructor(t){this.cache=null;this.writeChain=Promise.resolve();this.filePath=vo(t,".popmelt","threads.json")}async load(){if(this.cache)return this.cache;try{let t=await ho(this.filePath,"utf-8"),n=JSON.parse(t);if(n&&n.version===1&&n.threads)return this.cache=n,this.cache}catch{}return this.cache={...yo,threads:{}},this.cache}async getThread(t){return(await this.load()).threads[t]??null}async findContinuationThread(t){if(t.length===0)return null;let n=await this.load(),e=new Set(t);for(let o of Object.values(n.threads))if(o.elementIdentifiers.some(a=>e.has(a)))return o;return null}async createThread(t,n){let e=await this.load(),o={id:t,createdAt:Date.now(),updatedAt:Date.now(),elementIdentifiers:n,messages:[]};return e.threads[t]=o,await this.persist(),o}async appendMessage(t,n){let o=(await this.load()).threads[t];o&&(o.messages.push(n),o.updatedAt=Date.now(),await this.persist())}async addElementIdentifiers(t,n){let o=(await this.load()).threads[t];if(!o)return;let i=new Set(o.elementIdentifiers);for(let a of n)i.has(a)||o.elementIdentifiers.push(a);o.updatedAt=Date.now(),await this.persist()}async listRecent(t=5){let n=await this.load(),e=Object.values(n.threads);return e.sort((o,i)=>i.updatedAt-o.updatedAt),e.slice(0,t).map(o=>{let a=o.messages.find(c=>c.role==="human")?.feedbackSummary||"[thread]";return{id:o.id,createdAt:o.createdAt,updatedAt:o.updatedAt,preview:a,messageCount:o.messages.length,elementIdentifiers:o.elementIdentifiers}})}async getThreadHistory(t,n=6){let e=await this.getThread(t);return!e||e.messages.length===0?[]:e.messages.length<=n?e.messages:[e.messages[0],...e.messages.slice(-(n-1))]}async persist(){this.writeChain=this.writeChain.then(async()=>{if(this.cache)try{await fo(go(this.filePath),{recursive:!0}),await mo(this.filePath,JSON.stringify(this.cache,null,2))}catch(t){console.error("[ThreadStore] Failed to persist:",t)}}),await this.writeChain}};var wn="0.7.
|
|
332
|
+
`));return Qe([...Ke,...m])}function Ye(s,t,n=5e3){return new Promise((e,o)=>{eo(s,t,{encoding:"utf-8",timeout:n},(i,a)=>{if(i){o(i);return}e(a)})})}async function vn(s){return no(s,"utf-8")}async function co(s){let t=[ge(s,"projects"),ge(s,"telemetry")],n=[];for(let e of t)await yn(e,n,4);return n.sort((e,o)=>o.mtimeMs-e.mtimeMs).slice(0,80).map(e=>e.path)}async function yn(s,t,n){if(n<0)return;let e;try{e=await to(s,{withFileTypes:!0})}catch{return}await Promise.all(e.map(async o=>{let i=ge(s,o.name);if(o.isDirectory()){await yn(i,t,n-1);return}if(!(!o.isFile()||!lo(o.name)))try{let a=await so(i);if(a.size>2e6)return;t.push({path:i,mtimeMs:a.mtimeMs})}catch{}}))}function lo(s){return s.endsWith(".json")||s.endsWith(".jsonl")||s.endsWith(".md")||s.endsWith(".txt")}function Qe(s){let t=new Set,n=[];for(let e of s)t.has(e.id)||(t.add(e.id),n.push(e));return n}function uo(s){return[...new Set(s)]}function po(s){return s.charAt(0).toUpperCase()+s.slice(1)}var Ve=class{constructor(t=5){this.queue=[];this.activeJobs=new Map;this.activeProcesses=new Map;this.listeners=new Set;this.processor=null;this.eventBuffers=new Map;this.accumulators=new Map;this.cleanupTimers=new Map;this.maxConcurrency=t}setProcessor(t){this.processor=t}get active(){let t=this.activeJobs.values().next();return t.done?null:t.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(t,n){n?this.activeProcesses.set(t,n):this.activeProcesses.delete(t)}enqueue(t){return this.queue.push(t),this.processNext(),this.queue.length+this.activeJobs.size}addListener(t){return this.listeners.add(t),()=>this.listeners.delete(t)}broadcast(t,n,e){let o=this.bufferEvent(n,t);for(let i of this.listeners)i(o,n,e)}bufferEvent(t,n){let e=this.eventBuffers.get(t);e||(e={events:[],nextSeq:0},this.eventBuffers.set(t,e));let o={...n,seq:e.nextSeq++};return e.events.push(o),e.events.length>1e4&&e.events.splice(0,e.events.length-1e4),o}getBufferedEvents(t,n=-1){let e=this.eventBuffers.get(t),o=this.accumulators.get(t)??{response:"",thinking:""},i=this.activeJobs.has(t);if(!e)return null;let a=n<0?e.events:e.events.filter(c=>c.seq>n);return{jobId:t,events:a,currentSeq:e.nextSeq-1,accumulated:{...o},jobActive:i}}accumulateText(t,n,e){let o=this.accumulators.get(t);o||(o={response:"",thinking:""},this.accumulators.set(t,o)),o[n]+=e}getAccumulated(t){return this.accumulators.get(t)??null}scheduleBufferCleanup(t){let n=this.cleanupTimers.get(t);n&&clearTimeout(n);let e=setTimeout(()=>{this.eventBuffers.delete(t),this.accumulators.delete(t),this.cleanupTimers.delete(t)},6e4);this.cleanupTimers.set(t,e)}cancelJob(t){let n=this.activeProcesses.get(t),e=this.activeJobs.get(t);return!n||!e?!1:(n.kill("SIGTERM"),this.activeProcesses.delete(t),this.activeJobs.delete(t),e.status="error",e.error="Cancelled by user",this.broadcast({type:"error",jobId:e.id,threadId:e.threadId,message:"Cancelled by user",cancelled:!0,provider:e.provider,model:e.model},e.id,e.sourceId),this.processNext(),!0)}cancelActive(){if(this.activeJobs.size===0)return!1;let t=Array.from(this.activeJobs.keys());for(let n of t)this.cancelJob(n);return!0}destroy(){for(let t of this.activeProcesses.values())t.kill("SIGTERM");this.activeProcesses.clear(),this.activeJobs.clear(),this.queue=[],this.listeners.clear(),this.eventBuffers.clear(),this.accumulators.clear();for(let t of this.cleanupTimers.values())clearTimeout(t);this.cleanupTimers.clear()}async destroyAsync(t=1e4){let n=Array.from(this.activeProcesses.values());if(this.queue=[],this.listeners.clear(),n.length===0){this.activeProcesses.clear(),this.activeJobs.clear();return}for(let e of n)try{e.kill("SIGTERM")}catch{}await Promise.all(n.map(e=>new Promise(o=>{let i=!1,a=()=>{i||(i=!0,o())};e.on("exit",a),e.on("error",a),setTimeout(()=>{if(!i){try{e.kill("SIGKILL")}catch{}setTimeout(a,500)}},t)}))),this.activeProcesses.clear(),this.activeJobs.clear(),this.eventBuffers.clear(),this.accumulators.clear();for(let e of this.cleanupTimers.values())clearTimeout(e);this.cleanupTimers.clear()}processNext(){for(;this.activeJobs.size<this.maxConcurrency&&this.queue.length>0&&this.processor;){let t=this.queue.shift();this.activeJobs.set(t.id,t),t.status="running",this.broadcast({type:"job_started",jobId:t.id,position:0,threadId:t.threadId},t.id,t.sourceId),this.processor(t).catch(n=>{t.status="error",t.error=n instanceof Error?n.message:String(n),this.broadcast({type:"error",jobId:t.id,threadId:t.threadId,message:t.error,provider:t.provider,model:t.model},t.id,t.sourceId)}).finally(()=>{this.activeJobs.delete(t.id),this.activeProcesses.delete(t.id),this.scheduleBufferCleanup(t.id),this.processNext(),this.activeJobs.size===0&&this.queue.length===0&&this.broadcast({type:"queue_drained"},t.id)})}}};import{mkdir as fo,readFile as ho,writeFile as mo}from"fs/promises";import{dirname as go,join as vo}from"path";var yo={version:1,threads:{}},Ze=class{constructor(t){this.cache=null;this.writeChain=Promise.resolve();this.filePath=vo(t,".popmelt","threads.json")}async load(){if(this.cache)return this.cache;try{let t=await ho(this.filePath,"utf-8"),n=JSON.parse(t);if(n&&n.version===1&&n.threads)return this.cache=n,this.cache}catch{}return this.cache={...yo,threads:{}},this.cache}async getThread(t){return(await this.load()).threads[t]??null}async findContinuationThread(t){if(t.length===0)return null;let n=await this.load(),e=new Set(t);for(let o of Object.values(n.threads))if(o.elementIdentifiers.some(a=>e.has(a)))return o;return null}async createThread(t,n){let e=await this.load(),o={id:t,createdAt:Date.now(),updatedAt:Date.now(),elementIdentifiers:n,messages:[]};return e.threads[t]=o,await this.persist(),o}async appendMessage(t,n){let o=(await this.load()).threads[t];o&&(o.messages.push(n),o.updatedAt=Date.now(),await this.persist())}async addElementIdentifiers(t,n){let o=(await this.load()).threads[t];if(!o)return;let i=new Set(o.elementIdentifiers);for(let a of n)i.has(a)||o.elementIdentifiers.push(a);o.updatedAt=Date.now(),await this.persist()}async listRecent(t=5){let n=await this.load(),e=Object.values(n.threads);return e.sort((o,i)=>i.updatedAt-o.updatedAt),e.slice(0,t).map(o=>{let a=o.messages.find(c=>c.role==="human")?.feedbackSummary||"[thread]";return{id:o.id,createdAt:o.createdAt,updatedAt:o.updatedAt,preview:a,messageCount:o.messages.length,elementIdentifiers:o.elementIdentifiers}})}async getThreadHistory(t,n=6){let e=await this.getThread(t);return!e||e.messages.length===0?[]:e.messages.length<=n?e.messages:[e.messages[0],...e.messages.slice(-(n-1))]}async persist(){this.writeChain=this.writeChain.then(async()=>{if(this.cache)try{await fo(go(this.filePath),{recursive:!0}),await mo(this.filePath,JSON.stringify(this.cache,null,2))}catch(t){console.error("[ThreadStore] Failed to persist:",t)}}),await this.writeChain}};var wn="0.7.4";var Io=1111,To=["Read","Edit","Write","Glob","Grep","Bash","WebFetch","WebSearch","Bash(curl:*)"],Mo=1800*1e3,Co=3600*1e3;function En(s){if(!s)return!1;try{let t=new URL(s);return t.hostname==="localhost"||t.hostname.endsWith(".localhost")||t.hostname==="127.0.0.1"||t.hostname==="::1"||t.hostname==="[::1]"}catch{return!1}}function $o(s){let t=[];for(let n of s)if(n.type==="delta"){let e=n.text;if(!e)continue;let o=t[t.length-1];o&&o.kind==="text"?o.text+=e:t.push({kind:"text",text:e})}else if(n.type==="tool_use"){let e=n.tool||"",o=n.file??void 0,i=n.content??void 0,a=o?o.split("/").pop()??o:void 0,c;switch(e){case"Read":c=a?`Reading ${a}`:"Reading file";break;case"Edit":c=a?`Editing ${a}`:"Editing file";break;case"Write":c=a?`Writing ${a}`:"Writing file";break;case"Bash":c=i?i.split(`
|
|
333
333
|
`)[0].trim().slice(0,60):"Running command";break;case"Glob":c="Searching files";break;case"Grep":c="Searching code";break;case"WebFetch":c="Fetching page";break;case"WebSearch":c="Searching web";break;default:c=e?`Using ${e}`:"tool";break}let m=o??i??void 0,P=t[t.length-1];P&&P.kind==="tool_group"&&P.tool===e?P.items.push({label:c,detail:m}):t.push({kind:"tool_group",tool:e,items:[{label:c,detail:m}]})}return t}function _o(s,t){let n=s.headers.origin;En(n)&&(t.setHeader("Access-Control-Allow-Origin",n),t.setHeader("Access-Control-Allow-Methods","GET, POST, PATCH, DELETE, OPTIONS"),t.setHeader("Access-Control-Allow-Headers","Content-Type, X-Popmelt-Project-Id"))}function y(s,t,n){s.writeHead(t,{"Content-Type":"application/json"}),s.end(JSON.stringify(n))}function Oo(s,t){let n=s.headers["x-popmelt-project-id"];return(Array.isArray(n)?n[0]:n)||t.searchParams.get("projectId")||null}function Ao(s,t){if(!s)return t;let n=s.match(/^#?([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i);if(!n)return t;let[,e,o,i]=n;return`\x1B[38;2;${parseInt(e,16)};${parseInt(o,16)};${parseInt(i,16)}m${t}\x1B[0m`}function vt(s,t){try{s.res.write(`event: ${t.type}
|
|
334
334
|
data: ${JSON.stringify(t)}
|
|
335
335
|
|
|
@@ -356,4 +356,4 @@ data: {"status":"connected"}
|
|
|
356
356
|
|
|
357
357
|
`);let d=new URL(r.url||"/",`http://127.0.0.1:${W}`).searchParams.get("sourceId")||void 0,f={id:Se().slice(0,8),res:l,sourceId:d};_.add(f),r.on("close",()=>{_.delete(f)})}function In(r){let l=N.allActive;y(r,200,{ok:!0,version:wn,restartMode:A,projectId:e,projectName:gt(n),devOrigin:o,activeJob:l[0]?{id:l[0].id,status:l[0].status}:null,activeJobs:l.map(p=>({id:p.id,status:p.status,threadId:p.threadId,annotationIds:p.annotationIds,color:p.color,kind:p.kind})),queueDepth:N.depth,recentJobs:b})}async function Tn(r,l){let p=await new Promise(d=>{let f="";r.on("data",u=>{f+=u.toString()}),r.on("end",()=>d(f))});try{let d=JSON.parse(p);typeof d.devOrigin=="string"&&(o=d.devOrigin||null),y(l,200,{ok:!0,devOrigin:o})}catch{y(l,400,{error:"Invalid JSON"})}}async function Mn(r,l){let d=new URL(r.url||"/",`http://127.0.0.1:${W}`).searchParams.get("jobId"),u=(d?N.allActive.filter(O=>O.id===d):N.allActive).map(O=>O.threadId).filter(Boolean),g=d?N.cancelJob(d):N.cancelActive();for(let O of u)await R.appendMessage(O,{role:"assistant",timestamp:Date.now(),jobId:d||"",cancelled:!0});y(l,200,{cancelled:g})}async function Cn(r,l){if(C.isRunning){y(l,200,{skipped:!0,reason:"Already running"});return}let{provider:p,model:d}=await tt(r);if(p==="copilot"){y(l,400,{error:"Materialization is not available for Copilot yet."});return}let f=await C.getUnmaterializedPatternDecisions();if(f.length===0){y(l,200,{skipped:!0,reason:"No unmaterialized pattern decisions"});return}C.run({provider:p,model:d}).catch(()=>{}),y(l,200,{started:!0,decisionCount:f.length,decisionIds:f.map(u=>u.id)})}async function tt(r){try{let l=[];for await(let d of r)l.push(typeof d=="string"?Buffer.from(d):d);if(l.length===0)return{};let p=JSON.parse(Buffer.concat(l).toString());return{provider:De(typeof p.provider=="string"?p.provider:void 0),model:typeof p.model=="string"&&p.model?p.model:void 0}}catch{return{}}}async function $n(r,l){let p=await C.loadModel();if(!p){y(l,400,{error:"No model exists yet"});return}let d,f;try{let h=[];for await(let I of r)h.push(typeof I=="string"?Buffer.from(I):I);let L=JSON.parse(Buffer.concat(h).toString());d=L.provider,f=L.model}catch{}if(d==="copilot"){y(l,400,{error:"Rule synthesis is not available for Copilot yet."});return}let u=qt(p),g=Se().slice(0,8),F=(await R.createThread(g,[])).id;G.set(F,"synthesize"),await R.appendMessage(F,{role:"human",timestamp:Date.now(),jobId:g,feedbackSummary:"Synthesize rules \u2014 review and propose improvements"});let q={id:g,status:"queued",screenshotPath:"",feedback:{timestamp:new Date().toISOString(),url:"",viewport:{width:0,height:0},scrollPosition:{x:0,y:0},annotations:[],styleModifications:[]},createdAt:Date.now(),threadId:F,kind:"synthesize",provider:De(d),model:f||void 0};q._replyPrompt=u;let j=N.enqueue(q);y(l,200,{jobId:g,position:j,threadId:F})}async function _n(r,l){let{provider:p,model:d}=await tt(r);if(p==="copilot"){y(l,400,{error:"Eval synthesis is not available for Copilot yet."});return}let f=await k.listDecisionIds(),u=await k.loadDecisions(f),g=await R.load(),O=await C.loadModel(),F=await w.loadSuite(),q=Lt({decisions:u,threads:g,model:O,existingSuite:F}),j=Se().slice(0,8),L=(await R.createThread(j,[])).id;G.set(L,"synthesize_evals"),await R.appendMessage(L,{role:"human",timestamp:Date.now(),jobId:j,feedbackSummary:"Synthesize evals \u2014 infer evals from design history"});let I={id:j,status:"queued",screenshotPath:"",feedback:{timestamp:new Date().toISOString(),url:"",viewport:{width:0,height:0},scrollPosition:{x:0,y:0},annotations:[],styleModifications:[]},createdAt:Date.now(),color:"#6b7280",threadId:L,kind:"synthesize_evals",provider:p,model:d||void 0};I._replyPrompt=q;let T=N.enqueue(I);y(l,200,{jobId:j,position:T,threadId:L})}async function On(r,l,p){let d=decodeURIComponent(r),f=await w.findCase(d);if(!f){y(p,404,{error:"Eval not found"});return}if(f.status!=="approved"){y(p,400,{error:"Only approved evals can be run"});return}let{screenshot:u,feedback:g,provider:O,model:F,sourceId:q}=await qe(l),j=De(O)??B;if(j==="copilot"){y(p,400,{error:"Eval runs are not available for Copilot yet."});return}let h={};try{h=g?JSON.parse(g):{}}catch{y(p,400,{error:"Invalid eval run context JSON"});return}let L=Se().slice(0,8),I=Se().slice(0,8),T=me(i,`eval-run-${L}.webp`);await Ae(T,u);let se=await w.writeRunScreenshot(L,u),ee=h.viewport,ae=ee&&typeof ee=="object"?ee:{},ce={type:"current_page",url:typeof h.url=="string"?h.url:"",viewport:{width:typeof ae.width=="number"?ae.width:0,height:typeof ae.height=="number"?ae.height:0}},$=await C.loadModel(),Y=j==="claude"?K.name:j==="codex"?Z.name:null,D=j==="codex"?V.length>0:typeof Y=="string"&&/chrome|devtools/i.test(Y),U=Wt({evalCase:f,scope:ce,model:$,screenshotPath:T,chromeDevtoolsAvailable:D}),M=(await R.createThread(I,[])).id;G.set(M,"run_eval");let oe={timestamp:new Date().toISOString(),url:ce.url,viewport:ce.viewport,scrollPosition:{x:typeof h.scrollX=="number"?h.scrollX:0,y:typeof h.scrollY=="number"?h.scrollY:0},annotations:[],styleModifications:[]};await R.appendMessage(M,{role:"human",timestamp:Date.now(),jobId:I,screenshotPath:T,feedbackSummary:`Run eval \u2014 ${f.title}`,feedbackContext:[`Eval: ${f.title}`,"Scope: current page",`URL: ${ce.url||"unknown"}`,"Assertions:",...f.assertions.map(Xn=>`- ${Xn}`)].join(`
|
|
358
358
|
`)});let de={id:I,status:"queued",screenshotPath:T,feedback:oe,createdAt:Date.now(),color:"#111827",threadId:M,kind:"run_eval",evalId:d,evalRunId:L,provider:j,model:F||void 0,sourceId:q||void 0};de._replyPrompt=U,de._evalRunScope=ce,de._evalScreenshotPath=se;let nt=N.enqueue(de);y(p,200,{jobId:I,runId:L,position:nt,threadId:M,screenshotPath:se})}async function An(r,l,p){let d=decodeURIComponent(r),f={},u,g,O;try{let q=[];for await(let h of l)q.push(typeof h=="string"?Buffer.from(h):h);let j=JSON.parse(Buffer.concat(q).toString());u=j.status,g=j.title,O=j.assertions}catch{y(p,400,{error:"Invalid JSON"});return}if(u!==void 0&&u!=="pending"&&u!=="approved"&&u!=="rejected"){y(p,400,{error:"Invalid status"});return}if(u&&(f.status=u),g!==void 0){if(typeof g!="string"||g.trim().length===0){y(p,400,{error:"Invalid title"});return}f.title=g.trim()}if(O!==void 0){if(!Array.isArray(O)){y(p,400,{error:"Invalid assertions"});return}let q=O.filter(j=>typeof j=="string").map(j=>j.trim()).filter(Boolean);if(q.length===0){y(p,400,{error:"Invalid assertions"});return}f.assertions=q}if(!f.status&&!f.title&&!f.assertions){y(p,400,{error:"No eval changes provided"});return}let F=await w.updateCase(d,f);if(!F){y(p,404,{error:"Eval not found"});return}y(p,200,{eval:F})}async function Dn(r){let l=G.get(r);if(l)return l;let f=(await R.getThread(r))?.messages.find(u=>u.role==="human")?.feedbackSummary??"";if(f.startsWith("Synthesize evals"))return G.set(r,"synthesize_evals"),"synthesize_evals";if(f.startsWith("Synthesize rules"))return G.set(r,"synthesize"),"synthesize";if(f.startsWith("Run eval"))return G.set(r,"run_eval"),"run_eval"}async function Nn(r,l){let p=[];for await(let F of r)p.push(typeof F=="string"?Buffer.from(F):F);let d;if(p.length>0)try{d=JSON.parse(Buffer.concat(p).toString("utf-8")).serverUrl}catch{}let f=[];S.claude?.available&&S.claude.mcp&&!S.claude.mcp.found&&f.push(await rn(d)),S.codex?.available&&S.codex.mcp&&!S.codex.mcp.found&&f.push(await an(d)),S.copilot?.available&&S.copilot.mcp&&!S.copilot.mcp.found&&f.push(await cn(d,S.copilot.path??v));let[u,g,O]=await Promise.all([dt(n),ut(n),pt(n,S.copilot?.path??v)]);S.claude&&(S.claude.mcp=u),S.codex&&(S.codex.mcp=g),S.copilot&&(S.copilot.mcp=O),y(l,200,{results:f,capabilities:{providers:S}})}async function Jn(r,l){let p=[];for await(let u of r)p.push(typeof u=="string"?Buffer.from(u):u);let d;try{d=JSON.parse(Buffer.concat(p).toString("utf-8"))}catch{y(l,400,{error:"Invalid JSON"});return}if(!d.name||typeof d.name!="string"){y(l,400,{error:"Missing or invalid name"});return}let f=await C.addComponent(d.name);y(l,200,f)}async function Bn(r,l){let p=[];for await(let u of r)p.push(typeof u=="string"?Buffer.from(u):u);let d;try{d=JSON.parse(Buffer.concat(p).toString("utf-8"))}catch{y(l,400,{error:"Invalid JSON"});return}if(!d.name||typeof d.name!="string"){y(l,400,{error:"Missing or invalid name"});return}let f=await C.removeComponent(d.name);y(l,200,f)}async function Fn(r,l){let p=[];for await(let u of r)p.push(typeof u=="string"?Buffer.from(u):u);let d;try{d=JSON.parse(Buffer.concat(p).toString("utf-8"))}catch{y(l,400,{error:"Invalid JSON"});return}if(!d.path||typeof d.path!="string"||typeof d.value!="string"){y(l,400,{error:"Missing or invalid path/value"});return}let f=await C.updateToken(d.path,d.value);y(l,200,f)}async function jn(r,l){let p=[];for await(let u of r)p.push(typeof u=="string"?Buffer.from(u):u);let d;try{d=JSON.parse(Buffer.concat(p).toString("utf-8"))}catch{y(l,400,{error:"Invalid JSON"});return}if(!d.path||typeof d.path!="string"){y(l,400,{error:"Missing or invalid path"});return}let f=await C.removeToken(d.path);y(l,200,f)}function Un(r,l){let p=o??"http://localhost:3000";if(!o){let f=r.headers.referer||r.headers.origin;if(f)try{let u=new URL(typeof f=="string"?f:f[0]||"");(u.hostname==="localhost"||u.hostname==="127.0.0.1")&&(p=u.origin)}catch{}}let d=bt(W,p);l.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),l.end(d)}async function zn(r){let l=Date.now();if(E&&l<E.expires){y(r,200,E.data);return}try{let{scanForComponents:p}=await import("./react-scanner-ZXYS5M3Y.mjs"),{generateRenderFiles:d}=await import("./render-generator-EANIDD2E.mjs"),f=await p(n);E={data:f,expires:l+5e3},d(f,n,ie).then(u=>{ie=u}).catch(u=>console.warn("[Bridge] Render generation failed:",u)),y(r,200,f)}catch(p){console.error("[Bridge] Scanner error:",p),y(r,500,{error:"Failed to scan components"})}}async function Ln(r){let l=[me(n,"node_modules","@popmelt.com","core","dist","canvas.mjs"),me(n,"packages","popmelt","dist","canvas.mjs")];try{let p=Ro(import.meta.url);l.unshift(me(Eo(p),"canvas.mjs"))}catch{}for(let p of l)try{let d=await bn(p,"utf-8");r.writeHead(200,{"Content-Type":"application/javascript; charset=utf-8","Access-Control-Allow-Origin":"*"}),r.end(d);return}catch{}console.error("[Bridge] Canvas bundle not found in:",l),y(r,404,{error:"Canvas bundle not found"})}async function Wn(r,l){if(!r||r.includes("/")||r.includes("\\")||r.includes("..")){y(l,400,{error:"Invalid filename"});return}try{let p=await bn(me(i,r)),d=r.split(".").pop()?.toLowerCase(),f=d==="png"?"image/png":d==="webp"?"image/webp":d==="jpg"||d==="jpeg"?"image/jpeg":"application/octet-stream";l.writeHead(200,{"Content-Type":f,"Cache-Control":"public, max-age=3600"}),l.end(p)}catch{y(l,404,{error:"File not found"})}}function Je(r){return`/files/${gt(r)}`}async function Hn(r,l){let p=await R.getThread(r);if(!p){y(l,404,{error:"Thread not found"});return}let d=(await w.loadRuns()).runs.filter(g=>g.threadId===r).sort((g,O)=>O.completedAt-g.completedAt)[0],f=d?await w.findCase(d.evalId):null,u=p.messages.map(({screenshotPath:g,screenshotPaths:O,imagePaths:F,replyImagePaths:q,...j})=>({...j,...j.role==="assistant"&&d?{evalRun:{...d,title:f?.title}}:{},...g?{screenshotUrl:Je(g)}:{},...O?{screenshotUrls:Object.fromEntries(Object.entries(O).map(([h,L])=>[h,Je(L)]))}:{},...F?{imageUrls:Object.fromEntries(Object.entries(F).map(([h,L])=>[h,L.map(Je)]))}:{},...q?{replyImageUrls:q.map(Je)}:{}}));y(l,200,{id:p.id,createdAt:p.createdAt,messages:u})}let wt=9,St=!1;for(let r=t;r<t+wt;r++)try{await No(re,r),W=r,St=!0,console.log(`[\u22B9 is watching :${W}]`);break}catch(l){if(l.code==="EADDRINUSE"){let p=await Do(r);if(p&&p.projectId===e)return console.log(`[\u22B9 already watching :${r}]`),{port:r,projectId:e,close:async()=>{}};continue}throw l}if(!St)throw new Error(`[Bridge] All ports ${t}\u2013${t+wt-1} in use`);for(let[r,l]of Object.entries(S))!l.available||!l.path||H(r,l.path).then(p=>{if(p)console.log(`[Bridge] ${r} warmed up`);else{console.warn(`[Bridge] ${r} warm-up failed \u2014 marking unavailable`),l.available=!1,l.path=null;for(let d of _)vt(d,{type:"capabilities_changed",data:{}})}});let Gn=setInterval(()=>{kn(i).catch(()=>{})},Mo);return{port:W,projectId:e,close:async()=>{clearInterval(Gn),await N.destroyAsync();for(let r of _)try{r.res.end()}catch{}return _.clear(),new Promise(r=>{re.close(()=>r())})}}}async function kn(s){try{let t=await So(s),n=Date.now();for(let e of t){let o=me(s,e);try{let i=await bo(o);n-i.mtimeMs>Co&&await xo(o)}catch{}}}catch{}}var fe="\x1B[35m[popmelt]\x1B[0m";async function Uo(){let s=process.argv.slice(2);if(s[0]==="wrap"){let t=s.indexOf("--");(t===-1||t===s.length-1)&&(console.error(`${fe} Usage: popmelt wrap -- <dev command>`),console.error(`${fe} Example: popmelt wrap -- next dev`),console.error(`${fe} Example: popmelt wrap -- astro dev`),process.exit(1));let n=s.slice(t+1);await Wo(n);return}if(s[0]==="bridge"){await zo();return}if(s[0]==="stop"){await Lo();return}console.log(`${fe} Popmelt \u2014 design collaboration for AI coding agents`),console.log(""),console.log(" popmelt wrap -- <command> Start bridge + dev server together"),console.log(" popmelt bridge Start the bridge server standalone"),console.log(" popmelt stop Stop a detached bridge"),console.log(""),console.log("Examples:"),console.log(" popmelt wrap -- next dev"),console.log(" popmelt wrap -- astro dev"),console.log(" popmelt wrap -- vite"),console.log(""),console.log("In package.json:"),console.log(' "scripts": { "dev": "popmelt wrap -- next dev" }')}async function zo(){let s=await yt({projectRoot:process.cwd()});console.log(`${fe} Bridge running on http://localhost:${s.port}`),await new Promise(t=>{let n=async()=>{console.log(`
|
|
359
|
-
${fe} Shutting down bridge...`),await s.close(),t()};process.on("SIGINT",n),process.on("SIGTERM",n)})}async function Lo(){let s=jo(process.cwd(),".popmelt","bridge.lock"),t;try{t=JSON.parse(await Bo(s,"utf8"))}catch{console.log(`${fe} No bridge running (no .popmelt/bridge.lock found)`);return}try{process.kill(t.pid,"SIGTERM"),console.log(`${fe} Sent SIGTERM to bridge (pid ${t.pid}, port ${t.port})`)}catch(n){if(n.code==="ESRCH")console.log(`${fe} Bridge process ${t.pid} already dead`);else throw n}try{await Fo(s)}catch{}}async function Wo(s){let t=await yt({projectRoot:process.cwd()});console.log(`${fe} Bridge running on http://localhost:${t.port}`);let[n,...e]=s;console.log(`${fe} Starting: ${s.join(" ")}`);let o=Jo(n,e,{stdio:"inherit",shell:!0,env:{...process.env,POPMELT_BRIDGE_URL:`http://localhost:${t.port}
|
|
359
|
+
${fe} Shutting down bridge...`),await s.close(),t()};process.on("SIGINT",n),process.on("SIGTERM",n)})}async function Lo(){let s=jo(process.cwd(),".popmelt","bridge.lock"),t;try{t=JSON.parse(await Bo(s,"utf8"))}catch{console.log(`${fe} No bridge running (no .popmelt/bridge.lock found)`);return}try{process.kill(t.pid,"SIGTERM"),console.log(`${fe} Sent SIGTERM to bridge (pid ${t.pid}, port ${t.port})`)}catch(n){if(n.code==="ESRCH")console.log(`${fe} Bridge process ${t.pid} already dead`);else throw n}try{await Fo(s)}catch{}}async function Wo(s){let t=await yt({projectRoot:process.cwd()});console.log(`${fe} Bridge running on http://localhost:${t.port}`);let[n,...e]=s;console.log(`${fe} Starting: ${s.join(" ")}`);let o=Jo(n,e,{stdio:"inherit",shell:!0,env:{...process.env,POPMELT_BRIDGE_URL:`http://localhost:${t.port}`,POPMELT_PROJECT_ID:t.projectId}}),i=a=>{o.kill(a)};process.on("SIGINT",()=>i("SIGINT")),process.on("SIGTERM",()=>i("SIGTERM")),o.on("exit",async(a,c)=>{await t.close(),c?process.kill(process.pid,c):process.exit(a??0)})}Uo().catch(s=>{console.error(`${fe} Fatal:`,s),process.exit(1)});
|