lavish-axi 0.1.89 → 0.1.92
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 +15 -1
- package/dist/chrome-client.js +3 -2
- package/dist/cli.mjs +15 -5
- package/package.json +1 -1
- package/plugin.json +1 -1
package/README.md
CHANGED
|
@@ -216,7 +216,8 @@ pnpm link
|
|
|
216
216
|
- **Agent presence** - The browser shows when no agent is listening, keeps queued feedback for the next successful `lavish-axi poll` send even across reloads, and keeps human feedback actions available while the agent is working because the server queues them for the next poll. An agent reply concludes delivered work and returns presence to waiting (see the CLI Reference for reply and poll commands). A supervisor-owned process listener is shown as an external listener rather than an idle captain turn.
|
|
217
217
|
- **Delivery receipts** - Every note you have sent carries three emoji under it that light up in turn: 👀 **Seen** when a `lavish-axi poll` takes the note, 🛠️ **Working** when the artifact file changes after that, and ✅ **Done** when the agent replies. A step that has not happened yet is the same emoji greyed out. All three come from what the server observes; the agent does nothing extra. Until 👀 lights, the row says why: no agent is listening, or the agent is busy and the note is delivered on its next poll. A note answered without touching the artifact goes Seen to Done with Working still grey. A reply marks every note the agent has seen as Done, not notes still waiting for a poll. Each emoji names its step and time on hover and to screen readers. Notes sent before receipts existed show no receipt row.
|
|
218
218
|
In a Herdr-managed pane, set `LAVISH_AXI_HERDR_CHIME=1` to show a Herdr request notification and play its chime once an indefinite poll enters the waiting state. Immediate queued feedback and timed debug polls do not trigger a notification. The integration is off unless both `LAVISH_AXI_HERDR_CHIME` and Herdr's `HERDR_ENV` session marker equal `1`; leaving either unset or using any other value opts out. Notification delivery runs without blocking feedback: if Herdr is unavailable, rejects the notification, stalls, or fails, the poll continues unchanged.
|
|
219
|
-
Closing the last review tab while a poll is active starts a
|
|
219
|
+
Closing the last review tab while a poll is active starts a reconnect grace period, 10 seconds by default. A reload or quick reconnect keeps an active poll waiting; if every review stays disconnected, the poll returns `browser_disconnected` without ending the resumable session, and the agent asks whether to reopen or end it instead of acting uninvited.
|
|
220
|
+
A phone that locks its screen or backgrounds the tab drops the connection too, so set `LAVISH_AXI_DISCONNECT_GRACE_MS` on the server to a longer millisecond budget, or to `0` or `off` so a disconnect never ends the poll (it then waits for feedback, an end, or its own timeout). Empty or invalid values keep the 10-second default.
|
|
220
221
|
The no-timeout poll always writes an immediate stderr banner so it is visibly not hung; it adds the periodic stderr wait ticks only in an interactive terminal, so when stderr is piped (as under agent harnesses) the captured output carries no tick noise. Stdout always stays reserved for the final response; if the poll is interrupted or times out before feedback arrives, re-run it because feedback remains queued until delivery. Poll delivery consumes the response, so read the complete response before truncating or filtering it.
|
|
221
222
|
Codex-specific guidance keeps that poll attached to the active turn instead of hiding it in a background task, because completed background tasks may not resume the agent.
|
|
222
223
|
- **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.
|
|
@@ -313,6 +314,19 @@ For flows, architecture, state, or sequence diagrams, open the diagram playbook
|
|
|
313
314
|
| `lavish-axi server` | `--verbose` | Log session and watcher events to stderr; can also be enabled with `LAVISH_AXI_DEBUG=1`. Detached server output is appended with UTC timestamps to `~/.lavish-axi/server.log` (or `LAVISH_AXI_STATE_DIR/server.log`) for startup, shutdown-cause, and crash diagnostics. |
|
|
314
315
|
| `lavish-axi server` | `--also-listen <host>` | Also listen on this concrete address (repeatable). The CLI passes it when it replaces a running server, so the replacement keeps every address the old one served; see One server per port. |
|
|
315
316
|
|
|
317
|
+
## Telemetry
|
|
318
|
+
|
|
319
|
+
The npm release sends anonymous usage telemetry to an [Umami](https://umami.is) server at `https://a.kunchenguid.com`. The host and website ID are baked into the published bundle at build time, so telemetry is on by default for `npx -y lavish-axi`.
|
|
320
|
+
|
|
321
|
+
Each `lavish-axi` run sends two requests, except `lavish-axi --version` (also `-v` and `-V`), which sends none: a page view when the command starts, and a `command` event when it finishes. Both carry:
|
|
322
|
+
|
|
323
|
+
- the command name (for example `open`, `poll`, or `home` when you run it with no command), but not its arguments, file paths, artifact content, or prompts
|
|
324
|
+
- the Lavish version, `process.platform`, and `process.arch`
|
|
325
|
+
|
|
326
|
+
The `command` event also carries a `status` field: `success`, or `error` only when the CLI itself throws. A command that fails and sets a nonzero exit code is handled by the CLI framework, so it still reports `success`. No user identifier is sent. Requests time out after 1 second, and failures are ignored, so telemetry never changes what a command does.
|
|
327
|
+
|
|
328
|
+
Set `LAVISH_AXI_TELEMETRY=0` (or `false` or `off`) to turn it off. A build from source sends nothing unless `LAVISH_AXI_UMAMI_WEBSITE_ID` is set, and `LAVISH_AXI_UMAMI_HOST` overrides the host.
|
|
329
|
+
|
|
316
330
|
## Development
|
|
317
331
|
|
|
318
332
|
```sh
|
package/dist/chrome-client.js
CHANGED
|
@@ -792,6 +792,7 @@ function replaceExpiredThumbnail(event) {
|
|
|
792
792
|
chatLog.addEventListener("error", replaceExpiredThumbnail, true);
|
|
793
793
|
|
|
794
794
|
const DEFAULT_SEND_HINT = "Write a message or annotate an element first.";
|
|
795
|
+
const EMPTY_END_HINT = "Nothing to send. To end without feedback, use End session in the More menu (⋮).";
|
|
795
796
|
|
|
796
797
|
function showSendHint(message = DEFAULT_SEND_HINT, holdMs = 2600, focusInput = true) {
|
|
797
798
|
sendHint.textContent = message;
|
|
@@ -1971,7 +1972,7 @@ function sendQueued(endAfter) {
|
|
|
1971
1972
|
const shouldEnd = Boolean(endAfter && !chipsBlocked);
|
|
1972
1973
|
const preparations = shouldEnd ? [...feedbackPreparations] : [];
|
|
1973
1974
|
if (!queued.length && preparations.length === 0) {
|
|
1974
|
-
if (!chipsBlocked && !sendFailureOwner) showSendHint();
|
|
1975
|
+
if (!chipsBlocked && !sendFailureOwner) showSendHint(endAfter ? EMPTY_END_HINT : DEFAULT_SEND_HINT);
|
|
1975
1976
|
return;
|
|
1976
1977
|
}
|
|
1977
1978
|
if (!sendFailureOwner) hideSendHint(true);
|
|
@@ -2021,7 +2022,7 @@ function completeTerminalPreparation(terminal, results) {
|
|
|
2021
2022
|
clearPreparationFailure("terminal");
|
|
2022
2023
|
if (!terminal.prompts.length) {
|
|
2023
2024
|
releaseTerminalSubmission(terminal);
|
|
2024
|
-
if (!sendFailureOwner) showSendHint();
|
|
2025
|
+
if (!sendFailureOwner) showSendHint(EMPTY_END_HINT);
|
|
2025
2026
|
return;
|
|
2026
2027
|
}
|
|
2027
2028
|
// Only make the reservation durable once every preparation has joined the exact
|
package/dist/cli.mjs
CHANGED
|
@@ -585,7 +585,7 @@ function createDesignOutput() {
|
|
|
585
585
|
playbooks: listPlaybooks()
|
|
586
586
|
},
|
|
587
587
|
design: {
|
|
588
|
-
summary: "Use this Lavish CDN fallback only if (1) the user gave no design direction and (2) you already inspected the project the artifact is about and found no design system or style conventions to match. If you have not checked the subject project yet, check first. Lavish does not auto-inject any design system; artifacts stay portable HTML. Paint an explicit page background and readable text. " + DESIGN_PRIORITY_RULE + " Paste the CDN snippet below into your `<head>`.",
|
|
588
|
+
summary: "Use this Lavish CDN fallback only if (1) the user gave no design direction and (2) you already inspected the project the artifact is about and found no design system or style conventions to match. If you have not checked the subject project yet, check first. Lavish does not auto-inject any design system; artifacts stay portable HTML. Paint an explicit page background and readable text. " + DESIGN_PRIORITY_RULE + " Lavish adds only its SDK script to your file and never wraps a fragment, so start it with `<!doctype html>`: without one the page renders in quirks mode, where `<table>` text stops inheriting the color a wrapper theme sets. Paste the CDN snippet below into your `<head>`.",
|
|
589
589
|
cdn_snippet: DESIGN_CDN_SNIPPET,
|
|
590
590
|
cdn_urls: DESIGN_CDN_URLS,
|
|
591
591
|
versions: { tailwind: TAILWIND_BROWSER_VERSION, daisyui: DAISYUI_VERSION },
|
|
@@ -10161,7 +10161,7 @@ var BIND_RECOVERY_DELAYS_MS = [1e3, 2e3, 5e3, 1e4, 3e4];
|
|
|
10161
10161
|
var LOOPBACK_OWNER_PROBE_TIMEOUT_MS = 500;
|
|
10162
10162
|
var WEBSOCKET_CLOSE_GRACE_MS = 250;
|
|
10163
10163
|
var LIVE_EVENT_HEARTBEAT_MS = 3e4;
|
|
10164
|
-
var
|
|
10164
|
+
var DEFAULT_BROWSER_DISCONNECT_GRACE_MS = 1e4;
|
|
10165
10165
|
var ARTIFACT_CONTENT_SECURITY_POLICY = "sandbox allow-scripts allow-forms allow-popups allow-popups-to-escape-sandbox allow-downloads";
|
|
10166
10166
|
var ATTACHMENT_SWEEP_INTERVAL_MS = 60 * 6e4;
|
|
10167
10167
|
var SHUTDOWN_REASONS = /* @__PURE__ */ new Set(["upgrade", "local-build", "stop"]);
|
|
@@ -10250,7 +10250,15 @@ function resolveIdleTimeoutMs(env = process.env) {
|
|
|
10250
10250
|
if (raw === "0" || raw.toLowerCase() === "off") return null;
|
|
10251
10251
|
const value = Number(raw);
|
|
10252
10252
|
if (!Number.isFinite(value) || value <= 0) return DEFAULT_IDLE_TIMEOUT_MS;
|
|
10253
|
-
return value;
|
|
10253
|
+
return Math.min(value, 2147483647);
|
|
10254
|
+
}
|
|
10255
|
+
function resolveBrowserDisconnectGraceMs(env = process.env) {
|
|
10256
|
+
const raw = env.LAVISH_AXI_DISCONNECT_GRACE_MS?.trim();
|
|
10257
|
+
if (raw === void 0 || raw === "") return DEFAULT_BROWSER_DISCONNECT_GRACE_MS;
|
|
10258
|
+
if (raw === "0" || raw.toLowerCase() === "off") return null;
|
|
10259
|
+
const value = Number(raw);
|
|
10260
|
+
if (!Number.isFinite(value) || value <= 0) return DEFAULT_BROWSER_DISCONNECT_GRACE_MS;
|
|
10261
|
+
return Math.min(value, 2147483647);
|
|
10254
10262
|
}
|
|
10255
10263
|
async function serve({
|
|
10256
10264
|
env = process.env,
|
|
@@ -10261,7 +10269,7 @@ async function serve({
|
|
|
10261
10269
|
log = null,
|
|
10262
10270
|
pollHeartbeatMs = 15e3,
|
|
10263
10271
|
liveEventHeartbeatMs = LIVE_EVENT_HEARTBEAT_MS,
|
|
10264
|
-
browserDisconnectGraceMs =
|
|
10272
|
+
browserDisconnectGraceMs = resolveBrowserDisconnectGraceMs(env),
|
|
10265
10273
|
idleTimeoutMs = resolveIdleTimeoutMs(),
|
|
10266
10274
|
host = bindHost(env),
|
|
10267
10275
|
hosts,
|
|
@@ -10353,6 +10361,7 @@ async function serve({
|
|
|
10353
10361
|
}
|
|
10354
10362
|
function scheduleBrowserDisconnect(key) {
|
|
10355
10363
|
clearBrowserDisconnectTimer(key);
|
|
10364
|
+
if (browserDisconnectGraceMs === null) return;
|
|
10356
10365
|
if (shuttingDown || hasLiveEventClient(key) || !activePolls.has(key)) return;
|
|
10357
10366
|
const timer = setTimeout(() => {
|
|
10358
10367
|
browserDisconnectTimers.delete(key);
|
|
@@ -12778,7 +12787,7 @@ var AGENT_REPLY_INPUT_LIMIT_BYTES = AGENT_REPLY_JSON_LIMIT_BYTES - AGENT_REPLY_J
|
|
|
12778
12787
|
var AGENT_REPLY_LIMIT_LABEL = "2 MB JSON request limit";
|
|
12779
12788
|
var POLL_STATE_HEADER = "lavish-poll-state";
|
|
12780
12789
|
var CODEX_POLL_WAKE_PATH_GUIDANCE = "Codex detected: completed background tasks may not resume Codex automatically, so keep the poll attached to the active turn.";
|
|
12781
|
-
var VERSION = "0.1.
|
|
12790
|
+
var VERSION = "0.1.92";
|
|
12782
12791
|
function detectInvokingAgent(env = process.env) {
|
|
12783
12792
|
return ["CODEX_SANDBOX", "CODEX_THREAD_ID"].some((key) => Object.hasOwn(env, key)) ? "codex" : "generic";
|
|
12784
12793
|
}
|
|
@@ -12945,6 +12954,7 @@ function createHomeOutput({ bin, sessions, includeSessions = true, agent = "gene
|
|
|
12945
12954
|
"Run `lavish-axi end <html-file>` to end a session as the agent - ending it this way still allows a plain reopen later. When the user ends it from the browser instead, a later `lavish-axi <html-file>` refuses to reopen it without `--reopen`",
|
|
12946
12955
|
"Run `lavish-axi export <html-file> [--out <path>]` to write a portable copy of the artifact - one HTML file with its LOCAL assets inlined - so it opens with no Lavish server and no sibling files. Remote CDN/font references are left as links, so it needs network to render those. Users can also export from the browser chrome's overflow menu",
|
|
12947
12956
|
"Run `lavish-axi share <html-file> [--private | --password <pw>]` to publish the artifact on ht-ml.app (https://ht-ml.app), a third-party hosting service not part of Lavish, and get back a visitable URL. Shares are PUBLIC by default, so anyone with the link can open them. Pass --private to publish a PRIVATE page behind a password Lavish generates and returns - hand the user that password with the URL and say it is a shared secret anyone they give it to can use; --password <pw> uses one you were already given instead. Local assets are inlined; remote refs load over the network. It also returns a secret update_key that can republish or lock the same URL later - run `lavish-axi share --help` before using it. Users can also publish from the browser chrome's overflow menu",
|
|
12957
|
+
"A request under a hostname Lavish does not answer to (a reverse-proxy name, a LAN IP) gets 403 `forbidden host`. Set `LAVISH_AXI_ALLOWED_HOSTS` in the environment that starts the server, running `lavish-axi stop` first if one is already up. See README's Allowed hosts section for the rules",
|
|
12948
12958
|
"Run `lavish-axi stop` to shut down the background server (it also self-stops when idle or after the last session ends with nothing connected)",
|
|
12949
12959
|
`Run \`lavish-axi playbook <playbook_id>\` for focused artifact guidance. ${PLAYBOOK_ROUTER_HELP}`,
|
|
12950
12960
|
DESIGN_SYSTEM_HINT,
|
package/package.json
CHANGED
package/plugin.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
|
|
3
3
|
"name": "lavish-axi",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.92",
|
|
5
5
|
"description": "HTML is the new markdown. Lavish is the new editor for your HTML artifacts.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Kun Chen",
|