dsh-url-router 0.3.1 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +129 -112
- package/LICENSE +21 -21
- package/README.md +130 -126
- package/cordis.patch.yml +23 -23
- package/lib/client.js +2207 -2110
- package/lib/index.js +13 -13
- package/package.json +59 -59
package/README.md
CHANGED
|
@@ -1,126 +1,130 @@
|
|
|
1
|
-
# dsh-url-router
|
|
2
|
-
|
|
3
|
-
**DSH Web GUI 地址栏路由插件 —— 每个界面都有自己的链接:地址栏写着屏幕上的东西,链接点开就是那个界面。** 给 DeepSeek Harness (dsh) Web GUI 补上"可寻址":点侧栏会话,地址栏变成 `#/session/<id>`;点插件面板,变成 `#/panel/plugins`;点进某个插件、某个组件、某个任务,地址栏跟着一起走。把这条链接贴到新标签页、或者对着侧栏任意一行右键,就是浏览器自己的行为——无需复制按钮、无需自定义菜单。
|
|
4
|
-
|
|
5
|
-
它是**地址栏的唯一写者**:只改 URL 的 fragment,路径与查询串(例如启动时的 `?token=…`)原样保留;只用 `replaceState`,浏览面板不会往后退栈里塞历史。**只有浏览器半区**——零依赖、无宿主路由、无遥测。
|
|
6
|
-
|
|
7
|
-
[中文](#中文) · [English](#english)
|
|
8
|
-
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
## 中文
|
|
12
|
-
|
|
13
|
-
### 安装
|
|
14
|
-
|
|
15
|
-
```sh
|
|
16
|
-
# 通过插件管理器(推荐)
|
|
17
|
-
dsh plugin --profile web add dsh-url-router
|
|
18
|
-
|
|
19
|
-
# 重启 dsh web,之后硬刷新浏览器
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
开发时也可以直接挂工作树:
|
|
23
|
-
|
|
24
|
-
```sh
|
|
25
|
-
dsh plugin --profile web add "link:/path/to/dsh-url-router"
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
|
33
|
-
|
|
|
34
|
-
| `#/
|
|
35
|
-
| `#/panel
|
|
36
|
-
| `#/panel/plugins
|
|
37
|
-
| `#/panel/
|
|
38
|
-
| `#/panel/
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
-
|
|
57
|
-
-
|
|
58
|
-
-
|
|
59
|
-
-
|
|
60
|
-
-
|
|
61
|
-
-
|
|
62
|
-
-
|
|
63
|
-
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
-
|
|
71
|
-
-
|
|
72
|
-
-
|
|
73
|
-
-
|
|
74
|
-
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
|
104
|
-
|
|
|
105
|
-
| `#/
|
|
106
|
-
| `#/panel
|
|
107
|
-
| `#/panel/
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
###
|
|
116
|
-
|
|
117
|
-
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
- **
|
|
122
|
-
- **
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
1
|
+
# dsh-url-router
|
|
2
|
+
|
|
3
|
+
**DSH Web GUI 地址栏路由插件 —— 每个界面都有自己的链接:地址栏写着屏幕上的东西,链接点开就是那个界面。** 给 DeepSeek Harness (dsh) Web GUI 补上"可寻址":点侧栏会话,地址栏变成 `#/session/<id>`;点插件面板,变成 `#/panel/plugins`;点进某个插件、某个组件、某个任务,地址栏跟着一起走。把这条链接贴到新标签页、或者对着侧栏任意一行右键,就是浏览器自己的行为——无需复制按钮、无需自定义菜单。
|
|
4
|
+
|
|
5
|
+
它是**地址栏的唯一写者**:只改 URL 的 fragment,路径与查询串(例如启动时的 `?token=…`)原样保留;只用 `replaceState`,浏览面板不会往后退栈里塞历史。**只有浏览器半区**——零依赖、无宿主路由、无遥测。
|
|
6
|
+
|
|
7
|
+
[中文](#中文) · [English](#english)
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## 中文
|
|
12
|
+
|
|
13
|
+
### 安装
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
# 通过插件管理器(推荐)
|
|
17
|
+
dsh plugin --profile web add dsh-url-router
|
|
18
|
+
|
|
19
|
+
# 重启 dsh web,之后硬刷新浏览器
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
开发时也可以直接挂工作树:
|
|
23
|
+
|
|
24
|
+
```sh
|
|
25
|
+
dsh plugin --profile web add "link:/path/to/dsh-url-router"
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
**已登记进社区插件索引** ✓ —— [zhu1090093659/dsh-community-plugins](https://github.com/zhu1090093659/dsh-community-plugins) 的 `community.json` 是本插件在 DSH Workshop 商店与 dsh-market.com 清单里的唯一数据源 ✓(登记条目 `dsh-url-router`,`ui/panel` ✓)。
|
|
29
|
+
|
|
30
|
+
### 路由表
|
|
31
|
+
|
|
32
|
+
| 地址 | 界面 | 由谁打开 |
|
|
33
|
+
| --- | --- | --- |
|
|
34
|
+
| `#/session/<id>` | 主视图里的那个会话 | `uiWorkspace.openSession(id)` |
|
|
35
|
+
| `#/panel/<panelId>` | 主面板(`plugins`、`task-board`、`skill-explorer`、`ssh` …) | `layout.selectPanel(id)` |
|
|
36
|
+
| `#/panel/plugins/<包名>` | 某个已安装插件的页面 | 面板自己的列表行控件 |
|
|
37
|
+
| `#/panel/plugins/<官方项 id>` | 某个官方内置插件的页面(`shell`、`agent-loop`、`subagent`、`web-search`) | 面板自己的列表行控件 |
|
|
38
|
+
| `#/panel/plugins/<包名>/<组件 id>` | 插件页面里的某个组件页 | 面板自己的组件行控件 |
|
|
39
|
+
| `#/panel/task-board/task/<任务 id>` | 任务看板里某个任务的详情 | 任务看板自己的 `dsh-taskboard-open-task` 窗口事件 |
|
|
40
|
+
| `#/panel/task-board/new` | 任务看板的新建任务表单 | 任务看板自己的 `dsh-taskboard-new-task` 窗口事件 |
|
|
41
|
+
|
|
42
|
+
输入侧宽容:`sessions`/`panels` 复数、百分号编码都接受,一律规范化成上面的形式。**不认识的段位不碰**,只留一条诊断(留给以后的路由器,或者别的插件写的深链形态 ✓ —— 一个 fragment 只能有一个写者 ✓,所以读到不属于本插件的形态时会**明确说一句**,而不是静默 ✗)。
|
|
43
|
+
|
|
44
|
+
面板内部页是**面板自己的词汇表**,本插件不发明:插件管理器发布 `data-plugin-detail` / `data-plugin-item-detail` / `data-plugin-row-detail`,任务看板发布 `data-dsh-taskboard-open-task` / `data-dsh-taskboard-new-task`,并接受同名窗口事件。
|
|
45
|
+
|
|
46
|
+
### 每一行都是真链接
|
|
47
|
+
|
|
48
|
+
侧栏的会话行、插件面板的列表行(已安装组与官方组)都是**整行覆盖的透明真锚点**:
|
|
49
|
+
|
|
50
|
+
- **右键** → 浏览器原生菜单(在新标签页中打开 / 复制链接 / 另存为)
|
|
51
|
+
- **中键、Cmd/Ctrl + 单击** → 原生新标签页
|
|
52
|
+
- **左键单击** → 在本页打开(`preventDefault` 后调官方导航,不新增历史记录)
|
|
53
|
+
|
|
54
|
+
### 它守的规矩
|
|
55
|
+
|
|
56
|
+
- **只动 fragment**:路径与查询串从不改写(启动 `?token=…` 能活下来)。
|
|
57
|
+
- **唯一写者**:本插件拥有 fragment,请**不要**和别的写 fragment 的插件同时启用(例如 `dsh-session-url`),两者会互相覆盖。
|
|
58
|
+
- **只用 `replaceState`**:浏览面板不污染后退栈。
|
|
59
|
+
- **轮次信息:能证明才写** ✓。助手行自己的身份里就带轮次(`row/assistant/80/32` = 第 80 轮第 32 项 ✓);**工具行不带** ✗(只有调用 id ✓)→ 于是我从视图的**轮次边界** `[data-turn-start]` 反推 ✓,**但只在行夹在两个已渲染边界之间时才写** ✓(`turn/82/row/tool/call/…` ✓)。视图是虚拟化的 ✓,边界可能只渲染了一侧 ✗ → 那时**宁可不写轮次** ✓,也绝不猜一个错的轮次 ✗。
|
|
60
|
+
- **轨迹里的每一行都有自己的链接** ✓:`#/session/<id>/row/<类>/<作用域>/<id>`(例:`row/tool/call/call_ce3a…`、`row/assistant/80/32` = 第 80 轮第 32 项 ✓;有工作区时跟在会话 id 之后 ✓)。身份来自视图自己发的 **`data-trajectory-row-key`** ✓(值是 `<类>%00<作用域>%00<id>` ✓,我把它拆成可读路径 ✓);你家 Trajectory Plus 发的是 **`data-dshts-turn`**(轮号 ✓)→ 那种行按轮次写(`turn/<n>` ✓)。点一行就反映进地址栏 ✓(**纯被动**:不 preventDefault ✓)。粘贴行链接会打开那个对话并**尽力滚到那一行** ✓ —— 视图是虚拟化的 ✓,**没渲染出来的行不会被假装滚到** ✗(不会骗你 ✓)。
|
|
61
|
+
- **会话视图(对话 / 轨迹 / 轨迹plus …)也进地址栏** ✓:`#/session/<id>/view/<viewId>`(有工作区时是 `#/workspace/<名>/session/<id>/view/<viewId>` ✓)。**视图 id 是真的 id** ✓(来自槽位 `conversation.view` 的 `id` 字段 ✓,按 `order` 排序后与头部页签一一对应 ✓):实测本机是 `chat` / `trajectory` / **`surface`**(Trajectory Plus ✓)/ **`plus2`**(Trajectory Plus 2 ✓)。默认视图(第一个 ✓)**不写进链接** ✓,所以普通对话链接保持短 ✓。**粘贴视图链接会真的切过去** ✓(与其它覆盖层不同:这是链接存在的意义 ✓)。
|
|
62
|
+
- **工作区是"它住在哪",所以写在链接最前面** ✓:`#/workspace/<工作区名>/session/<会话id>`(侧栏本身就是这个形状 ✓)。工作区名是**给眼睛看的** ✓ —— 决定打开哪个会话的永远是会话 id ✓,所以**名字过期/写错也照样打开对的会话** ✓(地址栏随后自己纠正成真实工作区 ✓)。读不到工作区行(没有侧栏 / 树里没有)就**不猜** ✓,退回 `#/session/<id>` ✓。
|
|
63
|
+
- **作用域由视图决定,不靠猜**:主面板是应用级界面(列的是本机插件,不是某个对话),所以它的链接不带会话 id。
|
|
64
|
+
- **链接落地即交权**:视图一旦变成链接描述的那个界面,链接立刻失去权威——这样你在面板里继续点进去时,地址栏不会被拽回上一层。
|
|
65
|
+
- **绝不抛错**:官方 `selectPanel` 对未注册的面板 id 是抛异常的;所有宿主面调用都被容纳,失败只留一条诊断并回落到屏幕上真实的视图。
|
|
66
|
+
- **侧栏扫描有预算** ✓:一帧内的多次 DOM 变更合并成**一次**扫描 ✓;只带文本/普通元素的批次**直接跳过** ✓(流式输出不会一帧扫一次 ✓);工作区归属**一趟遍历**解决 ✓(不是每行走一遍树 ✗);已挂锚的行不再重挂 ✓,锚点被视图丢掉时下一趟自动补回 ✓。
|
|
67
|
+
|
|
68
|
+
### 已知限制
|
|
69
|
+
|
|
70
|
+
- **轮次链接是"位置",而且现在真能跳** ✓:点某一轮,地址栏记下 `#/session/<id>/turn/<n>` ✓;**粘贴它会打开那个对话、把历史翻页回那一轮、再滚到它** ✓(真机实测:贴 `/turn/118` → 窗口变成 118→121、目标在视口 true、最顶可见正是 118 ✓)。用的是**官方已有公开契约** ✓:`sessions.retainScope(id, source)` 拿到会话控制器 ✓ → `session.projections.faceOf('turnOutline')` 读到那一轮的 `seq` ✓ → `session.loadThrough(seq)` 翻页回去 ✓(完事 `reference.release()` ✓)→ 再按官方视口同款选择器 `[data-chat-turn]:not([hidden])` 滚到它 ✓。座位高度/相交都读不到时**不算到位** ✓,宁可继续重试也不假报 ✗。
|
|
71
|
+
- **右栏 pane 已闭环** ✓:`#/session/<id>/pane/<kind>` 与 `#/panel/<面板>/pane/<kind>` ✓(真机验证:贴链接开出对应页签 ✓、地址栏跟着切换 ✓)。页签种类由右栏自己注册 ✓(实测 7 种:`guide` / `subagentchat` / `changes-review` / `plan` / `files` / `text` / `terminal` ✓)。
|
|
72
|
+
- **设置面板已纳入**:`#/settings` ✓、**`#/settings/<分区>`** ✓、**`#/settings/<分区>/<页签>`** ✓(页签靠标准 `role="tab"` + `aria-selected` ✓,分区内任何页签都吃这一套 ✓)。分区**没有稳定 id** ✗(实测:导航项上只有 `aria-current="true"` ✓,父链是 `nav` ✓,右侧内容区一个 `data-*` 都没有 ✗;官方内部的 `openSection(id)` 也不对外 ✗)→ 所以**分区的身份就是它的显示名** ✓:反映读「`aria-current="true"` 且属于 `nav`」的那个按钮的**标签文字** ✓,驱动按标签点 ✓。含义:**换语言或官方改文案后,旧的分区链接会失效** ✗(但你重新点一次,地址栏就会写出新链接 ✓ —— 自洽、不过期 ✓)。裸 `#/settings` 只要面板开着就算落地 ✓,随后地址栏自动升级为具体分区 ✓。
|
|
73
|
+
- **设置页分区暂未纳入(旧描述)**:设置包没有"打开某个分区"的接缝(它们是 keyed list slot),只能等它自己发布类似契约。
|
|
74
|
+
- **会话内的轮次与行锚点已纳入** ✓:`#/session/<id>/turn/<n>` ✓(**反映 + 翻页 + 滚动 ✓ 全链路已闭环**)、`#/session/<id>/row/<类>/<作用域>/<id>` ✓(反映 + 尽力滚动 ✓,含可证明时的轮次归属 ✓)。轮次跳转用的是官方公开 API ✓,**没有等待任何新接缝** ✓(`uiChat.scrollToTurn` 那条请求已降级为锦上添花 ✓,讨论见 <https://github.com/deepseek-ai/deepseek-harness/discussions/9339> ✓)。
|
|
75
|
+
- **技能中心 / SSH 的内部页**:需要它们各自发布"当前实体 id + 按 id 打开"的契约(任务看板就是这么做的)。
|
|
76
|
+
- **和别的 fragment 写者互斥**(例如写 `#msg=` 的"跳到消息"插件):一个 URL 只有一个 fragment ✓,两个写者只能轮流拥有 ✗。本插件**不假装合并** ✓ —— 它认出外来 fragment ✓、**绝不覆盖** ✓,并明确说"只能启用一个写者" ✓(而不是互相静默擦掉对方的链接 ✗)。
|
|
77
|
+
- 链接**同名不跨机**:会话 id 只在同一台机器、同一个 `DSH_HOME` 下有意义。
|
|
78
|
+
|
|
79
|
+
### 开发
|
|
80
|
+
|
|
81
|
+
手写 JS 直接进 `lib/`(无构建步骤),`npm test` 直接跑交付产物(35→45 条用例,`node --test`)。改之前请读 [AGENTS.md](AGENTS.md) 里的路由与行链接契约。
|
|
82
|
+
|
|
83
|
+
### 排障
|
|
84
|
+
|
|
85
|
+
浏览器 Console 里调用 `window.__dshUrlRouter.report()` ✓,它会列出:当前地址栏 ✓、本插件认为屏幕在哪个界面 ✓、正在落地的链接与重试次数 ✓、**每一层读到了多少个钩子** ✓、右栏 pane 的**真实 kind 列表** ✓、以及它**拒绝认领**的段位 ✓。它绝不出错、也不写任何东西 ✓。
|
|
86
|
+
|
|
87
|
+
## English
|
|
88
|
+
|
|
89
|
+
**A URL router for the DSH Web GUI — every surface gets its own link.** Click a conversation and the address bar becomes `#/session/<id>`; click a panel (Plugins, Task Board, …) and it becomes `#/panel/<panelId>`; walk into a plugin, a component, or a task and the bar follows. Paste the link into another tab, or right-click any sidebar row for the browser's own "open in new tab / copy link".
|
|
90
|
+
|
|
91
|
+
It is the **single writer of the fragment**: path and query string (a launch `?token=…`) are never touched, and it only ever calls `replaceState`. **Browser half only** — no dependencies, no host route, no telemetry.
|
|
92
|
+
|
|
93
|
+
### Install
|
|
94
|
+
|
|
95
|
+
```sh
|
|
96
|
+
dsh plugin --profile web add dsh-url-router
|
|
97
|
+
# restart `dsh web`, then hard-refresh the browser
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Listed in the community plugin index: [zhu1090093659/dsh-community-plugins](https://github.com/zhu1090093659/dsh-community-plugins) keeps `community.json`, the single source for the DSH Workshop store catalog and the dsh-market.com manifest (entry `dsh-url-router`, `ui/panel`).
|
|
101
|
+
### Routes
|
|
102
|
+
|
|
103
|
+
| Route | Surface |
|
|
104
|
+
| --- | --- |
|
|
105
|
+
| `#/session/<id>` | the conversation the main view shows |
|
|
106
|
+
| `#/panel/<panelId>` | a main-column panel |
|
|
107
|
+
| `#/panel/plugins/<package>` | an installed plugin's page |
|
|
108
|
+
| `#/panel/plugins/<item>` | a built-in plugin's page (`shell`, `agent-loop`, `subagent`, `web-search`) |
|
|
109
|
+
| `#/panel/plugins/<package>/<component>` | one component page inside that plugin's page |
|
|
110
|
+
| `#/panel/task-board/task/<taskId>` | one task's detail on the task board |
|
|
111
|
+
| `#/panel/task-board/new` | the task board's new-task form |
|
|
112
|
+
|
|
113
|
+
A kind it does not know is left alone with a single diagnostic (a fragment has exactly one writer, so a foreign shape is named rather than silently ignored). Panel inner pages are the panel's own vocabulary: the plugin manager publishes `data-plugin-detail` / `data-plugin-item-detail` / `data-plugin-row-detail`, the task board publishes `data-dsh-taskboard-open-task` / `data-dsh-taskboard-new-task`.
|
|
114
|
+
|
|
115
|
+
### Every row is a real link
|
|
116
|
+
|
|
117
|
+
Conversation rows and both plugin-list groups carry a transparent full-row anchor: right-click gives the native menu, middle/Cmd-click opens a native new tab, and a plain left click navigates in place without adding a history entry.
|
|
118
|
+
|
|
119
|
+
### Rules it keeps
|
|
120
|
+
|
|
121
|
+
- **Fragment only.** Path and query are never rewritten.
|
|
122
|
+
- **One writer.** Do not run another fragment writer (`dsh-session-url`) beside it.
|
|
123
|
+
- **`replaceState` only**, so panels never fill the Back stack.
|
|
124
|
+
- **Scopes are declared, not guessed.** A panel is application-level and carries no session id.
|
|
125
|
+
- **A link stays authoritative until it lands**, then hands the address bar back.
|
|
126
|
+
- **Never throws.** Refused navigations are contained with one diagnostic.
|
|
127
|
+
|
|
128
|
+
### Limits
|
|
129
|
+
|
|
130
|
+
Still open: Skill Center / SSH inner pages, which need their own "publish the current id + accept an open request" contract the way the task board did. Session links are meaningful on the same machine and `DSH_HOME` only.
|
package/cordis.patch.yml
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
# dsh-url-router bundle patch: inserts the plugin row into the profile roster.
|
|
2
|
-
#
|
|
3
|
-
# The browser half (exports "./client") owns the URL fragment: it mirrors the view
|
|
4
|
-
# on screen into the address bar (`#/session/<id>`, `#/panel/<panelId>`) and opens
|
|
5
|
-
# the surface a link names. There is no host behavior: no route, no tool, no service.
|
|
6
|
-
#
|
|
7
|
-
# Because this plugin is the ONLY writer of the fragment, do not run it alongside
|
|
8
|
-
# another plugin that writes the fragment (for example dsh-session-url): the two
|
|
9
|
-
# would overwrite each other's URL on every notification.
|
|
10
|
-
#
|
|
11
|
-
# The entry name is the BARE package name on purpose: the client-module scanner
|
|
12
|
-
# treats it as a package specifier and resolves `<name>/package.json`, so a
|
|
13
|
-
# subpath entry would be cached as "not a client package" and the browser half
|
|
14
|
-
# would silently never load.
|
|
15
|
-
#
|
|
16
|
-
# A bundle-row change is a profile composition change: enabling, disabling or
|
|
17
|
-
# updating this plugin takes effect on the next page load for the browser half,
|
|
18
|
-
# and after a host restart for the row itself (unless the profile sets
|
|
19
|
-
# `patchReload: live`, in which case the row hot-loads and a page refresh is
|
|
20
|
-
# enough).
|
|
21
|
-
- insert:
|
|
22
|
-
- id: dsh-url-router
|
|
23
|
-
name: 'dsh-url-router'
|
|
1
|
+
# dsh-url-router bundle patch: inserts the plugin row into the profile roster.
|
|
2
|
+
#
|
|
3
|
+
# The browser half (exports "./client") owns the URL fragment: it mirrors the view
|
|
4
|
+
# on screen into the address bar (`#/session/<id>`, `#/panel/<panelId>`) and opens
|
|
5
|
+
# the surface a link names. There is no host behavior: no route, no tool, no service.
|
|
6
|
+
#
|
|
7
|
+
# Because this plugin is the ONLY writer of the fragment, do not run it alongside
|
|
8
|
+
# another plugin that writes the fragment (for example dsh-session-url): the two
|
|
9
|
+
# would overwrite each other's URL on every notification.
|
|
10
|
+
#
|
|
11
|
+
# The entry name is the BARE package name on purpose: the client-module scanner
|
|
12
|
+
# treats it as a package specifier and resolves `<name>/package.json`, so a
|
|
13
|
+
# subpath entry would be cached as "not a client package" and the browser half
|
|
14
|
+
# would silently never load.
|
|
15
|
+
#
|
|
16
|
+
# A bundle-row change is a profile composition change: enabling, disabling or
|
|
17
|
+
# updating this plugin takes effect on the next page load for the browser half,
|
|
18
|
+
# and after a host restart for the row itself (unless the profile sets
|
|
19
|
+
# `patchReload: live`, in which case the row hot-loads and a page refresh is
|
|
20
|
+
# enough).
|
|
21
|
+
- insert:
|
|
22
|
+
- id: dsh-url-router
|
|
23
|
+
name: 'dsh-url-router'
|