dsh-vscode-mode 0.1.19 → 0.1.21
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 +17 -7
- package/lib/client.js +1649 -272
- package/lib/client.js.map +1 -1
- package/lib/index.js +87 -0
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
- package/src/client/diffDock.ts +52 -0
- package/src/client/diffDockStore.ts +87 -0
- package/src/client/editorLayout.ts +19 -0
- package/src/client/events.ts +40 -11
- package/src/client/index.ts +49 -13
- package/src/client/outline/OutlinePanel.tsx +213 -0
- package/src/client/outline/index.ts +24 -0
- package/src/client/outline/parse.ts +271 -0
- package/src/client/outline/sources.ts +134 -0
- package/src/client/outline/types.ts +51 -0
- package/src/client/sidebar/SidebarView.ts +73 -0
- package/src/client/sidebar/panels/FileExplorer.ts +161 -0
- package/src/client/sidebar/panels/index.ts +24 -0
- package/src/client/sidebar/registry.ts +52 -0
- package/src/client/sidebar/types.ts +36 -0
- package/src/client/styles/editor.css +130 -5
- package/src/client/ui/ConversationDiffDock.ts +84 -0
- package/src/client/ui/DiffBox.ts +78 -29
- package/src/client/ui/EditorView.ts +209 -52
- package/src/rpc.ts +21 -0
- package/src/shared/rpc.ts +10 -0
- package/src/tree.ts +62 -0
package/lib/index.js
CHANGED
|
@@ -2405,6 +2405,52 @@ async function projectRefresh(ctx, workspacePath, serverName) {
|
|
|
2405
2405
|
return projectOf(ctx, workspacePath, workspace.title ?? "");
|
|
2406
2406
|
}
|
|
2407
2407
|
//#endregion
|
|
2408
|
+
//#region src/tree.ts
|
|
2409
|
+
/** 目录在文件前、名称按小写字母序的比较器(对齐 VSCode 资源管理器习惯)。 */
|
|
2410
|
+
function entryOrder(a, b) {
|
|
2411
|
+
const aDir = a.type === "directory" ? 0 : 1;
|
|
2412
|
+
const bDir = b.type === "directory" ? 0 : 1;
|
|
2413
|
+
if (aDir !== bDir) return aDir - bDir;
|
|
2414
|
+
const la = a.name.toLocaleLowerCase("en-US");
|
|
2415
|
+
const lb = b.name.toLocaleLowerCase("en-US");
|
|
2416
|
+
return la < lb ? -1 : la > lb ? 1 : 0;
|
|
2417
|
+
}
|
|
2418
|
+
/**
|
|
2419
|
+
* 归一化目录相对路径:去空白、反斜杠→斜杠、去首尾斜杠、`.`→''。
|
|
2420
|
+
* 任一路径段为 `..` 返回 null(拒绝越界)。
|
|
2421
|
+
* @author ddj 2026年08月26号
|
|
2422
|
+
* @param path 原始相对路径('' 表示根目录)
|
|
2423
|
+
* @returns 归一化相对路径('' = 根),非法返回 null
|
|
2424
|
+
*/
|
|
2425
|
+
function normalizeRel(path) {
|
|
2426
|
+
const rel = String(path ?? "").trim().replace(/\\/g, "/").replace(/^\/+|\/+$/g, "");
|
|
2427
|
+
if (!rel) return "";
|
|
2428
|
+
const segs = rel.split("/").filter((seg) => seg !== ".");
|
|
2429
|
+
if (!segs.length) return "";
|
|
2430
|
+
for (const seg of segs) if (seg === "..") return null;
|
|
2431
|
+
return segs.join("/");
|
|
2432
|
+
}
|
|
2433
|
+
/**
|
|
2434
|
+
* fs.listDir 结果 → TreeEntry 数组:相对路径拼接 + 目录优先排序。
|
|
2435
|
+
* @author ddj 2026年08月26号
|
|
2436
|
+
* @param rel 父目录相对路径('' = 根)
|
|
2437
|
+
* @param children 目录子项
|
|
2438
|
+
* @returns 排序后的树条目
|
|
2439
|
+
*/
|
|
2440
|
+
function toTreeEntries(rel, children) {
|
|
2441
|
+
const out = [];
|
|
2442
|
+
for (const child of children) {
|
|
2443
|
+
if (!child || typeof child.name !== "string" || !child.name) continue;
|
|
2444
|
+
out.push({
|
|
2445
|
+
name: child.name,
|
|
2446
|
+
path: rel ? rel + "/" + child.name : child.name,
|
|
2447
|
+
type: child.type === "directory" ? "directory" : child.type === "file" ? "file" : "other",
|
|
2448
|
+
size: typeof child.size === "number" ? child.size : void 0
|
|
2449
|
+
});
|
|
2450
|
+
}
|
|
2451
|
+
return out.sort(entryOrder);
|
|
2452
|
+
}
|
|
2453
|
+
//#endregion
|
|
2408
2454
|
//#region src/rpc.ts
|
|
2409
2455
|
/** cwd → Promise 链:串行化 debug 日志追加(fs read+write 非原子,避免并发丢行)。 */
|
|
2410
2456
|
const debugWriteQueues = /* @__PURE__ */ new Map();
|
|
@@ -2838,6 +2884,47 @@ function buildHandlers(ctx, registry, searcher = newSearcher(ctx)) {
|
|
|
2838
2884
|
})
|
|
2839
2885
|
};
|
|
2840
2886
|
},
|
|
2887
|
+
"edrv.listDir": async (args) => {
|
|
2888
|
+
const sc = await requireSession(ctx, args.sessionId);
|
|
2889
|
+
if ("err" in sc) return {
|
|
2890
|
+
ok: false,
|
|
2891
|
+
error: sc.err
|
|
2892
|
+
};
|
|
2893
|
+
const fs = ctx.get("fs");
|
|
2894
|
+
if (!fs) return {
|
|
2895
|
+
ok: false,
|
|
2896
|
+
error: "缺少 fs"
|
|
2897
|
+
};
|
|
2898
|
+
try {
|
|
2899
|
+
const rel = normalizeRel(args.path);
|
|
2900
|
+
if (rel === null) return {
|
|
2901
|
+
ok: false,
|
|
2902
|
+
error: "路径不合法"
|
|
2903
|
+
};
|
|
2904
|
+
const target = await resolveTarget(ctx, sc.session, rel || ".");
|
|
2905
|
+
const info = await fs.stat(target);
|
|
2906
|
+
if (!info) return {
|
|
2907
|
+
ok: false,
|
|
2908
|
+
error: "目录不存在"
|
|
2909
|
+
};
|
|
2910
|
+
if (info.type !== "directory") return {
|
|
2911
|
+
ok: false,
|
|
2912
|
+
error: "不是目录"
|
|
2913
|
+
};
|
|
2914
|
+
const children = await fs.listDir(target);
|
|
2915
|
+
return {
|
|
2916
|
+
ok: true,
|
|
2917
|
+
root: fs.processPath(await fs.resolve(".", { cwd: sc.cwd })),
|
|
2918
|
+
path: rel,
|
|
2919
|
+
entries: toTreeEntries(rel, children)
|
|
2920
|
+
};
|
|
2921
|
+
} catch (error) {
|
|
2922
|
+
return {
|
|
2923
|
+
ok: false,
|
|
2924
|
+
error: "读取目录失败:" + String(error)
|
|
2925
|
+
};
|
|
2926
|
+
}
|
|
2927
|
+
},
|
|
2841
2928
|
"mcp.list": async () => ({
|
|
2842
2929
|
ok: true,
|
|
2843
2930
|
...listMcp(ctx)
|