@monotykamary/dsh-web-app 0.1.0-rc.10

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 DeepSeek
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,6 @@
1
+ # Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
2
+ # side as of the last confirmed-consistent state. Both languages carry equal authority;
3
+ # after editing either side, bring the other along and re-record with:
4
+ # pnpm run verify-translation-pairing --write packages/bundle/web-app/README.md
5
+ README.md: 0bc66c08454ad65345fd08d607c62477861a2ba1
6
+ README.zh.md: a9a3206fe21d7bf49bea0733084f307593046d37
package/README.md ADDED
@@ -0,0 +1,33 @@
1
+ # `@monotykamary/dsh-web-app`
2
+
3
+ English | [中文](README.zh.md)
4
+
5
+ The dsh browser-surface bundle. [`cordis.patch.yml`](cordis.patch.yml) rides over [`dsh-base`](../base/README.md): it sets the coding persona, inserts the Web host rows (webserver, API gateway, workspace, projection cache, storage) and the browser plugin roster, the always-on client-plugin reload chain ([`dsh-client-hmr`](../../client/hmr/README.md), idle until a rebuild watcher rewrites client bundles), and mounts this package's `web-runtime` glue plugin (config `{printUrl, surfaceContext, trustedHosts, tailnet, portless}`). That plugin resolves the built frontend dist through `@monotykamary/dsh-web-frontend`'s exports, samples bind-dependent LAN trust once, resolves the enabled remote surfaces after the Loader tree settles (`--tailnet`: the tailscale serve DNS name; `--portless`: the `dsh.localhost` HTTPS alias) and adds their derived host authorities to the `/api` browser-trust fence through `ctx.connection.addTrustedAuthority`, provides the snapshot as `webRuntime` to the fence and client roster, mounts the [`frontend-static`](../../host/frontend-static/README.md) fallback owner, registers the harness-source and web-surface prompt sections plus the bash-visible `DSH_WEB_URL` runtime variable when `surfaceContext` is true, and prints the `dsh web:` URL line when `printUrl` is true, after its Loader tree settles so a sibling failure cannot announce a dead app. The line always leads with the canonical `http://127.0.0.1:<port>` (supervisors parse that prefix) and appends `LAN`, `tailnet`, and `portless` entries as they resolve. This bundle also owns the app command line: the ordinary `web-startup` provider ([`src/startup.ts`](src/startup.ts)) injects `ctx.cmdlineArgs` ([`dsh-cmdline`](../../boot/cmdline/README.md)), parses `--host`, `--port`, repeatable `--trusted-host`, `--tailnet`, `--portless`, and the app's `--help`, then provides `webStartup`. It rejects `--host 0.0.0.0` before publishing that service because the CLI intentionally does not support all-interfaces binding yet. `--tailnet` probes `tailscale serve status` for an HTTPS front of the bound port and `tailscale status` for the node DNS name, then trusts and announces `https://<node>.ts.net`; `--portless` registers the `dsh` alias (`portless alias dsh <port> --force`) and, while the proxy serves loopback `:443`, trusts and announces `https://dsh.localhost`. Missing tooling or an unmatched route logs a warning and leaves that surface off. Flag-configured rows inject the service and read it directly from lazy config, so nothing binds a port before argument resolution and `dsh --profile web --help` starts no server. [`dsh-headless`](../headless/README.md) is a sibling surface over the same base and does not mount this bundle.
6
+ The dsh browser-surface bundle. [`cordis.patch.yml`](cordis.patch.yml) rides over [`dsh-base`](../base/README.md): it sets the coding persona, inserts the Web host rows (webserver, API gateway, workspace, projection cache, storage) and the browser plugin roster, the always-on client-plugin reload chain ([`dsh-client-hmr`](../../client/hmr/README.md), idle until a rebuild watcher rewrites client bundles), and mounts this package's `web-runtime` glue plugin (config `{openBrowser, printUrl, surfaceContext, trustedHosts}`). That plugin resolves the built frontend dist through `@monotykamary/dsh-web-frontend`'s exports, samples bind-dependent LAN trust once, provides it as `webRuntime` to the browser-trust fence and client roster, mounts the [`frontend-static`](../../host/frontend-static/README.md) fallback owner, and registers the harness-source and web-surface prompt sections plus the bash-visible `DSH_WEB_URL` runtime variable when `surfaceContext` is true. After its Loader tree settles, it prints the `dsh web:` URL line when `printUrl` is true and opens the canonical host URL in the default browser when `openBrowser` is true and the inherited `SSH_CONNECTION` and `SSH_TTY` are blank or absent. An SSH launch keeps the URL line but suppresses browser handoff because the SSH client or editor owns the local forwarded address. Immediately before a handoff, the runtime prints `dsh web: opening the default browser; pass --no-open to disable`. A short-lived Node helper runs the maintained platform opener with the canonical scrubbed child environment. On Windows it stays alive until the short-lived PowerShell launcher exits, because `open` reports spawn before that launcher has handed the URL to the shell; elsewhere the helper stops after the opener accepts spawn. A helper failure writes a diagnostic with its reason and the manual URL to stderr without stopping the server, and no path waits for the browser to exit. This bundle also owns the app command line: the ordinary `web-startup` provider ([`src/startup.ts`](src/startup.ts)) injects `ctx.cmdlineArgs` ([`dsh-cmdline`](../../boot/cmdline/README.md)), parses `--host`, `--port`, repeatable `--trusted-host`, `--no-open`, and the app's `--help`, then provides `webStartup`; browser opening defaults on for local launches, and `--no-open` turns it off for this invocation. It rejects `--host 0.0.0.0` before publishing that service because the CLI intentionally does not support all-interfaces binding yet. Flag-configured rows inject the service and read it directly from lazy config, so nothing binds a port before argument resolution and `dsh --profile web --help` starts no server. [`dsh-headless`](../headless/README.md) is a sibling surface over the same base and does not mount this bundle.
7
+
8
+ ## Model retry defaults
9
+ Web uses the shared bounded normal default of five eligible retries after the initial request. The `deepseek-official` route and settings-added pi-ai routes use that default when they omit `retryPolicy`; explicit provider policies still win. Web adds no retry-specific composition override, so the same omission behavior applies to non-Web profiles.
10
+
11
+ ## Model Experience
12
+
13
+ ### Harness-source and Web-surface context
14
+
15
+ #### What the model sees
16
+
17
+ When `surfaceContext` is true, the `harness:source` section identifies the on-disk Harness implementation without claiming it is the working directory, and the `app:web-surface` global section (order −98) orients the model to the GUI: the canonical local URL, the "this page" referent, the update contract (the reload receiver is always on; no-refresh reloads additionally need the `pnpm run dev:web` watcher), and the instruction not to start replacement servers. `DSH_WEB_URL` additionally appears in the managed bash environment with its description, resolved per invocation from the live server. When it is false, neither section nor the variable is registered.
18
+
19
+ #### Token effect
20
+
21
+ One source line and one prompt paragraph per session plus two managed-environment variable lines; constant per process.
22
+
23
+ #### KV Cache effect
24
+
25
+ The prompt section sits near the system prompt's head and is stable for the life of the process (the port is a boot fact), so it does not invalidate the cache across turns.
26
+
27
+ ## Known Limitations and Deferred Work
28
+
29
+ - **The frontend dist must be built** — `require.resolve` of the dist fails loud at activation with a build hint; there is no source-serving fallback.
30
+ - **`lanAddresses` is a boot-time snapshot** — interface changes after boot are not re-advertised; the printed LAN URL always matches the configured trust fence.
31
+ - **Only handoff startup is observable** — observation ends when the platform opener accepts spawn, except that Windows waits for its short-lived PowerShell launcher to exit; a later browser exit is not reported, and the printed URL remains the manual fallback.
32
+ - **SSH forwarding owns the browser URL** — the printed canonical URL names the remote host's loopback endpoint; automatic handoff is suppressed, and the SSH client or editor must expose and open its local forwarded address.
33
+ - **Browser command overrides are launch-only** — a discovered `.env` may not set `BROWSER`; only an inherited value may reach an opener path that honors the variable, so a checkout cannot choose an executable for automatic handoff.
package/README.zh.md ADDED
@@ -0,0 +1,33 @@
1
+ # `@monotykamary/dsh-web-app`
2
+
3
+ [English](README.md) | 中文
4
+
5
+ dsh 浏览器表层组合包。[`cordis.patch.yml`](cordis.patch.yml) 叠加在 [`dsh-base`](../base/README.md) 之上:设置 coding persona,插入 Web 宿主行(webserver、API 网关、workspace、投影缓存、存储)、浏览器插件名录与始终挂载的客户端插件重载链([`dsh-client-hmr`](../../client/hmr/README.md),在重建 watcher 改写客户端 bundle 之前保持空闲),并挂载本包的 `web-runtime` 粘合插件(配置为 `{printUrl, surfaceContext, trustedHosts, tailnet, portless}`)。该插件通过 `@monotykamary/dsh-web-frontend` 的 exports 解析已构建的前端 dist,只采样一次依赖 bind 的 LAN 信任信息,在 Loader 配置树结算后解析已启用的远程表层(`--tailnet`:tailscale serve 的 DNS 名;`--portless`:`dsh.localhost` HTTPS 别名),通过 `ctx.connection.addTrustedAuthority` 把派生出的主机权威加入 `/api` 浏览器信任栅栏,将快照作为 `webRuntime` 提供给栅栏和客户端名录,挂载 [`frontend-static`](../../host/frontend-static/README.md) 回退席位所有者,在 `surfaceContext` 为 true 时注册 Harness 源码与 Web 表层提示词段落,以及 bash 可见的 `DSH_WEB_URL` 运行时变量,并在 `printUrl` 为 true 时等自身的 Loader 配置树结算后再打印 `dsh web:` URL 行,避免兄弟行失败时公告一个已失效的应用。该行始终以规范的 `http://127.0.0.1:<port>` 开头(监控程序解析此前缀),并随解析结果追加 `LAN`、`tailnet`、`portless` 条目。本组合包还持有应用命令行:普通 `web-startup` 提供方([`src/startup.ts`](src/startup.ts))注入 `ctx.cmdlineArgs`([`dsh-cmdline`](../../boot/cmdline/README.md)),解析 `--host`、`--port`、可重复的 `--trusted-host`、`--tailnet`、`--portless` 以及应用自己的 `--help`,再提供 `webStartup`。它会在发布该服务前拒绝 `--host 0.0.0.0`,因为 CLI 目前有意不支持绑定所有网络接口。`--tailnet` 探测 `tailscale serve status` 中绑定端口的 HTTPS 前端,并用 `tailscale status` 取节点 DNS 名,然后信任并公告 `https://<node>.ts.net`;`--portless` 注册 `dsh` 别名(`portless alias dsh <port> --force`),并在代理于回环 `:443` 上服务时信任并公告 `https://dsh.localhost`。工具缺失或路由不匹配会在启动日志打印警告并保持该表层关闭。由 flag 配置的行会注入该服务,并在惰性配置中直接读取它,因此参数解析完成前不会有任何东西绑定端口,`dsh --profile web --help` 也不会启动服务器。[`dsh-headless`](../headless/README.md) 是同一 base 之上的同级表层,不挂载本组合包。
6
+ dsh 浏览器表层组合包。[`cordis.patch.yml`](cordis.patch.yml) 叠加在 [`dsh-base`](../base/README.md) 之上:设置 coding persona,插入 Web 宿主行(webserver、API 网关、workspace、投影缓存、存储)、浏览器插件名录与始终挂载的客户端插件重载链([`dsh-client-hmr`](../../client/hmr/README.md),在重建 watcher 改写客户端 bundle 之前保持空闲),并挂载本包的 `web-runtime` 粘合插件(配置为 `{openBrowser, printUrl, surfaceContext, trustedHosts}`)。该插件通过 `@monotykamary/dsh-web-frontend` 的 exports 解析已构建的前端 dist,只采样一次依赖 bind 的 LAN 信任信息并将其作为 `webRuntime` 提供给浏览器信任栅栏和客户端名录,挂载 [`frontend-static`](../../host/frontend-static/README.md) 回退席位所有者,并在 `surfaceContext` 为 true 时注册 Harness 源码与 Web 表层提示词段落,以及 bash 可见的 `DSH_WEB_URL` 运行时变量。自身 Loader 配置树结算后,它在 `printUrl` 为 true 时打印 `dsh web:` URL 行;`openBrowser` 为 true 且继承的 `SSH_CONNECTION` 与 `SSH_TTY` 均为空或不存在时,才会用默认浏览器打开规范宿主机 URL。SSH 启动仍保留 URL 行,但会跳过浏览器交接,因为本地转发地址由 SSH 客户端或编辑器持有。交接前,运行时会打印英文提示 `dsh web: opening the default browser; pass --no-open to disable`。短生命周期 Node helper 使用规范的脱敏子进程环境运行受维护的平台 opener。在 Windows 上,helper 会保持存活,直至短生命周期的 PowerShell launcher 退出,因为 `open` 会在 launcher 把 URL 交给 shell 之前、仅在 spawn 时返回;其他平台则在 opener 接受 spawn 后结束。helper 失败时会向 stderr 写入包含原因和手动访问 URL 的诊断,不会停止服务器,且任何路径都不会等待浏览器退出。本组合包还持有应用命令行:普通 `web-startup` 提供方([`src/startup.ts`](src/startup.ts))注入 `ctx.cmdlineArgs`([`dsh-cmdline`](../../boot/cmdline/README.md)),解析 `--host`、`--port`、可重复的 `--trusted-host`、`--no-open` 以及应用自己的 `--help`,再提供 `webStartup`;本机启动默认会打开浏览器,`--no-open` 则只对本次调用关闭该行为。它会在发布该服务前拒绝 `--host 0.0.0.0`,因为 CLI 目前有意不支持绑定所有网络接口。由 flag 配置的行会注入该服务,并在惰性配置中直接读取它,因此参数解析完成前不会有任何东西绑定端口,`dsh --profile web --help` 也不会启动服务器。[`dsh-headless`](../headless/README.md) 是同一 base 之上的同级表层,不挂载本组合包。
7
+
8
+ ## 模型重试默认值
9
+ Web 使用共享的有界 normal 默认值,在首次请求后最多再重试五次符合条件的失败。`deepseek-official` 与由 settings 新增的 pi-ai 路由在省略 `retryPolicy` 时使用该默认值;显式提供方策略仍然优先。Web 不再增加重试专用的组合覆盖,因此非 Web profile 的省略行为与之相同。
10
+
11
+ ## 模型体验
12
+
13
+ ### Harness 源码与 Web 表层上下文
14
+
15
+ #### 模型看到的内容
16
+
17
+ 当 `surfaceContext` 为 true 时,`harness:source` 段落标明磁盘上的 Harness 实现,但不会声称它就是工作目录;全局段落 `app:web-surface`(顺序 −98)则向模型说明 GUI:规范的本地 URL、「this page」指代什么、更新约定(重载接收端始终开启;无刷新重载还需要 `pnpm run dev:web` watcher),以及不要启动替代服务器的指令。`DSH_WEB_URL` 还会连同描述出现在受管 bash 环境中,每次调用时从运行中的服务器解析。当它为 false 时,这两个段落和该变量都不会注册。
18
+
19
+ #### Token 影响
20
+
21
+ 每个会话一行源码说明和一段提示词,外加两行受管环境变量;每个进程内保持恒定。
22
+
23
+ #### KV Cache 影响
24
+
25
+ 该提示词段落位于系统提示词靠前位置,且在进程整个生命周期内稳定(端口是启动期事实),因此不会使跨轮次缓存失效。
26
+
27
+ ## 已知限制与延期工作
28
+
29
+ - **前端 dist 必须已构建**:对 dist 的 `require.resolve` 在激活时明确报错并给出构建提示;没有从源码直接服务的回退路径。
30
+ - **`lanAddresses` 是启动期快照**:启动后的网卡变化不会重新公告;打印的 LAN URL 始终与配置的信任栅栏一致。
31
+ - **只观测交接启动**:平台 opener 接受 spawn 后即结束观察,但 Windows 会等待其短生命周期 PowerShell launcher 退出;之后的浏览器退出不会上报,已打印 URL 仍是手动访问的回退路径。
32
+ - **SSH 转发持有浏览器 URL**:打印出的规范 URL 指向远端宿主机 loopback 端点;自动交接会被跳过,SSH 客户端或编辑器必须暴露并打开其本地转发地址。
33
+ - **浏览器命令覆盖只能来自启动环境**:被发现的 `.env` 不得设置 `BROWSER`;只有继承值可以抵达会读取该变量的 opener 路径,避免 checkout 为自动交接选择可执行文件。
@@ -0,0 +1,483 @@
1
+ # The dsh-web-app bundle patch: the browser surface over the dsh-base layer.
2
+ # Applied after dsh-base's insert; rows here override base rows by id, with
3
+ # the profile's own cordis.patch.yml and any --patch overlays still to come.
4
+ #
5
+ # A patch replaces the targeted row's whole `config`, so each row below
6
+ # restates every key it owns.
7
+ #
8
+ # The web-startup plugin injects `cmdlineArgs` and provides `webStartup` as an
9
+ # ordinary Cordis service. Rows configured from flags inject that service, so
10
+ # Loader resolves their expressions only after it exists. The web runtime then
11
+ # provides bind-dependent `webRuntime` values to the trust fence.
12
+ # `dsh --profile web --help` provides neither service, so no server binds.
13
+
14
+ # ── surface-specific values the base deliberately omits ─────────────────────
15
+
16
+ - id: system-prompt
17
+ config:
18
+ persona: >-
19
+ You are a coding agent powered by the {{model}} model. Your working directory is {{cwd}}.
20
+
21
+ # TODO: Re-enable shared HMR for Web after its reload lifecycle is tested.
22
+ - id: hmr
23
+ disabled: true
24
+
25
+ # Full-text session search is opt-in (the base row's `openAt: never`). This
26
+ # restatement keeps the Web values on one ephemeral in-memory index; a
27
+ # deployment enabling content search overrides `openAt` to `first-search` in a
28
+ # later patch layer, which defers the node:sqlite import and in-memory handle
29
+ # to the first search so Node 22 startup stays quiet.
30
+ - id: session-query-sqlite
31
+ config:
32
+ path: ':memory:'
33
+ openAt: never
34
+
35
+ # DSH_TOOLS_MODE (native|code|both) opts a whole dsh process into Code Mode
36
+ # while per-session tool-presentation selection is being designed; unset keeps
37
+ # the schema default (native). The dsh launcher applies the selection ABOVE
38
+ # every bundle layer (apps/cli/src/profile-boot.ts), so a custom-flavor bundle
39
+ # restating the tools row cannot silently drop it; remove that launcher seam
40
+ # once the web UI owns the choice per session.
41
+
42
+ # ── web-only host rows, the transport layer, and the browser roster ─────────
43
+
44
+ # `dsh.client` rows are the browser roster the modules node half scans into
45
+ # window.__DSH_BOOT__; the modules row is simultaneously a host row.
46
+ - insert:
47
+ - id: code-runtime
48
+ name: '@monotykamary/dsh-code-runtime-worker-thread'
49
+
50
+ - id: storage
51
+ name: '@monotykamary/dsh-storage'
52
+
53
+ - id: storage-json
54
+ name: '@monotykamary/dsh-storage-json'
55
+ config:
56
+ root: !!js dshHomePath('storages')
57
+
58
+ - id: storage-domain
59
+ name: '@monotykamary/dsh-storage-domain'
60
+ config:
61
+ backend: json
62
+
63
+ - id: message-feedback
64
+ name: '@monotykamary/dsh-message-feedback'
65
+ config:
66
+ maxNoteBytes: 8192
67
+
68
+ # Browser Session export: `/export` command plus the shared download dialog.
69
+ - id: session-log-download
70
+ name: '@monotykamary/dsh-session-log-export'
71
+
72
+ - id: workspace
73
+ name: '@monotykamary/dsh-workspace'
74
+
75
+ - id: session-projection-cache
76
+ name: '@monotykamary/dsh-session-projection-cache'
77
+ config:
78
+ writeEveryEvents: 200
79
+ writeIntervalMs: 5000
80
+
81
+ - id: session-reference
82
+ name: '@monotykamary/dsh-session-reference'
83
+
84
+ - id: file-reference-local
85
+ name: '@monotykamary/dsh-file-reference-local'
86
+
87
+ # Whole-log turn/step counts for the chat stats strip (the sessionStats
88
+ # projection key); the projection registry itself is a base-layer row.
89
+ - id: session-stats
90
+ name: '@monotykamary/dsh-session-stats'
91
+
92
+ # Resolve bind host, SSH launch, and display once at boot, then mount the
93
+ # matching dual-face directory picker. Mount -native or -browse directly in
94
+ # an overlay to pin the interaction.
95
+ - id: directory-picker
96
+ name: '@monotykamary/dsh-host-directory-picker-auto'
97
+
98
+ # Read-only projection of current Loader entries for trusted client RPCs.
99
+ - id: plugin-inventory
100
+ name: '@monotykamary/dsh-host-plugin-inventory'
101
+
102
+ # Session-authorized file tree, bounded reads, and guarded edits over each Agent's selected fs provider.
103
+ - id: workspace-files
104
+ name: '@monotykamary/dsh-host-workspace-files'
105
+
106
+ # The API gateway: the transport-agnostic dispatch face every client shape
107
+ # shares. The base layer's agent-default-model service owns the default model.
108
+ - id: api-gateway
109
+ name: '@monotykamary/dsh-host-apiproxy'
110
+
111
+ - id: cordis-host-runner
112
+ name: '@monotykamary/dsh-cordis-host-runner'
113
+
114
+ # Ordinary provider for the parsed Web flags. Its plugin-level injection
115
+ # waits for cmdlineArgs; no launcher metadata or special row kind is needed.
116
+ - id: web-startup
117
+ name: '@monotykamary/dsh-web-app/startup'
118
+
119
+ # ── layer 2: transport/service ──────────────────────────────────────────────
120
+
121
+ # Plain route-registration carrier; host and port come from the app's
122
+ # webStartup provider, with these deployment fallbacks. The dist is served by
123
+ # the web-runtime row below through the fallback seat.
124
+ - id: webserver
125
+ name: '@monotykamary/dsh-host-webserver'
126
+ inject: [webStartup]
127
+ config:
128
+ host: !!js ctx.webStartup.host ?? '127.0.0.1'
129
+ port: !!js ctx.webStartup.port ?? 3080
130
+
131
+ # Web glue owned by this bundle: resolves the built frontend dist (an
132
+ # assembly fact of dsh-web-app, never user config), mounts the
133
+ # frontend-static fallback owner, registers the web-surface prompt
134
+ # section and the bash runtime variable, prints the URL line, and opens the
135
+ # canonical local URL after the full tree settles. The webStartup provider
136
+ # supplies invocation-only values; after the server binds, this row samples
137
+ # LAN trust once, resolves the enabled remote surfaces (tailnet/portless)
138
+ # when the tree settles, and provides `webRuntime`. A complete agent-preset
139
+ # persona suppresses the prompt section for that agent while retaining the
140
+ # host-owned shell variable.
141
+ - id: web-runtime
142
+ name: '@monotykamary/dsh-web-app'
143
+ inject: [webStartup]
144
+ config:
145
+ openBrowser: !!js ctx.webStartup.openBrowser
146
+ printUrl: true
147
+ surfaceContext: true
148
+ trustedHosts: !!js ctx.webStartup.trustedHosts
149
+ tailnet: !!js ctx.webStartup.tailnet
150
+ portless: !!js ctx.webStartup.portless
151
+
152
+ # The client-plugin reload chain, always mounted: it is idle until a
153
+ # rebuild watcher (pnpm run dev:web) actually rewrites client bundles. It
154
+ # is a row rather than a child of web-runtime because its node half is a
155
+ # client-side package, which a host-side bundle cannot import.
156
+ - id: client-hmr
157
+ name: '@monotykamary/dsh-client-hmr'
158
+
159
+ # Web identity authority (SSO): absent --identity, provides nothing and the
160
+ # /api plane stays the pre-identity operator tier. --identity header trusts
161
+ # a reverse proxy's user header from a trusted source; --identity passkey
162
+ # runs the WebAuthn login under /auth/passkey and gates /api + WebSocket
163
+ # upgrades, admitting the operator through the generated bearer token.
164
+ - id: web-identity
165
+ name: '@monotykamary/dsh-web-identity'
166
+ inject: [webStartup]
167
+ config:
168
+ identity: !!js ctx.webStartup.identity
169
+
170
+ # ── browser plugin roster (dsh.client rows; node halves are layer-2 hosts) ──
171
+
172
+ # Dual-face: the node half scans this tree, composes window.__DSH_BOOT__,
173
+ # and serves /plugins/<id>/client.js; the browser half is the module table
174
+ # the shell kernel constructs before cordis exists (adopted as a plugin
175
+ # entry by the kernel, never fetched).
176
+ - id: modules
177
+ name: '@monotykamary/dsh-client-modules'
178
+
179
+ # Owns both ends of the web transport: node half binds the gateway to the
180
+ # webserver under /api; browser half is the fetch/SSE client.
181
+ - id: connection
182
+ name: '@monotykamary/dsh-client-connection'
183
+ inject: [webRuntime]
184
+ config:
185
+ # LAN literals derived from the active bind plus --trusted-host extras.
186
+ # A deployment adding authorities keeps this expression and concatenates
187
+ # its literals, for example: ['app.internal', ...ctx.webRuntime.trustedHosts].
188
+ trustedHosts: !!js ctx.webRuntime.trustedHosts
189
+
190
+ # Full-duplex browser attachment to each selected Agent's persistent terminals.
191
+ - id: terminal-web
192
+ name: '@monotykamary/dsh-terminal-web'
193
+
194
+ - id: api-remotes
195
+ name: '@monotykamary/dsh-api-remotes'
196
+
197
+ - id: client-runtime
198
+ name: '@monotykamary/dsh-client-runtime'
199
+
200
+ - id: cordis-client-runner
201
+ name: '@monotykamary/dsh-cordis-client-runner'
202
+
203
+ - id: ui-theme
204
+ name: '@monotykamary/dsh-client-ui-theme'
205
+
206
+ - id: locale
207
+ name: '@monotykamary/dsh-client-locale'
208
+
209
+ - id: ui-layout
210
+ name: '@monotykamary/dsh-client-ui-layout'
211
+
212
+ - id: ui-workbench
213
+ name: '@monotykamary/dsh-client-ui-workbench'
214
+
215
+ - id: ui-files
216
+ name: '@monotykamary/dsh-client-ui-files'
217
+
218
+ - id: ui-terminal
219
+ name: '@monotykamary/dsh-client-ui-terminal'
220
+
221
+ - id: ui-command-palette
222
+ name: '@monotykamary/dsh-client-ui-command-palette'
223
+
224
+ - id: ui-sidebar
225
+ name: '@monotykamary/dsh-client-ui-sidebar'
226
+
227
+ - id: ui-settings
228
+ name: '@monotykamary/dsh-client-ui-settings'
229
+
230
+ - id: ui-settings-general
231
+ name: '@monotykamary/dsh-client-ui-settings-general'
232
+
233
+ - id: ui-settings-models
234
+ name: '@monotykamary/dsh-client-ui-settings-models'
235
+
236
+ - id: ui-settings-plugin-inventory
237
+ name: '@monotykamary/dsh-client-ui-settings-plugin-inventory'
238
+
239
+ - id: ui-conversation
240
+ name: '@monotykamary/dsh-client-ui-conversation'
241
+
242
+ # Official occupants for the generic sidebar and conversation brand slots.
243
+ - id: ui-brand-official
244
+ name: '@monotykamary/dsh-client-ui-brand-official'
245
+
246
+ - id: ui-attachment
247
+ name: '@monotykamary/dsh-client-ui-attachment'
248
+
249
+ # Tool call tree, generic fallback, and keyed business Tool views.
250
+ - id: ui-tool
251
+ name: '@monotykamary/dsh-client-ui-tool'
252
+
253
+ - id: ui-cordis
254
+ name: '@monotykamary/dsh-client-ui-cordis'
255
+
256
+ # Durable workflow lifecycle as an independent Chat node after the
257
+ # existing generic workflow tool row.
258
+ - id: ui-workflow-run
259
+ name: '@monotykamary/dsh-client-ui-workflow-run'
260
+
261
+ # Turn tail: the produced-files row under each closing assistant message.
262
+ # Remove this entry to turn the surface off; the tail hole renders empty.
263
+ - id: ui-deliverables
264
+ name: '@monotykamary/dsh-client-ui-deliverables'
265
+
266
+
267
+ - id: ui-workspace
268
+ name: '@monotykamary/dsh-client-ui-workspace'
269
+ config:
270
+ autoSettleInactive: true
271
+ autoSettleAfterDays: 3
272
+
273
+ # Input triggers: the '/' | '@' pipeline (ui-input-trigger), the command surface over
274
+ # it (ui-commands), and the reference sources (ui-skill / ui-reference).
275
+ - id: ui-input-trigger
276
+ name: '@monotykamary/dsh-client-ui-input-trigger'
277
+
278
+ - id: ui-commands
279
+ name: '@monotykamary/dsh-client-ui-commands'
280
+
281
+ - id: ui-skill
282
+ name: '@monotykamary/dsh-client-ui-skill'
283
+
284
+ - id: ui-subagent
285
+ name: '@monotykamary/dsh-client-ui-subagent'
286
+
287
+ - id: ui-reference
288
+ name: '@monotykamary/dsh-client-ui-reference'
289
+
290
+ # Background jobs: the session-header list over the jobsBySession mirror.
291
+ - id: ui-jobs
292
+ name: '@monotykamary/dsh-client-ui-jobs'
293
+
294
+ # Goal surface: GoalBar in the input dock over the goal session projection.
295
+ - id: ui-goal
296
+ name: '@monotykamary/dsh-client-ui-goal'
297
+
298
+ # Per-message feedback: Like/Dislike plus an optional note in the
299
+ # assistant-message action strip, over the messageFeedback Remote.
300
+ - id: ui-message-feedback
301
+ name: '@monotykamary/dsh-client-ui-message-feedback'
302
+
303
+ # Model selection: the /model popupSelect + composer seat over session.models.
304
+ - id: ui-model-selection
305
+ name: '@monotykamary/dsh-client-ui-model-selection'
306
+
307
+ - id: ui-permission
308
+ name: '@monotykamary/dsh-client-ui-permission-presets'
309
+
310
+ # The agent-preset row in General settings: the default preset for
311
+ # sessions created later. Absent a roster it renders nothing.
312
+ - id: ui-agent-preset
313
+ name: '@monotykamary/dsh-client-ui-agent-preset'
314
+
315
+ # Plugin configuration: the host-plane sections a user owns, as expandable
316
+ # cards. A namespace this deployment does not expose renders nothing.
317
+ - id: ui-settings-plugins
318
+ name: '@monotykamary/dsh-client-ui-settings-plugins'
319
+
320
+ # Plan control: the composer plan seat over the plan projection + /plan channel.
321
+ - id: ui-plan
322
+ name: '@monotykamary/dsh-client-ui-plan'
323
+
324
+ # Automatic LLM session titles: the General settings toggle over the
325
+ # host `session-title-llm` settings section (off by default).
326
+ - id: ui-session-title
327
+ name: '@monotykamary/dsh-client-ui-session-title'
328
+
329
+ - id: ui-user-questions
330
+ name: '@monotykamary/dsh-client-ui-user-questions'
331
+
332
+ - id: ui-trajectory
333
+ name: '@monotykamary/dsh-client-ui-trajectory'
334
+
335
+ # ── the agent plane moves behind agent presets ─────────────────────────────
336
+ #
337
+ # Every row below composes what ONE agent contributes to the host registries:
338
+ # its tools, its prompt sections, its delegation backends. The base keeps them
339
+ # for the TUI, which is single-session and composes its agent process-wide; the
340
+ # Web surface disables them here and lets each session mount a preset instead.
341
+ #
342
+ # Disabling rather than deleting is deliberate: the base is shared, and a row
343
+ # absent from a surface overlay would silently reappear the day someone reorders
344
+ # the composition.
345
+
346
+ # `shell-env` STAYS in the host plane: `apps/cli/src/web.ts` injects it to
347
+ # publish `DSH_WEB_URL`/`DSH_WEB_MODE`, and a host row that injects a service is
348
+ # the criterion for host-plane ownership — injection resolves before any session
349
+ # exists, so there is no agent to key by. Behind a preset realm those variables
350
+ # would never reach the model's shell at all.
351
+
352
+ - id: tool-bash
353
+ disabled: true
354
+
355
+ - id: tool-pwsh
356
+ disabled: true
357
+
358
+ # The background-job REGISTRY stays on the host plane; only the model-facing
359
+ # `job_*` controls move. Its producers — `tool-bash` here, `tool-terminal` and a
360
+ # non-continuable `tool-subagent` elsewhere — are preset rows that resolve it
361
+ # with `ctx.get`, and an entry-local realm around the registry is invisible to
362
+ # every sibling row outside that realm, so `run_in_background` answered
363
+ # "background jobs unavailable" while the controls sat in the catalog. That is
364
+ # the `goals` criterion read from inside the preset: a Service a row outside its
365
+ # realm READS belongs to the plane both can see. The registry is keyed by owning
366
+ # agent, so one host instance serves every session exactly as before presets.
367
+
368
+ - id: tool-jobs
369
+ disabled: true
370
+
371
+ - id: tool-fs
372
+ disabled: true
373
+
374
+ - id: tool-fs-search
375
+ disabled: true
376
+
377
+ - id: tool-str-replace-editor
378
+ disabled: true
379
+
380
+ # The `skill` REGISTRY stays in the host plane. It is host+per-scope layered
381
+ # (the tools-registry shape): deployment-level providers — repository plugins,
382
+ # a host skill-filesystem row — register into its global layer, while a preset's
383
+ # `skill-filesystem` registers into that preset's layer, and each agent reads the
384
+ # merged catalog its scope chain selects. Only the per-agent rows move behind
385
+ # presets: the base host `skill-filesystem` row is disabled here (presets own local
386
+ # discovery), and `tool-skill` is what a preset mounts to give its agent the
387
+ # catalog and loader at all.
388
+
389
+ - id: skill-filesystem
390
+ disabled: true
391
+
392
+ - id: tool-skill
393
+ disabled: true
394
+
395
+ # The goal SERVICE, its session driver, and the `/goal` command STAY on the
396
+ # host plane; only the model-facing tool moves. The Gateway serves the goal
397
+ # domain as Remote endpoints, and a Remote method picks its receiver Service
398
+ # from a generated descriptor — it resolves `goals` on the host, so a
399
+ # per-session realm would answer `service-unavailable` for every browser call.
400
+ # That is the `shell-env` criterion read from the other side: injection is not
401
+ # the only host relationship a Service can have. The registry is keyed by
402
+ # session, so one host instance serves every session exactly as before presets.
403
+
404
+ - id: tool-goal
405
+ disabled: true
406
+
407
+ - id: plan-mode
408
+ disabled: true
409
+
410
+ # The token METER stays on the host plane; only the compaction backend that
411
+ # reads it moves. It owns the context-meter projection units, and that table is
412
+ # process-wide, so preset ownership would make the meter a function of which
413
+ # presets happen to be mounted rather than a per-session fact. Same criterion as
414
+ # `tasks` and `goals`; the reasoning has one home in
415
+ # `.agents/notes/implemented/architecture/2026-08-10-host-plane-ownership-after-presets.md`.
416
+
417
+ - id: compaction-basic
418
+ disabled: true
419
+
420
+ - id: command-compact
421
+ disabled: true
422
+
423
+ - id: tool-result-pruner
424
+ disabled: true
425
+
426
+ # The subagent registry and its backends STAY in the host plane. `subagents` is
427
+ # a process singleton with a cross-session query surface (`listChildren`,
428
+ # `followup`) that the host api-proxy serves to the browser, and a provider
429
+ # registers under a globally unique name, so a per-session copy would both
430
+ # starve that host row and collide on the second session. What a preset
431
+ # chooses is which delegation TOOLS its agent sees, below.
432
+
433
+ - id: tool-subagent-control
434
+ disabled: true
435
+
436
+ - id: tool-subagent-list-agents
437
+ disabled: true
438
+
439
+ - id: tool-subagent
440
+ disabled: true
441
+
442
+ - id: tool-subagent-fork
443
+ disabled: true
444
+
445
+ # `tool-subagent-report` is host-plane for the same reason as the registry, not
446
+ # because a preset may not want it: it registers a CONTINUABLE SETUP on that
447
+ # singleton rather than a tool this agent calls, and the setup list is not
448
+ # scope-aware — one copy per mounted preset means every child gets `report`
449
+ # registered once per live session, which throws on the second.
450
+
451
+ - id: workflow-worker-thread
452
+ disabled: true
453
+
454
+ - id: tool-workflow
455
+ disabled: true
456
+
457
+ - id: tool-ralph
458
+ disabled: true
459
+
460
+ - id: agent-instructions
461
+ disabled: true
462
+
463
+ - id: tool-todo
464
+ disabled: true
465
+
466
+ - id: tool-web
467
+ disabled: true
468
+
469
+ # The preset roster. `config/agent-presets/` ships with the deployment and is
470
+ # read-only (its entries carry `system` trust); `$DSH_HOME/.agent-presets` is
471
+ # where a person — or an agent — authors their own, and carries the same trust
472
+ # as shell access because a preset IS a composition.
473
+ #
474
+ # Only the SHIPPED root is an assembly fact: it sits beside the installed app's
475
+ # own config, so `apps/cli`'s `composeProfile` resolves and patches it in — the
476
+ # same treatment `distIndex` gets on the webserver row. The writable root is
477
+ # `dsh-agent-presets`' own default (`includeUserRoot`), so a composition that
478
+ # never reaches that patch still finds a person's presets.
479
+ - insert:
480
+ - id: agent-presets
481
+ name: '@monotykamary/dsh-agent-presets'
482
+ config:
483
+ default: standard