@codyswann/lisa 2.228.0 → 2.229.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/dist/cli/ui-cmd.d.ts +9 -1
- package/dist/cli/ui-cmd.d.ts.map +1 -1
- package/dist/cli/ui-cmd.js +142 -11
- package/dist/cli/ui-cmd.js.map +1 -1
- package/dist/cli/ui-status-json.d.ts +29 -0
- package/dist/cli/ui-status-json.d.ts.map +1 -0
- package/dist/cli/ui-status-json.js +162 -0
- package/dist/cli/ui-status-json.js.map +1 -0
- package/dist/cli/ui-status.d.ts +42 -0
- package/dist/cli/ui-status.d.ts.map +1 -0
- package/dist/cli/ui-status.js +221 -0
- package/dist/cli/ui-status.js.map +1 -0
- package/package.json +2 -1
- package/plugins/lisa/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-agy/plugin.json +1 -1
- package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-agy/plugin.json +1 -1
- package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-agy/plugin.json +1 -1
- package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-agy/plugin.json +1 -1
- package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-agy/plugin.json +1 -1
- package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-agy/plugin.json +1 -1
- package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-agy/plugin.json +1 -1
- package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-agy/plugin.json +1 -1
- package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
- package/ui/README.md +15 -0
- package/ui/index.html +156 -0
package/ui/README.md
CHANGED
|
@@ -27,6 +27,21 @@ live config it falls back to Lisa's shipped defaults:
|
|
|
27
27
|
open ui/index.html
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
+
## Live status contract
|
|
31
|
+
|
|
32
|
+
When served by `lisa ui`, the page fetches `GET /api/status` from the same
|
|
33
|
+
loopback origin and renders each probe in a compact status strip. A probe has
|
|
34
|
+
exactly one of three states: a real `value`, `unknown` with both a
|
|
35
|
+
machine-readable reason and human-readable message, or `not-applicable`.
|
|
36
|
+
Throwing and timing-out probes degrade independently to `unknown`, so one
|
|
37
|
+
unavailable integration cannot block the page or cause a value to be invented.
|
|
38
|
+
Concurrent requests share one in-flight snapshot. In-process probes must be
|
|
39
|
+
asynchronous and cooperate with the supplied abort signal; JSON depth and size
|
|
40
|
+
budgets also bound result normalization. The first reference probe scopes
|
|
41
|
+
`gh auth status --active` to the project's origin hostname; the
|
|
42
|
+
remaining live integrations are delivered by the console work that builds on
|
|
43
|
+
this transport.
|
|
44
|
+
|
|
30
45
|
## Config sync (`lisa sync`)
|
|
31
46
|
|
|
32
47
|
`lisa sync [path] [--dry-run] [--json]` makes `.lisa.config.json` (with the
|
package/ui/index.html
CHANGED
|
@@ -289,6 +289,45 @@
|
|
|
289
289
|
margin-top: 3px;
|
|
290
290
|
max-width: 26ch;
|
|
291
291
|
}
|
|
292
|
+
.live-status-panel {
|
|
293
|
+
display: flex;
|
|
294
|
+
align-items: center;
|
|
295
|
+
gap: 12px;
|
|
296
|
+
min-height: 42px;
|
|
297
|
+
padding: 7px 20px;
|
|
298
|
+
background: var(--surface2);
|
|
299
|
+
border-bottom: 1px solid var(--line);
|
|
300
|
+
}
|
|
301
|
+
.live-status-panel h2 {
|
|
302
|
+
margin: 0;
|
|
303
|
+
font-size: 12px;
|
|
304
|
+
color: var(--muted);
|
|
305
|
+
text-transform: uppercase;
|
|
306
|
+
letter-spacing: 0.06em;
|
|
307
|
+
}
|
|
308
|
+
.live-status-list {
|
|
309
|
+
display: flex;
|
|
310
|
+
align-items: center;
|
|
311
|
+
flex-wrap: wrap;
|
|
312
|
+
gap: 8px;
|
|
313
|
+
}
|
|
314
|
+
.live-status-item {
|
|
315
|
+
display: inline-flex;
|
|
316
|
+
align-items: center;
|
|
317
|
+
gap: 6px;
|
|
318
|
+
padding: 3px 9px;
|
|
319
|
+
border: 1px solid var(--line);
|
|
320
|
+
border-radius: 99px;
|
|
321
|
+
background: var(--surface);
|
|
322
|
+
font-family: var(--mono);
|
|
323
|
+
font-size: 11px;
|
|
324
|
+
}
|
|
325
|
+
.live-status-item .status-why {
|
|
326
|
+
display: inline;
|
|
327
|
+
margin: 0;
|
|
328
|
+
max-width: 48ch;
|
|
329
|
+
overflow-wrap: anywhere;
|
|
330
|
+
}
|
|
292
331
|
|
|
293
332
|
.check-item {
|
|
294
333
|
display: flex;
|
|
@@ -1203,6 +1242,18 @@
|
|
|
1203
1242
|
◐
|
|
1204
1243
|
</button>
|
|
1205
1244
|
</header>
|
|
1245
|
+
<section
|
|
1246
|
+
class="live-status-panel"
|
|
1247
|
+
aria-labelledby="liveStatusHeading"
|
|
1248
|
+
aria-live="polite"
|
|
1249
|
+
aria-atomic="true"
|
|
1250
|
+
role="status"
|
|
1251
|
+
>
|
|
1252
|
+
<h2 id="liveStatusHeading">Live status</h2>
|
|
1253
|
+
<div class="live-status-list" id="liveStatusList" role="list">
|
|
1254
|
+
<span class="live-status-item" role="listitem">Loading…</span>
|
|
1255
|
+
</div>
|
|
1256
|
+
</section>
|
|
1206
1257
|
<div class="app">
|
|
1207
1258
|
<nav class="sidebar" id="nav" aria-label="Settings sections"></nav>
|
|
1208
1259
|
<main class="main" id="main"></main>
|
|
@@ -5934,10 +5985,115 @@
|
|
|
5934
5985
|
}
|
|
5935
5986
|
}
|
|
5936
5987
|
|
|
5988
|
+
/* --- live-status hydration (same-origin GET /api/status) --- */
|
|
5989
|
+
function liveStatusValue(value) {
|
|
5990
|
+
if (typeof value === "string") return value;
|
|
5991
|
+
try {
|
|
5992
|
+
return JSON.stringify(value);
|
|
5993
|
+
} catch {
|
|
5994
|
+
return String(value);
|
|
5995
|
+
}
|
|
5996
|
+
}
|
|
5997
|
+
function normalizeLiveStatusResult(result) {
|
|
5998
|
+
if (!result || typeof result !== "object" || Array.isArray(result)) {
|
|
5999
|
+
return {
|
|
6000
|
+
state: "unknown",
|
|
6001
|
+
reason: "invalid-result",
|
|
6002
|
+
message: "Probe returned an invalid status result",
|
|
6003
|
+
};
|
|
6004
|
+
}
|
|
6005
|
+
const keys = Object.keys(result).sort().join(",");
|
|
6006
|
+
if (result.state === "value" && keys === "state,value") return result;
|
|
6007
|
+
if (result.state === "not-applicable" && keys === "state")
|
|
6008
|
+
return result;
|
|
6009
|
+
if (
|
|
6010
|
+
result.state === "unknown" &&
|
|
6011
|
+
keys === "message,reason,state" &&
|
|
6012
|
+
typeof result.reason === "string" &&
|
|
6013
|
+
result.reason.trim().length > 0 &&
|
|
6014
|
+
typeof result.message === "string" &&
|
|
6015
|
+
result.message.trim().length > 0
|
|
6016
|
+
) {
|
|
6017
|
+
return result;
|
|
6018
|
+
}
|
|
6019
|
+
return {
|
|
6020
|
+
state: "unknown",
|
|
6021
|
+
reason: "invalid-result",
|
|
6022
|
+
message: "Probe returned an invalid status result",
|
|
6023
|
+
};
|
|
6024
|
+
}
|
|
6025
|
+
function liveStatusProbeMap(snapshot) {
|
|
6026
|
+
if (
|
|
6027
|
+
!snapshot ||
|
|
6028
|
+
typeof snapshot !== "object" ||
|
|
6029
|
+
Array.isArray(snapshot) ||
|
|
6030
|
+
!Object.hasOwn(snapshot, "probes") ||
|
|
6031
|
+
!snapshot.probes ||
|
|
6032
|
+
typeof snapshot.probes !== "object" ||
|
|
6033
|
+
Array.isArray(snapshot.probes)
|
|
6034
|
+
) {
|
|
6035
|
+
throw new TypeError("Status response omitted a valid probes map");
|
|
6036
|
+
}
|
|
6037
|
+
return snapshot.probes;
|
|
6038
|
+
}
|
|
6039
|
+
function renderLiveStatuses(probes) {
|
|
6040
|
+
const list = document.getElementById("liveStatusList");
|
|
6041
|
+
list.innerHTML = "";
|
|
6042
|
+
const entries = Object.entries(probes || {});
|
|
6043
|
+
if (entries.length === 0) {
|
|
6044
|
+
const empty = el("span", "live-status-item", "No probes");
|
|
6045
|
+
empty.setAttribute("role", "listitem");
|
|
6046
|
+
list.appendChild(empty);
|
|
6047
|
+
return;
|
|
6048
|
+
}
|
|
6049
|
+
entries.forEach(([id, candidate]) => {
|
|
6050
|
+
const result = normalizeLiveStatusResult(candidate);
|
|
6051
|
+
const item = el("span", "live-status-item");
|
|
6052
|
+
item.setAttribute("role", "listitem");
|
|
6053
|
+
item.appendChild(el("b", "", esc(id)));
|
|
6054
|
+
if (result.state === "value") {
|
|
6055
|
+
item.appendChild(
|
|
6056
|
+
el("span", "badge pass", esc(liveStatusValue(result.value)))
|
|
6057
|
+
);
|
|
6058
|
+
} else if (result.state === "not-applicable") {
|
|
6059
|
+
item.appendChild(el("span", "badge default", "not applicable"));
|
|
6060
|
+
} else {
|
|
6061
|
+
item.appendChild(el("span", "badge warn", "unknown"));
|
|
6062
|
+
item.appendChild(
|
|
6063
|
+
el(
|
|
6064
|
+
"span",
|
|
6065
|
+
"status-why",
|
|
6066
|
+
esc(result.reason + ": " + result.message)
|
|
6067
|
+
)
|
|
6068
|
+
);
|
|
6069
|
+
}
|
|
6070
|
+
list.appendChild(item);
|
|
6071
|
+
});
|
|
6072
|
+
}
|
|
6073
|
+
async function hydrateLiveStatuses() {
|
|
6074
|
+
try {
|
|
6075
|
+
const response = await fetch("/api/status", {
|
|
6076
|
+
headers: { accept: "application/json" },
|
|
6077
|
+
});
|
|
6078
|
+
if (!response.ok) throw new Error("HTTP " + response.status);
|
|
6079
|
+
const snapshot = await response.json();
|
|
6080
|
+
renderLiveStatuses(liveStatusProbeMap(snapshot));
|
|
6081
|
+
} catch (error) {
|
|
6082
|
+
renderLiveStatuses({
|
|
6083
|
+
transport: {
|
|
6084
|
+
state: "unknown",
|
|
6085
|
+
reason: "status-unavailable",
|
|
6086
|
+
message: error instanceof Error ? error.message : String(error),
|
|
6087
|
+
},
|
|
6088
|
+
});
|
|
6089
|
+
}
|
|
6090
|
+
}
|
|
6091
|
+
|
|
5937
6092
|
/* --- boot (deferred so an injected live-config tag after this script is seen) --- */
|
|
5938
6093
|
function boot() {
|
|
5939
6094
|
hydrateFromLiveConfig();
|
|
5940
6095
|
renderAll();
|
|
6096
|
+
void hydrateLiveStatuses();
|
|
5941
6097
|
showSection(location.hash ? location.hash.slice(1) : "overview");
|
|
5942
6098
|
if (!document.getElementById("section-" + activeSection))
|
|
5943
6099
|
showSection("overview");
|