@grapecity-software/dsh-spreadjs-editor 0.2.1 → 0.2.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.
@@ -0,0 +1,92 @@
1
+ # SpreadJS editor / driver bridge contract
2
+
3
+ This is a structural browser interface for DSH plugins. Implementations do not import or depend on either GrapeCity plugin package. A compatible editor owns the licensed SpreadJS Workbook, its UI, loading, saving and recovery. A driver consumes the live reference offered by that editor. Using SpreadJS alone does not establish compatibility: both sides must implement this contract and use APIs supported by the owner's SpreadJS version and loaded modules.
4
+
5
+ ## Registry and selection
6
+
7
+ The editor publishes the Cordis client service `spreadjsBridgeRegistry`. A driver injects that service and calls `register({ id, title, attach })`. Use the driver's own globally unique plugin/package id; neither the service nor its entries are restricted to GrapeCity package names. `attach(provider)` returns an idempotent disposer. The editor attaches only the entry explicitly selected by the user and detaches it on selection changes or teardown. The registry is owned by one editor or coordinator per DSH profile; installing two independent owners of the same Cordis service is not supported.
8
+
9
+ ```ts
10
+ interface SpreadjsBridgeEntry {
11
+ readonly id: string
12
+ readonly title: () => string
13
+ attach(provider: SpreadjsWorkbookProvider): () => void
14
+ }
15
+
16
+ interface SpreadjsBridgeRegistry {
17
+ register(entry: SpreadjsBridgeEntry): () => void
18
+ list(): readonly SpreadjsBridgeEntry[]
19
+ subscribe(listener: () => void): () => void
20
+ selected(): string | undefined
21
+ current(): SpreadjsBridgeEntry | undefined
22
+ select(id: string | undefined): void
23
+ }
24
+ ```
25
+
26
+ Registration rejects duplicate ids. Registration and subscription return idempotent disposers; selection changes notify subscribers. `selected()` preserves the user's saved id even before its entry registers; `current()` returns that entry only when registered. An empty selection hands out no Workbook. Drivers must drop references when detached, stop advertising them, and revalidate before using them.
27
+
28
+ The editor persists its selected driver id in its DSH settings document's `bridge` field; `''` or an absent value means no driver. Browser registry selection mirrors that document. The bundled Driver's host reads only the explicitly configured `editorSettingsNamespace`, default `spreadjs-editor`, to register its tools and skill. A third-party editor uses its own namespace, declares a writable/volatile `bridge` field, and emits the normal DSH `settings/document-updated` event when changed. Set the Driver config to that namespace and restart DSH; do not impersonate another editor's settings document.
29
+
30
+ ```yaml
31
+ # Driver Loader entry: the editor owns the acme-sheet-editor settings document.
32
+ id: spreadjs
33
+ name: '@grapecity-software/dsh-spreadjs-driver'
34
+ config:
35
+ editorSettingsNamespace: acme-sheet-editor
36
+ ```
37
+
38
+ ## Workbook provider
39
+
40
+ The following is the complete interface. Optional methods preserve support for other drivers with smaller needs. The bundled Driver requires the capabilities in the table below; optional in TypeScript does not mean sufficient for every operation.
41
+
42
+ ```ts
43
+ interface SpreadjsWorkbookProvider {
44
+ readonly id: string
45
+ getWorkbook(): unknown | undefined
46
+ getNamespace?(): unknown
47
+ getActivePath?(): string | undefined
48
+ getWorkbookIdentity?(): {
49
+ sessionId: string
50
+ file: string
51
+ instanceId: string
52
+ } | undefined
53
+ getSessionId?(): string | undefined
54
+ openWorkbook?(address: string, timeoutMs: number): Promise<void>
55
+ acquireDriverLease?(): string
56
+ releaseDriverLease?(lease: string): void
57
+ isDriverBusy?(): boolean
58
+ getDriverLeaseSignal?(lease: string): AbortSignal | undefined
59
+ save?(lease?: string, options?: {
60
+ signal?: AbortSignal
61
+ beforeWrite?: () => Promise<void>
62
+ }): Promise<void>
63
+ }
64
+ ```
65
+
66
+ | Capability | Owner's responsibility | Bundled Driver usage |
67
+ | --- | --- | --- |
68
+ | Ready Workbook | Return the actual live SpreadJS Workbook only when ready; return undefined during load/save, failure and teardown. | Required for status/execution. |
69
+ | Provider identity | `id` is stable and unique among providers in the page. It is not required to be `spreadjs-designer`. | Routes within the page; public targets also include browser/load identity. |
70
+ | Document identity | Return the calling chat id, full file resource address, and an instance id renewed after every successful load, including `fromJSON` on the same object. | Required for scoped execution; absent identity is not advertised as executable. |
71
+ | File address | `getActivePath()` and identity.file use the same full `dsh-resource://file/session/<id>/<encoded-path>` address. | Validates the document and reports results. |
72
+ | Namespace | Return the owner's actual `GC` namespace and loaded modules. | Required for scripts using `GC`; no separate engine/version is bundled by the driver. |
73
+ | Exclusive lease | Refuse acquisition while loading/saving/busy; finish pending cell input. Block concurrent user edits and conflicting owner operations until release. | Required for execution, including reads. Lease release must be idempotent and bound to its original owner. |
74
+ | Owner teardown signal | Provide a lease AbortSignal; preserve any recoverable partial state, then abort it before destroying the instance. | Required for prompt interruption when the owner closes during an awaiting script. |
75
+ | Save | Validate lease ownership; export, await `beforeWrite`, check `signal` before write-back and pass it to cancellable I/O. Reject failures and downloads that did not write the original file. | Required only for `save:true`; omitting it must not report a successful write. |
76
+ | Navigation | Advertise the visible chat via `getSessionId()` even without a Workbook. `openWorkbook` opens through the owner's navigation and resolves only when the requested resource is ready; reject session changes, timeout and load failure. | Required only for `sjs_live_open`; no browser-side Workbook creation by the driver. |
77
+
78
+ Navigation must not destroy a leased instance without preserving partial state and aborting its owner signal. Recovery data belongs to the editor and is keyed by the full chat resource address; a snapshot is not a resumable JavaScript execution. The bundled Editor retains snapshots only for the current page lifetime. Other editors may provide durable recovery, but drivers must not assume it.
79
+
80
+ ## Execution and cancellation
81
+
82
+ The bundled Driver confines status and execution to the calling chat. Status targets are opaque and expire on reload/reopen. Several available instances require an explicit target, even for the same file in two browser tabs. A queued job captures browser, provider, chat, file and load identity; both dispatch and browser execution revalidate it. Only its claiming browser may settle it.
83
+
84
+ Execution acquires a lease, captures the original Workbook/file/signal, checks job permission, runs code, revalidates identity and permission, optionally calls the owner's save with the lease and permission options, then releases in finally. Do not reopen a successfully edited file merely to steal focus from the user's current tab.
85
+
86
+ Caller cancellation or timeout revokes permission to perform a later automatic save and aborts the script's injected `signal`. A script that ignores cancellation retains the lease until it settles or owner teardown interrupts it. Already applied edits are not rolled back, arbitrary page JavaScript cannot be forcibly terminated, and a write already sent to the server may complete. Code shares the owner page's globals; this bridge is not a JavaScript security sandbox.
87
+
88
+ ## Dependencies and compatibility checks
89
+
90
+ Neither plugin should declare the other as a dependency or peer dependency. The editor bundles its browser SpreadJS/Designer runtime and owns its licenses. The driver declares only the DSH peers it uses; it has no SpreadJS, Designer, browser engine or editor-package dependency. DSH supplies host services and the authenticated connection. The bridge is currently documented as structural interfaces rather than a separately published protocol package; copy the interfaces or implement an adapter without loading another editor runtime.
91
+
92
+ A third-party adapter should verify: registration/selection/detachment; execution against its own provider id; missing/busy instances; chat/file/reload isolation; lease release after script/save failure; cancellation during asynchronous work/export; snapshot and interruption on close; and readiness/failure of navigation if provided. SpreadJS version and optional module support must be checked separately. GcExcel uses a different engine and is outside this Workbook-reference contract.
package/lib/client.js CHANGED
@@ -1,4 +1,4 @@
1
1
  [diffend] Oversized file quarantined before diffing.
