lavish-axi 0.1.0 → 0.1.3
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/README.md
CHANGED
|
@@ -22,6 +22,10 @@
|
|
|
22
22
|
|
|
23
23
|
<h3 align="center">For when a rich editor is not rich enough.</h3>
|
|
24
24
|
|
|
25
|
+
<p align="center">
|
|
26
|
+
<img alt="Lavish Editor demo" src="lavish-editor-marketing/renders/lavish-editor-marketing.gif" width="960" />
|
|
27
|
+
</p>
|
|
28
|
+
|
|
25
29
|
HTML is the new markdown. Lavish is the new editor for your HTML artifacts.
|
|
26
30
|
|
|
27
31
|
Agents are good at producing rich HTML artifacts, but the human-agent collaboration loop on such artifacts is lacking and falls back into screenshots and long responses for “tell me what to change.”
|
|
@@ -107,6 +111,7 @@ npm link
|
|
|
107
111
|
## Development
|
|
108
112
|
|
|
109
113
|
```sh
|
|
114
|
+
npm run check # Run all verification commands
|
|
110
115
|
npm run build # Bundle the publishable CLI
|
|
111
116
|
npm test # Run node:test tests
|
|
112
117
|
npm run lint # Run ESLint
|
package/dist/cli.mjs
CHANGED
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
import { spawn } from "node:child_process";
|
|
5
5
|
import { access } from "node:fs/promises";
|
|
6
6
|
import os2 from "node:os";
|
|
7
|
-
import path4 from "node:path";
|
|
8
7
|
import { fileURLToPath } from "node:url";
|
|
9
8
|
import { AxiError, runAxiCli } from "axi-sdk-js";
|
|
10
9
|
|
|
@@ -439,6 +438,7 @@ function setPollActive(key, activePolls, events, active) {
|
|
|
439
438
|
}
|
|
440
439
|
function createChromeHtml(session) {
|
|
441
440
|
const initialChat = JSON.stringify(session.chat || []);
|
|
441
|
+
const fileInputSize = Math.max(1, session.file.length);
|
|
442
442
|
return `<!doctype html>
|
|
443
443
|
<html>
|
|
444
444
|
<head>
|
|
@@ -446,19 +446,14 @@ function createChromeHtml(session) {
|
|
|
446
446
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
447
447
|
<title>Lavish Editor</title>
|
|
448
448
|
<style>
|
|
449
|
-
|
|
450
|
-
.bar{height:
|
|
451
|
-
.
|
|
452
|
-
button{border:0;border-radius:10px;padding:9px 12px;background:#f4c95d;color:#17130a;font-weight:700;cursor:pointer}button:disabled{opacity:.55;cursor:not-allowed}
|
|
453
|
-
button.secondary{background:#2a2f3a;color:#f7f3ea}button.danger{background:#f06464;color:white}
|
|
454
|
-
.layout{height:calc(100vh - 56px);min-height:0;display:grid;grid-template-columns:1fr 360px}.frame{background:white}.panel{border-left:1px solid #2a2f3a;background:#11141a;display:flex;flex-direction:column;min-width:0;min-height:0}
|
|
455
|
-
.panel h2{font-size:15px;margin:16px 16px 8px}.chat{flex:1;min-height:0;overflow:auto;padding:0 16px 12px;display:flex;flex-direction:column;gap:10px}.bubble{border-radius:14px;padding:10px 12px;background:#1c212b;border:1px solid #303745}.bubble.user{background:#25230f;border-color:#5d4d1b}.bubble.agent{background:#172419;border-color:#315f3a}.bubble.agent-working{display:flex;align-items:center;gap:8px;color:#d8deea}.spinner{width:14px;height:14px;border-radius:999px;border:2px solid #315f3a;border-top-color:#8fe39e;animation:spin .8s linear infinite}.bubble small{display:block;color:#aeb6c6;margin-bottom:4px}@keyframes spin{to{transform:rotate(360deg)}}.composer{display:grid;gap:8px;padding:12px 16px;border-top:1px solid #2a2f3a;min-width:0;flex-shrink:0;box-sizing:border-box}.annotation-pills{display:flex;flex-wrap:wrap;gap:6px;min-width:0}.pill-wrap{position:relative;max-width:100%}.pill{display:flex;align-items:center;gap:6px;max-width:100%;border:1px solid #3c4557;border-radius:999px;background:#1c212b;color:#d8deea;padding:5px 7px 5px 9px;font-size:12px;font-weight:750}.pill-preview{display:block;max-width:220px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.pill-close{width:18px;height:18px;border:0;border-radius:999px;padding:0;background:#303745;color:#d8deea;line-height:18px;font-size:14px}.pill-tooltip{display:none;position:absolute;z-index:5;left:0;bottom:calc(100% + 8px);width:min(320px,80vw);border:1px solid #3c4557;border-radius:12px;background:#171a21;color:#d8deea;padding:10px;font-size:12px;font-weight:500;box-shadow:0 16px 44px rgba(0,0,0,.35)}.tooltip-label{color:#8c96aa;font-size:10px;font-weight:900;letter-spacing:.08em;text-transform:uppercase;margin:0 0 4px}.pill-tooltip-target{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;background:#0f1115;border:1px solid #303745;border-radius:8px;padding:6px;margin-bottom:8px;overflow-wrap:anywhere}.pill-tooltip-prompt{white-space:pre-wrap;overflow-wrap:anywhere}.pill-wrap:hover .pill-tooltip{display:block}.composer textarea{width:100%;max-width:100%;min-width:0;min-height:82px;resize:vertical;border-radius:12px;border:1px solid #303745;background:#0f1115;color:#f7f3ea;padding:10px;font:inherit;box-sizing:border-box}.actions{display:flex;gap:8px}
|
|
456
|
-
iframe{width:100%;height:100%;border:0;background:white}
|
|
449
|
+
:root{--ink-900:#0f1115;--ink-800:#11141a;--ink-700:#171a21;--ink-600:#1c212b;--steel-700:#2a2f3a;--steel-600:#303745;--steel-500:#3c4557;--steel-400:#8c96aa;--steel-300:#aeb6c6;--steel-200:#b9c0cf;--steel-100:#d8deea;--cream-50:#fffbf3;--cream-100:#f7f3ea;--cream-200:#e8e1cf;--brass-500:#f4c95d;--brass-400:#ffd877;--brass-ink:#17130a;--sage-900:#172419;--sage-700:#315f3a;--sage-300:#8fe39e;--amber-900:#25230f;--amber-700:#5d4d1b;--rust-500:#f06464;--bg:var(--ink-900);--bg-panel:var(--ink-800);--bg-bar:var(--ink-700);--bg-elevated:var(--ink-600);--fg:var(--cream-100);--fg-muted:var(--steel-100);--fg-dim:var(--steel-200);--fg-faint:var(--steel-300);--fg-label:var(--steel-400);--border:var(--steel-600);--border-subtle:var(--steel-700);--border-strong:var(--steel-500);--accent:var(--brass-500);--accent-hover:var(--brass-400);--accent-ink:var(--brass-ink);--danger:var(--rust-500);--font-serif:"EB Garamond","Iowan Old Style",Georgia,serif;--font-sans:Geist,ui-sans-serif,system-ui,-apple-system,"Segoe UI",sans-serif;--font-mono:"Geist Mono",ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;--text-xs:12px;--lh-xs:1.35;--text-sm:13px;--lh-sm:1.4;--text-base:14px;--lh-base:1.45;--text-md:16px;--lh-md:1.5;--text-lg:18px;--lh-lg:1.45;--text-xl:22px;--lh-xl:1.3;--text-2xl:28px;--lh-2xl:1.25;--text-3xl:36px;--lh-3xl:1.18;--text-4xl:48px;--lh-4xl:1.1;--text-5xl:64px;--lh-5xl:1.05;--text-display:92px;--lh-display:1;--w-regular:400;--w-medium:500;--w-semi:600;--w-bold:700;--w-brand:750;--track-tight:-.01em;--track-normal:0;--track-brand:.02em;--track-label:.08em;--track-caps:.12em;--space-1:2px;--space-2:4px;--space-3:6px;--space-4:8px;--space-5:10px;--space-6:12px;--space-8:16px;--space-10:20px;--space-12:24px;--space-16:32px;--space-20:40px;--space-24:48px;--space-32:64px;--radius-sm:8px;--radius-md:10px;--radius-lg:12px;--radius-xl:14px;--radius-pill:999px;--hairline:1px solid var(--border);--hairline-subtle:1px solid var(--border-subtle);--shadow-tooltip:0 16px 44px rgba(0,0,0,.35);--shadow-floating:0 20px 70px rgba(0,0,0,.35);--bar-h:56px;--panel-w:360px;--ease:cubic-bezier(.2,.6,.2,1);--dur-fast:120ms;--dur:180ms;--dur-slow:320ms;--annotate-outline:2px solid var(--accent);--annotate-offset:2px}
|
|
450
|
+
*{box-sizing:border-box}html,body{margin:0;width:100%;height:100%}body{background:var(--bg);color:var(--fg);font-family:var(--font-sans);font-size:var(--text-base);line-height:var(--lh-base);overflow:hidden;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}body.lavish{color-scheme:dark}:focus-visible{outline:var(--annotate-outline);outline-offset:var(--annotate-offset)}.bar{height:var(--bar-h);display:flex;align-items:center;gap:14px;padding:0 var(--space-8);background:var(--bg-bar);border-bottom:var(--hairline-subtle);box-sizing:border-box}.brand{display:flex;align-items:flex-end;height:22px;gap:8px;white-space:nowrap;flex-shrink:0}.brand-mark{font-family:var(--font-serif);font-style:italic;font-size:22px;line-height:1;color:var(--fg)}.brand-support{font-family:var(--font-sans);font-size:10px;font-weight:600;letter-spacing:.18em;text-transform:uppercase;color:var(--fg-muted);position:relative;top:1px}.divider{width:1px;height:22px;background:var(--border);flex:0 0 auto}.file-wrap{display:flex;align-items:center;height:22px;gap:8px;flex:1 1 auto;min-width:0;color:var(--fg-muted);font-family:var(--font-mono);font-size:12px}.file-input{display:block;min-width:0;width:auto;max-width:100%;border:1px solid var(--border-subtle);border-radius:var(--radius-sm);background:transparent;color:var(--fg-muted);font:inherit;font-family:var(--font-mono);font-size:12px;line-height:1;padding:4px 7px;text-overflow:ellipsis}.copy-button{border:1px solid var(--border);border-radius:var(--radius-sm);background:transparent;color:var(--fg-faint);font:inherit;font-family:var(--font-sans);font-size:11px;font-weight:600;line-height:1;padding:4px 7px;white-space:nowrap;cursor:pointer}.copy-button:hover{color:var(--fg);border-color:var(--border-strong)}.button{border:0;border-radius:var(--radius-md);padding:9px 14px;background:var(--accent);color:var(--accent-ink);font-family:inherit;font-size:var(--text-sm);font-weight:var(--w-bold);white-space:nowrap;cursor:pointer;transition:background 120ms ease-out,color 120ms ease-out,opacity 120ms ease-out,border-color 120ms ease-out}.button:hover:not(:disabled){background:var(--accent-hover)}.button:active:not(:disabled){opacity:.85}.button:disabled{opacity:.55;cursor:not-allowed}.button.secondary{background:var(--border-subtle);color:var(--fg);border:1px solid transparent;font-weight:var(--w-semi)}.button.secondary:hover:not(:disabled){background:var(--border)}.button.annotation-on{border:1px solid var(--accent)}.button.danger{background:transparent;color:var(--danger);border:1px solid var(--danger);font-weight:var(--w-semi)}.button.danger:hover:not(:disabled){background:rgba(240,100,100,.1)}.layout{height:calc(100vh - var(--bar-h));min-height:0;display:grid;grid-template-columns:minmax(0,1fr) var(--panel-w)}.frame{min-width:0;min-height:0;background:#fff}.panel{width:var(--panel-w);border-left:var(--hairline-subtle);background:var(--bg-panel);display:flex;flex-direction:column;min-width:0;min-height:0}.panel h2{font-size:15px;line-height:1.3;margin:16px 16px 8px;font-weight:var(--w-semi);letter-spacing:0}.chat{flex:1;min-height:0;overflow:auto;padding:0 16px 12px;display:flex;flex-direction:column;gap:10px}.bubble{max-width:85%;border-radius:var(--radius-xl);padding:10px 12px;background:var(--bg-elevated);border:var(--hairline);color:var(--fg)}.bubble.user{align-self:flex-end;background:var(--bg-elevated);border-color:var(--border-strong)}.bubble.agent{align-self:flex-start;background:transparent;border-color:var(--border-subtle)}.bubble.agent-working{display:flex;align-items:center;gap:8px;color:var(--fg-muted)}.spinner{width:14px;height:14px;border-radius:var(--radius-pill);border:2px solid var(--border);border-top-color:var(--accent);animation:spin .8s linear infinite;flex:0 0 auto}.bubble small{display:block;color:var(--fg-faint);margin-bottom:4px;font-size:10px;font-weight:var(--w-bold);letter-spacing:var(--track-label);text-transform:uppercase}.bubble.user small{text-align:right}@keyframes spin{to{transform:rotate(360deg)}}.composer{display:grid;gap:8px;padding:12px 16px;border-top:var(--hairline-subtle);min-width:0;flex-shrink:0;box-sizing:border-box}.annotation-pills{display:flex;flex-wrap:wrap;gap:6px;min-width:0}.pill-wrap{position:relative;max-width:100%}.pill{display:flex;align-items:center;gap:6px;max-width:100%;border:1px solid var(--border-strong);border-radius:var(--radius-pill);background:var(--bg-elevated);color:var(--fg-muted);padding:5px 7px 5px 11px;font-size:12px;font-weight:var(--w-bold)}.pill-preview{display:block;max-width:220px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.pill-close{width:18px;height:18px;border:0;border-radius:var(--radius-pill);padding:0;background:var(--border);color:var(--fg-muted);line-height:18px;font-size:14px;cursor:pointer}.pill-tooltip{display:none;position:absolute;z-index:5;left:0;bottom:calc(100% + 8px);width:min(320px,80vw);border:1px solid var(--border-strong);border-radius:var(--radius-lg);background:var(--bg-bar);color:var(--fg-muted);padding:10px;font-size:12px;font-weight:500;box-shadow:var(--shadow-tooltip)}.tooltip-label{color:var(--fg-label);font-size:10px;font-weight:900;letter-spacing:var(--track-label);text-transform:uppercase;margin:0 0 4px}.pill-tooltip-target{font-family:var(--font-mono);background:var(--bg);border:1px solid var(--border);border-radius:var(--radius-sm);padding:6px;margin-bottom:8px;overflow-wrap:anywhere}.pill-tooltip-prompt{white-space:pre-wrap;overflow-wrap:anywhere}.pill-wrap:hover .pill-tooltip,.pill-wrap:focus-within .pill-tooltip{display:block}.composer textarea{width:100%;max-width:100%;min-width:0;min-height:82px;resize:vertical;border-radius:var(--radius-lg);border:1px solid var(--border);background:var(--bg);color:var(--fg);padding:10px;font:inherit;font-family:var(--font-sans);box-sizing:border-box}.composer textarea::placeholder{color:var(--fg-label)}.actions{display:flex;gap:8px;justify-content:flex-end}.ended-view{height:calc(100vh - var(--bar-h));display:grid;place-items:center;padding:24px;background:var(--bg)}.ended-card{width:min(360px,100%);border:1px solid var(--border);border-radius:var(--radius-xl);background:var(--bg-panel);padding:20px 24px;text-align:center}.ended-title{font-family:var(--font-serif);font-style:italic;font-size:26px;line-height:1.2;color:var(--fg);margin-bottom:8px}.ended-copy{margin:0;color:var(--fg-faint);font-family:var(--font-mono);font-size:12px;line-height:1.45}iframe{width:100%;height:100%;border:0;background:white}
|
|
451
|
+
@media (max-width:860px){body{overflow:auto}.bar{min-height:var(--bar-h);height:auto;align-items:flex-start;flex-wrap:wrap;padding:10px 12px}.divider{display:none}.file-wrap{order:3;flex-basis:100%;font-size:11px}.layout{height:calc(100vh - var(--bar-h));grid-template-columns:1fr;grid-template-rows:minmax(0,1fr) min(42vh,360px)}.panel{width:100%;border-left:0;border-top:var(--hairline-subtle)}.chat{padding-bottom:10px}.pill-preview{max-width:min(220px,70vw)}}
|
|
457
452
|
</style>
|
|
458
453
|
</head>
|
|
459
|
-
<body>
|
|
460
|
-
<div class="bar"><div class="brand">Lavish Editor</div><div class="file"
|
|
461
|
-
<div class="layout"><div class="frame"><iframe id="artifact" sandbox="allow-scripts allow-forms allow-popups allow-downloads" src="/artifact/${session.key}/index.html"></iframe></div><aside class="panel"><h2>Conversation</h2><div class="chat" id="chatLog"></div><div class="composer"><div class="annotation-pills" id="annotationPills"></div><textarea id="chatInput" placeholder="Write a message for the agent..."></textarea><div class="actions"><button id="send">Send to Agent</button></div></div></aside></div>
|
|
454
|
+
<body class="lavish">
|
|
455
|
+
<div class="bar"><div class="brand"><span class="brand-mark">Lavish</span><span class="brand-support">Editor</span></div><div class="divider" aria-hidden="true"></div><div class="file-wrap" title="${escapeHtml(session.file)}"><input class="file-input" id="filePath" readonly size="${fileInputSize}" value="${escapeHtml(session.file)}"><button class="copy-button" id="copyPath" type="button">Copy Path</button></div><button class="button secondary annotation-on" id="annotation">Annotation: On</button><button class="button danger" id="end">End Session</button></div>
|
|
456
|
+
<div class="layout"><div class="frame"><iframe id="artifact" sandbox="allow-scripts allow-forms allow-popups allow-downloads" src="/artifact/${session.key}/index.html"></iframe></div><aside class="panel"><h2>Conversation</h2><div class="chat" id="chatLog"></div><div class="composer"><div class="annotation-pills" id="annotationPills"></div><textarea id="chatInput" placeholder="Write a message for the agent..."></textarea><div class="actions"><button class="button" id="send">Send to Agent</button></div></div></aside></div>
|
|
462
457
|
<script>
|
|
463
458
|
const key=${JSON.stringify(session.key)};
|
|
464
459
|
const initialChat=${initialChat};
|
|
@@ -467,6 +462,8 @@ const annotationPills=document.getElementById('annotationPills');
|
|
|
467
462
|
const chatLog=document.getElementById('chatLog');
|
|
468
463
|
const chatInput=document.getElementById('chatInput');
|
|
469
464
|
const sendButton=document.getElementById('send');
|
|
465
|
+
const filePathInput=document.getElementById('filePath');
|
|
466
|
+
const copyPathButton=document.getElementById('copyPath');
|
|
470
467
|
const queued=[];
|
|
471
468
|
let annotation=true;
|
|
472
469
|
let agentPolling=false;
|
|
@@ -480,12 +477,13 @@ function setAgentPolling(active){agentPolling=!!active;sendButton.disabled=!agen
|
|
|
480
477
|
function removeQueuedPrompt(index,event){if(event)event.stopPropagation();queued.splice(index,1);render()}
|
|
481
478
|
function postToFrame(message){frame.contentWindow&&frame.contentWindow.postMessage(message,'*')}
|
|
482
479
|
window.addEventListener('message',event=>{if(event.source!==frame.contentWindow)return;const msg=event.data||{};if(msg.type==='lavish:queuePrompt'){queued.push(msg.prompt);render()}if(msg.type==='lavish:snapshot'){pendingSnapshot=msg.snapshot||'';submitQueued()}if(msg.type==='lavish:sendQueuedPrompts'){sendQueued()}if(msg.type==='lavish:endSession'){endSession()}});
|
|
483
|
-
document.getElementById('annotation').onclick=()=>{annotation=!annotation;document.getElementById('annotation').textContent='Annotation: '+(annotation?'On':'Off');postToFrame({type:'lavish:setAnnotationMode',enabled:annotation})};
|
|
484
|
-
|
|
480
|
+
document.getElementById('annotation').onclick=()=>{annotation=!annotation;document.getElementById('annotation').textContent='Annotation: '+(annotation?'On':'Off');document.getElementById('annotation').classList.toggle('annotation-on',annotation);postToFrame({type:'lavish:setAnnotationMode',enabled:annotation})};
|
|
481
|
+
async function copyFilePath(){try{await navigator.clipboard.writeText(filePathInput.value)}catch{filePathInput.select();document.execCommand('copy')}copyPathButton.textContent='Copied';setTimeout(()=>{copyPathButton.textContent='Copy Path'},1200)}
|
|
482
|
+
sendButton.onclick=sendQueued;copyPathButton.onclick=copyFilePath;document.getElementById('end').onclick=endSession;
|
|
485
483
|
frame.addEventListener('load',()=>postToFrame({type:'lavish:setAnnotationMode',enabled:annotation}));
|
|
486
484
|
function sendQueued(){if(!agentPolling)return;const text=chatInput.value.trim();if(text){queued.push({uid:'',prompt:text,selector:'',tag:'message',text:'Freeform message'});addChat('user',text);chatInput.value='';render()}if(!queued.length)return;postToFrame({type:'lavish:requestSnapshot'})}
|
|
487
485
|
async function submitQueued(){const prompts=queued.splice(0,queued.length);render();setAgentPolling(false);await fetch('/api/'+key+'/prompts',{method:'POST',headers:{'content-type':'application/json'},body:JSON.stringify({prompts,domSnapshot:pendingSnapshot})})}
|
|
488
|
-
async function endSession(){await fetch('/api/'+key+'/end',{method:'POST'});document.body.innerHTML='<div class="bar"><div class="brand">Lavish Editor</div><div class="
|
|
486
|
+
async function endSession(){await fetch('/api/'+key+'/end',{method:'POST'});document.body.innerHTML='<div class="bar"><div class="brand"><span class="brand-mark">Lavish</span><span class="brand-support">Editor</span></div></div><main class="ended-view"><section class="ended-card"><div class="ended-title">Session ended.</div><p class="ended-copy">Return to your agent to continue.</p></section></main>'}
|
|
489
487
|
const events=new EventSource('/events/'+key);events.addEventListener('reload',()=>{frame.src=frame.src});events.addEventListener('agent-reply',event=>addChat('agent',JSON.parse(event.data).text));events.addEventListener('chat-sync',event=>syncChat(JSON.parse(event.data).chat||[]));events.addEventListener('agent-working',event=>setAgentPolling(!JSON.parse(event.data).working));render();initialChat.forEach(item=>addChat(item.role,item.text));setAgentPolling(false);
|
|
490
488
|
</script>
|
|
491
489
|
</body>
|
|
@@ -505,16 +503,16 @@ function uid(el){if(!ids.has(el))ids.set(el,String(++counter));return ids.get(el
|
|
|
505
503
|
function selector(el){if(!el||!el.tagName)return'';const parts=[];let node=el;while(node&&node.nodeType===1&&parts.length<5){let part=node.tagName.toLowerCase();if(node.id){part+='#'+CSS.escape(node.id);parts.unshift(part);break}const parent=node.parentElement;if(parent){const same=[...parent.children].filter(x=>x.tagName===node.tagName);if(same.length>1)part+=':nth-of-type('+(same.indexOf(node)+1)+')'}parts.unshift(part);node=parent}return parts.join(' > ')}
|
|
506
504
|
function context(el){return{uid:uid(el),selector:selector(el),tag:(el.tagName||'').toLowerCase(),text:(el.innerText||el.textContent||'').trim().replace(/\\s+/g,' ').slice(0,240)}}
|
|
507
505
|
function isLavishUi(el){return !!(el&&el.closest&&el.closest('[data-lavish-ui]'))}
|
|
508
|
-
function highlightElement(el){if(el){el.style.outline='2px solid #f4c95d';el.style.outlineOffset='2px'}}
|
|
506
|
+
function highlightElement(el){if(el){el.style.outline='var(--lavish-annotate-outline,2px solid #f4c95d)';el.style.outlineOffset='var(--lavish-annotate-offset,2px)'}}
|
|
509
507
|
function clearHighlight(el){if(el)el.style.outline=''}
|
|
510
|
-
function setAnnotationMode(enabled){annotationMode=!!enabled;let style=document.getElementById('lavish-cursor-style');if(annotationMode&&!style){style=document.createElement('style');style.id='lavish-cursor-style';style.textContent='*{cursor:default!important}';document.head.appendChild(style)}if(!annotationMode&&style)style.remove();if(!annotationMode)closeCard()}
|
|
508
|
+
function setAnnotationMode(enabled){annotationMode=!!enabled;let style=document.getElementById('lavish-cursor-style');if(annotationMode&&!style){style=document.createElement('style');style.id='lavish-cursor-style';style.textContent=':root{--lavish-accent:#f4c95d;--lavish-annotate-outline:2px solid var(--lavish-accent);--lavish-annotate-offset:2px}*{cursor:default!important}';document.head.appendChild(style)}if(!annotationMode&&style)style.remove();if(!annotationMode)closeCard()}
|
|
511
509
|
function queuePrompt(prompt,options={}){const item={...context(options.element||document.activeElement||document.body),prompt:String(prompt||'')};if(options.uid)item.uid=String(options.uid);if(options.selector)item.selector=String(options.selector);if(options.tag)item.tag=String(options.tag);if(options.text)item.text=String(options.text);if(options.data)item.prompt+='\\n\\nContext data:\\n'+JSON.stringify(options.data,null,2);parent.postMessage({type:'lavish:queuePrompt',prompt:item},'*')}
|
|
512
510
|
function sendQueuedPrompts(){parent.postMessage({type:'lavish:sendQueuedPrompts'},'*')}
|
|
513
511
|
function endSession(){parent.postMessage({type:'lavish:endSession'},'*')}
|
|
514
512
|
function snapshot(){const lines=[];function walk(el,depth){if(!(el instanceof Element)||depth>6||isLavishUi(el))return;const c=context(el);const name=c.text?' "'+c.text.slice(0,80).replace(/"/g,"'")+'"':'';lines.push(' '.repeat(depth)+'uid='+c.uid+' '+c.tag+name);for(const child of el.children)walk(child,depth+1)}walk(document.body,0);return lines.join('\\n')}
|
|
515
|
-
function ensureShadow(){if(shadow)return shadow;host=document.createElement('div');host.className='lavish-annotation-root';host.setAttribute('data-lavish-ui','annotation-root');document.documentElement.appendChild(host);shadow=host.attachShadow({mode:'open'});const style=document.createElement('style');style.textContent=':host{all:initial;position:fixed;z-index:2147483647;left:0;top:0;color-scheme:dark
|
|
513
|
+
function ensureShadow(){if(shadow)return shadow;host=document.createElement('div');host.className='lavish-annotation-root';host.setAttribute('data-lavish-ui','annotation-root');document.documentElement.appendChild(host);shadow=host.attachShadow({mode:'open'});const style=document.createElement('style');style.textContent=':host{all:initial;position:fixed;z-index:2147483647;left:0;top:0;color-scheme:dark;--ink-900:#0f1115;--ink-800:#11141a;--ink-700:#171a21;--ink-600:#1c212b;--steel-700:#2a2f3a;--steel-600:#303745;--steel-500:#3c4557;--steel-400:#8c96aa;--steel-300:#aeb6c6;--steel-200:#b9c0cf;--steel-100:#d8deea;--cream-50:#fffbf3;--cream-100:#f7f3ea;--cream-200:#e8e1cf;--brass-500:#f4c95d;--brass-400:#ffd877;--brass-ink:#17130a;--bg:var(--ink-900);--bg-panel:var(--ink-800);--bg-elevated:var(--ink-600);--fg:var(--cream-100);--fg-faint:var(--steel-300);--border:var(--steel-600);--accent:#f4c95d;--accent-hover:#ffd877;--font-sans:Geist,ui-sans-serif,system-ui,-apple-system,"Segoe UI",sans-serif;--font-mono:"Geist Mono",ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;--radius-md:10px;--radius-xl:14px;--shadow-floating:0 20px 70px rgba(0,0,0,.35);font-family:var(--font-sans)}*{box-sizing:border-box}:focus-visible{outline:2px solid var(--accent);outline-offset:2px}.lavish-annotation-card{position:fixed;width:min(320px,calc(100vw - 24px));padding:12px;border-radius:var(--radius-xl);background:var(--bg-panel);color:var(--fg);border:1px solid var(--accent);box-shadow:var(--shadow-floating);font:14px/1.4 var(--font-sans)}.lavish-heading{font-weight:700;margin-bottom:6px}.lavish-annotation-card textarea{width:100%;min-height:86px;resize:vertical;border-radius:var(--radius-md);border:1px solid var(--border);background:var(--bg);color:var(--fg);padding:9px;font:inherit;font-family:var(--font-sans)}.lavish-annotation-card textarea::placeholder{color:var(--fg-faint)}.lavish-annotation-card .lavish-row{display:flex;gap:8px;justify-content:flex-end;margin-top:8px}.lavish-annotation-card button{border:0;border-radius:var(--radius-md);padding:8px 10px;font-family:var(--font-sans);font-size:13px;font-weight:700;cursor:pointer}.lavish-annotation-card button:active{opacity:.85}.lavish-annotation-card .lavish-send{background:var(--accent);color:var(--brass-ink)}.lavish-annotation-card .lavish-send:hover{background:var(--accent-hover)}.lavish-annotation-card .lavish-cancel{background:var(--steel-700);color:var(--fg)}';shadow.appendChild(style);return shadow}
|
|
516
514
|
function closeCard(){if(shadow){for(const el of [...shadow.querySelectorAll('.lavish-annotation-card')])el.remove()}clearHighlight(selected);selected=null}
|
|
517
|
-
function showAnnotationCard(target){const root=ensureShadow();closeCard();selected=target;highlightElement(selected);const c=context(target);const rect=target.getBoundingClientRect();const card=document.createElement('div');card.className='lavish-annotation-card';card.innerHTML='<div
|
|
515
|
+
function showAnnotationCard(target){const root=ensureShadow();closeCard();selected=target;highlightElement(selected);const c=context(target);const rect=target.getBoundingClientRect();const card=document.createElement('div');card.className='lavish-annotation-card';card.innerHTML='<div class="lavish-heading">Annotate <'+c.tag+'></div><textarea placeholder="Tell the agent what to change about this element..."></textarea><div class="lavish-row"><button class="lavish-cancel" type="button">Cancel</button><button class="lavish-send" type="button">Queue</button></div>';root.appendChild(card);const left=Math.min(Math.max(12,rect.left),window.innerWidth-card.offsetWidth-12);const top=Math.min(Math.max(12,rect.bottom+8),window.innerHeight-card.offsetHeight-12);card.style.left=left+'px';card.style.top=top+'px';const textarea=card.querySelector('textarea');card.querySelector('.lavish-cancel').onclick=closeCard;card.querySelector('.lavish-send').onclick=()=>{const prompt=textarea.value.trim();if(prompt)queuePrompt(prompt,c);closeCard()};setTimeout(()=>textarea.focus(),0)}
|
|
518
516
|
window.lavish={queuePrompt,sendQueuedPrompts,endSession,getQueuedPrompts:()=>[],setStatus:message=>parent.postMessage({type:'lavish:status',message:String(message)},'*'),snapshot};
|
|
519
517
|
window.addEventListener('message',event=>{const msg=event.data||{};if(msg.type==='lavish:setAnnotationMode')setAnnotationMode(msg.enabled);if(msg.type==='lavish:requestSnapshot')parent.postMessage({type:'lavish:snapshot',snapshot:snapshot()},'*')});
|
|
520
518
|
document.addEventListener('mouseover',event=>{if(!annotationMode||isLavishUi(event.target))return;if(event.target===selected)return;if(hovered&&hovered!==selected)clearHighlight(hovered);hovered=event.target;highlightElement(hovered)},true);
|
|
@@ -616,9 +614,9 @@ var HttpTelemetryClient = class {
|
|
|
616
614
|
if (!trimmed) return;
|
|
617
615
|
this.send(trimmed, eventURL(this.app, trimmed), fields);
|
|
618
616
|
}
|
|
619
|
-
pageview(
|
|
617
|
+
pageview(path4, fields = {}) {
|
|
620
618
|
if (this.closed) return;
|
|
621
|
-
this.send("", normalizePagePath(
|
|
619
|
+
this.send("", normalizePagePath(path4), fields);
|
|
622
620
|
}
|
|
623
621
|
async close(timeoutMs = DEFAULT_REQUEST_TIMEOUT_MS) {
|
|
624
622
|
this.closed = true;
|
|
@@ -693,8 +691,8 @@ function eventURL(app, name) {
|
|
|
693
691
|
if (!name) return `app://${app}`;
|
|
694
692
|
return `app://${app}/${name.replace(/\./g, "/")}`;
|
|
695
693
|
}
|
|
696
|
-
function normalizePagePath(
|
|
697
|
-
const trimmed = String(
|
|
694
|
+
function normalizePagePath(path4) {
|
|
695
|
+
const trimmed = String(path4 || "").trim();
|
|
698
696
|
if (!trimmed) return "/";
|
|
699
697
|
return trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
|
|
700
698
|
}
|
|
@@ -742,11 +740,13 @@ async function run(argv) {
|
|
|
742
740
|
}
|
|
743
741
|
}
|
|
744
742
|
function collapseHomeDirectory(file, home) {
|
|
745
|
-
|
|
743
|
+
const normalizedFile = file.replaceAll("\\", "/");
|
|
744
|
+
const normalizedHome = home.replaceAll("\\", "/");
|
|
745
|
+
if (normalizedFile === normalizedHome) {
|
|
746
746
|
return "~";
|
|
747
747
|
}
|
|
748
|
-
if (
|
|
749
|
-
return
|
|
748
|
+
if (normalizedFile.startsWith(`${normalizedHome}/`)) {
|
|
749
|
+
return `~/${normalizedFile.slice(normalizedHome.length + 1)}`;
|
|
750
750
|
}
|
|
751
751
|
return file;
|
|
752
752
|
}
|
|
@@ -774,8 +774,9 @@ function createHomeOutput({ bin, sessions }) {
|
|
|
774
774
|
url: session.url,
|
|
775
775
|
pending_prompts: session.pending_prompts || 0
|
|
776
776
|
})),
|
|
777
|
-
|
|
778
|
-
"
|
|
777
|
+
example_use_cases: [
|
|
778
|
+
"Technical plans with diagrams, mockups, data flow, and code snippets",
|
|
779
|
+
"Brainstorming early ideas with recommendations, open questions, and visible tradeoffs",
|
|
779
780
|
"Design explorations with multiple visual options side by side",
|
|
780
781
|
"PR and code review explainers with annotated diffs and findings",
|
|
781
782
|
"Interactive prototypes with sliders, knobs, forms, and animation tuning",
|
|
@@ -783,6 +784,7 @@ function createHomeOutput({ bin, sessions }) {
|
|
|
783
784
|
"Custom editing interfaces for triage, config editing, prompt tuning, dataset curation, and structured config editing"
|
|
784
785
|
],
|
|
785
786
|
artifact_guidance: [
|
|
787
|
+
"Unless the user specifies another location, create HTML artifacts in the current working directory under `.lavish/`",
|
|
786
788
|
"Use clear sections, headings, tabs, cards, tables, diagrams, and spatial layout instead of long prose",
|
|
787
789
|
"Include concrete artifacts such as mockups, SVG diagrams, annotated code snippets, diffs, data-flow charts, and examples",
|
|
788
790
|
"For exploration, show multiple options side by side and label the tradeoff each option makes",
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lavish-axi",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "HTML is the new markdown. Lavish is the new editor for your HTML artifacts.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
|
-
"lavish-axi": "
|
|
7
|
+
"lavish-axi": "dist/cli.mjs"
|
|
8
8
|
},
|
|
9
9
|
"files": [
|
|
10
10
|
"dist",
|
|
11
|
+
"lavish-editor-marketing/renders/lavish-editor-marketing.gif",
|
|
11
12
|
"LICENSE",
|
|
12
13
|
"README.md"
|
|
13
14
|
],
|
|
14
15
|
"scripts": {
|
|
15
16
|
"build": "node scripts/build.js",
|
|
17
|
+
"check": "npm run build && npm run lint && npm run format:check && npm run typecheck && npm test",
|
|
16
18
|
"start": "node dist/cli.mjs",
|
|
17
19
|
"lint": "eslint bin src test scripts",
|
|
18
20
|
"format": "prettier --write .",
|
|
@@ -51,12 +53,12 @@
|
|
|
51
53
|
"license": "MIT",
|
|
52
54
|
"repository": {
|
|
53
55
|
"type": "git",
|
|
54
|
-
"url": "https://github.com/kunchenguid/lavish.git"
|
|
56
|
+
"url": "git+https://github.com/kunchenguid/lavish-axi.git"
|
|
55
57
|
},
|
|
56
58
|
"bugs": {
|
|
57
|
-
"url": "https://github.com/kunchenguid/lavish/issues"
|
|
59
|
+
"url": "https://github.com/kunchenguid/lavish-axi/issues"
|
|
58
60
|
},
|
|
59
|
-
"homepage": "https://github.com/kunchenguid/lavish#readme",
|
|
61
|
+
"homepage": "https://github.com/kunchenguid/lavish-axi#readme",
|
|
60
62
|
"publishConfig": {
|
|
61
63
|
"access": "public"
|
|
62
64
|
}
|