dsh-agent-persona 0.1.9 → 0.2.1
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/CHANGELOG.md +54 -0
- package/README.md +113 -190
- package/README_EN.md +117 -214
- package/icon.svg +17 -0
- package/lib/client.js +182 -18
- package/lib/index.d.ts +35 -9
- package/lib/index.js +91 -4
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +18 -13
- package/scripts/install.ps1 +10 -5
- package/scripts/install.sh +9 -5
- package/src/client.ts +218 -20
- package/src/index.ts +85 -4
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,60 @@ All notable changes to this project are documented here.
|
|
|
4
4
|
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
5
5
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [0.2.1] - 2026-11-08
|
|
8
|
+
|
|
9
|
+
这一版修了两个实际会踩到的问题,另外把文档和安装脚本里过时的说法清理了一遍。
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- **用「独占提示词」的 Agent 预设时,人设一个字都发不出去。** 这种预设会声明 `complete: true`,DSH 在
|
|
14
|
+
组装提示词的最后一步会把其他 section 全丢掉,本插件那一节也没了,而且不报错。现在插件在组装结束后
|
|
15
|
+
看一眼结果:发现只剩预设那一段、人设没进去,就把人设补进去——追加接在后面,替换整段换掉。
|
|
16
|
+
插件卸载时会把改动还原。
|
|
17
|
+
- 顺手把这层包装写稳了:宿主不让改方法时只跳过这个功能,不影响插件其他部分;插件卸载后即使别的插件
|
|
18
|
+
也包过一层,这里也不会继续往提示词里塞人设。
|
|
19
|
+
- **「提示词」不再慢一拍。** 以前打开着这个标签去发消息,标签里还是上一轮的 system prompt,得手动点
|
|
20
|
+
刷新或者整页刷新才更新。现在一轮跑完会自动重新读一次;正在编辑人设时不会动你的草稿。
|
|
21
|
+
|
|
22
|
+
### Tests
|
|
23
|
+
|
|
24
|
+
- 补了这些情况的测试:独占提示词下追加 / 替换 / 空正文、普通提示词不重复塞、包装还原、宿主报错时原样
|
|
25
|
+
返回,以及「插件装好后确实会包上 `assemble`」这一层。
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
|
|
29
|
+
- 文档和安装脚本跟上现状:重启说明补了 systemd 托管的做法,插件详情页「界面与功能」和四个界面入口写
|
|
30
|
+
清楚了;开发文档里的断言数量、`dsh.bundle.patch` 字段名、远程方法数(16 个)一并改正。
|
|
31
|
+
|
|
32
|
+
## [0.2.0] - 2026-11-07
|
|
33
|
+
|
|
34
|
+
插件页自己会管配置了,图标、显示名和最新的 DSH 也对上了。
|
|
35
|
+
|
|
36
|
+
### Added
|
|
37
|
+
|
|
38
|
+
- **插件详情页多了「界面与功能」。** 在「插件」里点开 dsh-agent-persona,描述和组件行之间就是这组开关:
|
|
39
|
+
编辑后自动保存、在设置左栏显示「Agent 人设」、在对话页显示「人设」标签、注册到 dsh-better-sidebar、
|
|
40
|
+
保存人设版本历史、禁止模型改写人设文件。它和设置页里那组开关写的是同一份 `prefs`,在哪里改都一样。
|
|
41
|
+
- **`showSettings` 偏好(默认开启)。** 关掉之后设置弹窗左栏不再出现本插件;插件页上的「界面与功能」
|
|
42
|
+
就是回来的路,不会被自己关掉。
|
|
43
|
+
- **四个座位的切换全部即时生效。** 设置入口、对话页标签、dsh-better-sidebar 卡片都在运行时注册/注销,
|
|
44
|
+
不再需要刷新页面(对话页标签旧版需要刷新,现在不用了)。
|
|
45
|
+
- **自己的图标与显示名。** `icon.svg`(人设卡片 + prompt 角标)通过 package.json 顶层 `icon` 字段提供;
|
|
46
|
+
`locale/zh.json` / `locale/en.json` 提供「Agent 人设 / Agent Persona」标题与描述,插件列表、详情页都生效。
|
|
47
|
+
|
|
48
|
+
### Changed
|
|
49
|
+
|
|
50
|
+
- **DSH 兼容范围收敛到 0.2.x。** peer 下限从 `0.1.5-rc.1` 抬到 `0.2.0-rc.2`(图标组件等 API 从这一版才有),
|
|
51
|
+
`dsh.compatibility.dshReleases` 只保留 0.2.0-rc.2 / 0.2.1-rc.2 / 0.2.2-rc.1,并补了 `engines.dsh`。
|
|
52
|
+
- 插件详情页的 `plugins.bundle.config` 注册去掉了无意义的 `order`(keyed slot 只认 key/priority);
|
|
53
|
+
四个弹窗补了 `closeLabel`,关闭按钮有可访问名。
|
|
54
|
+
- `showTab` 的状态文案改成「已显示/已隐藏「人设」标签」,不再提「刷新页面」。
|
|
55
|
+
|
|
56
|
+
### Tests
|
|
57
|
+
|
|
58
|
+
- 源码审计跟着新结构更新:动态座位(mount/drop)、`plugins.bundle.config` 注册、插件页组件、`showSettings`
|
|
59
|
+
归一化与状态文案;客户端断言 196 条,宿主断言 254 条,`generate-remote --check` 通过。
|
|
60
|
+
|
|
7
61
|
## [0.1.9] - 2026-10-23
|
|
8
62
|
|
|
9
63
|
版本历史从「只能看和恢复」补成「能管理」,并且不再记录重复的正文。
|
package/README.md
CHANGED
|
@@ -8,266 +8,189 @@
|
|
|
8
8
|
|
|
9
9
|
[English](./README_EN.md)
|
|
10
10
|
|
|
11
|
-
##
|
|
12
|
-
|
|
13
|
-
一个 DSH 部署里常常同时跑着好几摊活:写前端、写文档、盯告警、做代码审查。它们需要不同的身份、口径和约束。
|
|
14
|
-
这个插件把人设按**工作区**或**会话**分发出去,每一份都是 system prompt 里的一段:
|
|
15
|
-
|
|
16
|
-
- **多个人设,各自声明适用范围**:一条人设可以同时用于若干个工作区目录和若干个会话;匹配方式有
|
|
17
|
-
完全一致、开头是、包含、正则匹配四种。
|
|
18
|
-
- **越具体越优先**:会话 ID 的规则优先于工作区,精确优先于前缀/正则;只有具体度相同时才按列表顺序决定。
|
|
19
|
-
- **显式默认人设**:可以把某一条标成「默认人设」,它会收下所有没被位置命中的会话 —— 同一时刻只允许一条。
|
|
20
|
-
不标就没有兜底,那些会话继续用 DSH 自带的 system prompt。
|
|
21
|
-
- **一个位置只能属于一条人设**:把某个工作区/会话配给新人设时,原来占着它的那条会自动失去它,并告诉你从谁那里转来的。
|
|
22
|
-
- **追加或替换**:保留 DSH 自带的身份提示、把人设接在后面,或者去掉那句身份提示只用人设。
|
|
23
|
-
- **正文为空 = 这里不要人设**:给某个位置加一行、正文留空,就显式地在那里关掉人设。
|
|
24
|
-
- **改完下一条消息生效**,不用重启(正文按文件时间戳在每次组装时重读)。
|
|
25
|
-
- **工具改不动人设文件**:人设会被注入 system prompt,所以宿主注册了一个全局 `tools.guard`,拒绝一切指向人设
|
|
26
|
-
存储的写入(`write` / `edit` 各类文件工具,以及含写入特征的 shell 命令),只读命令照旧放行。
|
|
27
|
-
- **存储读不出来时不会悄悄丢**:文件存在但读不出来(内容坏了、不是人设存储)时,页面会说明原因,并且**在第一次
|
|
28
|
-
保存之前**先把原文件复制成 `personas.json.bak-<时间戳>`;备份失败就不会写入。
|
|
29
|
-
- **导入 / 导出**:导出为一份 JSON 文件(同时复制到剪贴板);导入可以选文件或粘贴,**边输入边预览**每条人设的
|
|
30
|
-
字数与规则数,再以「一律新建、一律停用」的方式写进去,默认人设不会被替换。
|
|
31
|
-
|
|
32
|
-
三处界面,各管一件事:
|
|
33
|
-
|
|
34
|
-
| 界面 | 位置 | 用途 |
|
|
35
|
-
|---|---|---|
|
|
36
|
-
| **设置页** | 设置 → Agent 人设 | 新建/编辑/删除/复制/排序人设;写正文、Markdown 预览、让 AI 改一版。标题旁另有 **GitHub / npm 链接**与**当前安装的版本号**(悬浮会说明这一份是 npm 装来的还是本地开发目录加载的) |
|
|
37
|
-
| **会话视图** | 对话页顶部的 **人设** 标签 | 看这条会话命中了哪条人设、**实际发出去的 system prompt**(渲染/源码两视图),以及就地管理全部人设 |
|
|
38
|
-
| **侧边栏卡片** | dsh-better-sidebar 的右侧栏 | 把上面那个「人设」页面挂进右侧栏(需要装了该插件) |
|
|
39
|
-
|
|
40
|
-
五个偏好开关(`编辑后自动保存` / `在对话页显示「人设」标签` / `注册到 dsh-better-sidebar` / `禁止模型改写人设文件` / `保存人设版本历史`)
|
|
41
|
-
都在**设置 → Agent 人设**页里,并且这个页面**不受这些开关影响** —— 关掉「对话页显示」或「注册到 dsh-better-sidebar」后,
|
|
42
|
-
回到这里就能重新打开。本插件不在**设置 → 通用设置**里添加任何条目;鼠标停在开关上会给出每个开关的完整说明。
|
|
43
|
-
|
|
44
|
-
## 为什么它压得住 AGENTS.md
|
|
11
|
+
## 它解决什么问题
|
|
45
12
|
|
|
46
|
-
DSH
|
|
47
|
-
*"They do not override system, developer, or direct user instructions."* 而这个插件写的是
|
|
48
|
-
**system prompt 的一个 section**(section 名 `agent-persona`,order 1,紧跟在身份行之后)。
|
|
13
|
+
同一个 DSH 里常常同时跑着好几摊活。写前端时,你希望 agent 直接给改法、少客套;写文档时,你希望它先把结构讲清楚;盯告警的会话里,你希望它动手前先确认。这些差别不方便全塞进 `AGENTS.md`——工作区指令进的是 user 角色消息,模型可以不完全照办。
|
|
49
14
|
|
|
50
|
-
|
|
15
|
+
这个插件把人设写成 **system prompt 的一个 section**(section 名 `agent-persona`,紧跟在 DSH 自带的身份行之后),再按工作区路径或会话 id 分发。一个位置只属于一条人设,越具体的规则越优先;改完之后,下一条消息就按新人设走。
|
|
51
16
|
|
|
52
|
-
##
|
|
17
|
+
## 安装
|
|
53
18
|
|
|
54
|
-
|
|
55
|
-
`0.2.1-rc.2`。** `package.json` 的 `dsh.compatibility` 声明的就是这四项 —— 含义是"我们在这些版本上跑过",
|
|
56
|
-
**不是**对更早或更新版本做过兼容工作的承诺;其它版本请自行验证。
|
|
57
|
-
|
|
58
|
-
侧边栏卡片还需要 **`dsh-better-sidebar`**:没装它时,「注册到 dsh-better-sidebar」这个开关不会出现
|
|
59
|
-
(没有可注册的地方),插件其余功能照常。
|
|
19
|
+
要求 DSH `0.2.0-rc.2` 及以上;当前版本在 `0.2.2-rc.1` 上实测通过(完整兼容列表见下文)。先在插件市场(如 dshmarket)或命令行装进你要用的 profile:
|
|
60
20
|
|
|
61
21
|
```bash
|
|
62
22
|
dsh plugin --profile web add dsh-agent-persona
|
|
63
23
|
```
|
|
64
24
|
|
|
65
|
-
装完**重启一次 `dsh web
|
|
25
|
+
装完**重启一次 `dsh web`**。profile 的 bundles 只在启动时读取,插件行就是从这里挂进去的。如果你的宿主由 systemd 之类的服务托管(比如本机的 `dsh-web-wood`),改用 `sudo systemctl restart dsh-web-wood`,别自己 kill 掉进程再手起。重启后设置左栏会多出 **Agent 人设**;`~/.dsh/dsh-agent-persona/state.json` 里也有加载心跳,写明了加载的文件、人设存哪、一共几条。
|
|
66
26
|
|
|
67
|
-
|
|
27
|
+
升级、卸载同样是 `dsh plugin --profile web update|remove dsh-agent-persona`,重启一次后生效。人设文件不会跟着删,也不会被覆盖。仓库里另有本地安装脚本:`bash scripts/install.sh`(Windows 用 `scripts/install.ps1`)。
|
|
68
28
|
|
|
69
|
-
|
|
70
|
-
- `cat ~/.dsh/dsh-agent-persona/state.json` —— 插件的加载心跳,写明了它加载了哪个文件、人设存哪、几条人设。
|
|
29
|
+
## 三分钟上手
|
|
71
30
|
|
|
72
|
-
|
|
31
|
+

|
|
73
32
|
|
|
74
|
-
|
|
33
|
+
打开 **设置 → Agent 人设**,点 **新建人设**,然后在「适用范围」里一行一行加位置:先选 **工作区目录** 或 **某个会话**,再从下拉框里挑具体目标。下拉框的数据来自 DSH 自己的工作区与会话列表,显示标题和「几分钟前」,不用记 session id;想用前缀、包含或正则,选 **自己输入…**。
|
|
75
34
|
|
|
76
|
-
|
|
77
|
-
dsh plugin --profile web update dsh-agent-persona # 升级(按依赖的版本范围取最新)
|
|
78
|
-
dsh plugin --profile web add dsh-agent-persona@latest # 想跨大版本升到最新
|
|
79
|
-
dsh plugin --profile web remove dsh-agent-persona # 卸载
|
|
80
|
-
```
|
|
35
|
+
写完正文、打开启用开关、保存。有两点值得先知道:
|
|
81
36
|
|
|
82
|
-
|
|
37
|
+
- 新建出来的人设默认**停用**,所以多建一条不会影响任何现有会话;
|
|
38
|
+
- 一个位置只能归一条人设。把某个工作区配给新的人设时,原来占着它的那条会自动失去它,保存时会告诉你是从谁那里转来的。
|
|
83
39
|
|
|
84
|
-
##
|
|
40
|
+
## 界面入口
|
|
85
41
|
|
|
86
|
-
|
|
42
|
+
| 入口 | 位置 | 用来做什么 |
|
|
43
|
+
|---|---|---|
|
|
44
|
+
| **设置页** | 设置 → Agent 人设 | 新建、编辑、删除、复制、排序人设;写正文、Markdown 预览、让 AI 改一版。标题旁有 GitHub / npm 链接和当前安装版本 |
|
|
45
|
+
| **对话页「人设」** | 对话页顶部的 **人设** 标签 | 看这条会话命中了谁、实际发出去的 system prompt,也能就地管理全部人设 |
|
|
46
|
+
| **右侧栏卡片** | dsh-better-sidebar 的右侧栏 | 把同一个「人设」页面挂进右边栏(需要装该插件) |
|
|
47
|
+
| **插件详情页** | Web GUI → 插件 → dsh-agent-persona | 6 个偏好开关、插件图标与显示名 |
|
|
87
48
|
|
|
88
|
-
|
|
49
|
+
### 插件详情页里的配置
|
|
89
50
|
|
|
90
|
-
-
|
|
91
|
-
- **适用范围**是一行一行加的。每行先选类型(**工作区目录** 或 **某个会话**),再从下拉框里挑具体是谁。
|
|
92
|
-
两种类型互斥:把一行从「工作区」切成「某个会话」,这一行原来选的值会被清掉,重新选。
|
|
93
|
-
- 下拉框里的工作区来自 DSH 的工作区列表(带会话数),会话来自 DSH 的全部会话,按时间倒序,
|
|
94
|
-
带**标题**、工作目录和「几分钟前」—— 不记得 session id 是什么没关系,认标题就行。
|
|
95
|
-
- 想用前缀、正则这类高级匹配,选 **自己输入…** 就会变成输入框。
|
|
96
|
-
- 折叠状态下,卡片第二行分开列出这条人设用在了哪些**工作区**、哪些**会话**;**一个位置都没加**时写着
|
|
97
|
-
「未设置位置:不生效,该会话仍用 DSH 自带的 prompt」——那是停在草稿状态的人设,不是兜底。
|
|
98
|
-
- 想让它兜底,就打开卡片里的 **默认人设** 开关;列表行上会出现绿色的「默认」标记。
|
|
51
|
+