2
2
  name: package/lib/client.js
3
- size: 51961608 bytes
4
- sha256: 9f275e2b18e8ba9a93544c9a3bf6ae82f4a9dec330d2f515176c2de65d827a07
3
+ size: 52049119 bytes
4
+ sha256: 48b261463d34de4f7ddfc71c88aabe8f48bf3283a5a502145bebe6fd7a58ce95
package/lib/index.js CHANGED
@@ -1,6 +1,12 @@
1
1
  import { createHash } from "node:crypto";
2
+ import { readFileSync } from "node:fs";
2
3
  import { mkdir, rename, rm, writeFile } from "node:fs/promises";
3
4
  import { dirname, join } from "node:path";
5
+ import z from "@deepseek-ai/schemastery";
6
+ //#region src/shared/settings.ts
7
+ /** The field holding the id of the chosen bridge. */
8
+ const BRIDGE_FIELD = "bridge";
9
+ //#endregion
4
10
  //#region src/index.ts
5
11
  /**
6
12
  * dsh-spreadjs-editor — node half.
@@ -36,7 +42,66 @@ import { dirname, join } from "node:path";
36
42
  const name = "dsh-spreadjs-editor";
37
43
  /** Required service: the web server whose route table this plugin extends. */
38
44
  const inject = ["webServer"];
