# flowix

> DSH 浏览器表层组合包：在 dsh-base 之上叠加 Web profile，承载 dsh --profile web 命令行解析、Web 服务粘合、前端 dist 服务、提示词段落与 bash 运行时变量。

## Metadata

- Author: [@text2future](https://github.com/text2future)
- Repo: <https://github.com/text2future/flowix.git>
- GitHub: [text2future/flowix](https://github.com/text2future/flowix)
- Stars: 331
- Language: TypeScript
- License: [MIT](https://spdx.org/licenses/MIT.html)
- Homepage: <https://www.flowix-memo.com/>
- Topics: `agent-memory`, `claude-code`, `codex-cli`, `desktop`, `dsh`, `dsh-plugin`, `dsh-plugin-desktop`, `hermes-agent`, `markdown-editor`, `memory-system`, `note-taking`, `open-code`
- Forks: 42
- Open Issues: 23
- Last push: 2026-08-19T17:44:52.000Z
- Added: 2026-08-20T00:00:00.000Z

## Install

```bash
dsh plugin --profile web add github:text2future/flowix/app/flowix-dsh-host/vendor/deepseek-harness/packages/bundle/web-app
```

## Wiki

## 一句话定位
DSH 浏览器表层组合包 `@deepseek-ai/dsh-web-app`，在 dsh-base 之上叠加 `dsh --profile web` 这一表层所需的全部宿主行（webserver、API 网关、workspace、投影缓存、存储、浏览器插件名录、客户端插件 HMR 链）和 `web-runtime` 粘合插件，承载命令行解析、前端 dist 服务、Web 表层提示词、bash 运行时变量和就绪 URL 行的打印。

## 核心能力
- 解析 `dsh --profile web` 命令行：支持 `--host`、`--port`、可重复的 `--trusted-host`、`--help`，并将 `--host 0.0.0.0` 与非数字 `--port` 视为用法错误
- 在 dsh-base 之上插入 Web 特有的宿主行：webserver、API gateway、cordis host/client runner、code-runtime、storage / storage-json / storage-domain、workspace、session-projection-cache、session-stats、message-feedback、session-log-export、directory-picker、plugin-inventory、agent-presets 等
- 注入客户端插件名册（`dsh.client` 行）：client-connection、api-remotes、client-runtime、ui-theme、ui-layout、ui-sidebar、ui-conversation、ui-tool、ui-cordis、ui-deliverables、ui-workspace、ui-input-trigger、ui-commands、ui-skill、ui-subagent、ui-jobs、ui-goal、ui-message-feedback、ui-model-selection、ui-permission、ui-agent-preset、ui-settings*、ui-plan、ui-user-questions、ui-trajectory 等
- 把 coding persona 设为 `You are a coding agent powered by the {{model}} model. Your working directory is {{cwd}}.`，禁用一系列面向 TUI 的工具/技能/计划/工作流行（tool-bash、tool-pwsh、tool-jobs、tool-fs、tool-fs-search、tool-str-replace-editor、skill-filesystem、tool-skill、tool-goal、plan-mode、compaction-basic、command-compact、tool-result-pruner、tool-subagent*、workflow-worker-thread、tool-workflow、tool-ralph、agent-instructions、tool-todo、tool-web、hmr）
- 通过 `web-runtime` 粘合插件：解析 `@deepseek-ai/dsh-web-frontend/dist/index.html`，挂载 `frontend-static` 回退席位所有者；只在启动时采样一次依赖 bind 的 LAN 信任信息并以 `webRuntime` 服务提供给浏览器信任栅栏；在 `surfaceContext=true` 时注册 `harness:source` 和 `app:web-surface`（order −98）提示词段落，以及 bash 运行时变量 `DSH_WEB_URL`；在 `printUrl=true` 时等本表层 Loader 配置树结算后打印 `dsh web:` URL 行

## 技术实现
- **语言**: TypeScript（strict ESM）+ YAML（cordis.patch.yml 静态清单）
- **关键依赖**: `@deepseek-ai/cordis`（peer，函数插件协议载体）+ `commander`（命令行解析）+ `@deepseek-ai/schemastery`（Config schema）+ 40 余个 `@deepseek-ai/dsh-*` 工作区包作为传递依赖
- **架构模式**: 函数插件组合包——`cordis.patch.yml` 通过 `package.json#dsh.bundle.patch` 被 profile 组合器静态加载，运行时由 `src/index.ts`（`web-runtime`）+ `src/startup.ts`（`web-startup`）+ `src/invariant.ts`（空操作 invariant 安装器）三部分承担；`web-startup` 先解析命令行并把 `webStartup` 作为普通 Cordis 服务发布，flag 配置的行（webserver、web-runtime）再 `inject: [webStartup]`，因此参数解析完成前不会绑定端口
- **入口文件**: `cordis.patch.yml`（profile 加载时使用）+ `src/index.ts`（web-runtime 粘合插件）+ `src/startup.ts`（web-startup 命令行提供方）

## 适用场景
想用浏览器 GUI 跑 DSH agent 而非终端 TUI 时，需要这个组合包作为 `dsh --profile web` 表层：它在 dsh-base 之外补齐浏览器渲染需要的所有宿主行与客户端 UI 插件，并替代理配置 `web-server`、命令行、前端 dist 服务、面向模型的 Web 表层提示与 bash 运行时变量。普通终端用户无需直接接触，profile 维护者把它作为第二层 patch 叠加在 dsh-base 之上即可。

## 前置依赖与兼容性
| 依赖 | 最低版本 | 说明 |
|---|---|---|
| DSH | >=0.1.0-rc.5 | 本包自身 `version`；必须叠在 dsh-base（>=0.1.0-rc.5）之后 |
| Node.js | >=22.19 | 工作区 `engines.node` 要求 `^22.19.0 \|\| >=24.0.0`，本包未单独声明 |
| 平台 | macOS / Windows / Linux | 通过 LAN 信任栅栏（`trustedHosts`）约束外部主机；不绑 `0.0.0.0` |
| 原生模块 | 无 | 纯 JS/TS + YAML；运行时依赖 `node:os.networkInterfaces()` 取本机 IPv4，无 node-gyp |

## 安装方式
```bash
dsh plugin --profile web add github:text2future/flowix/app/flowix-dsh-host/vendor/deepseek-harness/packages/bundle/web-app
```

## 配置项
| 配置 | 类型 | 说明 | 默认值 |
|---|---|---|---|
| `printUrl` | 布尔 | 启动成功后是否在终端打印 `dsh web:` URL 行；非交互层可关掉 | `true` |
| `surfaceContext` | 布尔 | 是否给模型注册 `harness:source` 与 `app:web-surface` 提示词段落，以及把 `DSH_WEB_URL` 注入 bash 环境；一次性非交互层在用户不在 GUI 时可关掉 | `true` |
| `trustedHosts` | 字符串数组 | 本次调用通过 `--trusted-host` 显式传入的额外可信主机（host 或 host:port，可重复），与启动期采样的 LAN IP 字面量共同构成 `webRuntime.trustedHosts` | `[]` |
| CLI `--host <host>` | 字符串 | webserver 绑定的主机；`0.0.0.0` 会被 CLI 显式拒绝 | 未设置时回落到 patch 中的部署默认值 `127.0.0.1` |
| CLI `--port <port>` | 数字 | webserver 监听的端口；传 `0` 让 OS 选空闲端口 | 未设置时回落到 patch 中的部署默认值 `3080` |
| CLI `--trusted-host <authority...>` | 字符串（可重复） | 浏览器信任栅栏额外接受的可信主机（host 或 host:port） | 无 |
| CLI `-h, --help` | 开关 | 打印本应用的帮助；不会启动服务也不会发布 `webStartup` 服务 | — |

## 常见问题

**Q: web-runtime 和 web-startup 有什么区别？**

A: web-startup 是普通的命令行提供方（`src/startup.ts`），注入 `cmdlineArgs` 后用 commander 解析 `--host`、`--port`、可重复的 `--trusted-host`、`--help`，把结果以 `webStartup` 服务发布；web-runtime（`src/index.ts`）才是叠在 base 之上的粘合插件，它注入 `webStartup`、在拿到 `webServer` 之后才发布 `webRuntime`、挂前端 dist 服务、注册提示词段落与 bash 变量，并在就绪后打 URL 行——前者负责命令行，后者负责运行时粘合。

**Q: 启动后看到了 `dsh web: http://127.0.0.1:xxxx (LAN: http://192.168.x.x:xxxx)` 这一行说明什么？**

A: 这一行是就绪信号：本表层所有宿主行已成功挂载、Loader 配置树已结算、`webServer` 仍存在；监督进程看到这行就会立刻开始 RPC。如果用了 `0.0.0.0` 绑定、并且 `--trusted-host` 也为空，括号里的 LAN URL 会从启动期 `networkInterfaces()` 的 IPv4 快照里取第一条。

**Q: 我想在自己部署里关掉 URL 行或者关掉面向模型的 Web 表层提示，怎么办？**

A: 在自己 profile 的更高层 patch 里覆盖 `web-runtime` 行的 `printUrl`（设为 `false` 就不打 URL 行）或 `surfaceContext`（设为 `false` 就不注册 `harness:source`/`app:web-surface` 提示词段落，也不注入 `DSH_WEB_URL` bash 变量）。`trustedHosts` 也可在那里扩展为例如 `['app.internal', ...ctx.webRuntime.trustedHosts]`。

**Q: 启动时报 `web-app: frontend dist not built; run pnpm run build from the repository root first` 怎么办？**

A: 这是设计内的失败：web-runtime 通过 `require.resolve('@deepseek-ai/dsh-web-frontend/dist/index.html')` 解析前端 dist，没源码降级路径。在仓库根执行 `pnpm run build`（或 `pnpm run build:web` 单独构建前端）后再启动即可。

**Q: 我能在浏览器里通过 LAN 主机访问本机 GUI 吗？**

A: 默认不能：webserver 绑的是 `127.0.0.1`，而 `--host 0.0.0.0` 被 CLI 拒绝。最稳的做法是把 `--host` 设为本机 LAN IPv4，并通过 `--trusted-host` 把目标 host（含端口）显式列入信任栅栏；若确实要绑所有接口，请改用其他方式并自行承担暴露远程代码执行的风险。

**Q: 客户端插件改了之后浏览器能自动刷新吗？**

A: 客户端插件重载链路（`dsh-client-hmr`）在 Web profile 下已挂载但当前整体 HMR 处于关闭状态（`cordis.patch.yml` 中 `hmr` 行 `disabled: true`，README 标记 TODO：待重载生命周期测试通过后再启用）。在该 TODO 解决前，客户端插件改动不会无刷新自动刷新；GUI shell 与普通 package 改动则需要重建 Web 产物并手动刷新页面。

## 上手难度
进阶 — 需要理解 DSH 的 cordis.patch.yml 分层叠加规则、`web-startup` 与 `web-runtime` 两个服务的依赖顺序，以及 Commander flag → 服务 → 表达式解析的链路；普通用户一般通过 `dsh --profile web` 直接使用，profile 维护者才需要编辑这一层。

## 已知问题与限制
- **前端 dist 必须已构建**：`web-runtime` 通过 `require.resolve('@deepseek-ai/dsh-web-frontend/dist/index.html')` 解析，激活时找不到会直接抛 `web-app: frontend dist not built; run pnpm run build from the repository root first`，没有从源码服务前端的降级路径
- **`lanAddresses` 是启动期快照**：web-runtime 只在 `apply` 时采样一次 `networkInterfaces()`；启动后网卡增删或 IPv4 变化不会被重新公告，已打印的 LAN URL 始终等于本次启动期构建的信任栅栏
- **共享 HMR 当前关闭**：`cordis.patch.yml` 第 22–23 行将 `hmr` 行设为 `disabled: true`，并注释 `TODO: Re-enable shared HMR for Web after its reload lifecycle is tested.`；客户端插件重载链路 (`dsh-client-hmr`) 仅在显式启用该行后才真正生效
- **CLI 不支持 `--host 0.0.0.0`**：出于安全考虑，`src/startup.ts:69-71` 主动拒绝全接口绑定，给出明确错误提示

---

This document is auto-generated by [deepseek-plugin.org](https://deepseek-plugin.org). HTML page: [flowix](https://deepseek-plugin.org/plugins/text2future/flowix/app/flowix-dsh-host/vendor/deepseek-harness/packages/bundle/web-app)
Wiki generated by AI (model: `MiniMax-M3`)
