lume-dsh-plugin 0.4.4 → 0.5.0
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/README.md +31 -9
- package/lib/host/compaction.js +41 -0
- package/lib/host/diag.js +25 -0
- package/lib/host/protocol.js +15 -0
- package/lib/host/reflection.js +1 -1
- package/lib/host/session-runtime.js +1 -0
- package/lib/host/thinking.js +71 -0
- package/lib/index.js +38 -55
- package/package.json +26 -13
package/README.md
CHANGED
|
@@ -2,15 +2,32 @@
|
|
|
2
2
|
|
|
3
3
|
# Lume(微光)
|
|
4
4
|
|
|
5
|
-
**DSH Desktop
|
|
5
|
+
**DSH Desktop 增强插件。给会话装上两样东西:靠谱的任务执行纪律,和一段真实的关系。**
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
- **人设系统** —— 塑造「以何种风格表达」:具名、具备长期记忆、可随对话演进的对话人格
|
|
7
|
+
### 能力一:任务执行纪律(自适应协议)
|
|
9
8
|
|
|
10
|
-
|
|
9
|
+
约束「如何正确完成任务」,始终生效、不依赖人设:
|
|
10
|
+
|
|
11
|
+
- **自适应协议分层**——闲聊走短版、任务走完整版、推理型模型走精简版,按请求类型与模型能力分流,不为闲聊支付完整工作协议的 token
|
|
12
|
+
- **意图路由**——问答 / 查找 / 讨论 / 诊断 / 执行五类先行分流:诊断不越权修复,讨论不提前收敛,只有执行才改动状态
|
|
13
|
+
- **证据时效**——引用日志、历史、旧报错前先核对时间戳与因果:历史里存在的错误不等于当前问题的原因
|
|
14
|
+
- **真实工具结果验证**——监听工具成败与结果未知;失败或未知不允许报完成,交付时区分「已验证 / 未验证 / 推测有效」
|
|
15
|
+
- **会话内自愈与复盘回环**——相同请求连续失败自动注入归因纠偏;跨会话聚合反思评分,对持续低分的维度定向提醒
|
|
16
|
+
- **上下文压缩感知**——压缩发生后重锚状态,提醒模型摘要不是完整历史,细节依赖先确认
|
|
17
|
+
|
|
18
|
+
### 能力二:人设系统(人设即人)
|
|
19
|
+
|
|
20
|
+
塑造「以何种风格表达」:具名角色、长期记忆、随对话演进:
|
|
21
|
+
|
|
22
|
+
- **聊天记录蒸馏**——从微信/QQ 导出记录蒸馏角色卡,语气、口头禅与回复篇幅锚定真实对话统计
|
|
23
|
+
- **长期记忆与生命周期**——事件记忆 + 故事记忆;相对时间的临时记忆自动过期,长期事实不受影响
|
|
24
|
+
- **双向反馈闭环**——负面反馈自动转成风格约定,被认可的回复摘录为语料,语气随使用收敛
|
|
25
|
+
- **记忆星图与角色卡导入导出**——可视化记忆、行内编辑,卡片可分享迁移
|
|
26
|
+
|
|
27
|
+
人设只影响自然语言表达,不介入任务执行,也不影响代码、命令与工具调用的结果。
|
|
11
28
|
|
|
12
29
|
[](https://github.com/cayan0x/Lume/actions/workflows/ci.yml)
|
|
13
|
-
[](./CHANGELOG.md)
|
|
14
31
|
[](./LICENSE)
|
|
15
32
|
|
|
16
33
|
*人设系统:内置角色卡、蒸馏与管理入口,以及记忆星图*
|
|
@@ -19,7 +36,7 @@
|
|
|
19
36
|
|
|
20
37
|
---
|
|
21
38
|
|
|
22
|
-
##
|
|
39
|
+
## 一、任务执行协议
|
|
23
40
|
|
|
24
41
|
这是可公开复用的工程工作协议,不是模型隐藏思维链。协议注入每个会话;无论选择哪个人设(包括「不使用人设」),都始终生效。
|
|
25
42
|
|
|
@@ -60,7 +77,7 @@
|
|
|
60
77
|
|
|
61
78
|
这三层共同形成“常规协议 → 检测问题 → 临时强化 → 成功解除 → 跨会话复盘”的闭环,在需要深度处理时增加约束,在简单问题上控制 Token 消耗。
|
|
62
79
|
|
|
63
|
-
###
|
|
80
|
+
### 优化清单
|
|
64
81
|
|
|
65
82
|
- [x] 问答、查找、讨论、诊断、执行五类请求路由
|
|
66
83
|
- [x] 诊断不越权修复,讨论不提前替用户拍板
|
|
@@ -71,12 +88,17 @@
|
|
|
71
88
|
- [x] 上一轮执行回复缺少验证证据时的后续复核提醒
|
|
72
89
|
- [x] 任务阶段状态机:回答 / 查找 / 讨论 / 归因 / 执行 / 验证 / 交付
|
|
73
90
|
- [x] 真实工具证据:区分工具成功、失败和结果未知,不把工具调用本身当作目标完成
|
|
91
|
+
- [x] 证据时效:引用日志/历史/旧报错前核对时间戳与因果,不用旧错误填空
|
|
74
92
|
- [x] 记忆生命周期:相对时间记忆标记为临时记忆,30 天后自动失效;旧记忆无感兼容
|
|
75
93
|
- [x] 反思日志跨会话反馈、旧字段迁移和模型感知协议
|
|
94
|
+
- [x] 上下文压缩感知:识别宿主压缩检查点,压缩后重锚状态并提醒“摘要不是完整历史”
|
|
76
95
|
- [x] 角色卡算法自动升级且保留记忆、风格和认可语料
|
|
77
|
-
- [ ] DSH 宿主级历史压缩:当前由 DSH 的 `dsh-compact` 宿主能力负责,插件依赖未开放直接调用接口,不能由 Lume 安全替代
|
|
78
96
|
|
|
79
|
-
|
|
97
|
+
### 为什么不接管宿主的历史压缩
|
|
98
|
+
|
|
99
|
+
压缩服务由 DSH 的 agent preset 在自己的隔离域里挂载(`isolate: { compaction: true }`),profile 层的插件注册的同名服务不会被 `/compact` 或自动压缩使用——**第三方插件在标准 preset 下无法替换压缩后端**,这属于宿主的架构边界,不是接口开放与否的问题。
|
|
100
|
+
|
|
101
|
+
Lume 因此选择「观察 + 重锚」:压缩发生时记录规模,在随后一轮注入提示,提醒模型摘要只保留要点、依赖早期细节时先确认;压缩产生的摘要消息带固定来源标记,Lume 用它把摘要与真实用户消息区分开,避免摘要污染当前目标与协议路由。人设契约、长期记忆与协议本身注入在 system prompt 段,不参与对话历史压缩,因此不受影响。
|
|
80
102
|
|
|
81
103
|
## 二、人设系统:「人设即人」
|
|
82
104
|
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 压缩感知:识别宿主的上下文压缩,并把它变成一次状态重锚。
|
|
3
|
+
*
|
|
4
|
+
* ## 为什么不做「接管压缩后端」
|
|
5
|
+
*
|
|
6
|
+
* 一度尝试继承 `dsh-compaction-basic` 用 Lume 的摘要模板替换宿主的 coding 模板,
|
|
7
|
+
* 结论是**在标准 preset 下做不到**:宿主的 standard/ptc preset 把压缩服务放在
|
|
8
|
+
* 自己的隔离域里——
|
|
9
|
+
*
|
|
10
|
+
* ```yaml
|
|
11
|
+
* - id: compaction
|
|
12
|
+
* name: cordis:group
|
|
13
|
+
* isolate:
|
|
14
|
+
* compaction: true
|
|
15
|
+
* config:
|
|
16
|
+
* - id: compaction-basic
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* profile 层注册的同名服务在另一个隔离域,`/compact` 与自动压缩都只会用它自己
|
|
20
|
+
* 域内的后端。第三方插件无法把自己的实现塞进 preset 的隔离域,也不该改写宿主
|
|
21
|
+
* 的 preset 资产。因此这里放弃接管,改为「观察 + 重锚」。
|
|
22
|
+
*
|
|
23
|
+
* ## 观察什么
|
|
24
|
+
*
|
|
25
|
+
* 压缩把较早对话替换成一条摘要 user/message,该消息带 backend-independent 标记
|
|
26
|
+
* `{kind:"plugin", plugin:"compact"}`。用标记而不是文案匹配,宿主改模板也不会失效。
|
|
27
|
+
* 同时必须把它与真实用户消息区分——否则摘要会被当成「用户当前说的话」,污染
|
|
28
|
+
* 协议路由所依赖的 lastQuery 与对话缓冲。
|
|
29
|
+
*
|
|
30
|
+
* 规模信息(替换了多少项、多少 tokens)来自 `compaction/summary` 会话事件;
|
|
31
|
+
* 事件缺失时退化为不带规模的提醒,功能不依赖它。
|
|
32
|
+
*/
|
|
33
|
+
/**
|
|
34
|
+
* 压缩检查点判定:宿主替换被压缩历史的摘要消息带
|
|
35
|
+
* `source = {kind:"plugin", plugin:"compact", compactionId, sourceCommandId?}`。
|
|
36
|
+
* 见 `@deepseek-ai/dsh-compaction` 的 `compactCheckpointSource`。
|
|
37
|
+
*/
|
|
38
|
+
export function isCompactionCheckpoint(data) {
|
|
39
|
+
const source = data?.source;
|
|
40
|
+
return source?.kind === "plugin" && source?.plugin === "compact";
|
|
41
|
+
}
|
package/lib/host/diag.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lume 诊断日志:写 `$DSH_HOME/lume-compaction.log`。
|
|
3
|
+
*
|
|
4
|
+
* 存在的理由:`ctx.logger` 的输出不落在 DSH Desktop 的 harness.log 里(实测为 0 行),
|
|
5
|
+
* 宿主 stderr 又会被桌面外壳缓冲——排查「静默功能」时两者都不可靠。压缩这类
|
|
6
|
+
* 自动触发、用户无感的行为需要一个稳定可见的通道:每次接管/摘要/压缩事件一行。
|
|
7
|
+
*
|
|
8
|
+
* 宿主未提供 DSH_HOME 时静默跳过;任何写失败都不影响功能。
|
|
9
|
+
*/
|
|
10
|
+
import { appendFileSync } from "node:fs";
|
|
11
|
+
import { join } from "node:path";
|
|
12
|
+
/** 诊断文件名(位于 DSH_HOME 下)。 */
|
|
13
|
+
export const LUME_LOG_FILE = "lume-compaction.log";
|
|
14
|
+
/** 追加一行诊断;失败静默。 */
|
|
15
|
+
export function appendLumeLog(message) {
|
|
16
|
+
try {
|
|
17
|
+
const home = process.env.DSH_HOME;
|
|
18
|
+
if (!home)
|
|
19
|
+
return;
|
|
20
|
+
appendFileSync(join(home, LUME_LOG_FILE), `${new Date().toISOString()} ${message}\n`, "utf8");
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
/* 诊断失败不阻断功能 */
|
|
24
|
+
}
|
|
25
|
+
}
|
package/lib/host/protocol.js
CHANGED
|
@@ -79,3 +79,18 @@ export function buildAlignmentCorrection(kind) {
|
|
|
79
79
|
? "〔即时对齐纠偏〕用户正在纠正上一轮理解。先用一句话复述你现在理解的目标和边界,若仍有歧义只问一个关键问题;不要沿用上一轮假设,也不要直接继续执行。"
|
|
80
80
|
: "〔即时对齐纠偏〕用户重复提出相近请求,说明上一轮可能没有解决真正目标。先检查上一轮回答是否答非所问或没有产生结果,再给出针对当前目标的回应;不要原样重复上一轮。";
|
|
81
81
|
}
|
|
82
|
+
/**
|
|
83
|
+
* 压缩后的状态重锚:宿主的 preset 在自己的隔离域里执行压缩,Lume 无法接管该
|
|
84
|
+
* 服务,但能观察到压缩事件。压缩把较早对话替换成一条摘要——摘要必然丢细节,
|
|
85
|
+
* 而模型很容易把摘要当成完整历史。这里提醒它在依赖旧细节时先确认。
|
|
86
|
+
*
|
|
87
|
+
* 只在压缩后一轮内注入:更久之后摘要已成为正常上下文的一部分。
|
|
88
|
+
*/
|
|
89
|
+
export function buildCompactionNotice(info, currentTurn) {
|
|
90
|
+
if (currentTurn - info.turnIndex > 1)
|
|
91
|
+
return null;
|
|
92
|
+
const scale = info.shadowedItems > 0
|
|
93
|
+
? `约 ${info.shadowedItems} 项历史${info.tokens > 0 ? `(~${info.tokens} tokens)` : ""}已被摘要替换`
|
|
94
|
+
: "较早的历史已被摘要替换";
|
|
95
|
+
return `〔上下文压缩提示〕上一轮发生的上下文压缩已生效:${scale}。摘要只保留要点,早期对话的具体细节(文件路径、数字、原始报错、当时确认过的结论)可能已经不在上下文里。如果当前任务或用户的话依赖这些细节中的任何一项,先回看或直接问,不要假设摘要包含全部信息,也不要凭印象补全。`;
|
|
96
|
+
}
|
package/lib/host/reflection.js
CHANGED
|
@@ -87,7 +87,7 @@ export const REFLECTION_SYSTEM = [
|
|
|
87
87
|
"",
|
|
88
88
|
"上下文管理:是否理解并保留目标、约束、状态、关键决策和已排除假设",
|
|
89
89
|
"计划与门控:是否拆解任务、先调研再执行,并按风险自适应投入",
|
|
90
|
-
"
|
|
90
|
+
"验证与失败处理:是否在变更后验证,失败时归因并更换方案;引用日志/历史/旧报错作为证据时是否核对时间戳与因果归属,有没有把历史错误当成本次问题的原因",
|
|
91
91
|
"结果复核:是否对照完成标准、边界条件、兼容性和数据保留进行复核",
|
|
92
92
|
"",
|
|
93
93
|
"只输出一个 JSON 对象,形如 {\"context\":2,\"planning\":2,\"verification\":1,\"review\":0,\"note\":\"...\"},note 一句话中文,不要输出其他内容。",
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 任务执行协议文本(Codex 风格)与分流判据。
|
|
3
|
+
*
|
|
4
|
+
* 从 index.ts 抽出:协议是行为约束的核心资产,独立成模块才能被测试直接锁定
|
|
5
|
+
* (此前埋在插件入口里,任何措辞回归都只能靠人眼发现)。
|
|
6
|
+
*
|
|
7
|
+
* 三套变体按「请求类型 × 模型能力」分流:
|
|
8
|
+
* - THINKING_TEXT 完整协议:任务型请求 + 未确认模型能力
|
|
9
|
+
* - THINKING_COMPACT_TEXT 短版协议:闲聊/问答轮,避免每轮重复支付完整协议
|
|
10
|
+
* - THINKING_REASONING_TEXT 精简协议:推理型模型的任务轮,省掉它天生具备的
|
|
11
|
+
* 计划/分解条款,只保留行为约束、证据纪律与事实边界
|
|
12
|
+
*/
|
|
13
|
+
/** Codex 风格任务执行协议:完整版。 */
|
|
14
|
+
export const THINKING_TEXT = `[任务执行协议]
|
|
15
|
+
|
|
16
|
+
你应遵循以下公开的工程工作协议。它约束任务如何被完成,不要求输出隐藏的逐步思考过程;对外只给出必要的结论、计划、变更和验证结果。
|
|
17
|
+
|
|
18
|
+
**身份分工**:人设只影响自然语言表达;本协议负责正确完成任务。代码、数学、工具调用、结构化输出和安全判断保持准确、朴素,不因人设而戏剧化。
|
|
19
|
+
|
|
20
|
+
**P0 上下文管理**:先确认用户真正要达成的结果、约束、涉及的文件/系统和完成标准。上下文变长时压缩为:目标、已完成事项、关键决策、当前状态、错误、已排除假设、下一步。不要反复提出已经解决或排除的问题。
|
|
21
|
+
|
|
22
|
+
**P1 阶段门控**:复杂任务按“理解 → 只读调研 → 简短计划 → 执行 → 验证 → 汇报”推进。调研和计划阶段不修改外部状态;未确认目标文件、接口和影响范围前,不直接动手。
|
|
23
|
+
|
|
24
|
+
**P1 任务分解**:把大任务拆成可验证的小步骤,优先处理阻塞项和高风险项。每一步都说明完成条件;能并行的只读检查并行进行,存在依赖的步骤按顺序执行。
|
|
25
|
+
|
|
26
|
+
**P1 自适应投入**:不要把“快速”当成固定目标。简单、低风险、目标明确且可直接验证的问题,直接给出答案或执行最小步骤;复杂、模糊、高风险、涉及数据迁移/外部状态或验证成本高的问题,主动增加上下文分析、方案比较、边界检查和验证轮次。只有在信息足够且风险可控时才快速收敛。
|
|
27
|
+
|
|
28
|
+
**P0 意图对齐**:先辨认这一轮是问答、查找、讨论、诊断还是执行。问答先回答;查找先核对事实;讨论先比较取舍;诊断先解释证据和根因,不越权修复;执行才修改状态。用户要结论时不要只汇报动作,用户要探讨时不要擅自锁定方案。
|
|
29
|
+
|
|
30
|
+
**P1 信息路由**:优先定位最可能影响结果的入口、数据流和约束,不平均浏览无关内容;无依赖的只读检查可以并行,依赖前置结果的操作必须等待确认。
|
|
31
|
+
|
|
32
|
+
**P2 变更纪律**:修改前完整读取相关文件,理解现有实现和用户已有改动;一次性完成同一文件的相关修改。保持改动最小、可回滚、与现有接口兼容,不重写无关代码,不覆盖用户数据。
|
|
33
|
+
|
|
34
|
+
**P2 验证闭环**:每次修改后立即运行与风险匹配的测试、类型检查、构建或最小复现。不要只看“命令成功”,还要确认输出确实满足目标。发现失败先归因:输入、逻辑、接口、环境或权限;修复后重新验证。
|
|
35
|
+
|
|
36
|
+
**P2 证据时效**:日志、历史记录、报错文本、旧结论都带时间。引用它们作为证据前先核对时间戳是否落在当前问题的时间窗口内,并确认因果关系——**历史里存在的错误不等于当前问题的原因**。日志里翻到一条报错就直接当成用户当前症状的解释,是最常见的误判。若无法确认时间归属,如实说明「这条是历史记录,与当前问题是否相关未确认」,再去找与当前时间窗对应的证据;找不到就说不确定,不要用旧错误填空。
|
|
37
|
+
|
|
38
|
+
**P2 达成标准**:完成动作不等于达成目标。交付前必须回答:用户要的结果是否已经出现?用户能否实际使用?是否引入了需要用户清理的中间文件、配置、会话或其他副作用?
|
|
39
|
+
|
|
40
|
+
**P2 振荡预防**:同一假设连续失败后停止重复尝试,记录失败原因并换方案。已排除的假设不再重提;不使用破坏性命令绕过问题;不把测试删掉或放宽断言来制造假成功。
|
|
41
|
+
|
|
42
|
+
**P3 结果复核**:完成前逐项对照用户要求、边界条件、错误路径、兼容性和数据保留。区分“已实现”“已验证”“推测有效”和“仍然缺失”,不把部分完成说成全部完成。
|
|
43
|
+
|
|
44
|
+
**工具与安全**:工具调用前判断是否只读、是否会写入或删除、目标是否精确、是否涉及隐私或外部通信。优先使用专用工具和最小权限;破坏性操作、敏感数据传输和不可逆变更必须先获得明确授权。
|
|
45
|
+
|
|
46
|
+
**代码任务**:先定位入口、数据流和测试,再修改;优先复用现有抽象;为新行为补回归测试;同时考虑旧数据迁移、失败回退和用户已有状态。最终汇报修改文件、验证结果、已知限制和用户需要采取的动作。
|
|
47
|
+
|
|
48
|
+
**对话任务**:先直接回答当前问题,再补充必要依据;简单问题保持简洁,复杂问题给出足够的推理依据、假设和验证边界。不编造已经执行的操作、工具结果、文件内容或当前状态。需要用户决定时只提出真正阻塞的问题。
|
|
49
|
+
|
|
50
|
+
**隐私与事实边界**:示例、历史消息和角色记忆用于相关性与表达参考,不自动等于当前事实。涉及时间、地点、当前行为和现实状态时,只依据当前上下文或可靠工具结果。
|
|
51
|
+
|
|
52
|
+
每次完成一个阶段后,检查:目标是否仍然一致?变更是否在授权范围内?验证是否覆盖了最可能的失败方式?`;
|
|
53
|
+
/** 普通闲聊用短版协议;任务型请求才注入完整版,避免每轮重复支付完整工作协议。 */
|
|
54
|
+
export const THINKING_COMPACT_TEXT = `[任务执行协议]
|
|
55
|
+
先区分问答、查找、讨论、诊断、执行:问答先答,查找先核对,讨论先比较,诊断先归因,执行才改动。复杂或高风险任务先理解目标和约束,再调研、计划、执行、验证、复核。修改前读取相关内容,修改后确认实际生效并检查副作用;失败先归因,不重复已排除方案。引用日志、历史记录或旧报错作为证据时,先核对时间戳是否落在当前问题的时间窗口内——历史错误不等于当前问题的原因,无法确认就明说。人设只影响表达,不影响事实、代码、工具调用和安全判断。历史示例只参考风格,不自动等于当前事实。`;
|
|
56
|
+
/** 任务型请求的判据:命中即注入完整协议(而非短版)。 */
|
|
57
|
+
export const TASK_SIGNAL_RE = /代码|编程|文件|项目|仓库|脚本|命令|调研|研究|分析|实现|修改|修复|构建|测试|部署|配置|安装|迁移|导入|导出|接口|API|数据库|批量|计划|方案|风险|审查|review|debug|bug|深度|复杂/i;
|
|
58
|
+
/** 推理型模型判据:命中即用精简协议(它天生会计划,重复条款只稀释注意力)。 */
|
|
59
|
+
export const REASONING_MODEL_RE = /deepseek-v[345]|reason|o[134]|gpt-5/i;
|
|
60
|
+
/** 推理型模型的任务协议:省掉它天生具备的计划/分解条款,保留行为约束与事实边界。 */
|
|
61
|
+
export const THINKING_REASONING_TEXT = `[任务执行协议]
|
|
62
|
+
已确认当前模型具备推理能力。仍须保护用户改动,修改后立即验证;失败先归因并更换方案,不重复已排除假设;完成前复核需求、边界和数据保留。引用日志、历史记录或旧报错作为证据时先核对时间戳与因果:历史错误不等于当前问题的原因,确认不了就明说。示例、历史消息和角色记忆只作表达与相关性参考,不自动等于当前事实。人设只影响表达,不影响代码、工具调用和安全判断。`;
|
|
63
|
+
/**
|
|
64
|
+
* 按「是否任务型 × 是否推理模型」选择协议变体。
|
|
65
|
+
* 路由未知(模型名缺失)时回退完整版,避免误判造成能力退化。
|
|
66
|
+
*/
|
|
67
|
+
export function selectThinkingProtocol(input) {
|
|
68
|
+
if (!input.isTask)
|
|
69
|
+
return THINKING_COMPACT_TEXT;
|
|
70
|
+
return input.isReasoningModel ? THINKING_REASONING_TEXT : THINKING_TEXT;
|
|
71
|
+
}
|
package/lib/index.js
CHANGED
|
@@ -31,54 +31,11 @@ import { detectLeak } from "./core/leak-detector.js";
|
|
|
31
31
|
import { messageText } from "./core/text.js";
|
|
32
32
|
import { composeBoundary } from "./host/boundary.js";
|
|
33
33
|
import { SessionRuntimeStore } from "./host/session-runtime.js";
|
|
34
|
+
import { isCompactionCheckpoint } from "./host/compaction.js";
|
|
34
35
|
import { LUME_REFLECTION_SPEC, ReflectionStore, buildReflectionPrompt, parseReflectionScore } from "./host/reflection.js";
|
|
35
|
-
import {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
你应遵循以下公开的工程工作协议。它约束任务如何被完成,不要求输出隐藏的逐步思考过程;对外只给出必要的结论、计划、变更和验证结果。
|
|
40
|
-
|
|
41
|
-
**身份分工**:人设只影响自然语言表达;本协议负责正确完成任务。代码、数学、工具调用、结构化输出和安全判断保持准确、朴素,不因人设而戏剧化。
|
|
42
|
-
|
|
43
|
-
**P0 上下文管理**:先确认用户真正要达成的结果、约束、涉及的文件/系统和完成标准。上下文变长时压缩为:目标、已完成事项、关键决策、当前状态、错误、已排除假设、下一步。不要反复提出已经解决或排除的问题。
|
|
44
|
-
|
|
45
|
-
**P1 阶段门控**:复杂任务按“理解 → 只读调研 → 简短计划 → 执行 → 验证 → 汇报”推进。调研和计划阶段不修改外部状态;未确认目标文件、接口和影响范围前,不直接动手。
|
|
46
|
-
|
|
47
|
-
**P1 任务分解**:把大任务拆成可验证的小步骤,优先处理阻塞项和高风险项。每一步都说明完成条件;能并行的只读检查并行进行,存在依赖的步骤按顺序执行。
|
|
48
|
-
|
|
49
|
-
**P1 自适应投入**:不要把“快速”当成固定目标。简单、低风险、目标明确且可直接验证的问题,直接给出答案或执行最小步骤;复杂、模糊、高风险、涉及数据迁移/外部状态或验证成本高的问题,主动增加上下文分析、方案比较、边界检查和验证轮次。只有在信息足够且风险可控时才快速收敛。
|
|
50
|
-
|
|
51
|
-
**P0 意图对齐**:先辨认这一轮是问答、查找、讨论、诊断还是执行。问答先回答;查找先核对事实;讨论先比较取舍;诊断先解释证据和根因,不越权修复;执行才修改状态。用户要结论时不要只汇报动作,用户要探讨时不要擅自锁定方案。
|
|
52
|
-
|
|
53
|
-
**P1 信息路由**:优先定位最可能影响结果的入口、数据流和约束,不平均浏览无关内容;无依赖的只读检查可以并行,依赖前置结果的操作必须等待确认。
|
|
54
|
-
|
|
55
|
-
**P2 变更纪律**:修改前完整读取相关文件,理解现有实现和用户已有改动;一次性完成同一文件的相关修改。保持改动最小、可回滚、与现有接口兼容,不重写无关代码,不覆盖用户数据。
|
|
56
|
-
|
|
57
|
-
**P2 验证闭环**:每次修改后立即运行与风险匹配的测试、类型检查、构建或最小复现。不要只看“命令成功”,还要确认输出确实满足目标。发现失败先归因:输入、逻辑、接口、环境或权限;修复后重新验证。
|
|
58
|
-
|
|
59
|
-
**P2 达成标准**:完成动作不等于达成目标。交付前必须回答:用户要的结果是否已经出现?用户能否实际使用?是否引入了需要用户清理的中间文件、配置、会话或其他副作用?
|
|
60
|
-
|
|
61
|
-
**P2 振荡预防**:同一假设连续失败后停止重复尝试,记录失败原因并换方案。已排除的假设不再重提;不使用破坏性命令绕过问题;不把测试删掉或放宽断言来制造假成功。
|
|
62
|
-
|
|
63
|
-
**P3 结果复核**:完成前逐项对照用户要求、边界条件、错误路径、兼容性和数据保留。区分“已实现”“已验证”“推测有效”和“仍然缺失”,不把部分完成说成全部完成。
|
|
64
|
-
|
|
65
|
-
**工具与安全**:工具调用前判断是否只读、是否会写入或删除、目标是否精确、是否涉及隐私或外部通信。优先使用专用工具和最小权限;破坏性操作、敏感数据传输和不可逆变更必须先获得明确授权。
|
|
66
|
-
|
|
67
|
-
**代码任务**:先定位入口、数据流和测试,再修改;优先复用现有抽象;为新行为补回归测试;同时考虑旧数据迁移、失败回退和用户已有状态。最终汇报修改文件、验证结果、已知限制和用户需要采取的动作。
|
|
68
|
-
|
|
69
|
-
**对话任务**:先直接回答当前问题,再补充必要依据;简单问题保持简洁,复杂问题给出足够的推理依据、假设和验证边界。不编造已经执行的操作、工具结果、文件内容或当前状态。需要用户决定时只提出真正阻塞的问题。
|
|
70
|
-
|
|
71
|
-
**隐私与事实边界**:示例、历史消息和角色记忆用于相关性与表达参考,不自动等于当前事实。涉及时间、地点、当前行为和现实状态时,只依据当前上下文或可靠工具结果。
|
|
72
|
-
|
|
73
|
-
每次完成一个阶段后,检查:目标是否仍然一致?变更是否在授权范围内?验证是否覆盖了最可能的失败方式?`;
|
|
74
|
-
/** 普通闲聊用短版协议;任务型请求才注入完整版,避免每轮重复支付完整工作协议。 */
|
|
75
|
-
const THINKING_COMPACT_TEXT = `[任务执行协议]
|
|
76
|
-
先区分问答、查找、讨论、诊断、执行:问答先答,查找先核对,讨论先比较,诊断先归因,执行才改动。复杂或高风险任务先理解目标和约束,再调研、计划、执行、验证、复核。修改前读取相关内容,修改后确认实际生效并检查副作用;失败先归因,不重复已排除方案。人设只影响表达,不影响事实、代码、工具调用和安全判断。历史示例只参考风格,不自动等于当前事实。`;
|
|
77
|
-
const TASK_SIGNAL_RE = /代码|编程|文件|项目|仓库|脚本|命令|调研|研究|分析|实现|修改|修复|构建|测试|部署|配置|安装|迁移|导入|导出|接口|API|数据库|批量|计划|方案|风险|审查|review|debug|bug|深度|复杂/i;
|
|
78
|
-
const REASONING_MODEL_RE = /deepseek-v[345]|reason|o[134]|gpt-5/i;
|
|
79
|
-
/** 推理型模型的任务协议:省掉它天生具备的计划/分解条款,保留行为约束与事实边界。 */
|
|
80
|
-
const THINKING_REASONING_TEXT = `[任务执行协议]
|
|
81
|
-
已确认当前模型具备推理能力。仍须保护用户改动,修改后立即验证;失败先归因并更换方案,不重复已排除假设;完成前复核需求、边界和数据保留。示例、历史消息和角色记忆只作表达与相关性参考,不自动等于当前事实。人设只影响表达,不影响代码、工具调用和安全判断。`;
|
|
36
|
+
import { appendLumeLog } from "./host/diag.js";
|
|
37
|
+
import { buildAlignmentCorrection, buildCompactionNotice, buildInteractionDirective, buildLongSessionGuard, buildSessionAnchor, buildTaskPhaseDirective, buildToolEvidenceDirective, classifyInteraction, taskPhaseForMode } from "./host/protocol.js";
|
|
38
|
+
import { REASONING_MODEL_RE, TASK_SIGNAL_RE, selectThinkingProtocol } from "./host/thinking.js";
|
|
82
39
|
/** schemastery → domainTable 形参的桥接(与 identity.ts 同款)。 */
|
|
83
40
|
const recordSchema = zodLike;
|
|
84
41
|
/** 会话人设选择的持久层(键 = sessionId)。 */
|
|
@@ -466,6 +423,17 @@ export function apply(ctx, config = {}) {
|
|
|
466
423
|
break;
|
|
467
424
|
}
|
|
468
425
|
case "user/message": {
|
|
426
|
+
// 压缩检查点:宿主把被压缩的历史替换成一条摘要消息,必须与真实
|
|
427
|
+
// 用户消息区分——否则摘要会被当成「用户当前说的话」,污染协议
|
|
428
|
+
// 路由所依赖的 lastQuery 与对话缓冲。这是兜底识别:同一轮里
|
|
429
|
+
// compaction/summary 通常先到且带规模,不要把那条覆盖成无规模的。
|
|
430
|
+
if (isCompactionCheckpoint(event.data)) {
|
|
431
|
+
if (!st.compaction || st.compaction.turnIndex !== st.turnIndex) {
|
|
432
|
+
st.compaction = { turnIndex: st.turnIndex, shadowedItems: 0, tokens: 0 };
|
|
433
|
+
}
|
|
434
|
+
appendLumeLog(`[${sid}] 检测到上下文压缩检查点(第 ${st.turnIndex} 轮)`);
|
|
435
|
+
break;
|
|
436
|
+
}
|
|
469
437
|
const text = messageText(event.data);
|
|
470
438
|
if (text) {
|
|
471
439
|
const normalized = text.trim().replace(/\s+/g, " ").slice(0, 240);
|
|
@@ -524,6 +492,16 @@ export function apply(ctx, config = {}) {
|
|
|
524
492
|
st.taskPhase = unknownResult || explicitError ? "diagnose" : "verify";
|
|
525
493
|
break;
|
|
526
494
|
}
|
|
495
|
+
case "compaction/summary": {
|
|
496
|
+
// 压缩由宿主 preset 在隔离域执行(Lume 无法接管该服务),但事件在
|
|
497
|
+
// 会话总线上可见。记录规模,供下一轮注入「摘要不是完整历史」的重锚。
|
|
498
|
+
const data = event.data;
|
|
499
|
+
const shadowedItems = Array.isArray(data?.shadowedSeqs) ? data.shadowedSeqs.length : 0;
|
|
500
|
+
const tokens = typeof data?.shadowedTokenCount === "number" ? data.shadowedTokenCount : 0;
|
|
501
|
+
st.compaction = { turnIndex: st.turnIndex, shadowedItems, tokens };
|
|
502
|
+
appendLumeLog(`[${sid}] 压缩完成:替换 ${shadowedItems} 项历史(~${tokens} tokens),下一轮注入状态重锚`);
|
|
503
|
+
break;
|
|
504
|
+
}
|
|
527
505
|
case "turn/end": {
|
|
528
506
|
st.turnIndex++;
|
|
529
507
|
// 低成本会话内纠偏:只处理明确的错误/失败信号,且要求连续轮次用户请求相同。
|
|
@@ -569,6 +547,11 @@ export function apply(ctx, config = {}) {
|
|
|
569
547
|
break;
|
|
570
548
|
}
|
|
571
549
|
default:
|
|
550
|
+
// 诊断:压缩事件是否经由 session/event 总线投递(宿主按 session
|
|
551
|
+
// 所属上下文收集监听者,隔离域里发出的日志事件可能不经过这里)。
|
|
552
|
+
if (typeof event.type === "string" && /compact/i.test(event.type)) {
|
|
553
|
+
appendLumeLog(`[${sid}] 收到未处理的压缩事件类型 ${event.type}`);
|
|
554
|
+
}
|
|
572
555
|
break;
|
|
573
556
|
}
|
|
574
557
|
}), "lume: session events");
|
|
@@ -769,15 +752,12 @@ export function apply(ctx, config = {}) {
|
|
|
769
752
|
const sid = context.agent?.session?.id ?? context.agent?.id;
|
|
770
753
|
const st = sid ? runtime.get(String(sid)) : null;
|
|
771
754
|
const query = st?.lastQuery ?? "";
|
|
772
|
-
const task = TASK_SIGNAL_RE.test(query);
|
|
773
755
|
// 已知推理型模型具备计划能力,任务轮只保留变更、验证、归因和复核约束;
|
|
774
756
|
// 路由未知时使用完整版,避免误判造成能力退化。
|
|
775
|
-
const
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
? THINKING_REASONING_TEXT
|
|
780
|
-
: THINKING_TEXT;
|
|
757
|
+
const base = selectThinkingProtocol({
|
|
758
|
+
isTask: TASK_SIGNAL_RE.test(query),
|
|
759
|
+
isReasoningModel: typeof llmRoute?.model === "string" && REASONING_MODEL_RE.test(llmRoute.model),
|
|
760
|
+
});
|
|
781
761
|
// 纠偏与反思提醒属于任务协议,跟人设无关——挂在 thinking 段
|
|
782
762
|
// 才能在「不使用人设」的纯任务会话里也生效。
|
|
783
763
|
const correction = st?.protocolCorrection;
|
|
@@ -789,7 +769,10 @@ export function apply(ctx, config = {}) {
|
|
|
789
769
|
const postTurnReview = st?.postTurnReview;
|
|
790
770
|
const phase = buildTaskPhaseDirective(st?.taskPhase ?? "answer");
|
|
791
771
|
const toolEvidence = st ? buildToolEvidenceDirective({ calls: st.toolCalls, successes: st.toolSuccesses, failures: st.toolFailures, unknown: st.toolUnknown }) : null;
|
|
792
|
-
|
|
772
|
+
// 压缩重锚:宿主的 preset 隔离域负责压缩,Lume 只能观察事件;
|
|
773
|
+
// 在压缩后一轮提醒「摘要不是完整历史」。
|
|
774
|
+
const compactionNotice = st?.compaction ? buildCompactionNotice(st.compaction, st.turnIndex) : null;
|
|
775
|
+
return [base, route, phase, longSession, anchor, alignment, postTurnReview, toolEvidence, compactionNotice, correction, reflectionHint].filter(Boolean).join("\n\n");
|
|
793
776
|
},
|
|
794
777
|
}), "lume.thinking-section()");
|
|
795
778
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lume-dsh-plugin",
|
|
3
3
|
"description": "微光 (Lume) — DSH Desktop 增强插件:Codex 风格自适应任务执行协议 + 人设系统(聊天记录蒸馏具名角色、长期记忆、风格纠偏自动捕获)",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.5.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
7
7
|
"exports": {
|
|
@@ -51,17 +51,10 @@
|
|
|
51
51
|
},
|
|
52
52
|
"peerDependencies": {
|
|
53
53
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
54
|
-
"@deepseek-ai/dsh-client-
|
|
55
|
-
"@deepseek-ai/dsh-
|
|
56
|
-
"@deepseek-ai/dsh-
|
|
57
|
-
"@deepseek-ai/dsh-
|
|
58
|
-
"@deepseek-ai/dsh-client-ui-primitives": "^0.1.1-rc.2",
|
|
59
|
-
"@deepseek-ai/dsh-invariants": "^0.1.1-rc.2",
|
|
60
|
-
"@deepseek-ai/dsh-llm": "^0.0.1-rc.1",
|
|
61
|
-
"@deepseek-ai/dsh-storage-domain": "^0.0.1-rc.1",
|
|
62
|
-
"@deepseek-ai/dsh-system-prompt": "^0.1.1-rc.2",
|
|
63
|
-
"@deepseek-ai/dsh-tools": "^0.0.1-rc.1",
|
|
64
|
-
"@deepseek-ai/dsh-typert-protocol": "^0.1.1-rc.2",
|
|
54
|
+
"@deepseek-ai/dsh-client-ui-primitives": "*",
|
|
55
|
+
"@deepseek-ai/dsh-llm": "*",
|
|
56
|
+
"@deepseek-ai/dsh-storage-domain": "*",
|
|
57
|
+
"@deepseek-ai/dsh-tools": "*",
|
|
65
58
|
"@deepseek-ai/schemastery": "^3.18.1"
|
|
66
59
|
},
|
|
67
60
|
"scripts": {
|
|
@@ -95,5 +88,25 @@
|
|
|
95
88
|
"assets/personalities.json",
|
|
96
89
|
"assets/personalities/*.txt",
|
|
97
90
|
"assets/personalities/*.jsonl"
|
|
98
|
-
]
|
|
91
|
+
],
|
|
92
|
+
"peerDependenciesMeta": {
|
|
93
|
+
"@deepseek-ai/cordis": {
|
|
94
|
+
"optional": true
|
|
95
|
+
},
|
|
96
|
+
"@deepseek-ai/dsh-client-ui-primitives": {
|
|
97
|
+
"optional": true
|
|
98
|
+
},
|
|
99
|
+
"@deepseek-ai/dsh-llm": {
|
|
100
|
+
"optional": true
|
|
101
|
+
},
|
|
102
|
+
"@deepseek-ai/dsh-storage-domain": {
|
|
103
|
+
"optional": true
|
|
104
|
+
},
|
|
105
|
+
"@deepseek-ai/dsh-tools": {
|
|
106
|
+
"optional": true
|
|
107
|
+
},
|
|
108
|
+
"@deepseek-ai/schemastery": {
|
|
109
|
+
"optional": true
|
|
110
|
+
}
|
|
111
|
+
}
|
|
99
112
|
}
|