fix(mac): redesign onboarding remote-gateway detail section (#114494)

* fix(mac): redesign onboarding remote-gateway detail section

* chore(i18n): refresh native inventory for onboarding redesign
This commit is contained in:
Peter Steinberger
2026-07-27 06:36:02 -04:00
committed by GitHub
parent c8ebf57731
commit 981b4cc3fe
2 changed files with 346 additions and 297 deletions
+193 -185
View File
@@ -35427,7 +35427,7 @@
},
{
"kind": "ui-call",
"line": 132,
"line": 131,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Set up later",
"surface": "apple",
@@ -35435,7 +35435,7 @@
},
{
"kind": "ui-modifier",
"line": 138,
"line": 137,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Skip Gateway setup for now; pick Local or Remote later in Settings → General.",
"surface": "apple",
@@ -35443,7 +35443,7 @@
},
{
"kind": "ui-call",
"line": 142,
"line": 141,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "OK — OpenClaw wont start anything yet. Pick Local or Remote later in Settings → General.",
"surface": "apple",
@@ -35451,7 +35451,7 @@
},
{
"kind": "conditional-branch",
"line": 181,
"line": 180,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Existing gateway detected",
"surface": "apple",
@@ -35459,7 +35459,7 @@
},
{
"kind": "conditional-branch",
"line": 182,
"line": 181,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Port \\(probe.port) already in use",
"surface": "apple",
@@ -35467,7 +35467,7 @@
},
{
"kind": "conditional-branch",
"line": 183,
"line": 182,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": " (\\(probe.command) pid \\(probe.pid))",
"surface": "apple",
@@ -35475,7 +35475,7 @@
},
{
"kind": "conditional-branch",
"line": 191,
"line": 190,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "1 gateway found on your network — click to choose it.",
"surface": "apple",
@@ -35483,7 +35483,7 @@
},
{
"kind": "conditional-branch",
"line": 192,
"line": 191,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "\\(count) gateways found on your network — click to choose one.",
"surface": "apple",
@@ -35491,7 +35491,7 @@
},
{
"kind": "ui-call",
"line": 206,
"line": 205,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "No gateways found on your network yet.",
"surface": "apple",
@@ -35499,7 +35499,7 @@
},
{
"kind": "ui-call",
"line": 209,
"line": 208,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Look again",
"surface": "apple",
@@ -35507,143 +35507,23 @@
},
{
"kind": "ui-modifier",
"line": 214,
"line": 213,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Retry discovery (Bonjour + Tailscale DNS-SD).",
"surface": "apple",
"id": "native.apple.e39798604090ef9c"
},
{
"kind": "conditional-branch",
"kind": "ui-call",
"line": 242,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Advanced…",
"surface": "apple",
"id": "native.apple.94575e6937b47f7b"
},
{
"kind": "conditional-branch",
"line": 242,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Hide Advanced",
"surface": "apple",
"id": "native.apple.22947c17e44f76af"
},
{
"kind": "ui-call",
"line": 262,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Transport",
"surface": "apple",
"id": "native.apple.7881cec64b177026"
},
{
"kind": "ui-call",
"line": 263,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "SSH tunnel",
"surface": "apple",
"id": "native.apple.8413b40cd91c9a19"
},
{
"kind": "ui-call",
"line": 264,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Direct (ws/wss)",
"surface": "apple",
"id": "native.apple.915c50965d971bb4"
},
{
"kind": "ui-call",
"line": 271,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Gateway URL",
"surface": "apple",
"id": "native.apple.9c90f7bc1b9564b1"
},
{
"kind": "ui-call",
"line": 274,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "wss://gateway.example.ts.net",
"surface": "apple",
"id": "native.apple.ba96e44d673d04d3"
},
{
"kind": "ui-call",
"line": 281,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "SSH target",
"surface": "apple",
"id": "native.apple.a193ae2a5ff9decd"
},
{
"kind": "ui-call",
"line": 301,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Identity file",
"surface": "apple",
"id": "native.apple.ecf41ca39add6b84"
},
{
"kind": "ui-call",
"line": 304,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "/Users/you/.ssh/id_ed25519",
"surface": "apple",
"id": "native.apple.ef96d6a2a48a4c54"
},
{
"kind": "ui-call",
"line": 309,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Project root",
"surface": "apple",
"id": "native.apple.0ef039b18340a2e1"
},
{
"kind": "ui-call",
"line": 312,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "/home/you/Projects/openclaw",
"surface": "apple",
"id": "native.apple.dca75ab0dd73f0a4"
},
{
"kind": "ui-call",
"line": 317,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "CLI path",
"surface": "apple",
"id": "native.apple.6998a7754dea6eb1"
},
{
"kind": "ui-call",
"line": 320,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "/Applications/OpenClaw.app/.../openclaw",
"surface": "apple",
"id": "native.apple.5a3f4f943c8ee86a"
},
{
"kind": "conditional-branch",
"line": 330,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Tip: use Tailscale Serve so the gateway has a valid HTTPS cert.",
"surface": "apple",
"id": "native.apple.56e9b0831ec1eded"
},
{
"kind": "conditional-branch",
"line": 331,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Tip: keep Tailscale enabled so your gateway stays reachable.",
"surface": "apple",
"id": "native.apple.ab88df30f426b434"
},
{
"kind": "ui-call",
"line": 446,
"line": 362,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Remote connection",
"surface": "apple",
@@ -35651,23 +35531,39 @@
},
{
"kind": "ui-call",
"line": 448,
"line": 364,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Checks the real remote websocket and auth handshake.",
"source": "Verify OpenClaw can reach this gateway.",
"surface": "apple",
"id": "native.apple.bee162bb681696a3"
"id": "native.apple.f6332654911cb2e2"
},
{
"kind": "ui-call",
"line": 461,
"line": 377,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Check connection",
"surface": "apple",
"id": "native.apple.6e5d3a3c3022e8c8"
},
{
"kind": "conditional-branch",
"line": 419,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Advanced options",
"surface": "apple",
"id": "native.apple.23254b5b9707c581"
},
{
"kind": "conditional-branch",
"line": 419,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Hide advanced options",
"surface": "apple",
"id": "native.apple.dfc5606a4813ecfc"
},
{
"kind": "ui-call",
"line": 491,
"line": 438,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Gateway token",
"surface": "apple",
@@ -35675,23 +35571,23 @@
},
{
"kind": "ui-call",
"line": 494,
"line": 441,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "remote gateway auth token (gateway.remote.token)",
"source": "Paste the token from your gateway",
"surface": "apple",
"id": "native.apple.014d9fcbd97f6c48"
"id": "native.apple.14a6b8d735579fae"
},
{
"kind": "ui-call",
"line": 498,
"line": 448,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Used when the remote gateway requires token auth.",
"source": "Only needed when the gateway requires token auth.",
"surface": "apple",
"id": "native.apple.cc14b91d20cc33ba"
"id": "native.apple.143603a153dd0100"
},
{
"kind": "ui-call-concatenated",
"line": 502,
"line": 457,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "The current gateway.remote.token value is not plain text. OpenClaw for macOS cannot use it directly; enter a plaintext token here to replace it.",
"surface": "apple",
@@ -35699,7 +35595,119 @@
},
{
"kind": "ui-call",
"line": 519,
"line": 475,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Transport",
"surface": "apple",
"id": "native.apple.7881cec64b177026"
},
{
"kind": "ui-call",
"line": 476,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "SSH tunnel",
"surface": "apple",
"id": "native.apple.8413b40cd91c9a19"
},
{
"kind": "ui-call",
"line": 477,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Direct (ws/wss)",
"surface": "apple",
"id": "native.apple.915c50965d971bb4"
},
{
"kind": "ui-call",
"line": 485,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Gateway URL",
"surface": "apple",
"id": "native.apple.9c90f7bc1b9564b1"
},
{
"kind": "ui-call",
"line": 488,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "wss://gateway.example.ts.net",
"surface": "apple",
"id": "native.apple.ba96e44d673d04d3"
},
{
"kind": "ui-call",
"line": 495,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "SSH target",
"surface": "apple",
"id": "native.apple.a193ae2a5ff9decd"
},
{
"kind": "ui-call",
"line": 515,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Identity file",
"surface": "apple",
"id": "native.apple.ecf41ca39add6b84"
},
{
"kind": "ui-call",
"line": 518,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "/Users/you/.ssh/id_ed25519",
"surface": "apple",
"id": "native.apple.ef96d6a2a48a4c54"
},
{
"kind": "ui-call",
"line": 523,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Project root",
"surface": "apple",
"id": "native.apple.0ef039b18340a2e1"
},
{
"kind": "ui-call",
"line": 526,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "/home/you/Projects/openclaw",
"surface": "apple",
"id": "native.apple.dca75ab0dd73f0a4"
},
{
"kind": "ui-call",
"line": 531,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "CLI path",
"surface": "apple",
"id": "native.apple.6998a7754dea6eb1"
},
{
"kind": "ui-call",
"line": 534,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "/Applications/OpenClaw.app/.../openclaw",
"surface": "apple",
"id": "native.apple.5a3f4f943c8ee86a"
},
{
"kind": "conditional-branch",
"line": 545,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Tip: use Tailscale Serve so the gateway has a valid HTTPS cert.",
"surface": "apple",
"id": "native.apple.56e9b0831ec1eded"
},
{
"kind": "conditional-branch",
"line": 546,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Tip: keep Tailscale enabled so your gateway stays reachable.",
"surface": "apple",
"id": "native.apple.ab88df30f426b434"
},
{
"kind": "ui-call",
"line": 560,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Checking remote gateway…",
"surface": "apple",
@@ -35707,7 +35715,7 @@
},
{
"kind": "conditional-branch",
"line": 651,
"line": 692,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": " · ssh \\(parsed.port)",
"surface": "apple",
@@ -35715,7 +35723,7 @@
},
{
"kind": "ui-call",
"line": 720,
"line": 761,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Grant permissions",
"surface": "apple",
@@ -35723,7 +35731,7 @@
},
{
"kind": "ui-call-concatenated",
"line": 727,
"line": 768,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "These macOS permissions let OpenClaw automate apps and capture context on this Mac. Status updates automatically.",
"surface": "apple",
@@ -35731,7 +35739,7 @@
},
{
"kind": "ui-call",
"line": 762,
"line": 803,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Getting things ready",
"surface": "apple",
@@ -35739,7 +35747,7 @@
},
{
"kind": "ui-named-argument",
"line": 773,
"line": 814,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Install OpenClaw",
"surface": "apple",
@@ -35747,7 +35755,7 @@
},
{
"kind": "conditional-branch",
"line": 780,
"line": 821,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Prepare the Mac node",
"surface": "apple",
@@ -35755,7 +35763,7 @@
},
{
"kind": "conditional-branch",
"line": 780,
"line": 821,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Start the background service",
"surface": "apple",
@@ -35763,7 +35771,7 @@
},
{
"kind": "conditional-branch",
"line": 782,
"line": 823,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Runs inside the app and uses its macOS permissions.",
"surface": "apple",
@@ -35771,7 +35779,7 @@
},
{
"kind": "conditional-branch",
"line": 783,
"line": 824,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Runs quietly and starts again after a restart.",
"surface": "apple",
@@ -35779,7 +35787,7 @@
},
{
"kind": "ui-named-argument",
"line": 786,
"line": 827,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Ready for the next step",
"surface": "apple",
@@ -35787,7 +35795,7 @@
},
{
"kind": "conditional-branch",
"line": 788,
"line": 829,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Once ready, this Mac connects to your selected Gateway.",
"surface": "apple",
@@ -35795,7 +35803,7 @@
},
{
"kind": "conditional-branch",
"line": 789,
"line": 830,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Once the service answers, youll connect your AI.",
"surface": "apple",
@@ -35803,7 +35811,7 @@
},
{
"kind": "ui-named-argument",
"line": 794,
"line": 835,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "The Gateway didnt start",
"surface": "apple",
@@ -35811,7 +35819,7 @@
},
{
"kind": "ui-named-argument",
"line": 797,
"line": 838,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Try again",
"surface": "apple",
@@ -35819,7 +35827,7 @@
},
{
"kind": "ui-call",
"line": 888,
"line": 929,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Youre all set!",
"surface": "apple",
@@ -35827,7 +35835,7 @@
},
{
"kind": "ui-call",
"line": 891,
"line": 932,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Finish opens the chat — say hi to your new agent.",
"surface": "apple",
@@ -35835,7 +35843,7 @@
},
{
"kind": "ui-named-argument",
"line": 899,
"line": 940,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Configure later",
"surface": "apple",
@@ -35843,7 +35851,7 @@
},
{
"kind": "ui-named-argument",
"line": 900,
"line": 941,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Pick Local or Remote in Settings → General whenever youre ready.",
"surface": "apple",
@@ -35851,7 +35859,7 @@
},
{
"kind": "ui-named-argument",
"line": 907,
"line": 948,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Remote gateway checklist",
"surface": "apple",
@@ -35859,7 +35867,7 @@
},
{
"kind": "ui-named-argument-multiline",
"line": 908,
"line": 949,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "On your gateway host: install/update the `openclaw` package and make sure credentials exist\n(typically `~/.openclaw/credentials/oauth.json`). Then connect again if needed.",
"surface": "apple",
@@ -35867,7 +35875,7 @@
},
{
"kind": "ui-named-argument",
"line": 917,
"line": 958,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Open the menu bar panel",
"surface": "apple",
@@ -35875,7 +35883,7 @@
},
{
"kind": "ui-named-argument",
"line": 918,
"line": 959,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Click the OpenClaw menu bar icon for the compact chat panel and status.",
"surface": "apple",
@@ -35883,7 +35891,7 @@
},
{
"kind": "ui-named-argument",
"line": 921,
"line": 962,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Connect Discord, Slack, Telegram, WhatsApp, …",
"surface": "apple",
@@ -35891,7 +35899,7 @@
},
{
"kind": "ui-named-argument",
"line": 922,
"line": 963,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Open Settings → Channels to link channels and monitor status.",
"surface": "apple",
@@ -35899,7 +35907,7 @@
},
{
"kind": "ui-named-argument",
"line": 924,
"line": 965,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Open Settings → Channels",
"surface": "apple",
@@ -35907,7 +35915,7 @@
},
{
"kind": "ui-named-argument",
"line": 929,
"line": 970,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Try Voice Wake",
"surface": "apple",
@@ -35915,7 +35923,7 @@
},
{
"kind": "ui-named-argument",
"line": 930,
"line": 971,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Enable Voice Wake in Settings for hands-free commands with a live transcript overlay.",
"surface": "apple",
@@ -35923,7 +35931,7 @@
},
{
"kind": "ui-named-argument",
"line": 933,
"line": 974,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Use the panel + Canvas",
"surface": "apple",
@@ -35931,7 +35939,7 @@
},
{
"kind": "ui-named-argument-concatenated",
"line": 934,
"line": 975,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Open the compact chat panel; the agent can show previews and richer visuals in Canvas.",
"surface": "apple",
@@ -35939,7 +35947,7 @@
},
{
"kind": "ui-named-argument",
"line": 938,
"line": 979,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Give your agent more powers",
"surface": "apple",
@@ -35947,7 +35955,7 @@
},
{
"kind": "ui-named-argument",
"line": 939,
"line": 980,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Enable optional skills (Peekaboo, oracle, camsnap, …) from Settings → Skills.",
"surface": "apple",
@@ -35955,7 +35963,7 @@
},
{
"kind": "ui-named-argument",
"line": 941,
"line": 982,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Open Settings → Skills",
"surface": "apple",
@@ -35963,7 +35971,7 @@
},
{
"kind": "ui-call",
"line": 946,
"line": 987,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Launch at login",
"surface": "apple",
@@ -35971,7 +35979,7 @@
},
{
"kind": "ui-call",
"line": 973,
"line": 1014,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Skills included",
"surface": "apple",
@@ -35979,7 +35987,7 @@
},
{
"kind": "ui-call",
"line": 980,
"line": 1021,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Refresh",
"surface": "apple",
@@ -35987,7 +35995,7 @@
},
{
"kind": "ui-call",
"line": 989,
"line": 1030,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Couldnt load skills from the Gateway.",
"surface": "apple",
@@ -35995,7 +36003,7 @@
},
{
"kind": "ui-call-concatenated",
"line": 992,
"line": 1033,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Make sure the Gateway is running and connected, then hit Refresh (or open Settings → Skills).",
"surface": "apple",
@@ -36003,7 +36011,7 @@
},
{
"kind": "ui-call",
"line": 998,
"line": 1039,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "Details: \\(error)",
"surface": "apple",
@@ -36011,7 +36019,7 @@
},
{
"kind": "ui-call",
"line": 1004,
"line": 1045,
"path": "apps/macos/Sources/OpenClaw/OnboardingView+Pages.swift",
"source": "No skills reported yet.",
"surface": "apple",
@@ -118,11 +118,10 @@ extension OnboardingView {
self.gatewayDiscoverySection()
if self.shouldShowRemoteConnectionSection {
Divider().padding(.vertical, 4)
self.remoteConnectionSection()
} else {
self.advancedConnectionSection()
}
self.advancedConnectionSection()
}
}
}
@@ -237,104 +236,18 @@ extension OnboardingView {
}
}
@ViewBuilder
private func advancedConnectionSection() -> some View {
Button(showAdvancedConnection ? "Hide Advanced" : "Advanced…") {
// Open-only: this button renders only while the remote panel (and its
// Hide toggle) is absent, so it never needs to collapse anything.
Button("Advanced…") {
withAnimation(.spring(response: 0.25, dampingFraction: 0.9)) {
self.showAdvancedConnection.toggle()
self.showAdvancedConnection = true
}
if self.showAdvancedConnection, self.state.connectionMode != .remote {
if self.state.connectionMode != .remote {
self.state.connectionMode = .remote
}
}
.buttonStyle(.link)
if showAdvancedConnection {
let labelWidth: CGFloat = 110
let fieldWidth: CGFloat = 320
VStack(alignment: .leading, spacing: 10) {
Grid(alignment: .leading, horizontalSpacing: 12, verticalSpacing: 8) {
GridRow {
Text("Transport")
.font(.callout.weight(.semibold))
.frame(width: labelWidth, alignment: .leading)
Picker("Transport", selection: self.manualRemoteTransportBinding) {
Text("SSH tunnel").tag(AppState.RemoteTransport.ssh)
Text("Direct (ws/wss)").tag(AppState.RemoteTransport.direct)
}
.pickerStyle(.segmented)
.frame(width: fieldWidth)
}
if self.state.remoteTransport == .direct {
GridRow {
Text("Gateway URL")
.font(.callout.weight(.semibold))
.frame(width: labelWidth, alignment: .leading)
TextField("wss://gateway.example.ts.net", text: self.manualRemoteURLBinding)
.textFieldStyle(.roundedBorder)
.frame(width: fieldWidth)
}
}
if self.state.remoteTransport == .ssh {
GridRow {
Text("SSH target")
.font(.callout.weight(.semibold))
.frame(width: labelWidth, alignment: .leading)
TextField("user@host[:port]", text: self.manualRemoteTargetBinding)
.textFieldStyle(.roundedBorder)
.frame(width: fieldWidth)
}
if let message = CommandResolver
.sshTargetValidationMessage(self.state.remoteTarget)
{
GridRow {
Text("")
.frame(width: labelWidth, alignment: .leading)
Text(message)
.font(.caption)
.foregroundStyle(.red)
.frame(width: fieldWidth, alignment: .leading)
}
}
GridRow {
Text("Identity file")
.font(.callout.weight(.semibold))
.frame(width: labelWidth, alignment: .leading)
TextField("/Users/you/.ssh/id_ed25519", text: self.$state.remoteIdentity)
.textFieldStyle(.roundedBorder)
.frame(width: fieldWidth)
}
GridRow {
Text("Project root")
.font(.callout.weight(.semibold))
.frame(width: labelWidth, alignment: .leading)
TextField("/home/you/Projects/openclaw", text: self.$state.remoteProjectRoot)
.textFieldStyle(.roundedBorder)
.frame(width: fieldWidth)
}
GridRow {
Text("CLI path")
.font(.callout.weight(.semibold))
.frame(width: labelWidth, alignment: .leading)
TextField(
"/Applications/OpenClaw.app/.../openclaw",
text: self.$state.remoteCliPath)
.textFieldStyle(.roundedBorder)
.frame(width: fieldWidth)
}
}
}
Text(self.state.remoteTransport == .direct
? "Tip: use Tailscale Serve so the gateway has a valid HTTPS cert."
: "Tip: keep Tailscale enabled so your gateway stays reachable.")
.font(.footnote)
.foregroundStyle(.secondary)
.lineLimit(1)
}
.transition(.opacity.combined(with: .move(edge: .top)))
}
}
private var manualRemoteTransportBinding: Binding<AppState.RemoteTransport> {
@@ -440,12 +353,15 @@ extension OnboardingView {
}
private func remoteConnectionSection() -> some View {
VStack(alignment: .leading, spacing: 10) {
let labelWidth: CGFloat = 110
let fieldWidth: CGFloat = 320
return VStack(alignment: .leading, spacing: 10) {
HStack(alignment: .top, spacing: 12) {
VStack(alignment: .leading, spacing: 2) {
Text("Remote connection")
.font(.callout.weight(.semibold))
Text("Checks the real remote websocket and auth handshake.")
Text("Verify OpenClaw can reach this gateway.")
.font(.caption)
.foregroundStyle(.secondary)
}
@@ -466,10 +382,8 @@ extension OnboardingView {
.disabled(!self.canProbeRemoteConnection)
}
if self.shouldShowRemoteTokenField {
self.remoteTokenField()
}
// Probe feedback sits with the Check connection button it explains,
// above the form rows, so grid growth never pushes it out of view.
if let message = self.remoteProbePreflightMessage, self.remoteProbeState != .checking {
Text(message)
.font(.caption)
@@ -482,23 +396,64 @@ extension OnboardingView {
if let issue = self.remoteAuthIssue {
self.remoteAuthPromptView(issue: issue)
}
Grid(alignment: .leading, horizontalSpacing: 12, verticalSpacing: 8) {
if self.shouldShowRemoteTokenField {
self.remoteTokenField(labelWidth: labelWidth, fieldWidth: fieldWidth)
}
if self.showAdvancedConnection {
self.advancedConnectionFields(labelWidth: labelWidth, fieldWidth: fieldWidth)
}
}
Button {
withAnimation(.spring(response: 0.25, dampingFraction: 0.9)) {
self.showAdvancedConnection.toggle()
}
if self.showAdvancedConnection, self.state.connectionMode != .remote {
self.state.connectionMode = .remote
}
} label: {
HStack(spacing: 4) {
Image(systemName: self.showAdvancedConnection ? "chevron.up" : "chevron.down")
Text(self.showAdvancedConnection ? "Hide advanced options" : "Advanced options")
}
}
.buttonStyle(.link)
}
.padding(12)
.background(
// controlBackgroundColor matches the card fill, so the hairline
// stroke is what makes this read as a contained panel.
RoundedRectangle(cornerRadius: 10, style: .continuous)
.fill(Color(NSColor.controlBackgroundColor))
.overlay(
RoundedRectangle(cornerRadius: 10, style: .continuous)
.strokeBorder(Color(NSColor.separatorColor))))
}
private func remoteTokenField() -> some View {
VStack(alignment: .leading, spacing: 6) {
HStack(alignment: .center, spacing: 12) {
Text("Gateway token")
.font(.callout.weight(.semibold))
.frame(width: 110, alignment: .leading)
SecureField("remote gateway auth token (gateway.remote.token)", text: self.$state.remoteToken)
.textFieldStyle(.roundedBorder)
.frame(maxWidth: 320)
}
Text("Used when the remote gateway requires token auth.")
@ViewBuilder
private func remoteTokenField(labelWidth: CGFloat, fieldWidth: CGFloat) -> some View {
GridRow {
Text("Gateway token")
.font(.callout.weight(.semibold))
.frame(width: labelWidth, alignment: .leading)
SecureField("Paste the token from your gateway", text: self.$state.remoteToken)
.textFieldStyle(.roundedBorder)
.frame(width: fieldWidth)
}
GridRow {
Text("")
.frame(width: labelWidth, alignment: .leading)
Text("Only needed when the gateway requires token auth.")
.font(.caption)
.foregroundStyle(.secondary)
if self.state.remoteTokenUnsupported {
.frame(width: fieldWidth, alignment: .leading)
}
if self.state.remoteTokenUnsupported {
GridRow {
Text("")
.frame(width: labelWidth, alignment: .leading)
Text(
"The current gateway.remote.token value is not plain text. "
+ "OpenClaw for macOS cannot use it directly; "
@@ -506,10 +461,96 @@ extension OnboardingView {
.font(.caption)
.foregroundStyle(.orange)
.fixedSize(horizontal: false, vertical: true)
.frame(width: fieldWidth, alignment: .leading)
}
}
}
@ViewBuilder
private func advancedConnectionFields(labelWidth: CGFloat, fieldWidth: CGFloat) -> some View {
GridRow {
Text("Transport")
.font(.callout.weight(.semibold))
.frame(width: labelWidth, alignment: .leading)
Picker("Transport", selection: self.manualRemoteTransportBinding) {
Text("SSH tunnel").tag(AppState.RemoteTransport.ssh)
Text("Direct (ws/wss)").tag(AppState.RemoteTransport.direct)
}
.labelsHidden()
.pickerStyle(.segmented)
.frame(width: fieldWidth)
}
if self.state.remoteTransport == .direct {
GridRow {
Text("Gateway URL")
.font(.callout.weight(.semibold))
.frame(width: labelWidth, alignment: .leading)
TextField("wss://gateway.example.ts.net", text: self.manualRemoteURLBinding)
.textFieldStyle(.roundedBorder)
.frame(width: fieldWidth)
}
}
if self.state.remoteTransport == .ssh {
GridRow {
Text("SSH target")
.font(.callout.weight(.semibold))
.frame(width: labelWidth, alignment: .leading)
TextField("user@host[:port]", text: self.manualRemoteTargetBinding)
.textFieldStyle(.roundedBorder)
.frame(width: fieldWidth)
}
if let message = CommandResolver
.sshTargetValidationMessage(self.state.remoteTarget)
{
GridRow {
Text("")
.frame(width: labelWidth, alignment: .leading)
Text(message)
.font(.caption)
.foregroundStyle(.red)
.frame(width: fieldWidth, alignment: .leading)
}
}
GridRow {
Text("Identity file")
.font(.callout.weight(.semibold))
.frame(width: labelWidth, alignment: .leading)
TextField("/Users/you/.ssh/id_ed25519", text: self.$state.remoteIdentity)
.textFieldStyle(.roundedBorder)
.frame(width: fieldWidth)
}
GridRow {
Text("Project root")
.font(.callout.weight(.semibold))
.frame(width: labelWidth, alignment: .leading)
TextField("/home/you/Projects/openclaw", text: self.$state.remoteProjectRoot)
.textFieldStyle(.roundedBorder)
.frame(width: fieldWidth)
}
GridRow {
Text("CLI path")
.font(.callout.weight(.semibold))
.frame(width: labelWidth, alignment: .leading)
TextField(
"/Applications/OpenClaw.app/.../openclaw",
text: self.$state.remoteCliPath)
.textFieldStyle(.roundedBorder)
.frame(width: fieldWidth)
}
}
GridRow {
Text("")
.frame(width: labelWidth, alignment: .leading)
Text(self.state.remoteTransport == .direct
? "Tip: use Tailscale Serve so the gateway has a valid HTTPS cert."
: "Tip: keep Tailscale enabled so your gateway stays reachable.")
.font(.footnote)
.foregroundStyle(.secondary)
.lineLimit(1)
.frame(width: fieldWidth, alignment: .leading)
}
}
@ViewBuilder
private func remoteProbeStatusView() -> some View {
switch remoteProbeState {