mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-03 12:11:40 +00:00
* feat(ui): resolve session URLs through the gateway with best-effort slug matching Session URLs now resolve a stored board face and a display-name slug through the gateway instead of guessing from the browser's cached session page. - An uncached open marks only the in-app navigation, never the shareable href, so the chat loader can re-derive the face and replace the URL. - A cached row settles the lookup locally, keeping navigation off the wire. - A one-segment reference resolves short id, then literal key, then display-name slug; ties reuse the existing disambiguation view. * refactor(ui): keep slug ties on short disambiguation prefixes Slug candidates reused the full uuid, which produced 32-character links in the disambiguation view. uniqueShortIdPrefix already falls back to the full id when the bounded search was truncated, so reuse it and drop the flag. * fix(ui): navigate worktree owner links in-app so the face marker survives The Worktrees owner link was a bare anchor consuming only the shareable href, so preferenceDerivedFace was a no-op there and an uncached owner always opened on chat. Match the other session surfaces: keep the clean href and navigate with the options on plain clicks. * fix(ui): search the first uuid block so long session references resolve The gateway matches sessions.list search as a plain substring and stored keys hold a hyphenated uuid, so any hyphen-stripped reference past the first block matched nothing and 404'd. This hit disambiguation links, which offer prefixes longer than eight characters. Send the first block and keep applying the full prefix per row. A resolved slug now canonicalizes to that same short reference instead of a full uuid, so /chat/main/deploy-monitor settles on -6db92d48. * docs(ui): record why the face marker stays out of shareable hrefs
206 lines
13 KiB
Markdown
206 lines
13 KiB
Markdown
---
|
|
summary: "Control UI URL routes, stable session-link grammar, and connection handoff parameters"
|
|
read_when:
|
|
- You need to bookmark or share a Control UI session
|
|
- You are adding or changing a Control UI route
|
|
- You need a terminal, approval, onboarding, or remote Gateway URL
|
|
title: "Control UI URLs"
|
|
---
|
|
|
|
The Control UI uses readable paths for pages and session links. A configured
|
|
`gateway.controlUi.basePath` prefixes every path below. For example, `/chat/main`
|
|
becomes `/openclaw/chat/main` when the base path is `/openclaw`.
|
|
|
|
## Session and dashboard URLs
|
|
|
|
Chat and dashboard views are parallel route namespaces:
|
|
|
|
```text
|
|
/chat/main/deploy-monitor-6db92d48
|
|
/dashboard/main/deploy-monitor-6db92d48
|
|
/chat/main/telegram/12345
|
|
/chat/main/cron/nightly/run/8821
|
|
/chat/main
|
|
```
|
|
|
|
The path grammar is:
|
|
|
|
```text
|
|
/<namespace>/<agentId>
|
|
/<namespace>/<agentId>/<sessionRef>
|
|
/<namespace>/<agentId>/<restSegment>/<restSegment>...
|
|
```
|
|
|
|
`<namespace>` is either `/chat` or `/dashboard`. The first form opens that
|
|
agent's main session. The other forms encode one immutable session key in one of
|
|
two ways.
|
|
|
|
The short-id form applies when the session key's rest, everything after
|
|
`agent:<agentId>:`, ends in a UUID. `<sessionRef>` is an optional display-name
|
|
slug plus a short id, such as `deploy-monitor-6db92d48`. The short id is the
|
|
authoritative part: at least eight lowercase hexadecimal characters from the
|
|
start of the key's trailing UUID, with UUID dashes omitted. Longer prefixes up
|
|
to all 32 hexadecimal characters are accepted. The row's rotating `sessionId`
|
|
is not part of the URL identity.
|
|
|
|
Every other key uses the literal-key form. Each colon-delimited segment after
|
|
`agent:<agentId>:` becomes one URL-encoded path segment. For example,
|
|
`agent:main:telegram:12345` becomes `/chat/main/telegram/12345`, and
|
|
`agent:main:cron:nightly:run:8821` becomes
|
|
`/chat/main/cron/nightly/run/8821`.
|
|
|
|
Literal rest segments exactly equal to `.` or `..` use `~dot` and `~dotdot` so
|
|
browsers cannot collapse them as relative path segments. A literal segment that
|
|
starts with `~` doubles that leading character to keep the encoding reversible.
|
|
When an otherwise literal one-segment rest could be mistaken for a short id,
|
|
the builder inserts `~key` before it, for example
|
|
`agent:main:release-deadbeef` becomes
|
|
`/chat/main/~key/release-deadbeef`. The marker forces literal interpretation
|
|
and appears only when the unescaped form would be ambiguous.
|
|
|
|
The reserved single-segment literal rest names are `main`, `global`, `boot`,
|
|
and `sessions`. The configured `session.mainKey` joins that set at runtime.
|
|
Exactly one segment after the agent id is literal when it is reserved or does
|
|
not contain a valid short id; otherwise it is a short reference. Two or more
|
|
segments after the agent id are always literal.
|
|
|
|
Only the configured `session.mainKey` collapses to the agent-only main-session
|
|
path. With `session.mainKey: "workspace"`, `agent:research:workspace` becomes
|
|
`/chat/research`, while the distinct key `agent:research:main` remains the
|
|
literal path `/chat/research/main`.
|
|
|
|
### Stability contract
|
|
|
|
The following parts are stable URL contracts:
|
|
|
|
- The `/chat` and `/dashboard` namespace words.
|
|
- The key UUID short id in short-id URLs.
|
|
- The arity and short-versus-literal parsing rules above.
|
|
|
|
In short-id form, the agent segment and slug are explicitly decorative. They may
|
|
change without notice and are not used to identify or validate the session.
|
|
After resolution, the Control UI replaces the address bar with the current
|
|
agent id and current display-name slug without adding a browser-history entry.
|
|
|
|
In literal-key form, the agent segment is authoritative because it is part of
|
|
the reconstructed session key. The remaining literal segments are authoritative
|
|
too. A slug, when present, is always decorative; literal-key forms do not
|
|
synthesize one.
|
|
|
|
As a best-effort convenience, an unescaped one-segment literal that does not
|
|
resolve as an exact session key is also checked against display-name slugs. One
|
|
exact slug match is replaced in the address bar with its full
|
|
`/<namespace>/<agentId>/<slug>-<shortId>` reference. If several sessions share
|
|
the slug, the UI shows the same disambiguation view used for short-id ties
|
|
instead of guessing. Exact short-id and literal-key references always win over
|
|
slug matching.
|
|
|
|
If one short id matches more than one session, the UI does not guess. It shows a
|
|
small disambiguation view with the matching display names, agents, and longer id
|
|
prefixes. Use a longer prefix to make the URL unique. Resolution examines at
|
|
most five pages of search results; if more remain, the view says that the search
|
|
was incomplete instead of guessing.
|
|
|
|
Canonical links do not use `?session=` or `?face=`. Released links such as
|
|
`/chat?session=<sessionKey>` are accepted only at the application boundary as a
|
|
migration aid and immediately rewritten, without adding browser history, to the
|
|
canonical path. The released `?face=dashboard` companion selects the
|
|
`/dashboard` namespace during that rewrite. Loaders and page code never read the
|
|
query-form identity, and new links must not emit it. The Sessions list keeps its
|
|
own `?session=` parameter because that parameter expands a row; it is not a
|
|
session deep link. The one-shot composer value `?draft=` remains supported on
|
|
chat and dashboard session paths.
|
|
|
|
## Route table
|
|
|
|
This table lists every Control UI application route. A dash means the route has
|
|
no route-specific URL parameters.
|
|
|
|
| Page | Canonical path | Aliases | Parameters or dynamic forms |
|
|
| ------------------- | --------------------------- | ------------------------- | ------------------------------------------------ |
|
|
| Chat | `/chat` | - | Key-backed session forms above; `?draft=<text>` |
|
|
| Dashboard | `/dashboard` | - | Key-backed session forms above; `?draft=<text>` |
|
|
| Dashboards | `/dashboards` | - | - |
|
|
| Ask OpenClaw | `/custodian` | - | `?intent=new-agent`, `?onboarding=1` |
|
|
| New session | `/new` | - | `?agent=<agentId>`, `?catalog=<catalogId>` |
|
|
| Activity | `/activity` | - | - |
|
|
| Apps | `/apps` | - | - |
|
|
| Agents | `/settings/agents` | `/agents` | `?agent=<agentId>` |
|
|
| Channels | `/settings/channels` | `/channels` | Shared settings parameters below |
|
|
| Connection | `/settings/connection` | - | Shared settings parameters below |
|
|
| General settings | `/settings/general` | `/config` | Shared settings parameters below |
|
|
| Profile | `/settings/profile` | `/profile` | Shared settings parameters below |
|
|
| Communications | `/settings/communications` | `/communications` | Shared settings parameters below |
|
|
| Appearance | `/settings/appearance` | `/appearance` | Shared settings parameters below |
|
|
| Notifications | `/settings/notifications` | - | Shared settings parameters below |
|
|
| Security | `/settings/security` | - | Shared settings parameters below |
|
|
| Advanced | `/settings/advanced` | - | Shared settings parameters below |
|
|
| Approvals | `/settings/approvals` | - | Shared settings parameters below |
|
|
| Automation settings | `/settings/automation` | `/automation` | Shared settings parameters below |
|
|
| MCP | `/settings/mcp` | `/mcp` | Shared settings parameters below |
|
|
| Infrastructure | `/settings/infrastructure` | `/infrastructure` | Shared settings parameters below |
|
|
| Labs | `/settings/labs` | - | Shared settings parameters below |
|
|
| About | `/settings/about` | - | Shared settings parameters below |
|
|
| AI and agents | `/settings/ai-agents` | `/ai-agents` | Shared settings parameters below |
|
|
| Model setup | `/settings/model-setup` | `/model-setup` | `?firstRun=1` |
|
|
| Model providers | `/settings/model-providers` | `/model-providers` | Shared settings parameters below |
|
|
| Import memory | `/memory-import` | `/settings/memory-import` | - |
|
|
| Workboard | `/workboard` | - | `/workboard/<boardId>` |
|
|
| Worktrees | `/worktrees` | `/settings/worktrees` | - |
|
|
| Sessions | `/sessions` | `/settings/sessions` | `?session=<sessionKey>`, `?status=archived\|all` |
|
|
| Usage | `/usage` | - | - |
|
|
| Debug | `/debug` | - | - |
|
|
| Logs | `/logs` | - | - |
|
|
| Skill Workshop | `/skills/workshop` | - | - |
|
|
| Skills | `/skills` | - | - |
|
|
| Plugins | `/settings/plugins` | - | `?tab=discover\|installed` |
|
|
| Automations | `/cron` | - | - |
|
|
| Tasks | `/tasks` | - | - |
|
|
| Devices | `/settings/devices` | `/nodes` | Shared settings parameters below |
|
|
| Plugin tab host | `/plugin` | - | `?plugin=<pluginId>&id=<tabId>` |
|
|
|
|
Settings routes that use schema-backed deep links accept `?section=<section>`,
|
|
`?advanced=1`, and `#<setting-id>`. These values select content within the page;
|
|
they do not change the route identity.
|
|
|
|
## Special documents and startup modes
|
|
|
|
These Gateway-served documents sit outside the application route table:
|
|
|
|
- `/?onboarding=1` opens the first-run onboarding presentation.
|
|
- `/?view=terminal` opens the full-screen terminal-only document used by the
|
|
mobile apps. Availability still requires `gateway.terminal.enabled` and
|
|
`operator.admin`.
|
|
- `/approve/<approvalId>` opens a standalone approval document. With a base
|
|
path, use `<basePath>/approve/<approvalId>`. The id identifies an approval but
|
|
never authorizes it; normal Gateway authentication still applies.
|
|
|
|
The approval namespace is reserved ahead of plugin HTTP routes for all HTTP
|
|
methods. When Control UI serving is disabled, it returns `404` instead of
|
|
falling through to a plugin route.
|
|
|
|
## Remote Gateway handoff
|
|
|
|
The Vite development UI can connect to a different Gateway:
|
|
|
|
```text
|
|
http://localhost:5173/?gatewayUrl=ws%3A%2F%2F<gateway-host>%3A18789
|
|
http://localhost:5173/?gatewayUrl=wss%3A%2F%2F<gateway-host>%3A18789#token=<gateway-token>
|
|
```
|
|
|
|
URL-encode a full `ws://` or `wss://` value. `gatewayUrl` is accepted only in a
|
|
top-level window, stored after load, and removed from the address bar. Prefer
|
|
`#token=` because fragments do not enter HTTP request logs or Referer headers.
|
|
The legacy `?token=` handoff remains a bootstrap-only credential fallback and
|
|
is stripped immediately. Passwords stay in memory only.
|
|
|
|
When `gatewayUrl` selects another Gateway, the UI does not fall back to local
|
|
configuration or environment credentials. Provide the remote Gateway's token
|
|
or password explicitly, and use `wss://` behind TLS.
|
|
|
|
## Related
|
|
|
|
- [Control UI](/web/control-ui)
|
|
- [Dashboard](/web/dashboard)
|
|
- [Session dashboards](/web/dashboards)
|