45
+ /**
46
+ * The largest workbook accepted on the wire, used when the patch sets none.
47
+ *
48
+ * Declared above the schema so the schema's own `default` can name it: a
49
+ * schema is built while this module evaluates, so a constant declared below
50
+ * would be in its temporal dead zone at that moment.
51
+ */
39
52
  const DEFAULT_MAX_SAVE_BYTES = 67108864;
53
+ /**
54
+ * Cordis configuration schema.
55
+ *
56
+ * The `[BRIDGE_FIELD]` key is spread rather than spelled so the two halves of
57
+ * the choice cannot drift: the browser half writes through the same constant,
58
+ * and a rename would otherwise surface as "the setting does not stick".
59
+ *
60
+ * **`volatile()` is what makes the choice persist at all.** DSH accepts a
61
+ * settings write only for a field declared volatile — `SettingsForms.write`
62
+ * builds a volatile-only projection of the schema and throws
63
+ * `Config field "bridge" is not volatile` for anything else. Without it every
64
+ * click was refused, the refusal arrived as a *resolved `false`* rather than a
65
+ * rejection, and the choice lived only in the running page: the next start
66
+ * showed None again. The license keys and the two save limits are deployment
67
+ * configuration an operator puts in the patch, so they stay non-volatile and
68
+ * unwritable from the UI.
69
+ *
70
+ * No `default` on `bridge`: an ABSENT field and an explicit `''` are different
71
+ * states — "never chosen" versus "chosen None" — and only the absence is
72
+ * visible to a later default-if-unset rule.
73
+ *
74
+ * Deliberately NOT annotated `z<Config>`. That annotation asserts the schema's
75
+ * input and output are the same type, and for a volatile field they are not: a
76
+ * patch carries a plain string, while the resolved value is a `Volatile<…>`
77
+ * handle — a stable reference, because DSH may rewrite the value while this
78
+ * plugin runs. The shipped plugins with a volatile field leave the annotation
79
+ * off for the same reason.
80
+ */
81
+ const Config = z.object({
82
+ licenseKey: z.string().default(""),
83
+ designerLicenseKey: z.string().default(""),
84
+ maxSaveBytes: z.natural().default(DEFAULT_MAX_SAVE_BYTES),
85
+ trustedHosts: z.array(z.string()).default([]),
86
+ [BRIDGE_FIELD]: z.string().volatile()
87
+ });
88
+ /** The SpreadJS version this build bundled, or `unknown` outside a build. */
89
+ const SPREADJS_VERSION = "19.2.1";
90
+ /**
91
+ * This package's own version, read from the manifest the module ships beside.
92
+ * The published layout keeps `lib/index.js` next to `package.json`, so this
93
+ * relative URL resolves in the repository, in a tarball install, and inside a
94
+ * profile — no import of a bare `package.json` specifier, which a consumer's
95
+ * resolver may not be allowed to reach.
96
+ */
97
+ const PLUGIN_VERSION = (() => {
98
+ try {
99
+ const manifest = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
100
+ return typeof manifest.version === "string" && manifest.version !== "" ? manifest.version : "unknown";
101
+ } catch {
102
+ return "unknown";
103
+ }
104
+ })();
40
105
  /** A failure with an HTTP status, so handlers stay flat. */