|
|
99
52
|
|
|
100
|
-
|
|
53
|
+
插件详情页多了「界面与功能」区块,副标题说明它决定插件在 DSH 里出现在哪、编辑时有哪些保护;人设内容仍在「设置 → Agent 人设」里编辑,关掉左栏入口后这个页面就是回来的路。6 个开关集中在这里,设置页里也保留了同一组,两处写的是同一份 `prefs`,改哪边都会同步;每次拨动立刻保存,没有「保存」按钮。
|
|
101
54
|
|
|
102
|
-
|
|
55
|
+
关掉「在设置左栏显示「Agent 人设」」只是从设置导航里隐藏,插件详情页仍在,可以继续改人设、随时开回来。插件列表里中文名是「Agent 人设」、英文名是「Agent Persona」,说明文字来自 `locale/`,图标是包根的 `icon.svg`,不跟随主题色。
|
|
103
56
|
|
|
104
|
-
|
|
57
|
+

|
|
105
58
|
|
|
106
|
-
|
|
107
|
-
`personas.history.json`)。编辑器底部的 **版本历史** 按钮打开对比窗口:
|
|
59
|
+
## 人设列表与编辑
|
|
108
60
|
|
|
109
|
-
|
|
61
|
+
列表按优先级从上到下排列,卡片上能看到启用状态、默认人设标记、用在了哪些工作区与会话、正文长度和规则数。`⋯` 菜单里可以上移、下移、复制、删除。折叠状态下如果一条人设**一个位置都没加**,会写着「未设置位置:不生效,该会话仍用 DSH 自带的 prompt」——那是草稿,不是兜底。想让它兜底,打开卡片里的 **默认人设** 开关,同一时刻只允许一条。
|
|
110
62
|
|
|
111
|
-
-
|
|
112
|
-
- **每条都是 diff**:相等行只记行数,只有真正改动的行才存原文,所以一百条版本也远小于一百份正文。
|
|
113
|
-
- **恢复**:选中任意一条点「恢复到此版本」写回正文;恢复动作本身也记一条,恢复错了还能再回滚。
|
|
114
|
-
- **删除**:选中任意一条点「删除此版本」(连点两次确认)就把这条记录删掉;它后面的版本会重新计算
|
|
115
|
-
diff,仍然可以逐条打开,链不会断。
|
|
116
|
-
- **同一份正文只存一条**:每条版本带正文的 sha256 前 16 位,保存时若和已有版本的内容哈希相同,就不
|
|
117
|
-
再新增记录(撤销、恢复后再保存、导入同样的正文都属于这种情况),列表和对比窗口里都能看到哈希。
|
|
118
|
-
- **链式重放**:第一条版本作为基准快照,之后逐条重放;超过 200 条时把最旧的几条折进基准,
|
|
119
|
-
保留下来的版本仍可逐条打开。每条记录带内容摘要,历史文件被手改坏时重放会报错,不会给出别的正文。
|
|
120
|
-
- 关掉开关只是停止记录,已有历史仍可查看与恢复。
|
|
63
|
+

