# dsh-logger-panel

[English](README.md) | 中文

适用于 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)（`dsh`）的运行日志面板。它捕获 Host 的 Cordis logger 输出，通过 SSE 实时流入 **设置 > 日志** 页面，并把同一批记录持久化到私有 `$DSH_HOME/logs/dsh-logger-panel` 目录下按日期与大小轮转的有界 JSONL 文件。

页面只按纯文本渲染记录。原始 logger 参数、Fiber 引用、ANSI 转义与可执行标记都不会跨过浏览器 wire。

## 特性

- 实时视图：快照 + 每 100 毫秒批量推送 SSE 增量。
- 历史分页：点击「加载更早」从轮转 JSONL 文件中跨轮转、跨日期读回更早记录，让浏览器视图突破内存窗口。
- 底部自动跟随；向上滚动后暂停，并提供「回到最新」按钮恢复。
- 内存有界：Host 为每个新连接的浏览器保留最近 2,000 条记录。
- JSONL 持久化：Host 激活、日期变化或达到 5 MiB 上限时打开新的 `YYYY-MM-DD-N.jsonl`；超过 30 天的匹配文件会被删除。目录以 `0700` 创建，文件以 `0600` 创建。
- 磁盘队列有界（1,000 条）。持久化失败时面板会报告故障并继续实时流；被省略的记录会计数。

## 要求

- 带 Web profile 的 DeepSeek Harness（设置外壳来自 `dsh-client-ui-settings`、client 模块系统与 `dsh-host-webserver`），版本 `0.1.0-rc.6` 或更新。
- Node `^22.19 || >=24`。

## 安装

该包是一个 [dsh 组合包](https://deepseek-harness.github.io/deepseek-harness/develop/basic/publish/)。`package.json` 的 `dsh.bundle` 指向 `cordis.patch.yml` 以激活 Host 插件，并声明 `dsh.client` 让 Web profile 自动发现浏览器 bundle。

从 npm：

```sh
dsh plugin --profile demo add dsh-logger-panel
dsh --profile demo
```

从 git（`prepare` 脚本会在安装时构建 `lib/`；请先在 profile 的 `pnpm-workspace.yaml` 中授权构建）：

```sh
dsh plugin --profile demo add github:LingLambda/dsh-logger-panel#<sha>
```

针对 Harness checkout 做本地开发时，用 overlay 装载 Host 源码：

```sh
pnpm dsh web --patch ./cordis.patch.yml --patch /absolute/path/to/dsh-logger-panel/overlay.yml
```

```yaml
- insert:
    - id: logger-panel
      name: /absolute/path/to/dsh-logger-panel/src/index.ts
```

## 配置

插件行以 `logger-panel` 插入。在你的 profile patch 中覆盖其 `config`：

```yaml
- id: logger-panel
  name: dsh-logger-panel
  config:
    root: /var/log/dsh         # 默认：$DSH_HOME/logs/dsh-logger-panel
    maxRecords: 2000           # 为连接浏览器保留的记录数
    maxRecordChars: 20000      # 单条格式化消息保留的最大字符数
    batchMs: 100               # SSE 批量推送间隔
    maxFileBytes: 5242880      # 每个 JSONL 文件在轮转前的字节数
    maxAgeDays: 30             # 保留天数；0 表示不删除
    maxPendingRecords: 1000    # 领先于磁盘写入而接受的最大记录数
    historyPageSize: 500       # 单个历史页返回的记录数
```

## 工作原理

Host 注册一个 Cordis logger exporter。每条消息被格式化为有界纯文本并追加到内存历史，同一条记录同时排队进入 JSONL writer，因此所有捕获级别都会落盘，不做任何内容筛选。每个浏览器连接先收到快照，再收到批量增量；关闭时会排空已接受的文件写入。初次创建目录或打开文件失败会拒绝插件激活；运行期写入失败会停止持久化、在面板中报告，并让内存与 SSE 路径继续工作。

`/dsh-logger-panel/logs/history` 端点按倒序从 JSONL 文件分页读回更早记录。首次请求以浏览器最早一条实时记录为锚点，避免重复返回当前窗口；后续请求使用不透明游标继续。浏览器把已加载的历史与实时窗口分开维护：实时裁剪不会删除历史，重连快照会去重合并。

## 开发

```sh
corepack yarn install
corepack yarn typecheck
corepack yarn test
corepack yarn build
```

## 许可证

MIT
