dsh-vscode-mode 0.1.10 → 0.1.12
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 +12 -0
- package/lib/client.js +537 -54
- package/lib/client.js.map +1 -1
- package/lib/index.js +1003 -94
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
- package/src/capture.ts +44 -8
- package/src/client/index.ts +11 -2
- package/src/client/monaco/diffRender.ts +1 -1
- package/src/client/state/records.ts +5 -2
- package/src/client/state/regions.ts +26 -20
- package/src/client/styles/mcp.css +87 -0
- package/src/client/ui/DiffBox.ts +1 -0
- package/src/client/ui/McpSettings.ts +233 -0
- package/src/index.ts +4 -2
- package/src/mcp.ts +123 -0
- package/src/mcpIsolation.ts +160 -0
- package/src/mcpProject.ts +258 -0
- package/src/model.ts +66 -34
- package/src/revert.ts +10 -3
- package/src/rpc.ts +44 -0
- package/src/shared/diff.ts +201 -0
- package/src/shared/mcp.ts +53 -0
- package/src/shared/rpc.ts +21 -0
- package/src/shared/types.ts +15 -0
- package/src/store.ts +29 -31
package/src/store.ts
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
* 作者 ddj 2026-08-20
|
|
5
5
|
*/
|
|
6
6
|
import type { ArchiveBatch, ArchiveData, DiffRecord, SidecarData } from './shared/types.js'
|
|
7
|
+
import type { ReadState } from './shared/diff.js'
|
|
8
|
+
import { fingerprint, isNoopHunk, locateHunks, preciseHunk } from './shared/diff.js'
|
|
7
9
|
import { archiveEntryFor, groupByBatch, normalizeRecord } from './model.js'
|
|
8
10
|
|
|
9
11
|
export const SIDECAR = '.dsh-edit-review.json'
|
|
@@ -105,21 +107,23 @@ export async function saveBucket(ctx: Ctx, cwd: string, recsMap: Map<string, Dif
|
|
|
105
107
|
* @author ddj 2026年08月20号
|
|
106
108
|
* @param cache path → 内容(null=缺失/读取失败,''=过大跳过)
|
|
107
109
|
*/
|
|
108
|
-
export async function readForCache(ctx: Ctx, session: Session, cache: Map<string,
|
|
109
|
-
|
|
110
|
+
export async function readForCache(ctx: Ctx, session: Session, cache: Map<string, ReadState>, path: string): Promise<ReadState> {
|
|
111
|
+
const cached = cache.get(path)
|
|
112
|
+
if (cached) return cached
|
|
110
113
|
const fs = ctx.get('fs')
|
|
111
|
-
if (!fs) { cache.set(path,
|
|
114
|
+
if (!fs) { const state: ReadState = { kind: 'unavailable' }; cache.set(path, state); return state }
|
|
112
115
|
try {
|
|
113
116
|
const target = await resolveTarget(ctx, session, path)
|
|
114
117
|
const info = await fs.stat(target)
|
|
115
|
-
if (!info || info.type !== 'file') { cache.set(path,
|
|
116
|
-
if ((info.size ?? 0) > READ_CAP) { cache.set(path,
|
|
117
|
-
const
|
|
118
|
-
cache.set(path,
|
|
119
|
-
return
|
|
118
|
+
if (!info || info.type !== 'file') { const state: ReadState = { kind: 'missing' }; cache.set(path, state); return state }
|
|
119
|
+
if ((info.size ?? 0) > READ_CAP) { const state: ReadState = { kind: 'unavailable' }; cache.set(path, state); return state }
|
|
120
|
+
const state: ReadState = { kind: 'content', content: await fs.readText(target) }
|
|
121
|
+
cache.set(path, state)
|
|
122
|
+
return state
|
|
120
123
|
} catch (error) {
|
|
121
|
-
|
|
122
|
-
|
|
124
|
+
const state: ReadState = { kind: 'unavailable' }
|
|
125
|
+
cache.set(path, state)
|
|
126
|
+
return state
|
|
123
127
|
}
|
|
124
128
|
}
|
|
125
129
|
|
|
@@ -128,28 +132,22 @@ export async function readForCache(ctx: Ctx, session: Session, cache: Map<string
|
|
|
128
132
|
* 或新建文件已不存在,或全为空差异。满足则应由 host 自动归档。
|
|
129
133
|
* @author ddj 2026年08月20号
|
|
130
134
|
*/
|
|
131
|
-
export async function recordIsStale(ctx: Ctx, session: Session, cache: Map<string,
|
|
135
|
+
export async function recordIsStale(ctx: Ctx, session: Session, cache: Map<string, ReadState>, rec: DiffRecord): Promise<boolean> {
|
|
132
136
|
if (rec.superseded === true) return true
|
|
133
137
|
if (!Array.isArray(rec.hunks) || !rec.hunks.length) return true
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
if (oldText !== null && oldText === newText) continue
|
|
148
|
-
if (newText === null || newText === undefined) continue
|
|
149
|
-
const content = await readForCache(ctx, session, cache, rec.path)
|
|
150
|
-
if (content !== null && content.indexOf(newText) >= 0) { hasLocatablePending = true; break }
|
|
151
|
-
}
|
|
152
|
-
return !hasLocatablePending
|
|
138
|
+
const state = await readForCache(ctx, session, cache, rec.path)
|
|
139
|
+
if (state.kind === 'unavailable') return false
|
|
140
|
+
if (state.kind === 'missing') return true
|
|
141
|
+
if (rec.create === true) return false
|
|
142
|
+
const pending = rec.hunks.map((_, idx) => ({ idx, hunk: preciseHunk(rec, idx), status: rec.decisions.perHunk[idx] ?? rec.decisions.call }))
|
|
143
|
+
.filter((item) => item.status === 'pending' && item.hunk && !isNoopHunk(item.hunk))
|
|
144
|
+
if (!pending.length) return true
|
|
145
|
+
const currentFingerprint = fingerprint(state.content)
|
|
146
|
+
if (rec.afterFingerprint && currentFingerprint === rec.afterFingerprint) { rec.conflict = false; return false }
|
|
147
|
+
const locations = locateHunks(state.content, pending.map((item) => item.hunk!))
|
|
148
|
+
if (locations.some((location) => location.matched)) { rec.conflict = false; return false }
|
|
149
|
+
rec.conflict = true
|
|
150
|
+
return false
|
|
153
151
|
}
|
|
154
152
|
|
|
155
153
|
/**
|
|
@@ -161,7 +159,7 @@ export async function recordIsStale(ctx: Ctx, session: Session, cache: Map<strin
|
|
|
161
159
|
export async function autoArchiveStale(ctx: Ctx, session: Session, cwd: string, bucket: Map<string, DiffRecord>): Promise<number> {
|
|
162
160
|
const fs = ctx.get('fs')
|
|
163
161
|
if (!fs) return 0
|
|
164
|
-
const cache = new Map<string,
|
|
162
|
+
const cache = new Map<string, ReadState>()
|
|
165
163
|
const stale: DiffRecord[] = []
|
|
166
164
|
for (const rec of bucket.values()) {
|
|
167
165
|
if (rec.archived || rec.superseded === true) continue
|