@popmelt.com/core 0.11.3 → 0.12.0
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/codex-plugin/.codex-plugin/plugin.json +1 -1
- package/dist/bridge-entry.mjs +3 -3
- package/dist/{chunk-6UUYBXUW.mjs → chunk-AGGSNB3B.mjs} +1 -1
- package/dist/cli.mjs +3 -3
- package/dist/index.d.mts +31 -1
- package/dist/index.mjs +69 -42
- package/dist/plugin-astro.mjs +1 -1
- package/dist/plugin-next.d.mts +40 -0
- package/dist/plugin-vite.mjs +1 -1
- package/dist/{server-QPTMLI2U.mjs → server-34WZBGOE.mjs} +36 -36
- package/dist/server.mjs +3 -3
- package/package.json +2 -1
package/dist/server.mjs
CHANGED
|
@@ -158,7 +158,7 @@ Search raw \`.popmelt\` records only when the supplied Imprint context is insuff
|
|
|
158
158
|
|
|
159
159
|
Use Popmelt history to explain why a decision was made or how shared understanding developed. Use git history only when the question depends on chronology or source provenance. Clearly distinguish recorded human or collaboration evidence from your own inference.
|
|
160
160
|
|
|
161
|
-
Apply an evidence-sufficiency stopping rule: stop researching as soon as the relevant Imprint and current source adequately explain the observation. If one corroborating collaboration record is needed, stop after finding it unless the evidence conflicts or the developer requested a fuller history. Do not reconstruct an exhaustive timeline for a present-tense explanation, and do not search the full history for routine implementation work.`;function kn(o,e,t){let n=[];if(o.annotations.length>0){n.push("## Annotations");for(let r of o.annotations){let i=r.elements.map(l=>{let v=[l.selector];return l.reactComponent&&v.push(`(${l.reactComponent})`),v.join(" ")}).join(", "),s=r.instruction||"No text";n.push(`- id=${r.id} [${r.type}] ${s} \u2192 Elements: ${i||"none"}`);let a=e?.[r.id];if(a&&a.length>0)for(let l of a)n.push(` Attached image: use the Read tool to view ${l}`);let d=t?.[r.id];if(d?.length)for(let l of d)n.push(` Attached context (${l.name}, ${l.mimeType}): use the Read tool to inspect ${l.path}`)}}if(o.styleModifications.length>0){n.push(""),n.push("## Style Changes (make permanent in source)"),n.push("The developer previewed these CSS changes via inline style overrides. Find the corresponding styles in the source files and update them so the changes persist:");for(let r of o.styleModifications){let i=r.element?.reactComponent?`(${r.element.reactComponent})`:"";for(let s of r.changes)n.push(`- ${r.selector} ${i}: ${s.property} ${s.original} \u2192 ${s.modified}`)}}if(o.textModifications?.length){n.push(""),n.push("## Text Changes (make permanent in source)"),n.push("The developer directly edited rendered DOM text in the browser. Find the source copy and update it so the text change persists:");for(let r of o.textModifications){let i=r.element?.reactComponent?`(${r.element.reactComponent})`:"",s=JSON.stringify(r.original),a=JSON.stringify(r.modified),d=r.textNodePath.length>0?` textNodePath=${r.textNodePath.join(".")}`:"";n.push(`- ${r.selector} ${i}${d}: ${s} \u2192 ${a}`)}}if(o.domModifications?.length){n.push(""),n.push("## DOM Structure Changes (make permanent in source)"),n.push("The developer rearranged or copied rendered elements in the browser as a visual reference. Update the source structure so this layout/content relationship persists:");for(let r of o.domModifications){let i=r.element?.reactComponent?`(${r.element.reactComponent})`:"",s=r.sourceElement?.reactComponent?` from ${r.sourceSelector} (${r.sourceElement.reactComponent})`:r.sourceSelector?` from ${r.sourceSelector}`:"",a=r.referenceSelector?` ${r.placement} ${r.referenceSelector}`:` at index ${r.targetIndex}`;n.push(`- ${r.operation}: ${r.selector} ${i}${s} \u2192 ${r.targetParentSelector}${a}`)}}if(o.spacingTokenChanges?.length){n.push(""),n.push("## Spacing Token Changes"),n.push("The developer adjusted these spacing tokens. Apply each change to the source code:");for(let r of o.spacingTokenChanges){n.push(`
|
|
161
|
+
Apply an evidence-sufficiency stopping rule: stop researching as soon as the relevant Imprint and current source adequately explain the observation. If one corroborating collaboration record is needed, stop after finding it unless the evidence conflicts or the developer requested a fuller history. Do not reconstruct an exhaustive timeline for a present-tense explanation, and do not search the full history for routine implementation work.`;function kn(o,e,t){let n=[];if(o.annotations.length>0){n.push("## Annotations");for(let r of o.annotations){let i=r.elements.map(l=>{let v=[l.selector];return l.reactComponent&&v.push(`(${l.reactComponent})`),v.join(" ")}).join(", "),s=r.instruction||"No text";n.push(`- id=${r.id} [${r.type}] ${s} \u2192 Elements: ${i||"none"}`);let a=e?.[r.id];if(a&&a.length>0)for(let l of a)n.push(` Attached image: use the Read tool to view ${l}`);let d=t?.[r.id];if(d?.length)for(let l of d)n.push(` Attached context (${l.name}, ${l.mimeType}): use the Read tool to inspect ${l.path}`)}}if(o.styleModifications.length>0){n.push(""),n.push("## Style Changes (make permanent in source)"),n.push("The developer previewed these CSS changes via inline style overrides. Find the corresponding styles in the source files and update them so the changes persist:");for(let r of o.styleModifications){let i=r.element?.reactComponent?`(${r.element.reactComponent})`:"";for(let s of r.changes){let a=s.token?` [${s.token}]`:"";n.push(`- ${r.selector} ${i}: ${s.property} ${s.original} \u2192 ${s.modified}${a}`)}}}if(o.textModifications?.length){n.push(""),n.push("## Text Changes (make permanent in source)"),n.push("The developer directly edited rendered DOM text in the browser. Find the source copy and update it so the text change persists:");for(let r of o.textModifications){let i=r.element?.reactComponent?`(${r.element.reactComponent})`:"",s=JSON.stringify(r.original),a=JSON.stringify(r.modified),d=r.textNodePath.length>0?` textNodePath=${r.textNodePath.join(".")}`:"";n.push(`- ${r.selector} ${i}${d}: ${s} \u2192 ${a}`)}}if(o.domModifications?.length){n.push(""),n.push("## DOM Structure Changes (make permanent in source)"),n.push("The developer rearranged or copied rendered elements in the browser as a visual reference. Update the source structure so this layout/content relationship persists:");for(let r of o.domModifications){let i=r.element?.reactComponent?`(${r.element.reactComponent})`:"",s=r.sourceElement?.reactComponent?` from ${r.sourceSelector} (${r.sourceElement.reactComponent})`:r.sourceSelector?` from ${r.sourceSelector}`:"",a=r.referenceSelector?` ${r.placement} ${r.referenceSelector}`:` at index ${r.targetIndex}`;n.push(`- ${r.operation}: ${r.selector} ${i}${s} \u2192 ${r.targetParentSelector}${a}`)}}if(o.spacingTokenChanges?.length){n.push(""),n.push("## Spacing Token Changes"),n.push("The developer adjusted these spacing tokens. Apply each change to the source code:");for(let r of o.spacingTokenChanges){n.push(`
|
|
162
162
|
### ${r.tokenName}: ${r.originalPx}px \u2192 ${r.newPx}px`);for(let i of r.affectedElements){let s=i.reactComponent?` (${i.reactComponent})`:"";i.matchedClass&&i.suggestedClass?n.push(`- ${i.selector}${s}: \`${i.matchedClass}\` \u2192 \`${i.suggestedClass}\``):n.push(`- ${i.selector}${s}: ${i.property} ${r.originalPx}px \u2192 ${r.newPx}px`),n.push(` class="${i.className}"`)}}}if(o.inspectedElement){let r=o.inspectedElement;n.push(""),n.push("## Inspected Element"),n.push("The developer has this element selected in the inspector:");let i=[r.selector];r.reactComponent&&i.push(`(${r.reactComponent})`),r.context&&i.push(`in ${r.context}`),r.textContent&&i.push(`"${r.textContent.slice(0,80)}"`),n.push(`- ${i.join(" ")}`)}return n.join(`
|
|
163
163
|
`)}function ls(o,e,t){let n=[],i=new Set(e.annotations.map(s=>s.pathname).filter(Boolean)).size>1;if(n.push("You are reviewing a UI screenshot with developer annotations."),n.push(""),!i&&t?.provider!=="codex"&&(n.push(`IMPORTANT: First, use the Read tool to view the screenshot at: ${o}`),n.push("")),n.push(`The developer annotated their running app at ${e.url} (${e.viewport.width}x${e.viewport.height}).`),t?.threadHistory&&t.threadHistory.length>0){n.push(""),n.push("## Previous Conversation");let s=0;for(let a of t.threadHistory)if(a.role==="human")s++,a.replyToQuestion?(n.push(`### Round ${s} (human) \u2014 reply`),n.push(`"${a.replyToQuestion}"`)):(n.push(`### Round ${s} (human)`),a.feedbackSummary&&n.push(`Annotations: ${a.feedbackSummary}`),a.annotationIds&&a.annotationIds.length>0&&n.push(`Annotation IDs: ${a.annotationIds.join(", ")}`));else if(a.question)n.push(`### Round ${s} (assistant) \u2014 question`),n.push(`"${a.question}"`);else{if(n.push(`### Round ${s} (assistant)`),a.responseText&&n.push(`Response: ${a.responseText}`),a.resolutions&&a.resolutions.length>0)for(let d of a.resolutions){let l=d.finalScope??d.inferredScope,v=l?` [${l.breadth} ${l.target}]`:"";n.push(`- ${d.annotationId}: ${d.status}${v} \u2014 ${d.summary}`),d.filesModified&&d.filesModified.length>0&&n.push(` Files: ${d.filesModified.join(", ")}`)}a.toolsUsed&&a.toolsUsed.length>0&&n.push(`Tools used: ${a.toolsUsed.join(", ")}`)}n.push(""),n.push("The current round is shown in full below.")}if(t?.designModel){n.push(""),n.push("## Established Design Policies"),n.push("This project has an active product model projected only from accepted canonical decisions. When making changes, follow these patterns unless the developer explicitly overrides them.");let s=t.designModel.rules;if(Array.isArray(s)&&s.length>0)if(n.push(""),n.push("Rules:"),s.length>0&&typeof s[0]=="object"&&s[0]!==null&&"scope"in s[0]){let v=new Map;for(let S of s)if(typeof S=="object"&&S!==null&&"text"in S){let g=S,P=g.scope||"general";v.has(P)||v.set(P,[]),v.get(P).push(g.text)}for(let[S,g]of v){n.push(`**${S.charAt(0).toUpperCase()+S.slice(1)}**`);for(let P of g)n.push(`- ${P}`)}}else for(let v of s)typeof v=="string"&&n.push(`- ${v}`);let a=t.designModel.tokens;a&&typeof a=="object"&&(n.push(""),n.push("Design tokens:"),n.push("```json"),n.push(JSON.stringify(a,null,2)),n.push("```"));let d=t.designModel.components;d&&typeof d=="object"&&(n.push(""),n.push("Component patterns:"),n.push("```json"),n.push(JSON.stringify(d,null,2)),n.push("```")),n.push(""),n.push("### Applied Model-Gap Details"),n.push("Only when you actually modify the project and implement a design decision that has no matching policy in the model above (e.g., styling a component type not yet in the model, choosing a color with no token, picking spacing with no rule), describe that applied gap:"),n.push("<novel>"),n.push('[{"category":"component","element":"button","decision":"Used 8px border-radius, 12px 24px padding","reason":"No button pattern in design model"}]'),n.push("</novel>"),n.push('- `category`: "token" (color, spacing, typography), "component" (UI component pattern), or "element" (specific element style)'),n.push("- `element`: What you are styling or creating"),n.push("- `decision`: What you actually implemented (specific values)"),n.push("- `reason`: Why this is novel (what is missing from the model)"),n.push("Do not emit <novel> for answer-only, explanatory, investigative, advisory, planning, or question turns. Never describe a recommendation or proposed future change as applied."),n.push("This is an execution receipt, not a memory proposal. Continuous imprinting separately decides whether the collaboration produced reusable learning.")}if(t?.designModel||(n.push(""),n.push("## Design Context"),n.push("This project uses Popmelt for product governance. Accepted canonical decisions may be projected into a rebuildable working model.")),i){let s=t?.screenshotPaths??{},a=new Map;for(let d of e.annotations){let l=d.pathname||new URL(e.url).pathname;a.has(l)||a.set(l,[]),a.get(l).push(d)}n.push(""),n.push("The developer annotated multiple pages. Each page section includes its own screenshot where available.");for(let[d,l]of a){n.push(""),n.push(`## Page: ${d}`);let v=s[d];v&&t?.provider!=="codex"?n.push(`IMPORTANT: Use the Read tool to view the screenshot at: ${v}`):!v&&t?.provider!=="codex"&&(Object.keys(s).length===0?(n.push(`IMPORTANT: Use the Read tool to view the screenshot at: ${o}`),n.push("(This screenshot shows the page the developer was on when submitting \u2014 not this page)")):n.push("(No screenshot available for this page \u2014 work from the annotation text and selectors)"));let S={...e,annotations:l,styleModifications:e.styleModifications},g=kn(S,t?.imagePaths,t?.attachmentFiles);g&&(n.push(""),n.push(g))}}else{let s=kn(e,t?.imagePaths,t?.attachmentFiles);s&&(n.push(""),n.push(s))}return n.push(""),n.push("Follow the developer's instructions. If they ask for changes, apply them to the source files \u2014 the dev server has HMR so changes appear immediately. If they ask a question or request analysis, respond in text without modifying code."),n.push(""),n.push("IMPORTANT: If any elements you modify have a `data-pm` attribute, preserve it in the source. This attribute tracks annotation positions."),n.push(""),n.push("## Resolution"),n.push("After completing all work, output one resolution envelope listing what you did for each annotation:"),n.push("<resolution>"),n.push('{"annotations":[{"annotationId":"<id>","status":"resolved","summary":"<what you did>","filesModified":["<file>"],"declaredScope":{"breadth":"...","target":"..."},"inferredScope":{"breadth":"...","target":"..."}}]}'),n.push("</resolution>"),n.push("Continuous imprinting may require an additional `imprint` field in this same envelope. Follow that contract when it appears below; do not emit a second resolution block."),n.push(`Use status "resolved" when the change is complete, or "needs_review" if you're unsure about the result.`),n.push(""),n.push("### Scope classification"),n.push("Each resolution MUST include scope fields:"),n.push("- `declaredScope`: What scope the user's instruction text implies. null if no signal."),n.push("- `inferredScope`: What scope the change actually has, based on what you modified."),n.push("Scope has two dimensions:"),n.push('- `breadth`: "instance" (just this occurrence) or "pattern" (all similar occurrences)'),n.push('- `target`: "element" (a specific DOM element), "component" (a React/UI component), or "token" (a design token \u2014 color, spacing, typography)'),n.push('Note: "instance" + "token" is invalid \u2014 tokens are inherently patterns.'),n.push("If you cannot confidently determine scope, set it to null."),n.push(""),n.push("## Questions"),n.push("If the annotation text is unclear, ambiguous, gibberish, or you are unsure what the developer wants, output a question:"),n.push('<question>What do you mean by "..."?</question>'),n.push("Do NOT guess what unclear instructions mean \u2014 ask instead."),n.push("You may output BOTH a <resolution> for clear annotations AND a <question> for unclear ones in the same response."),n.join(`
|
|
164
164
|
`)}function ps(o){return o.match(/<question>\s*([\s\S]*?)\s*<\/question>/)?.[1]??null}function us(o,e,t,n){let r=[];r.push("You are continuing work on a UI based on the developer's reply to your question."),r.push(""),t!=="codex"&&r.push(`IMPORTANT: First, use the Read tool to view the screenshot at: ${o}`);let i=e.find(s=>s.role==="human"&&s.feedbackContext);if(i?.feedbackContext&&(r.push(""),r.push(i.feedbackContext)),e.length>0){r.push(""),r.push("## Conversation History");let s=0;for(let a of e)a.role==="human"?(s++,a.replyToQuestion?(r.push(`### Round ${s} (human) \u2014 reply`),r.push(`"${a.replyToQuestion}"`)):(r.push(`### Round ${s} (human)`),a.feedbackSummary&&r.push(`Annotations: ${a.feedbackSummary}`))):a.question?(r.push(`### Round ${s} (assistant) \u2014 question`),r.push(`"${a.question}"`)):(r.push(`### Round ${s} (assistant)`),a.responseText&&r.push(`Response: ${a.responseText}`))}if(r.push(""),r.push("The developer answered your question. Continue working based on their reply."),r.push("Follow their instructions \u2014 apply code changes only if requested. The dev server has HMR so changes appear immediately."),r.push(""),r.push("IMPORTANT: If any elements you modify have a `data-pm` attribute, preserve it in the source. This attribute tracks annotation positions."),n&&n.length>0){r.push(""),r.push("## Attached Images"),r.push("The developer attached reference images with their reply:");for(let s of n)r.push(`Attached image: use the Read tool to view the image at: ${s}`)}return r.push(""),r.push("## Resolution"),r.push("After completing all work, output one resolution envelope listing what you did for each annotation:"),r.push("<resolution>"),r.push('{"annotations":[{"annotationId":"<id>","status":"resolved","summary":"<what you did>","filesModified":["<file>"],"declaredScope":{"breadth":"...","target":"..."},"inferredScope":{"breadth":"...","target":"..."}}]}'),r.push("</resolution>"),r.push("Continuous imprinting may require an additional `imprint` field in this same envelope. Follow that contract when it appears below; do not emit a second resolution block."),r.push(`Use status "resolved" when the change is complete, or "needs_review" if you're unsure about the result.`),r.push(""),r.push("### Scope classification"),r.push("Each resolution MUST include scope fields:"),r.push("- `declaredScope`: What scope the user's instruction text implies. null if no signal."),r.push("- `inferredScope`: What scope the change actually has, based on what you modified."),r.push("Scope has two dimensions:"),r.push('- `breadth`: "instance" (just this occurrence) or "pattern" (all similar occurrences)'),r.push('- `target`: "element" (a specific DOM element), "component" (a React/UI component), or "token" (a design token \u2014 color, spacing, typography)'),r.push('Note: "instance" + "token" is invalid \u2014 tokens are inherently patterns.'),r.push("If you cannot confidently determine scope, set it to null."),r.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.'),r.push(""),r.push("## Questions"),r.push("If you still need clarification, output:"),r.push("<question>Your question here</question>"),r.push("You may output BOTH a <resolution> and a <question> in the same response."),r.join(`
|
|
@@ -170,10 +170,10 @@ Apply an evidence-sufficiency stopping rule: stop researching as soon as the rel
|
|
|
170
170
|
`);let n=new Map;for(let r of e){let i=r.pathname||"(unknown)",s=n.get(i)??[];s.push(r.instruction),n.set(i,s)}return[...n.entries()].map(([r,i])=>`\`${r}\`
|
|
171
171
|
${i.map(s=>`- ${s}`).join(`
|
|
172
172
|
`)}`).join(`
|
|
173
|
-
`)}var Ds={name:"@popmelt.com/core",version:"0.
|
|
173
|
+
`)}var Ds={name:"@popmelt.com/core",version:"0.12.0",description:"The design collaboration layer for AI coding agents",license:"PolyForm-Shield-1.0.0",author:"Popmelt <reb@popmelt.com> (https://popmelt.com)",homepage:"https://github.com/popmelt/core",bugs:{url:"https://github.com/popmelt/core/issues"},repository:{type:"git",url:"git+https://github.com/popmelt/core.git"},keywords:["ai","annotations","collaboration","devtools","react","visual-feedback"],bin:{popmelt:"dist/cli.mjs"},sideEffects:!1,engines:{node:">=18.0.0"},scripts:{build:"tsup",clean:"git clean -xdf .turbo node_modules dist",format:'prettier --check "**/*.{ts,tsx}"',lint:"eslint .","pack:smoke":"node scripts/pack-smoke.mjs",prepublishOnly:"pnpm run verify",test:"vitest run","test:watch":"vitest",typecheck:"tsc --noEmit --incremental false",verify:"pnpm run typecheck && pnpm run lint && pnpm run test && pnpm run build && pnpm run pack:smoke"},exports:{".":{source:"./src/index.ts",types:"./dist/index.d.mts",import:"./dist/index.mjs"},"./provider":{source:"./src/components/PopmeltProvider.tsx",types:"./dist/index.d.mts",import:"./dist/index.mjs"},"./server":{source:"./src/server/index.ts",types:"./dist/server.d.mts",import:"./dist/server.mjs"},"./memory":{source:"./src/memory/index.ts",types:"./dist/memory.d.mts",import:"./dist/memory.mjs"},"./memory/legacy":{source:"./src/server/memory/index.ts",types:"./dist/memory-legacy.d.mts",import:"./dist/memory-legacy.mjs"},"./memory/store":{source:"./src/server/memory/journal-index.ts",types:"./dist/memory-store.d.mts",import:"./dist/memory-store.mjs"},"./next":{source:"./src/plugins/next.ts",types:"./dist/plugin-next.d.mts",import:"./dist/plugin-next.mjs",default:"./dist/plugin-next.mjs"},"./vite":{source:"./src/plugins/vite.ts",types:"./dist/plugin-vite.d.mts",import:"./dist/plugin-vite.mjs",default:"./dist/plugin-vite.mjs"},"./astro":{source:"./src/plugins/astro.ts",types:"./dist/plugin-astro.d.mts",import:"./dist/plugin-astro.mjs",default:"./dist/plugin-astro.mjs"}},files:["dist","codex-plugin","LICENSE","README.md","THIRD_PARTY_NOTICES.md"],dependencies:{"modern-screenshot":"4.7.0",ws:"8.21.1"},peerDependencies:{"lucide-react":">=1.23.0",next:">=14.0.0",react:">=18.0.0","react-dom":">=18.0.0"},peerDependenciesMeta:{next:{optional:!0}},devDependencies:{"@kit/eslint-config":"workspace:^","@types/react":"19.1.0","@types/react-dom":"19.1.2","@types/ws":"8.18.1",eslint:"^9.24.0",geist:"1.7.2",jsdom:"26.1.0","lucide-react":"^1.23.0",next:"15.3.8",prettier:"^3.5.3",react:"19.1.0","react-dom":"19.1.0",tsup:"^8.5.1",typescript:"^5.8.3",vitest:"^3.2.4"}};var dt=Ds.version;var ep=1111,tp=["Read","Edit","Write","Glob","Grep","Bash","WebFetch","WebSearch","Bash(curl:*)"],np=1800*1e3,op=3600*1e3,Bs=45e3,rp=5e3,ip=1e4,sp=2*1024*1024;function Js(o){return o.length<=1?o[0]??"":["The developer sent these queued steering messages while you were working:","",...o.map((e,t)=>`${t+1}. ${e}`)].join(`
|
|
174
174
|
`)}function On(o){return[...new Set(o.flatMap(e=>{let t=e.imprintSummary;return e.role==="assistant"&&t?.grounding&&!t.resolvedAction?[t.grounding.explanationId]:[]}))]}function qs(o){let e=o.findLastIndex(r=>r.role==="assistant");if(e<0)return[];let t=o[e];if(!t?.question||!t.jobId.startsWith("imprint-"))return[];let n=o.slice(0,e).findLast(r=>r.role==="assistant"&&r.imprintSummary?.resolvedAction==="no"&&!!r.imprintSummary.grounding);return n?.imprintSummary?.grounding?[n.imprintSummary.grounding.explanationId]:[]}function ap(o,e){if(e.size===1)return[...o].reverse().find(t=>{let n=t.imprintSummary;return t.role==="assistant"&&!!n?.grounding&&!n?.resolvedAction&&e.has(n.grounding.explanationId)})}function zs(o){if(!o)return!1;try{let e=new URL(o);return e.hostname==="localhost"||e.hostname.endsWith(".localhost")||e.hostname==="127.0.0.1"||e.hostname==="::1"||e.hostname==="[::1]"}catch{return!1}}function dp(o,e,t){let n=[...t];for(let r of o)if(r.type==="tool_use"){let i=r.tool||"",s=r.file??void 0,a=r.content??void 0,d=s?s.split("/").pop()??s:void 0,l;switch(i){case"Read":l=d?`Reading ${d}`:"Reading file";break;case"Edit":l=d?`Editing ${d}`:"Editing file";break;case"Write":l=d?`Writing ${d}`:"Writing file";break;case"Bash":l=a?a.split(`
|
|
175
175
|
`)[0].trim().slice(0,60):"Running command";break;case"Glob":l="Searching files";break;case"Grep":l="Searching code";break;case"WebFetch":l="Fetching page";break;case"WebSearch":l="Searching web";break;default:l=i?`Using ${i}`:"tool";break}let v=s??a??void 0,S=s?Fs(s)?s:Zl(e,s):void 0,g=n[n.length-1];g&&g.kind==="tool_group"&&g.tool===i?g.items.push({label:l,detail:v,...S?{filePath:S}:{}}):n.push({kind:"tool_group",tool:i,items:[{label:l,detail:v,...S?{filePath:S}:{}}]})}return n}function cp(o,e){if(o.processedIds.length===0&&o.success)return"No accepted decisions were ready for model projection.";if(o.success&&o.proposalId)return"";let t=[];return o.success?t.push("Model suggestion ready."):t.push("Model projection failed."),o.proposalId&&t.push("Review the proposed model changes below."),e&&(e.outputStats?t.push(`${e.outputStats.ruleCount} rules, ${e.outputStats.tokenSectionCount} token sections, ${e.outputStats.componentCount} components proposed from ${e.decisionIds.length} decision${e.decisionIds.length===1?"":"s"}.`):t.push(`${e.decisionIds.length} decision${e.decisionIds.length===1?"":"s"} processed.`)),o.error&&(t.push(""),t.push(`Error: ${o.error}`),t.push("The selected decisions were not marked applied and remain visible in projection history.")),t.join(`
|
|
176
|
-
`)}function lp(o,e=96){let t=o.replace(/\s+/g," ").trim();return t.length>e?`${t.slice(0,e-1)}...`:t}function Ls(o){let e=o.styleModifications.flatMap(s=>{let a=s.element?.reactComponent||s.element?.tagName||s.selector;return s.changes.map(d=>`${a}: ${d.property} ${d.original||"unset"} -> ${d.modified||"unset"}`)}),t=(o.spacingTokenChanges??[]).map(s=>`${s.tokenName}: ${s.originalPx}px -> ${s.newPx}px`),n=(o.textModifications??[]).map(s=>`${s.element?.reactComponent||s.element?.tagName||s.selector}: text ${s.original||"empty"} -> ${s.modified||"empty"}`),r=o.annotations.map(s=>{let a=s.instruction?.trim();if(a)return a;if(s.imageCount&&s.imageCount>0)return`${s.imageCount} image${s.imageCount===1?"":"s"}`;let d=s.elements?.[0]?.reactComponent||s.elements?.[0]?.selector||s.linkedSelector||s.type;return`${s.type==="annotation"?"Annotation":`${s.type} annotation`} on ${d}`}),i=[...e,...n,...t,...r].map(s=>lp(s)).filter(Boolean);return i.length===0?"Annotation":i.length<=3?i.join("; "):`${i.slice(0,3).join("; ")}; +${i.length-3} more`}function pp(o,e){let t=o.headers.origin;zs(t)&&(e.setHeader("Access-Control-Allow-Origin",t),e.setHeader("Access-Control-Allow-Methods","GET, POST, PATCH, DELETE, OPTIONS"),e.setHeader("Access-Control-Allow-Headers","Content-Type, X-Popmelt-Project-Id"))}function $(o,e,t){o.writeHead(e,{"Content-Type":"application/json"}),o.end(JSON.stringify(t))}var up=16384,mp=131072;async function Oe(o,e=up){let t=[],n=0;for await(let i of o){let s=typeof i=="string"?Buffer.from(i):i;if(n+=s.length,n>e)throw new Error("Request body too large");t.push(s)}if(t.length===0)return{};let r=JSON.parse(Buffer.concat(t).toString("utf8"));if(!r||typeof r!="object"||Array.isArray(r))throw new Error("Expected a JSON object");return r}async function fp(o,e){let t=[],n=0;for await(let r of o){let i=typeof r=="string"?Buffer.from(r):r;if(n+=i.length,n>e)throw new Error("Request body too large");t.push(i)}return Buffer.concat(t)}function hp(o,e){let t=o.headers["x-popmelt-project-id"];return(Array.isArray(t)?t[0]:t)||e.searchParams.get("projectId")||null}function gp(o,e){if(!o)return e;let t=o.match(/^#?([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i);if(!t)return e;let[,n,r,i]=t;return`\x1B[38;2;${parseInt(n,16)};${parseInt(r,16)};${parseInt(i,16)}m${e}\x1B[0m`}function Co(o,e){try{o.res.write(`event: ${e.type}
|
|
176
|
+
`)}function lp(o,e=96){let t=o.replace(/\s+/g," ").trim();return t.length>e?`${t.slice(0,e-1)}...`:t}function Ls(o){let e=o.styleModifications.flatMap(s=>{let a=s.element?.reactComponent||s.element?.tagName||s.selector;return s.changes.map(d=>`${a}: ${d.property} ${d.original||"unset"} -> ${d.modified||"unset"}${d.token?` [${d.token}]`:""}`)}),t=(o.spacingTokenChanges??[]).map(s=>`${s.tokenName}: ${s.originalPx}px -> ${s.newPx}px`),n=(o.textModifications??[]).map(s=>`${s.element?.reactComponent||s.element?.tagName||s.selector}: text ${s.original||"empty"} -> ${s.modified||"empty"}`),r=o.annotations.map(s=>{let a=s.instruction?.trim();if(a)return a;if(s.imageCount&&s.imageCount>0)return`${s.imageCount} image${s.imageCount===1?"":"s"}`;let d=s.elements?.[0]?.reactComponent||s.elements?.[0]?.selector||s.linkedSelector||s.type;return`${s.type==="annotation"?"Annotation":`${s.type} annotation`} on ${d}`}),i=[...e,...n,...t,...r].map(s=>lp(s)).filter(Boolean);return i.length===0?"Annotation":i.length<=3?i.join("; "):`${i.slice(0,3).join("; ")}; +${i.length-3} more`}function pp(o,e){let t=o.headers.origin;zs(t)&&(e.setHeader("Access-Control-Allow-Origin",t),e.setHeader("Access-Control-Allow-Methods","GET, POST, PATCH, DELETE, OPTIONS"),e.setHeader("Access-Control-Allow-Headers","Content-Type, X-Popmelt-Project-Id"))}function $(o,e,t){o.writeHead(e,{"Content-Type":"application/json"}),o.end(JSON.stringify(t))}var up=16384,mp=131072;async function Oe(o,e=up){let t=[],n=0;for await(let i of o){let s=typeof i=="string"?Buffer.from(i):i;if(n+=s.length,n>e)throw new Error("Request body too large");t.push(s)}if(t.length===0)return{};let r=JSON.parse(Buffer.concat(t).toString("utf8"));if(!r||typeof r!="object"||Array.isArray(r))throw new Error("Expected a JSON object");return r}async function fp(o,e){let t=[],n=0;for await(let r of o){let i=typeof r=="string"?Buffer.from(r):r;if(n+=i.length,n>e)throw new Error("Request body too large");t.push(i)}return Buffer.concat(t)}function hp(o,e){let t=o.headers["x-popmelt-project-id"];return(Array.isArray(t)?t[0]:t)||e.searchParams.get("projectId")||null}function gp(o,e){if(!o)return e;let t=o.match(/^#?([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i);if(!t)return e;let[,n,r,i]=t;return`\x1B[38;2;${parseInt(n,16)};${parseInt(r,16)};${parseInt(i,16)}m${e}\x1B[0m`}function Co(o,e){try{o.res.write(`event: ${e.type}
|
|
177
177
|
data: ${JSON.stringify(e)}
|
|
178
178
|
|
|
179
179
|
`)}catch{}}function rn(o){return o==="claude"||o==="codex"||o==="copilot"?o:void 0}async function $o(o){try{let e=new AbortController,t=setTimeout(()=>e.abort(),500),n=await fetch(`http://127.0.0.1:${o}/status`,{signal:e.signal});return clearTimeout(t),n.ok?await n.json():null}catch{return null}}function yp(o,e){return new Promise((t,n)=>{let r=s=>{o.removeListener("listening",i),n(s)},i=()=>{o.removeListener("error",r),t()};o.once("error",r),o.once("listening",i),o.listen(e,"127.0.0.1")})}async function Vs(o={}){let e=new Date().toISOString(),t=o.port??ep,n=o.projectRoot??process.cwd(),r=await Kl(n).catch(()=>n),i=Gt(r),s=await Xn(r),a=o.devOrigin??(process.env.PORT?`http://localhost:${process.env.PORT}`:null),d=o.tempDir??Xe(Xl(),"popmelt-bridge"),l=o.maxTurns??40,v=o.maxBudgetUsd??1,S=[...o.allowedTools??tp],g=o.claudePath??"claude",P=o.copilotPath??"copilot",T=o.provider??"codex",h=o.timeoutMs,u=o.nativeCaptureUrl??process.env.POPMELT_CDP_URL??null,y=o.restartMode??"embedded",I=t,p={},A={claude:g,codex:"codex",copilot:P};for(let[c,b]of Object.entries(A))try{let _=b.includes("/")?b:Fl("which",[b],{encoding:"utf-8"}).trim();p[c]={available:!0,path:_}}catch{p[c]={available:!1,path:null}}function f(c,b){return new Promise(_=>{let w=Ns(b,["--version"],{stdio:["ignore","ignore","ignore"]}),M=!1,k=J=>{M||(M=!0,_(J))},N=setTimeout(()=>{w.kill("SIGTERM"),k(!0)},5e3);w.on("error",()=>{clearTimeout(N),k(!1)}),w.on("close",J=>{clearTimeout(N),k(J===0)})})}await Promise.all([(async()=>{p.claude&&(p.claude.models=p.claude.available&&p.claude.path?await Is(p.claude.path).catch(()=>wo):wo)})(),(async()=>{p.codex&&(p.codex.models=p.codex.available&&p.codex.path?await ys(p.codex.path).catch(()=>jn):jn)})(),(async()=>{p.copilot&&(p.copilot.models=p.copilot.available&&p.copilot.path?await gs(p.copilot.path).catch(()=>[Mn]):[Mn])})()]);let[m,j,D]=await Promise.all([wr(r),vr(r),br(r,p.copilot?.path??P)]);p.claude&&(p.claude.mcp=m),p.codex&&(p.codex.mcp=j),p.copilot&&(p.copilot.mcp=D),m.found&&m.name&&S.push(`mcp__${m.name}__*`),await zl(d,{recursive:!0}),Us(d).catch(()=>{});let R=new bo(1),O=new mo,K=new ho(Bs),G=null,E=0,W=!1,H=()=>{E+=1,W=!1,G&&clearTimeout(G),G=null},fe=()=>{try{process.kill(process.pid,"SIGTERM")}catch{process.exit(0)}},X=()=>{if(y!=="detached"||K.size>0||W)return;W=!0;let c=++E,b=Date.now()+ip,_=()=>{if(c!==E)return;if(K.size>0){H();return}if(!(R.isRunning||R.depth>0||O.isRunning||O.depth>0)||Date.now()>=b){W=!1,G=setTimeout(fe,50),G.unref?.();return}G=setTimeout(_,250),G.unref?.()};_()},oe=new Set,x=new jo(r),C=await x.recoverInterruptedTurns();C>0&&console.warn(`[Popmelt] Recovered ${C} interrupted thread turn(s) from durable history.`);let q=new co(r);q.sweep();let B=new Ht(r),Q=new gt(r,i);try{let c=await Q.store.migrateTopology();c.migrated&&console.log(`[Popmelt] Imprint topology migrated to v2 (${c.relationMutations} relation mutation(s)).`)}catch(c){console.warn(`[Popmelt] Imprint topology migration deferred: ${c instanceof Error?c.message:String(c)}`)}let he=new Mo(r),_e=new ro(r),se=new uo(r,{claudePath:g,provider:T,timeoutMs:h,loadProjectableDecisions:c=>B.getProjectableDecisions(c),onEvent:c=>{for(let b of oe)Co(b,c)}}),De=new Gn({projectRoot:r,storeId:s.storeId,projectId:i,threadStore:x,memoryService:B,imprintService:Q,loadConcreteModel:()=>se.loadModel()});B.beginAutomaticInitialization({writerVersion:dt}).then(async c=>{c.state==="ready"?(await B.migrateImprintSnapshot(),await B.syncImprintGraph(),await se.applyCanonicalEntries(await B.getCanonicalModelEntries()),T!=="copilot"&&(await se.getUnprojectedPatternDecisions()).length>0&&await $e({provider:T,reason:"Project accepted decisions that were waiting when the bridge restarted"})):c.state==="degraded"&&console.warn(`[\u22B9 ${I}] Product memory is degraded; legacy preview remains available: ${c.error}`)});let It=20,sn=300*1e3,Ae=[];function nt(){let c=Date.now()-sn;for(;Ae.length>0&&(Ae[0].completedAt<c||Ae.length>It);)Ae.shift()}let wt=new Map;R.addListener((c,b,_)=>{for(let w of oe)(!_||!w.sourceId||w.sourceId===_)&&Co(w,c)}),O.addListener((c,b,_)=>{for(let w of oe)(!_||!w.sourceId||w.sourceId===_)&&Co(w,c)}),O.setProcessor(async c=>{let b=c.provider??T;try{let _=await se.run({provider:b,model:c.model,threadId:c.threadId,presentationJobId:c.id,agentSettings:c.agentSettings});if(c.status==="cancelled")return;let w=await se.loadRuns(),M=_.runId?w.runs.find(N=>N.id===_.runId):void 0;if(_.success&&_.proposalId){let N=await se.findModelProposal(_.proposalId),J=await se.loadModel(),F=N?zi(N,J):null;if(N&&F){let U=N.decisionIds.map(L=>({decisionId:L,status:"projected"}));await B.applyModelProjection({runId:N.runId??N.id,presentationJobId:N.presentationJobId,decisionIds:N.decisionIds,changes:F.map(L=>({path:L.path,value:L.value,decisionIds:L.decisionIds})),coverage:U}),await se.applySelectedModelProposal(N.id,F.map(L=>({path:L.path,value:L.value})),F.map(L=>({group:L.path[0]==="rules"||L.path[0]==="components"||L.path[0]==="tokens"?L.path[0]:"model",label:L.label??L.id,detail:L.rationale,path:L.path,value:L.value})),"automatic")}}let k=cp(_,M);if(c.threadId&&(await x.updateMessage(c.threadId,c.id,{role:"assistant",timestamp:Date.now(),jobId:c.id,responseText:k,model:c.model,provider:b})||await x.appendMessage(c.threadId,{role:"assistant",timestamp:Date.now(),jobId:c.id,responseText:k,model:c.model,provider:b})),_.success)c.status="done",c.result=k,O.broadcast({type:"done",jobId:c.id,success:!0,responseText:k,threadId:c.threadId},c.id,c.sourceId),Ae.push({id:c.id,status:"done",completedAt:Date.now(),threadId:c.threadId,annotationIds:c.annotationIds,color:"#000000",kind:"project_model"}),nt();else{if(c.status="error",c.error=_.error??"Projection failed",c.threadId){let N=`Model projection failed.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@popmelt.com/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "The design collaboration layer for AI coding agents",
|
|
5
5
|
"license": "PolyForm-Shield-1.0.0",
|
|
6
6
|
"author": "Popmelt <reb@popmelt.com> (https://popmelt.com)",
|
|
@@ -72,6 +72,7 @@
|
|
|
72
72
|
},
|
|
73
73
|
"./next": {
|
|
74
74
|
"source": "./src/plugins/next.ts",
|
|
75
|
+
"types": "./dist/plugin-next.d.mts",
|
|
75
76
|
"import": "./dist/plugin-next.mjs",
|
|
76
77
|
"default": "./dist/plugin-next.mjs"
|
|
77
78
|
},
|