dsh-vscode-mode 0.23.0 → 0.23.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/README.md +5 -3
- package/lib/client.js +17 -23
- package/lib/client.js.map +2 -2
- package/lib/index.js +42 -0
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
- package/src/client/reviewBatch.ts +17 -21
- package/src/client/ui/EditorView.ts +5 -1
- package/src/reviewRpc.ts +40 -0
- package/src/shared/rpc.ts +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-vscode-mode",
|
|
3
|
-
"version": "0.23.
|
|
3
|
+
"version": "0.23.1",
|
|
4
4
|
"description": "DSH 上的类 VSCode 编码体验:Monaco 编辑器(文件页签/QuickOpen/状态栏,可驻 DSH 0.1.5+ 官方右侧 Sidebar 与对话同屏)+ 命令栏(Ctrl+Shift+P)与可扩展指令系统 + VS Code 兼容代码片段(.code-snippets 全局/项目,IntelliSense 展开)+ Agent 编辑差异审查(整文件差异/采纳/拒绝/归档/回滚)+ SVN 集成(侧栏变更面板/日志弹窗/并排差异)+ 语言服务器(LSP)智能(跳转定义/引用/hover/大纲 + VSIX 扩展市场安装),状态持久化到工作区旁车,界面状态(页签/光标/侧栏/编辑 Tab/导航历史)镜像到 DSH home 跨重启恢复",
|
|
5
5
|
"icon": "assets/icon.svg",
|
|
6
6
|
"keywords": [
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import type { ReviewDetail, ReviewItem, ReviewPage, ReviewResult } from '../shared/review.js'
|
|
3
3
|
|
|
4
4
|
export interface BatchPort {
|
|
5
|
-
|
|
5
|
+
snapshot: () => Promise<ReviewPage>
|
|
6
6
|
detail: (id: string) => Promise<ReviewDetail>
|
|
7
7
|
decide: (detail: ReviewDetail, reject: boolean, operationId: string) => Promise<ReviewResult<{ revision: number }>>
|
|
8
8
|
guard: () => void
|
|
@@ -10,27 +10,23 @@ export interface BatchPort {
|
|
|
10
10
|
}
|
|
11
11
|
export interface BatchResult { completed: number; total: number; paths: string[]; error: string }
|
|
12
12
|
|
|
13
|
-
/**
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
/**
|
|
14
|
+
* @public
|
|
15
|
+
* @author ddj 2026年10月31号
|
|
16
|
+
* @description: 取一次完整待审快照。分页计数只用于展示,批量写入必须一次取全,避免把页内数字当成总数。
|
|
17
|
+
* @param port 已鉴权的 RPC 适配器
|
|
18
|
+
* @returns 冻结的完整待审集;任何不一致都在首个写入前中止
|
|
19
|
+
* @throws 快照重复、版本已变或数量不完整
|
|
20
|
+
*/
|
|
21
|
+
export async function loadPending(port: Pick<BatchPort, 'snapshot'>): Promise<ReviewItem[]> {
|
|
22
|
+
const page = await port.snapshot()
|
|
16
23
|
const seen = new Set<string>()
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
if (page.pending !== expected) throw new Error('待审记录在分页期间变化,请刷新后重试')
|
|
24
|
-
for (const item of page.items) {
|
|
25
|
-
if (seen.has(item.id) || !item.current || item.decision !== 'pending') throw new Error('待审分页发生重复或版本变化,请刷新后重试')
|
|
26
|
-
seen.add(item.id); items.push(item)
|
|
27
|
-
}
|
|
28
|
-
if (page.nextCursor === null) break
|
|
29
|
-
if (cursors.has(page.nextCursor) || page.items.length === 0) throw new Error('待审分页未完整返回,请刷新后重试')
|
|
30
|
-
cursor = page.nextCursor; cursors.add(cursor)
|
|
31
|
-
} while (true)
|
|
32
|
-
if (items.length !== expected) throw new Error('待审记录数量不完整,未执行批量操作')
|
|
33
|
-
return items
|
|
24
|
+
for (const item of page.items) {
|
|
25
|
+
if (seen.has(item.id) || !item.current || item.decision !== 'pending') throw new Error('待审快照发生重复或版本变化,请刷新后重试')
|
|
26
|
+
seen.add(item.id)
|
|
27
|
+
}
|
|
28
|
+
if (page.nextCursor !== null || page.items.length !== page.pending) throw new Error('待审记录数量不完整,未执行批量操作')
|
|
29
|
+
return page.items
|
|
34
30
|
}
|
|
35
31
|
|
|
36
32
|
/** @public @author ddj 2026年10月27号 @param port Guarded existing per-file decision adapter. @param reject Undo instead of Keep. @returns Precise partial result; Undo stops at first conflict, never claims atomic multi-file rollback. */
|
|
@@ -3479,7 +3479,11 @@ export function EditorView(props) {
|
|
|
3479
3479
|
setStatus(reject ? '正在检查并 Undo 全部待审记录…' : '正在 Keep 全部待审记录…')
|
|
3480
3480
|
try {
|
|
3481
3481
|
const result = await runReviewBatch({
|
|
3482
|
-
|
|
3482
|
+
snapshot: async () => {
|
|
3483
|
+
const res = await rpc('edrv.review.list', { sessionId, all: true })
|
|
3484
|
+
if (!res.ok) throw new Error(res.error)
|
|
3485
|
+
return res.page
|
|
3486
|
+
},
|
|
3483
3487
|
detail: async (id) => { const res = await rpc('edrv.review.detail', { sessionId, id }); if (!res.ok) throw new Error(res.error); return res.detail },
|
|
3484
3488
|
decide: (detail, undo, operationId) => rpc('edrv.review.decide', { sessionId, id: detail.item.id, seq: detail.item.seq, revision: detail.item.revision, operationId, scope: 'file', decision: undo ? 'rejected' : 'accepted' }),
|
|
3485
3489
|
guard: () => guardReviewAll(reject, token), operation: batchOperation,
|
package/src/reviewRpc.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/** Session-scoped official review RPC. @author ddj 2026年10月26号 */
|
|
2
2
|
import type { RpcHandlerMap } from './shared/rpc.js'
|
|
3
|
+
import type { ReviewItem, ReviewPage } from './shared/review.js'
|
|
3
4
|
import type { PendingPage } from './shared/pendingReview.js'
|
|
4
5
|
import { decideReview, reviewDetail, reviewPage } from './reviewDb.js'
|
|
5
6
|
import { undoReview } from './reviewUndo.js'
|
|
@@ -9,6 +10,41 @@ import { bucketOf, resolveScope, sessionOf } from './registry.js'
|
|
|
9
10
|
import type { Registry } from './registry.js'
|
|
10
11
|
import type { Ctx } from './store.js'
|
|
11
12
|
|
|
13
|
+
/** 批量写入快照的硬上限:待审积压超过它说明状态异常,宁可拒绝也不做无界写循环。 */
|
|
14
|
+
const BATCH_LIMIT = 2000
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @private
|
|
18
|
+
* @author ddj 2026年10月31号
|
|
19
|
+
* @description: 批量写入用的一次性完整快照。合并口径与列表一致(待审投影优先、同路径官方旧行让位),
|
|
20
|
+
* 但一次取全,且 items 与 pending 同源,客户端才能把它当成写前不变式。
|
|
21
|
+
* @param cwd 工作区
|
|
22
|
+
* @param pending 该会话可见的待审页
|
|
23
|
+
* @returns 完整快照;待审积压超过上限或分页期间数量漂移时返回错误
|
|
24
|
+
*/
|
|
25
|
+
function batchSnapshot(cwd: string, pending: PendingPage): { ok: true; page: ReviewPage } | { ok: false; error: string } {
|
|
26
|
+
const first = reviewPage(cwd)
|
|
27
|
+
if (first.pending > BATCH_LIMIT) return { ok: false, error: `待审记录过多(${first.pending} 条,上限 ${BATCH_LIMIT}),请先分批处理后重试` }
|
|
28
|
+
|
|
29
|
+
const official: ReviewItem[] = []
|
|
30
|
+
let page: ReviewPage | undefined = first
|
|
31
|
+
while (page) {
|
|
32
|
+
for (const item of page.items) if (item.current && item.decision === 'pending') official.push(item)
|
|
33
|
+
page = page.nextCursor === null ? undefined : reviewPage(cwd, page.nextCursor)
|
|
34
|
+
}
|
|
35
|
+
// 分页期间有记录被判定掉:数量对不上就不给客户端一份半截快照
|
|
36
|
+
if (official.length !== first.pending) return { ok: false, error: '待审记录数量不完整,未执行批量操作' }
|
|
37
|
+
|
|
38
|
+
// 待审投影已接管的路径,官方旧行必须让位,否则同一文件会被批量写两次
|
|
39
|
+
const live = pending.items.filter((item) => !item.settled)
|
|
40
|
+
const kept = official.filter((row) => !live.some((entry) => pendingSamePath(entry.path, row.currentPath) || pendingSamePath(entry.path, row.path)))
|
|
41
|
+
const items = [...live.map((entry) => pendingItemOf(entry, cwd)), ...kept]
|
|
42
|
+
return {
|
|
43
|
+
ok: true,
|
|
44
|
+
page: { items, pending: items.length, nextCursor: null, gaps: first.gaps, ...(first.overview ? { overview: first.overview } : {}) },
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
12
48
|
/**
|
|
13
49
|
* @public
|
|
14
50
|
* @author ddj 2026年10月26号 / 2026年10月28号
|
|
@@ -52,6 +88,10 @@ export function reviewHandlers(ctx: Ctx, registry: Registry): Partial<RpcHandler
|
|
|
52
88
|
return {
|
|
53
89
|
'edrv.review.list': async (args) => {
|
|
54
90
|
const cwd = await workspace(args.sessionId)
|
|
91
|
+
// 批量通道要的是一次性完整快照:分页口径的 pending 只是页内展示计数,不能当完整性不变式
|
|
92
|
+
if (args.all && !args.history && args.path === undefined) {
|
|
93
|
+
return batchSnapshot(cwd, pendingPageOf(cwd, args.sessionId))
|
|
94
|
+
}
|
|
55
95
|
const official = reviewPage(cwd, args.cursor, args.history, args.path)
|
|
56
96
|
const pending = pendingPageOf(cwd, args.sessionId)
|
|
57
97
|
// 历史快照只属于官方通道;待审条目没有轮次历史,混进去会造出假的「轮次 0」。
|
package/src/shared/rpc.ts
CHANGED
|
@@ -375,7 +375,7 @@ export interface UiStatePatchInput {
|
|
|
375
375
|
|
|
376
376
|
/** 每个方法的请求参数(sessionId 为公共可选字段)。 */
|
|
377
377
|
export interface RpcRequestMap {
|
|
378
|
-
'edrv.review.list': ReviewRequest & { cursor?: number; history?: boolean; path?: string }
|
|
378
|
+
'edrv.review.list': ReviewRequest & { cursor?: number; history?: boolean; path?: string; all?: boolean }
|
|
379
379
|
'edrv.review.detail': ReviewRequest & { id: string }
|
|
380
380
|
'edrv.review.decide': DecideReview
|
|
381
381
|
'edrv.pending.list': PendingRequest
|