|
|
121
64
|
|
|
122
|
-
|
|
65
|
+
展开卡片后可以改名称、默认人设、注入方式和正文。正文支持 Markdown 预览,也能让 DSH 当前设置的模型改一版;AI 只产出建议稿,点「采用」或「追加」才进编辑框,再保存才落盘。导入导出也在这一页:导出是一份 JSON 文件(同时复制到剪贴板);导入可以选文件或直接粘贴,边输入边预览每条人设的字数与规则数,再以「一律新建、一律停用」的方式写进去,不会顶掉默认人设。
|
|
123
66
|
|
|
124
|
-
|
|
67
|
+
## 版本历史(可选)
|
|
125
68
|
|
|
126
|
-
-
|
|
127
|
-
**插件注入**的"看起来像用户消息"的东西一律不展示,弹窗顶部只写「已隐藏 N 条插件注入内容」,
|
|
128
|
-
不占位置,也不会让你困惑"这条我没说过"。
|
|
129
|
-
- 消息过长会被截断,就地提供 **展开全文**(只重读这一条,换掉这一个气泡)与 **收起全文**。
|
|
130
|
-
- **跳到最新** 只显示最后一个用户输入及之后的回复。
|
|
69
|
+

|
|
131
70
|
|
|
132
|
-
|
|
71
|
+
打开 **保存版本历史** 后,每次保存正文都会在 `personas.history.json` 里记一条 diff。编辑器底部的 **版本历史** 按钮打开对比窗口:
|
|
133
72
|
|
|
134
|
-
|
|
73
|
+
- **只记正文**:改名称、启用状态、适用范围不产生版本;
|
|
74
|
+
- **存的是 diff**:相同行只记行数,只有真正改动的行保留原文;
|
|
75
|
+
- **恢复与删除**:任意一条都能恢复;恢复本身也记一版,恢复错了还能回滚。删除一条后,后面的版本会按新的前一条重算 diff,链不会断;
|
|
76
|
+
- **同文去重**:正文的 sha256 前 16 位相同就不新增版本,撤销、恢复后再保存、导入同一份正文都会命中;
|
|
77
|
+
- 关掉开关只是停止记录,已有历史仍可查看和恢复。
|
|
135
78
|
|
|
136
|
-
|
|
79
|
+
## 对话页的「人设」标签
|
|
137
80
|
|
|
138
|
-
-
|
|
139
|
-
以及它自己的状态标记(在用 / 已停用、是否默认人设、注入方式);下面是一个就地编辑器
|
|
140
|
-
(名称、默认人设开关、注入方式、正文),改动后卡片头会出现「未保存 · 点击保存」。
|
|
141
|
-
- **提示词**:这条会话**实际发出去的** system prompt,可以切换「渲染 / 源码」、复制、刷新。
|
|
142
|
-
没有命中任何人设时,这里显示的就是 DSH 原生注入的 prompt —— 不做任何特殊处理。
|
|
143
|
-
- **管理**:与设置页同一套卡片(新建、启用/停用、编辑、排序、复制、删除),就地管理。
|
|
81
|
+

