@y9931666/dsh-plugin-crossfire 0.1.5 → 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/LICENSE +21 -0
- package/README.md +10 -7
- package/lib/index.js +643 -52
- package/lib/types/engine.d.ts +22 -4
- package/lib/types/plan.d.ts +111 -0
- package/lib/types/prompt.d.ts +1 -1
- package/lib/types/redteam.d.ts +12 -4
- package/lib/types/tools.d.ts +2 -1
- package/lib/types/types.d.ts +28 -0
- package/lib/types/version.d.ts +3 -3
- package/package.json +40 -37
- package/release-notes/v0.2.0.md +44 -0
package/lib/types/engine.d.ts
CHANGED
|
@@ -37,10 +37,26 @@ export interface ExpertRosterEntry {
|
|
|
37
37
|
* 匹配不到时退回**顺序**兜底(见 {@link planExperts}),两种写法都能用。
|
|
38
38
|
*/
|
|
39
39
|
key: string;
|
|
40
|
+
/**
|
|
41
|
+
* 这位专家负责的维度(可选;**有它时优先于 `key` 匹配**)。
|
|
42
|
+
*
|
|
43
|
+
* 为什么需要它:启动前确认卡是按维度逐行列出的,用户在卡上改的是"安全这一行",
|
|
44
|
+
* 而不是"key 恰好叫安全的那位专家"。只在 `key` 上做匹配意味着用户给专家换个
|
|
45
|
+
* 名字(`crypto-auditor`)之后,这行配置就悄悄对不上了 —— 于是退到顺序兜底,
|
|
46
|
+
* 看起来还能跑,实际配错了人。显式带维度就没有这层歧义。
|
|
47
|
+
*/
|
|
48
|
+
dimension?: string;
|
|
40
49
|
/** 用户补充的角色定位(进 persona 的「你的角色定位」段)。 */
|
|
41
50
|
role?: string;
|
|
42
51
|
provider?: string;
|
|
43
52
|
model?: string;
|
|
53
|
+
/**
|
|
54
|
+
* 用户补充的提示词(进 persona 的「评审者补充提示词」段)。
|
|
55
|
+
*
|
|
56
|
+
* 与 {@link role} 同一条边界:只收窄专长,不放宽只读/不产出方案/不迎合;
|
|
57
|
+
* 缺席时 persona 与从前逐字一致。
|
|
58
|
+
*/
|
|
59
|
+
prompt?: string;
|
|
44
60
|
/**
|
|
45
61
|
* 预设名(只有角色预设带它)。
|
|
46
62
|
*
|
|
@@ -57,11 +73,13 @@ export interface ExpertRosterEntry {
|
|
|
57
73
|
* `record.dimensions` 的顺序截断,所以**用户排在前面的维度优先** —— 这是可预期的,
|
|
58
74
|
* 而不是随机丢人。
|
|
59
75
|
*
|
|
60
|
-
*
|
|
61
|
-
* 1. `roster` 里 `
|
|
62
|
-
*
|
|
76
|
+
* 人选来源三条,按优先级:
|
|
77
|
+
* 1. `roster` 里 `dimension` 等于该维度的那一条(确认卡落盘的阵容就是这种形状:
|
|
78
|
+
* 用户确认的是"安全这一行",而不是某个恰好叫安全的 key);
|
|
79
|
+
* 2. 否则 `key` 等于维度名的那一条(精确指定,最符合直觉);
|
|
80
|
+
* 3. 否则按**顺序**取 roster 的第 i 条(i = 维度序号)—— 用户不必把 key 改名成
|
|
63
81
|
* 维度名也能用上一份现成的阵容;
|
|
64
|
-
*
|
|
82
|
+
* 4. 都取不到时只写维度与状态(专家继承主持人路由、无补充定位),与从前完全一致。
|
|
65
83
|
*
|
|
66
84
|
* @param roster - 可选人选来源;缺席或为空时行为与从前逐字一致。
|
|
67
85
|
*/
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 评审启动前的设置确认卡(R1):草案数据结构 + 卡片 Markdown 渲染 + 答案解析。
|
|
3
|
+
*
|
|
4
|
+
* ## 为什么要有这张卡
|
|
5
|
+
*
|
|
6
|
+
* 用户点「确定开始」之前就得**看全**将要发生什么:评审标题、来源、强度档
|
|
7
|
+
* (每维几位专家、复审上限、轮数、Token)、维度、立场,以及每一位红队专家的
|
|
8
|
+
* 维度 / key / 模型 / 角色 / 提示词。它把"即将开评"从一句"我开始了"变成一份
|
|
9
|
+
* 可核对的清单 —— 用户在点按钮之前就能发现"专家怎么跑到另一个模型上了"。
|
|
10
|
+
*
|
|
11
|
+
* ## 为什么是两张表而不是一行行文字
|
|
12
|
+
*
|
|
13
|
+
* 同一份信息用表格摊开时,用户能**按列横着比**(例如逐个看模型或提示词),
|
|
14
|
+
* 而条目式文本只能竖着读。针锋最容易配错的恰恰是"某一位专家的某一列"。
|
|
15
|
+
*
|
|
16
|
+
* ## 为什么这里不落盘、不拉专家
|
|
17
|
+
*
|
|
18
|
+
* 这个模块只做渲染与解析。真正的创建仍由主持人调用 `crossfire_open` 完成
|
|
19
|
+
* (与圆桌 `plan.ts` 的分工一致):确认工具一旦顺手建记录,用户改一次草案就会
|
|
20
|
+
* 在磁盘上留下一条没人用的空记录,"确认前不产生任何状态"这条不变量就没了。
|
|
21
|
+
*
|
|
22
|
+
* @module dsh-plugin-crossfire/plan
|
|
23
|
+
*/
|
|
24
|
+
import { type Intensity } from './types.ts';
|
|
25
|
+
/** 卡片上"批准"选项的固定标签;`intent.approve` 必须与它逐字一致。 */
|
|
26
|
+
export declare const PLAN_APPROVE_LABEL = "\u786E\u5B9A\u5F00\u59CB";
|
|
27
|
+
/** 卡片上的次选项:用户想改点什么。 */
|
|
28
|
+
export declare const PLAN_REVISE_LABEL = "\u4ECD\u9700\u4FEE\u6539";
|
|
29
|
+
/** 表 2 里的一位专家(= 本次评审将拉起的那一行)。 */
|
|
30
|
+
export interface DraftExpert {
|
|
31
|
+
/** 专家 key(缺省就是维度名;用户想换一个称呼时才会不同)。 */
|
|
32
|
+
key: string;
|
|
33
|
+
/** 负责的维度。 */
|
|
34
|
+
dimension: string;
|
|
35
|
+
/** 用户补充的角色定位。 */
|
|
36
|
+
role?: string;
|
|
37
|
+
provider?: string;
|
|
38
|
+
model?: string;
|
|
39
|
+
/** 用户补充的提示词(进 persona 的「评审者补充提示词」段)。 */
|
|
40
|
+
prompt?: string;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* 一张确认卡所描述的评审草案(尚未创建)。
|
|
44
|
+
*
|
|
45
|
+
* 字段与 `crossfire_open` 的入参一一对应,外加 `changes` / `revised`,这样用户
|
|
46
|
+
* 确认后主持人可以**原样**按草案调用 `crossfire_open`,不再自行拍参数。
|
|
47
|
+
*/
|
|
48
|
+
export interface ReviewDraft {
|
|
49
|
+
/** 一句话标题(卡片抬头 + 导出标题)。 */
|
|
50
|
+
title: string;
|
|
51
|
+
/** 待验证正文。 */
|
|
52
|
+
content: string;
|
|
53
|
+
/** 来源。 */
|
|
54
|
+
source: 'manual' | 'chat' | 'file';
|
|
55
|
+
/** 来源引用(文件路径或对话锚点)。 */
|
|
56
|
+
sourceRef?: string;
|
|
57
|
+
/** 本次采用的维度(已归一化)。 */
|
|
58
|
+
dimensions: string[];
|
|
59
|
+
/** 强度档。 */
|
|
60
|
+
intensity: Intensity;
|
|
61
|
+
/** 用户的立场与理由(可空)。 */
|
|
62
|
+
stance: string;
|
|
63
|
+
/** 红队阵容(已按维度展开;用户改过的行以这里为准)。 */
|
|
64
|
+
experts: DraftExpert[];
|
|
65
|
+
/** 轮数上限(超限闭麦)。 */
|
|
66
|
+
maxRounds: number;
|
|
67
|
+
/** Token 预算(超限闭麦)。 */
|
|
68
|
+
maxTokens: number;
|
|
69
|
+
/** 主持人总结的本次变更点(`revised` 时显示在卡片顶部)。 */
|
|
70
|
+
changes: string[];
|
|
71
|
+
/** 本次是"用户要求修改后"的再次确认。 */
|
|
72
|
+
revised: boolean;
|
|
73
|
+
}
|
|
74
|
+
/** 卡片选项的三态解析结果。 */
|
|
75
|
+
export type PlanConfirmation = {
|
|
76
|
+
kind: 'approved';
|
|
77
|
+
} | {
|
|
78
|
+
kind: 'revise';
|
|
79
|
+
note: string;
|
|
80
|
+
}
|
|
81
|
+
/** 服务缺失或用户没给任何选择:主持人应把它当作"再确认一次"。 */
|
|
82
|
+
| {
|
|
83
|
+
kind: 'unavailable';
|
|
84
|
+
note: string;
|
|
85
|
+
};
|
|
86
|
+
/** 待验证正文在卡片上最多显示的字数(超出截断,完整正文随评审落盘)。 */
|
|
87
|
+
export declare const SUBJECT_PREVIEW_MAX = 1200;
|
|
88
|
+
/** 提示词摘要的最大字数(表 2 的「提示词」列)。 */
|
|
89
|
+
export declare const PROMPT_SUMMARY_MAX = 40;
|
|
90
|
+
/**
|
|
91
|
+
* 把一份草案渲染成卡片正文(Markdown,放 `AskUserQuestionItem.detail`)。
|
|
92
|
+
*
|
|
93
|
+
* 结构固定为:抬头 →(revised 时)本次变更 → 表 1 评审设置 → 表 2 红队阵容 →
|
|
94
|
+
* 待验证正文 → 立场全文 → 修改说明。**顺序有意义**:先给"怎么评",再给"评什么",
|
|
95
|
+
* 最后才是"怎么改这张卡"。
|
|
96
|
+
*/
|
|
97
|
+
export declare function formatReviewDraft(draft: ReviewDraft): string;
|
|
98
|
+
/**
|
|
99
|
+
* 解析用户的卡片回答。
|
|
100
|
+
*
|
|
101
|
+
* 协议与 `intent.kind: 'plan-review'` 的语义一致:`selected` 含
|
|
102
|
+
* `PLAN_APPROVE_LABEL` 即视为批准,其余选项(或只有 custom 文本)视为要求修改。
|
|
103
|
+
* 不识别 intent 的 UI 会退回普通选项列表,答复编码完全相同。
|
|
104
|
+
*
|
|
105
|
+
* 纯空白 custom 不算"要求修改"(那只是用户点错了),统一归 unavailable ——
|
|
106
|
+
* 主持人会改用文字再确认一次,而不是拿一句空话去改草案。
|
|
107
|
+
*/
|
|
108
|
+
export declare function resolvePlanConfirmation(answer: {
|
|
109
|
+
selected: string[];
|
|
110
|
+
custom?: string;
|
|
111
|
+
} | undefined, approveLabel?: string): PlanConfirmation;
|
package/lib/types/prompt.d.ts
CHANGED
package/lib/types/redteam.d.ts
CHANGED
|
@@ -33,10 +33,10 @@ export declare const EXPERT_TOOL_ALLOW: readonly string[];
|
|
|
33
33
|
/**
|
|
34
34
|
* 红队专家禁止使用的工具(黑名单)。
|
|
35
35
|
*
|
|
36
|
-
* 这里列的是全部**主持人专属**的 `crossfire_*`
|
|
37
|
-
*
|
|
38
|
-
* `crossfire_collect`/`crossfire_finish
|
|
39
|
-
* 当场失效。
|
|
36
|
+
* 这里列的是全部**主持人专属**的 `crossfire_*` 工具:启动前确认、开评审、发起
|
|
37
|
+
* 攻击、收集缺陷、定稿、复审、导出、写入立场。这些都是主持人的编排权,专家一旦
|
|
38
|
+
* 能调 `crossfire_plan_review`/`crossfire_collect`/`crossfire_finish`,就等于自己
|
|
39
|
+
* 给自己结案,"表态由人做"当场失效。
|
|
40
40
|
*
|
|
41
41
|
* 为什么白名单之外还要再来一份黑名单:两者是**与**关系(必须同时在白名单里
|
|
42
42
|
* 且不在黑名单里才可见)。将来有人为了加一个只读工具而改动
|
|
@@ -86,6 +86,14 @@ export interface ExpertPersonaInput {
|
|
|
86
86
|
* 用户写一句"你可以修改文件",白名单就不再是最后一道闸。
|
|
87
87
|
*/
|
|
88
88
|
role?: string;
|
|
89
|
+
/**
|
|
90
|
+
* 用户在启动前确认卡里为这位专家写的**补充提示词**(可空)。
|
|
91
|
+
*
|
|
92
|
+
* 它和 {@link role} 进 persona 的同一类段落(「评审者补充提示词」),带着同一套
|
|
93
|
+
* 不可覆盖声明:只能收窄专长,不能放宽只读、不能让它产出方案、不能让它迎合用户。
|
|
94
|
+
* 空/纯空白时 persona 与从前**逐字**相同。
|
|
95
|
+
*/
|
|
96
|
+
prompt?: string;
|
|
89
97
|
}
|
|
90
98
|
/**
|
|
91
99
|
* 报告信封的格式说明(persona 与 welcome 共用同一份文本)。
|
package/lib/types/tools.d.ts
CHANGED
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
*
|
|
6
6
|
* 圆桌是"主持人统筹":模型负责建会、拉人、转述、聚合、推进每一轮。crossfire 不
|
|
7
7
|
* 需要这些 —— 卡片上的按钮经 RPC 直接驱动 host 状态机(O1 决策)。所以这里的工具
|
|
8
|
-
*
|
|
8
|
+
* 面刻意小:**预检一步 + 状态机七步、每步一件事、每步可单独重试**,模型只在
|
|
9
|
+
* "推不动了"的时候介入。
|
|
9
10
|
*
|
|
10
11
|
* 状态机(见 review.ts):
|
|
11
12
|
* draft --open--> attacking --attack--> judging --collect--> settled --finish-->
|
package/lib/types/types.d.ts
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
*
|
|
9
9
|
* @module dsh-plugin-crossfire/types
|
|
10
10
|
*/
|
|
11
|
+
import type { ExpertRosterEntry } from './engine.ts';
|
|
11
12
|
/**
|
|
12
13
|
* 固定维度池。
|
|
13
14
|
*
|
|
@@ -145,6 +146,17 @@ export interface RedTeamExpert {
|
|
|
145
146
|
* 2. 缺席时 persona 与从前逐字一致(老记录不受影响)。
|
|
146
147
|
*/
|
|
147
148
|
role?: string;
|
|
149
|
+
/**
|
|
150
|
+
* 这位专家的**补充提示词**(来自启动前确认卡的自由文本,可空)。
|
|
151
|
+
*
|
|
152
|
+
* 与 {@link role} 是两条不同的来源、同一个落点:role 是"角色预设/阵容成员"里的
|
|
153
|
+
* 短定位,prompt 是用户在确认卡里对这位专家写的完整补充说明。两者都只进 persona
|
|
154
|
+
* 的补充段,都**不能**放宽硬约束(见 `redteam.ts` 的不可覆盖声明)。
|
|
155
|
+
*
|
|
156
|
+
* 缺席时 persona 与从前逐字一致;同样必须登记进 `review.ts` 的 `sanitizeExpert()`
|
|
157
|
+
* 白名单,否则会"写进 JSON 却读不回来"。
|
|
158
|
+
*/
|
|
159
|
+
prompt?: string;
|
|
148
160
|
/**
|
|
149
161
|
* 这位专家**真正下发出去的那份 persona 的逐字副本**。
|
|
150
162
|
*
|
|
@@ -228,6 +240,22 @@ export interface CrossfireRecord {
|
|
|
228
240
|
dimensions: Dimension[];
|
|
229
241
|
intensity: Intensity;
|
|
230
242
|
experts: RedTeamExpert[];
|
|
243
|
+
/**
|
|
244
|
+
* 启动前确认卡(`crossfire_plan_review` → `crossfire_open`)里逐行确认过的阵容。
|
|
245
|
+
*
|
|
246
|
+
* 它与 {@link experts} 是两个阶段的东西,刻意分开存:
|
|
247
|
+
* - `expertRoster` 是**用户确认过的配置**(每维一位、模型/角色/提示词都可能被
|
|
248
|
+
* 用户改过),主持人在 `crossfire_open` 时原样落盘;
|
|
249
|
+
* - `experts` 是**实际拉起的那一批**(带 childId / status / persona),由
|
|
250
|
+
* `crossfire_attack` 生成。
|
|
251
|
+
*
|
|
252
|
+
* 分开的理由:`experts` 在复审轮开轮时会被清空(`crossfire_recheck` 置 `[]`),
|
|
253
|
+
* 而确认过的阵容必须活过整场评审 —— 否则复审轮会悄悄退回设置页的默认阵容,
|
|
254
|
+
* 用户确认过的东西就丢了。
|
|
255
|
+
*
|
|
256
|
+
* 缺席 = 没有走确认卡 / 没指定阵容,行为与从前逐字一致(按设置页阵容或纯继承)。
|
|
257
|
+
*/
|
|
258
|
+
expertRoster?: ExpertRosterEntry[];
|
|
231
259
|
defects: Defect[];
|
|
232
260
|
/** 当前第几轮(首轮 = 1)。 */
|
|
233
261
|
reviewPass: number;
|
package/lib/types/version.d.ts
CHANGED
|
@@ -9,10 +9,10 @@
|
|
|
9
9
|
* @module dsh-plugin-crossfire/version
|
|
10
10
|
*/
|
|
11
11
|
/** 当前插件版本(必须与 package.json 的 version 逐字一致)。 */
|
|
12
|
-
export declare const PLUGIN_VERSION = "0.1
|
|
12
|
+
export declare const PLUGIN_VERSION = "0.2.1";
|
|
13
13
|
/** 导出物头部使用的插件标识行。 */
|
|
14
|
-
export declare const PLUGIN_ID = "@y9931666/dsh-plugin-crossfire v0.1
|
|
14
|
+
export declare const PLUGIN_ID = "@y9931666/dsh-plugin-crossfire v0.2.1";
|
|
15
15
|
/** DeepSeek Harness 版本区间(导出头部展示用)。
|
|
16
16
|
* 必须与 `compatibility.json` 的 `recommendedHost` 一致 —— 由
|
|
17
17
|
* `test/version.test.mjs` 强制。 */
|
|
18
|
-
export declare const HARNESS_RANGE = "DeepSeek Harness 0.2.
|
|
18
|
+
export declare const HARNESS_RANGE = "DeepSeek Harness 0.2.2-rc.1+";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@y9931666/dsh-plugin-crossfire",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public",
|
|
6
6
|
"registry": "https://registry.npmjs.org/"
|
|
@@ -64,33 +64,36 @@
|
|
|
64
64
|
}
|
|
65
65
|
},
|
|
66
66
|
"crossfire": {
|
|
67
|
-
"hostBaseline": "0.2.
|
|
67
|
+
"hostBaseline": "0.2.2-rc.1"
|
|
68
68
|
},
|
|
69
69
|
"scripts": {
|
|
70
70
|
"typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.client.json --noEmit",
|
|
71
71
|
"test": "node --test --test-isolation=none \"test/*.test.mjs\"",
|
|
72
72
|
"test:inline": "node --test --test-isolation=none \"test/*.test.mjs\"",
|
|
73
73
|
"build": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.client.json --noEmit && tsdown -c tsdown.config.ts && tsc -p tsconfig.json --emitDeclarationOnly && tsc -p tsconfig.client.json --emitDeclarationOnly",
|
|
74
|
-
"bundle:client": "tsdown -c tsdown.config.ts"
|
|
74
|
+
"bundle:client": "tsdown -c tsdown.config.ts",
|
|
75
|
+
"compatibility": "node scripts/compatibility.mjs",
|
|
76
|
+
"verify:package": "node scripts/verify-package.mjs",
|
|
77
|
+
"publish:guard": "node scripts/compatibility.mjs && node scripts/verify-package.mjs --strict"
|
|
75
78
|
},
|
|
76
79
|
"peerDependencies": {
|
|
77
|
-
"@deepseek-ai/cordis": "^4.0
|
|
78
|
-
"@deepseek-ai/schemastery": "^3.
|
|
79
|
-
"@deepseek-ai/dsh-agent": "^0.2.
|
|
80
|
-
"@deepseek-ai/dsh-atomic-write": "^0.2.
|
|
81
|
-
"@deepseek-ai/dsh-client-connection": "^0.2.
|
|
82
|
-
"@deepseek-ai/dsh-client-locale": "^0.2.
|
|
83
|
-
"@deepseek-ai/dsh-client-ui-conversation": "^0.2.
|
|
84
|
-
"@deepseek-ai/dsh-client-ui-renderer": "^0.2.
|
|
85
|
-
"@deepseek-ai/dsh-client-ui-settings": "^0.2.
|
|
86
|
-
"@deepseek-ai/dsh-client-ui-tool": "^0.2.
|
|
87
|
-
"@deepseek-ai/dsh-host-webserver": "^0.2.
|
|
88
|
-
"@deepseek-ai/dsh-llm": "^0.2.
|
|
89
|
-
"@deepseek-ai/dsh-session": "^0.2.
|
|
90
|
-
"@deepseek-ai/dsh-subagent": "^0.2.
|
|
91
|
-
"@deepseek-ai/dsh-system-prompt": "^0.2.
|
|
92
|
-
"@deepseek-ai/dsh-tools": "^0.2.
|
|
93
|
-
"@deepseek-ai/dsh-workspace": "^0.2.
|
|
80
|
+
"@deepseek-ai/cordis": "^4.1.0",
|
|
81
|
+
"@deepseek-ai/schemastery": "^3.19.0",
|
|
82
|
+
"@deepseek-ai/dsh-agent": "^0.2.2-rc.1",
|
|
83
|
+
"@deepseek-ai/dsh-atomic-write": "^0.2.2-rc.1",
|
|
84
|
+
"@deepseek-ai/dsh-client-connection": "^0.2.2-rc.1",
|
|
85
|
+
"@deepseek-ai/dsh-client-locale": "^0.2.2-rc.1",
|
|
86
|
+
"@deepseek-ai/dsh-client-ui-conversation": "^0.2.2-rc.1",
|
|
87
|
+
"@deepseek-ai/dsh-client-ui-renderer": "^0.2.2-rc.1",
|
|
88
|
+
"@deepseek-ai/dsh-client-ui-settings": "^0.2.2-rc.1",
|
|
89
|
+
"@deepseek-ai/dsh-client-ui-tool": "^0.2.2-rc.1",
|
|
90
|
+
"@deepseek-ai/dsh-host-webserver": "^0.2.2-rc.1",
|
|
91
|
+
"@deepseek-ai/dsh-llm": "^0.2.2-rc.1",
|
|
92
|
+
"@deepseek-ai/dsh-session": "^0.2.2-rc.1",
|
|
93
|
+
"@deepseek-ai/dsh-subagent": "^0.2.2-rc.1",
|
|
94
|
+
"@deepseek-ai/dsh-system-prompt": "^0.2.2-rc.1",
|
|
95
|
+
"@deepseek-ai/dsh-tools": "^0.2.2-rc.1",
|
|
96
|
+
"@deepseek-ai/dsh-workspace": "^0.2.2-rc.1",
|
|
94
97
|
"react": "^18.2.0"
|
|
95
98
|
},
|
|
96
99
|
"peerDependenciesMeta": {
|
|
@@ -150,23 +153,23 @@
|
|
|
150
153
|
}
|
|
151
154
|
},
|
|
152
155
|
"devDependencies": {
|
|
153
|
-
"@deepseek-ai/cordis": "4.0
|
|
154
|
-
"@deepseek-ai/schemastery": "3.
|
|
155
|
-
"@deepseek-ai/dsh-agent": "0.2.
|
|
156
|
-
"@deepseek-ai/dsh-atomic-write": "0.2.
|
|
157
|
-
"@deepseek-ai/dsh-client-connection": "0.2.
|
|
158
|
-
"@deepseek-ai/dsh-client-locale": "0.2.
|
|
159
|
-
"@deepseek-ai/dsh-client-ui-conversation": "0.2.
|
|
160
|
-
"@deepseek-ai/dsh-client-ui-renderer": "0.2.
|
|
161
|
-
"@deepseek-ai/dsh-client-ui-settings": "0.2.
|
|
162
|
-
"@deepseek-ai/dsh-client-ui-tool": "0.2.
|
|
163
|
-
"@deepseek-ai/dsh-host-webserver": "0.2.
|
|
164
|
-
"@deepseek-ai/dsh-llm": "0.2.
|
|
165
|
-
"@deepseek-ai/dsh-session": "0.2.
|
|
166
|
-
"@deepseek-ai/dsh-subagent": "0.2.
|
|
167
|
-
"@deepseek-ai/dsh-system-prompt": "0.2.
|
|
168
|
-
"@deepseek-ai/dsh-tools": "0.2.
|
|
169
|
-
"@deepseek-ai/dsh-workspace": "0.2.
|
|
156
|
+
"@deepseek-ai/cordis": "4.1.0",
|
|
157
|
+
"@deepseek-ai/schemastery": "3.19.0",
|
|
158
|
+
"@deepseek-ai/dsh-agent": "0.2.2-rc.1",
|
|
159
|
+
"@deepseek-ai/dsh-atomic-write": "0.2.2-rc.1",
|
|
160
|
+
"@deepseek-ai/dsh-client-connection": "0.2.2-rc.1",
|
|
161
|
+
"@deepseek-ai/dsh-client-locale": "0.2.2-rc.1",
|
|
162
|
+
"@deepseek-ai/dsh-client-ui-conversation": "0.2.2-rc.1",
|
|
163
|
+
"@deepseek-ai/dsh-client-ui-renderer": "0.2.2-rc.1",
|
|
164
|
+
"@deepseek-ai/dsh-client-ui-settings": "0.2.2-rc.1",
|
|
165
|
+
"@deepseek-ai/dsh-client-ui-tool": "0.2.2-rc.1",
|
|
166
|
+
"@deepseek-ai/dsh-host-webserver": "0.2.2-rc.1",
|
|
167
|
+
"@deepseek-ai/dsh-llm": "0.2.2-rc.1",
|
|
168
|
+
"@deepseek-ai/dsh-session": "0.2.2-rc.1",
|
|
169
|
+
"@deepseek-ai/dsh-subagent": "0.2.2-rc.1",
|
|
170
|
+
"@deepseek-ai/dsh-system-prompt": "0.2.2-rc.1",
|
|
171
|
+
"@deepseek-ai/dsh-tools": "0.2.2-rc.1",
|
|
172
|
+
"@deepseek-ai/dsh-workspace": "0.2.2-rc.1",
|
|
170
173
|
"@types/node": "^22.0.0",
|
|
171
174
|
"@types/react": "~18.3.1",
|
|
172
175
|
"react": "^18.2.0",
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# v0.2.0 — 开评前确认卡 + 每维度专家粒度
|
|
2
|
+
|
|
3
|
+
本版给针锋加上「**开始评审之前**先看一张设置确认卡」的一步,并让红队阵容可以按维度逐行配置(模型 / 角色 / 提示词)。状态机与「表态由人做」的边界不变;不传新参数时行为与 v0.1.6 逐字一致。
|
|
4
|
+
|
|
5
|
+
## 新增:`crossfire_plan_review`(第 0 步)
|
|
6
|
+
|
|
7
|
+
- 在 `crossfire_open` 之前弹一张 Markdown 卡,固定两张表:
|
|
8
|
+
- **表 1 评审设置**:评审标题、来源、强度(每维专家数 / 复审上限 / 轮数 / Token)、维度、立场摘要、红队人数。
|
|
9
|
+
- **表 2 红队阵容**:`# / 维度 / 专家 key / 模型 / 角色 / 提示词` 六列。
|
|
10
|
+
- 表下方给待验证正文(超过 1200 字截断并注明「完整正文随评审落盘」)与立场全文。
|
|
11
|
+
- 按钮:「**确定开始**」/「**仍需修改**」。改完再弹时顶部列「本次变更」;主持人没写变更点就如实标「(本次未标注具体变更)」。
|
|
12
|
+
- 该工具**不落盘、不拉专家**:确认前磁盘上不会出现一条空评审。
|
|
13
|
+
|
|
14
|
+
## 红队阵容可以按维度逐行配置
|
|
15
|
+
|
|
16
|
+
- `crossfire_plan_review` / `crossfire_open` 新增 `experts[]`:每行一位专家,可指定 `dimension` / `key` / `role` / `provider` / `model` / `prompt`。
|
|
17
|
+
- `crossfire_open` 把确认过的阵容落盘为 `CrossfireRecord.expertRoster`;`crossfire_attack` 与卡片「发起攻击」都**优先消费它**(复审轮同样保留,不会退回设置页旧阵容)。
|
|
18
|
+
- 匹配优先级:`dimension` → `key` → 顺序兜底。用户给专家改名字也不会配错行;没有 `dimension` 的老 roster 行为不变。
|
|
19
|
+
|
|
20
|
+
## 专家提示词(补充定位)
|
|
21
|
+
|
|
22
|
+
- `prompt` 进入 persona 的「评审者补充提示词」段,并在同段声明:**只放宽专长范围,不放宽只读 / 不产出方案 / 不迎合**;与硬约束冲突的部分视为无效。
|
|
23
|
+
- 空值(缺省 / 空串 / 纯空白)时 persona 与 v0.1.6 **逐字一致**。`review.ts` 的净化白名单、`rpc.ts` 的 persona 重建分支都已同步,避免"写盘读不回"或"查看原提示词少一段"。
|
|
24
|
+
|
|
25
|
+
## 安全性
|
|
26
|
+
|
|
27
|
+
- `crossfire_plan_review` 已加入红队专家的工具黑名单:专家不能自己开评/改设置。
|
|
28
|
+
- 确认卡只确认「怎么开评」;认定/驳回仍在评审卡上由人完成。
|
|
29
|
+
|
|
30
|
+
## 兼容性
|
|
31
|
+
|
|
32
|
+
- 不传 `experts` 时:确认卡按「每维一位」生成默认阵容;`crossfire_open` 不写 `expertRoster`,`crossfire_attack` 退回原有规划,行为与 v0.1.6 一致。
|
|
33
|
+
- 默认阵容借 `planExperts` 生成(与真正开打同一段逻辑),不会出现"卡上是一套、开打是另一套"。
|
|
34
|
+
|
|
35
|
+
## 验证
|
|
36
|
+
|
|
37
|
+
- `tsc`(host / client)通过。
|
|
38
|
+
- 全量测试 **271 / 271 通过**(新增 plan 渲染、三态、工具接线、落盘/读回、persona 边界、roster 匹配等用例)。
|
|
39
|
+
- `tsdown` 构建通过。
|
|
40
|
+
|
|
41
|
+
## 发布
|
|
42
|
+
|
|
43
|
+
- npm 稳定轨:`npm publish`(`latest`)
|
|
44
|
+
- 升级:`npm i @y9931666/dsh-plugin-crossfire@latest`
|