Nightly Build / build (push) Successful in 7m51s
An eye next to the paperclip shares what the user has open with their next
message: the page, the folder being browsed, the file open in the viewer and
any highlighted passage (line numbers where a source view exists), plus which
entity a detail page is about. The bag is client-authored {label, value} pairs
in English — the backend only clamps (chars, never bytes), neutralizes the
harness tag and renders one <system-extra> block per message, deduped
consecutively so it appears exactly when the view changed. On by default,
per-device toggle, hover/tap to preview, a chip on every sent message;
docs/view-context.md for users, an updated harness.md clause for the model.
43 lines
2.1 KiB
JavaScript
43 lines
2.1 KiB
JavaScript
/**
|
|
* Hash routing, shared.
|
|
*
|
|
* `pageFromHash()` turns `location.hash` into the page id the app navigates by
|
|
* (`llm-page-change`'s `detail.page`, the sidebar's `_activePage`, the value the
|
|
* view-context store describes). It lives here — and not in `sidebar.js`, where
|
|
* it grew — because there are now two readers of it: the menu highlight and the
|
|
* view context attached to a message. Two copies of this logic would drift, and
|
|
* the drift would be invisible: the assistant would be told the user is on one
|
|
* page while the menu highlights another.
|
|
*
|
|
* The mobile shell (`mobile-app.js`) routes a fixed set of sections of its own
|
|
* and does not go through this.
|
|
*/
|
|
|
|
// Every hash segment the app accepts as a page. Anything else falls back to
|
|
// `home`, so a hand-typed or stale URL lands on the chat rather than nowhere.
|
|
export const KNOWN_PAGES = [
|
|
'inbox', 'dashboard', 'tasks', 'projects', 'files', 'models', 'providers',
|
|
'approval', 'agents', 'users', 'roles', 'shared-folders', 'connectors',
|
|
'connector', 'plugins', 'plugin-detail', 'marketplace', 'profile', 'config',
|
|
'llm-requests', 'session', 'system-agents', 'file_viewer', 'tool_detail',
|
|
];
|
|
|
|
export function pageFromHash() {
|
|
const hash = location.hash.slice(1);
|
|
if (!hash) return 'home';
|
|
// Segment ends at the first `/` (e.g. `#session/123`) or `?` (e.g. `#file_viewer?path=...`).
|
|
const match = hash.match(/^([^/?]+)/);
|
|
const segment = match ? match[1] : '';
|
|
// Plugin pages: `#plugin/<plugin_id>/<page_id>` — the route is accepted by
|
|
// shape (deep links must survive the async `/api/plugins/pages` load); the
|
|
// host reports an error if the page turns out not to exist for this user.
|
|
if (segment === 'plugin') {
|
|
const m = hash.match(/^plugin\/([^/?]+)\/([^/?]+)/);
|
|
return m ? `plugin/${m[1]}/${m[2]}` : 'home';
|
|
}
|
|
// `connector` (singular) is the per-connector detail page, `connectors` the list.
|
|
// `plugin-catalog` is the pre-merge hash of what is now `#plugins`.
|
|
const page = segment === 'plugin-catalog' ? 'plugins' : segment;
|
|
return KNOWN_PAGES.includes(page) ? page : 'home';
|
|
}
|