|
|
144
82
|
|
|
145
|
-
|
|
83
|
+
选中一条会话后,顶部有 **人设 / 提示词 / 管理** 三个面板:
|
|
146
84
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
| 在对话页显示「人设」标签 | 开 | 是否注册对话页那个视图 | 立即(运行时注册/注销) |
|
|
151
|
-
| 注册到 dsh-better-sidebar | 开 | 是否把「人设」页面注册进 dsh-better-sidebar 的右侧栏 | 立即;**没装该插件时这个开关不显示** |
|
|
152
|
-
| 禁止模型改写人设文件 | 开 | 按**能力**判定:任何会写入/删除人设存储(含它的历史文件与备份副本)的工具调用都拒绝,读取、`grep`、把路径写进笔记都不受影响;关掉后不拦 | 立即;对**下一次工具调用**生效 |
|
|
153
|
-
| 保存人设版本历史 | 关 | 每次保存记一条可重放的 diff(最多 200 条,可查看/对比/恢复) | 立即;关掉后不再记新版本,已有历史仍可查看 |
|
|
85
|
+
- **人设**:命中了哪条人设、依据是哪几条规则、正文渲染结果,以及就地编辑器;
|
|
86
|
+
- **提示词**:这条会话**实际发出去的** system prompt,可切换渲染/源码、复制、刷新。一轮对话结束时它会自己重新读一次,不用手动点刷新;如果你正开着编辑框,它不会把你的改动冲掉;
|
|
87
|
+
- **管理**:和设置页同一套卡片,就地新建、启用、编辑、排序、复制、删除。
|
|
154
88
|
|
|
155
|
-
|
|
156
|
-
供"加载时决定要不要注册视图"用。
|
|
89
|
+
旁边的只读会话记录弹窗只显示你真正敲进去的内容,插件注入的「看起来像用户消息」的内容会折叠成一行提示;长消息可单条展开,也能跳到最新。
|
|
157
90
|
|
|
158
|
-
##
|
|
91
|
+
## 右侧栏卡片
|
|
159
92
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
93
|
+

