refactor: apply repository naming contract
Apply the accepted pre-release package, service, type, directory, and role renames as one repository-wide change.
This commit is contained in:
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write packages/bundle/web-app/README.md
|
||||
README.md: 06856a47cd8ccc2c6ee5a53c40928b1bd2933cc7
|
||||
README.zh.md: 8befc7c7404ea1b082842f122769967fff32df2f
|
||||
README.md: 3f7fbe7bbbeba2ee753ab2dfa8c945e798dd6a02
|
||||
README.zh.md: 357ca9946ed7fef1bf4c691c6666156bb293b5e0
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
English | [中文](README.zh.md)
|
||||
|
||||
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}`). That plugin resolves the built frontend dist through `@deepseek-ai/dsh-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, 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. 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`, and the app's `--help`, then provides `webStartup`. Flag-configured rows inject that 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.
|
||||
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}`). That plugin resolves the built frontend dist through `@deepseek-ai/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, 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. 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`, and the app's `--help`, then provides `webStartup`. Flag-configured rows inject that 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.
|
||||
|
||||
## Model Experience
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
[English](README.md) | 中文
|
||||
|
||||
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}`)。该插件通过 `@deepseek-ai/dsh-frontend` 的 exports 解析已构建的前端 dist,只采样一次依赖 bind 的 LAN 信任信息并将其作为 `webRuntime` 提供给浏览器信任栅栏和客户端名录,挂载 [`frontend-static`](../../host/frontend-static/README.md) 回退席位所有者,在 `surfaceContext` 为 true 时注册 Harness 源码与 Web 表层提示词段落,以及 bash 可见的 `DSH_WEB_URL` 运行时变量,并在 `printUrl` 为 true 时等自身的 Loader 配置树结算后再打印 `dsh web:` URL 行,避免兄弟行失败时公告一个已失效的应用。本组合包还持有应用命令行:普通 `web-startup` 提供方([`src/startup.ts`](src/startup.ts))注入 `ctx.cmdlineArgs`([`dsh-cmdline`](../../boot/cmdline/README.md)),解析 `--host`、`--port`、可重复的 `--trusted-host` 以及应用自己的 `--help`,再提供 `webStartup`。由 flag 配置的行会注入该服务,并在惰性配置中直接读取它,因此参数解析完成前不会有任何东西绑定端口,`dsh --profile web --help` 也不会启动服务器。[`dsh-headless`](../headless/README.md) 是同一 base 之上的同级表层,不挂载本组合包。
|
||||
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}`)。该插件通过 `@deepseek-ai/dsh-web-frontend` 的 exports 解析已构建的前端 dist,只采样一次依赖 bind 的 LAN 信任信息并将其作为 `webRuntime` 提供给浏览器信任栅栏和客户端名录,挂载 [`frontend-static`](../../host/frontend-static/README.md) 回退席位所有者,在 `surfaceContext` 为 true 时注册 Harness 源码与 Web 表层提示词段落,以及 bash 可见的 `DSH_WEB_URL` 运行时变量,并在 `printUrl` 为 true 时等自身的 Loader 配置树结算后再打印 `dsh web:` URL 行,避免兄弟行失败时公告一个已失效的应用。本组合包还持有应用命令行:普通 `web-startup` 提供方([`src/startup.ts`](src/startup.ts))注入 `ctx.cmdlineArgs`([`dsh-cmdline`](../../boot/cmdline/README.md)),解析 `--host`、`--port`、可重复的 `--trusted-host` 以及应用自己的 `--help`,再提供 `webStartup`。由 flag 配置的行会注入该服务,并在惰性配置中直接读取它,因此参数解析完成前不会有任何东西绑定端口,`dsh --profile web --help` 也不会启动服务器。[`dsh-headless`](../headless/README.md) 是同一 base 之上的同级表层,不挂载本组合包。
|
||||
|
||||
## 模型体验
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
- id: tools
|
||||
config:
|
||||
# TEMPORARY workaround: DSH_TOOLS_MODE (native|code|both) opts a whole dsh
|
||||
# process into Code Mode while per-session tool-mode selection is being
|
||||
# process into Code Mode while per-session tool-presentation selection is being
|
||||
# designed; unset keeps the schema default (native). Remove the env seam
|
||||
# once the web UI owns the choice per session.
|
||||
mode: !!js process.env.DSH_TOOLS_MODE
|
||||
@@ -45,7 +45,7 @@
|
||||
# window.__DSH_BOOT__; the modules row is simultaneously a host row.
|
||||
- insert:
|
||||
- id: code-runtime
|
||||
name: '@deepseek-ai/dsh-code-runtime-worker'
|
||||
name: '@deepseek-ai/dsh-code-runtime-worker-thread'
|
||||
|
||||
- id: storage
|
||||
name: '@deepseek-ai/dsh-storage'
|
||||
@@ -66,8 +66,8 @@
|
||||
maxNoteBytes: 8192
|
||||
|
||||
# Browser Session export: `/export` command plus the shared download dialog.
|
||||
- id: session-export
|
||||
name: '@deepseek-ai/dsh-session-export'
|
||||
- id: session-log-download
|
||||
name: '@deepseek-ai/dsh-session-log-download'
|
||||
|
||||
- id: workspace
|
||||
name: '@deepseek-ai/dsh-workspace'
|
||||
@@ -182,11 +182,11 @@
|
||||
- id: ui-settings-general
|
||||
name: '@deepseek-ai/dsh-client-ui-settings-general'
|
||||
|
||||
- id: ui-models
|
||||
name: '@deepseek-ai/dsh-client-ui-models'
|
||||
- id: ui-settings-models
|
||||
name: '@deepseek-ai/dsh-client-ui-settings-models'
|
||||
|
||||
- id: ui-plugins
|
||||
name: '@deepseek-ai/dsh-client-ui-plugins'
|
||||
- id: ui-settings-plugin-inventory
|
||||
name: '@deepseek-ai/dsh-client-ui-settings-plugin-inventory'
|
||||
|
||||
- id: ui-conversation
|
||||
name: '@deepseek-ai/dsh-client-ui-conversation'
|
||||
@@ -209,13 +209,13 @@
|
||||
- id: ui-workspace
|
||||
name: '@deepseek-ai/dsh-client-ui-workspace'
|
||||
|
||||
# Input triggers: the '/' | '@' pipeline (ui-slash), the command surface over
|
||||
# it (ui-command), and the two reference sources (ui-skill / ui-subagent).
|
||||
- id: ui-slash
|
||||
name: '@deepseek-ai/dsh-client-ui-slash'
|
||||
# Input triggers: the '/' | '@' pipeline (ui-input-trigger), the command surface over
|
||||
# it (ui-commands), and the two reference sources (ui-skill / ui-subagent).
|
||||
- id: ui-input-trigger
|
||||
name: '@deepseek-ai/dsh-client-ui-input-trigger'
|
||||
|
||||
- id: ui-command
|
||||
name: '@deepseek-ai/dsh-client-ui-command'
|
||||
- id: ui-commands
|
||||
name: '@deepseek-ai/dsh-client-ui-commands'
|
||||
|
||||
- id: ui-skill
|
||||
name: '@deepseek-ai/dsh-client-ui-skill'
|
||||
@@ -223,9 +223,9 @@
|
||||
- id: ui-subagent
|
||||
name: '@deepseek-ai/dsh-client-ui-subagent'
|
||||
|
||||
# Background tasks: the session-header list over the tasksBySession mirror.
|
||||
- id: ui-task
|
||||
name: '@deepseek-ai/dsh-client-ui-task'
|
||||
# Background jobs: the session-header list over the jobsBySession mirror.
|
||||
- id: ui-jobs
|
||||
name: '@deepseek-ai/dsh-client-ui-jobs'
|
||||
|
||||
# Goal surface: GoalBar in the input dock over the goal session projection.
|
||||
- id: ui-goal
|
||||
@@ -233,15 +233,15 @@
|
||||
|
||||
# Per-message feedback: Like/Dislike plus an optional note in the
|
||||
# assistant-message action strip, over the messageFeedback Remote.
|
||||
- id: ui-feedback
|
||||
name: '@deepseek-ai/dsh-client-ui-feedback'
|
||||
- id: ui-message-feedback
|
||||
name: '@deepseek-ai/dsh-client-ui-message-feedback'
|
||||
|
||||
# Model selection: the /model popupSelect + composer seat over session.models.
|
||||
- id: ui-model
|
||||
name: '@deepseek-ai/dsh-client-ui-model'
|
||||
- id: ui-model-selection
|
||||
name: '@deepseek-ai/dsh-client-ui-model-selection'
|
||||
|
||||
- id: ui-permission
|
||||
name: '@deepseek-ai/dsh-client-ui-permission'
|
||||
name: '@deepseek-ai/dsh-client-ui-permission-presets'
|
||||
|
||||
# The agent-preset row in General settings: the default preset for
|
||||
# sessions created later. Absent a roster it renders nothing.
|
||||
@@ -250,15 +250,15 @@
|
||||
|
||||
# Plugin configuration: the host-plane sections a user owns, as expandable
|
||||
# cards. A namespace this deployment does not expose renders nothing.
|
||||
- id: ui-plugin-config
|
||||
name: '@deepseek-ai/dsh-client-ui-plugin-config'
|
||||
- id: ui-settings-plugins
|
||||
name: '@deepseek-ai/dsh-client-ui-settings-plugins'
|
||||
|
||||
# Plan control: the composer plan seat over the plan projection + /plan channel.
|
||||
- id: ui-plan
|
||||
name: '@deepseek-ai/dsh-client-ui-plan'
|
||||
|
||||
- id: ui-question
|
||||
name: '@deepseek-ai/dsh-client-ui-question'
|
||||
- id: ui-user-questions
|
||||
name: '@deepseek-ai/dsh-client-ui-user-questions'
|
||||
|
||||
- id: ui-trajectory
|
||||
name: '@deepseek-ai/dsh-client-ui-trajectory'
|
||||
@@ -274,7 +274,7 @@
|
||||
# absent from a surface overlay would silently reappear the day someone reorders
|
||||
# the composition.
|
||||
|
||||
# `bash-env` STAYS in the host plane: `apps/cli/src/web.ts` injects it to
|
||||
# `shell-env` STAYS in the host plane: `apps/cli/src/web.ts` injects it to
|
||||
# publish `DSH_WEB_URL`/`DSH_WEB_MODE`, and a host row that injects a service is
|
||||
# the criterion for host-plane ownership — injection resolves before any session
|
||||
# exists, so there is no agent to key by. Behind a preset realm those variables
|
||||
@@ -286,17 +286,17 @@
|
||||
- id: tool-pwsh
|
||||
disabled: true
|
||||
|
||||
# The background-task REGISTRY stays on the host plane; only the model-facing
|
||||
# `task_*` controls move. Its producers — `tool-bash` here, `tool-pty` and a
|
||||
# The background-job REGISTRY stays on the host plane; only the model-facing
|
||||
# `job_*` controls move. Its producers — `tool-bash` here, `tool-terminal` and a
|
||||
# non-continuable `tool-subagent` elsewhere — are preset rows that resolve it
|
||||
# with `ctx.get`, and an entry-local realm around the registry is invisible to
|
||||
# every sibling row outside that realm, so `run_in_background` answered
|
||||
# "background tasks unavailable" while the controls sat in the catalog. That is
|
||||
# "background jobs unavailable" while the controls sat in the catalog. That is
|
||||
# the `goals` criterion read from inside the preset: a Service a row outside its
|
||||
# realm READS belongs to the plane both can see. The registry is keyed by owning
|
||||
# agent, so one host instance serves every session exactly as before presets.
|
||||
|
||||
- id: tool-tasks
|
||||
- id: tool-jobs
|
||||
disabled: true
|
||||
|
||||
- id: tool-fs
|
||||
@@ -310,14 +310,14 @@
|
||||
|
||||
# The `skill` REGISTRY stays in the host plane. It is host+per-scope layered
|
||||
# (the tools-registry shape): deployment-level providers — repository plugins,
|
||||
# a host skill-local row — register into its global layer, while a preset's
|
||||
# `skill-local` registers into that preset's layer, and each agent reads the
|
||||
# a host skill-filesystem row — register into its global layer, while a preset's
|
||||
# `skill-filesystem` registers into that preset's layer, and each agent reads the
|
||||
# merged catalog its scope chain selects. Only the per-agent rows move behind
|
||||
# presets: the base host `skill-local` row is disabled here (presets own local
|
||||
# presets: the base host `skill-filesystem` row is disabled here (presets own local
|
||||
# discovery), and `tool-skill` is what a preset mounts to give its agent the
|
||||
# catalog and loader at all.
|
||||
|
||||
- id: skill-local
|
||||
- id: skill-filesystem
|
||||
disabled: true
|
||||
|
||||
- id: tool-skill
|
||||
@@ -328,7 +328,7 @@
|
||||
# domain as Remote endpoints, and a Remote method picks its receiver Service
|
||||
# from a generated descriptor — it resolves `goals` on the host, so a
|
||||
# per-session realm would answer `service-unavailable` for every browser call.
|
||||
# That is the `bash-env` criterion read from the other side: injection is not
|
||||
# That is the `shell-env` criterion read from the other side: injection is not
|
||||
# the only host relationship a Service can have. The registry is keyed by
|
||||
# session, so one host instance serves every session exactly as before presets.
|
||||
|
||||
@@ -345,13 +345,13 @@
|
||||
# `tasks` and `goals`; the reasoning has one home in
|
||||
# `.agents/notes/implemented/architecture/2026-08-10-host-plane-ownership-after-presets.md`.
|
||||
|
||||
- id: compact-basic
|
||||
- id: compaction-basic
|
||||
disabled: true
|
||||
|
||||
- id: command-compact
|
||||
disabled: true
|
||||
|
||||
- id: tool-result-prune
|
||||
- id: tool-result-pruner
|
||||
disabled: true
|
||||
|
||||
# The subagent registry and its backends STAY in the host plane. `subagents` is
|
||||
@@ -379,7 +379,7 @@
|
||||
# scope-aware — one copy per mounted preset means every child gets `report`
|
||||
# registered once per live session, which throws on the second.
|
||||
|
||||
- id: workflow-workerthread
|
||||
- id: workflow-worker-thread
|
||||
disabled: true
|
||||
|
||||
- id: tool-workflow
|
||||
@@ -388,7 +388,7 @@
|
||||
- id: tool-ralph
|
||||
disabled: true
|
||||
|
||||
- id: workspace-context
|
||||
- id: agent-instructions
|
||||
disabled: true
|
||||
|
||||
- id: tool-todo
|
||||
|
||||
@@ -53,37 +53,37 @@
|
||||
"@deepseek-ai/dsh-client-modules": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-runtime": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-agent-preset": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-command": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-commands": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-conversation": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-deliverables": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-directory-picker": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-directory-picker-browse": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-directory-picker-native": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-feedback": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-message-feedback": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-goal": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-layout": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-model": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-models": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-plugins": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-permission": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-model-selection": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-settings-models": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-settings-plugin-inventory": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-permission-presets": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-plan": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-plugin-config": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-question": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-settings-plugins": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-user-questions": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-settings": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-settings-general": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-sidebar": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-skill": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-slash": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-input-trigger": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-subagent": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-task": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-jobs": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-theme": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-tool": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-workflow-run": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-trajectory": "workspace:^",
|
||||
"@deepseek-ai/dsh-client-ui-workspace": "workspace:^",
|
||||
"@deepseek-ai/dsh-cmdline": "workspace:^",
|
||||
"@deepseek-ai/dsh-code-runtime-worker": "workspace:^",
|
||||
"@deepseek-ai/dsh-frontend": "workspace:^",
|
||||
"@deepseek-ai/dsh-frontend-static": "workspace:^",
|
||||
"@deepseek-ai/dsh-code-runtime-worker-thread": "workspace:^",
|
||||
"@deepseek-ai/dsh-web-frontend": "workspace:^",
|
||||
"@deepseek-ai/dsh-host-frontend-static": "workspace:^",
|
||||
"@deepseek-ai/dsh-host-apiproxy": "workspace:^",
|
||||
"@deepseek-ai/dsh-host-directory-picker-auto": "workspace:^",
|
||||
"@deepseek-ai/dsh-host-directory-picker-browse": "workspace:^",
|
||||
@@ -92,7 +92,7 @@
|
||||
"@deepseek-ai/dsh-host-webserver": "workspace:^",
|
||||
"@deepseek-ai/dsh-message-feedback": "workspace:^",
|
||||
"@deepseek-ai/dsh-session-projection-cache": "workspace:^",
|
||||
"@deepseek-ai/dsh-session-export": "workspace:^",
|
||||
"@deepseek-ai/dsh-session-log-download": "workspace:^",
|
||||
"@deepseek-ai/dsh-session-stats": "workspace:^",
|
||||
"@deepseek-ai/dsh-storage": "workspace:^",
|
||||
"@deepseek-ai/dsh-storage-domain": "workspace:^",
|
||||
@@ -103,14 +103,14 @@
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@deepseek-ai/cordis-plugin-loader": "workspace:^",
|
||||
"@deepseek-ai/dsh-bash-env": "workspace:^",
|
||||
"@deepseek-ai/dsh-shell-env": "workspace:^",
|
||||
"@deepseek-ai/dsh-invariants": "workspace:^",
|
||||
"@deepseek-ai/dsh-system-prompt": "workspace:^",
|
||||
"@deepseek-ai/cordis": "workspace:^"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@deepseek-ai/cordis-plugin-loader": "workspace:^",
|
||||
"@deepseek-ai/dsh-bash-env": "workspace:^",
|
||||
"@deepseek-ai/dsh-shell-env": "workspace:^",
|
||||
"@deepseek-ai/dsh-invariants": "workspace:^",
|
||||
"@deepseek-ai/dsh-system-prompt": "workspace:^",
|
||||
"@deepseek-ai/cordis": "workspace:^"
|
||||
|
||||
@@ -16,11 +16,11 @@ import { fileURLToPath } from 'node:url'
|
||||
import type { Context } from '@deepseek-ai/cordis'
|
||||
import z from '@deepseek-ai/schemastery'
|
||||
import { addHarnessSourceSection } from '@deepseek-ai/dsh-app-boot'
|
||||
import * as FrontendStatic from '@deepseek-ai/dsh-frontend-static'
|
||||
import * as FrontendStatic from '@deepseek-ai/dsh-host-frontend-static'
|
||||
import type {} from '@deepseek-ai/cordis-plugin-loader'
|
||||
import type {} from '@deepseek-ai/dsh-host-webserver'
|
||||
import type {} from '@deepseek-ai/dsh-system-prompt'
|
||||
import type {} from '@deepseek-ai/dsh-bash-env'
|
||||
import type {} from '@deepseek-ai/dsh-shell-env'
|
||||
|
||||
/** Stable Cordis plugin name. */
|
||||
export const name = 'web-app'
|
||||
@@ -32,7 +32,7 @@ const SOURCE_ROOT = fileURLToPath(new URL('../../../..', import.meta.url))
|
||||
const WEB_RUNTIME_SERVICE = 'webRuntime'
|
||||
|
||||
/** Services required before the web runtime can mount. */
|
||||
export const inject = ['httpServer']
|
||||
export const inject = ['webServer']
|
||||
|
||||
/** Plugin config: composed deployment settings plus per-invocation command-line values. */
|
||||
export interface Config {
|
||||
@@ -102,13 +102,13 @@ function webSurfacePrompt(webUrl: string): string {
|
||||
+ updateContract
|
||||
+ 'Starting another server does not update this GUI. '
|
||||
+ 'The apps/web Vite entry builds the shell but is not a standalone application because only dsh web injects window.__DSH_BOOT__. '
|
||||
+ 'Do not start a replacement server unless the user asks; if one is needed, use a managed background task and verify its exact URL.'
|
||||
+ 'Do not start a replacement server unless the user asks; if one is needed, use a managed background job and verify its exact URL.'
|
||||
}
|
||||
|
||||
/** Resolve the canonical loopback URL from the active Web server. */
|
||||
function localWebUrl(ctx: Context): string {
|
||||
const port = ctx.get('httpServer')?.port
|
||||
if (port === undefined) throw new Error('web-app: httpServer service missing while resolving Web runtime')
|
||||
const port = ctx.get('webServer')?.port
|
||||
if (port === undefined) throw new Error('web-app: webServer service missing while resolving Web runtime')
|
||||
return `http://${LOOPBACK_HOST}:${String(port)}`
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ function localWebUrl(ctx: Context): string {
|
||||
function resolveDistIndex(): string {
|
||||
const require = createRequire(import.meta.url)
|
||||
try {
|
||||
return require.resolve('@deepseek-ai/dsh-frontend/dist/index.html')
|
||||
return require.resolve('@deepseek-ai/dsh-web-frontend/dist/index.html')
|
||||
} catch {
|
||||
/* v8 ignore next 2 -- reachable only on a checkout without a built dist; the test tree builds it */
|
||||
throw new Error('web-app: frontend dist not built; run pnpm run build from the repository root first')
|
||||
@@ -129,11 +129,11 @@ export const internals: { resolveDistIndex: () => string } = { resolveDistIndex
|
||||
/**
|
||||
* Mount the Web runtime: dist serving, surface prompt, the bash runtime
|
||||
* variable, and the URL line.
|
||||
* @param ctx - plugin context carrying the httpServer service.
|
||||
* @param ctx - plugin context carrying the webServer service.
|
||||
* @param config - validated {@link Config}.
|
||||
*/
|
||||
export function apply(ctx: Context, config: Config): void {
|
||||
const runtime = resolveLanTrust(ctx.httpServer.host, config.trustedHosts)
|
||||
const runtime = resolveLanTrust(ctx.webServer.host, config.trustedHosts)
|
||||
// Release dependent rows only after bind-dependent trust has been sampled once.
|
||||
ctx.provide(WEB_RUNTIME_SERVICE, runtime)
|
||||
ctx.plugin(FrontendStatic, { distIndex: internals.resolveDistIndex() })
|
||||
@@ -146,8 +146,8 @@ export function apply(ctx: Context, config: Config): void {
|
||||
text: () => webSurfacePrompt(localWebUrl(promptCtx)),
|
||||
})
|
||||
})
|
||||
ctx.inject(['bashEnv'], (runtimeCtx) => {
|
||||
runtimeCtx.bashEnv.register({
|
||||
ctx.inject(['shellEnv'], (runtimeCtx) => {
|
||||
runtimeCtx.shellEnv.register({
|
||||
name: 'web-runtime',
|
||||
variables: {
|
||||
[DSH_WEB_URL]: { description: 'Canonical local URL of the DeepSeek Harness Web GUI serving this session.' },
|
||||
@@ -164,7 +164,7 @@ export function apply(ctx: Context, config: Config): void {
|
||||
const printUrl = (): void => {
|
||||
// Reuse the exact LAN snapshot provided to the /api trust fence.
|
||||
const lanCandidate = runtime.lanAddresses[0]
|
||||
const port = ctx.httpServer.port
|
||||
const port = ctx.webServer.port
|
||||
console.log(`dsh web: ${localWebUrl(ctx)}${lanCandidate === undefined ? '' : ` (LAN: http://${lanCandidate}:${String(port)})`}`)
|
||||
}
|
||||
// This row's own activation can precede a sibling failure. The app owns
|
||||
@@ -177,7 +177,7 @@ export function apply(ctx: Context, config: Config): void {
|
||||
// The tree can be disposed while the boot was in flight (early
|
||||
// SIGTERM); a URL line for a dead server would only mislead, and
|
||||
// reading the torn-down port would turn a clean shutdown into a crash.
|
||||
if (ctx.get('httpServer') !== undefined) printUrl()
|
||||
if (ctx.get('webServer') !== undefined) printUrl()
|
||||
// Loader reports a failed boot; this row only stays quiet.
|
||||
}, () => {})
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import { join } from 'node:path'
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest'
|
||||
import { Context } from '@deepseek-ai/cordis'
|
||||
import SystemPrompt from '@deepseek-ai/dsh-system-prompt'
|
||||
import type { HttpServerService } from '@deepseek-ai/dsh-host-webserver'
|
||||
import type { WebServer } from '@deepseek-ai/dsh-host-webserver'
|
||||
import { apply, Config, internals } from '../src/index.ts'
|
||||
|
||||
vi.mock('node:os', async importOriginal => ({
|
||||
@@ -43,8 +43,8 @@ function stageDist(): string {
|
||||
return index
|
||||
}
|
||||
|
||||
/** A fake httpServer capturing the fallback seat and index taps. */
|
||||
function fakeHttpServer(host: '127.0.0.1' | '0.0.0.0' = '127.0.0.1'): { server: HttpServerService; seat: () => unknown } {
|
||||
/** A fake webServer capturing the fallback seat and index taps. */
|
||||
function fakeHttpServer(host: '127.0.0.1' | '0.0.0.0' = '127.0.0.1'): { server: WebServer; seat: () => unknown } {
|
||||
let fallback: unknown
|
||||
const server = {
|
||||
host,
|
||||
@@ -54,7 +54,7 @@ function fakeHttpServer(host: '127.0.0.1' | '0.0.0.0' = '127.0.0.1'): { server:
|
||||
return () => { fallback = undefined }
|
||||
},
|
||||
applyIndexTaps: (html: string) => html,
|
||||
} as unknown as HttpServerService
|
||||
} as unknown as WebServer
|
||||
return { server, seat: () => fallback }
|
||||
}
|
||||
|
||||
@@ -74,9 +74,9 @@ describe('web-app runtime glue', () => {
|
||||
stageDist()
|
||||
const ctx = new Context()
|
||||
const { server, seat } = fakeHttpServer('0.0.0.0')
|
||||
ctx.provide('httpServer', server)
|
||||
ctx.provide('webServer', server)
|
||||
const contributions: BashContribution[] = []
|
||||
ctx.provide('bashEnv', {
|
||||
ctx.provide('shellEnv', {
|
||||
register: (contribution: BashContribution) => {
|
||||
contributions.push(contribution)
|
||||
return () => {}
|
||||
@@ -110,7 +110,7 @@ describe('web-app runtime glue', () => {
|
||||
it('stays quiet with printUrl off', async () => {
|
||||
stageDist()
|
||||
const ctx = new Context()
|
||||
ctx.provide('httpServer', fakeHttpServer().server)
|
||||
ctx.provide('webServer', fakeHttpServer().server)
|
||||
const log = vi.spyOn(console, 'log').mockImplementation(() => {})
|
||||
apply(ctx, new Config({ printUrl: false, surfaceContext: true, trustedHosts: [] }))
|
||||
await ctx.plugin(SystemPrompt, { persona: '' })
|
||||
@@ -125,9 +125,9 @@ describe('web-app runtime glue', () => {
|
||||
it('skips the surface context when disabled (the one-shot layer): no prompt section, no bash variables', async () => {
|
||||
stageDist()
|
||||
const ctx = new Context()
|
||||
ctx.provide('httpServer', fakeHttpServer().server)
|
||||
ctx.provide('webServer', fakeHttpServer().server)
|
||||
const contributions: BashContribution[] = []
|
||||
ctx.provide('bashEnv', {
|
||||
ctx.provide('shellEnv', {
|
||||
register: (contribution: BashContribution) => {
|
||||
contributions.push(contribution)
|
||||
return () => {}
|
||||
@@ -146,7 +146,7 @@ describe('web-app runtime glue', () => {
|
||||
it('prints the loopback-only URL line when no LAN snapshot exists', async () => {
|
||||
stageDist()
|
||||
const ctx = new Context()
|
||||
ctx.provide('httpServer', fakeHttpServer().server)
|
||||
ctx.provide('webServer', fakeHttpServer().server)
|
||||
const log = vi.spyOn(console, 'log').mockImplementation(() => {})
|
||||
apply(ctx, new Config({ printUrl: true, surfaceContext: true, trustedHosts: [] }))
|
||||
await new Promise(resolve => setTimeout(resolve, 0))
|
||||
@@ -159,7 +159,7 @@ describe('web-app runtime glue', () => {
|
||||
// Settlement path: the line waits for loader.await() so supervisors can
|
||||
// RPC immediately after observing it.
|
||||
const settled = new Context()
|
||||
settled.provide('httpServer', fakeHttpServer().server)
|
||||
settled.provide('webServer', fakeHttpServer().server)
|
||||
let release: () => void
|
||||
const settlement = new Promise<void>((resolve) => { release = resolve })
|
||||
provideLoader(settled, () => settlement)
|
||||
@@ -176,7 +176,7 @@ describe('web-app runtime glue', () => {
|
||||
// for a process that is about to exit.
|
||||
log.mockClear()
|
||||
const failed = new Context()
|
||||
failed.provide('httpServer', fakeHttpServer().server)
|
||||
failed.provide('webServer', fakeHttpServer().server)
|
||||
provideLoader(failed, async () => { throw new Error('boot failed') })
|
||||
apply(failed, new Config({ printUrl: true, surfaceContext: true, trustedHosts: [] }))
|
||||
await new Promise(resolve => setTimeout(resolve, 0))
|
||||
@@ -188,14 +188,14 @@ describe('web-app runtime glue', () => {
|
||||
log.mockClear()
|
||||
const torn = new Context()
|
||||
const child = torn.plugin((childCtx: Context) => {
|
||||
childCtx.provide('httpServer', fakeHttpServer().server)
|
||||
childCtx.provide('webServer', fakeHttpServer().server)
|
||||
})
|
||||
await child
|
||||
let releaseTorn: () => void
|
||||
const tornSettlement = new Promise<void>((resolve) => { releaseTorn = resolve })
|
||||
provideLoader(torn, () => tornSettlement)
|
||||
apply(torn, new Config({ printUrl: true, surfaceContext: true, trustedHosts: [] }))
|
||||
await child.dispose() // the httpServer service goes away
|
||||
await child.dispose() // the webServer service goes away
|
||||
releaseTorn!()
|
||||
await new Promise(resolve => setTimeout(resolve, 0))
|
||||
expect(log).not.toHaveBeenCalled()
|
||||
@@ -209,11 +209,11 @@ describe('web-app runtime glue', () => {
|
||||
// section must throw, never render a URL with an undefined port.
|
||||
const { server } = fakeHttpServer()
|
||||
Object.defineProperty(server, 'port', { get: () => undefined })
|
||||
ctx.provide('httpServer', server)
|
||||
ctx.provide('webServer', server)
|
||||
apply(ctx, new Config({ printUrl: false, surfaceContext: true, trustedHosts: [] }))
|
||||
await ctx.plugin(SystemPrompt, { persona: '' })
|
||||
await new Promise(resolve => setTimeout(resolve, 0))
|
||||
await expect(ctx.systemPrompt.assemble()).rejects.toThrow('httpServer service missing')
|
||||
await expect(ctx.systemPrompt.assemble()).rejects.toThrow('webServer service missing')
|
||||
await ctx.fiber.dispose()
|
||||
})
|
||||
|
||||
|
||||
@@ -33,10 +33,10 @@
|
||||
"path": "../../core/system-prompt"
|
||||
},
|
||||
{
|
||||
"path": "../../bash/bash-env"
|
||||
"path": "../../shell/shell-env"
|
||||
},
|
||||
{
|
||||
"path": "../../support/invariants"
|
||||
"path": "../../runtime-diagnostics/invariants"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user