dsh-soul 0.7.0 → 0.7.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/LICENSE +21 -0
- package/README.md +32 -19
- package/README_EN.md +36 -19
- package/client/index.mjs +263 -74
- package/index.mjs +425 -76
- package/lib/config.mjs +42 -6
- package/lib/injection.mjs +2 -2
- package/lib/personas.mjs +34 -22
- package/lib/store.mjs +125 -0
- package/package.json +11 -2
- package/scripts/lib/skip-report.mjs +73 -0
- package/scripts/verify-client.mjs +700 -0
- package/scripts/verify-compat.mjs +58 -9
- package/scripts/verify-config.mjs +901 -34
- package/scripts/verify-e2e-prompt.mjs +627 -0
- package/scripts/verify-live-prompt.mjs +445 -0
- package/scripts/verify-nav-icon.mjs +35 -7
- package/scripts/verify-store.mjs +310 -0
- package/scripts/verify-trail.mjs +21 -8
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 LiuYanFeng
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -20,7 +20,8 @@ DeepSeek Harness 个性化设置插件,用于配置 Agent 的昵称、回复
|
|
|
20
20
|
- 提示词随输出语言本地化:`language=en` 时 system prompt 使用英文描述
|
|
21
21
|
- 输入自定义指令
|
|
22
22
|
- Agent 可调用工具 `set_persona`,让模型在对话中直接调整人设
|
|
23
|
-
- 人设预设:
|
|
23
|
+
- 人设预设:7 个内置人设(苏格拉底式提问者 / 极简主义者 / 资深架构师 / 教学型讲解者 / 严格代码审阅者 / 头脑风暴伙伴 / 自驱型协作者,随插件提供、不可删除)+ 多套自建人设一键切换(保存 / 使用 / 列表 / 删除,Web UI 与命令双入口);每行摘要显示风格与偏离默认的维度
|
|
24
|
+
- 预设只管 Agent 的人格:**切换预设不会动「关于你」**(昵称 / 职业 / 介绍是你本人的资料,与「Agent 怎么说话」是两码事)。内置与自建一视同仁——保存预设时只快照风格 / 特质 / 回复长度 / 输出语言 / 自定义指令,不包含身份字段;早期版本存下的完整快照会在读取时自动剥离
|
|
24
25
|
- `set_persona` 确认模式(`requireToolConfirmation`):Agent 的人设修改需经 `/soul confirm` 确认后才生效
|
|
25
26
|
- 输入框光轨:Agent 回复中时,输入框边框显示沿边循环流动的光轨(默认颜色 `#679EFE`)
|
|
26
27
|
- 颜色:预设色板、取色器或十六进制输入(如 `#679EFE`)
|
|
@@ -30,6 +31,10 @@ DeepSeek Harness 个性化设置插件,用于配置 Agent 的昵称、回复
|
|
|
30
31
|
- `/soul set` 键值方式修改配置项
|
|
31
32
|
- 配置持久化保存
|
|
32
33
|
- 配置输入校验:字段白名单、类型、长度上限(昵称/职业 50、介绍 500、自定义指令 2000 字符)、枚举与十六进制颜色校验,非法或超限字段整单拒绝
|
|
34
|
+
- 配置持久化健壮性:写入为**原子替换**(先写临时文件再 `rename`,中断不会留下半份配置);读取区分「文件不存在」与「文件损坏」——损坏时保留原文件、另存 `.corrupt` 备份、**拒绝覆写**,并把原因直接显示在设置页,避免自定义指令与人设库被静默清空
|
|
35
|
+
- 配置损坏时有**逃生口**:「重置」会先把损坏文件移开(备份为 `.corrupt`)再写入默认值 —— 否则损坏状态下五条写路径全被拒,用户只能自己删文件
|
|
36
|
+
- 送达可观测:`/soul show` 的「送达」行、`GET /api/soul/status`、设置页提示条(`configError` = 配置读不出来;`deliveryWarning` = 配置送不到活动会话)
|
|
37
|
+
- 提示词插值已关闭:自定义指令里的 `{{…}}` 按字面保留,不会触发宿主提示词装配失败
|
|
33
38
|
- 配置更新后同步到所有活动 Agent
|
|
34
39
|
- 变更检测:仅在影响 Agent 行为的配置实际变化时刷新提示词并注入会话;纯外观配置(输入框光轨)只落盘,不产生注入消息
|
|
35
40
|
- 插件图标:插件管理列表与侧栏入口显示专属图标(`assets/icon.svg`,36×36,随 npm 包发布)
|
|
@@ -39,8 +44,8 @@ DeepSeek Harness 个性化设置插件,用于配置 Agent 的昵称、回复
|
|
|
39
44
|
## 安装
|
|
40
45
|
|
|
41
46
|
```powershell
|
|
42
|
-
dsh plugin --profile
|
|
43
|
-
dsh plugin --profile
|
|
47
|
+
dsh plugin --profile <profile> add dsh-soul
|
|
48
|
+
dsh plugin --profile <profile> update dsh-soul
|
|
44
49
|
```
|
|
45
50
|
|
|
46
51
|
插件配置由 `cordis.patch.yml` 提供:
|
|
@@ -66,7 +71,7 @@ dsh plugin --profile web update dsh-soul
|
|
|
66
71
|
若 DSH 提示「dsh-soul@x.y.z 与 DSH a.b.c 不兼容」,说明插件版本早于该 DSH 版本,升级插件即可:
|
|
67
72
|
|
|
68
73
|
```powershell
|
|
69
|
-
dsh plugin --profile
|
|
74
|
+
dsh plugin --profile <profile> update dsh-soul
|
|
70
75
|
```
|
|
71
76
|
|
|
72
77
|
## 截图
|
|
@@ -94,15 +99,15 @@ dsh plugin --profile web update dsh-soul
|
|
|
94
99
|
也可以使用斜杠命令:
|
|
95
100
|
|
|
96
101
|
```text
|
|
97
|
-
/soul show
|
|
102
|
+
/soul show 查看当前配置(含确认模式、预设数量与送达状态)
|
|
98
103
|
/soul set k=v 修改配置项(如 /soul set style=humorous language=en;光轨:trailColor=#679EFE trailSpeed=fast trailWidth=thick)
|
|
99
|
-
/soul save <名>
|
|
104
|
+
/soul save <名> 保存当前人设为预设(只含人格维度,不含「关于你」;内置名不可占用)
|
|
100
105
|
/soul use <名> 应用人设预设(内置预设同样可用)
|
|
101
106
|
/soul list 查看人设预设(✔ 标记当前匹配项;内置项带 [内置] 标记)
|
|
102
107
|
/soul del <名> 删除人设预设(delete / rm 别名;内置预设不可删)
|
|
103
108
|
/soul confirm 应用待确认的人设变更(确认模式)
|
|
104
109
|
/soul reject 拒绝待确认的人设变更
|
|
105
|
-
/soul reset
|
|
110
|
+
/soul reset 重置配置(保留人设预设库);配置损坏时这是逃生口,会先备份为 .corrupt
|
|
106
111
|
/soul enable 启用个性化设置
|
|
107
112
|
/soul disable 禁用个性化设置
|
|
108
113
|
/soul 小明 设置昵称
|
|
@@ -139,7 +144,7 @@ soul-config.json
|
|
|
139
144
|
}
|
|
140
145
|
```
|
|
141
146
|
|
|
142
|
-
自建人设预设保存在同一文件的 `personas` 字段:名称 →
|
|
147
|
+
自建人设预设保存在同一文件的 `personas` 字段:名称 → 人设字段快照(风格 / 特质 / 回复长度 / 输出语言 / 自定义指令)+ `updatedAt`。**预设不含「关于你」**(昵称 / 职业 / 介绍)——那是使用者本人的资料,切换预设只换 Agent 的说话方式;这条由 `PROFILE_FIELDS` 与 `PERSONA_FIELDS`(`lib/config.mjs`)结构性保证:保存快照、应用取键、★ 匹配判据、磁盘归一化四条路径都按 `PERSONA_FIELDS` 白名单走,所以内置与自建行为一致。预设库变更不影响活动配置,使用预设时才应用到配置并同步会话。内置人设不落盘(见 `lib/personas.mjs`),列表 / 使用 / ★ 匹配统一走「内置 + 自建」的合并视图,同名以内置为准,内置名既不可保存占用也不可删除。
|
|
143
148
|
|
|
144
149
|
输入框光轨字段:`trailEnabled`(是否启用,默认 `true`)、`trailColor`(6 位十六进制颜色,统一大写存储,默认 `#679EFE`)、`trailSpeed`(`slow` / `normal` / `fast`,默认 `slow`)、`trailWidth`(`thin` / `normal` / `thick`,默认 `thin`)。这四个字段属纯外观配置,只落盘、不进入 system prompt、不触发会话注入。
|
|
145
150
|
|
|
@@ -147,32 +152,40 @@ soul-config.json
|
|
|
147
152
|
|
|
148
153
|
## 实现原理
|
|
149
154
|
|
|
150
|
-
|
|
155
|
+
「保存后下一次请求即生效」由**两条通道**共同保证(缺一不可,见 `DEBUGGING.md` 3.5)。
|
|
156
|
+
|
|
157
|
+
**通道一:system prompt section。** 插件把配置编译成 system prompt 并注册到 DSH:
|
|
151
158
|
|
|
152
159
|
```js
|
|
153
160
|
spCtx.systemPrompt.section({
|
|
154
161
|
name: 'soul:persona',
|
|
155
162
|
order: 0,
|
|
163
|
+
// 关闭宿主提示词插值:默认开启时,用户自定义指令里任何一对完整的 {{…}}
|
|
164
|
+
// 都会让装配抛错(该抛错在 agent.step() 开头且无 try/catch ⇒ 每轮都失败)
|
|
165
|
+
interpolate: false,
|
|
156
166
|
text: () => compilePrompt(configCache || DEFAULT_CONFIG)
|
|
157
167
|
})
|
|
158
168
|
```
|
|
159
169
|
|
|
160
|
-
|
|
170
|
+
宿主在**每一个 step 之前**都会重新装配提示词,对函数式 `text` provider **不做缓存**,并在文本变化时自行提交新的 system 快照 —— 所以这一条的更新时机是「下一次请求」。
|
|
171
|
+
|
|
172
|
+
**通道二:活动会话注入。** 配置变化后,插件遍历所有活动 Agent,用标准 `UserMessage` 调用 `agent.inject()`:
|
|
161
173
|
|
|
162
174
|
```js
|
|
163
175
|
agent.inject(createUserMessage({
|
|
164
|
-
content: [{ type: 'text', text: prompt }],
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
form: 'snapshot',
|
|
169
|
-
sections: [{ name: 'soul:persona', text: prompt }]
|
|
170
|
-
}
|
|
176
|
+
content: [{ type: 'text', text: `[dsh-soul 个性化配置已更新]\n…\n${prompt}` }],
|
|
177
|
+
// 会话格式 v4 要求生产者自持 kind(不得再用共享的 kind:'plugin' + plugin 字段,
|
|
178
|
+
// 那会让每一轮在 step 开始前失败);构造见 lib/injection.mjs
|
|
179
|
+
source: { kind: 'plugin:dsh-soul', form: 'snapshot', sections: [{ name: 'soul:persona', text: prompt }] }
|
|
171
180
|
}))
|
|
172
181
|
```
|
|
173
182
|
|
|
174
|
-
`agent.inject()`
|
|
183
|
+
`agent.inject()` 会把最新配置放入 Agent 的待处理上下文,在下一次请求中生效;不会主动触发新请求,也不会修改历史消息。它同时是「即时生效」的可见载体:会话里会出现一条 `[dsh-soul 个性化配置已更新]` 消息。
|
|
184
|
+
|
|
185
|
+
> 为什么两条都要:**只保留通道一时,实测「会话进行中修改人设」不会在下一轮生效**(0.7.1 开发中曾据此删除通道二,随后原样撤回)。`npm run verify:host` 与 `npm run verify:e2e` 分别把两条通道钉住,DSH 升级后请重跑。
|
|
186
|
+
|
|
187
|
+
**诊断。** 这两条通道静默失效时症状都是「改了配置不生效」,因此插件会如实记录送达结果:`/soul show` 末尾的「送达」行、`GET /api/soul/status`、以及设置页的提示条(`configError` = 配置读不出来,`deliveryWarning` = 配置送不到活动会话)。
|
|
175
188
|
|
|
176
189
|
## 许可证
|
|
177
190
|
|
|
178
|
-
MIT License
|
|
191
|
+
MIT License,完整文本见 [LICENSE](LICENSE)。
|
package/README_EN.md
CHANGED
|
@@ -20,7 +20,8 @@ A personalization plugin for DeepSeek Harness (DSH). Configure your agent's nick
|
|
|
20
20
|
- The compiled system prompt follows the output language (English descriptions when `language=en`)
|
|
21
21
|
- Custom instructions
|
|
22
22
|
- Agent-callable tool `set_persona` to let the model adjust persona during a conversation
|
|
23
|
-
- Named personas:
|
|
23
|
+
- Named personas: 7 built-in personas (Socratic Questioner / Minimalist / Senior Architect / Teaching Explainer / Strict Code Reviewer / Brainstorm Partner / Self-Driven Collaborator — shipped with the plugin, cannot be deleted) plus your own named personas, switched with one click (save / use / list / delete, in both the Web UI and slash commands); each row summarises the style and every dimension that differs from its default
|
|
24
|
+
- Personas cover the **agent's personality only**: switching a persona never touches **"About you"** (nickname / occupation / bio describe *you*, not how the agent talks). Built-in and self-saved personas behave identically — saving a persona snapshots style / traits / reply length / reply language / custom instructions, never the identity fields; full-config snapshots written by earlier versions are stripped on read
|
|
24
25
|
- `set_persona` confirmation mode (`requireToolConfirmation`): agent persona changes take effect only after `/soul confirm`
|
|
25
26
|
- Composer light trail: while the agent is replying, a light trail loops around the composer border (default color `#679EFE`)
|
|
26
27
|
- Color: preset swatches, a color picker, or a hex input (e.g. `#679EFE`)
|
|
@@ -30,6 +31,10 @@ A personalization plugin for DeepSeek Harness (DSH). Configure your agent's nick
|
|
|
30
31
|
- `/soul set` key=value field updates
|
|
31
32
|
- Configuration persisted to disk
|
|
32
33
|
- Input validation: field whitelist, types, length limits (nickname/occupation 50, bio 500, custom instructions 2000 chars), enum and hex-color checks; invalid or oversized fields reject the whole write
|
|
34
|
+
- Durable config: writes are **atomic** (temp file + `rename`, so an interrupted write can never leave half a config); reads tell "file missing" apart from "file corrupted" — a corrupt file is left untouched, backed up as `.corrupt`, **refused as a write target**, and the reason is shown right in the settings page so your custom instructions and persona library are never silently wiped
|
|
35
|
+
- Reset is the **escape hatch** for a corrupt config: since every other write path refuses to touch a corrupt file, `/soul reset` (and the settings-page reset button) moves it aside as `.corrupt` and writes a fresh default config, reporting the backup path — so a bad file never locks you out of the plugin without a restart
|
|
36
|
+
- Delivery is **observable**: `/soul show` ends with a delivery line, `GET /api/soul/status` reports `version` / `enabled` / `configPath` / `configError` / `promptChars` / both channels / `deliveryWarning`, and the settings page shows the same reason as a banner. `configError` (**cannot read** the config) and `deliveryWarning` (**cannot deliver** it to active sessions) are reported separately — same symptom, different fix
|
|
37
|
+
- Prompt interpolation is disabled: `{{…}}` in custom instructions stays literal and can no longer break system-prompt assembly
|
|
33
38
|
- Configuration synced to all active agents after every update
|
|
34
39
|
- Change detection: the prompt is refreshed and sessions injected only when a behavior-affecting field actually changed — appearance-only config (composer light trail) is persisted without injecting anything
|
|
35
40
|
- Plugin icon: a dedicated icon in the plugin manager list and the sidebar entry (`assets/icon.svg`, 36×36, shipped with the npm package)
|
|
@@ -39,10 +44,12 @@ A personalization plugin for DeepSeek Harness (DSH). Configure your agent's nick
|
|
|
39
44
|
## Installation
|
|
40
45
|
|
|
41
46
|
```powershell
|
|
42
|
-
dsh plugin --profile
|
|
43
|
-
dsh plugin --profile
|
|
47
|
+
dsh plugin --profile <profile> add dsh-soul
|
|
48
|
+
dsh plugin --profile <profile> update dsh-soul
|
|
44
49
|
```
|
|
45
50
|
|
|
51
|
+
Replace `<profile>` with your own profile name (e.g. `desktop` when using the DSH desktop build).
|
|
52
|
+
|
|
46
53
|
The plugin is registered via `cordis.patch.yml`:
|
|
47
54
|
|
|
48
55
|
```yaml
|
|
@@ -66,7 +73,7 @@ So DSH **0.1.x and 0.2.x** are supported, prereleases included. Run `npm run ver
|
|
|
66
73
|
If DSH reports "dsh-soul@x.y.z is incompatible with DSH a.b.c", the plugin predates that DSH version — updating it is enough:
|
|
67
74
|
|
|
68
75
|
```powershell
|
|
69
|
-
dsh plugin --profile
|
|
76
|
+
dsh plugin --profile <profile> update dsh-soul
|
|
70
77
|
```
|
|
71
78
|
|
|
72
79
|
## Screenshots
|
|
@@ -94,15 +101,15 @@ After starting DSH, open the **Personalization** section on the settings page, e
|
|
|
94
101
|
Slash commands are also available:
|
|
95
102
|
|
|
96
103
|
```text
|
|
97
|
-
/soul show Show current configuration (confirmation mode &
|
|
104
|
+
/soul show Show current configuration (confirmation mode, persona count & delivery status)
|
|
98
105
|
/soul set k=v Change config fields (e.g. /soul set style=humorous language=en; trail: trailColor=#679EFE trailSpeed=fast trailWidth=thick)
|
|
99
|
-
/soul save <name> Save the current
|
|
106
|
+
/soul save <name> Save the current persona as a preset (personality fields only, never "About you"; built-in names are reserved)
|
|
100
107
|
/soul use <name> Apply a persona (built-in personas work the same way)
|
|
101
108
|
/soul list List personas (✔ marks the active match; built-ins carry a [built-in] tag)
|
|
102
109
|
/soul del <name> Delete a persona (delete / rm aliases; built-in personas cannot be deleted)
|
|
103
110
|
/soul confirm Apply the pending persona proposal (confirmation mode)
|
|
104
111
|
/soul reject Discard the pending persona proposal
|
|
105
|
-
/soul reset Reset configuration (keeps the persona library)
|
|
112
|
+
/soul reset Reset configuration (keeps the persona library; with a corrupt config this is the escape hatch — the bad file is moved aside as .corrupt first)
|
|
106
113
|
/soul enable Enable personalization
|
|
107
114
|
/soul disable Disable personalization
|
|
108
115
|
/soul Bob Set nickname
|
|
@@ -139,7 +146,7 @@ Example:
|
|
|
139
146
|
}
|
|
140
147
|
```
|
|
141
148
|
|
|
142
|
-
Your own personas are stored in the same file under the `personas` field: name → persona field snapshot (
|
|
149
|
+
Your own personas are stored in the same file under the `personas` field: name → persona field snapshot (style / traits / reply length / reply language / custom instructions) + `updatedAt`. **A persona never contains "About you"** (nickname / occupation / bio) — those describe you, and switching a persona only changes how the agent talks. This is enforced structurally by `PROFILE_FIELDS` and `PERSONA_FIELDS` in `lib/config.mjs`: snapshotting, applying, ★ matching and on-disk normalisation all go through the `PERSONA_FIELDS` allow-list, so built-in and self-saved personas behave the same way. Persona library changes never touch the active config; a persona is applied to the config (and synced to sessions) only when used. Built-in personas are not persisted — they live in `lib/personas.mjs` — and listing / applying / match detection all go through the merged view of built-ins plus your own; on a name collision the built-in wins, and a built-in name can neither be saved over nor deleted.
|
|
143
150
|
|
|
144
151
|
Composer light trail fields: `trailEnabled` (on/off, default `true`), `trailColor` (6-digit hex, stored uppercase, default `#679EFE`), `trailSpeed` (`slow` / `normal` / `fast`, default `slow`), `trailWidth` (`thin` / `normal` / `thick`, default `thin`). These are appearance-only: they are persisted but never enter the system prompt and never trigger a session injection.
|
|
145
152
|
|
|
@@ -147,32 +154,42 @@ Length limits: nickname / occupation 50 chars, bio 500 chars, custom instruction
|
|
|
147
154
|
|
|
148
155
|
## How It Works
|
|
149
156
|
|
|
150
|
-
|
|
157
|
+
"Takes effect on the next request after saving" is guaranteed by **two channels** — both are required (see `DEBUGGING.md` 3.5).
|
|
158
|
+
|
|
159
|
+
**Channel 1: the system-prompt section.** The plugin compiles the config into a system prompt and registers it with DSH:
|
|
151
160
|
|
|
152
161
|
```js
|
|
153
162
|
spCtx.systemPrompt.section({
|
|
154
163
|
name: 'soul:persona',
|
|
155
164
|
order: 0,
|
|
165
|
+
// Host prompt interpolation is disabled: with it on, any complete {{…}} pair in your
|
|
166
|
+
// custom instructions makes assembly throw — and that throw happens at the top of
|
|
167
|
+
// agent.step() with no try/catch, so every single turn fails.
|
|
168
|
+
interpolate: false,
|
|
156
169
|
text: () => compilePrompt(configCache || DEFAULT_CONFIG)
|
|
157
170
|
})
|
|
158
171
|
```
|
|
159
172
|
|
|
160
|
-
|
|
173
|
+
The host re-assembles the prompt **before every step**, does **not** cache function-form `text` providers, and commits a new system snapshot whenever the text changes — so this channel updates on the **next request**.
|
|
174
|
+
|
|
175
|
+
**Channel 2: injection into active sessions.** After a config change the plugin walks every active agent and calls `agent.inject()` with a standard `UserMessage`:
|
|
161
176
|
|
|
162
177
|
```js
|
|
163
178
|
agent.inject(createUserMessage({
|
|
164
|
-
content: [{ type: 'text', text: prompt }],
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
sections: [{ name: 'soul:persona', text: prompt }]
|
|
170
|
-
}
|
|
179
|
+
content: [{ type: 'text', text: `[dsh-soul personalization updated]\n…\n${prompt}` }],
|
|
180
|
+
// Session format v4 requires producers to carry their own kind (the shared
|
|
181
|
+
// kind:'plugin' + plugin field is rejected, failing every turn before step);
|
|
182
|
+
// construction lives in lib/injection.mjs
|
|
183
|
+
source: { kind: 'plugin:dsh-soul', form: 'snapshot', sections: [{ name: 'soul:persona', text: prompt }] }
|
|
171
184
|
}))
|
|
172
185
|
```
|
|
173
186
|
|
|
174
|
-
`agent.inject()` places the latest
|
|
187
|
+
`agent.inject()` places the latest config into the agent's pending context so it takes effect on the next request; it does not trigger a new request and does not rewrite message history. It is also the visible carrier of "already updated": a `[dsh-soul personalization updated]` message shows up in the conversation.
|
|
188
|
+
|
|
189
|
+
> Why both are needed: **with channel 1 alone, changing the persona mid-conversation was measured not to take effect on the next turn** (channel 2 was removed on that assumption during 0.7.1 development, then rolled back verbatim). `npm run verify:host` and `npm run verify:e2e` pin each channel down in place; re-run them after every DSH upgrade.
|
|
190
|
+
|
|
191
|
+
**Diagnostics.** Both channels fail silently with the same symptom — "I changed the config and nothing happened" — so the plugin records delivery honestly: the delivery line at the end of `/soul show`, `GET /api/soul/status`, and the banner on the settings page (`configError` = the config **cannot be read**; `deliveryWarning` = it **cannot be delivered** to active sessions).
|
|
175
192
|
|
|
176
193
|
## License
|
|
177
194
|
|
|
178
|
-
MIT License
|
|
195
|
+
MIT License — see [LICENSE](LICENSE) for the full text.
|