lavish-axi 0.1.37 → 0.1.38
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 +2 -2
- package/dist/chrome-client.js +3 -16
- package/dist/chrome.css +16 -17
- package/dist/cli.mjs +3 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -158,12 +158,12 @@ pnpm link
|
|
|
158
158
|
For reversible choices, let option clicks update local state, then queue exactly one final answer from a per-question submit or Queue answer button with `window.lavish.queuePrompt()`.
|
|
159
159
|
Mark only custom (non-native) clickable elements with `data-lavish-action` so Lavish does not annotate them, and use `data-lavish-question` or `queueKey` when pre-send updates for the same question should replace each other.
|
|
160
160
|
Queued annotation preview pills and chat history share a scrollable Conversation panel above a sticky composer, so long feedback queues do not push the text box or send controls off screen.
|
|
161
|
-
The browser chrome keeps editing actions in the overflow menu (copy path, reload artifact, copy DOM snapshot, export standalone HTML, publish link, end session)
|
|
161
|
+
The browser chrome keeps editing actions in the overflow menu (copy path, reload artifact, copy DOM snapshot, export standalone HTML, publish link, end session), while the composer exposes **Send & End** beside **Send to Agent** to submit queued prompts and user-ended attribution together.
|
|
162
162
|
- **Keyboard shortcuts** - In the chrome composer, Enter sends queued prompts and Shift+Enter inserts a newline.
|
|
163
163
|
In the annotation card, Enter queues the annotation, Shift+Enter inserts a newline, and Ctrl+Enter (Cmd+Enter on macOS) queues it and sends all queued prompts immediately.
|
|
164
164
|
Cmd+I or Ctrl+I toggles between annotate and explore mode from either the browser chrome or the artifact iframe, including while focus is in a textarea or control.
|
|
165
165
|
- **Agent presence** - The browser shows when no agent is listening, keeps queued feedback and fresh layout warnings for the next successful `lavish-axi poll` send even across reloads, and only blocks human sends while the agent is working on delivered feedback. The no-timeout poll writes an immediate stderr banner and periodic stderr heartbeats while stdout stays reserved for the final response; if the poll is interrupted or times out, re-run it because queued feedback is never lost.
|
|
166
|
-
- **Session end etiquette** - Lavish tracks who ended a session: a human clicking **End session** (or **Send &
|
|
166
|
+
- **Session end etiquette** - Lavish tracks who ended a session: a human clicking **End session** (or **Send & End**) in the browser is a user-initiated end, while `lavish-axi end <html-file>` is agent-initiated.
|
|
167
167
|
A plain `lavish-axi <html-file>` after a user-initiated end refuses to reopen the browser and returns guidance instead; pass `--reopen` only when the user asks for further review or something important needs their visual attention.
|
|
168
168
|
Agent-initiated ends keep reopening normally, same as before.
|
|
169
169
|
`lavish-axi poll`'s `ended` response and the `feedback` response for the final batch before an end both carry `next_step` guidance telling the agent to stop polling and deliver remaining updates in chat instead of reopening.
|
package/dist/chrome-client.js
CHANGED
|
@@ -20,10 +20,6 @@ const annotationPills = /** @type {HTMLDivElement} */ (document.getElementById("
|
|
|
20
20
|
const chatLog = /** @type {HTMLDivElement} */ (document.getElementById("chatLog"));
|
|
21
21
|
const chatInput = /** @type {HTMLTextAreaElement} */ (document.getElementById("chatInput"));
|
|
22
22
|
const sendButton = /** @type {HTMLButtonElement} */ (document.getElementById("send"));
|
|
23
|
-
const sendCaret = /** @type {HTMLButtonElement} */ (document.getElementById("sendCaret"));
|
|
24
|
-
const sendActions = /** @type {HTMLDivElement} */ (document.getElementById("sendActions"));
|
|
25
|
-
const sendMenu = /** @type {HTMLDivElement} */ (document.getElementById("sendMenu"));
|
|
26
|
-
const sendFromMenuButton = /** @type {HTMLButtonElement} */ (document.getElementById("sendFromMenu"));
|
|
27
23
|
const sendAndEndButton = /** @type {HTMLButtonElement} */ (document.getElementById("sendAndEnd"));
|
|
28
24
|
const annotationSwitch = /** @type {HTMLButtonElement} */ (document.getElementById("annotation"));
|
|
29
25
|
const moreWrap = /** @type {HTMLDivElement} */ (document.getElementById("moreWrap"));
|
|
@@ -56,7 +52,7 @@ const layoutGateTitle = /** @type {HTMLDivElement} */ (document.getElementById("
|
|
|
56
52
|
const layoutGateCopy = /** @type {HTMLParagraphElement} */ (document.getElementById("layoutGateCopy"));
|
|
57
53
|
const layoutGateAction = /** @type {HTMLButtonElement} */ (document.getElementById("layoutGateAction"));
|
|
58
54
|
const layoutIssueBanner = /** @type {HTMLDivElement} */ (document.getElementById("layoutIssueBanner"));
|
|
59
|
-
const sendHint = /** @type {
|
|
55
|
+
const sendHint = /** @type {HTMLDivElement} */ (document.getElementById("sendHint"));
|
|
60
56
|
const artifactSrc = frame.dataset.artifactSrc || frame.getAttribute?.("data-artifact-src") || frame.src || "";
|
|
61
57
|
|
|
62
58
|
const queued = loadQueuedPrompts();
|
|
@@ -152,8 +148,7 @@ function render() {
|
|
|
152
148
|
|
|
153
149
|
function updateSendState() {
|
|
154
150
|
sendButton.disabled = ended || agentPresence === "working";
|
|
155
|
-
|
|
156
|
-
sendFromMenuButton.disabled = sendButton.disabled;
|
|
151
|
+
sendAndEndButton.disabled = sendButton.disabled;
|
|
157
152
|
}
|
|
158
153
|
|
|
159
154
|
function showSendHint() {
|
|
@@ -177,7 +172,6 @@ function setMenuOpen(button, menu, open) {
|
|
|
177
172
|
|
|
178
173
|
function closeMenus() {
|
|
179
174
|
setMenuOpen(moreButton, moreMenu, false);
|
|
180
|
-
setMenuOpen(sendCaret, sendMenu, false);
|
|
181
175
|
}
|
|
182
176
|
|
|
183
177
|
function toggleMenu(button, menu) {
|
|
@@ -319,11 +313,7 @@ function sendQueued(endAfter) {
|
|
|
319
313
|
render();
|
|
320
314
|
}
|
|
321
315
|
if (!queued.length) {
|
|
322
|
-
|
|
323
|
-
endSession();
|
|
324
|
-
} else {
|
|
325
|
-
showSendHint();
|
|
326
|
-
}
|
|
316
|
+
showSendHint();
|
|
327
317
|
return;
|
|
328
318
|
}
|
|
329
319
|
hideSendHint();
|
|
@@ -738,9 +728,7 @@ function toggleAnnotationMode() {
|
|
|
738
728
|
annotationSwitch.onclick = toggleAnnotationMode;
|
|
739
729
|
|
|
740
730
|
sendButton.onclick = () => sendQueued(false);
|
|
741
|
-
sendFromMenuButton.onclick = () => sendQueued(false);
|
|
742
731
|
sendAndEndButton.onclick = () => sendQueued(true);
|
|
743
|
-
sendCaret.onclick = () => toggleMenu(sendCaret, sendMenu);
|
|
744
732
|
moreButton.onclick = () => toggleMenu(moreButton, moreMenu);
|
|
745
733
|
chatInput.addEventListener("keydown", (event) => {
|
|
746
734
|
if (event.key === "Enter" && !event.shiftKey && !event.isComposing) {
|
|
@@ -769,7 +757,6 @@ endButton.onclick = () => {
|
|
|
769
757
|
document.addEventListener("mousedown", (event) => {
|
|
770
758
|
const target = /** @type {Node} */ (event.target);
|
|
771
759
|
if (!moreMenu.hidden && !moreWrap.contains(target)) setMenuOpen(moreButton, moreMenu, false);
|
|
772
|
-
if (!sendMenu.hidden && !sendActions.contains(target)) setMenuOpen(sendCaret, sendMenu, false);
|
|
773
760
|
});
|
|
774
761
|
document.addEventListener("keydown", (event) => {
|
|
775
762
|
if (event.key === "Escape") {
|
package/dist/chrome.css
CHANGED
|
@@ -404,25 +404,18 @@ body.lavish {
|
|
|
404
404
|
opacity: 0.55;
|
|
405
405
|
cursor: not-allowed;
|
|
406
406
|
}
|
|
407
|
-
.
|
|
407
|
+
.button-danger {
|
|
408
408
|
display: inline-flex;
|
|
409
|
-
align-items:
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
409
|
+
align-items: center;
|
|
410
|
+
gap: 8px;
|
|
411
|
+
background: transparent;
|
|
412
|
+
color: var(--danger);
|
|
413
413
|
}
|
|
414
|
-
.
|
|
415
|
-
|
|
416
|
-
padding: 9px;
|
|
417
|
-
border-left: 1px solid rgba(23, 19, 10, 0.22);
|
|
418
|
-
display: grid;
|
|
419
|
-
place-items: center;
|
|
414
|
+
.button-danger:hover:not(:disabled) {
|
|
415
|
+
background: rgba(240, 100, 100, 0.1);
|
|
420
416
|
}
|
|
421
|
-
.
|
|
422
|
-
|
|
423
|
-
bottom: 44px;
|
|
424
|
-
width: 208px;
|
|
425
|
-
border-radius: 11px;
|
|
417
|
+
.button-danger > svg {
|
|
418
|
+
flex-shrink: 0;
|
|
426
419
|
}
|
|
427
420
|
.share-overlay {
|
|
428
421
|
position: fixed;
|
|
@@ -852,10 +845,10 @@ body.lavish {
|
|
|
852
845
|
align-items: center;
|
|
853
846
|
gap: 8px;
|
|
854
847
|
justify-content: flex-end;
|
|
848
|
+
min-width: 0;
|
|
855
849
|
position: relative;
|
|
856
850
|
}
|
|
857
851
|
.send-hint {
|
|
858
|
-
margin-right: auto;
|
|
859
852
|
color: var(--fg-faint);
|
|
860
853
|
font-size: 11px;
|
|
861
854
|
line-height: 1.35;
|
|
@@ -863,6 +856,12 @@ body.lavish {
|
|
|
863
856
|
.send-hint[hidden] {
|
|
864
857
|
display: none;
|
|
865
858
|
}
|
|
859
|
+
@media (max-width: 320px) {
|
|
860
|
+
.composer {
|
|
861
|
+
padding-left: 12px;
|
|
862
|
+
padding-right: 12px;
|
|
863
|
+
}
|
|
864
|
+
}
|
|
866
865
|
.ended-overlay {
|
|
867
866
|
position: fixed;
|
|
868
867
|
inset: var(--bar-h) 0 0 0;
|
package/dist/cli.mjs
CHANGED
|
@@ -6108,9 +6108,7 @@ var chromeIcons = {
|
|
|
6108
6108
|
exit: chromeIcon(
|
|
6109
6109
|
'<path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/><polyline points="16 17 21 12 16 7"/><line x1="21" y1="12" x2="9" y2="12"/>',
|
|
6110
6110
|
15
|
|
6111
|
-
)
|
|
6112
|
-
send: chromeIcon('<path d="M22 2 11 13"/><path d="M22 2 15 22l-4-9-9-4Z"/>', 14),
|
|
6113
|
-
caret: chromeIcon('<path d="m6 9 6 6 6-6"/>', 13, 2)
|
|
6111
|
+
)
|
|
6114
6112
|
};
|
|
6115
6113
|
function displayPathParts(file, home = homedir()) {
|
|
6116
6114
|
const normalizedFile = file.replaceAll("\\", "/");
|
|
@@ -6200,7 +6198,7 @@ ${faviconTag}
|
|
|
6200
6198
|
</head>
|
|
6201
6199
|
<body class="${bodyClass}">
|
|
6202
6200
|
<div class="bar"><div class="brand"><span class="brand-mark">Lavish</span><span class="brand-support">Editor</span></div><div class="spacer" aria-hidden="true"></div><button class="annotate-switch" id="annotation" type="button" aria-pressed="true" title="${escapeHtml(modeToggleHint)}"><span class="switch-track" aria-hidden="true"><span class="switch-knob"></span></span><span>Annotate</span></button><div class="more-wrap" id="moreWrap"><button class="more-button" id="moreButton" type="button" title="More" aria-haspopup="menu" aria-expanded="false">${chromeIcons.more}</button><div class="menu more-menu" id="moreMenu" hidden><div class="menu-head"><div class="menu-label">Editing</div><button class="menu-file" id="copyPath" type="button" title="Copy path \xB7 ${escapeHtml(session.file)}">${chromeIcons.file}<span class="menu-file-text"><span class="path-head">${escapeHtml(pathHead)}</span><span class="path-tail">${escapeHtml(pathTail)}</span></span><span class="copy-hint" id="copyHint"><span class="icon-copy">${chromeIcons.copy}</span><span class="icon-check">${chromeIcons.check}</span><span id="copyHintText">Copy</span></span></button></div><div class="menu-rule"></div><button class="menu-item" id="reloadArtifact" type="button">${chromeIcons.refresh}<span>Reload artifact</span></button><button class="menu-item" id="copySnapshot" type="button">${chromeIcons.camera}<span>Copy DOM snapshot</span></button><button class="menu-item" id="exportArtifact" type="button">${chromeIcons.download}<span>Export standalone HTML</span></button><button class="menu-item" id="shareArtifact" type="button">${chromeIcons.globe}<span>Publish link</span></button><div class="menu-rule"></div><button class="menu-item danger" id="end" type="button">${chromeIcons.exit}<span>End session</span></button></div></div></div>
|
|
6203
|
-
<div class="layout"><div class="frame"><iframe id="artifact" sandbox="allow-scripts allow-forms allow-popups allow-downloads" data-artifact-src="/artifact/${session.key}/index.html"></iframe><div class="layout-issue-banner" id="layoutIssueBanner" hidden>This surface may have layout issues. Your agent has been notified.</div></div><aside class="panel"><h2>Conversation</h2><div class="panel-scroll" id="panelScroll"><div class="chat" id="chatLog"></div><div class="annotation-pills" id="annotationPills"></div></div><div class="composer"><div class="presence-banner" id="presenceBanner" hidden>Your agent is not listening. If this persists, ask your agent to poll for updates from Lavish.</div><textarea id="chatInput" placeholder="Write a message for the agent..."></textarea><div class="
|
|
6201
|
+
<div class="layout"><div class="frame"><iframe id="artifact" sandbox="allow-scripts allow-forms allow-popups allow-downloads" data-artifact-src="/artifact/${session.key}/index.html"></iframe><div class="layout-issue-banner" id="layoutIssueBanner" hidden>This surface may have layout issues. Your agent has been notified.</div></div><aside class="panel"><h2>Conversation</h2><div class="panel-scroll" id="panelScroll"><div class="chat" id="chatLog"></div><div class="annotation-pills" id="annotationPills"></div></div><div class="composer"><div class="presence-banner" id="presenceBanner" hidden>Your agent is not listening. If this persists, ask your agent to poll for updates from Lavish.</div><textarea id="chatInput" placeholder="Write a message for the agent..."></textarea><div class="send-hint" id="sendHint" hidden>Write a message or annotate an element first.</div><div class="actions" id="sendActions"><button class="button button-danger" id="sendAndEnd" type="button">${chromeIcons.exit}<span>Send & End</span></button><button class="button" id="send">Send to Agent</button></div></div></aside></div>
|
|
6204
6202
|
<div class="share-overlay" id="shareDialog" role="dialog" aria-modal="true" aria-labelledby="shareTitleText" hidden><form class="share-card" id="shareForm"><div class="share-head"><div><div class="share-kicker">Publish to <a class="share-link" href="https://ht-ml.app" target="_blank" rel="noopener noreferrer">ht-ml.app</a></div><h2 id="shareTitleText">Publish artifact</h2></div><button class="share-close" id="shareClose" type="button" aria-label="Close publish dialog"><svg width="14" height="14" viewBox="0 0 10 10" fill="none" aria-hidden="true" focusable="false"><path d="M1 1L9 9M9 1L1 9" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/></svg></button></div><p class="share-note">ht-ml.app is a separate, third-party hosting service, not part of Lavish. Publishing sends this artifact to its servers.</p><p class="share-copy">This uploads this artifact to ht-ml.app with local assets inlined. Without a password, the page is PUBLIC and anyone with the link can open it. With a password, the page is PRIVATE and viewers must supply the password to view.</p><p class="share-note">Do not publish secrets. The Lavish annotation SDK is not included.</p><div class="share-grid"><label>Password (optional)<input id="sharePassword" name="password" type="password" autocomplete="new-password" placeholder="Leave blank for a public page"></label></div><div class="share-status" id="shareStatus" role="status"></div><div class="share-result" id="shareResult" hidden><label>Share URL<div class="share-copy-row"><input id="shareUrl" readonly><button class="share-copy-btn" id="copyShareUrl" type="button">Copy URL</button></div></label><label>Update key (secret)<div class="share-copy-row"><input id="shareUpdateKey" readonly><button class="share-copy-btn" id="copyUpdateKey" type="button">Copy key</button></div></label><p class="share-note">Keep the update key private. ht-ml.app returns it once and it is the only way to update or delete this page later.</p></div><div class="share-actions"><button class="share-cancel" id="shareCancel" type="button">Cancel</button><button class="button" id="sharePublish" type="submit">Publish</button></div></form></div>
|
|
6205
6203
|
<div class="ended-overlay layout-gate-overlay" id="layoutGateOverlay"${layoutGateHidden}><div class="ended-card"><div class="ended-title" id="layoutGateTitle">Checking layout.<br>One moment.</div><p class="ended-copy" id="layoutGateCopy">Lavish is waiting for fonts and final geometry before revealing this artifact.</p><button class="button ended-action" id="layoutGateAction" type="button">Show anyway</button></div></div>
|
|
6206
6204
|
<div class="ended-overlay" id="endedOverlay" hidden><div class="ended-card"><div class="ended-title">Session ended.<br>Return to your agent to continue.</div><p class="ended-copy">${escapeHtml(session.file)}</p></div></div>
|
|
@@ -6412,7 +6410,7 @@ function normalizePagePath(path6) {
|
|
|
6412
6410
|
var COMMANDS = /* @__PURE__ */ new Set(["open", "poll", "end", "stop", "server", "playbook", "design", "setup", "export", "share"]);
|
|
6413
6411
|
var RESERVED = new Set(RESERVED_COMMANDS);
|
|
6414
6412
|
var DESCRIPTION = "Lavish Editor helps agents turn rich HTML artifacts into collaborative human review surfaces. Whenever you are about to give user a complex response that will be easier to understand via a rich / interactive page, consider using Lavish Editor. First generate an interactive HTML artifact according to user request, then run `lavish-axi <html-file>` so the user can visually review it, annotate elements or selected text, queue prompts, and send feedback back through `lavish-axi poll`.";
|
|
6415
|
-
var VERSION = "0.1.
|
|
6413
|
+
var VERSION = "0.1.38";
|
|
6416
6414
|
async function run(argv) {
|
|
6417
6415
|
await ensureStateDir();
|
|
6418
6416
|
const normalizedArgv = normalizeArgv(argv);
|