# prts-terrarchive

PRTS.chat 为 DeepSeek Harness（DSH）提供的资料插件：把《明日方舟》与
《明日方舟：终末地》的游戏原文、档案，以及社区审校 Wiki、实体图鉴与《泰拉年表》
装进本地资料包，为 Agent 提供带原文行号的检索与引用工具，并可按需接入
PRTS.chat 云端混合检索与 DSH 原生网页工具。

[中文](README.md) | [English](README.en.md)

## 这是什么

本插件为 DSH 提供明日方舟与终末地联合资料检索能力。插件先从 PRTS.chat 取得已批准的
最新 release 与逐文件摘要，再从 ModelScope 镜像或 PRTS.chat 下载本地语料；
Agent 可以离线检索并按原文行号阅读材料；可选的 PRTS.chat 云端混合检索用于发现
候选材料，并将结果映射回本地原文核验。由于云端服务承载能力有限，当前为每个用户
每日提供 1000 次 DSH 匿名云端检索调用额度；额度策略可能根据实际运行情况调整。

- **本地检索**：`corpus_search` 用同一组参数同时检索两款游戏，
  支持游戏、资料类型、内容形式、角色、活动／任务、Wiki 字段等结构化过滤；
- **原文阅读**：`corpus_read` 可按关卡代号、密录名、角色资料类别直接定位，
  并可连续阅读整个明日方舟活动或终末地任务；引用格式统一为《篇章名》第 N 行；
- **活动时间线**：`timeline_search` 检索 PRTS Wiki《泰拉年表》本地投影，
  支持实体别名自动裂变与出处标记反查；
- **云端混合检索**：双模块模式下一次 `cloud_search` 默认并行查询两款游戏的图谱、档案、
  原文与 Wiki，联合排序后映射回本地篇章；

## 数据来源声明

