@y9931666/dsh-plugin-roundtable 1.0.0-rc.2
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 +328 -0
- package/cordis.patch.yml +22 -0
- package/lib/client.js +4276 -0
- package/lib/edge-helper-iqXOG5o_.js +12 -0
- package/lib/index.js +4535 -0
- package/lib/state-BzBQig2q.js +479 -0
- package/lib/state-pJShWoUr.js +3 -0
- package/lib/types/aggregator.d.ts +15 -0
- package/lib/types/budget.d.ts +46 -0
- package/lib/types/charter.d.ts +13 -0
- package/lib/types/client/RoundTableSettings.d.ts +14 -0
- package/lib/types/client/RoundTableView.d.ts +27 -0
- package/lib/types/client/brand-logos.generated.d.ts +5 -0
- package/lib/types/client/index.d.ts +23 -0
- package/lib/types/client/locales.d.ts +14 -0
- package/lib/types/client/slot-boundary.d.ts +49 -0
- package/lib/types/client/tool-views-model.d.ts +65 -0
- package/lib/types/client/tool-views.d.ts +31 -0
- package/lib/types/client/wire.d.ts +238 -0
- package/lib/types/edge-helper.d.ts +7 -0
- package/lib/types/harness-compat.d.ts +204 -0
- package/lib/types/index.d.ts +53 -0
- package/lib/types/kb-digest.d.ts +47 -0
- package/lib/types/members.d.ts +83 -0
- package/lib/types/node-events.d.ts +90 -0
- package/lib/types/plan.d.ts +86 -0
- package/lib/types/preferences.d.ts +143 -0
- package/lib/types/prompt.d.ts +52 -0
- package/lib/types/proxy-thinking.d.ts +12 -0
- package/lib/types/review-split.d.ts +61 -0
- package/lib/types/rpc.d.ts +89 -0
- package/lib/types/skills.d.ts +61 -0
- package/lib/types/snapshot.d.ts +96 -0
- package/lib/types/state.d.ts +142 -0
- package/lib/types/token-usage.d.ts +71 -0
- package/lib/types/tools.d.ts +59 -0
- package/lib/types/types.d.ts +330 -0
- package/lib/types/version.d.ts +21 -0
- package/lib/types/web-guard.d.ts +37 -0
- package/lib/types/workspace-candidates.d.ts +17 -0
- package/lib/workspace-candidates-B7isleLt.js +3 -0
- package/lib/workspace-candidates-DNmGPpSc.js +20 -0
- package/package.json +161 -0
- package/release-notes/v0.2.0.md +39 -0
- package/release-notes/v0.2.1.md +39 -0
- package/release-notes/v0.2.2.md +54 -0
- package/release-notes/v0.2.21.md +42 -0
- package/release-notes/v0.2.31.md +70 -0
- package/release-notes/v0.2.32.md +52 -0
- package/release-notes/v0.2.35.md +116 -0
- package/release-notes/v0.2.36.md +84 -0
- package/release-notes/v1.0.0-rc.1.md +165 -0
- package/release-notes/v1.0.0-rc.2.md +180 -0
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RoundTable durable meeting state types.
|
|
3
|
+
*
|
|
4
|
+
* A meeting is one directory under the state root holding `meeting.json`
|
|
5
|
+
* (nodes, edges, decisions, budget, charter) plus a `transcript.jsonl`
|
|
6
|
+
* (utterances). Expert nodes are continuable subagents whose durable child
|
|
7
|
+
* session ids are recorded in the meeting file, so a meeting survives
|
|
8
|
+
* harness restarts.
|
|
9
|
+
* @module dsh-plugin-roundtable/types
|
|
10
|
+
*/
|
|
11
|
+
/** Collaboration mode: captain orchestrates every exchange, experts talk
|
|
12
|
+
* peer-to-peer, or a 针锋相对 (red-team) review of a settled plan. */
|
|
13
|
+
export type MeetingMode = 'orchestrated' | 'egalitarian' | 'redteam';
|
|
14
|
+
/** skill 传递方式(D5):主持人中转 / 专家直接调用。 */
|
|
15
|
+
export type SkillDelivery = 'relay' | 'direct';
|
|
16
|
+
/** Meeting lifecycle. `muted` = budget exceeded (闭麦); user may top up or close.
|
|
17
|
+
*
|
|
18
|
+
* `archived` is a RESERVED state: no code path in this plugin ever writes it
|
|
19
|
+
* (meeting archiving / read-only mode is deliberately out of scope for this
|
|
20
|
+
* release). The guards that test for it are kept on purpose — they are
|
|
21
|
+
* defensive branches, not dead weight, so implementing archiving later cannot
|
|
22
|
+
* silently miss a call site. */
|
|
23
|
+
export type MeetingStatus = 'active' | 'muted' | 'ended' | 'archived';
|
|
24
|
+
/** One expert node's lifecycle status. */
|
|
25
|
+
export type NodeStatus = 'idle' | 'working' | 'ready' | 'removed';
|
|
26
|
+
/** Edge direction: forward (pipeline) or bidirectional (debate channel). */
|
|
27
|
+
export type EdgeDirection = 'forward' | 'bidirectional';
|
|
28
|
+
/** What one transcript line records. */
|
|
29
|
+
export type UtteranceKind = 'speech' | 'proxy-thinking' | 'retrieval' | 'decision' | 'auto-capture';
|
|
30
|
+
/** Node statuses that still count as participants. */
|
|
31
|
+
export declare const ACTIVE_NODE_STATUSES: readonly NodeStatus[];
|
|
32
|
+
/** Reserved speaker key of the captain (the owning session). */
|
|
33
|
+
export declare const CAPTAIN_KEY = "captain";
|
|
34
|
+
/** Reserved speaker key of the aggregation gateway. */
|
|
35
|
+
export declare const AGGREGATOR_KEY = "aggregator";
|
|
36
|
+
/** One expert node: a continuable subagent plus its meeting-side record. */
|
|
37
|
+
export interface MeetingNode {
|
|
38
|
+
/** Durable continuable subagent session id (empty until spawned). */
|
|
39
|
+
id: string;
|
|
40
|
+
/** Unique display key inside the meeting (used by edges and mailboxes). */
|
|
41
|
+
key: string;
|
|
42
|
+
/** Role description, e.g. `researcher`, `engineer`, `reviewer`. */
|
|
43
|
+
role?: string;
|
|
44
|
+
/** Resolved LLM provider route captured when this node was created. */
|
|
45
|
+
provider?: string;
|
|
46
|
+
/** Resolved model captured when this node was created. */
|
|
47
|
+
model?: string;
|
|
48
|
+
/** Resolved reasoning effort captured when this node was created.
|
|
49
|
+
* An adapter-owned opaque id (e.g. `high` / `medium` / `low` — the exact
|
|
50
|
+
* vocabulary belongs to the model capability, not to this plugin). Read by
|
|
51
|
+
* `spawnNode` into `agentOptions.reasoningEffort` and surfaced by
|
|
52
|
+
* `roundtable_status`; absent = inherit the captain's route-owned effort. */
|
|
53
|
+
reasoningEffort?: string;
|
|
54
|
+
status: NodeStatus;
|
|
55
|
+
joinedAt: number;
|
|
56
|
+
/** 最近一次失败的可读说明(第 1 批)。子代理以 error 结束、或 provider 请求
|
|
57
|
+
* 失败时写入,下一次成功产出时清除 —— 让"这位专家到底跑起来了没有"在
|
|
58
|
+
* `roundtable_status` 里直接可见,而不是只留一个 removed 墓碑。 */
|
|
59
|
+
lastError?: string;
|
|
60
|
+
}
|
|
61
|
+
/** One directed channel between two participants. */
|
|
62
|
+
export interface MeetingEdge {
|
|
63
|
+
id: string;
|
|
64
|
+
/** Node key, or `captain` / `aggregator`. */
|
|
65
|
+
from: string;
|
|
66
|
+
/** Node key, or `captain` / `aggregator`. */
|
|
67
|
+
to: string;
|
|
68
|
+
direction: EdgeDirection;
|
|
69
|
+
createdAt: number;
|
|
70
|
+
}
|
|
71
|
+
/** One line of the meeting transcript. */
|
|
72
|
+
export interface MeetingUtterance {
|
|
73
|
+
id: string;
|
|
74
|
+
/** Speaker: a node key or `captain`. */
|
|
75
|
+
nodeKey: string;
|
|
76
|
+
kind: UtteranceKind;
|
|
77
|
+
content: string;
|
|
78
|
+
/** Gateway-produced structured summary (set by `roundtable_summarize`). */
|
|
79
|
+
summary?: string;
|
|
80
|
+
/** Directed audience (absent = submitted to the gateway). */
|
|
81
|
+
to?: string;
|
|
82
|
+
round: number;
|
|
83
|
+
ts: number;
|
|
84
|
+
}
|
|
85
|
+
/** One human decision requested by the captain. */
|
|
86
|
+
export interface MeetingDecision {
|
|
87
|
+
id: string;
|
|
88
|
+
question: string;
|
|
89
|
+
/** Option labels offered to the user (方案 A / B / ...). */
|
|
90
|
+
options: string[];
|
|
91
|
+
chosen?: string;
|
|
92
|
+
customAnswer?: string;
|
|
93
|
+
status: 'pending' | 'resolved';
|
|
94
|
+
ts: number;
|
|
95
|
+
}
|
|
96
|
+
/** Round/token budget; exceeding either mutes the meeting. */
|
|
97
|
+
export interface MeetingBudget {
|
|
98
|
+
maxRounds: number;
|
|
99
|
+
maxTokens: number;
|
|
100
|
+
usedRounds: number;
|
|
101
|
+
usedTokens: number;
|
|
102
|
+
/**
|
|
103
|
+
* 最近一次测得的 **provider 上报**用量(第 3 批)。与 `usedTokens`(发言文本
|
|
104
|
+
* 粗估)**并列而非替代** —— 熔断口径不变,仍走 `usedTokens`。缺省/0 表示
|
|
105
|
+
* 此刻没有可测的 live 子会话。
|
|
106
|
+
*/
|
|
107
|
+
usedTokensReal?: number;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* One pending user action recorded by the Web UI (`user-actions.jsonl`).
|
|
111
|
+
*
|
|
112
|
+
* The UI never mutates meeting state directly: an expert edit (add/remove)
|
|
113
|
+
* is appended here as a pending action, the captain (主持人) drains the file
|
|
114
|
+
* next round through `roundtable_*` tools, and only clears it after every
|
|
115
|
+
* line was executed successfully. Empty file = no pending work.
|
|
116
|
+
*/
|
|
117
|
+
export interface UserAction {
|
|
118
|
+
id: string;
|
|
119
|
+
ts: number;
|
|
120
|
+
/** What the captain must do: add an expert node / remove one / other. */
|
|
121
|
+
kind: 'add-node' | 'remove-node' | 'kb-path' | 'other';
|
|
122
|
+
/** Target node key when the action concerns one expert. */
|
|
123
|
+
nodeKey?: string;
|
|
124
|
+
/** Role text captured for an add-node action. */
|
|
125
|
+
role?: string;
|
|
126
|
+
/** Provider route captured for an add-node action (empty = inherit captain). */
|
|
127
|
+
provider?: string;
|
|
128
|
+
/** Model captured for an add-node action (empty = inherit captain). */
|
|
129
|
+
model?: string;
|
|
130
|
+
/** Human-readable sentence, e.g. "删除了专家 researcher". */
|
|
131
|
+
text: string;
|
|
132
|
+
}
|
|
133
|
+
/** 用户自建的角色预设(B3)。
|
|
134
|
+
*
|
|
135
|
+
* 全局偏好(`settings.yaml` 的 `roundtable` 命名空间),不属于任何一场会议:
|
|
136
|
+
* 新建/编辑/删除预设都不会影响已创建的会议。它只是"专家管理"表单的填充
|
|
137
|
+
* 来源 —— 选中后把 role/provider/model 三个字段写进同一条 `add-node`
|
|
138
|
+
* user-action,链路与手填完全一致(不需要新链路)。 */
|
|
139
|
+
export interface RolePreset {
|
|
140
|
+
/** 稳定 id(新建时生成;编辑与删除都按 id 定位)。 */
|
|
141
|
+
id: string;
|
|
142
|
+
/** 预设名称,如"安全审查"。 */
|
|
143
|
+
name: string;
|
|
144
|
+
/** 角色说明,最终写进专家节点的 role。 */
|
|
145
|
+
role: string;
|
|
146
|
+
/** 可选 LLM provider 路由;必须与 model 同时给出才生效。空 = 继承主持人。 */
|
|
147
|
+
provider?: string;
|
|
148
|
+
/** 可选模型名;空 = 继承主持人。 */
|
|
149
|
+
model?: string;
|
|
150
|
+
}
|
|
151
|
+
/** 阵容预设里的一位成员(B3+)。
|
|
152
|
+
*
|
|
153
|
+
* 与 {@link RolePreset} 的分工:预设描述"一位专家该怎么配",阵容描述
|
|
154
|
+
* "这一场请哪几位专家"。阵容**刻意不描述会议怎么开** —— 没有节点顺序、
|
|
155
|
+
* 没有连线、没有依赖与分支。这条边界是被红队评审认定过的(gpt-2:模板与
|
|
156
|
+
* 角色预设的边界未定义),所以在这里用类型直接钉死,避免"阵容"演化成
|
|
157
|
+
* 又一个会议模板。 */
|
|
158
|
+
export interface RoleSquadMember {
|
|
159
|
+
/** 专家 key(进会议后的节点标识,规则同节点的 key)。 */
|
|
160
|
+
key: string;
|
|
161
|
+
/** 角色说明,写入节点的 role;可为空。 */
|
|
162
|
+
role: string;
|
|
163
|
+
/** 可选 LLM provider 路由;必须与 model 同时给出才生效。空 = 继承主持人。 */
|
|
164
|
+
provider?: string;
|
|
165
|
+
/** 可选模型名;空 = 继承主持人。 */
|
|
166
|
+
model?: string;
|
|
167
|
+
}
|
|
168
|
+
/** 用户自建的阵容预设(B3+):一次把多位专家排进 user-actions 队列。
|
|
169
|
+
*
|
|
170
|
+
* 链路与手填完全一致 —— 套用阵容就是逐位提交 `add-node` user-action,
|
|
171
|
+
* 主持人下一轮照常 `roundtable_add_node`。因此它不需要任何新链路,
|
|
172
|
+
* 也不改变会议的运行时语义。 */
|
|
173
|
+
export interface RoleSquad {
|
|
174
|
+
/** 稳定 id(新建时生成;编辑与删除都按 id 定位)。 */
|
|
175
|
+
id: string;
|
|
176
|
+
/** 阵容名称,如"方案评审三人组"。 */
|
|
177
|
+
name: string;
|
|
178
|
+
/** 成员清单(至少一位)。 */
|
|
179
|
+
members: RoleSquadMember[];
|
|
180
|
+
}
|
|
181
|
+
/** 知识库摘要缓存(C2)的一条条目。
|
|
182
|
+
*
|
|
183
|
+
* 失效键 = `path + size + mtimeMs`:任一变化即视为失效。宿主
|
|
184
|
+
* `listKbDirectory()` 本来就在 stat 每个条目,所以比对不产生额外 IO。
|
|
185
|
+
* 本插件**不自己调 LLM 生成摘要** —— digest 由主持人读过文件后写下,
|
|
186
|
+
* 缓存只负责"命中就不必再读第二遍"(你读 + 专家读 = 双倍 token)。 */
|
|
187
|
+
export interface KbDigestEntry {
|
|
188
|
+
/** 知识库中被读取条目的绝对路径。 */
|
|
189
|
+
path: string;
|
|
190
|
+
/** 失效键:写摘要时的文件大小(字节)。 */
|
|
191
|
+
size: number;
|
|
192
|
+
/** 失效键:写摘要时的修改时间(ms)。 */
|
|
193
|
+
mtimeMs: number;
|
|
194
|
+
/** 主持人写下的要点摘要(不是全文)。 */
|
|
195
|
+
digest: string;
|
|
196
|
+
/** 摘要写入时间(ms),超限时按最旧淘汰。 */
|
|
197
|
+
ts: number;
|
|
198
|
+
}
|
|
199
|
+
/** `<meetingDir>/kb-digest.json` 的形状(独立文件,避开 meeting.json 竞态)。 */
|
|
200
|
+
export interface KbDigestFile {
|
|
201
|
+
meetingId: string;
|
|
202
|
+
entries: KbDigestEntry[];
|
|
203
|
+
updatedAt: number;
|
|
204
|
+
}
|
|
205
|
+
/** The full durable meeting record (transcript lives in transcript.jsonl). */
|
|
206
|
+
export interface Meeting {
|
|
207
|
+
/**
|
|
208
|
+
* 数据格式版本(`meeting.json` 的形状版本)。
|
|
209
|
+
*
|
|
210
|
+
* 与 `ReviewRecord.schemaVersion` 同一套机制:**缺失视为 1**(v0.2.36 及
|
|
211
|
+
* 之前写出的文件都没有这个字段)。读取时由 `normalizeMeeting()` 在内存里
|
|
212
|
+
* 幂等升到当前版本,下次 `writeMeeting` 顺带落盘。
|
|
213
|
+
*
|
|
214
|
+
* 存在的理由:`meeting.json` 是本插件最核心的持久化文件,此前却是唯一
|
|
215
|
+
* 「裸 `JSON.parse(...) as Meeting`」——形状一变,老文件要么读出 undefined
|
|
216
|
+
* 字段、要么静默损坏,且没有任何版本号可供分支。维护模式下「以后的改动
|
|
217
|
+
* 会不会读不出老会议」必须有一个明确答案,这个字段就是那个答案。
|
|
218
|
+
*/
|
|
219
|
+
schemaVersion?: number;
|
|
220
|
+
/** Sanitized stable id; the meeting directory name. */
|
|
221
|
+
id: string;
|
|
222
|
+
name: string;
|
|
223
|
+
/** Meeting background and goal (charter section one). */
|
|
224
|
+
goal: string;
|
|
225
|
+
mode: MeetingMode;
|
|
226
|
+
/** Session id of the captain (DeepSeek) that owns this meeting. */
|
|
227
|
+
captainSessionId: string;
|
|
228
|
+
/** The injected《全局协作总纲》. */
|
|
229
|
+
charter: string;
|
|
230
|
+
nodes: MeetingNode[];
|
|
231
|
+
edges: MeetingEdge[];
|
|
232
|
+
decisions: MeetingDecision[];
|
|
233
|
+
budget: MeetingBudget;
|
|
234
|
+
/** Current debate round. */
|
|
235
|
+
round: number;
|
|
236
|
+
/** 知识库目录(阅览版):主持人按需读取其中文件转交专家。空 = 未设置。 */
|
|
237
|
+
kbPath?: string;
|
|
238
|
+
/** 本次会议选中的 skill 名称清单(来自 `ctx.skills.list()`);空/缺省 = 未选。 */
|
|
239
|
+
skills?: string[];
|
|
240
|
+
/** skill 传递方式(创建时固化):relay=主持人中转;direct=专家自行调用。 */
|
|
241
|
+
skillDelivery?: SkillDelivery;
|
|
242
|
+
status: MeetingStatus;
|
|
243
|
+
createdAt: number;
|
|
244
|
+
updatedAt: number;
|
|
245
|
+
}
|
|
246
|
+
/** 观点证据分级(C1):代码/bug 类缺陷须给可复现步骤;设计类缺陷给论证链。 */
|
|
247
|
+
export interface ReviewEvidence {
|
|
248
|
+
/** 证据类型:repro=可复现步骤;argument=论证链(设计类缺陷适用)。 */
|
|
249
|
+
kind: 'repro' | 'argument';
|
|
250
|
+
/** 证据正文:复现步骤(1. 2. 3.)或论证链。≤600 字符。 */
|
|
251
|
+
text: string;
|
|
252
|
+
}
|
|
253
|
+
/** 针锋相对评审:一个观点(红队专家提的一条缺陷,可能是发言拆分而来)。 */
|
|
254
|
+
export interface ReviewViewpoint {
|
|
255
|
+
/** 行 id:`${utteranceId}#${seq}`(拆分后 seq≥1;未拆分整条 seq=0)。 */
|
|
256
|
+
id: string;
|
|
257
|
+
/** 来源发言 id(collect 幂等键:同一发言只收集一次)。 */
|
|
258
|
+
utteranceId: string;
|
|
259
|
+
/** 提出该观点的专家节点 key。 */
|
|
260
|
+
nodeKey: string;
|
|
261
|
+
/** 缺陷内容(单条观点文本)。 */
|
|
262
|
+
content: string;
|
|
263
|
+
/** 三态:pending=未操作;endorsed=用户支持认定为真实缺陷;rejected=用户审阅后否定。可互切。 */
|
|
264
|
+
status: 'pending' | 'endorsed' | 'rejected';
|
|
265
|
+
/** 驳回理由(C2:驳回必填;支持后改回 pending/rejected 不清除,供追溯)。 */
|
|
266
|
+
rejectReason?: string;
|
|
267
|
+
/** 证据分级(C1):LLM 拆分时按发言内容提取;无则 undefined。 */
|
|
268
|
+
evidence?: ReviewEvidence;
|
|
269
|
+
/** 观点对应的原文引用子串(≤120 字符,无则 undefined)。 */
|
|
270
|
+
quote?: string;
|
|
271
|
+
/** 维度标签(自由字符串,默认"其他")。 */
|
|
272
|
+
dimension: string;
|
|
273
|
+
ts: number;
|
|
274
|
+
/** 发言内序号:0=整条未拆分;≥1=拆分出的第 N 条。 */
|
|
275
|
+
seq: number;
|
|
276
|
+
}
|
|
277
|
+
/** 一轮已完成的评审快照(闭环复审 history 项)。 */
|
|
278
|
+
export interface ReviewPassSnapshot {
|
|
279
|
+
pass: number;
|
|
280
|
+
question: string;
|
|
281
|
+
plan: string;
|
|
282
|
+
viewpoints: ReviewViewpoint[];
|
|
283
|
+
finishedAt: number;
|
|
284
|
+
/** 该轮修订说明(主持人 finish_review 时附,供下一轮核对旧缺陷是否修复)。 */
|
|
285
|
+
revisedPlanSummary?: string;
|
|
286
|
+
}
|
|
287
|
+
/** 一条轻量用户反馈(E1/E3,工作区级 feedback.jsonl,匿名)。
|
|
288
|
+
* 只记录结构化使用事实 + 用户主动填写的一句说明;绝不记录对话内容。 */
|
|
289
|
+
export interface FeedbackEntry {
|
|
290
|
+
id: string;
|
|
291
|
+
ts: number;
|
|
292
|
+
/** 会议 id(仅稳定 id,不存会议名/内容,便于去重)。 */
|
|
293
|
+
meetingId: string;
|
|
294
|
+
/** 协作模式(orchestrated / egalitarian / redteam)。 */
|
|
295
|
+
mode: string;
|
|
296
|
+
/** 专家 provider 去重列表(如 ["zai-coding-cn"])。 */
|
|
297
|
+
providers: string[];
|
|
298
|
+
/** 专家 model 去重列表(如 ["glm-5.2"])。 */
|
|
299
|
+
models: string[];
|
|
300
|
+
/** 会议结束时预算用量。 */
|
|
301
|
+
usedRounds: number;
|
|
302
|
+
usedTokens: number;
|
|
303
|
+
/** 1 键有用度:good / meh / bad。 */
|
|
304
|
+
rating: 'good' | 'meh' | 'bad';
|
|
305
|
+
/** 可选一句"最卡的点"(用户主动填写)。 */
|
|
306
|
+
note?: string;
|
|
307
|
+
}
|
|
308
|
+
/** 针锋相对评审记录(`<meetingDir>/review.json`,独立文件防 meeting.json 竞态)。 */
|
|
309
|
+
export interface ReviewRecord {
|
|
310
|
+
meetingId: string;
|
|
311
|
+
/** 用户最初提出的问题。 */
|
|
312
|
+
question: string;
|
|
313
|
+
/** 主持人提供的方案与说明。 */
|
|
314
|
+
plan: string;
|
|
315
|
+
/** reviewing=评审进行中;ready=观点已收集,弹窗可展示;done=用户完成评审。 */
|
|
316
|
+
status: 'reviewing' | 'ready' | 'done';
|
|
317
|
+
/** 闭环复审(C3):当前第几轮评审(首轮 = 1;每轮定稿后再开下一轮 +1)。 */
|
|
318
|
+
reviewPass: number;
|
|
319
|
+
/** 闭环复审(C3):最大评审轮数(首轮 + 最多复审 2 次 = 3);达到上限后再想继续须用户显式批准。 */
|
|
320
|
+
maxReviewPass: number;
|
|
321
|
+
/** 之前各轮已定稿的评审快照(闭环核对"旧缺陷是否修复"的依据)。 */
|
|
322
|
+
history: ReviewPassSnapshot[];
|
|
323
|
+
/** schema 版本:1=旧(endorsed 布尔);2=三态 + 观点拆分(当前)。缺失视为 1。 */
|
|
324
|
+
schemaVersion: 1 | 2;
|
|
325
|
+
viewpoints: ReviewViewpoint[];
|
|
326
|
+
startedAt: number;
|
|
327
|
+
updatedAt: number;
|
|
328
|
+
/** 完成评审的时间(status → done 时写)。 */
|
|
329
|
+
finishedAt?: number;
|
|
330
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 插件版本号的源码侧单一来源。
|
|
3
|
+
*
|
|
4
|
+
* `package.json` 的 `version` 是发布侧的权威值,两者必须一致:
|
|
5
|
+
* `test/version.test.mjs` 会在不一致时直接让测试失败。加这道闸门是因为
|
|
6
|
+
* `renderReviewMarkdown` 的导出头部曾长期硬编码 `v0.2.21`,而 package.json
|
|
7
|
+
* 已经走到 0.2.32 —— 导出物里的版本号说了谎,却没有任何测试会发现。
|
|
8
|
+
*
|
|
9
|
+
* @module dsh-plugin-roundtable/version
|
|
10
|
+
*/
|
|
11
|
+
/** 当前插件版本(必须与 package.json 的 version 逐字一致)。 */
|
|
12
|
+
export declare const PLUGIN_VERSION = "1.0.0-rc.2";
|
|
13
|
+
/** 导出物头部使用的插件标识行。 */
|
|
14
|
+
export declare const PLUGIN_ID = "@y9931666/dsh-plugin-roundtable v1.0.0-rc.2";
|
|
15
|
+
/** DeepSeek Harness 版本区间(导出头部展示用)。
|
|
16
|
+
*
|
|
17
|
+
* 必须与 `compatibility.json` 的 `recommendedHost` 一致 —— 由
|
|
18
|
+
* `test/compatibility.test.mjs` 强制,`scripts/compatibility.mjs` 参与发布门禁。
|
|
19
|
+
* 此前这里是硬编码字符串,与 devDependencies 一起漂到了 rc.2 而无人发现;
|
|
20
|
+
* 0.2.0-rc.2 这次跨大版本升级同样由这两道闸门兜住。 */
|
|
21
|
+
export declare const HARNESS_RANGE = "DeepSeek Harness 0.2.0-rc.2+";
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Web 路由的认证栅栏(第 2 批 / P5)。
|
|
3
|
+
*
|
|
4
|
+
* 插件自建的两条 Web 路由(`/plugins/dsh-plugin-roundtable/rpc` 与 `.../state`)
|
|
5
|
+
* 注册在宿主 `webServer` 上,而宿主 webserver 自述 "knows no harness concepts"、
|
|
6
|
+
* handler 只有裸 `(req, res)` —— 栅栏**不会自动施加**。宿主为此专门暴露了
|
|
7
|
+
* `connection.requestRejection()`,其文档原文就是:"Apply Connection's
|
|
8
|
+
* Host/Origin checks and browser authentication to another Web route"。
|
|
9
|
+
*
|
|
10
|
+
* 不接它的后果是真实的:本机任意网页(DNS rebinding 后同源,或 `text/plain`
|
|
11
|
+
* 简单 POST 免预检)都能命中插件路由 —— 删会议、改连线、读走全部评审内容与
|
|
12
|
+
* 发言。宿主自己的 `/api` 有栅栏,插件这两条路由曾是缺口。
|
|
13
|
+
*
|
|
14
|
+
* @module dsh-plugin-roundtable/web-guard
|
|
15
|
+
*/
|
|
16
|
+
import type { IncomingMessage } from 'node:http';
|
|
17
|
+
/** The single Connection ability this guard needs. */
|
|
18
|
+
export interface ConnectionFence {
|
|
19
|
+
requestRejection(request: {
|
|
20
|
+
headers: IncomingMessage['headers'];
|
|
21
|
+
}): 401 | 403 | undefined;
|
|
22
|
+
}
|
|
23
|
+
/** Request-body cap for the plugin RPC route (1 MiB — same order as the host's own API). */
|
|
24
|
+
export declare const MAX_RPC_BODY_BYTES = 1048576;
|
|
25
|
+
/** Pick the fence out of a possibly-absent service (never load-gating). */
|
|
26
|
+
export declare function connectionFenceOf(service: unknown): ConnectionFence | undefined;
|
|
27
|
+
/**
|
|
28
|
+
* Decide whether one inbound request may proceed.
|
|
29
|
+
*
|
|
30
|
+
* @returns the HTTP status to reject with, or `undefined` to proceed.
|
|
31
|
+
*
|
|
32
|
+
* A composition without the Connection service has no fence to apply and is let
|
|
33
|
+
* through — the plugin must stay usable in minimal profiles. A fence that
|
|
34
|
+
* *throws* is treated as a rejection: this is a security boundary, and failing
|
|
35
|
+
* open would silently undo it.
|
|
36
|
+
*/
|
|
37
|
+
export declare function rejectWebRequest(fence: ConnectionFence | undefined, headers: IncomingMessage['headers']): 401 | 403 | undefined;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Process-local registry of workspace candidate paths, bound by index.ts when
|
|
3
|
+
* the workspace registry becomes available. Kept in its own module so both
|
|
4
|
+
* the RPC helper and the snapshot route read one source without importing the
|
|
5
|
+
* web-server types.
|
|
6
|
+
* @module dsh-plugin-roundtable/workspace-candidates
|
|
7
|
+
*/
|
|
8
|
+
/** Bind the candidate list (call once from index.ts). */
|
|
9
|
+
export declare function setWorkspaceCandidates(next: {
|
|
10
|
+
title: string;
|
|
11
|
+
path: string;
|
|
12
|
+
}[]): void;
|
|
13
|
+
/** Current workspace candidates. */
|
|
14
|
+
export declare function workspaceCandidates(): readonly {
|
|
15
|
+
title: string;
|
|
16
|
+
path: string;
|
|
17
|
+
}[];
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
//#region src/workspace-candidates.ts
|
|
2
|
+
/**
|
|
3
|
+
* Process-local registry of workspace candidate paths, bound by index.ts when
|
|
4
|
+
* the workspace registry becomes available. Kept in its own module so both
|
|
5
|
+
* the RPC helper and the snapshot route read one source without importing the
|
|
6
|
+
* web-server types.
|
|
7
|
+
* @module dsh-plugin-roundtable/workspace-candidates
|
|
8
|
+
*/
|
|
9
|
+
let candidates = [];
|
|
10
|
+
/** Bind the candidate list (call once from index.ts). */
|
|
11
|
+
function setWorkspaceCandidates(next) {
|
|
12
|
+
candidates = next;
|
|
13
|
+
}
|
|
14
|
+
/** Current workspace candidates. */
|
|
15
|
+
function workspaceCandidates() {
|
|
16
|
+
return candidates;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
//#endregion
|
|
20
|
+
export { workspaceCandidates as n, setWorkspaceCandidates as t };
|
package/package.json
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@y9931666/dsh-plugin-roundtable",
|
|
3
|
+
"version": "1.0.0-rc.2",
|
|
4
|
+
"publishConfig": {
|
|
5
|
+
"access": "public",
|
|
6
|
+
"registry": "https://registry.npmjs.org/"
|
|
7
|
+
},
|
|
8
|
+
"description": "RoundTable for DeepSeek Harness: turn one session into a visualized round-table meeting — expert nodes on a ring, directed edges, an aggregation gateway, proxy thinking for black-box worker models, and a live topology tab in the web GUI. Includes 针锋相对 (adversarial review): red-team experts attack a settled plan and you endorse real flaws.",
|
|
9
|
+
"author": {
|
|
10
|
+
"name": "y9931666",
|
|
11
|
+
"url": "https://github.com/9931666"
|
|
12
|
+
},
|
|
13
|
+
"homepage": "https://github.com/9931666/dsh-plugin-roundtable#readme",
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "git+https://github.com/9931666/dsh-plugin-roundtable.git"
|
|
17
|
+
},
|
|
18
|
+
"bugs": {
|
|
19
|
+
"url": "https://github.com/9931666/dsh-plugin-roundtable/issues"
|
|
20
|
+
},
|
|
21
|
+
"keywords": [
|
|
22
|
+
"dsh",
|
|
23
|
+
"dsh-plugin",
|
|
24
|
+
"deepseek-harness",
|
|
25
|
+
"roundtable",
|
|
26
|
+
"multi-agent",
|
|
27
|
+
"debate",
|
|
28
|
+
"topology",
|
|
29
|
+
"proxy-thinking",
|
|
30
|
+
"adversarial-review",
|
|
31
|
+
"red-team"
|
|
32
|
+
],
|
|
33
|
+
"type": "module",
|
|
34
|
+
"license": "MIT",
|
|
35
|
+
"main": "./lib/index.js",
|
|
36
|
+
"types": "./lib/types/index.d.ts",
|
|
37
|
+
"exports": {
|
|
38
|
+
".": {
|
|
39
|
+
"types": "./lib/types/index.d.ts",
|
|
40
|
+
"default": "./lib/index.js"
|
|
41
|
+
},
|
|
42
|
+
"./client": {
|
|
43
|
+
"types": "./lib/types/client/index.d.ts",
|
|
44
|
+
"default": "./lib/client.js"
|
|
45
|
+
},
|
|
46
|
+
"./cordis.patch.yml": "./cordis.patch.yml",
|
|
47
|
+
"./package.json": "./package.json"
|
|
48
|
+
},
|
|
49
|
+
"files": [
|
|
50
|
+
"lib",
|
|
51
|
+
"cordis.patch.yml",
|
|
52
|
+
"release-notes",
|
|
53
|
+
"README.md"
|
|
54
|
+
],
|
|
55
|
+
"dsh": {
|
|
56
|
+
"bundle": {
|
|
57
|
+
"patch": "./cordis.patch.yml"
|
|
58
|
+
},
|
|
59
|
+
"client": {
|
|
60
|
+
"inject": [
|
|
61
|
+
"@deepseek-ai/dsh-client-connection",
|
|
62
|
+
"@deepseek-ai/dsh-client-locale",
|
|
63
|
+
"@deepseek-ai/dsh-client-ui-conversation",
|
|
64
|
+
"@deepseek-ai/dsh-client-ui-renderer",
|
|
65
|
+
"@deepseek-ai/dsh-client-ui-settings"
|
|
66
|
+
],
|
|
67
|
+
"platform": "web"
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
"roundtable": {
|
|
71
|
+
"hostBaseline": "0.2.0-rc.2"
|
|
72
|
+
},
|
|
73
|
+
"scripts": {
|
|
74
|
+
"typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.client.json --noEmit",
|
|
75
|
+
"test": "node --test test/",
|
|
76
|
+
"test:inline": "node --test --test-isolation=none \"test/*.test.mjs\"",
|
|
77
|
+
"prompt:budget": "node scripts/prompt-budget.mjs",
|
|
78
|
+
"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",
|
|
79
|
+
"bundle:client": "tsdown -c tsdown.config.ts",
|
|
80
|
+
"compatibility": "node scripts/compatibility.mjs",
|
|
81
|
+
"verify:package": "node scripts/verify-package.mjs",
|
|
82
|
+
"doctor": "node scripts/doctor.mjs",
|
|
83
|
+
"release": "node scripts/release.mjs",
|
|
84
|
+
"publish:guard": "node scripts/compatibility.mjs && node scripts/verify-package.mjs --strict && node scripts/release.mjs"
|
|
85
|
+
},
|
|
86
|
+
"peerDependencies": {
|
|
87
|
+
"@deepseek-ai/cordis": "^4.0.4",
|
|
88
|
+
"@deepseek-ai/schemastery": "^3.18.4",
|
|
89
|
+
"@deepseek-ai/dsh-agent": "^0.2.0-rc.2",
|
|
90
|
+
"@deepseek-ai/dsh-atomic-write": "^0.2.0-rc.2",
|
|
91
|
+
"@deepseek-ai/dsh-client-connection": "^0.2.0-rc.2",
|
|
92
|
+
"@deepseek-ai/dsh-client-locale": "^0.2.0-rc.2",
|
|
93
|
+
"@deepseek-ai/dsh-client-ui-conversation": "^0.2.0-rc.2",
|
|
94
|
+
"@deepseek-ai/dsh-client-ui-renderer": "^0.2.0-rc.2",
|
|
95
|
+
"@deepseek-ai/dsh-client-ui-settings": "^0.2.0-rc.2",
|
|
96
|
+
"@deepseek-ai/dsh-client-ui-tool": "^0.2.0-rc.2",
|
|
97
|
+
"@deepseek-ai/dsh-host-webserver": "^0.2.0-rc.2",
|
|
98
|
+
"@deepseek-ai/dsh-llm": "^0.2.0-rc.2",
|
|
99
|
+
"@deepseek-ai/dsh-session": "^0.2.0-rc.2",
|
|
100
|
+
"@deepseek-ai/dsh-skill": "^0.2.0-rc.2",
|
|
101
|
+
"@deepseek-ai/dsh-subagent": "^0.2.0-rc.2",
|
|
102
|
+
"@deepseek-ai/dsh-system-prompt": "^0.2.0-rc.2",
|
|
103
|
+
"@deepseek-ai/dsh-tools": "^0.2.0-rc.2",
|
|
104
|
+
"@deepseek-ai/dsh-user-questions": "^0.2.0-rc.2",
|
|
105
|
+
"@deepseek-ai/dsh-workspace": "^0.2.0-rc.2",
|
|
106
|
+
"react": "^18.2.0"
|
|
107
|
+
},
|
|
108
|
+
"peerDependenciesMeta": {
|
|
109
|
+
"@deepseek-ai/cordis": { "optional": true },
|
|
110
|
+
"@deepseek-ai/schemastery": { "optional": true },
|
|
111
|
+
"@deepseek-ai/dsh-agent": { "optional": true },
|
|
112
|
+
"@deepseek-ai/dsh-atomic-write": { "optional": true },
|
|
113
|
+
"@deepseek-ai/dsh-client-connection": { "optional": true },
|
|
114
|
+
"@deepseek-ai/dsh-client-locale": { "optional": true },
|
|
115
|
+
"@deepseek-ai/dsh-client-ui-conversation": { "optional": true },
|
|
116
|
+
"@deepseek-ai/dsh-client-ui-renderer": { "optional": true },
|
|
117
|
+
"@deepseek-ai/dsh-client-ui-settings": { "optional": true },
|
|
118
|
+
"@deepseek-ai/dsh-client-ui-tool": { "optional": true },
|
|
119
|
+
"@deepseek-ai/dsh-host-webserver": { "optional": true },
|
|
120
|
+
"@deepseek-ai/dsh-llm": { "optional": true },
|
|
121
|
+
"@deepseek-ai/dsh-session": { "optional": true },
|
|
122
|
+
"@deepseek-ai/dsh-skill": { "optional": true },
|
|
123
|
+
"@deepseek-ai/dsh-subagent": { "optional": true },
|
|
124
|
+
"@deepseek-ai/dsh-system-prompt": { "optional": true },
|
|
125
|
+
"@deepseek-ai/dsh-tools": { "optional": true },
|
|
126
|
+
"@deepseek-ai/dsh-user-questions": { "optional": true },
|
|
127
|
+
"@deepseek-ai/dsh-workspace": { "optional": true },
|
|
128
|
+
"react": { "optional": true }
|
|
129
|
+
},
|
|
130
|
+
"devDependencies": {
|
|
131
|
+
"@deepseek-ai/cordis": "4.0.4",
|
|
132
|
+
"@deepseek-ai/schemastery": "3.18.4",
|
|
133
|
+
"@deepseek-ai/dsh-agent": "0.2.0-rc.2",
|
|
134
|
+
"@deepseek-ai/dsh-atomic-write": "0.2.0-rc.2",
|
|
135
|
+
"@deepseek-ai/dsh-client-connection": "0.2.0-rc.2",
|
|
136
|
+
"@deepseek-ai/dsh-client-locale": "0.2.0-rc.2",
|
|
137
|
+
"@deepseek-ai/dsh-client-ui-conversation": "0.2.0-rc.2",
|
|
138
|
+
"@deepseek-ai/dsh-client-ui-renderer": "0.2.0-rc.2",
|
|
139
|
+
"@deepseek-ai/dsh-client-ui-settings": "0.2.0-rc.2",
|
|
140
|
+
"@deepseek-ai/dsh-client-ui-tool": "0.2.0-rc.2",
|
|
141
|
+
"@deepseek-ai/dsh-host-webserver": "0.2.0-rc.2",
|
|
142
|
+
"@deepseek-ai/dsh-llm": "0.2.0-rc.2",
|
|
143
|
+
"@deepseek-ai/dsh-session": "0.2.0-rc.2",
|
|
144
|
+
"@deepseek-ai/dsh-skill": "0.2.0-rc.2",
|
|
145
|
+
"@deepseek-ai/dsh-subagent": "0.2.0-rc.2",
|
|
146
|
+
"@deepseek-ai/dsh-system-prompt": "0.2.0-rc.2",
|
|
147
|
+
"@deepseek-ai/dsh-tools": "0.2.0-rc.2",
|
|
148
|
+
"@deepseek-ai/dsh-user-questions": "0.2.0-rc.2",
|
|
149
|
+
"@deepseek-ai/dsh-workspace": "0.2.0-rc.2",
|
|
150
|
+
"@types/node": "^22.0.0",
|
|
151
|
+
"@types/react": "~18.3.1",
|
|
152
|
+
"@types/react-dom": "^18.3.7",
|
|
153
|
+
"react": "^18.2.0",
|
|
154
|
+
"react-dom": "^18.2.0",
|
|
155
|
+
"tsdown": "^0.15.0",
|
|
156
|
+
"typescript": "^5.9.0"
|
|
157
|
+
},
|
|
158
|
+
"engines": {
|
|
159
|
+
"node": ">=22.0.0"
|
|
160
|
+
}
|
|
161
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# RoundTable v0.2.0
|
|
2
|
+
|
|
3
|
+
可视化圆桌会议插件正式版:**主持人 + 一圈专家 + 汇聚网关**,加上「针锋相对」红队评审。
|
|
4
|
+
|
|
5
|
+
## 新增(V0.2 主线)
|
|
6
|
+
|
|
7
|
+
- **专家管理界面**:右栏「+」加/删专家、模型下拉选厂商(DeepSeek / GLM / 千问 / Kimi / MiniMax…);改动记入 `user-actions.jsonl`,主持人下一轮自动执行,UI 与主持人认知同步。
|
|
8
|
+
- **厂商 Logo 头像**:DeepSeek / GLM / Gemini / Claude / Kimi / MiniMax 真实 Logo(base64 内联、离线可用)。
|
|
9
|
+
- **知识库(阅览版)**:填路径即列文件;主持人按需读取转交,避免 Token 双倍消耗。
|
|
10
|
+
- **回答限制**:专家每轮输出上限 + 最多意见数,会议更省 Token。
|
|
11
|
+
- **会议删除**:一键删会议(确认 + 磁盘彻底删除 + 连带清理子代理)。
|
|
12
|
+
- **互通开关**:只看当前对话会议 / 看全部。
|
|
13
|
+
- **代码收尾**:全量审查清理死代码(host bundle 84.1→80.5 kB),行为不变。
|
|
14
|
+
|
|
15
|
+
## 新增(V0.2.1 针锋相对评审)
|
|
16
|
+
|
|
17
|
+
- **红队评审流程**:用户与主持人定下方案后,主持人发起「针锋相对」→ 红队专家只挑毛病 → 评审弹窗(左=问题+方案、右=观点列表)→ 用户点「支持」认定真实缺陷 → 缺陷进入下一轮方案修改。
|
|
18
|
+
- 评审记录独立存储(`review.json`)、快照自动弹出评审窗口、标题区 badge + 右栏「分针记录」面板。
|
|
19
|
+
- 被删除的专家从拓扑图彻底移除(含连线)。
|
|
20
|
+
|
|
21
|
+
## 新增(V0.2.2 下一迭代)
|
|
22
|
+
|
|
23
|
+
- **观点拆分**:专家发言由 LLM 自动拆成 1~3 条独立观点(JSON schema 约束 + 解析失败整条兜底 + quote 原文校验),支持单条「支持」。
|
|
24
|
+
- **三态表态**:每个观点 支持 / 驳回 / 取消 互切(`review.setStatus`,旧接口兼容);已认定数只计「支持」。
|
|
25
|
+
- **「针锋相对」协作模式**:设置「默认协作模式」新增第三项,charter 自动附加红队评审协议。
|
|
26
|
+
- **健壮性**:进行中的评审禁止静默覆盖;用户表态回写升级为结构化行 id;专家列表已退出置底、快照按 key 去重防同名残留。
|
|
27
|
+
|
|
28
|
+
## 安装
|
|
29
|
+
|
|
30
|
+
```sh
|
|
31
|
+
dsh plugin --profile web add @huanlin/dsh-plugin-roundtable
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
或从源码:`git clone https://github.com/9931666/dsh-plugin-roundtable && cd dsh-plugin-roundtable && pnpm install && pnpm build && dsh plugin --profile web add .`
|
|
35
|
+
|
|
36
|
+
## 已知限制
|
|
37
|
+
|
|
38
|
+
- 专家子代理默认路由(`spawn`)依赖宿主可用的 LLM 路由;跨厂商专家需在加人时显式指定 provider/model。
|
|
39
|
+
- 状态为文件级持久化,多进程同时改同一会议不保证一致。
|