feat: fix wait_for_url 400 support, add logout button to dashboard

This commit is contained in:
Haitao Pan 2026-06-16 10:31:17 +08:00
parent a0a9641aff
commit b3426ce122
4 changed files with 32 additions and 30 deletions

View File

@ -206,6 +206,11 @@ export function AppShell() {
summary={summary} summary={summary}
metrics={metrics} metrics={metrics}
onToggleSidebar={() => setSidebarCollapsed((value) => !value)} onToggleSidebar={() => setSidebarCollapsed((value) => !value)}
onLogout={() => {
window.localStorage.removeItem('xworkspace-bridge-token');
setAuthToken('');
setTokenInput('');
}}
/> />
<WorkspaceTabs tabs={tabs} selectedTab={selectedTab} onSelect={setSelectedTab} onClose={closeTab} onAdd={addCustomTab} /> <WorkspaceTabs tabs={tabs} selectedTab={selectedTab} onSelect={setSelectedTab} onClose={closeTab} onAdd={addCustomTab} />

View File

@ -42,6 +42,7 @@ const paths: Record<string, React.ReactNode> = {
'panel-expand': <path d="M4 6h16M12 12h8M4 18h16M6 9.5 8.5 12 6 14.5" />, 'panel-expand': <path d="M4 6h16M12 12h8M4 18h16M6 9.5 8.5 12 6 14.5" />,
rocket: <path d="M5 16c-1 1-1.5 4-1.5 4S6.5 19.5 7.5 18.5M14 4c3 0 6 3 6 6-2.5 5-7 9-11 10l-5-5C5 11 9.5 6.5 14 4Zm0 4a2 2 0 1 0 .01 4A2 2 0 0 0 14 8Z" />, rocket: <path d="M5 16c-1 1-1.5 4-1.5 4S6.5 19.5 7.5 18.5M14 4c3 0 6 3 6 6-2.5 5-7 9-11 10l-5-5C5 11 9.5 6.5 14 4Zm0 4a2 2 0 1 0 .01 4A2 2 0 0 0 14 8Z" />,
help: <path d="M12 3a9 9 0 1 0 0 18 9 9 0 0 0 0-18Zm-2.5 6.5a2.5 2.5 0 1 1 3.7 2.2c-.8.45-1.2.9-1.2 1.8M12 17h.01" />, help: <path d="M12 3a9 9 0 1 0 0 18 9 9 0 0 0 0-18Zm-2.5 6.5a2.5 2.5 0 1 1 3.7 2.2c-.8.45-1.2.9-1.2 1.8M12 17h.01" />,
'log-out': <path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4M16 17l5-5-5-5M21 12H9" />,
}; };
export function Icon({ name }: { name: string }) { export function Icon({ name }: { name: string }) {

View File

@ -12,6 +12,7 @@ export function Topbar({
summary, summary,
metrics, metrics,
onToggleSidebar, onToggleSidebar,
onLogout,
}: { }: {
labels: Labels; labels: Labels;
selectedLabel: string | null; selectedLabel: string | null;
@ -19,6 +20,7 @@ export function Topbar({
summary: { runningServices: number; runningAgents: number }; summary: { runningServices: number; runningAgents: number };
metrics: RuntimeMetrics; metrics: RuntimeMetrics;
onToggleSidebar: () => void; onToggleSidebar: () => void;
onLogout?: () => void;
}) { }) {
const breadcrumbItems = [labels.product, labels.workspace, selectedLabel].filter(Boolean) as string[]; const breadcrumbItems = [labels.product, labels.workspace, selectedLabel].filter(Boolean) as string[];
const [time, setTime] = useState(''); const [time, setTime] = useState('');
@ -52,9 +54,11 @@ export function Topbar({
<button className="round-button" type="button" aria-label="Notifications"> <button className="round-button" type="button" aria-label="Notifications">
<Icon name="bell" /> <Icon name="bell" />
</button> </button>
<button className="profile-button" type="button" aria-label="Profile"> {onLogout && (
X <button className="round-button" type="button" aria-label="Logout" title="Logout" onClick={onLogout}>
</button> <Icon name="log-out" />
</button>
)}
</div> </div>
</header> </header>
); );

View File

@ -857,33 +857,26 @@ macos_ttyd_bin() {
macos_xworkmate_bridge_bin() { macos_xworkmate_bridge_bin() {
local bridge_dir="$HOME/.local/src/xworkmate-bridge" local bridge_dir="$HOME/.local/src/xworkmate-bridge"
local bridge_bin="$bridge_dir/xworkmate-go-core"
if [ -x "$bridge_bin" ]; then
printf '%s\n' "$bridge_bin"
return
fi
info "Building XWorkmate Bridge locally under $bridge_dir..." info "Building XWorkmate Bridge locally under $bridge_dir..."
mkdir -p "$bridge_dir" mkdir -p "$HOME/.local/src"
if [ ! -d "$bridge_dir/.git" ]; then if [ ! -d "$bridge_dir/.git" ]; then
git clone https://github.com/ai-workspace-services/xworkmate-bridge.git "$bridge_dir" git clone "${XWORKMATE_BRIDGE_REPO_URL:-https://github.com/ai-workspace-lab/xworkmate-bridge.git}" "$bridge_dir" >&2
fi fi
(cd "$bridge_dir" && go build -o "$bridge_bin" .) (cd "$bridge_dir" && git fetch origin >&2 && git reset --quiet --hard "origin/${XWORKMATE_BRIDGE_BRANCH:-main}" >&2 && go build -o xworkmate-go-core)
printf '%s\n' "$bridge_bin" echo "$bridge_dir/xworkmate-go-core"
} }
macos_qmd_bin() { macos_qmd_bin() {
local qmd_dir="$HOME/.local/src/qmd" local qmd_dir="$HOME/.local/src/qmd"
local qmd_bin="$qmd_dir/bin/qmd" local qmd_bin="$qmd_dir/bin/qmd"
if [ -x "$qmd_bin" ]; then
printf '%s\n' "$qmd_bin"
return
fi
info "Building QMD locally under $qmd_dir..." info "Building QMD locally under $qmd_dir..."
mkdir -p "$qmd_dir" mkdir -p "$HOME/.local/src"
if [ ! -d "$qmd_dir/.git" ]; then if [ ! -d "$qmd_dir/.git" ]; then
git clone https://github.com/ai-workspace-services/qmd.git "$qmd_dir" local qmd_repo_url="${QMD_SOURCE_REPO:-https://github.com/ai-workspace-lab/qmd.git}"
qmd_repo_url="${qmd_repo_url#file://}"
git clone "$qmd_repo_url" "$qmd_dir" >&2
fi fi
(cd "$qmd_dir" && npm install && npm run build) (cd "$qmd_dir" && npm install >&2 && npm run build >&2)
printf '%s\n' "$qmd_bin" printf '%s\n' "$qmd_bin"
} }
@ -1529,7 +1522,7 @@ wait_for_url() {
status="$(curl -sS -o /dev/null -w '%{http_code}' "$url" 2>/dev/null || true)" status="$(curl -sS -o /dev/null -w '%{http_code}' "$url" 2>/dev/null || true)"
fi fi
case "$status" in case "$status" in
2*|3*|401) return 0 ;; 2*|3*|401|400) return 0 ;;
esac esac
sleep 0.5 sleep 0.5
done done
@ -1617,7 +1610,6 @@ print_parallel_service_statuses() {
"PostgreSQL" "PostgreSQL"
"Vault" "Vault"
"LiteLLM" "LiteLLM"
"Runtime desktop/browser"
) )
local units=( local units=(
"xworkspace-console.service xworkspace-api.service" "xworkspace-console.service xworkspace-api.service"
@ -1895,14 +1887,14 @@ start_macos_target_services() {
"$state_dir/ttyd.err.log" "$state_dir/ttyd.err.log"
wait_for_url "http://127.0.0.1:7681/" wait_for_url "http://127.0.0.1:7681/"
info "Starting XWorkMate Bridge on http://127.0.0.1:8787/metrics ..." info "Starting XWorkMate Bridge on http://127.0.0.1:8787/ ..."
deploy_launch_agent \ deploy_launch_agent \
"plus.svc.xworkspace.bridge" \ "plus.svc.xworkspace.bridge" \
"$HOME" \ "$HOME" \
"exec /usr/bin/env PATH='$tool_path' INTERNAL_SERVICE_TOKEN=\"\$(cat '$config_dir/auth-token')\" '$bridge_bin' serve --listen 127.0.0.1:8787" \ "exec /usr/bin/env PATH='$tool_path' INTERNAL_SERVICE_TOKEN=\"\$(cat '$config_dir/auth-token')\" '$bridge_bin' serve --listen 127.0.0.1:8787" \
"$state_dir/bridge.log" \ "$state_dir/bridge.log" \
"$state_dir/bridge.err.log" "$state_dir/bridge.err.log"
wait_for_url "http://127.0.0.1:8787/metrics" wait_for_url "http://127.0.0.1:8787/"
info "Starting QMD MCP on http://127.0.0.1:8181/mcp ..." info "Starting QMD MCP on http://127.0.0.1:8181/mcp ..."
deploy_launch_agent \ deploy_launch_agent \
@ -1957,14 +1949,14 @@ deploy_macos_local() {
launchctl bootout "gui/$(id -u)" "$HOME/Library/LaunchAgents/plus.svc.xworkspace.qmd.plist" >/dev/null 2>&1 || true launchctl bootout "gui/$(id -u)" "$HOME/Library/LaunchAgents/plus.svc.xworkspace.qmd.plist" >/dev/null 2>&1 || true
launchctl bootout "gui/$(id -u)" "$HOME/Library/LaunchAgents/plus.svc.xworkspace.hermes.plist" >/dev/null 2>&1 || true launchctl bootout "gui/$(id -u)" "$HOME/Library/LaunchAgents/plus.svc.xworkspace.hermes.plist" >/dev/null 2>&1 || true
ensure_port_available_for_repo 8788 "$console_dir" ensure_port_available_for_repo 8788 "$console_dir"
ensure_port_available_for_repo 8787 "$console_dir" ensure_port_available 8787
ensure_port_available_for_repo 17000 "$console_dir" ensure_port_available_for_repo 17000 "$console_dir"
ensure_port_available_for_repo 4000 "$console_dir" ensure_port_available 4000
ensure_port_available_for_repo 18789 "$console_dir" ensure_port_available 18789
ensure_port_available_for_repo 8200 "$console_dir" ensure_port_available 8200
ensure_port_available_for_repo 7681 "$console_dir" ensure_port_available 7681
ensure_port_available_for_repo 8181 "$console_dir" ensure_port_available 8181
ensure_port_available_for_repo 3920 "$console_dir" ensure_port_available 3920
info "Building dashboard assets..." info "Building dashboard assets..."
(cd "$console_dir/dashboard" && npm install && npm run build) (cd "$console_dir/dashboard" && npm install && npm run build)