41
106
  var HttpError = class extends Error {
42
107
  status;
@@ -220,7 +285,14 @@ function apply(ctx, config = {}) {
220
285
  }
221
286
  try {
222
287
  if (pathname === "/spreadjs/api/health") {
223
- sendJson(res, 200, { ok: true });
288
+ sendJson(res, 200, {
289
+ ok: true,
290
+ plugin: {
291
+ name,
292
+ version: PLUGIN_VERSION
293
+ },
294
+ spreadjs: SPREADJS_VERSION
295
+ });
224
296
  return;
225
297
  }
226
298
  if (pathname === "/spreadjs/api/config") {
@@ -237,6 +309,11 @@ function apply(ctx, config = {}) {
237
309
  }
238
310
  });
239
311
  ctx.effect(() => disposer, "dsh-spreadjs-editor: /spreadjs routes");
312
+ ctx.inject(["settings"], (child) => {
313
+ const settings = child.settings;
314
+ if (settings === void 0) return () => {};
315
+ return settings.configure({ auto: false }, ctx.fiber);
316
+ });
240
317
  }
241
318
  //#endregion
242
- export { apply, inject, name };
319
+ export { Config, PLUGIN_VERSION, SPREADJS_VERSION, apply, inject, name };
package/package.json CHANGED
@@ -1,116 +1,121 @@
1
- {
2
- "name": "@grapecity-software/dsh-spreadjs-editor",
3
- "version": "0.2.1",
4
- "description": "DeepSeek Harness Web UI plugin: SpreadJS workbook editor for the harness's own right Sidebar, with binary save.",
5
- "keywords": [
6
- "deepseek-harness",
7
- "dsh",
8
- "webui",
9
- "plugin",
10
- "spreadjs",
11
- "excel"
12
- ],
13
- "type": "module",
14
- "main": "lib/index.js",
15
- "exports": {
16
- ".": {
17
- "default": "./lib/index.js"
18
- },
19
- "./client": {
20
- "default": "./lib/client.js"
21
- },
22
- "./package.json": "./package.json"
23
- },
24
- "files": [
25
- "lib/*.js",
26
- "lib/licenses",
27
- "cordis.patch.yml",
28
- "README.md",
29
- "CHANGELOG.md",
30
- "LICENSE",
31
- "THIRD_PARTY_NOTICES.md"
32
- ],
33
- "scripts": {
34
- "build": "node scripts/build.mjs && node scripts/copy-notices.mjs",
35
- "grapecity:update": "node scripts/update-grapecity.mjs",
36
- "prepack": "npm run build",
37
- "prepublishOnly": "npm run typecheck && npm test && npm run build && node scripts/smoke-client.mjs && node scripts/smoke-node.mjs && npm run verify:package",
38
- "rebuild": "node scripts/build.mjs",
39
- "probe:live": "node scripts/probe-live-save.mjs",
40
- "test": "vitest run",
41
- "typecheck": "tsc --noEmit",
42
- "verify:package": "node scripts/verify-package.mjs"
43
- },
44
- "engines": {
45
- "node": ">=20"
46
- },
47
- "publishConfig": {
48
- "access": "public"
49
- },
50
- "repository": {
51
- "type": "git",
52
- "url": "https://github.com/GrapeCityXA/dsh-plugin-spreadjs-editor.git"
53
- },
54
- "dsh": {
55
- "engines": {
56
- "dsh": ">=0.1.5-rc.3"
57
- },
58
- "bundle": {
59
- "patch": "./cordis.patch.yml"
60
- },
61
- "client": {
62
- "platform": "web",
63
- "inject": [
64
- "@deepseek-ai/dsh-client-ui-theme",
65
- "@deepseek-ai/dsh-client-ui-slots",
66
- "@deepseek-ai/dsh-client-ui-sidebar-right",
67
- "@deepseek-ai/dsh-client-ui-sidebar-documentpreview"
68
- ]
69
- }
70
- },
71
- "peerDependencies": {
72
- "@deepseek-ai/cordis": ">=4.0.0",
73
- "@deepseek-ai/dsh-client-ui-renderer": ">=0.1.5-rc.3",
74
- "@deepseek-ai/dsh-client-ui-sidebar-documentpreview": ">=0.1.5-rc.3",
75
- "@deepseek-ai/dsh-client-ui-slots": ">=0.1.5-rc.3",
76
- "@deepseek-ai/dsh-client-ui-theme": ">=0.1.5-rc.3",
77
- "react": "^18.0.0"
78
- },
79
- "devDependencies": {
80
- "@grapecity-software/spread-excelio": "19.2.0",
81
- "@grapecity-software/spread-sheets": "19.2.0",
82
- "@grapecity-software/spread-sheets-io": "19.2.0",
83
- "@grapecity-software/spread-sheets-resources-zh": "19.2.0",
84
- "@grapecity-software/spread-sheets-designer": "19.2.0",
85
- "@grapecity-software/spread-sheets-designer-resources-cn": "19.2.0",
86
- "@grapecity-software/spread-sheets-shapes": "19.2.0",
87
- "@grapecity-software/spread-sheets-charts": "19.2.0",
88
- "@grapecity-software/spread-sheets-slicers": "19.2.0",
89
- "@grapecity-software/spread-sheets-sparklines": "19.2.0",
90
- "@grapecity-software/spread-sheets-print": "19.2.0",
91
- "@grapecity-software/spread-sheets-pdf": "19.2.0",
92
- "@grapecity-software/spread-sheets-barcode": "19.2.0",
93
- "@grapecity-software/spread-sheets-formula-panel": "19.2.0",
94
- "@grapecity-software/spread-sheets-pivot-addon": "19.2.0",
95
- "@grapecity-software/spread-sheets-tablesheet": "19.2.0",
96
- "@grapecity-software/spread-sheets-datacharts-addon": "19.2.0",
97
- "@grapecity-software/spread-sheets-ganttsheet": "19.2.0",
98
- "@grapecity-software/spread-sheets-reportsheet-addon": "19.2.0",
99
- "@grapecity-software/spread-sheets-languagepackages": "19.2.0",
100
- "tsdown": "^0.22.0",
101
- "typescript": "^5.9.0",
102
- "unrun": "^0.3.1",
103
- "@deepseek-ai/cordis": "^4.0.1",
104
- "@deepseek-ai/dsh-client-ui-renderer": "0.1.5-rc.3",
105
- "@deepseek-ai/dsh-client-ui-slots": "0.1.5-rc.3",
106
- "@deepseek-ai/dsh-client-ui-sidebar-right": "0.1.5-rc.3",
107
- "@deepseek-ai/dsh-client-ui-sidebar-documentpreview": "0.1.5-rc.3",
108
- "@deepseek-ai/dsh-client-ui-theme": "0.1.5-rc.3",
109
- "@deepseek-ai/dsh-host-webserver": "0.1.5-rc.3",
110
- "@types/node": "^22.0.0",
111
- "@types/react": "^18.3.0",
112
- "react": "^18.2.0",
113
- "vitest": "^3.0.0"
114
- },
115
- "license": "MIT"
116
- }
1
+ {
2
+ "name": "@grapecity-software/dsh-spreadjs-editor",
3
+ "version": "0.2.3",
4
+ "description": "DSH sidebar SpreadJS editor with binary save, recovery and a selectable bridge for compatible drivers.",
5
+ "keywords": [
6
+ "deepseek-harness",
7
+ "dsh",
8
+ "webui",
9
+ "plugin",
10
+ "spreadjs",
11
+ "excel"
12
+ ],
13
+ "type": "module",
14
+ "main": "lib/index.js",
15
+ "exports": {
16
+ ".": {
17
+ "default": "./lib/index.js"
18
+ },
19
+ "./client": {
20
+ "default": "./lib/client.js"
21
+ },
22
+ "./package.json": "./package.json"
23
+ },
24
+ "files": [
25
+ "lib/*.js",
26
+ "lib/licenses",
27
+ "cordis.patch.yml",
28
+ "README.md",
29
+ "docs/bridge-contract.md",
30
+ "CHANGELOG.md",
31
+ "LICENSE",
32
+ "THIRD_PARTY_NOTICES.md"
33
+ ],
34
+ "scripts": {
35
+ "build": "node scripts/build.mjs && node scripts/copy-notices.mjs",
36
+ "grapecity:update": "node scripts/update-grapecity.mjs",
37
+ "prepack": "npm run build",
38
+ "prepublishOnly": "npm run typecheck && npm test && npm run build && node scripts/smoke-client.mjs && node scripts/smoke-node.mjs && npm run verify:package",
39
+ "rebuild": "node scripts/build.mjs",
40
+ "probe:live": "node scripts/probe-live-save.mjs",
41
+ "release": "node scripts/release.mjs",
42
+ "test": "vitest run",
43
+ "typecheck": "tsc --noEmit",
44
+ "verify:package": "node scripts/verify-package.mjs"
45
+ },
46
+ "engines": {
47
+ "node": ">=22.19.0"
48
+ },
49
+ "publishConfig": {
50
+ "access": "public"
51
+ },
52
+ "repository": {
53
+ "type": "git",
54
+ "url": "https://github.com/GrapeCityXA/dsh-plugin-spreadjs-editor.git"
55
+ },
56
+ "dsh": {
57
+ "engines": {
58
+ "dsh": "0.2.0-rc.2"
59
+ },
60
+ "bundle": {
61
+ "patch": "./cordis.patch.yml"
62
+ },
63
+ "client": {
64
+ "platform": "web",
65
+ "inject": [
66
+ "@deepseek-ai/dsh-client-ui-theme",
67
+ "@deepseek-ai/dsh-client-ui-slots",
68
+ "@deepseek-ai/dsh-client-ui-sidebar-right",
69
+ "@deepseek-ai/dsh-client-ui-sidebar-documentpreview"
70
+ ]
71
+ }
72
+ },
73
+ "peerDependencies": {
74
+ "@deepseek-ai/cordis": "~4.0.4",
75
+ "@deepseek-ai/schemastery": "~3.18.4",
76
+ "@deepseek-ai/dsh-client-ui-renderer": "0.2.0-rc.2",
77
+ "@deepseek-ai/dsh-client-ui-sidebar-documentpreview": "0.2.0-rc.2",
78
+ "@deepseek-ai/dsh-client-ui-slots": "0.2.0-rc.2",
79
+ "@deepseek-ai/dsh-client-ui-theme": "0.2.0-rc.2",
80
+ "react": "^18.0.0"
81
+ },
82
+ "devDependencies": {
83
+ "@grapecity-software/spread-excelio": "19.2.1",
84
+ "@grapecity-software/spread-sheets": "19.2.1",
85
+ "@grapecity-software/spread-sheets-io": "19.2.1",
86
+ "@grapecity-software/spread-sheets-resources-zh": "19.2.1",
87
+ "@grapecity-software/spread-sheets-designer": "19.2.1",
88
+ "@grapecity-software/spread-sheets-designer-resources-cn": "19.2.1",
89
+ "@grapecity-software/spread-sheets-shapes": "19.2.1",
90
+ "@grapecity-software/spread-sheets-charts": "19.2.1",
91
+ "@grapecity-software/spread-sheets-slicers": "19.2.1",
92
+ "@grapecity-software/spread-sheets-sparklines": "19.2.1",
93
+ "@grapecity-software/spread-sheets-print": "19.2.1",
94
+ "@grapecity-software/spread-sheets-pdf": "19.2.1",
95
+ "@grapecity-software/spread-sheets-barcode": "19.2.1",
96
+ "@grapecity-software/spread-sheets-formula-panel": "19.2.1",
97
+ "@grapecity-software/spread-sheets-pivot-addon": "19.2.1",
98
+ "@grapecity-software/spread-sheets-tablesheet": "19.2.1",
99
+ "@grapecity-software/spread-sheets-datacharts-addon": "19.2.1",
100
+ "@grapecity-software/spread-sheets-ganttsheet": "19.2.1",
101
+ "@grapecity-software/spread-sheets-reportsheet-addon": "19.2.1",
102
+ "@grapecity-software/spread-sheets-languagepackages": "19.2.1",
103
+ "tsdown": "^0.22.0",
104
+ "typescript": "^5.9.0",
105
+ "unrun": "^0.3.1",
106
+ "@deepseek-ai/cordis": "~4.0.4",
107
+ "@deepseek-ai/schemastery": "~3.18.4",
108
+ "@deepseek-ai/dsh-client-ui-renderer": "0.2.0-rc.2",
109
+ "@deepseek-ai/dsh-client-ui-slots": "0.2.0-rc.2",
110
+ "@deepseek-ai/dsh-client-ui-sidebar-right": "0.2.0-rc.2",
111
+ "@deepseek-ai/dsh-client-ui-sidebar-documentpreview": "0.2.0-rc.2",
112
+ "@deepseek-ai/dsh-client-ui-theme": "0.2.0-rc.2",
113
+ "@deepseek-ai/dsh-client-ui-settings": "0.2.0-rc.2",
114
+ "@deepseek-ai/dsh-host-webserver": "0.2.0-rc.2",
115
+ "@types/node": "^22.0.0",
116
+ "@types/react": "^18.3.0",
117
+ "react": "^18.2.0",
118
+ "vitest": "^3.0.0"
119
+ },
120
+ "license": "MIT"
121
+ }