|
|
94
|
+
|
|
95
|
+
装了 **dsh-better-sidebar** 之后,同一个「人设」页面可以挂进右侧栏。没装该插件时,「注册到 dsh-better-sidebar」这个开关不会出现,其余功能不受影响。
|
|
96
|
+
|
|
97
|
+
## 6 个偏好开关
|
|
98
|
+
|
|
99
|
+
| 开关 | 默认 | 作用 | 在哪里改 | 生效时机 |
|
|
100
|
+
|---|---|---|---|---|
|
|
101
|
+
| 在设置左栏显示「Agent 人设」 | 开 | 设置左侧导航里是否出现这个页面;关掉后从「插件 → dsh-agent-persona」进来 | 设置页或插件详情页 | 立即 |
|
|
102
|
+
| 在对话页显示「人设」标签 | 开 | 是否注册对话页顶部的「人设」标签 | 设置页或插件详情页 | 立即(运行时注册/注销) |
|
|
103
|
+
| 注册到 dsh-better-sidebar | 开 | 是否把人设页注册进右侧栏;没装该插件时这一项不出现 | 设置页或插件详情页 | 立即 |
|
|
104
|
+
| 编辑后自动保存 | 关 | 停手约 1 秒自动保存编辑区 | 设置页或插件详情页 | 立即;切换适用范围行时不自动保存,避免存下半截选择 |
|
|
105
|
+
| 保存人设版本历史 | 关 | 每次保存正文记一条可重放的 diff | 设置页或插件详情页 | 立即;关掉后不再记新版本,旧历史仍可查看 |
|
|
106
|
+
| 禁止模型改写人设文件 | 开 | 拒绝会写到人设存储的工具调用(读取、grep 不受影响) | 设置页或插件详情页 | 对下一次工具调用生效 |
|
|
107
|
+
|
|
108
|
+
偏好存在人设文件的 `prefs` 字段里,不是浏览器,所以它和数据的可见范围一致;浏览器只留一份镜像,用来决定加载时要不要注册视图。
|
|
109
|
+
|
|
110
|
+
## 匹配与优先级
|
|
111
|
+
|
|
112
|
+
每次组装 system prompt 时:
|
|
113
|
+
|
|
114
|
+
1. 停用的人设跳过;
|
|
115
|
+
2. 任意一行命中就成为候选,按具体度比较:会话 id(3 分)> 工作区(1 分),精确 > 前缀/包含/正则;
|
|
116
|
+
3. 具体度相同,取列表里靠上的那条;
|
|
117
|
+
4. 一个位置都没加的人设不参与匹配(草稿态),除非标了默认人设;
|
|
118
|
+
5. 谁都没命中,有默认人设就用它,没有就不注入;
|
|
119
|
+
6. 赢家的正文为空,等于「这里明确不要人设」,不注入任何东西。
|
|
120
|
+
|
|
121
|
+
四种匹配里只有 `完全一致` 会把路径归一化(`/a/project/` 和 `/a/project` 算同一个);`开头是`、`包含`、`正则匹配` 拿你写的字符串原样比较。值空着、正则写错、会话没有对应字段,都算不匹配,不会报错。细节见 [docs/architecture.md](./docs/architecture.md)。
|
|
164
122
|
|
|
165
|
-
|
|
166
|
-
插件不会去覆盖它 —— 别人的身份提示优先。
|
|
123
|
+
### 注入方式:追加还是替换
|
|
167
124
|
|
|
168
|
-
|
|
125
|
+
| 方式 | 效果 |
|
|
126
|
+
|---|---|
|
|
127
|
+
| **追加**(默认) | 保留 DSH 自带的身份句,人设接在它后面 |
|
|
128
|
+
| **替换** | 去掉 DSH 自带的身份句和部署自己写的 persona 段,只用这条人设 |
|
|
169
129
|
|
|
170
|
-
|
|
130
|
+
「替换」只动部署自己写的那段。如果某个 Agent 预设在自己的作用域里写了 persona,插件不会覆盖它——别人的身份提示优先。
|
|
171
131
|
|
|
172
|
-
|
|
173
|
-
2. 一条人设的**任意一行**匹配上,它就是候选,按"具体度"比较(会话 ID 3 分 > 工作区 1 分;精确 > 前缀/包含/正则);
|
|
174
|
-
3. 具体度相同 → 取列表里靠上的那条(顺序在卡片的 `⋯` 菜单里调);
|
|
175
|
-
4. **一个位置都没加的人设不参与匹配**(草稿态),除非它被标成「默认人设」;
|
|
176
|
-
5. 谁都没命中 → 看有没有「默认人设」,有就用它,没有就不注入;
|
|
177
|
-
6. 赢家的正文是空的 → 不注入任何人设(这是"这里明确不要人设"的表达方式)。
|
|
132
|
+
正文里可以用 `{{model}}` 和 `{{cwd}}`,渲染时替换成当前值;其它 `{{...}}` 会被去掉,不会让整个组装报错。
|
|
178
133
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
134
|
+
还有一种情况得说清楚:有些 Agent 预设的人设段会声明 `complete: true`,意思是「这一节就是完整提示词」。
|
|
135
|
+
DSH 组装到最后会把别的 section 全扔掉,插件写的那节也一样,所以这种预设下人设看起来配好了、实际没发出去。
|
|
136
|
+
现在插件会在组装结束后检查一遍:要是只剩预设那一段、人设没进去,就把它补进去——追加接在后面,替换则
|
|
137
|
+
整段换成这条人设。换句话说,遇到这种预设时上面「别人的身份提示优先」就不作数了,那段提示词是唯一的位子。
|
|
182
138
|
|
|
183
|
-
##
|
|
139
|
+
## 数据与安全
|
|
184
140
|
|
|
185
141
|
```
|
|
186
142
|
~/.dsh/dsh-agent-persona/
|
|
187
|
-
├── personas.json #
|
|
143
|
+
├── personas.json # 人设 + 偏好,权限 600,原子写入
|
|
188
144
|
├── personas.history.json # 版本历史(开关打开后才出现)
|
|
189
145
|
└── state.json # 加载心跳,每次加载时重写
|
|
190
146
|
```
|
|
191
147
|
|
|
192
|
-
|
|
193
|
-
整个组装抛错,所以这里做了保护)。
|
|
194
|
-
|
|
195
|
-
配置项(Schemastery schema,加载时校验,写错类型会**加载失败**而不是被忽略):
|
|
196
|
-
|
|
197
|
-
| 配置 | 默认 | 说明 |
|
|
198
|
-
|---|---|---|
|
|
199
|
-
| `storePath` | `''` | 人设文件位置;留空即 `$DSH_HOME/dsh-agent-persona/personas.json` |
|
|
200
|
-
| `tuneProvider` | `''` | AI 调优用哪个 provider;留空即 DSH 当前设置的模型 |
|
|
201
|
-
| `tuneModel` | `''` | 同上,模型 id |
|
|
202
|
-
|
|
203
|
-
### 多个 profile 各用自己的人设文件(可选)
|
|
204
|
-
|
|
205
|
-
人设数据默认是**全局一份**(`$DSH_HOME/dsh-agent-persona/personas.json`,与其它插件的状态目录同一约定),
|
|
206
|
-
所以同一台机器上的多个 profile 共用同一份人设。要让某个 profile 独立,在**该 profile** 的
|
|
207
|
-
`cordis.patch.yml` 里覆盖它自己的路径(是覆盖字段,**不要**再 insert 一行):
|
|
148
|
+
默认是**全局一份**,同一台机器上的多个 profile 共用。要让某个 profile 独立,在它的 `cordis.patch.yml` 里覆盖 `storePath`:
|
|
208
149
|
|
|
209
150
|
```yaml
|
|
210
|
-
# ~/.dsh/profiles/<该 profile>/cordis.patch.yml
|
|
211
151
|
- id: agent-persona
|
|
212
152
|
config:
|
|
213
|
-
storePath: /Users/you/.dsh/profiles
|
|
153
|
+
storePath: /Users/you/.dsh/profiles/<profile>/personas.json
|
|
214
154
|
```
|
|
215
155
|
|
|
216
|
-
|
|
217
|
-
|
|
156
|
+
当前生效的文件路径始终显示在「Agent 人设」页的 meta 行上(`保存在 …`)。配置项还有 `tuneProvider` / `tuneModel`,留空就用 DSH 当前设置的模型。
|
|
157
|
+
|
|
158
|
+
安全这块说清楚:**人设是行为约束,不是安全边界**。它约束模型怎么说,不阻止模型用工具。插件注册了一个全局 `tools.guard`,按能力判断这次调用会不会写到 `personas.json`、它的历史文件或备份副本——参数里的路径、shell 命令的重定向目标和写入型命令、补丁正文里的目标都算。但本机 `danger-full-access` 下仍能绕过:改插件代码、运行时拼接的路径、`$VAR` 展开、别名包装,静态判定都看不见。要更结实得在机器层面做,比如 `chflags uchg <人设文件>`,或者把 DSH 跑在受限沙箱里。
|
|
159
|
+
|
|
160
|
+
文件存在但读不出来时,页面会说明原因,并在第一次保存前把原文件备份成 `personas.json.bak-<时间戳>`;备份失败就不写入。
|
|
218
161
|
|
|
219
|
-
##
|
|
162
|
+
## 兼容性
|
|
220
163
|
|
|
221
|
-
|
|
222
|
-
|
|
164
|
+
当前 `package.json` 的 `dsh.compatibility` 声明为这些版本,`engines.dsh` 同样限定 `>=0.2.0-rc.2 <0.3.0`:
|
|
165
|
+
|
|
166
|
+
| DSH 版本 | 说明 |
|
|
167
|
+
|---|---|
|
|
168
|
+
| `0.2.0-rc.2` | 支持的最早版本 |
|
|
169
|
+
| `0.2.1-rc.2` | 实测通过 |
|
|
170
|
+
| `0.2.2-rc.1` | 本版实测通过(当前发布目标) |
|
|
171
|
+
|
|
172
|
+
这张表只表示「我们在这些版本上跑过」,不是对更早或更新版本的兼容承诺。
|
|
223
173
|
|
|
224
174
|
## 几句实话
|
|
225
175
|
|
|
226
|
-
-
|
|
227
|
-
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
-
|
|
231
|
-
运行时拼出来的路径静态看不出;`$VAR` 展开看不出;别名/函数包装也看不出。要更结实得在本机层面做:
|
|
232
|
-
`chflags uchg <人设文件>`(自己改之前先 `chflags nouchg`),或者把 DSH 跑在受限沙箱里、让人设文件属于别的用户。
|
|
233
|
-
- 判定**按单次工具调用**生效:同一条命令里既读又写,写的那部分照样被拒,只读的部分不会被连坐。
|
|
234
|
-
- 多处同时匹配时**只取第一条**,不拼接;规则是线性扫的,几十条没问题,几百条就该重新设计了。
|
|
235
|
-
- 一个 profile 里只装一次。同一个进程挂两个同 id 的行会让组合起不来。
|
|
236
|
-
- **测试的边界**:仓库里的测试是**单元测试 + 源码审计**(236 条宿主断言 + 187 条客户端断言 + 生成产物漂移校验;
|
|
237
|
-
这个数字由测试自己统计,不会随文件改动而失真),它们保证逻辑与代码形状,**不驱动浏览器** —— 界面行为
|
|
238
|
-
(视图渲染、开关、侧边栏卡片)目前靠人工核对。
|
|
176
|
+
- **只取第一条命中**,不拼接;规则是线性扫描,几十条没问题,几百条该重新设计。
|
|
177
|
+
- 一个 profile 里只装一次。同一个进程里挂两个同 id 的行,组合会起不来。
|
|
178
|
+
- 规则里的工作区路径按字符串比对,别依赖大小写或软链接的等价性(`完全一致` 会归一化路径,另外三种不会)。
|
|
179
|
+
- 仓库测试覆盖单元测试与源码审计,界面行为以浏览器实测为准。
|
|
180
|
+
- 人设文件里存的是明文,别把密钥写进正文。
|
|
239
181
|
|
|
240
182
|
## 开发
|
|
241
183
|
|
|
242
|
-
源码是 TypeScript,`lib/` 是构建产物(不进 git
|
|
243
|
-
|
|
244
|
-
```
|
|
245
|
-
src/index.ts host 半边:存储、匹配、system-prompt section、远程服务
|
|
246
|
-
src/client.ts client 半边:设置页 + 会话视图 + 侧边栏卡片(打包成单文件 lib/client.js)
|
|
247
|
-
src/endpoints.ts 远程方法的单一来源(生成 src/remote.ts 与 src/typert.ts)
|
|
248
|
-
scripts/ 生成器 + 安装脚本
|
|
249
|
-
test/ 单元测试与源码审计
|
|
250
|
-
docs/ 架构、开发笔记、设计决策
|
|
251
|
-
```
|
|
184
|
+
源码是 TypeScript,`lib/` 是构建产物(不进 git):`src/index.ts` 是 host 半边(存储、匹配、system-prompt section、远程服务),`src/client.ts` 是 client 半边(设置页、对话页视图、侧边栏卡片),`src/endpoints.ts` 是远程方法的单一来源。目录结构见 [docs/architecture.md](./docs/architecture.md)。
|
|
252
185
|
|
|
253
186
|
```bash
|
|
254
187
|
npm install
|
|
255
188
|
npm run build # generate:remote → tsc → esbuild(产出 lib/)
|
|
256
|
-
npm run typecheck # 两个 tsconfig
|
|
257
|
-
npm test #
|
|
258
|
-
dsh --profile web --dump-config | grep -c 'id: agent-persona' # 组合自检,应输出 1
|
|
189
|
+
npm run typecheck # 两个 tsconfig
|
|
190
|
+
npm test # 单元测试 + 源码审计 + 生成产物漂移校验
|
|
259
191
|
```
|
|
260
192
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
- `src/**` 改完必须 **`npm run build`**(`lib/` 是产物)。
|
|
264
|
-
- 客户端产物(`lib/client.js`)改**内容**:客户端会按内容重算,**刷新页面**即可;别改文件名。
|
|
265
|
-
- 宿主产物(`lib/index.js`)改**内容**:ESM 按 URL 缓存模块,**不会**自动重载 —— 重启 `dsh web`。
|
|
266
|
-
- `package.json` 的 `dsh.bundle.patch` 或 profile 的 `bundles` 有改动:必须重启。
|
|
267
|
-
- 生成产物(`src/remote.ts`、`src/typert.ts`)**不要手改**:改 `src/endpoints.ts` 后跑
|
|
268
|
-
`npm run generate:remote`,`npm test` 会校验它们是否与来源一致。
|
|
269
|
-
|
|
270
|
-
细节在 [docs/development.md](./docs/development.md),内部结构在 [docs/architecture.md](./docs/architecture.md)。
|
|
193
|
+
改完代码怎么生效、开发接线怎么配,见 [docs/development.md](./docs/development.md)。
|
|
271
194
|
|
|
272
195
|
## 许可
|
|
273
196
|
|