cicy-desktop 2.1.69 → 2.1.71
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/package.json +7 -7
- package/src/backends/homepage-react/assets/index-BpljolQs.js +365 -0
- package/src/backends/homepage-react/assets/{index-BniEbx_j.css → index-C9AZlTew.css} +1 -1
- package/src/backends/homepage-react/index.html +2 -2
- package/src/backends/local-teams.js +42 -4
- package/src/backends/sidecar-ipc.js +23 -1
- package/src/i18n/locales/en.json +9 -7
- package/src/i18n/locales/zh-CN.json +9 -7
- package/src/sidecar/cicy-code.js +54 -111
- package/src/sidecar/localbin.js +133 -0
- package/src/sidecar/native.js +4 -2
- package/src/sidecar/runtime.js +7 -3
- package/workers/render/src/App.css +156 -10
- package/workers/render/src/App.jsx +254 -39
- package/.env.dev +0 -7
- package/src/backends/homepage-react/assets/index-B8gGhz8B.js +0 -365
- package/workers/render.bak.20260528-2338/DESIGN_v2.md +0 -254
- package/workers/render.bak.20260528-2338/index.html +0 -12
- package/workers/render.bak.20260528-2338/package-lock.json +0 -827
- package/workers/render.bak.20260528-2338/package.json +0 -19
- package/workers/render.bak.20260528-2338/public/_headers +0 -5
- package/workers/render.bak.20260528-2338/public/manifest.json +0 -6
- package/workers/render.bak.20260528-2338/src/App.css +0 -224
- package/workers/render.bak.20260528-2338/src/App.jsx +0 -1028
- package/workers/render.bak.20260528-2338/src/api.js +0 -285
- package/workers/render.bak.20260528-2338/src/cicycode-ops.js +0 -222
- package/workers/render.bak.20260528-2338/src/components/BackendCard.css +0 -299
- package/workers/render.bak.20260528-2338/src/components/BackendCard.jsx +0 -133
- package/workers/render.bak.20260528-2338/src/components/BackendModal.css +0 -161
- package/workers/render.bak.20260528-2338/src/components/BackendModal.jsx +0 -199
- package/workers/render.bak.20260528-2338/src/components/Button.css +0 -72
- package/workers/render.bak.20260528-2338/src/components/Button.jsx +0 -37
- package/workers/render.bak.20260528-2338/src/components/Card.css +0 -42
- package/workers/render.bak.20260528-2338/src/components/Card.jsx +0 -21
- package/workers/render.bak.20260528-2338/src/components/Icon.jsx +0 -30
- package/workers/render.bak.20260528-2338/src/components/Menu.css +0 -55
- package/workers/render.bak.20260528-2338/src/components/Menu.jsx +0 -91
- package/workers/render.bak.20260528-2338/src/components/SidecarBanner.css +0 -79
- package/workers/render.bak.20260528-2338/src/components/SidecarBanner.jsx +0 -84
- package/workers/render.bak.20260528-2338/src/components/StatusChip.css +0 -19
- package/workers/render.bak.20260528-2338/src/components/StatusChip.jsx +0 -31
- package/workers/render.bak.20260528-2338/src/components/Toast.css +0 -31
- package/workers/render.bak.20260528-2338/src/components/Toast.jsx +0 -23
- package/workers/render.bak.20260528-2338/src/components/WslSetupBanner.css +0 -464
- package/workers/render.bak.20260528-2338/src/components/WslSetupBanner.jsx +0 -716
- package/workers/render.bak.20260528-2338/src/dockerInstaller.js +0 -0
- package/workers/render.bak.20260528-2338/src/i18n/en.json +0 -116
- package/workers/render.bak.20260528-2338/src/i18n/fr.json +0 -116
- package/workers/render.bak.20260528-2338/src/i18n/index.js +0 -69
- package/workers/render.bak.20260528-2338/src/i18n/ja.json +0 -116
- package/workers/render.bak.20260528-2338/src/i18n/zh-CN.json +0 -121
- package/workers/render.bak.20260528-2338/src/main.js +0 -475
- package/workers/render.bak.20260528-2338/src/main.jsx +0 -18
- package/workers/render.bak.20260528-2338/src/style.css +0 -275
- package/workers/render.bak.20260528-2338/src/styles/base.css +0 -98
- package/workers/render.bak.20260528-2338/src/styles/tokens.css +0 -90
- package/workers/render.bak.20260528-2338/src/tos.js +0 -72
- package/workers/render.bak.20260528-2338/src/worker.js +0 -40
- package/workers/render.bak.20260528-2338/src/wslInstaller.js +0 -1563
- package/workers/render.bak.20260528-2338/vite.config.js +0 -36
- package/workers/render.bak.20260528-2338/wrangler.toml +0 -17
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import Button from "./Button.jsx";
|
|
2
|
-
import Icon from "./Icon.jsx";
|
|
3
|
-
import "./SidecarBanner.css";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* <SidecarBanner state="..." info={...} progress={...} onInstall onCancel />
|
|
7
|
-
*
|
|
8
|
-
* Full-width banner shown when:
|
|
9
|
-
* missing — cicy-code not installed yet (first-run blocker)
|
|
10
|
-
* installing — install / upgrade in progress
|
|
11
|
-
* error — last install attempt failed
|
|
12
|
-
*
|
|
13
|
-
* In other states (uptodate, outdated, checking) the banner is null;
|
|
14
|
-
* "outdated" surfaces inside the BackendCard's menu instead.
|
|
15
|
-
*/
|
|
16
|
-
export default function SidecarBanner({ state, info, progress, error, onInstall, onCancel }) {
|
|
17
|
-
if (state !== "missing" && state !== "installing" && state !== "error") return null;
|
|
18
|
-
|
|
19
|
-
const isInstalling = state === "installing";
|
|
20
|
-
const isError = state === "error";
|
|
21
|
-
|
|
22
|
-
let title, subtitle, actions;
|
|
23
|
-
|
|
24
|
-
if (state === "missing") {
|
|
25
|
-
title = "Install cicy-code to get started";
|
|
26
|
-
subtitle = info?.latest
|
|
27
|
-
? `Latest v${info.latest} · ${info.network === "cn" ? "China mirror" : "GitHub direct"}`
|
|
28
|
-
: "Required for the local engine";
|
|
29
|
-
actions = <Button variant="primary" icon={<Icon name="download" />} onClick={onInstall}>Install</Button>;
|
|
30
|
-
} else if (isInstalling) {
|
|
31
|
-
const p = progress || {};
|
|
32
|
-
title = p.message || "Installing…";
|
|
33
|
-
const pct = typeof p.progress === "number" ? Math.round(p.progress * 100) : null;
|
|
34
|
-
subtitle = p.phase === "downloading" && p.total
|
|
35
|
-
? `${formatBytes(p.received)} / ${formatBytes(p.total)}${p.version ? ` · v${p.version}` : ""}`
|
|
36
|
-
: (p.version ? `v${p.version}` : p.phase || "");
|
|
37
|
-
actions = <Button variant="ghost" onClick={onCancel}>Cancel</Button>;
|
|
38
|
-
return (
|
|
39
|
-
<div className="sidecar-banner is-installing">
|
|
40
|
-
<div className="sidecar-banner__head">
|
|
41
|
-
<div className="sidecar-banner__icon"><Icon name="download" size={18} /></div>
|
|
42
|
-
<div className="sidecar-banner__text">
|
|
43
|
-
<div className="sidecar-banner__title">{title}</div>
|
|
44
|
-
<div className="sidecar-banner__subtitle">{subtitle}</div>
|
|
45
|
-
</div>
|
|
46
|
-
<div className="sidecar-banner__actions">{actions}</div>
|
|
47
|
-
</div>
|
|
48
|
-
<div className={`sidecar-banner__bar ${pct == null ? "is-indeterminate" : ""}`}>
|
|
49
|
-
<div className="sidecar-banner__bar-fill" style={{ width: pct == null ? "30%" : `${pct}%` }} />
|
|
50
|
-
</div>
|
|
51
|
-
<div className="sidecar-banner__bar-meta">
|
|
52
|
-
<span>{p.phase || ""}</span>
|
|
53
|
-
<span>{pct == null ? "" : `${pct}%`}</span>
|
|
54
|
-
</div>
|
|
55
|
-
</div>
|
|
56
|
-
);
|
|
57
|
-
} else if (isError) {
|
|
58
|
-
title = "Install failed";
|
|
59
|
-
subtitle = error || "Unknown error";
|
|
60
|
-
actions = <Button variant="primary" onClick={onInstall}>Retry</Button>;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
return (
|
|
64
|
-
<div className={`sidecar-banner ${isError ? "is-error" : ""}`}>
|
|
65
|
-
<div className="sidecar-banner__head">
|
|
66
|
-
<div className="sidecar-banner__icon">
|
|
67
|
-
<Icon name={isError ? "warn" : "download"} size={18} />
|
|
68
|
-
</div>
|
|
69
|
-
<div className="sidecar-banner__text">
|
|
70
|
-
<div className="sidecar-banner__title">{title}</div>
|
|
71
|
-
<div className="sidecar-banner__subtitle">{subtitle}</div>
|
|
72
|
-
</div>
|
|
73
|
-
<div className="sidecar-banner__actions">{actions}</div>
|
|
74
|
-
</div>
|
|
75
|
-
</div>
|
|
76
|
-
);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
function formatBytes(n) {
|
|
80
|
-
if (n == null) return "?";
|
|
81
|
-
if (n < 1024) return `${n} B`;
|
|
82
|
-
if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`;
|
|
83
|
-
return `${(n / (1024 * 1024)).toFixed(1)} MB`;
|
|
84
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
.status-chip {
|
|
2
|
-
display: inline-flex;
|
|
3
|
-
align-items: center;
|
|
4
|
-
gap: var(--sp-2);
|
|
5
|
-
padding: 2px 10px;
|
|
6
|
-
border-radius: var(--r-pill);
|
|
7
|
-
font-size: var(--t-xs);
|
|
8
|
-
font-weight: 500;
|
|
9
|
-
white-space: nowrap;
|
|
10
|
-
}
|
|
11
|
-
.status-chip__dot {
|
|
12
|
-
width: 6px; height: 6px;
|
|
13
|
-
border-radius: 50%;
|
|
14
|
-
background: currentColor;
|
|
15
|
-
flex-shrink: 0;
|
|
16
|
-
}
|
|
17
|
-
.status-chip--up .status-chip__dot {
|
|
18
|
-
box-shadow: 0 0 0 3px rgba(74,222,128,0.18);
|
|
19
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import "./StatusChip.css";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* <StatusChip kind="up|warn|down|unknown" label="..." />
|
|
5
|
-
*
|
|
6
|
-
* The single source of truth for backend status presentation.
|
|
7
|
-
* Avoids the row's previous "dot + colored text + icon" triple-redundancy.
|
|
8
|
-
*/
|
|
9
|
-
const COLORS = {
|
|
10
|
-
up: { bg: "var(--success-soft)", fg: "var(--success)", label: "Online" },
|
|
11
|
-
warn: { bg: "var(--warn-soft)", fg: "var(--warn)", label: "Degraded" },
|
|
12
|
-
down: { bg: "var(--danger-soft)", fg: "var(--danger)", label: "Offline" },
|
|
13
|
-
unknown: { bg: "var(--bg-elev-2)", fg: "var(--fg-3)", label: "—" },
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
export default function StatusChip({ kind = "unknown", label }) {
|
|
17
|
-
const c = COLORS[kind] || COLORS.unknown;
|
|
18
|
-
return (
|
|
19
|
-
<span className={`status-chip status-chip--${kind}`} style={{ background: c.bg, color: c.fg }}>
|
|
20
|
-
<span className="status-chip__dot" />
|
|
21
|
-
{label || c.label}
|
|
22
|
-
</span>
|
|
23
|
-
);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export function dotKind(health) {
|
|
27
|
-
if (!health) return "unknown";
|
|
28
|
-
if (health.ok && health.status === "ok") return "up";
|
|
29
|
-
if (health.ok) return "warn";
|
|
30
|
-
return "down";
|
|
31
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
.toast-stack {
|
|
2
|
-
position: fixed;
|
|
3
|
-
left: 50%;
|
|
4
|
-
bottom: var(--sp-5);
|
|
5
|
-
transform: translateX(-50%);
|
|
6
|
-
display: flex;
|
|
7
|
-
flex-direction: column;
|
|
8
|
-
gap: var(--sp-2);
|
|
9
|
-
z-index: 2000;
|
|
10
|
-
pointer-events: none;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
.toast {
|
|
14
|
-
background: var(--bg-elev-2);
|
|
15
|
-
color: var(--fg);
|
|
16
|
-
border: 1px solid var(--hairline-2);
|
|
17
|
-
padding: var(--sp-3) var(--sp-4);
|
|
18
|
-
border-radius: var(--r-pill);
|
|
19
|
-
font-size: var(--t-sm);
|
|
20
|
-
box-shadow: var(--shadow-2);
|
|
21
|
-
animation: toast-in var(--dur-base) var(--ease);
|
|
22
|
-
max-width: 90vw;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
.toast--error { border-color: var(--danger); color: var(--danger); }
|
|
26
|
-
.toast--success { border-color: var(--success); color: var(--success); }
|
|
27
|
-
|
|
28
|
-
@keyframes toast-in {
|
|
29
|
-
from { opacity: 0; transform: translateY(8px); }
|
|
30
|
-
to { opacity: 1; transform: translateY(0); }
|
|
31
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { useEffect, useState } from "react";
|
|
2
|
-
import "./Toast.css";
|
|
3
|
-
|
|
4
|
-
let pushImpl = () => {};
|
|
5
|
-
export function pushToast(msg, kind = "info") { pushImpl({ msg, kind, id: Date.now() + Math.random() }); }
|
|
6
|
-
|
|
7
|
-
export default function Toast() {
|
|
8
|
-
const [items, setItems] = useState([]);
|
|
9
|
-
useEffect(() => {
|
|
10
|
-
pushImpl = (it) => {
|
|
11
|
-
setItems((prev) => [...prev, it]);
|
|
12
|
-
setTimeout(() => setItems((prev) => prev.filter((x) => x.id !== it.id)), 2400);
|
|
13
|
-
};
|
|
14
|
-
return () => { pushImpl = () => {}; };
|
|
15
|
-
}, []);
|
|
16
|
-
return (
|
|
17
|
-
<div className="toast-stack">
|
|
18
|
-
{items.map((it) => (
|
|
19
|
-
<div key={it.id} className={`toast toast--${it.kind}`}>{it.msg}</div>
|
|
20
|
-
))}
|
|
21
|
-
</div>
|
|
22
|
-
);
|
|
23
|
-
}
|
|
@@ -1,464 +0,0 @@
|
|
|
1
|
-
/* ── WSL setup drawer — right-side slide-out ─────────────────────────
|
|
2
|
-
The drawer floats over the main app content so the cards stay visible
|
|
3
|
-
underneath. We keep all the `.wsl-banner__*` class names internally
|
|
4
|
-
(banner → drawer was a UX rename, not a structural rewrite) so the
|
|
5
|
-
JSX didn't need to be touched. Backdrop is intentionally near-zero
|
|
6
|
-
opacity — the install can take 10+ min and we don't want the user
|
|
7
|
-
feeling locked out of the rest of the app. */
|
|
8
|
-
|
|
9
|
-
/* Subtle tint behind the drawer — pointer-events:none so users can still
|
|
10
|
-
click backend cards / tabs underneath. Pure visual cue that the drawer
|
|
11
|
-
is the focused area without actually trapping interaction. */
|
|
12
|
-
.wsl-drawer-backdrop {
|
|
13
|
-
position: fixed;
|
|
14
|
-
inset: 0;
|
|
15
|
-
background: linear-gradient(to right, transparent 0%, transparent 40%, rgba(0, 0, 0, 0.10) 100%);
|
|
16
|
-
pointer-events: none;
|
|
17
|
-
z-index: 90;
|
|
18
|
-
animation: drawer-backdrop-in var(--dur-base) var(--ease);
|
|
19
|
-
}
|
|
20
|
-
@keyframes drawer-backdrop-in {
|
|
21
|
-
from { opacity: 0; }
|
|
22
|
-
to { opacity: 1; }
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
.wsl-banner {
|
|
26
|
-
position: fixed;
|
|
27
|
-
top: 0;
|
|
28
|
-
right: 0;
|
|
29
|
-
height: 100vh;
|
|
30
|
-
width: min(560px, 100vw);
|
|
31
|
-
z-index: 100;
|
|
32
|
-
background: var(--bg-elev-1);
|
|
33
|
-
border-left: 1px solid var(--hairline);
|
|
34
|
-
box-shadow: -8px 0 24px rgba(0, 0, 0, 0.18);
|
|
35
|
-
padding: var(--sp-4);
|
|
36
|
-
display: flex;
|
|
37
|
-
flex-direction: column;
|
|
38
|
-
gap: var(--sp-3);
|
|
39
|
-
overflow: hidden; /* let inner sections scroll, log fills bottom */
|
|
40
|
-
scrollbar-width: thin;
|
|
41
|
-
animation: drawer-in 280ms cubic-bezier(0.16, 1, 0.3, 1);
|
|
42
|
-
}
|
|
43
|
-
@keyframes drawer-in {
|
|
44
|
-
from { transform: translateX(100%); }
|
|
45
|
-
to { transform: translateX(0); }
|
|
46
|
-
}
|
|
47
|
-
.wsl-banner.is-error {
|
|
48
|
-
border-left: 3px solid var(--danger);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
.wsl-banner__head {
|
|
52
|
-
display: flex;
|
|
53
|
-
align-items: flex-start;
|
|
54
|
-
gap: var(--sp-3);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
.wsl-banner__icon {
|
|
58
|
-
width: 36px; height: 36px;
|
|
59
|
-
display: grid; place-items: center;
|
|
60
|
-
background: var(--warn-soft);
|
|
61
|
-
color: var(--warn);
|
|
62
|
-
border-radius: var(--r-sm);
|
|
63
|
-
flex-shrink: 0;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
.wsl-banner__text { flex: 1; min-width: 0; }
|
|
67
|
-
.wsl-banner__title { font-size: var(--t-md); font-weight: 600; color: var(--fg); }
|
|
68
|
-
.wsl-banner__subtitle { font-size: var(--t-xs); color: var(--fg-2); margin-top: 4px; line-height: 1.5; }
|
|
69
|
-
|
|
70
|
-
.wsl-banner__cmd {
|
|
71
|
-
display: flex;
|
|
72
|
-
align-items: center;
|
|
73
|
-
justify-content: space-between;
|
|
74
|
-
gap: var(--sp-3);
|
|
75
|
-
background: var(--bg);
|
|
76
|
-
border: 1px solid var(--hairline);
|
|
77
|
-
border-radius: var(--r-sm);
|
|
78
|
-
padding: var(--sp-2) var(--sp-3);
|
|
79
|
-
}
|
|
80
|
-
.wsl-banner__cmd code {
|
|
81
|
-
font-family: var(--font-mono);
|
|
82
|
-
font-size: var(--t-sm);
|
|
83
|
-
color: var(--fg);
|
|
84
|
-
user-select: text;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
.wsl-banner__link {
|
|
88
|
-
font-size: var(--t-xs);
|
|
89
|
-
color: var(--fg-3);
|
|
90
|
-
align-self: flex-start;
|
|
91
|
-
}
|
|
92
|
-
.wsl-banner__link:hover { color: var(--brand); }
|
|
93
|
-
|
|
94
|
-
.wsl-banner__actions {
|
|
95
|
-
display: flex;
|
|
96
|
-
flex-direction: column;
|
|
97
|
-
gap: var(--sp-2);
|
|
98
|
-
}
|
|
99
|
-
.wsl-banner__hint {
|
|
100
|
-
font-size: var(--t-xs);
|
|
101
|
-
color: var(--fg-3);
|
|
102
|
-
line-height: 1.5;
|
|
103
|
-
}
|
|
104
|
-
.wsl-banner__error {
|
|
105
|
-
background: color-mix(in srgb, var(--danger) 8%, transparent);
|
|
106
|
-
border: 1px solid color-mix(in srgb, var(--danger) 30%, transparent);
|
|
107
|
-
border-radius: var(--r-sm);
|
|
108
|
-
padding: var(--sp-2) var(--sp-3);
|
|
109
|
-
color: var(--danger);
|
|
110
|
-
font-size: var(--t-xs);
|
|
111
|
-
word-break: break-word;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
/* ── Agent picker — shown when phase=picking-agents ───────────────── */
|
|
116
|
-
.wsl-banner__pick {
|
|
117
|
-
display: flex;
|
|
118
|
-
flex-direction: column;
|
|
119
|
-
gap: var(--sp-2);
|
|
120
|
-
padding: var(--sp-3);
|
|
121
|
-
background: var(--bg);
|
|
122
|
-
border: 1px solid var(--brand);
|
|
123
|
-
border-radius: var(--r-sm);
|
|
124
|
-
margin-top: var(--sp-2);
|
|
125
|
-
}
|
|
126
|
-
.wsl-banner__pick-title {
|
|
127
|
-
font-size: var(--t-sm);
|
|
128
|
-
font-weight: 600;
|
|
129
|
-
color: var(--fg);
|
|
130
|
-
}
|
|
131
|
-
.wsl-banner__pick-hint {
|
|
132
|
-
font-size: var(--t-xs);
|
|
133
|
-
color: var(--fg-3);
|
|
134
|
-
margin-bottom: 4px;
|
|
135
|
-
}
|
|
136
|
-
.wsl-banner__pick-options {
|
|
137
|
-
display: flex;
|
|
138
|
-
flex-direction: column;
|
|
139
|
-
gap: 6px;
|
|
140
|
-
}
|
|
141
|
-
.wsl-banner__pick-row {
|
|
142
|
-
display: flex;
|
|
143
|
-
align-items: center;
|
|
144
|
-
gap: 10px;
|
|
145
|
-
padding: 8px 10px;
|
|
146
|
-
border: 1px solid var(--hairline);
|
|
147
|
-
border-radius: var(--r-sm);
|
|
148
|
-
cursor: pointer;
|
|
149
|
-
transition: background 0.12s ease, border-color 0.12s ease;
|
|
150
|
-
user-select: none;
|
|
151
|
-
}
|
|
152
|
-
.wsl-banner__pick-row:hover {
|
|
153
|
-
background: color-mix(in srgb, var(--brand) 6%, transparent);
|
|
154
|
-
}
|
|
155
|
-
.wsl-banner__pick-row.is-checked {
|
|
156
|
-
border-color: var(--brand);
|
|
157
|
-
background: color-mix(in srgb, var(--brand) 10%, transparent);
|
|
158
|
-
}
|
|
159
|
-
.wsl-banner__pick-row input[type="checkbox"] {
|
|
160
|
-
accent-color: var(--brand);
|
|
161
|
-
margin: 0;
|
|
162
|
-
flex-shrink: 0;
|
|
163
|
-
}
|
|
164
|
-
.wsl-banner__pick-row-text { flex: 1; min-width: 0; }
|
|
165
|
-
.wsl-banner__pick-row-name { font-size: var(--t-sm); font-weight: 600; color: var(--fg); }
|
|
166
|
-
.wsl-banner__pick-row-desc { font-size: 11px; color: var(--fg-3); margin-top: 2px; }
|
|
167
|
-
.wsl-banner__pick-confirm {
|
|
168
|
-
margin-top: var(--sp-2);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
/* ── Live install progress + scrolling shell log ──────────────────────
|
|
173
|
-
The progress block becomes flex:1 so the raw shell log fills whatever
|
|
174
|
-
vertical room is left in the drawer when expanded. */
|
|
175
|
-
.wsl-banner__progress {
|
|
176
|
-
display: flex;
|
|
177
|
-
flex-direction: column;
|
|
178
|
-
gap: 8px;
|
|
179
|
-
margin-top: var(--sp-2);
|
|
180
|
-
padding-top: var(--sp-3);
|
|
181
|
-
border-top: 1px solid var(--hairline);
|
|
182
|
-
flex: 1 1 0;
|
|
183
|
-
min-height: 0;
|
|
184
|
-
overflow: hidden;
|
|
185
|
-
}
|
|
186
|
-
.wsl-banner__progress-text {
|
|
187
|
-
display: flex;
|
|
188
|
-
justify-content: space-between;
|
|
189
|
-
align-items: baseline;
|
|
190
|
-
font-size: var(--t-sm);
|
|
191
|
-
color: var(--fg-2);
|
|
192
|
-
}
|
|
193
|
-
.wsl-banner__progress-pct {
|
|
194
|
-
color: var(--brand);
|
|
195
|
-
font-weight: 700;
|
|
196
|
-
font-variant-numeric: tabular-nums;
|
|
197
|
-
}
|
|
198
|
-
.wsl-banner__progress-bar {
|
|
199
|
-
height: 4px;
|
|
200
|
-
background: var(--bg-1, #0d1117);
|
|
201
|
-
border-radius: 999px;
|
|
202
|
-
overflow: hidden;
|
|
203
|
-
position: relative;
|
|
204
|
-
}
|
|
205
|
-
.wsl-banner__progress-fill {
|
|
206
|
-
height: 100%;
|
|
207
|
-
background: var(--brand);
|
|
208
|
-
border-radius: inherit;
|
|
209
|
-
transition: width 0.3s ease;
|
|
210
|
-
}
|
|
211
|
-
.wsl-banner__progress-bar.is-indeterminate .wsl-banner__progress-fill {
|
|
212
|
-
animation: wsl-indeterminate 1.4s infinite ease-in-out;
|
|
213
|
-
width: 30% !important;
|
|
214
|
-
}
|
|
215
|
-
@keyframes wsl-indeterminate {
|
|
216
|
-
0% { transform: translateX(-100%); }
|
|
217
|
-
100% { transform: translateX(400%); }
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
/* docker-pivot simplified banner: progress bar row + agent picker */
|
|
221
|
-
.wsl-banner__progress-row {
|
|
222
|
-
display: flex;
|
|
223
|
-
align-items: center;
|
|
224
|
-
gap: 12px;
|
|
225
|
-
margin-top: var(--sp-2);
|
|
226
|
-
}
|
|
227
|
-
.wsl-banner__progress-row .wsl-banner__progress-bar {
|
|
228
|
-
flex: 1 1 0;
|
|
229
|
-
}
|
|
230
|
-
.wsl-banner__progress-row .wsl-banner__progress-text {
|
|
231
|
-
font-size: var(--t-sm);
|
|
232
|
-
color: var(--fg-2);
|
|
233
|
-
font-variant-numeric: tabular-nums;
|
|
234
|
-
white-space: nowrap;
|
|
235
|
-
}
|
|
236
|
-
.wsl-banner__agents {
|
|
237
|
-
margin-top: var(--sp-3);
|
|
238
|
-
padding: var(--sp-3);
|
|
239
|
-
background: var(--bg-1, #0d1117);
|
|
240
|
-
border: 1px solid var(--hairline);
|
|
241
|
-
border-radius: 8px;
|
|
242
|
-
display: flex;
|
|
243
|
-
flex-direction: column;
|
|
244
|
-
gap: var(--sp-2);
|
|
245
|
-
}
|
|
246
|
-
.wsl-banner__agents-title {
|
|
247
|
-
font-weight: 600;
|
|
248
|
-
font-size: var(--t-md);
|
|
249
|
-
}
|
|
250
|
-
.wsl-banner__agents-list {
|
|
251
|
-
display: flex;
|
|
252
|
-
flex-wrap: wrap;
|
|
253
|
-
gap: var(--sp-3);
|
|
254
|
-
}
|
|
255
|
-
.wsl-banner__agent-row {
|
|
256
|
-
display: inline-flex;
|
|
257
|
-
align-items: center;
|
|
258
|
-
gap: 6px;
|
|
259
|
-
cursor: pointer;
|
|
260
|
-
}
|
|
261
|
-
.wsl-banner__log {
|
|
262
|
-
margin: 0;
|
|
263
|
-
flex: 1 1 0; /* fill all remaining space in __progress */
|
|
264
|
-
min-height: 120px;
|
|
265
|
-
max-height: none;
|
|
266
|
-
overflow-y: auto;
|
|
267
|
-
font-family: var(--font-mono);
|
|
268
|
-
font-size: 11px;
|
|
269
|
-
line-height: 1.45;
|
|
270
|
-
color: var(--fg-3);
|
|
271
|
-
background: color-mix(in srgb, var(--bg-1, #0d1117) 80%, transparent);
|
|
272
|
-
border: 1px solid var(--hairline);
|
|
273
|
-
border-radius: 6px;
|
|
274
|
-
padding: 8px 10px;
|
|
275
|
-
white-space: pre-wrap;
|
|
276
|
-
word-break: break-word;
|
|
277
|
-
user-select: text;
|
|
278
|
-
scrollbar-width: thin;
|
|
279
|
-
scrollbar-color: var(--hairline) transparent;
|
|
280
|
-
}
|
|
281
|
-
.wsl-banner__log::-webkit-scrollbar { width: 10px; }
|
|
282
|
-
.wsl-banner__log::-webkit-scrollbar-track { background: transparent; }
|
|
283
|
-
.wsl-banner__log::-webkit-scrollbar-thumb {
|
|
284
|
-
background: color-mix(in srgb, var(--fg-3, #8b949e) 35%, transparent);
|
|
285
|
-
border-radius: 5px;
|
|
286
|
-
border: 2px solid transparent;
|
|
287
|
-
background-clip: padding-box;
|
|
288
|
-
}
|
|
289
|
-
.wsl-banner__log::-webkit-scrollbar-thumb:hover {
|
|
290
|
-
background: color-mix(in srgb, var(--fg-3, #8b949e) 60%, transparent);
|
|
291
|
-
background-clip: padding-box;
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
/* ── Step timeline — readable, structured progress ───────────────────── */
|
|
296
|
-
.wsl-banner__steps {
|
|
297
|
-
margin: 0;
|
|
298
|
-
padding: 0;
|
|
299
|
-
list-style: none;
|
|
300
|
-
display: flex;
|
|
301
|
-
flex-direction: column;
|
|
302
|
-
gap: 4px;
|
|
303
|
-
font-size: var(--t-sm);
|
|
304
|
-
flex-shrink: 0;
|
|
305
|
-
max-height: 55vh;
|
|
306
|
-
overflow-y: auto;
|
|
307
|
-
scrollbar-width: thin;
|
|
308
|
-
}
|
|
309
|
-
.wsl-banner__step {
|
|
310
|
-
display: flex;
|
|
311
|
-
align-items: baseline;
|
|
312
|
-
gap: 8px;
|
|
313
|
-
padding: 4px 6px;
|
|
314
|
-
border-radius: 4px;
|
|
315
|
-
color: var(--fg-3);
|
|
316
|
-
transition: background 0.15s ease, color 0.15s ease;
|
|
317
|
-
}
|
|
318
|
-
.wsl-banner__step.is-done { color: var(--fg-2); }
|
|
319
|
-
.wsl-banner__step.is-active {
|
|
320
|
-
color: var(--fg);
|
|
321
|
-
background: color-mix(in srgb, var(--brand) 8%, transparent);
|
|
322
|
-
}
|
|
323
|
-
.wsl-banner__step-icon {
|
|
324
|
-
display: inline-block;
|
|
325
|
-
width: 14px;
|
|
326
|
-
text-align: center;
|
|
327
|
-
font-family: var(--font-mono);
|
|
328
|
-
color: var(--fg-3);
|
|
329
|
-
flex-shrink: 0;
|
|
330
|
-
}
|
|
331
|
-
.wsl-banner__step.is-done .wsl-banner__step-icon { color: var(--brand); }
|
|
332
|
-
.wsl-banner__step.is-active .wsl-banner__step-icon {
|
|
333
|
-
color: var(--brand);
|
|
334
|
-
animation: wsl-step-pulse 1.2s infinite ease-in-out;
|
|
335
|
-
}
|
|
336
|
-
@keyframes wsl-step-pulse {
|
|
337
|
-
0%, 100% { opacity: 1; }
|
|
338
|
-
50% { opacity: 0.35; }
|
|
339
|
-
}
|
|
340
|
-
.wsl-banner__step-text {
|
|
341
|
-
flex: 1;
|
|
342
|
-
min-width: 0;
|
|
343
|
-
word-break: break-word;
|
|
344
|
-
}
|
|
345
|
-
.wsl-banner__step-pct {
|
|
346
|
-
margin-left: 6px;
|
|
347
|
-
color: var(--brand);
|
|
348
|
-
font-weight: 600;
|
|
349
|
-
font-variant-numeric: tabular-nums;
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
/* ── Raw shell log — opt-in, intentionally low-key ──────────────────── */
|
|
353
|
-
.wsl-banner__rawlog {
|
|
354
|
-
display: flex;
|
|
355
|
-
flex-direction: column;
|
|
356
|
-
gap: 6px;
|
|
357
|
-
margin-top: 4px;
|
|
358
|
-
flex: 1 1 0;
|
|
359
|
-
min-height: 0;
|
|
360
|
-
}
|
|
361
|
-
.wsl-banner__rawlog-toggle {
|
|
362
|
-
align-self: flex-end;
|
|
363
|
-
background: transparent;
|
|
364
|
-
border: 0;
|
|
365
|
-
padding: 0;
|
|
366
|
-
font: inherit;
|
|
367
|
-
font-size: 10px;
|
|
368
|
-
color: var(--fg-3);
|
|
369
|
-
opacity: 0.55;
|
|
370
|
-
cursor: pointer;
|
|
371
|
-
user-select: none;
|
|
372
|
-
text-decoration: underline;
|
|
373
|
-
text-underline-offset: 2px;
|
|
374
|
-
}
|
|
375
|
-
.wsl-banner__rawlog-toggle:hover { opacity: 1; }
|
|
376
|
-
|
|
377
|
-
.wsl-banner__step-label { font-weight: 500; }
|
|
378
|
-
.wsl-banner__step-detail {
|
|
379
|
-
color: var(--fg-3);
|
|
380
|
-
font-size: 11px;
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
.wsl-banner__step.is-error {
|
|
384
|
-
color: var(--danger, #f87171);
|
|
385
|
-
background: color-mix(in srgb, var(--danger, #f87171) 6%, transparent);
|
|
386
|
-
}
|
|
387
|
-
.wsl-banner__step.is-error .wsl-banner__step-icon {
|
|
388
|
-
color: var(--danger, #f87171);
|
|
389
|
-
}
|
|
390
|
-
.wsl-banner__step-error {
|
|
391
|
-
display: block;
|
|
392
|
-
margin-top: 4px;
|
|
393
|
-
padding-left: 0;
|
|
394
|
-
font-size: 11px;
|
|
395
|
-
color: var(--danger, #f87171);
|
|
396
|
-
word-break: break-word;
|
|
397
|
-
}
|
|
398
|
-
.wsl-banner__step-retry {
|
|
399
|
-
margin-left: 8px;
|
|
400
|
-
padding: 2px 10px;
|
|
401
|
-
border: 1px solid var(--brand);
|
|
402
|
-
background: transparent;
|
|
403
|
-
color: var(--brand);
|
|
404
|
-
border-radius: 4px;
|
|
405
|
-
font: inherit;
|
|
406
|
-
font-size: 11px;
|
|
407
|
-
cursor: pointer;
|
|
408
|
-
flex-shrink: 0;
|
|
409
|
-
align-self: center;
|
|
410
|
-
}
|
|
411
|
-
.wsl-banner__step-retry:hover {
|
|
412
|
-
background: color-mix(in srgb, var(--brand) 10%, transparent);
|
|
413
|
-
}
|
|
414
|
-
.wsl-banner__step-retry:disabled {
|
|
415
|
-
opacity: 0.5;
|
|
416
|
-
cursor: default;
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
/* ── Prominent top-level failure banner — surfaces the first failed
|
|
420
|
-
step's reason at the top of the drawer so the user doesn't have to
|
|
421
|
-
scan the timeline to spot the red ✗. Includes a retry CTA. ──────── */
|
|
422
|
-
.wsl-banner__failure {
|
|
423
|
-
display: flex;
|
|
424
|
-
flex-direction: column;
|
|
425
|
-
gap: var(--sp-2);
|
|
426
|
-
padding: var(--sp-3);
|
|
427
|
-
background: color-mix(in srgb, var(--danger, #f87171) 10%, transparent);
|
|
428
|
-
border: 1px solid var(--danger, #f87171);
|
|
429
|
-
border-left-width: 3px;
|
|
430
|
-
border-radius: var(--r-sm);
|
|
431
|
-
}
|
|
432
|
-
.wsl-banner__failure-head {
|
|
433
|
-
display: flex;
|
|
434
|
-
align-items: center;
|
|
435
|
-
gap: 8px;
|
|
436
|
-
font-size: var(--t-sm);
|
|
437
|
-
font-weight: 600;
|
|
438
|
-
color: var(--danger, #f87171);
|
|
439
|
-
}
|
|
440
|
-
.wsl-banner__failure-step {
|
|
441
|
-
font-size: 11px;
|
|
442
|
-
color: var(--fg-3);
|
|
443
|
-
text-transform: uppercase;
|
|
444
|
-
letter-spacing: 0.04em;
|
|
445
|
-
}
|
|
446
|
-
.wsl-banner__failure-msg {
|
|
447
|
-
font-family: var(--font-mono);
|
|
448
|
-
font-size: 12px;
|
|
449
|
-
color: var(--fg);
|
|
450
|
-
background: var(--bg);
|
|
451
|
-
border: 1px solid var(--hairline);
|
|
452
|
-
border-radius: var(--r-sm);
|
|
453
|
-
padding: 8px 10px;
|
|
454
|
-
white-space: pre-wrap;
|
|
455
|
-
word-break: break-word;
|
|
456
|
-
max-height: 140px;
|
|
457
|
-
overflow-y: auto;
|
|
458
|
-
}
|
|
459
|
-
.wsl-banner__failure-actions {
|
|
460
|
-
display: flex;
|
|
461
|
-
gap: 8px;
|
|
462
|
-
flex-wrap: wrap;
|
|
463
|
-
}
|
|
464
|
-
|