@legioncodeinc/hive 0.2.1 → 0.3.1
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/assets/brand/activeloop-full-mark-logo-on-dark.svg +209 -0
- package/assets/brand/activeloop-full-mark-logo.svg +208 -0
- package/assets/brand/divider-major.svg +1 -0
- package/assets/brand/divider-minor.svg +1 -0
- package/assets/brand/doctor-mark.svg +1 -0
- package/assets/brand/hive-mark.svg +1 -0
- package/assets/brand/hive-wordmark-black.svg +1 -0
- package/assets/brand/hive-wordmark-on-dark.svg +1 -0
- package/assets/brand/legion-logo-dark.svg +16 -0
- package/assets/brand/legion-logo-light.svg +16 -0
- package/assets/brand/nectar-mark.svg +1 -0
- package/assets/logos/fonts/Inter-Italic-VariableFont_opsz_wght.ttf +0 -0
- package/assets/logos/fonts/Inter-VariableFont_opsz_wght.ttf +0 -0
- package/assets/logos/fonts/JetBrainsMono-Bold.woff2 +0 -0
- package/assets/logos/fonts/JetBrainsMono-Medium.woff2 +0 -0
- package/assets/logos/fonts/JetBrainsMono-Regular.woff2 +0 -0
- package/assets/logos/fonts/JetBrainsMono-SemiBold.woff2 +0 -0
- package/assets/logos/honeycomb-memory-cluster.svg +17 -0
- package/assets/styles.css +11 -0
- package/assets/tokens/base.css +76 -0
- package/assets/tokens/colors.css +111 -0
- package/assets/tokens/fonts.css +32 -0
- package/assets/tokens/spacing.css +48 -0
- package/assets/tokens/typography.css +38 -0
- package/dist/daemon/dashboard/app.js +26 -25
- package/dist/daemon/dashboard/host.d.ts +7 -0
- package/dist/daemon/dashboard/host.js +16 -0
- package/dist/daemon/dashboard/host.js.map +1 -1
- package/dist/daemon/dashboard/web-assets.d.ts +2 -0
- package/dist/daemon/dashboard/web-assets.js +19 -0
- package/dist/daemon/dashboard/web-assets.js.map +1 -1
- package/dist/daemon/gate.d.ts +2 -2
- package/dist/daemon/gate.js +15 -4
- package/dist/daemon/gate.js.map +1 -1
- package/dist/daemon/installer/bin-resolver.d.ts +34 -0
- package/dist/daemon/installer/bin-resolver.js +107 -0
- package/dist/daemon/installer/bin-resolver.js.map +1 -0
- package/dist/daemon/installer/config.d.ts +63 -0
- package/dist/daemon/installer/config.js +74 -0
- package/dist/daemon/installer/config.js.map +1 -0
- package/dist/daemon/installer/detection.d.ts +20 -0
- package/dist/daemon/installer/detection.js +73 -0
- package/dist/daemon/installer/detection.js.map +1 -0
- package/dist/daemon/installer/funnel-telemetry.d.ts +54 -0
- package/dist/daemon/installer/funnel-telemetry.js +134 -0
- package/dist/daemon/installer/funnel-telemetry.js.map +1 -0
- package/dist/daemon/installer/index.d.ts +12 -0
- package/dist/daemon/installer/index.js +10 -0
- package/dist/daemon/installer/index.js.map +1 -0
- package/dist/daemon/installer/install-state.d.ts +56 -0
- package/dist/daemon/installer/install-state.js +159 -0
- package/dist/daemon/installer/install-state.js.map +1 -0
- package/dist/daemon/installer/manifest-snapshot.json +25 -0
- package/dist/daemon/installer/manifest.d.ts +47 -0
- package/dist/daemon/installer/manifest.js +103 -0
- package/dist/daemon/installer/manifest.js.map +1 -0
- package/dist/daemon/installer/products.d.ts +33 -0
- package/dist/daemon/installer/products.js +42 -0
- package/dist/daemon/installer/products.js.map +1 -0
- package/dist/daemon/installer/routes.d.ts +43 -0
- package/dist/daemon/installer/routes.js +201 -0
- package/dist/daemon/installer/routes.js.map +1 -0
- package/dist/daemon/installer/security.d.ts +33 -0
- package/dist/daemon/installer/security.js +80 -0
- package/dist/daemon/installer/security.js.map +1 -0
- package/dist/daemon/installer/spawn.d.ts +49 -0
- package/dist/daemon/installer/spawn.js +63 -0
- package/dist/daemon/installer/spawn.js.map +1 -0
- package/dist/daemon/installer/token.d.ts +23 -0
- package/dist/daemon/installer/token.js +56 -0
- package/dist/daemon/installer/token.js.map +1 -0
- package/dist/daemon/server.d.ts +6 -0
- package/dist/daemon/server.js +7 -0
- package/dist/daemon/server.js.map +1 -1
- package/dist/dashboard/web/app.js +42 -20
- package/dist/dashboard/web/app.js.map +1 -1
- package/dist/dashboard/web/boot-route.d.ts +11 -7
- package/dist/dashboard/web/boot-route.js +12 -6
- package/dist/dashboard/web/boot-route.js.map +1 -1
- package/dist/dashboard/web/main.js +2 -1
- package/dist/dashboard/web/main.js.map +1 -1
- package/dist/dashboard/web/onboarding/advanced-picker.d.ts +16 -0
- package/dist/dashboard/web/onboarding/advanced-picker.js +59 -0
- package/dist/dashboard/web/onboarding/advanced-picker.js.map +1 -0
- package/dist/dashboard/web/onboarding/contracts.d.ts +188 -0
- package/dist/dashboard/web/onboarding/contracts.js +161 -0
- package/dist/dashboard/web/onboarding/contracts.js.map +1 -0
- package/dist/dashboard/web/onboarding/health-view.d.ts +17 -0
- package/dist/dashboard/web/onboarding/health-view.js +79 -0
- package/dist/dashboard/web/onboarding/health-view.js.map +1 -0
- package/dist/dashboard/web/onboarding/install-card.d.ts +28 -0
- package/dist/dashboard/web/onboarding/install-card.js +171 -0
- package/dist/dashboard/web/onboarding/install-card.js.map +1 -0
- package/dist/dashboard/web/onboarding/login-step.d.ts +29 -0
- package/dist/dashboard/web/onboarding/login-step.js +104 -0
- package/dist/dashboard/web/onboarding/login-step.js.map +1 -0
- package/dist/dashboard/web/onboarding/onboarding-client.d.ts +52 -0
- package/dist/dashboard/web/onboarding/onboarding-client.js +133 -0
- package/dist/dashboard/web/onboarding/onboarding-client.js.map +1 -0
- package/dist/dashboard/web/onboarding/onboarding-hero.d.ts +24 -0
- package/dist/dashboard/web/onboarding/onboarding-hero.js +70 -0
- package/dist/dashboard/web/onboarding/onboarding-hero.js.map +1 -0
- package/dist/dashboard/web/onboarding/onboarding-screen.d.ts +43 -0
- package/dist/dashboard/web/onboarding/onboarding-screen.js +193 -0
- package/dist/dashboard/web/onboarding/onboarding-screen.js.map +1 -0
- package/dist/dashboard/web/onboarding/onboarding-selection-store.d.ts +20 -0
- package/dist/dashboard/web/onboarding/onboarding-selection-store.js +76 -0
- package/dist/dashboard/web/onboarding/onboarding-selection-store.js.map +1 -0
- package/dist/dashboard/web/onboarding/product-copy.d.ts +40 -0
- package/dist/dashboard/web/onboarding/product-copy.js +70 -0
- package/dist/dashboard/web/onboarding/product-copy.js.map +1 -0
- package/dist/dashboard/web/onboarding/use-install-dwell.d.ts +27 -0
- package/dist/dashboard/web/onboarding/use-install-dwell.js +42 -0
- package/dist/dashboard/web/onboarding/use-install-dwell.js.map +1 -0
- package/dist/dashboard/web/onboarding/use-onboarding-token.d.ts +14 -0
- package/dist/dashboard/web/onboarding/use-onboarding-token.js +41 -0
- package/dist/dashboard/web/onboarding/use-onboarding-token.js.map +1 -0
- package/dist/dashboard/web/route-daemon-owner.d.ts +7 -0
- package/dist/dashboard/web/route-daemon-owner.js +15 -0
- package/dist/dashboard/web/route-daemon-owner.js.map +1 -0
- package/dist/dashboard/web/wire.d.ts +1 -1
- package/dist/shared/onboarding-types.d.ts +79 -0
- package/dist/shared/onboarding-types.js +12 -0
- package/dist/shared/onboarding-types.js.map +1 -0
- package/dist/telemetry/emit.d.ts +30 -3
- package/dist/telemetry/emit.js +25 -2
- package/dist/telemetry/emit.js.map +1 -1
- package/dist/telemetry/onboarding-session-ledger.d.ts +31 -0
- package/dist/telemetry/onboarding-session-ledger.js +78 -0
- package/dist/telemetry/onboarding-session-ledger.js.map +1 -0
- package/package.json +6 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"onboarding-hero.js","sourceRoot":"","sources":["../../../../src/dashboard/web/onboarding/onboarding-hero.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `/onboarding` route's TOP-LEVEL screen, PRD-009b. Mirrors `/buzzing`/`/login`'s posture
|
|
3
|
+
* (`buzzing-screen.tsx`, `setup-gate.tsx`): a single top-level component `main.tsx` mounts directly
|
|
4
|
+
* (via `boot-route.ts`), owning its own state machine rather than nesting inside the authenticated
|
|
5
|
+
* `<Shell>`. The state machine:
|
|
6
|
+
*
|
|
7
|
+
* detect (+ an upfront health read for ob-AC-3) ─┬─ all installed AND healthy → short-circuit
|
|
8
|
+
* ├─ a remaining product is mid-flight/failed →
|
|
9
|
+
* │ resume straight into "installing" (ob-AC-16/17)
|
|
10
|
+
* └─ otherwise → the first-run hero (ob-AC-4/5)
|
|
11
|
+
* hero ─ Standard → installing(all remaining, fixed order) (ob-AC-6)
|
|
12
|
+
* └ Advanced → picker → installing(exactly the chosen subset) (ob-AC-7)
|
|
13
|
+
* installing(queue, index) ── each card completes+dwells → advance → next index, else → health
|
|
14
|
+
* health ── polls until ready → login
|
|
15
|
+
* login ── device-code display, then a hard navigation to `/` on authenticated (ob-AC-14/15)
|
|
16
|
+
*
|
|
17
|
+
* Resume honesty (ob-AC-16): the Standard/Advanced choice is persisted client-side
|
|
18
|
+
* (onboarding-selection-store), so a resumed install uses `buildResumeQueue`, which excludes a
|
|
19
|
+
* not-installed product the operator explicitly deselected in Advanced. Without that memory, resume
|
|
20
|
+
* would fall back to only products that are genuinely mid-flight or failed, never silently
|
|
21
|
+
* reinstalling a deselected one.
|
|
22
|
+
*/
|
|
23
|
+
import React from "react";
|
|
24
|
+
import { type OnboardingClient } from "./onboarding-client.js";
|
|
25
|
+
import type { WireClient } from "../wire.js";
|
|
26
|
+
export interface OnboardingScreenProps {
|
|
27
|
+
readonly assetBase?: string;
|
|
28
|
+
/** Test seam: inject a fake onboarding client, bypassing the real token + fetch wiring entirely. */
|
|
29
|
+
readonly client?: OnboardingClient;
|
|
30
|
+
/** Test seam: inject a fake proxied setup wire client for the login step. */
|
|
31
|
+
readonly wire?: WireClient;
|
|
32
|
+
/** Test seam: override the brief install dwell (ob-AC-11, revised). */
|
|
33
|
+
readonly minDwellMs?: number;
|
|
34
|
+
/** Test seam: override the health-check poll interval. */
|
|
35
|
+
readonly healthPollMs?: number;
|
|
36
|
+
/** Test seam: override the login step's `/setup/state` poll interval. */
|
|
37
|
+
readonly loginPollMs?: number;
|
|
38
|
+
/** Test seam: called instead of the real hard navigation from the short-circuit summary. */
|
|
39
|
+
readonly onShortCircuitNavigate?: () => void;
|
|
40
|
+
/** Test seam: called instead of the real hard navigation once login completes (ob-AC-15). */
|
|
41
|
+
readonly onAuthenticated?: () => void;
|
|
42
|
+
}
|
|
43
|
+
export declare function OnboardingScreen({ assetBase, client: clientOverride, wire, minDwellMs, healthPollMs, loginPollMs, onShortCircuitNavigate, onAuthenticated, }: OnboardingScreenProps): React.JSX.Element;
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* The `/onboarding` route's TOP-LEVEL screen, PRD-009b. Mirrors `/buzzing`/`/login`'s posture
|
|
4
|
+
* (`buzzing-screen.tsx`, `setup-gate.tsx`): a single top-level component `main.tsx` mounts directly
|
|
5
|
+
* (via `boot-route.ts`), owning its own state machine rather than nesting inside the authenticated
|
|
6
|
+
* `<Shell>`. The state machine:
|
|
7
|
+
*
|
|
8
|
+
* detect (+ an upfront health read for ob-AC-3) ─┬─ all installed AND healthy → short-circuit
|
|
9
|
+
* ├─ a remaining product is mid-flight/failed →
|
|
10
|
+
* │ resume straight into "installing" (ob-AC-16/17)
|
|
11
|
+
* └─ otherwise → the first-run hero (ob-AC-4/5)
|
|
12
|
+
* hero ─ Standard → installing(all remaining, fixed order) (ob-AC-6)
|
|
13
|
+
* └ Advanced → picker → installing(exactly the chosen subset) (ob-AC-7)
|
|
14
|
+
* installing(queue, index) ── each card completes+dwells → advance → next index, else → health
|
|
15
|
+
* health ── polls until ready → login
|
|
16
|
+
* login ── device-code display, then a hard navigation to `/` on authenticated (ob-AC-14/15)
|
|
17
|
+
*
|
|
18
|
+
* Resume honesty (ob-AC-16): the Standard/Advanced choice is persisted client-side
|
|
19
|
+
* (onboarding-selection-store), so a resumed install uses `buildResumeQueue`, which excludes a
|
|
20
|
+
* not-installed product the operator explicitly deselected in Advanced. Without that memory, resume
|
|
21
|
+
* would fall back to only products that are genuinely mid-flight or failed, never silently
|
|
22
|
+
* reinstalling a deselected one.
|
|
23
|
+
*/
|
|
24
|
+
import React from "react";
|
|
25
|
+
import { AdvancedPicker } from "./advanced-picker.js";
|
|
26
|
+
import { buildResumeQueue, DEFAULT_PRODUCT_DETECTION, detectionFor, hasResumableInstall, isFleetFullyInstalled, remainingProducts, } from "./contracts.js";
|
|
27
|
+
import { clearSelection, persistSelection, readSelection } from "./onboarding-selection-store.js";
|
|
28
|
+
import { HealthView } from "./health-view.js";
|
|
29
|
+
import { InstallCard } from "./install-card.js";
|
|
30
|
+
import { LoginStep } from "./login-step.js";
|
|
31
|
+
import { createOnboardingClient } from "./onboarding-client.js";
|
|
32
|
+
import { OnboardingHero } from "./onboarding-hero.js";
|
|
33
|
+
import { useOnboardingToken } from "./use-onboarding-token.js";
|
|
34
|
+
import { Button } from "../primitives.js";
|
|
35
|
+
/** An empty install queue means nothing more to do, skip straight to the health gate. */
|
|
36
|
+
function installingOrHealth(queue) {
|
|
37
|
+
return queue.length === 0 ? { kind: "health" } : { kind: "installing", queue, index: 0 };
|
|
38
|
+
}
|
|
39
|
+
/** ob-AC-3, the terminal "nothing to do" screen for an already-installed, healthy machine. */
|
|
40
|
+
function ShortCircuitSummary({ onGoToDashboard }) {
|
|
41
|
+
return (_jsx("div", { "data-testid": "onboarding-short-circuit", style: { display: "flex", alignItems: "center", justifyContent: "center", minHeight: "100vh", padding: 32, background: "var(--bg-canvas)", textAlign: "center" }, children: _jsxs("div", { style: {
|
|
42
|
+
display: "flex",
|
|
43
|
+
flexDirection: "column",
|
|
44
|
+
alignItems: "center",
|
|
45
|
+
gap: 18,
|
|
46
|
+
maxWidth: 440,
|
|
47
|
+
padding: "40px 32px",
|
|
48
|
+
background: "var(--bg-surface)",
|
|
49
|
+
border: "1px solid var(--border-default)",
|
|
50
|
+
borderRadius: "var(--radius-xl)",
|
|
51
|
+
}, children: [_jsx("h1", { style: { fontSize: "var(--text-xl)", fontWeight: 700, color: "var(--text-primary)", margin: 0, letterSpacing: "-0.02em" }, children: "Your fleet is already up" }), _jsx("p", { style: { fontFamily: "var(--font-sans)", fontSize: "var(--text-sm)", color: "var(--text-secondary)", margin: 0, lineHeight: 1.5 }, children: "Every product is installed and the fleet reads healthy. Nothing to install here." }), _jsx(Button, { variant: "primary", size: "lg", "data-testid": "onboarding-go-to-dashboard", onClick: onGoToDashboard, children: "Go to dashboard" })] }) }));
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* The terminal "no token" screen. The one-time token rides the opened URL (`/onboarding?t=...`) and
|
|
55
|
+
* is held in memory only, so landing here without one (a refresh after the URL scrub, the printed
|
|
56
|
+
* fallback link, a bookmark) can never recover on its own — the operator re-runs the installer,
|
|
57
|
+
* which mints a fresh token and reopens the portal.
|
|
58
|
+
*/
|
|
59
|
+
function MissingTokenNotice() {
|
|
60
|
+
return (_jsx("div", { "data-testid": "onboarding-missing-token", style: { display: "flex", alignItems: "center", justifyContent: "center", minHeight: "100vh", padding: 32, background: "var(--bg-canvas)", textAlign: "center" }, children: _jsxs("div", { style: {
|
|
61
|
+
display: "flex",
|
|
62
|
+
flexDirection: "column",
|
|
63
|
+
alignItems: "center",
|
|
64
|
+
gap: 18,
|
|
65
|
+
maxWidth: 480,
|
|
66
|
+
padding: "40px 32px",
|
|
67
|
+
background: "var(--bg-surface)",
|
|
68
|
+
border: "1px solid var(--border-default)",
|
|
69
|
+
borderRadius: "var(--radius-xl)",
|
|
70
|
+
}, children: [_jsx("h1", { style: { fontSize: "var(--text-xl)", fontWeight: 700, color: "var(--text-primary)", margin: 0, letterSpacing: "-0.02em" }, children: "This setup link has expired" }), _jsx("p", { style: { fontFamily: "var(--font-sans)", fontSize: "var(--text-sm)", color: "var(--text-secondary)", margin: 0, lineHeight: 1.5 }, children: "The setup page needs the one-time link the installer opens for you, and this visit did not carry it (refreshing this page drops it too). Re-run the installer to get a fresh link:" }), _jsx("code", { style: {
|
|
71
|
+
fontFamily: "var(--font-mono)",
|
|
72
|
+
fontSize: "var(--text-xs)",
|
|
73
|
+
color: "var(--text-primary)",
|
|
74
|
+
background: "var(--bg-canvas)",
|
|
75
|
+
border: "1px solid var(--border-default)",
|
|
76
|
+
borderRadius: "var(--radius-md)",
|
|
77
|
+
padding: "10px 14px",
|
|
78
|
+
}, children: "curl -fsSL https://get.theapiary.sh | sh" })] }) }));
|
|
79
|
+
}
|
|
80
|
+
/** The brief pre-detection placeholder, visible only for the moment detect+health are in flight. */
|
|
81
|
+
function LoadingPlaceholder() {
|
|
82
|
+
return (_jsx("div", { "data-testid": "onboarding-loading", style: { display: "flex", alignItems: "center", justifyContent: "center", minHeight: "100vh", background: "var(--bg-canvas)" }, children: _jsx("p", { style: { fontFamily: "var(--font-mono)", fontSize: "var(--text-xs)", color: "var(--text-tertiary)" }, children: "Checking what is already installed\u2026" }) }));
|
|
83
|
+
}
|
|
84
|
+
export function OnboardingScreen({ assetBase = "assets", client: clientOverride, wire, minDwellMs, healthPollMs, loginPollMs, onShortCircuitNavigate, onAuthenticated, }) {
|
|
85
|
+
const token = useOnboardingToken();
|
|
86
|
+
// A test-injected client bypasses the token gate entirely (it never talks to the real token
|
|
87
|
+
// wiring); real usage waits for `useOnboardingToken` to resolve the `?t=` query param first.
|
|
88
|
+
// A RESOLVED-ABSENT token (`""`) is terminal: without it every installer call 401s, so the
|
|
89
|
+
// screen shows recovery guidance below instead of spinning on the loading placeholder forever.
|
|
90
|
+
const tokenReady = clientOverride !== undefined || (token !== null && token !== "");
|
|
91
|
+
const tokenMissing = clientOverride === undefined && token === "";
|
|
92
|
+
const client = React.useMemo(() => clientOverride ?? createOnboardingClient(token ?? ""), [clientOverride, token]);
|
|
93
|
+
const [phase, setPhase] = React.useState({ kind: "loading" });
|
|
94
|
+
const [detection, setDetection] = React.useState(null);
|
|
95
|
+
const startedEventFiredRef = React.useRef(false);
|
|
96
|
+
React.useEffect(() => {
|
|
97
|
+
if (!tokenReady || startedEventFiredRef.current)
|
|
98
|
+
return;
|
|
99
|
+
startedEventFiredRef.current = true;
|
|
100
|
+
client.sendEvent("onboarding_started");
|
|
101
|
+
}, [client, tokenReady]);
|
|
102
|
+
React.useEffect(() => {
|
|
103
|
+
if (!tokenReady)
|
|
104
|
+
return;
|
|
105
|
+
let alive = true;
|
|
106
|
+
void (async () => {
|
|
107
|
+
const [detectResult, healthResult] = await Promise.all([client.detect(), client.health()]);
|
|
108
|
+
if (!alive)
|
|
109
|
+
return;
|
|
110
|
+
setDetection(detectResult);
|
|
111
|
+
if (isFleetFullyInstalled(detectResult) && healthResult.ready) {
|
|
112
|
+
setPhase({ kind: "short-circuit" });
|
|
113
|
+
}
|
|
114
|
+
else if (hasResumableInstall(detectResult)) {
|
|
115
|
+
// Resume honors the operator's persisted subset so a deselected product is never
|
|
116
|
+
// silently reinstalled; falls back to only mid-flight/failed products when unknown.
|
|
117
|
+
setPhase(installingOrHealth(buildResumeQueue(detectResult, readSelection())));
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
setPhase({ kind: "hero" });
|
|
121
|
+
}
|
|
122
|
+
})();
|
|
123
|
+
return () => {
|
|
124
|
+
alive = false;
|
|
125
|
+
};
|
|
126
|
+
}, [client, tokenReady]);
|
|
127
|
+
const chooseMode = React.useCallback((mode) => {
|
|
128
|
+
client.sendEvent("mode_selected", { mode });
|
|
129
|
+
if (mode === "standard") {
|
|
130
|
+
const queue = detection !== null ? remainingProducts(detection) : [];
|
|
131
|
+
persistSelection(queue);
|
|
132
|
+
setPhase(installingOrHealth(queue));
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
setPhase({ kind: "picker" });
|
|
136
|
+
}
|
|
137
|
+
}, [client, detection]);
|
|
138
|
+
const confirmAdvanced = React.useCallback((selected) => {
|
|
139
|
+
persistSelection(selected);
|
|
140
|
+
setPhase(installingOrHealth(selected));
|
|
141
|
+
}, []);
|
|
142
|
+
const advanceInstall = React.useCallback(() => {
|
|
143
|
+
setPhase((current) => {
|
|
144
|
+
if (current.kind !== "installing")
|
|
145
|
+
return current;
|
|
146
|
+
const nextIndex = current.index + 1;
|
|
147
|
+
return nextIndex >= current.queue.length ? { kind: "health" } : { kind: "installing", queue: current.queue, index: nextIndex };
|
|
148
|
+
});
|
|
149
|
+
}, []);
|
|
150
|
+
const goToLogin = React.useCallback(() => setPhase({ kind: "login" }), []);
|
|
151
|
+
const handleShortCircuitNavigate = React.useCallback(() => {
|
|
152
|
+
clearSelection();
|
|
153
|
+
if (onShortCircuitNavigate !== undefined) {
|
|
154
|
+
onShortCircuitNavigate();
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
if (typeof window !== "undefined")
|
|
158
|
+
window.location.assign("/");
|
|
159
|
+
}, [onShortCircuitNavigate]);
|
|
160
|
+
// Onboarding reached its terminal state (login complete): drop the persisted subset so a later
|
|
161
|
+
// visit starts clean rather than resuming against a stale choice.
|
|
162
|
+
const handleAuthenticated = React.useCallback(() => {
|
|
163
|
+
clearSelection();
|
|
164
|
+
if (onAuthenticated !== undefined)
|
|
165
|
+
onAuthenticated();
|
|
166
|
+
}, [onAuthenticated]);
|
|
167
|
+
if (tokenMissing)
|
|
168
|
+
return _jsx(MissingTokenNotice, {});
|
|
169
|
+
switch (phase.kind) {
|
|
170
|
+
case "loading":
|
|
171
|
+
return _jsx(LoadingPlaceholder, {});
|
|
172
|
+
case "short-circuit":
|
|
173
|
+
return _jsx(ShortCircuitSummary, { onGoToDashboard: handleShortCircuitNavigate });
|
|
174
|
+
case "hero":
|
|
175
|
+
return _jsx(OnboardingHero, { assetBase: assetBase, onChooseStandard: () => chooseMode("standard"), onChooseAdvanced: () => chooseMode("advanced") });
|
|
176
|
+
case "picker":
|
|
177
|
+
return _jsx(AdvancedPicker, { products: detection !== null ? remainingProducts(detection) : [], assetBase: assetBase, onConfirm: confirmAdvanced });
|
|
178
|
+
case "installing": {
|
|
179
|
+
const product = phase.queue[phase.index];
|
|
180
|
+
const initialDetection = detection !== null ? detectionFor(detection, product) : DEFAULT_PRODUCT_DETECTION;
|
|
181
|
+
return (_jsx(InstallCard, { product: product, initialDetection: initialDetection, client: client, assetBase: assetBase, onAdvance: advanceInstall, minDwellMs: minDwellMs }, product));
|
|
182
|
+
}
|
|
183
|
+
case "health":
|
|
184
|
+
return _jsx(HealthView, { client: client, onReady: goToLogin, pollMs: healthPollMs });
|
|
185
|
+
case "login":
|
|
186
|
+
return _jsx(LoginStep, { onboardingClient: client, wire: wire, onAuthenticated: handleAuthenticated, pollMs: loginPollMs });
|
|
187
|
+
default: {
|
|
188
|
+
const exhaustive = phase;
|
|
189
|
+
return exhaustive;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
//# sourceMappingURL=onboarding-screen.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"onboarding-screen.js","sourceRoot":"","sources":["../../../../src/dashboard/web/onboarding/onboarding-screen.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session-scoped memory of the product subset the operator chose (Standard = the whole fleet,
|
|
3
|
+
* Advanced = exactly the checked products). PRD-009b ob-AC-16 resume honesty: without this, an
|
|
4
|
+
* interrupted Advanced install resumes from `remainingProducts(detection)`, which is every
|
|
5
|
+
* not-installed product, so a product the operator explicitly DESELECTED would be silently
|
|
6
|
+
* reinstalled on re-entry. Persisting the choice lets `buildResumeQueue` exclude a not-installed
|
|
7
|
+
* product the operator never asked for, while still resuming any product that is genuinely
|
|
8
|
+
* mid-flight or failed (those are in-flight facts, not assumptions).
|
|
9
|
+
*
|
|
10
|
+
* Storage is `sessionStorage` (per browser session, cleared when the tab closes) and every access
|
|
11
|
+
* is guarded: a missing `window`, a storage exception (private mode, quota, disabled), or a
|
|
12
|
+
* malformed value all degrade to "no memory" rather than throwing into the onboarding flow.
|
|
13
|
+
*/
|
|
14
|
+
import { type InstallableProduct } from "./contracts.js";
|
|
15
|
+
/** Persist the chosen installable subset (order-normalized to the fixed order, de-duplicated). */
|
|
16
|
+
export declare function persistSelection(selected: readonly InstallableProduct[]): void;
|
|
17
|
+
/** Read the persisted subset, or null when nothing valid is stored. */
|
|
18
|
+
export declare function readSelection(): readonly InstallableProduct[] | null;
|
|
19
|
+
/** Drop the persisted subset (call when onboarding reaches a terminal state). */
|
|
20
|
+
export declare function clearSelection(): void;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session-scoped memory of the product subset the operator chose (Standard = the whole fleet,
|
|
3
|
+
* Advanced = exactly the checked products). PRD-009b ob-AC-16 resume honesty: without this, an
|
|
4
|
+
* interrupted Advanced install resumes from `remainingProducts(detection)`, which is every
|
|
5
|
+
* not-installed product, so a product the operator explicitly DESELECTED would be silently
|
|
6
|
+
* reinstalled on re-entry. Persisting the choice lets `buildResumeQueue` exclude a not-installed
|
|
7
|
+
* product the operator never asked for, while still resuming any product that is genuinely
|
|
8
|
+
* mid-flight or failed (those are in-flight facts, not assumptions).
|
|
9
|
+
*
|
|
10
|
+
* Storage is `sessionStorage` (per browser session, cleared when the tab closes) and every access
|
|
11
|
+
* is guarded: a missing `window`, a storage exception (private mode, quota, disabled), or a
|
|
12
|
+
* malformed value all degrade to "no memory" rather than throwing into the onboarding flow.
|
|
13
|
+
*/
|
|
14
|
+
import { FIXED_PRODUCT_ORDER, isInstallableProduct } from "./contracts.js";
|
|
15
|
+
const SELECTION_KEY = "hive-onboarding-selection";
|
|
16
|
+
function storage() {
|
|
17
|
+
try {
|
|
18
|
+
if (typeof window === "undefined")
|
|
19
|
+
return null;
|
|
20
|
+
return window.sessionStorage;
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/** Persist the chosen installable subset (order-normalized to the fixed order, de-duplicated). */
|
|
27
|
+
export function persistSelection(selected) {
|
|
28
|
+
const store = storage();
|
|
29
|
+
if (store === null)
|
|
30
|
+
return;
|
|
31
|
+
const normalized = FIXED_PRODUCT_ORDER.filter((p) => selected.includes(p));
|
|
32
|
+
try {
|
|
33
|
+
store.setItem(SELECTION_KEY, JSON.stringify(normalized));
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
// A storage write failure is non-fatal: resume simply falls back to the conservative path.
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/** Read the persisted subset, or null when nothing valid is stored. */
|
|
40
|
+
export function readSelection() {
|
|
41
|
+
const store = storage();
|
|
42
|
+
if (store === null)
|
|
43
|
+
return null;
|
|
44
|
+
let raw;
|
|
45
|
+
try {
|
|
46
|
+
raw = store.getItem(SELECTION_KEY);
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
if (raw === null)
|
|
52
|
+
return null;
|
|
53
|
+
try {
|
|
54
|
+
const parsed = JSON.parse(raw);
|
|
55
|
+
if (!Array.isArray(parsed))
|
|
56
|
+
return null;
|
|
57
|
+
const products = parsed.filter((v) => typeof v === "string" && isInstallableProduct(v));
|
|
58
|
+
return products.length > 0 ? FIXED_PRODUCT_ORDER.filter((p) => products.includes(p)) : null;
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/** Drop the persisted subset (call when onboarding reaches a terminal state). */
|
|
65
|
+
export function clearSelection() {
|
|
66
|
+
const store = storage();
|
|
67
|
+
if (store === null)
|
|
68
|
+
return;
|
|
69
|
+
try {
|
|
70
|
+
store.removeItem(SELECTION_KEY);
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
// Non-fatal.
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=onboarding-selection-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"onboarding-selection-store.js","sourceRoot":"","sources":["../../../../src/dashboard/web/onboarding/onboarding-selection-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAA2B,MAAM,gBAAgB,CAAC;AAEpG,MAAM,aAAa,GAAG,2BAA2B,CAAC;AAElD,SAAS,OAAO;IACf,IAAI,CAAC;QACJ,IAAI,OAAO,MAAM,KAAK,WAAW;YAAE,OAAO,IAAI,CAAC;QAC/C,OAAO,MAAM,CAAC,cAAc,CAAC;IAC9B,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,IAAI,CAAC;IACb,CAAC;AACF,CAAC;AAED,kGAAkG;AAClG,MAAM,UAAU,gBAAgB,CAAC,QAAuC;IACvE,MAAM,KAAK,GAAG,OAAO,EAAE,CAAC;IACxB,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO;IAC3B,MAAM,UAAU,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3E,IAAI,CAAC;QACJ,KAAK,CAAC,OAAO,CAAC,aAAa,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC;IAC1D,CAAC;IAAC,MAAM,CAAC;QACR,2FAA2F;IAC5F,CAAC;AACF,CAAC;AAED,uEAAuE;AACvE,MAAM,UAAU,aAAa;IAC5B,MAAM,KAAK,GAAG,OAAO,EAAE,CAAC;IACxB,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAChC,IAAI,GAAkB,CAAC;IACvB,IAAI,CAAC;QACJ,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;IACpC,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,IAAI,CAAC;IACb,CAAC;IACD,IAAI,GAAG,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC9B,IAAI,CAAC;QACJ,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACxC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;YAAE,OAAO,IAAI,CAAC;QACxC,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAA2B,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,oBAAoB,CAAC,CAAC,CAAC,CAAC,CAAC;QACjH,OAAO,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC7F,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,IAAI,CAAC;IACb,CAAC;AACF,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,cAAc;IAC7B,MAAM,KAAK,GAAG,OAAO,EAAE,CAAC;IACxB,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO;IAC3B,IAAI,CAAC;QACJ,KAAK,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;IACjC,CAAC;IAAC,MAAM,CAAC;QACR,aAAa;IACd,CAAC;AACF,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The onboarding CONTENT layer, PRD-009b ob-AC-8/ob-AC-10. Per-product benefit copy (drafted from
|
|
3
|
+
* each sibling repo's README voice: `honeycomb/README.md`, `doctor/README.md`, `nectar/README.md`)
|
|
4
|
+
* plus the npm-safety reassurance every install card carries and the Doctor-deselect warning the
|
|
5
|
+
* Advanced picker shows (ob-AC-7). Kept as data, not JSX, so copy review never touches a component.
|
|
6
|
+
*/
|
|
7
|
+
import type { InstallableProduct, OnboardingProduct } from "./contracts.js";
|
|
8
|
+
export interface ProductCopy {
|
|
9
|
+
readonly title: string;
|
|
10
|
+
/** A punchy, honest headline (drafted from the product's README hero line). */
|
|
11
|
+
readonly headline: string;
|
|
12
|
+
/** Two short supporting lines, concrete, no invented claims. */
|
|
13
|
+
readonly lines: readonly [string, string];
|
|
14
|
+
/** Doctor carries the `Recommended` badge in the Advanced picker (ob-AC-7). */
|
|
15
|
+
readonly recommended: boolean;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Drafted verbatim from each product's README (see the task report for the source lines this
|
|
19
|
+
* copy distills): Doctor's "watchdog that keeps your agents' brain alive" + repair-ladder pitch,
|
|
20
|
+
* Honeycomb's "shared, persistent memory" + skillify/propagation pitch, Nectar's "stable identity
|
|
21
|
+
* that survives refactors" + the fourth-recall-arm pitch. Honest and concrete, no invented claims.
|
|
22
|
+
*/
|
|
23
|
+
export declare const PRODUCT_COPY: Record<InstallableProduct, ProductCopy>;
|
|
24
|
+
/**
|
|
25
|
+
* ob-AC-10, the npm-safety reassurance every install card carries, verbatim. Checkably true for
|
|
26
|
+
* all four packages (`@legioncodeinc/{honeycomb,doctor,hive,nectar}` each publish with npm Trusted
|
|
27
|
+
* Publishing OIDC provenance per the parent PRD's overview), so this never overstates the claim.
|
|
28
|
+
*/
|
|
29
|
+
export declare const NPM_SAFETY_COPY = "Installed straight from the public npm registry. Every package here is signed and provenance verified through npm Trusted Publishing (OIDC), so what installs is exactly what we published.";
|
|
30
|
+
/** ob-AC-7, shown when Doctor is deselected in the Advanced picker. */
|
|
31
|
+
export declare const DOCTOR_DESELECT_WARNING = "Without Doctor, nothing restarts your daemons after a crash or reboot.";
|
|
32
|
+
/**
|
|
33
|
+
* Resolve a product's brand mark URL. Honeycomb keeps its existing top-level, `assetBase`-relative
|
|
34
|
+
* route (`host.ts`'s `DASHBOARD_LOGO_PATH`, unchanged by this PRD); Doctor, Hive, and Nectar are
|
|
35
|
+
* served by the daemon agent at the new fixed `/assets/brand/<name>-mark.svg` route (see the task
|
|
36
|
+
* brief), independent of `assetBase`.
|
|
37
|
+
*/
|
|
38
|
+
export declare function productLogoUrl(product: OnboardingProduct, assetBase: string): string;
|
|
39
|
+
/** The install-stage vocabulary (ob-AC-9): a short human label per stage, never a percentage. */
|
|
40
|
+
export declare const INSTALL_STAGE_LABEL: Record<"resolving" | "downloading" | "linking" | "registering_service" | "completed" | "failed", string>;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The onboarding CONTENT layer, PRD-009b ob-AC-8/ob-AC-10. Per-product benefit copy (drafted from
|
|
3
|
+
* each sibling repo's README voice: `honeycomb/README.md`, `doctor/README.md`, `nectar/README.md`)
|
|
4
|
+
* plus the npm-safety reassurance every install card carries and the Doctor-deselect warning the
|
|
5
|
+
* Advanced picker shows (ob-AC-7). Kept as data, not JSX, so copy review never touches a component.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Drafted verbatim from each product's README (see the task report for the source lines this
|
|
9
|
+
* copy distills): Doctor's "watchdog that keeps your agents' brain alive" + repair-ladder pitch,
|
|
10
|
+
* Honeycomb's "shared, persistent memory" + skillify/propagation pitch, Nectar's "stable identity
|
|
11
|
+
* that survives refactors" + the fourth-recall-arm pitch. Honest and concrete, no invented claims.
|
|
12
|
+
*/
|
|
13
|
+
export const PRODUCT_COPY = {
|
|
14
|
+
doctor: {
|
|
15
|
+
title: "Doctor",
|
|
16
|
+
headline: "Doctor keeps your daemons alive while you are not looking.",
|
|
17
|
+
lines: [
|
|
18
|
+
"Restarts a crashed daemon, then climbs an escalating repair ladder if a plain restart is not enough.",
|
|
19
|
+
"Runs OS-supervised so it starts on boot and survives its own crashes too.",
|
|
20
|
+
],
|
|
21
|
+
recommended: true,
|
|
22
|
+
},
|
|
23
|
+
honeycomb: {
|
|
24
|
+
title: "Honeycomb",
|
|
25
|
+
headline: "Honeycomb is the shared memory your agents keep across sessions.",
|
|
26
|
+
lines: [
|
|
27
|
+
"Captures what happens on every turn and recalls it in any harness, on any machine.",
|
|
28
|
+
"Mines reusable skills from real sessions and propagates them to your whole team automatically.",
|
|
29
|
+
],
|
|
30
|
+
recommended: false,
|
|
31
|
+
},
|
|
32
|
+
nectar: {
|
|
33
|
+
title: "Nectar",
|
|
34
|
+
headline: "Nectar gives every file in your repo an identity that survives refactors.",
|
|
35
|
+
lines: [
|
|
36
|
+
"Tracks files through renames and moves, so memory tied to an old path never goes stale.",
|
|
37
|
+
"Feeds Honeycomb's recall a fourth arm, so asking where the login logic lives actually works.",
|
|
38
|
+
],
|
|
39
|
+
recommended: false,
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* ob-AC-10, the npm-safety reassurance every install card carries, verbatim. Checkably true for
|
|
44
|
+
* all four packages (`@legioncodeinc/{honeycomb,doctor,hive,nectar}` each publish with npm Trusted
|
|
45
|
+
* Publishing OIDC provenance per the parent PRD's overview), so this never overstates the claim.
|
|
46
|
+
*/
|
|
47
|
+
export const NPM_SAFETY_COPY = "Installed straight from the public npm registry. Every package here is signed and provenance verified through npm Trusted Publishing (OIDC), so what installs is exactly what we published.";
|
|
48
|
+
/** ob-AC-7, shown when Doctor is deselected in the Advanced picker. */
|
|
49
|
+
export const DOCTOR_DESELECT_WARNING = "Without Doctor, nothing restarts your daemons after a crash or reboot.";
|
|
50
|
+
/**
|
|
51
|
+
* Resolve a product's brand mark URL. Honeycomb keeps its existing top-level, `assetBase`-relative
|
|
52
|
+
* route (`host.ts`'s `DASHBOARD_LOGO_PATH`, unchanged by this PRD); Doctor, Hive, and Nectar are
|
|
53
|
+
* served by the daemon agent at the new fixed `/assets/brand/<name>-mark.svg` route (see the task
|
|
54
|
+
* brief), independent of `assetBase`.
|
|
55
|
+
*/
|
|
56
|
+
export function productLogoUrl(product, assetBase) {
|
|
57
|
+
if (product === "honeycomb")
|
|
58
|
+
return `${assetBase}/honeycomb-memory-cluster.svg`;
|
|
59
|
+
return `/assets/brand/${product}-mark.svg`;
|
|
60
|
+
}
|
|
61
|
+
/** The install-stage vocabulary (ob-AC-9): a short human label per stage, never a percentage. */
|
|
62
|
+
export const INSTALL_STAGE_LABEL = {
|
|
63
|
+
resolving: "Resolving the package",
|
|
64
|
+
downloading: "Downloading from npm",
|
|
65
|
+
linking: "Linking the binary",
|
|
66
|
+
registering_service: "Registering the service",
|
|
67
|
+
completed: "Installed",
|
|
68
|
+
failed: "Installation failed",
|
|
69
|
+
};
|
|
70
|
+
//# sourceMappingURL=product-copy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"product-copy.js","sourceRoot":"","sources":["../../../../src/dashboard/web/onboarding/product-copy.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAcH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,YAAY,GAA4C;IACpE,MAAM,EAAE;QACP,KAAK,EAAE,QAAQ;QACf,QAAQ,EAAE,4DAA4D;QACtE,KAAK,EAAE;YACN,sGAAsG;YACtG,2EAA2E;SAC3E;QACD,WAAW,EAAE,IAAI;KACjB;IACD,SAAS,EAAE;QACV,KAAK,EAAE,WAAW;QAClB,QAAQ,EAAE,kEAAkE;QAC5E,KAAK,EAAE;YACN,oFAAoF;YACpF,gGAAgG;SAChG;QACD,WAAW,EAAE,KAAK;KAClB;IACD,MAAM,EAAE;QACP,KAAK,EAAE,QAAQ;QACf,QAAQ,EAAE,2EAA2E;QACrF,KAAK,EAAE;YACN,yFAAyF;YACzF,8FAA8F;SAC9F;QACD,WAAW,EAAE,KAAK;KAClB;CACD,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAC3B,6LAA6L,CAAC;AAE/L,uEAAuE;AACvE,MAAM,CAAC,MAAM,uBAAuB,GAAG,wEAAwE,CAAC;AAEhH;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,OAA0B,EAAE,SAAiB;IAC3E,IAAI,OAAO,KAAK,WAAW;QAAE,OAAO,GAAG,SAAS,+BAA+B,CAAC;IAChF,OAAO,iBAAiB,OAAO,WAAW,CAAC;AAC5C,CAAC;AAED,iGAAiG;AACjG,MAAM,CAAC,MAAM,mBAAmB,GAG5B;IACH,SAAS,EAAE,uBAAuB;IAClC,WAAW,EAAE,sBAAsB;IACnC,OAAO,EAAE,oBAAoB;IAC7B,mBAAmB,EAAE,yBAAyB;IAC9C,SAAS,EAAE,WAAW;IACtB,MAAM,EAAE,qBAAqB;CAC7B,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The install card's MINIMUM DWELL hook, PRD-009b ob-AC-11 (revised). The card advances as soon as
|
|
3
|
+
* the install actually completes, held only long enough for the completed state to visibly register
|
|
4
|
+
* (a sub-second flash-through would read as broken); a longer install simply holds the card until
|
|
5
|
+
* its own terminal state. The dwell timer NEVER masks a failure, this hook only ever gates the
|
|
6
|
+
* advance-on-SUCCESS path; a failed card renders its error immediately regardless of how much
|
|
7
|
+
* dwell time has elapsed (the caller never calls this hook's `ready` with a failure in mind).
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* The minimum time a card stays up after mount before a SUCCESSFUL install may advance. Short by
|
|
11
|
+
* design: the real install time drives the pace (originally ~30s per ob-AC-11, cut down because
|
|
12
|
+
* holding a finished install visibly idle reads as slowness, not polish). Overridable in tests.
|
|
13
|
+
*/
|
|
14
|
+
export declare const DEFAULT_MIN_DWELL_MS = 2000;
|
|
15
|
+
export interface UseInstallDwellOptions {
|
|
16
|
+
/** Called exactly once, after `ready` has been true for the remaining minimum-dwell duration. */
|
|
17
|
+
readonly onDwellSatisfied: () => void;
|
|
18
|
+
/** Overrides {@link DEFAULT_MIN_DWELL_MS} (a test injects a short window). */
|
|
19
|
+
readonly minDwellMs?: number;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* `ready` flips true once the install reaches its `completed` terminal state. The card's mount
|
|
23
|
+
* time is the dwell clock's start (installs begin the instant a card mounts), so a completion that
|
|
24
|
+
* lands at second 6 still holds the card until second 30; a completion that lands at second 40 has
|
|
25
|
+
* already satisfied the dwell and advances immediately.
|
|
26
|
+
*/
|
|
27
|
+
export declare function useInstallDwell(ready: boolean, options: UseInstallDwellOptions): void;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The install card's MINIMUM DWELL hook, PRD-009b ob-AC-11 (revised). The card advances as soon as
|
|
3
|
+
* the install actually completes, held only long enough for the completed state to visibly register
|
|
4
|
+
* (a sub-second flash-through would read as broken); a longer install simply holds the card until
|
|
5
|
+
* its own terminal state. The dwell timer NEVER masks a failure, this hook only ever gates the
|
|
6
|
+
* advance-on-SUCCESS path; a failed card renders its error immediately regardless of how much
|
|
7
|
+
* dwell time has elapsed (the caller never calls this hook's `ready` with a failure in mind).
|
|
8
|
+
*/
|
|
9
|
+
import React from "react";
|
|
10
|
+
/**
|
|
11
|
+
* The minimum time a card stays up after mount before a SUCCESSFUL install may advance. Short by
|
|
12
|
+
* design: the real install time drives the pace (originally ~30s per ob-AC-11, cut down because
|
|
13
|
+
* holding a finished install visibly idle reads as slowness, not polish). Overridable in tests.
|
|
14
|
+
*/
|
|
15
|
+
export const DEFAULT_MIN_DWELL_MS = 2_000;
|
|
16
|
+
/**
|
|
17
|
+
* `ready` flips true once the install reaches its `completed` terminal state. The card's mount
|
|
18
|
+
* time is the dwell clock's start (installs begin the instant a card mounts), so a completion that
|
|
19
|
+
* lands at second 6 still holds the card until second 30; a completion that lands at second 40 has
|
|
20
|
+
* already satisfied the dwell and advances immediately.
|
|
21
|
+
*/
|
|
22
|
+
export function useInstallDwell(ready, options) {
|
|
23
|
+
const { minDwellMs = DEFAULT_MIN_DWELL_MS } = options;
|
|
24
|
+
const startedAtRef = React.useRef(Date.now());
|
|
25
|
+
const firedRef = React.useRef(false);
|
|
26
|
+
// Read through a ref so a caller passing a fresh `onDwellSatisfied` closure every render never
|
|
27
|
+
// re-triggers the scheduling effect below (only `ready`/`minDwellMs` should do that).
|
|
28
|
+
const onDwellSatisfiedRef = React.useRef(options.onDwellSatisfied);
|
|
29
|
+
onDwellSatisfiedRef.current = options.onDwellSatisfied;
|
|
30
|
+
React.useEffect(() => {
|
|
31
|
+
if (!ready || firedRef.current)
|
|
32
|
+
return;
|
|
33
|
+
const elapsed = Date.now() - startedAtRef.current;
|
|
34
|
+
const remaining = Math.max(0, minDwellMs - elapsed);
|
|
35
|
+
const id = setTimeout(() => {
|
|
36
|
+
firedRef.current = true;
|
|
37
|
+
onDwellSatisfiedRef.current();
|
|
38
|
+
}, remaining);
|
|
39
|
+
return () => clearTimeout(id);
|
|
40
|
+
}, [ready, minDwellMs]);
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=use-install-dwell.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-install-dwell.js","sourceRoot":"","sources":["../../../../src/dashboard/web/onboarding/use-install-dwell.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B;;;;GAIG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,KAAK,CAAC;AAS1C;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,KAAc,EAAE,OAA+B;IAC9E,MAAM,EAAE,UAAU,GAAG,oBAAoB,EAAE,GAAG,OAAO,CAAC;IACtD,MAAM,YAAY,GAAG,KAAK,CAAC,MAAM,CAAS,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IACtD,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAErC,+FAA+F;IAC/F,sFAAsF;IACtF,MAAM,mBAAmB,GAAG,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACnE,mBAAmB,CAAC,OAAO,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAEvD,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACpB,IAAI,CAAC,KAAK,IAAI,QAAQ,CAAC,OAAO;YAAE,OAAO;QACvC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,YAAY,CAAC,OAAO,CAAC;QAClD,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,CAAC;QACpD,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,EAAE;YAC1B,QAAQ,CAAC,OAAO,GAAG,IAAI,CAAC;YACxB,mBAAmB,CAAC,OAAO,EAAE,CAAC;QAC/B,CAAC,EAAE,SAAS,CAAC,CAAC;QACd,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;IAC/B,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC;AACzB,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one-time onboarding TOKEN hook, PRD-009b implementation note. The bootstrap mints the token
|
|
3
|
+
* and hands it to the browser via `/onboarding?t=...`; this hook reads it ONCE on mount, keeps it
|
|
4
|
+
* in React state (memory only) for the page's lifetime, and immediately strips it from the visible
|
|
5
|
+
* URL via `history.replaceState` so casual screen-sharing never exposes it. The read+strip is a side
|
|
6
|
+
* effect, so it runs inside `useEffect` (not a `useState` lazy initializer), render must stay pure.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Read `?t=` once, strip it from the visible URL, and return the token. Tri-state so the caller can
|
|
10
|
+
* distinguish "still resolving" from "resolved, absent": `null` until the mount effect has run,
|
|
11
|
+
* `""` when the URL carried no token (the caller shows recovery guidance rather than spinning
|
|
12
|
+
* forever), and the token string otherwise.
|
|
13
|
+
*/
|
|
14
|
+
export declare function useOnboardingToken(): string | null;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one-time onboarding TOKEN hook, PRD-009b implementation note. The bootstrap mints the token
|
|
3
|
+
* and hands it to the browser via `/onboarding?t=...`; this hook reads it ONCE on mount, keeps it
|
|
4
|
+
* in React state (memory only) for the page's lifetime, and immediately strips it from the visible
|
|
5
|
+
* URL via `history.replaceState` so casual screen-sharing never exposes it. The read+strip is a side
|
|
6
|
+
* effect, so it runs inside `useEffect` (not a `useState` lazy initializer), render must stay pure.
|
|
7
|
+
*/
|
|
8
|
+
import React from "react";
|
|
9
|
+
const TOKEN_QUERY_PARAM = "t";
|
|
10
|
+
/**
|
|
11
|
+
* Read `?t=` once, strip it from the visible URL, and return the token. Tri-state so the caller can
|
|
12
|
+
* distinguish "still resolving" from "resolved, absent": `null` until the mount effect has run,
|
|
13
|
+
* `""` when the URL carried no token (the caller shows recovery guidance rather than spinning
|
|
14
|
+
* forever), and the token string otherwise.
|
|
15
|
+
*/
|
|
16
|
+
export function useOnboardingToken() {
|
|
17
|
+
const [token, setToken] = React.useState(null);
|
|
18
|
+
React.useEffect(() => {
|
|
19
|
+
if (typeof window === "undefined")
|
|
20
|
+
return;
|
|
21
|
+
const params = new URLSearchParams(window.location.search);
|
|
22
|
+
const fromUrl = params.get(TOKEN_QUERY_PARAM);
|
|
23
|
+
if (fromUrl === null || fromUrl === "") {
|
|
24
|
+
setToken("");
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
setToken(fromUrl);
|
|
28
|
+
// Move it out of the visible URL (PRD implementation note), the token stays in memory only.
|
|
29
|
+
try {
|
|
30
|
+
const url = new URL(window.location.href);
|
|
31
|
+
url.searchParams.delete(TOKEN_QUERY_PARAM);
|
|
32
|
+
window.history.replaceState(null, "", `${url.pathname}${url.search}${url.hash}`);
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
// A `history` API failure (e.g. an unusual embedding context) must never block the flow ,
|
|
36
|
+
// the token still landed in state; only the cosmetic URL scrub is skipped.
|
|
37
|
+
}
|
|
38
|
+
}, []);
|
|
39
|
+
return token;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=use-onboarding-token.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-onboarding-token.js","sourceRoot":"","sources":["../../../../src/dashboard/web/onboarding/use-onboarding-token.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,iBAAiB,GAAG,GAAY,CAAC;AAEvC;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB;IACjC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAgB,IAAI,CAAC,CAAC;IAE9D,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACpB,IAAI,OAAO,MAAM,KAAK,WAAW;YAAE,OAAO;QAC1C,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC3D,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;QAC9C,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,EAAE,EAAE,CAAC;YACxC,QAAQ,CAAC,EAAE,CAAC,CAAC;YACb,OAAO;QACR,CAAC;QAED,QAAQ,CAAC,OAAO,CAAC,CAAC;QAElB,4FAA4F;QAC5F,IAAI,CAAC;YACJ,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;YAC1C,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;YAC3C,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,IAAI,EAAE,EAAE,EAAE,GAAG,GAAG,CAAC,QAAQ,GAAG,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;QAClF,CAAC;QAAC,MAAM,CAAC;YACR,0FAA0F;YAC1F,2EAA2E;QAC5E,CAAC;IACF,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,KAAK,CAAC;AACd,CAAC"}
|