Onboarding: keep TUI flow exclusive
parent
157d6d2db7
commit
58d5b39c9a
|
|
@ -16,6 +16,8 @@ Docs: https://docs.openclaw.ai
|
||||||
|
|
||||||
### Fixes
|
### Fixes
|
||||||
|
|
||||||
|
- Onboarding: keep TUI flow exclusive (skip completion prompt + background Web UI seed).
|
||||||
|
- TUI: block onboarding output while TUI is active and restore terminal state on exit.
|
||||||
- Agents: repair malformed tool calls and session transcripts. (#7473) Thanks @justinhuangcode.
|
- Agents: repair malformed tool calls and session transcripts. (#7473) Thanks @justinhuangcode.
|
||||||
- fix(agents): validate AbortSignal instances before calling AbortSignal.any() (#7277) (thanks @Elarwei001)
|
- fix(agents): validate AbortSignal instances before calling AbortSignal.any() (#7277) (thanks @Elarwei001)
|
||||||
- fix(webchat): respect user scroll position during streaming and refresh (#7226) (thanks @marcomarandiz)
|
- fix(webchat): respect user scroll position during streaming and refresh (#7226) (thanks @marcomarandiz)
|
||||||
|
|
|
||||||
|
|
@ -662,4 +662,10 @@ export async function runTui(opts: TuiOptions) {
|
||||||
updateFooter();
|
updateFooter();
|
||||||
tui.start();
|
tui.start();
|
||||||
client.start();
|
client.start();
|
||||||
|
await new Promise<void>((resolve) => {
|
||||||
|
const finish = () => resolve();
|
||||||
|
process.once("exit", finish);
|
||||||
|
process.once("SIGINT", finish);
|
||||||
|
process.once("SIGTERM", finish);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,6 @@ import {
|
||||||
detectBrowserOpenSupport,
|
detectBrowserOpenSupport,
|
||||||
formatControlUiSshHint,
|
formatControlUiSshHint,
|
||||||
openUrl,
|
openUrl,
|
||||||
openUrlInBackground,
|
|
||||||
probeGatewayReachable,
|
probeGatewayReachable,
|
||||||
waitForGatewayReachable,
|
waitForGatewayReachable,
|
||||||
resolveControlUiLinks,
|
resolveControlUiLinks,
|
||||||
|
|
@ -29,6 +28,7 @@ import {
|
||||||
import { resolveGatewayService } from "../daemon/service.js";
|
import { resolveGatewayService } from "../daemon/service.js";
|
||||||
import { isSystemdUserServiceAvailable } from "../daemon/systemd.js";
|
import { isSystemdUserServiceAvailable } from "../daemon/systemd.js";
|
||||||
import { ensureControlUiAssetsBuilt } from "../infra/control-ui-assets.js";
|
import { ensureControlUiAssetsBuilt } from "../infra/control-ui-assets.js";
|
||||||
|
import { restoreTerminalState } from "../terminal/restore.js";
|
||||||
import { runTui } from "../tui/tui.js";
|
import { runTui } from "../tui/tui.js";
|
||||||
import { resolveUserPath } from "../utils.js";
|
import { resolveUserPath } from "../utils.js";
|
||||||
|
|
||||||
|
|
@ -43,7 +43,9 @@ type FinalizeOnboardingOptions = {
|
||||||
runtime: RuntimeEnv;
|
runtime: RuntimeEnv;
|
||||||
};
|
};
|
||||||
|
|
||||||
export async function finalizeOnboardingWizard(options: FinalizeOnboardingOptions) {
|
export async function finalizeOnboardingWizard(
|
||||||
|
options: FinalizeOnboardingOptions,
|
||||||
|
): Promise<{ launchedTui: boolean }> {
|
||||||
const { flow, opts, baseConfig, nextConfig, settings, prompter, runtime } = options;
|
const { flow, opts, baseConfig, nextConfig, settings, prompter, runtime } = options;
|
||||||
|
|
||||||
const withWizardProgress = async <T>(
|
const withWizardProgress = async <T>(
|
||||||
|
|
@ -286,6 +288,7 @@ export async function finalizeOnboardingWizard(options: FinalizeOnboardingOption
|
||||||
let controlUiOpenHint: string | undefined;
|
let controlUiOpenHint: string | undefined;
|
||||||
let seededInBackground = false;
|
let seededInBackground = false;
|
||||||
let hatchChoice: "tui" | "web" | "later" | null = null;
|
let hatchChoice: "tui" | "web" | "later" | null = null;
|
||||||
|
let launchedTui = false;
|
||||||
|
|
||||||
if (!opts.skipUi && gatewayProbe.ok) {
|
if (!opts.skipUi && gatewayProbe.ok) {
|
||||||
if (hasBootstrap) {
|
if (hasBootstrap) {
|
||||||
|
|
@ -321,6 +324,7 @@ export async function finalizeOnboardingWizard(options: FinalizeOnboardingOption
|
||||||
});
|
});
|
||||||
|
|
||||||
if (hatchChoice === "tui") {
|
if (hatchChoice === "tui") {
|
||||||
|
restoreTerminalState("pre-onboarding tui");
|
||||||
await runTui({
|
await runTui({
|
||||||
url: links.wsUrl,
|
url: links.wsUrl,
|
||||||
token: settings.authMode === "token" ? settings.gatewayToken : undefined,
|
token: settings.authMode === "token" ? settings.gatewayToken : undefined,
|
||||||
|
|
@ -329,17 +333,7 @@ export async function finalizeOnboardingWizard(options: FinalizeOnboardingOption
|
||||||
deliver: false,
|
deliver: false,
|
||||||
message: hasBootstrap ? "Wake up, my friend!" : undefined,
|
message: hasBootstrap ? "Wake up, my friend!" : undefined,
|
||||||
});
|
});
|
||||||
if (settings.authMode === "token" && settings.gatewayToken) {
|
launchedTui = true;
|
||||||
seededInBackground = await openUrlInBackground(authedUrl);
|
|
||||||
}
|
|
||||||
if (seededInBackground) {
|
|
||||||
await prompter.note(
|
|
||||||
`Web UI seeded in the background. Open later with: ${formatCliCommand(
|
|
||||||
"openclaw dashboard --no-open",
|
|
||||||
)}`,
|
|
||||||
"Web UI",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else if (hatchChoice === "web") {
|
} else if (hatchChoice === "web") {
|
||||||
const browserSupport = await detectBrowserOpenSupport();
|
const browserSupport = await detectBrowserOpenSupport();
|
||||||
if (browserSupport.ok) {
|
if (browserSupport.ok) {
|
||||||
|
|
@ -471,4 +465,6 @@ export async function finalizeOnboardingWizard(options: FinalizeOnboardingOption
|
||||||
? "Onboarding complete. Web UI seeded in the background; open it anytime with the tokenized link above."
|
? "Onboarding complete. Web UI seeded in the background; open it anytime with the tokenized link above."
|
||||||
: "Onboarding complete. Use the tokenized dashboard link above to control OpenClaw.",
|
: "Onboarding complete. Use the tokenized dashboard link above to control OpenClaw.",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
return { launchedTui };
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -455,7 +455,7 @@ export async function runOnboardingWizard(
|
||||||
nextConfig = applyWizardMetadata(nextConfig, { command: "onboard", mode });
|
nextConfig = applyWizardMetadata(nextConfig, { command: "onboard", mode });
|
||||||
await writeConfigFile(nextConfig);
|
await writeConfigFile(nextConfig);
|
||||||
|
|
||||||
await finalizeOnboardingWizard({
|
const { launchedTui } = await finalizeOnboardingWizard({
|
||||||
flow,
|
flow,
|
||||||
opts,
|
opts,
|
||||||
baseConfig,
|
baseConfig,
|
||||||
|
|
@ -465,6 +465,9 @@ export async function runOnboardingWizard(
|
||||||
prompter,
|
prompter,
|
||||||
runtime,
|
runtime,
|
||||||
});
|
});
|
||||||
|
if (launchedTui) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const installShell = await prompter.confirm({
|
const installShell = await prompter.confirm({
|
||||||
message: "Install shell completion script?",
|
message: "Install shell completion script?",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue