@dsh-xhl/dsh-file-explorer 0.1.2 → 0.1.3

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 CHANGED
@@ -5,6 +5,8 @@
5
5
  ## 功能
6
6
 
7
7
  - **标题栏 ButtonGroup**(`conversation.session.header.utilities`):左侧按钮 + 右侧下拉(编辑器 / 文件夹 / VSCode)
8
+ - **Hero / 新建会话同样显示**:同一 ButtonGroup 通过框架通用浮层 `shell.overlay` 由插件自身定位到会话列右上角(hero 阶段显示,有记录后由标题栏图标接管,无重复);纯插件实现,不改动框架代码(详见 `docs/hero-filex-button.md`)
9
+ - **对话内点击文件 → 编辑器预览**:聊天里的文件路径链接(工具行、产物行、正文提及)默认用系统程序打开;插件拦截 `remote.session.openWorkspacePath` 与 `workspaces.openPath` 两条通道,改为在编辑器弹窗中预览(目录或 cwd 外的路径仍落回系统打开)
8
10
  - **编辑器**(默认):点击打开全屏文件预览 / 编辑弹窗(Ctrl+P 亦可)
9
11
  - **文件夹**:点击直接打开会话工作区所在的**系统文件夹**(Windows `explorer` / macOS `open` / Linux `xdg-open`)
10
12
  - **VSCode**:点击用 `code` 命令行在 **VS Code** 中打开会话工作区(自动探测安装位置 / PATH)
package/cordis.patch.yml CHANGED
@@ -1,8 +1,8 @@
1
- # dsh-file-explorer bundle patch
2
- #
3
- # 通过 bundle 通道挂载:
4
- # dsh plugin --profile <name> add @dsh-xhl/dsh-file-explorer@<version>
5
- # 或手动把 '@dsh-xhl/dsh-file-explorer' 加进 profile 的 dsh.profile.bundles 并 link 依赖。
6
- - insert:
7
- - id: dsh-file-explorer
8
- name: '@dsh-xhl/dsh-file-explorer'
1
+ # dsh-file-explorer bundle patch
2
+ #
3
+ # 通过 bundle 通道挂载:
4
+ # dsh plugin --profile <name> add @dsh-xhl/dsh-file-explorer@<version>
5
+ # 或手动把 '@dsh-xhl/dsh-file-explorer' 加进 profile 的 dsh.profile.bundles 并 link 依赖。
6
+ - insert:
7
+ - id: dsh-file-explorer
8
+ name: '@dsh-xhl/dsh-file-explorer'
package/lib/client.js CHANGED
@@ -37018,6 +37018,14 @@ window.__ModuleLoader__.load({
37018
37018
  .filex-group .filex-group-main{border-radius:8px 0 0 8px;padding:0 9px}
37019
37019
  .filex-group .filex-group-trigger{margin-left:-1px;border-radius:0 8px 8px 0;border-left:0;padding:0 7px}
37020
37020
 
37021
+ /* ── hero floating utility (shell.overlay entry) ─────────────────────── */
37022
+ /* The same ButtonGroup, pinned by the plugin to the conversation column's
37023
+ top-right while the column is in its hero phase. The shell.overlay layer
37024
+ is click-through by design, so the entry opts back into pointer events;
37025
+ no explicit z-index keeps it below sibling overlay entries (modal,
37026
+ notices) and any body-portaled popup. */
37027
+ .filex-hero-fab{position:fixed;pointer-events:auto}
37028
+
37021
37029
  /* ── transient notice strip ──────────────────────────────────────────── */
37022
37030
  .filex-notice{position:fixed;left:50%;bottom:24px;transform:translateX(-50%);z-index:2147483003;display:flex;align-items:center;gap:10px;max-width:70vw;padding:9px 14px;font:12px/1.5 ui-monospace,SFMono-Regular,Menlo,monospace;color:var(--dsw-alias-state-warn-primary,#f59e0b);background:var(--dsw-alias-bg-layer-2,#1b1b22);border:1px solid rgba(245,158,11,.5);border-radius:10px;box-shadow:0 8px 28px rgba(0,0,0,.45);pointer-events:auto}
37023
37031
  .filex-notice-btn{border:0;background:transparent;color:inherit;cursor:pointer;font-size:14px;line-height:1;padding:2px 4px;opacity:.7;flex-shrink:0}
@@ -37946,16 +37954,70 @@ window.__ModuleLoader__.load({
37946
37954
  * @returns the disposer restoring the original method (HMR-safe).
37947
37955
  */
37948
37956
  function wrapOpenPath(workspaces, deps) {
37957
+ const descriptor = Object.getOwnPropertyDescriptor(workspaces, "openPath");
37949
37958
  const original = workspaces.openPath;
37950
- workspaces.openPath = async (path) => {
37959
+ const wrapped = async (path) => {
37951
37960
  const sessionId = deps.currentSessionId();
37952
37961
  if (sessionId !== void 0) {
37953
37962
  if (await deps.openInEditor(path, sessionId)) return;
37954
37963
  }
37955
37964
  return original.call(workspaces, path);
37956
37965
  };
37966
+ Object.defineProperty(workspaces, "openPath", {
37967
+ configurable: true,
37968
+ enumerable: descriptor?.enumerable ?? true,
37969
+ writable: false,
37970
+ value: wrapped
37971
+ });
37957
37972
  return () => {
37958
- workspaces.openPath = original;
37973
+ if (descriptor !== void 0) Object.defineProperty(workspaces, "openPath", descriptor);
37974
+ else {
37975
+ delete workspaces.openPath;
37976
+ workspaces.openPath = original;
37977
+ }
37978
+ };
37979
+ }
37980
+ /**
37981
+ * Wrap `remote.session.openWorkspacePath` — the chat file-open funnel in
37982
+ * current runtimes (ui-chat's `ChatView` calls it for tool-row path links,
37983
+ * the produced-files row, and prose file mentions alike). Intercepted opens
37984
+ * go to the explorer modal and resolve as a successful open (the caller only
37985
+ * checks `ok`); anything that declines falls through to the original RPC,
37986
+ * which opens the path with the Host OS default application.
37987
+ *
37988
+ * The generated remote face exposes `openWorkspacePath` as an own accessor
37989
+ * (getter without setter), so a plain assignment silently fails — the
37990
+ * property is redefined instead, and the original descriptor is restored on
37991
+ * disposal (HMR-safe).
37992
+ * @param service - the `remote.session` face to wrap.
37993
+ * @param deps - per-call takeover decisions (same as {@link wrapOpenPath}).
37994
+ * @returns the disposer restoring the original method (HMR-safe).
37995
+ */
37996
+ function wrapOpenWorkspacePath(service, deps) {
37997
+ const descriptor = Object.getOwnPropertyDescriptor(service, "openWorkspacePath");
37998
+ const original = service.openWorkspacePath;
37999
+ const wrapped = async (input) => {
38000
+ const sessionId = deps.currentSessionId();
38001
+ if (sessionId !== void 0) {
38002
+ if (await deps.openInEditor(input.path, sessionId)) return {
38003
+ ok: true,
38004
+ value: { opened: true }
38005
+ };
38006
+ }
38007
+ return original.call(service, input);
38008
+ };
38009
+ Object.defineProperty(service, "openWorkspacePath", {
38010
+ configurable: true,
38011
+ enumerable: descriptor?.enumerable ?? true,
38012
+ writable: false,
38013
+ value: wrapped
38014
+ });
38015
+ return () => {
38016
+ if (descriptor !== void 0) Object.defineProperty(service, "openWorkspacePath", descriptor);
38017
+ else {
38018
+ delete service.openWorkspacePath;
38019
+ service.openWorkspacePath = original;
38020
+ }
37959
38021
  };
37960
38022
  }
37961
38023
  //#endregion
@@ -37973,6 +38035,15 @@ window.__ModuleLoader__.load({
37973
38035
  * new default mode and immediately runs that mode's open action. The choice
37974
38036
  * is persisted in localStorage so it survives reloads.
37975
38037
  *
38038
+ * The same ButtonGroup is also shown on the new-session screen through the
38039
+ * generic `shell.overlay` floating layer (no shell change involved): a
38040
+ * plugin-owned entry pins it to the conversation column's top-right while
38041
+ * the column is in its hero phase — the no-session hero and the
38042
+ * blank-session (new chat) hero, where the session header and its utilities
38043
+ * seat are absent or deliberately hidden. The floating entry resolves its
38044
+ * session itself: the actions fall back to the live selection
38045
+ * (`useSessions` → `state.current`) and show a notice when none exists.
38046
+ *
37976
38047
  * Session binding: every /filex request is conversation-scoped, so the modal
37977
38048
  * must know WHICH session it belongs to — the host resolves the workspace
37978
38049
  * from `session.header.cwd`, never from a global setting. The slot supplies
@@ -37983,7 +38054,9 @@ window.__ModuleLoader__.load({
37983
38054
  const inject = [
37984
38055
  "slots",
37985
38056
  "sessions",
37986
- "workspaces"
38057
+ "workspaces",
38058
+ "remote",
38059
+ "remote.session"
37987
38060
  ];
37988
38061
  const MODE_STORAGE_KEY = "dsh-file-explorer.header-mode";
37989
38062
  /** Read the persisted mode; anything unknown defaults to the editor. */
@@ -38079,7 +38152,7 @@ window.__ModuleLoader__.load({
38079
38152
  function openExplorer(sessionId, path) {
38080
38153
  const resolved = sessionId !== void 0 && sessionId !== "" ? sessionId : activeSessionId;
38081
38154
  if (resolved === void 0) {
38082
- showNotice("没有可用的会话:无法确定文件工作区。请先新建/选择一个会话,再从该会话标题栏的按钮打开。");
38155
+ showNotice("没有可用的会话:无法确定文件工作区。请先新建/选择一个会话。");
38083
38156
  return;
38084
38157
  }
38085
38158
  store = {
@@ -38246,6 +38319,58 @@ window.__ModuleLoader__.load({
38246
38319
  })
38247
38320
  });
38248
38321
  }
38322
+ /**
38323
+ * Hero / new-session floating utility: the same HeaderGroup, rendered by the
38324
+ * plugin itself through the generic `shell.overlay` floating layer (no shell
38325
+ * change needed) and pinned to the conversation column's top-right corner —
38326
+ * the spot where the session-header utilities sit once a conversation has
38327
+ * records. Shown only while the conversation column is in its `hero` phase
38328
+ * (no session at all, or a blank session whose header is deliberately
38329
+ * hidden); the position is measured from the rendered column root
38330
+ * (`[data-phase]`), so sidebar collapse and details-panel toggles are
38331
+ * tracked automatically. Clicking behaves exactly like the header icon: in a
38332
+ * blank-session hero the actions bind to that session, and with no session
38333
+ * at all they surface the no-session notice.
38334
+ */
38335
+ function HeroFilexButton(props) {
38336
+ const [pos, setPos] = (0, react.useState)(null);
38337
+ (0, react.useEffect)(() => {
38338
+ const update = () => {
38339
+ const column = document.querySelector("[data-phase]");
38340
+ if (column === null || column.getAttribute("data-phase") !== "hero") {
38341
+ setPos(null);
38342
+ return;
38343
+ }
38344
+ const rect = column.getBoundingClientRect();
38345
+ if (rect.width === 0 || rect.height === 0) {
38346
+ setPos(null);
38347
+ return;
38348
+ }
38349
+ const top = rect.top + 14;
38350
+ const right = window.innerWidth - rect.right + 28;
38351
+ setPos((current) => current !== null && current.top === top && current.right === right ? current : {
38352
+ top,
38353
+ right
38354
+ });
38355
+ };
38356
+ const timer = window.setInterval(update, 400);
38357
+ window.addEventListener("resize", update);
38358
+ update();
38359
+ return () => {
38360
+ window.clearInterval(timer);
38361
+ window.removeEventListener("resize", update);
38362
+ };
38363
+ }, []);
38364
+ if (pos === null) return null;
38365
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
38366
+ className: "filex-hero-fab",
38367
+ style: {
38368
+ top: pos.top,
38369
+ right: pos.right
38370
+ },
38371
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(HeaderGroup, { useSessions: props.useSessions })
38372
+ });
38373
+ }
38249
38374
  /** The overlay entry: keyboard shortcut + modal + transient notice. */
38250
38375
  function ExplorerOverlay(props) {
38251
38376
  const state = (0, react.useSyncExternalStore)(subscribe, getSnapshot);
@@ -38321,25 +38446,45 @@ window.__ModuleLoader__.load({
38321
38446
  order: 10,
38322
38447
  label: "文件预览 / 编辑"
38323
38448
  }, HeaderGroup));
38324
- ctx.slots.inject("shell.overlay", () => ctx.slots.register({
38325
- name: "shell.overlay",
38326
- id: "file-explorer-overlay",
38327
- order: 100,
38328
- label: "文件预览"
38329
- }, ExplorerOverlay));
38449
+ ctx.slots.inject("shell.overlay", () => {
38450
+ const overlay = ctx.slots.register({
38451
+ name: "shell.overlay",
38452
+ id: "file-explorer-overlay",
38453
+ order: 100,
38454
+ label: "文件预览"
38455
+ }, ExplorerOverlay);
38456
+ const heroFab = ctx.slots.register({
38457
+ name: "shell.overlay",
38458
+ id: "file-explorer-hero-fab",
38459
+ order: 90,
38460
+ label: "文件预览 / 编辑(hero)"
38461
+ }, HeroFilexButton);
38462
+ return () => {
38463
+ overlay();
38464
+ heroFab();
38465
+ };
38466
+ });
38330
38467
  probeVscode();
38331
- ctx.effect(() => wrapOpenPath(ctx.workspaces, {
38332
- currentSessionId: () => activeSessionId,
38333
- openInEditor: async (path, sessionId) => {
38334
- try {
38335
- await api.fsRead({ sessionId }, path);
38336
- } catch {
38337
- return false;
38468
+ ctx.effect(() => {
38469
+ const deps = {
38470
+ currentSessionId: () => activeSessionId,
38471
+ openInEditor: async (path, sessionId) => {
38472
+ try {
38473
+ await api.fsRead({ sessionId }, path);
38474
+ } catch {
38475
+ return false;
38476
+ }
38477
+ openExplorer(sessionId, path);
38478
+ return true;
38338
38479
  }
38339
- openExplorer(sessionId, path);
38340
- return true;
38341
- }
38342
- }), "dsh-file-explorer: openPath interception");
38480
+ };
38481
+ const restoreOpenPath = wrapOpenPath(ctx.workspaces, deps);
38482
+ const restoreWorkspacePath = ctx.remote?.session?.openWorkspacePath !== void 0 ? wrapOpenWorkspacePath(ctx.remote.session, deps) : () => {};
38483
+ return () => {
38484
+ restoreOpenPath();
38485
+ restoreWorkspacePath();
38486
+ };
38487
+ }, "dsh-file-explorer: file-open interception");
38343
38488
  } catch (error) {
38344
38489
  fail("load", error);
38345
38490
  }
@@ -64,6 +64,31 @@ export interface FilexWorkspacesService {
64
64
  /** Open a filesystem path through the Host (OS default application). */
65
65
  openPath(path: string): Promise<void>;
66
66
  }
67
+ /** Result of the chat's workspace-path open RPC (dsh-api-remotes face). */
68
+ export interface FilexWorkspaceOpenResult {
69
+ ok: boolean;
70
+ value?: {
71
+ opened: boolean;
72
+ };
73
+ error?: {
74
+ message: string;
75
+ };
76
+ }
77
+ /**
78
+ * The `ctx.remote.session` face (dsh-api-remotes): the remote API the
79
+ * conversation view uses for chat-side file opens in current runtimes —
80
+ * `session/openWorkspacePath` opens with the Host OS default application
81
+ * unless a plugin takes it over.
82
+ */
83
+ export interface FilexRemoteSession {
84
+ openWorkspacePath(input: {
85
+ path: string;
86
+ }): Promise<FilexWorkspaceOpenResult>;
87
+ }
88
+ /** The `ctx.remote` service face (structural subset used by this plugin). */
89
+ export interface FilexRemoteService {
90
+ session: FilexRemoteSession;
91
+ }
67
92
  /** The composer input face (client conversation service). */
68
93
  export interface FilexConversationInput {
69
94
  state: {
@@ -98,6 +123,10 @@ declare module 'cordis' {
98
123
  slots: FilexSlotsService;
99
124
  /** Client-only: the chat's file-open funnel the explorer intercepts. */
100
125
  workspaces: FilexWorkspacesService;
126
+ /** Client-only: the remote API face (dsh-api-remotes); chat-side file
127
+ * opens route through `remote.session.openWorkspacePath` in current
128
+ * runtimes, which the explorer also intercepts. */
129
+ remote?: FilexRemoteService;
101
130
  /** Subscribe to session events (cordis event API). */
102
131
  on(event: string, listener: (session: unknown, event: unknown) => void): () => void;
103
132
  /** DSH-vendored cordis lifecycle helper. */
package/package.json CHANGED
@@ -1,113 +1,113 @@
1
- {
2
- "name": "@dsh-xhl/dsh-file-explorer",
3
- "version": "0.1.2",
4
- "description": "DSH 外部编译型插件:工作区文件预览 / 编辑(CodeMirror 6 编辑器 + 文件树 + 全文搜索 + Markdown/HTML/图片/PDF 预览)。移植自同目录下的动态 Cordis 插件版本。",
5
- "type": "module",
6
- "main": "lib/index.js",
7
- "types": "lib/types/index.d.ts",
8
- "exports": {
9
- ".": {
10
- "types": "./lib/types/index.d.ts",
11
- "default": "./lib/index.js"
12
- },
13
- "./client": "./lib/client.js",
14
- "./package.json": "./package.json"
15
- },
16
- "engines": {
17
- "node": ">=20"
18
- },
19
- "publishConfig": {
20
- "access": "public",
21
- "registry": "https://registry.npmjs.org"
22
- },
23
- "dsh": {
24
- "bundle": {
25
- "patch": "./cordis.patch.yml"
26
- },
27
- "client": {
28
- "inject": [
29
- "@deepseek-ai/dsh-client-runtime",
30
- "@deepseek-ai/dsh-client-ui-slots",
31
- "@deepseek-ai/dsh-client-web-react"
32
- ],
33
- "platform": "web"
34
- }
35
- },
36
- "files": [
37
- "lib/index.js",
38
- "lib/client.js",
39
- "lib/types/**/*.d.ts",
40
- "cordis.patch.yml",
41
- "README.md"
42
- ],
43
- "scripts": {
44
- "build": "node -e \"fs.rmSync('lib',{recursive:true,force:true})\" && tsc -p tsconfig.build.json && tsdown",
45
- "typecheck": "tsc --noEmit",
46
- "bundle": "tsdown",
47
- "prepare": "tsdown"
48
- },
49
- "license": "MIT",
50
- "peerDependencies": {
51
- "@deepseek-ai/cordis": "^4.0.1",
52
- "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6",
53
- "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6",
54
- "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6",
55
- "@deepseek-ai/dsh-client-web-react": "^0.1.0-rc.6",
56
- "@deepseek-ai/dsh-host-webserver": "^0.1.0-rc.6",
57
- "@deepseek-ai/dsh-session": "^0.1.0-rc.6",
58
- "cordis": "^4.0.0-rc.7",
59
- "react": "^18.2.0",
60
- "react-dom": "^18.2.0"
61
- },
62
- "peerDependenciesMeta": {
63
- "cordis": {
64
- "optional": true
65
- }
66
- },
67
- "dependencies": {
68
- "@codemirror/commands": "^6.10.4",
69
- "@codemirror/lang-cpp": "^6.0.3",
70
- "@codemirror/lang-css": "^6.3.1",
71
- "@codemirror/lang-go": "^6.0.1",
72
- "@codemirror/lang-html": "^6.4.12",
73
- "@codemirror/lang-java": "^6.0.2",
74
- "@codemirror/lang-javascript": "^6.2.5",
75
- "@codemirror/lang-json": "^6.0.2",
76
- "@codemirror/lang-markdown": "^6.5.2",
77
- "@codemirror/lang-php": "^6.0.2",
78
- "@codemirror/lang-python": "^6.2.1",
79
- "@codemirror/lang-rust": "^6.0.2",
80
- "@codemirror/lang-sql": "^6.10.0",
81
- "@codemirror/lang-vue": "^0.1.3",
82
- "@codemirror/lang-xml": "^6.1.0",
83
- "@codemirror/lang-yaml": "^6.1.3",
84
- "@codemirror/language": "^6.12.4",
85
- "@codemirror/legacy-modes": "^6.5.3",
86
- "@codemirror/search": "6.7.1",
87
- "@codemirror/state": "^6.7.1",
88
- "@codemirror/view": "^6.43.8",
89
- "@lezer/highlight": "^1.2.3",
90
- "vscode-icons-js": "^11.6.1"
91
- },
92
- "devDependencies": {
93
- "@deepseek-ai/cordis": "^4.0.1",
94
- "@deepseek-ai/dsh-agent": "^0.1.0-rc.6",
95
- "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.6",
96
- "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6",
97
- "@deepseek-ai/dsh-client-ui-conversation": "^0.1.0-rc.6",
98
- "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6",
99
- "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6",
100
- "@deepseek-ai/dsh-client-web-react": "^0.1.0-rc.6",
101
- "@deepseek-ai/dsh-host-webserver": "^0.1.0-rc.6",
102
- "@deepseek-ai/dsh-session": "^0.1.0-rc.6",
103
- "@deepseek-ai/dsh-tools": "^0.1.0-rc.6",
104
- "@types/node": "^22.0.0",
105
- "@types/react": "~18.3.1",
106
- "@types/react-dom": "~18.3.1",
107
- "cordis": "^4.0.0-rc.7",
108
- "react": "^18.2.0",
109
- "react-dom": "^18.2.0",
110
- "tsdown": "^0.22.2",
111
- "typescript": "^5.6.0"
112
- }
113
- }
1
+ {
2
+ "name": "@dsh-xhl/dsh-file-explorer",
3
+ "version": "0.1.3",
4
+ "description": "DSH 外部编译型插件:工作区文件预览 / 编辑(CodeMirror 6 编辑器 + 文件树 + 全文搜索 + Markdown/HTML/图片/PDF 预览)。移植自同目录下的动态 Cordis 插件版本。",
5
+ "type": "module",
6
+ "main": "lib/index.js",
7
+ "types": "lib/types/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./lib/types/index.d.ts",
11
+ "default": "./lib/index.js"
12
+ },
13
+ "./client": "./lib/client.js",
14
+ "./package.json": "./package.json"
15
+ },
16
+ "engines": {
17
+ "node": ">=20"
18
+ },
19
+ "publishConfig": {
20
+ "access": "public",
21
+ "registry": "https://registry.npmjs.org"
22
+ },
23
+ "dsh": {
24
+ "bundle": {
25
+ "patch": "./cordis.patch.yml"
26
+ },
27
+ "client": {
28
+ "inject": [
29
+ "@deepseek-ai/dsh-client-runtime",
30
+ "@deepseek-ai/dsh-client-ui-slots",
31
+ "@deepseek-ai/dsh-client-web-react"
32
+ ],
33
+ "platform": "web"
34
+ }
35
+ },
36
+ "files": [
37
+ "lib/index.js",
38
+ "lib/client.js",
39
+ "lib/types/**/*.d.ts",
40
+ "cordis.patch.yml",
41
+ "README.md"
42
+ ],
43
+ "scripts": {
44
+ "build": "node -e \"fs.rmSync('lib',{recursive:true,force:true})\" && tsc -p tsconfig.build.json && tsdown",
45
+ "typecheck": "tsc --noEmit",
46
+ "bundle": "tsdown",
47
+ "prepare": "tsdown"
48
+ },
49
+ "license": "MIT",
50
+ "peerDependencies": {
51
+ "@deepseek-ai/cordis": "^4.0.1",
52
+ "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6",
53
+ "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6",
54
+ "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6",
55
+ "@deepseek-ai/dsh-client-web-react": "^0.1.0-rc.6",
56
+ "@deepseek-ai/dsh-host-webserver": "^0.1.0-rc.6",
57
+ "@deepseek-ai/dsh-session": "^0.1.0-rc.6",
58
+ "cordis": "^4.0.0-rc.7",
59
+ "react": "^18.2.0",
60
+ "react-dom": "^18.2.0"
61
+ },
62
+ "peerDependenciesMeta": {
63
+ "cordis": {
64
+ "optional": true
65
+ }
66
+ },
67
+ "dependencies": {
68
+ "@codemirror/commands": "^6.10.4",
69
+ "@codemirror/lang-cpp": "^6.0.3",
70
+ "@codemirror/lang-css": "^6.3.1",
71
+ "@codemirror/lang-go": "^6.0.1",
72
+ "@codemirror/lang-html": "^6.4.12",
73
+ "@codemirror/lang-java": "^6.0.2",
74
+ "@codemirror/lang-javascript": "^6.2.5",
75
+ "@codemirror/lang-json": "^6.0.2",
76
+ "@codemirror/lang-markdown": "^6.5.2",
77
+ "@codemirror/lang-php": "^6.0.2",
78
+ "@codemirror/lang-python": "^6.2.1",
79
+ "@codemirror/lang-rust": "^6.0.2",
80
+ "@codemirror/lang-sql": "^6.10.0",
81
+ "@codemirror/lang-vue": "^0.1.3",
82
+ "@codemirror/lang-xml": "^6.1.0",
83
+ "@codemirror/lang-yaml": "^6.1.3",
84
+ "@codemirror/language": "^6.12.4",
85
+ "@codemirror/legacy-modes": "^6.5.3",
86
+ "@codemirror/search": "6.7.1",
87
+ "@codemirror/state": "^6.7.1",
88
+ "@codemirror/view": "^6.43.8",
89
+ "@lezer/highlight": "^1.2.3",
90
+ "vscode-icons-js": "^11.6.1"
91
+ },
92
+ "devDependencies": {
93
+ "@deepseek-ai/cordis": "^4.0.1",
94
+ "@deepseek-ai/dsh-agent": "^0.1.0-rc.6",
95
+ "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.6",
96
+ "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6",
97
+ "@deepseek-ai/dsh-client-ui-conversation": "^0.1.0-rc.6",
98
+ "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6",
99
+ "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6",
100
+ "@deepseek-ai/dsh-client-web-react": "^0.1.0-rc.6",
101
+ "@deepseek-ai/dsh-host-webserver": "^0.1.0-rc.6",
102
+ "@deepseek-ai/dsh-session": "^0.1.0-rc.6",
103
+ "@deepseek-ai/dsh-tools": "^0.1.0-rc.6",
104
+ "@types/node": "^22.0.0",
105
+ "@types/react": "~18.3.1",
106
+ "@types/react-dom": "~18.3.1",
107
+ "cordis": "^4.0.0-rc.7",
108
+ "react": "^18.2.0",
109
+ "react-dom": "^18.2.0",
110
+ "tsdown": "^0.22.2",
111
+ "typescript": "^5.6.0"
112
+ }
113
+ }