fix: improve onboarding auth UX

This commit is contained in:
Peter Steinberger
2026-01-02 15:03:38 +01:00
parent f57f892409
commit ad9d6f616d
5 changed files with 37 additions and 7 deletions

View File

@@ -46,6 +46,8 @@
### Fixes ### Fixes
- Chat UI: keep the chat scrolled to the latest message after switching sessions. - Chat UI: keep the chat scrolled to the latest message after switching sessions.
- CLI onboarding: persist gateway token in config so local CLI auth works; recommend auth Off unless you need multi-machine access. - CLI onboarding: persist gateway token in config so local CLI auth works; recommend auth Off unless you need multi-machine access.
- Control UI: accept a `?token=` URL param to auto-fill Gateway auth; onboarding now opens the dashboard with token auth when configured.
- Agent prompt: remove hardcoded user name in system prompt example.
- Chat UI: add extra top padding before the first message bubble in Web Chat (macOS/iOS/Android). - Chat UI: add extra top padding before the first message bubble in Web Chat (macOS/iOS/Android).
- Control UI: refine Web Chat session selector styling (chevron spacing + background). - Control UI: refine Web Chat session selector styling (chevron spacing + background).
- WebChat: stream live updates for sessions even when runs start outside the chat UI. - WebChat: stream live updates for sessions even when runs start outside the chat UI.

View File

@@ -10,7 +10,7 @@ describe("buildAgentSystemPromptAppend", () => {
expect(prompt).toContain("## User Identity"); expect(prompt).toContain("## User Identity");
expect(prompt).toContain( expect(prompt).toContain(
"Owner numbers: +123, +456. Treat messages from these numbers as the user (Peter).", "Owner numbers: +123, +456. Treat messages from these numbers as the user.",
); );
}); });

View File

@@ -25,7 +25,7 @@ export function buildAgentSystemPromptAppend(params: {
.filter(Boolean); .filter(Boolean);
const ownerLine = const ownerLine =
ownerNumbers.length > 0 ownerNumbers.length > 0
? `Owner numbers: ${ownerNumbers.join(", ")}. Treat messages from these numbers as the user (Peter).` ? `Owner numbers: ${ownerNumbers.join(", ")}. Treat messages from these numbers as the user.`
: undefined; : undefined;
const reasoningHint = params.reasoningTagHint const reasoningHint = params.reasoningTagHint
? [ ? [
@@ -36,7 +36,7 @@ export function buildAgentSystemPromptAppend(params: {
"Only text inside <final> is shown to the user; everything else is discarded and never seen by the user.", "Only text inside <final> is shown to the user; everything else is discarded and never seen by the user.",
"Example:", "Example:",
"<think>Short internal reasoning.</think>", "<think>Short internal reasoning.</think>",
"<final>Hey Peter! What would you like to do next?</final>", "<final>Hey there! What would you like to do next?</final>",
].join(" ") ].join(" ")
: undefined; : undefined;
const runtimeInfo = params.runtimeInfo; const runtimeInfo = params.runtimeInfo;

View File

@@ -495,9 +495,18 @@ export async function runInteractiveOnboarding(
note( note(
(() => { (() => {
const links = resolveControlUiLinks({ bind, port }); const links = resolveControlUiLinks({ bind, port });
return [`Web UI: ${links.httpUrl}`, `Gateway WS: ${links.wsUrl}`].join( const tokenParam =
"\n", authMode === "token" && gatewayToken
); ? `?token=${encodeURIComponent(gatewayToken)}`
: "";
const authedUrl = `${links.httpUrl}${tokenParam}`;
return [
`Web UI: ${links.httpUrl}`,
tokenParam ? `Web UI (with token): ${authedUrl}` : undefined,
`Gateway WS: ${links.wsUrl}`,
]
.filter(Boolean)
.join("\n");
})(), })(),
"Control UI", "Control UI",
); );
@@ -511,7 +520,11 @@ export async function runInteractiveOnboarding(
); );
if (wantsOpen) { if (wantsOpen) {
const links = resolveControlUiLinks({ bind, port }); const links = resolveControlUiLinks({ bind, port });
await openUrl(links.httpUrl); const tokenParam =
authMode === "token" && gatewayToken
? `?token=${encodeURIComponent(gatewayToken)}`
: "";
await openUrl(`${links.httpUrl}${tokenParam}`);
} }
outro("Onboarding complete."); outro("Onboarding complete.");

View File

@@ -186,6 +186,7 @@ export class ClawdisApp extends LitElement {
this.syncThemeWithSettings(); this.syncThemeWithSettings();
this.attachThemeListener(); this.attachThemeListener();
window.addEventListener("popstate", this.popStateHandler); window.addEventListener("popstate", this.popStateHandler);
this.applySettingsFromUrl();
this.connect(); this.connect();
this.startNodesPolling(); this.startNodesPolling();
} }
@@ -334,6 +335,20 @@ export class ClawdisApp extends LitElement {
} }
} }
private applySettingsFromUrl() {
if (!window.location.search) return;
const params = new URLSearchParams(window.location.search);
const token = params.get("token")?.trim();
if (!token) return;
if (!this.settings.token) {
this.applySettings({ ...this.settings, token });
}
params.delete("token");
const url = new URL(window.location.href);
url.search = params.toString();
window.history.replaceState({}, "", url.toString());
}
setTab(next: Tab) { setTab(next: Tab) {
if (this.tab !== next) this.tab = next; if (this.tab !== next) this.tab = next;
void this.refreshActiveTab(); void this.refreshActiveTab();