- **自建 Wiki 数据**：来源于 [littlepangding/arknights_lore_wiki](https://github.com/littlepangding/arknights_lore_wiki)。
- **《泰拉年表》数据**：来源于 [PRTS Wiki《泰拉年表》](https://prts.wiki/w/%E6%B3%B0%E6%8B%89%E5%B9%B4%E8%A1%A8)，供本插件的时间线检索使用。

## 核心特性

| 特性 | 说明 |
| --- | --- |
| 自由组合 | PRTS 模式继承标准模式的完整能力；创造模式可将 PRTS 工具加入任意自定义模式 |
| 双游戏资料 | 明日方舟与终末地原文、档案、审校 Wiki、实体与时间线使用统一工具检索 |
| 读取去重 | 会话级证据状态跟踪已进入模型上下文的原文，重复/重叠读取自动回放或只补读新行 |
| 自带皮肤 | Harness 默认 / PRTS Agent / Endfield AIC / 莱茵生命资料馆 |

## 莱茵生命资料馆

在 **设置 → 插件 → PRTS 语料 → 界面皮肤** 选择「莱茵生命资料馆」，然后在会话中打开
「资料馆」。检索阵列、调查板、重点证据盒和双层档案架位于同一个三维场景。
可用底部导航、边缘入口或点击可见模型切换，镜头连续移动。

调查板工具与调查技能仅在「莱茵生命资料馆」皮肤下启用。其他皮肤直接在对话中检索和回答，不会要求建板或把回答只存入板内报告。同一 PRTS 会话切换皮肤后会更新工具，无需新建对话；切出莱茵不会删除已保存的线索、报告或档案，切回后可继续查看。

- **检索阵列**保留候选资料；**档案架**收录已交付给 Agent 的资料或用户主动收藏的资料，分别保留已读和引用状态，每页上下两层、每层十二份。
- **重点证据盒**属于指定调查板，用于暂存待核对、待整理的材料；放入盒子不会自动标成已读，也不必先收藏。
- **调查板**由 Agent 持续添加线索与关系，中央保留带版本的报告。新建还是延续调查由 LLM 通过调查工具决定，追问不会机械地创建新板。
- 纸片支持拖动、缩放、红绳连线与手动编辑。编辑沿用同款纸色和编号，自动保存并支持撤销；板面数据由 Host 持久化。
- 手动检索支持本地与云端模式及高级设置。阅读器支持 Markdown、来源版本、命中位置与实际已读范围；返回时恢复原入口、筛选和阅读位置。
- 手动浏览暂时停留在当前资料，Agent 下一次查阅时恢复跟随；点击「暂停跟随」才会持续暂停，直到点击「恢复跟随」。用户查看的板、Agent 工作板和证据盒目标分别管理。

长文分页、档案架分页、减少动态效果和无 WebGL 时的文字阅读模式均可用。
操作细节见 [资料馆说明](docs/rhine-lab.md) 与 [交互与资料分层](docs/rhine-interaction-flow.md)。

前端沿用 Three.js + TypeScript + Vite。三维主体、档案循环导航与渲染使用原项目实现和
默认画质；主界面按调查用途重新设计，原版演示档案已全部移除。开发预览读取本地真实资料包，不连接 Agent：

```bash
npm ci
npm run build:rhine
npm run preview:rhine
```

打开 `http://127.0.0.1:4177`。可通过 `PRTS_RHINE_RELEASES=/path/to/releases` 指定只读资料包目录。
直接预览证据白板：`http://127.0.0.1:4177/?rhineView=board`。
语法检查使用 `npm run check`，测试使用 `npm test`；浏览器检查使用 `npm run test:rhine:browser`（需要 Playwright）。

## 环境要求

- Web：Node.js **≥ 22.19**，DSH 运行时 **≥ 0.2.0-rc.1**（包内 `engines.dsh` 声明）；已按 **0.2.1-rc.2** 源码逐项核对
- 官方 Electron Desktop：使用与插件兼容的 DSH 桌面版本；桌面自带运行时
- 磁盘空间：语料大小以设置页与 release 清单为准，下载前不会自动占用完整语料空间

## 安装

### 官方 Electron Desktop（推荐）

在新版 DSH 桌面端，无需打开终端：

1. 打开左侧 **插件**，点击右上角 **＋ 添加插件**。
2. 在「包名或地址」输入框中粘贴下面带版本号的 npm 包名；**只填包名，不要填 `npm install` 或 `dsh plugin add` 命令**：

   ```text
   prts-terrarchive@0.2.3
   ```

   建议指定版本。只填 `prts-terrarchive` 时，安装预览可能显示 npm 的 `latest`，实际安装却选择较旧的版本，原因见下方说明。
3. 在 **安装源** 中按网络情况选择「npm 官方源」或「中国大陆镜像源」，点击 **安装**。
4. 安装完成后点击 **立即启用**；如果直接关闭了对话框，请在已安装列表中打开插件开关。
5. 打开 **设置 → 插件 → PRTS 语料** 下载资料并选择皮肤，然后新建会话，选择 **PRTS 模式**。

「添加插件」也接受以下来源，任选一种即可，不需要重复安装：

| 来源 | 输入框中填写的内容 | 适用情况 |
| --- | --- | --- |
| npm（推荐） | `prts-terrarchive@0.2.3` | 安装指定发布版本 |
| GitHub | `https://github.com/HTian-qwq/prts-terrarchive.git` | 安装仓库源码，需要本机能访问 GitHub |
| 本地目录 | `D:\ds\prts-terrarchive` | 安装已下载的完整插件目录；替换为本机实际绝对路径 |

也支持本地 `.tgz` 插件包的绝对路径。仓库和 npm 包均已包含构建好的界面与 JavaScript 运行时依赖，仅安装或更新插件无需另装 `js-yaml`、`zod` 或运行 `npm ci`。

**安装源只影响 npm 包及依赖下载，不能代理 GitHub 仓库或压缩包直链。** 如果 GitHub 无法连接，可以改填 npm 包名并选择镜像源。新发布版本在镜像中尚未可用时，可切换「npm 官方源」重试。

**安装预览与已安装版本不同：** 使用 pnpm 11 的 DSH 默认优先安装发布满 24 小时的版本，而安装预览读取的是注册表版本。例如，0.2.3 刚发布时，只填包名可能预览 0.2.3、实际安装 0.2.2。这是安装器的版本选择差异。[pnpm 官方说明](https://pnpm.io/blog/releases/11.0)介绍了这项默认设置。请按下面的升级流程卸载旧版，再填 `prts-terrarchive@0.2.3` 安装，完成后在插件详情中核对版本；无需清除语料或会话数据。

**升级插件：** 当前桌面安装界面不提供自动更新。需要升级 npm 或 GitHub 安装的插件时，在插件详情中卸载，再通过「添加插件」重新安装并启用；指定版本号时记得换成目标版本。本地源码安装先在原目录执行 `git pull`，再完全退出并重启桌面端。插件更新与语料更新分别进行，资料版本在「PRTS 语料」中管理。

旧版桌面如只支持 npm 包名，请使用 `prts-terrarchive` 并按其界面提示启用。Electron 的 `desktop` profile 由应用管理，不要运行 `node bin/install.js desktop` 或 `dsh plugin --profile desktop`。

### Web 本地安装

可以从本地源码安装，或使用已内置插件的 PRTS Portable：

```bash
npm install --global @deepseek-ai/dsh@0.2.0-rc.1
git clone https://github.com/HTian-qwq/prts-terrarchive.git
cd prts-terrarchive
node bin/install.js web
```

仓库和 npm 包已包含构建好的 JavaScript 运行时依赖。仅安装插件或执行 `git pull` 更新源码时，无需另装 `js-yaml`、`zod`；修改代码、重新构建时才需要 `npm ci`。

本地安装器把插件加入指定 profile。DSH `0.1.7` 起由插件直接注册「PRTS 模式」；
旧版 DSH 仍创建或迁移 `$DSH_HOME/.agent-presets/prts` 中的兼容预设。省略第二个参数时使用当前插件目录，也可以传入另一个本地目录或压缩包：

```bash
node bin/install.js web /path/to/prts-terrarchive
```

### Web：从 npm 安装

可直接从 npm 安装插件 bundle，无需额外运行安装脚本：

```bash
dsh plugin --profile web add prts-terrarchive@0.2.3
```

重启 `dsh web` 后，DSH `0.1.7` 起由插件注册「PRTS 模式」，禁用或卸载插件时
自动撤销；默认模式和正在运行的普通会话保持不变。新版不读取旧的
`$DSH_HOME/.agent-presets/prts` 文件。若曾自定义旧预设，请在新版的模式配置中手动迁移；
旧文件会保留。旧版 DSH 继续使用文件模板，已有用户修改不会被覆盖。npm 安装不执行 `postinstall`。

```bash
dsh plugin --profile web remove prts-terrarchive
```

### 工具与自定义模式

「PRTS 模式」在插件启用时继承**当前宿主的标准模式**，包含其终端、文件读写与搜索、后台任务、技能、目标、计划、子 Agent、工作流等能力，再添加 PRTS 检索和调查工具。平台条件、服务隔离及标准模式中停用的可选工具保持原配置，权限仍由 DSH 管理。修改标准模式后重启宿主，并在新会话验证。

在**创造模式**可以直接要求：“保留标准模式全部能力，再加上 PRTS 检索和调查工具，创建我的研究模式。” Agent 可发现 `prts-composition` 技能，按宿主流程安装用户自己的组合。可复用入口为 `prts-terrarchive/tools`（仅 Agent 工具）和 `prts-terrarchive/skill`（检索与调查指导）；已有 skill loader 不需重复添加。示例和自定义 PRTS 完整工具清单的方法见[组合说明](skills/prts-composition/SKILL.md)。

旧版 DSH 在启动时将自己版本的 standard 组合写入未修改的自动生成预设。用户修改过或没有生成标记的旧文件不会被覆盖；这类预设可按组合说明手动扩展。普通标准模式不会被自动添加 PRTS 工具。

### 语料下载与 Portable

Web 与官方桌面共享默认的 `$DSH_HOME` 用户资料，但各自安装插件。插件包包含界面、地图
模型、贴图、技能和预设，**不包含语料、Node/DSH 运行库或用户数据**。首次使用请在
「设置 → 插件 → PRTS 语料」自行下载语料，切换皮肤无需另下模型和贴图。

PRTS Portable 发行包预装插件、预设和完整语料，解压后无需另行下载语料。
官方 Electron 便携版使用 `build-electron.ps1` 构建，原 WebView2 构建入口继续保留，
详见 [Portable 仓库](https://github.com/HTian-qwq/prts-terrarchive-portable)。

Portable 打包器已放置插件时，仍可使用 `node bin/install.js web --preset-only` 生成或迁移
兼容预设；该选项不调用 DSH CLI。

### Windows

Web 本地安装需要可用的 `dsh.cmd`。安装器经 cmd.exe 调用它，插件路径含换行或
`%` `!` `&` `|` `<` `>` `^` `"` 时会明确报错，请改用不含这些字符的目录。
`DSH` 环境变量可指定 `dsh.cmd` 的绝对路径。官方 DSH 的语料默认保存到
`%USERPROFILE%\.dsh\prts-corpus\releases`；Portable 的会话和设置保存在发行目录的
`userdata`，语料及后续资料更新保存在 `corpus/releases`。

## 安装后：五步上手

1. **重启** `dsh web` 或所用桌面应用；
2. **设置 → 插件 →「PRTS 语料」**：选择皮肤（Harness 默认 / PRTS Agent / Endfield AIC / 莱茵生命资料馆）；皮肤模型、贴图与字体已随插件包安装；
3. **版本管理**：Portable 已附带完整语料；其他安装方式按设置中的启用游戏下载安装（优先 ModelScope 镜像）。只启用终末地时下载终末地官方资料和审校知识两包；只启用明日方舟时下载方舟的五包。之后启用另一款游戏，再点击下载或更新会补齐缺少的包，已校验文件会复用；关闭游戏不会删除已安装资料。未安装资料时
   PRTS 模式仍可进入；调用本地工具会提醒前往本设置页安装；
4. **新建会话，顶部模式下拉选「PRTS 模式」**；
5. 直接用自然语言提问，或让模型调用下列工具。

## PRTS 模式的工具面

| 来源 | 工具 | 用途 |
| --- | --- | --- |
| dsh-base（所有模式共有） | bash/sandbox 等 | 常规 Agent 能力，本插件不裁剪 |
| 本插件 | `corpus_search` | 本地语料 grep 检索与目录浏览 |
| 本插件 | `corpus_read` | 按玩家可见定位器或自然标题读取官方行号原文 |
| 本插件 | `corpus_i18n` | 终末地官方多语言原文查询、名称与档案对照 |
| 本插件 | `timeline_search` | 活动时间线检索 / 出处反查 |
| 本插件 | `cloud_search` / `cloud_inspect` | PRTS.chat 云端混合检索（默认匿名会话） |
| `@deepseek-ai/dsh-tool-web` | `web_search` / `web_fetch` | 公网检索与已知 URL 精读核验 |
| `@deepseek-ai/dsh-tool-skill` | skill 加载器 | 按需加载检索策略技能 |
| 本插件 | `prts-retrieval` 技能 | 检索配方与字段语义（按需注入，不占 system prompt） |

检索 Skill 默认加载核心策略与当前启用游戏的模块说明；工具契约、详细流程、配方和诊断文档通过技能中的链接按需读取。调查 Skill 默认加载核心工作流，分页回看、协作提醒、引文验证和恢复示例见[调查板操作细则](skills/prts-investigation/references/board-guide.md)。

## 工具详解

### corpus_i18n — 终末地官方多语言查询

使用带本地化附件的终末地资料包（插件 0.2.0 起支持）：

```js
corpus_i18n({query: "管理员，你来了。", languages: ["EN", "JP", "KR"]})
corpus_i18n({title: "<检索结果的完整标题>", line: 1, languages: ["EN"]})
```

也可用已有 `document_uid` 替代标题。名称/原句默认精确匹配，片段可加 `match_mode:"literal"`；外语反查加 `source_language:"EN"`。返回官方字典中的文本及来源，默认不显示内部文本 ID；显式设 `include_ids:true` 才返回字符串 ID，供 `text_ids` 精确复查。空译文、未映射来源、未安装附件分别报告，不自动生成译文。

角色档案按整条记录、档案库按内容块返回，中文行号只是来源定位，不表示各语言分段相同。长记录会分页，原样提交 `page.continuation` 即可续查。旧资料包仍可搜索和阅读；多语言附件须随新资料版本安装。

构建方式和数据格式见 [官方多语言工具](docs/endfield-official-i18n.md)。

### corpus_search — 本地语料检索

像 grep 一样搜索本地语料；命中立即返回原行及上下各一行，按文档归并。`query` 使用
短实体名、篇章展示名或原句片段；也可省略 `query`，仅按过滤条件列出资料入口。

| 参数 | 说明 |
| --- | --- |
| `query` | 搜索词（≤512 码点）；在 NFKC 归一化 + 小写后的文本上匹配 |
| `games` | 可选游戏过滤；省略时同时搜索 `arknights` 与 `endfield` |
| `resource_types` | 资料类型过滤（数组内 OR）；明日方舟与终末地可选值见下文 |
| `content_types` | 内容形式，例如 `dialogue`、`cutscene`、`radio`、`sns_chat` |
| `collection_names` | 明日方舟活动名或终末地任务名，使用同一个字段 |
| `match_mode` | `literal`（默认，连续字面匹配）/ `regex`（线性安全子集：字面量、`^`/`$`、`.`、字符类、转义和固定次数 `{n}`；不支持分组、分支及可变量词） |
| `character_names` / `story_names` / `activity_names` | 角色 / 篇章 / 活动展示名过滤 |
| `entity_names` | 只返回出现指定实体的行（自动展开别名） |
| `speakers` | 结构化说话人过滤，只匹配亲口台词（自动展开已登记别名，如 银灰→恩希欧迪斯） |
| `wiki_sections` | Wiki 标签字段过滤（相关活动、剧情总结、角色剧情概括等 16 种） |
| `context_terms` | 要求命中附近（±3 行）同时出现的语境词，≤8 个 |
| `after` | 下一页的版本绑定可读锚点 `{ data_version, resource_type, title, position }`；与原搜索条件一起原样提交 |

约束：过滤数组每项非空、最多 16 项、单项最长 512 码点。结果预算固定，
保留原搜索条件，并把返回的 `next_after` 原样放入 `after`，可确定性扫描到
`exhausted=true`。锚点使用完整 `data_version`、资料类型和自然标题；资料版本切换后
旧锚点会被拒绝，必须重新搜索。分页不向模型暴露内部签名串。

**明日方舟资料类型（resource_types）**：`story` 官方剧情原文；`character_profile` 档案/招聘/
潜能；`character_module` 模组；`character_voice` 语音；`character_skin` 时装；
`operator_record` 干员密录；`character_bundle` 指定角色的档案+模组+语音+密录；
`character_wiki` 规范角色 Wiki；`story_wiki` 活动/密录 Wiki；
`character_activity_wiki` 角色×活动辅助 Wiki；`reviewed_wiki` 全部自建 Wiki；
`terra_journey` 大地巡旅；`entity_profile` 实体资料；`reference` 时间线等引用资料。

**终末地资料类型**：`original_story` 官方剧情原文；`archive` 官方档案；
`knowledge` 知识资料；`wiki` 整理性 Wiki；`character_story` 角色故事；
`timeline` 时间线资料；`entity_profile` 实体资料。可配合 `content_types` 区分对话、
过场、广播、通讯、环境对话、SNS 等内容形式。

### corpus_read — 原文阅读

优先使用游戏内关卡代号、密录名、角色名、活动名或任务名；无法稳定定位时再使用搜索返回的标题；标题可省略分隔符与 Wiki 序号后缀，找不到时会列出最接近的完整标题。
不使用内部 `document_id`、ref 或路径。搜索结果只在同名歧义时给出公开稳定的 `document_uid`；它替代 `title`，不得同时提交两者。同名多合集不会自动合并。

| 用法 | 参数 |
| --- | --- |
| 明日方舟关卡 | `stage_code`；同代号多篇时可加 `story_part`：`before` / `after` / `story`（省略时默认行动前并提示其他篇）；加 `line` 可定点读上下文 |
| 干员密录 | `character_name` + `record_name`；多段密录加 `segment` |
| 角色官方资料 | `character_name` + `material`，类别为 `profile/module/voice/skin/recruitment/potential` |
| 双模块同名角色消歧 | 在角色定位参数之外加 `game: "arknights"` 或 `game: "endfield"`；无同名歧义时不填 |
| 整活动连续阅读 | `activity_name` + `mode: "activity"` |
| 终末地任务连续阅读 | `collection_name` + `mode: "collection"`，可选 `content_types` |
| 其他资料定点上下文 | `title` + `line`（`line` 是中心行，默认前后各 3 行；不用于全文续读） |
| 终末地角色档案 | `character_name` + `material: "profile"`（与明日方舟同一套；如 `{"character_name":"管理员","material":"profile"}`） |
| 读 Wiki 字段 | `title` + `section`（精确读取标签字段，不含标签行） |
| 分页读其他全文 | `title` + `mode: "document"`，要从中间开始时加 `start_line`（`max_lines` 默认 100、上限 500；`max_chars` 默认 12000、上限 100000） |
| 同名单篇 | `document_uid` + `line`，或 `document_uid` + `mode: "document"`；不再提交 `title` |
| 续读 | 复制结果末尾的续读调用；单篇续页给 `start_line`，活动/任务给 `position`，`data_version` 为短版本号且可省略；旧 `cursor` 仅兼容历史会话 |

`mode: "document"` 不接受 `line`（除 `line: 1` 这类无害占位）：两者语义不同，混用会让续读停在同一段并误显示为「复用上文」。`start_line` 只用于全文连续读取。

每次读取只选一种主定位方式。`max_lines/max_chars` 只限制输出量，不能代替 `line`、`section` 或 `mode`。

重复读取与部分补读保持正常的预算和续页位置。部分补读会用 `coverage` 标明本页复用的上文行及新返回行；全文是否读完仍以 `page.has_more` 为准。
复用只看宿主给出的「当前可见 surface」：长会话里上文若已被压缩或折叠，那一页会既看不到行、又被判定为可见。此时传 `reuse: false` 强制重发本页全文，不要改 `max_lines` 绕着试。

每条命中还会带「句柄」：`doc_xxxxxxxxxxxxxxxx#L12`（区间为 `#L12-30`）。它同时是篇章定位和行号，直接把句柄塞回读取即可，不必先查 `document_uid`：
`corpus_read({"citation":"doc_xxxxxxxxxxxxxxxx#L12"})`。`citation` 与 `title`/`document_uid`/`line` 互斥，格式错误会直接报 `INVALID_REQUEST`。

零命中会给出检索覆盖范围（`scope`：本地篇数/行数），例如「已检查完整检索范围（本地 34007 篇 / 1133511 行），没有找到」——「没有」因此可以当作否定证据引用，但范围仍以当前安装的资料包为准。

引用格式统一为「《篇章名》第 N 行」。剧情文档只返回请求的原文；剧情总结与活动
时间线必须通过 `timeline_search` 或 Wiki 字段显式检索，不自动夹带。

### timeline_search — 活动时间线

按活动名、年份及自动展开的实体别名检索活动时间线（PRTS Wiki《泰拉年表》本地投影）。

| 参数 | 说明 |
| --- | --- |
| `query` | 可选的事件正文短语（≤200 字符） |
| `activity_names` | 活动展示名（≤20 项，如「孤星」；接受主线章节号常见写法） |
| `entity_names` | 角色/实体展示名（≤20 项，自动经别名图鉴裂变后检索） |
| `year_start` / `year_end` | 年份范围（含端点，可单独使用） |
| `source_marker` | 反查模式：原样传回结果中的「年表出处:tle_…」标记，返回该事件完整来源 |
| `max_results` | 最多返回事件数，默认 20、上限 100 |

### cloud_search / cloud_inspect — 云端混合检索（可选）

用自然语言查询 PRTS.chat 云端的图谱、档案、原文、自建 Wiki 和时间线组合索引。
默认走**匿名会话**（内置 PoW 挑战，无需账号），也可在设置页配置静态 token。
返回末尾的「## 可读取原文」列出已映射到本地篇章的完整标题与行号，直接按
`title + line` 调用 `corpus_read` 核验。`cloud_inspect` 用于复查最近一次云端
检索的状态（回答材料、候选、诊断），`request_id` 由运行时自动注入。

本地资料尚未安装或无法读取时，云端答案仍会返回，并提示本地原文映射不可用；安装或修复资料包后可继续核验原文。

### web_search / web_fetch — DSH 原生网页工具

由 PRTS 模式挂载：`web_search` 发现网页候选，`web_fetch` 读取已知 URL 正文，
用于语料之外的历史沿革、词源、民俗等公网信息核验。DSH `0.1.2-alpha.1` 起的匿名
HTTP provider 只允许公网 HTTP(S)，并包含 DNS 解析校验、连接地址固定、同源重定向
以及响应大小和超时限制。

## 检索配方

Wiki 资料不是无差别文本池：工具会区分规范角色页、活动/密录页和角色×活动辅助页。
常见问题的组合方式：

```text
凯尔希参加过哪些活动？
  → corpus_search({ resource_types: ["character_wiki"],
                     character_names: ["凯尔希"], wiki_sections: ["相关活动"] })

凯尔希在《孤星》里做了什么？
  → corpus_search({ resource_types: ["story_wiki"], activity_names: ["孤星"],
                     wiki_sections: ["角色剧情概括"], query: "凯尔希" })

1102 年 1 月发生了什么？
  → timeline_search({ year_start: 1102, year_end: 1102 })

某人亲口说过什么？
  → corpus_search({ speakers: ["阿米娅"], query: "博士" })
```

完整字段语义与更多配方见 `skills/prts-retrieval/references/wiki-schema.md`
与 `retrieval-recipes.md`（模型通过 `prts-retrieval` 技能按需读取）。

## 资料与配置

- 默认资料目录：`$DSH_HOME/prts-corpus/releases`；用户配置：`$DSH_HOME/prts-corpus.json`
- 配置分三层：内置默认值 ← `cordis.patch.yml` 行内 config ← 用户文件（设置页写入，立即生效）
- 版本检查固定请求 `https://prts.chat` 的 `current`；release、pack 和逐分片摘要均以
  PRTS.chat 为信任源，不能被配置改到其他站点。ModelScope 与可配置回退站点只提供
  该固定 release 的压缩字节；
  文件写入前校验大小和 SHA-256，同一 release 的并发准备由跨进程锁合并
- 设置页通过 Harness Connection 认证 RPC 访问 Host；修改配置后云端工具热注册/注销

读取或搜索期间切换资料版本时，请求会返回可重试的 `PACKAGE_VERSION_MISMATCH`，
重新定位到当前版本后再调用即可。旧任务不会回写新版本的正文或倒排缓存，缓存复用
及跨篇章读取也受同一版本检查约束。

### 实体别名与冲突

识别用户问题里的实体时，一个别名字面只能归属一个实体。当前数据里别名有两个来源：

- **明日方舟**：`references/char_alias.txt`（每行 `规范名;别名;别名…`，源自
  `arknights_lore_wiki/data/char_alias.txt`，本意是生成剧情时定位有别名的人物）+ 实体资料里的
  `aliases` 字段；
- **终末地**：只有实体资料里的 `aliases` 字段。

冲突按以下顺序收敛，绝不把同一个字面交给两个实体：

1. 字面等于某实体自身规范名时归该实体（「海嗣」归海嗣，不再当作某个人的别名）；
2. 否则若 `char_alias.txt` 明确声明了归属，按表裁决（「预言家」归博士）；
3. 两处都没有裁决的冲突（共用称号、同一人物两条实体记录、被误写成别名的类别词）一律不归属任何实体，
   并在本轮上下文里列出候选规范名，提示直呼实体名或分开检索。

代码只负责"不许双重归属"，不猜谁才是对的。要真正消除第 3 类，需要修数据：合并重复实体记录，
或从实体 JSON 的 `aliases` 里删掉误写的词。

**可配置项**（`$DSH_HOME/prts-corpus.json`，设置页可视化编辑）：

| 键 | 默认 | 说明 |
| --- | --- | --- |
| `uiSkin` | `harness` | 皮肤：`harness` / `prts-agent` / `endfield-aic` / `rhine-lab` |
| `cloudEnabled` | 裸插件 `false`；官方 PRTS preset `true` | 云端工具开关；安装器生成的 PRTS 模式默认启用匿名云端检索 |
| `cloudBaseUrl` | `https://prts.chat` | 云端地址（https，或仅环回主机的 http） |
| `cloudToken` | 空 | 静态 Bearer token；留空使用匿名 PoW 会话 |
| `cloudGame` | `all` | `all`（一次检索两款游戏）/ `arknights` / `endfield` |
| `enabledGames` | `["arknights","endfield"]` | 本地与云端工具允许检索的模块，同时决定新下载所需资料包；单模块可只保留其中一项，新会话会装配对应 Skill |
| `cloudUserId` | 空 | 匿名会话的稳定用户标识 |
| `cloudTimeoutMs` | `90000` | 云端请求超时（1000–600000） |
| `cloudMaxResponseBytes` | 32 MiB | 云端响应上限（1 KiB–64 MiB） |
| `downloadSiteBaseUrl` | `https://prts.chat` | 仅作为校验哈希后的字节回退站点；不参与选版或签发摘要 |
| `downloadOrder` | `["modelscope","site"]` | 下载源顺序 |
| `cacheShards` | `24` | 正文分片 LRU 缓存大小（1–128） |

静态 token 绑定保存时的服务源（协议、主机和端口），不会随基础配置或用户配置中的地址变化发送给其他源。旧用户配置若尚无源绑定，请在设置页的令牌框重新输入并保存一次；旧值保留在文件中，重新保存前不会用于请求。只改同源 URL 路径不影响已绑定 token。

若在 preset 的 `prts-corpus.config.enabledGames` 设置基础范围，也应把相同数组传给相邻的 `prts-terrarchive/skill` entry；安装器生成和迁移的官方 PRTS preset 已自动保持两者一致。用户配置文件中的 `enabledGames` 会同时覆盖两边，修改后请新建会话以装配新的模块说明。

实体检索提示会在 `prts-retrieval` Skill 加载后，按当前用户问题写入 DSH 动态上下文快照；新快照会取代旧快照。PRTS 段只列出当前搭载的资料模块、当前问题命中的规范实体与游戏归属，以及与本轮实体相关的再旅者关系。工具调用标题会同时标明本地或云端资料及检索的游戏范围。

**内存说明**：新版资料包附带轻量 `document_catalog`，启动只从目录建立篇章定位、
标题、别名和检索元数据；正文分片在读取或命中后才解压，并由 `cacheShards` 限制缓存
数量。旧资料包仍兼容，但首次初始化需要扫描其正文分片。Node/V8 可能保留已申请的
堆页，因此操作系统看到的常驻内存不会在查询结束后立即回落。

## 皮肤

设置 → 插件 → PRTS 语料中选择：

- **Harness 默认**：不改动宿主外观；
- **PRTS Agent**：PRTS 终端风格界面；
- **Endfield AIC**：明日方舟：终末地终端风格，含 3D 地图。所需运行代码、模型与贴图已预压缩并随插件包安装，切换皮肤不会触发额外下载。
- **莱茵生命资料馆**：保留 RhineLabUI 原版循环档案阵列，加入 Agent 调查板、重点证据盒、双层分页档案架、本地／云端检索、阅读和摘录。开发时运行 `npm run build:rhine` 和 `npm run preview:rhine`。
- **Agent 回看与协作提醒**：`investigation_get` 可以分页回看线索正文、报告、档案架和重点证据盒，也能按来源 ID 读取保存的正文。手动收藏会同步到会话存储，旧浏览器收藏自动补入。用户新增或修改材料后，运行中的 Agent 在下一次推理时收到提醒，空闲时留到下次对话；只有成功读取对应内容才标为已查看，浏览器查看不会消除提醒。用法见 [调查工作流](skills/prts-investigation/SKILL.md)。

Endfield AIC 的插件代码、UI 集成与地图渲染实现采用 MIT License；其中使用的游戏衍生模型与贴图不属于 MIT 授权范围，仅作为该可选皮肤的组成部分随包提供。具体文件范围见 [GAME_ASSETS.md](GAME_ASSETS.md)。这与「版本管理」下载的语料相互独立：语料按需从 ModelScope 下载，皮肤资源无需另行下载。

## 开发

```bash
npm run build:runtime # 更新随包交付的 YAML / Zod，依赖或构建入口修改后运行
npm run check:runtime # 隔离环境加载所有 Host 入口，不使用 node_modules
npm run check        # 全部源码语法检查
npm test             # node --test 全量测试；语料集成用例需本地 data/releases，否则自动跳过
git diff --check     # 检查待提交文本
```

真实网络下载脚本 `test/real-download.mjs` 不在默认测试集中，避免单元测试意外
下载大型资料。

**目录结构**：

```text
src/
  index.js               插件入口：工具注册、配置装配、云端热重载
  search.js              corpus_search 执行层（候选预筛、扫描、签名游标分页）
  search-projection.js   搜索结果的模型可见投影与渲染
  read.js                corpus_read 执行层（单篇/活动/终末地任务连续阅读）
  timeline.js            timeline_search 执行层（别名裂变、年份交集、出处反查）
  store.js               资料包只读访问层（1/2/3-gram 倒排、旧包短词回退、分片 LRU）
  wiki.js                Wiki 文档角色与标签字段解析
  entity-recognizer.js   实体别名 Aho-Corasick 自动机
  evidence-state.js      会话级证据状态（读取覆盖去重、上下文可见性判定）
  cloud.js               云端客户端（匿名 PoW 会话、静态 token、限流）
  cloud-projection.js    云端结果的模型可见投影
  source-map.js          云端证据 → 本地篇章映射
  installer.js           资料下载器（双源回退、SHA-256 校验、跨进程锁）
  state.js               三层配置与共享状态
  ui.js                  设置页 API（Connection RPC）与静态资源
  skill.js               prts-retrieval 技能注册
lib/
  client.js              Web 客户端入口（皮肤生命周期、设置 UI 席位）
  skins/common.css       插件公共控件样式（始终加载）
  skins/prts-agent.css   PRTS Agent 独立皮肤（仅启用时加载）
  skins/endfield-aic.css Endfield AIC 独立皮肤（仅启用时加载）
  endfield-map/          终末地皮肤地图资源（brotli/gzip 预压缩）
bin/
  install.js             一键安装器
  pack-map-assets.mjs    地图资源压缩打包脚本
contracts/               工具请求/响应 JSON Schema
skills/prts-retrieval/   检索策略技能（字段语义、检索配方）
presets/                 PRTS 模式声明及旧版用户预设初始化
```

## 兼容性

DSH `0.1.2-alpha.1` 与 `0.1.2-alpha.2`（web profile）已完成历史真机验证；其中
`alpha.1` 通过官方 tag 构建并完成安装、预设解析、宿主启动、设置路由和客户端 bundle
加载检查。当前声明的最低运行时为 DSH `0.2.0-rc.1`（`engines.dsh`），并已对照
`0.2.1-rc.2` 源码逐个核对工具注册、systemPrompt 上下文、连接层 Fetch 路由、skill、
preset 与客户端模块协议：0.2.1 起精确 Fetch 路由只放行 owner 主体，桌面载体需显式
声明该主体；PTC 子调用也会持久化 `presentationMeta`，但客户端不读取它，因此证据卡
仍由插件的 receipt 提供。共享 Connection Fetch 通道支持
Web 与官方 Electron 源码实现；Web 同时保留 HTTP 路由。新版声明式预设与
旧版文件预设均通过本项目单元测试。针对 `0.1.7-rc.2`（`477b4f420553`），另以真实
Cordis、Tools、SystemPrompt、Storage Domain 与官方网页工具验证作用域、工具回执、
冷启动调查恢复和服务释放；四种皮肤也在官方插件管理页、设置组件及新旧会话布局下
通过浏览器回归。网页正文仅保存实际交付给模型的文本；恢复档案按网页 URL 合并，
避免实时结果与持久化 ID 不同造成重复入架。模型切换兼容新版 `RemoteResult` 和旧版
`void` 接口，并在失败时保留原会话。`npm pack` / `npm publish` 还会自动检查随包运行时版本，并在无 `node_modules` 的临时目录中加载所有 Host 入口，阻止缺少运行时依赖的包发布。上述测试使用本地模拟网页提供方，无需账号或 API Key；
当前版本的完整 Host 启动及 Windows Electron 实机端到端验证仍待完成。
Electron 便携版默认固定 `0.2.0-rc.1` 官方 tag；旧 Electron 构建入口仍固定
`0.1.5-alpha.1`，原 WebView2 构建固定 `0.1.3-alpha.1`。发行版仍需通过 Windows 上的真实 Host 冒烟。

旧版自定义部署若关闭 `includeUserRoot` 且没有其它 `trust: user` 的预设目录，插件不会写入
预设或更改 roots；部署者需先启用用户预设功能。插件依赖宿主内部接口（`ctx.tools`、
`system-prompt/assemble`、Connection Fetch、agent 预设、客户端 slots/theme）；DSH 大版本升级后
请按「安装 → 重启 → 设置页 → PRTS 模式 → 语料工具 → 网页工具 → 皮肤 → 版本热切换」
过一遍冒烟。

## 许可证与第三方内容

本项目按以下边界提供和授权内容：

- **原创代码与文档**：采用 [MIT License](LICENSE)。
- **游戏相关内容**：《明日方舟》《明日方舟：终末地》相关名称、商标、图像、模型、贴图、游戏数据及其他游戏素材不属于 MIT 授权范围，其权利归各自权利人所有。终末地皮肤所携带资源的具体范围见 [GAME_ASSETS.md](GAME_ASSETS.md)。
- **语料数据**：完整语料不随 Git 仓库或插件代码分发；用户通过插件下载的 PRTS.chat
  资料集适用 [明日方舟资料集](https://modelscope.cn/datasets/HTiantian/prts-agent-corpus-arknights)
  与 [终末地资料集](https://modelscope.cn/datasets/HTiantian/prts-agent-corpus-endfield)
  页面标明的许可证、来源声明和使用条款，不因本项目采用 MIT License 而改变。

本项目为非官方社区项目，与相关游戏的开发商、发行商及其关联方不存在隶属、赞助或背书关系。完整声明见 [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md)。
