@michengai/dsh-archive-manager 1.0.20 → 1.1.0

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.
@@ -1,5 +1,6 @@
1
1
  import { symbols } from "@deepseek-ai/cordis";
2
2
  import { record } from "./contracts.js";
3
+ import { guardReleaseAgeExclude, mergeMinimumReleaseAgeExclude, recordReleaseAgeExclude } from "./release-age.js";
3
4
  import { spawn } from "node:child_process";
4
5
  import { existsSync, readFileSync } from "node:fs";
5
6
  import { readFile } from "node:fs/promises";
@@ -305,15 +306,26 @@ async function runPluginManagerInstall(target, packageSpec) {
305
306
  throw new Error(result.error?.message || result.packageResult?.output || "\u66F4\u65B0\u5931\u8D25\uFF0C\u8BF7\u67E5\u770B\u670D\u52A1\u7AEF\u65E5\u5FD7\u3002");
306
307
  }
307
308
  async function install(target, packageSpec) {
309
+ await guardReleaseAgeExclude(target.profileDir, packageSpec);
308
310
  if (target.desktopPnpm !== void 0) {
309
311
  const handle = target.desktopPnpm.runPlugin(["add", "--config.minimumReleaseAge=0", packageSpec, "--registry=https://registry.npmjs.org/"], target.profileDir);
310
312
  const result = await handle.done;
311
313
  if (result.exitCode !== 0) throw new Error(`\u66F4\u65B0\u8FDB\u7A0B\u9000\u51FA\u7801 ${String(result.exitCode)}\u3002`);
314
+ await recordReleaseAgeExclude(target.profileDir, packageSpec);
312
315
  return;
313
316
  }
314
- if (target.packageManager !== void 0) return runPackageManagerInstall(target, packageSpec);
315
- if (target.pluginManager !== void 0) return runPluginManagerInstall(target, packageSpec);
316
- return runCliInstall(target, packageSpec);
317
+ if (target.packageManager !== void 0) {
318
+ await runPackageManagerInstall(target, packageSpec);
319
+ await recordReleaseAgeExclude(target.profileDir, packageSpec);
320
+ return;
321
+ }
322
+ if (target.pluginManager !== void 0) {
323
+ await runPluginManagerInstall(target, packageSpec);
324
+ await recordReleaseAgeExclude(target.profileDir, packageSpec);
325
+ return;
326
+ }
327
+ await runCliInstall(target, packageSpec);
328
+ await recordReleaseAgeExclude(target.profileDir, packageSpec);
317
329
  }
318
330
  function json(response, statusCode, value) {
319
331
  response.writeHead(statusCode, { "content-type": "application/json; charset=utf-8", "cache-control": "no-store" });
@@ -417,6 +429,8 @@ export {
417
429
  isDshCliEntry,
418
430
  isNewerVersion,
419
431
  isTrustedUpdateRequest,
432
+ mergeMinimumReleaseAgeExclude,
433
+ recordReleaseAgeExclude,
420
434
  registerPluginUpdater,
421
435
  resolveUpdateRuntime,
422
436
  shouldNotifyParent
package/lib/projcache.js CHANGED
@@ -222,10 +222,6 @@ var ArchiveProjectionCache = class extends CacheBase {
222
222
  await super.write(session);
223
223
  if (this.deletedSessionIds.has(session.id)) await this.requireTable().delete(session.id);
224
224
  }
225
- /**
226
- * 守住所有底层写入。rc.2 的冷读经 `putSoft -> put`,alpha.2 则
227
- * 直接经 `put`;把墓碑与 whenIdle 跟踪放在这里可同时兼容两代实现。
228
- */
229
225
  put(id, identity, rows) {
230
226
  if (this.deletedSessionIds.has(id)) return Promise.resolve();
231
227
  const task = this.putCore(id, identity, rows);
@@ -236,16 +232,6 @@ var ArchiveProjectionCache = class extends CacheBase {
236
232
  await super.put(id, identity, rows);
237
233
  if (this.deletedSessionIds.has(id)) await this.requireTable().delete(id);
238
234
  }
239
- /** rc.2 公开的 fail-soft 辅助在 alpha.2 已移除;保留同形兼容入口。 */
240
- async putSoft(id, identity, rows, what) {
241
- const upstream = CacheBase.prototype.putSoft;
242
- if (typeof upstream === "function") return upstream.call(this, id, identity, rows, what);
243
- try {
244
- await this.put(id, identity, rows);
245
- } catch (error) {
246
- this.ctx.logger.warn(`session projection cache: ${what} for "${id}" failed (cache stays stale): ${String(error)}`);
247
- }
248
- }
249
235
  /**
250
236
  * 全部被跟踪的在途写入落定后 resolve(含失败)。空闲缓存上调用立即返回。
251
237
  * @returns 跟踪写入落定后的 resolution。
@@ -0,0 +1,164 @@
1
+ import { existsSync } from "node:fs";
2
+ import { readFile, rename, unlink, writeFile } from "node:fs/promises";
3
+ import { resolve } from "node:path";
4
+ function releaseAgeSpec(packageSpec) {
5
+ const at = packageSpec.lastIndexOf("@");
6
+ if (at <= 0) return void 0;
7
+ const name = packageSpec.slice(0, at);
8
+ const version = packageSpec.slice(at + 1);
9
+ if (!isPackageName(name) || !isReleaseVersion(version)) return void 0;
10
+ return { name, version };
11
+ }
12
+ function isPackageName(name) {
13
+ return /^@[^/\s]+\/[^/\s]+$/.test(name) || /^[^@/\s]+$/.test(name);
14
+ }
15
+ function isReleaseVersion(version) {
16
+ return /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(version);
17
+ }
18
+ function unreadableReleaseAgeExclude() {
19
+ return new Error("\u53D1\u5E03\u5E74\u9F84\u767D\u540D\u5355\u65E0\u6CD5\u5B89\u5168\u5408\u5E76\uFF0C\u5DF2\u505C\u6B62\u66F4\u65B0\uFF0C\u907F\u514D\u8FD9\u4E2A profile \u4E4B\u540E\u65E0\u6CD5\u5B89\u88C5\u63D2\u4EF6\u3002");
20
+ }
21
+ function excludeEntry(indent, name, versions, comment = "") {
22
+ const entry = `${indent}- '${name}@${versions.join(" || ")}'`;
23
+ return comment === "" ? entry : `${entry} ${comment}`;
24
+ }
25
+ function parseExcludeLine(line) {
26
+ const dash = line.indexOf("-");
27
+ if (!/^\s+-/.test(line) || dash < 0) return void 0;
28
+ const indent = line.slice(0, dash);
29
+ const raw = line.slice(dash + 1).trim();
30
+ let body = raw;
31
+ let comment = "";
32
+ if (raw.startsWith("'") || raw.startsWith('"')) {
33
+ const quote = raw[0] ?? "'";
34
+ const end = raw.lastIndexOf(quote);
35
+ if (end <= 0) return void 0;
36
+ const rest = raw.slice(end + 1).trim();
37
+ if (rest !== "" && !rest.startsWith("#")) return void 0;
38
+ if (rest.startsWith("#")) comment = rest;
39
+ body = raw.slice(1, end);
40
+ } else if (raw.includes("#")) return void 0;
41
+ if (body.includes("#")) return void 0;
42
+ const versionAt = body.lastIndexOf("@");
43
+ if (versionAt > 0) {
44
+ const name = body.slice(0, versionAt);
45
+ const versions = body.slice(versionAt + 1).split(" || ");
46
+ if (isPackageName(name) && versions.every(isReleaseVersion)) return { indent, name, versions, comment };
47
+ return void 0;
48
+ }
49
+ if (isPackageName(body) || /^@[^/\s]+\/\*$/.test(body)) return { indent, name: body, versions: void 0, comment };
50
+ return void 0;
51
+ }
52
+ function mergeMinimumReleaseAgeExclude(yaml, packageSpec) {
53
+ const spec = releaseAgeSpec(packageSpec);
54
+ if (spec === void 0) throw new Error("\u66F4\u65B0\u7248\u672C\u65E0\u6CD5\u5199\u5165\u53D1\u5E03\u5E74\u9F84\u767D\u540D\u5355\uFF0C\u5DF2\u505C\u6B62\u66F4\u65B0\u3002");
55
+ const eol = yaml.includes("\r\n") ? "\r\n" : "\n";
56
+ const text = yaml.replaceAll("\r\n", "\n");
57
+ const next = mergeReleaseAgeText(text, spec.name, spec.version);
58
+ return eol === "\r\n" ? next.replaceAll("\n", "\r\n") : next;
59
+ }
60
+ function mergeReleaseAgeText(yaml, name, version) {
61
+ if (/minimumReleaseAgeExclude:[^\n\r]/.test(yaml)) throw unreadableReleaseAgeExclude();
62
+ const marker = /(?:^|\n)minimumReleaseAgeExclude:[ \t]*(?:\n|$)/.exec(yaml);
63
+ if (marker === null) {
64
+ const base = yaml.endsWith("\n") || yaml.length === 0 ? yaml : `${yaml}
65
+ `;
66
+ const gap = base.length === 0 || base.endsWith("\n\n") ? "" : "\n";
67
+ return `${base}${gap}minimumReleaseAgeExclude:
68
+ - '${name}@${version}'
69
+ `;
70
+ }
71
+ const keyAt = (marker.index ?? 0) + (marker[0].startsWith("\n") ? 1 : 0);
72
+ let cursor = keyAt + "minimumReleaseAgeExclude:".length;
73
+ while (cursor < yaml.length && (yaml[cursor] === " " || yaml[cursor] === " ")) cursor += 1;
74
+ if (yaml[cursor] !== "\n") throw unreadableReleaseAgeExclude();
75
+ const bodyStart = cursor + 1;
76
+ const lines = [];
77
+ let bodyEnd = bodyStart;
78
+ while (bodyEnd <= yaml.length) {
79
+ const nextNl = yaml.indexOf("\n", bodyEnd);
80
+ const lineEnd = nextNl === -1 ? yaml.length : nextNl;
81
+ const line = yaml.slice(bodyEnd, lineEnd);
82
+ const ended = line.trim() !== "" && !/^[ \t]*#/.test(line) && !/^[ \t]/.test(line);
83
+ if (ended) break;
84
+ if (line.trim() !== "" && !/^[ \t]*#/.test(line) && !/^[ \t]+-/.test(line)) throw unreadableReleaseAgeExclude();
85
+ lines.push(line);
86
+ if (nextNl === -1) {
87
+ bodyEnd = yaml.length;
88
+ break;
89
+ }
90
+ bodyEnd = nextNl + 1;
91
+ if (bodyEnd === yaml.length) break;
92
+ }
93
+ let ours;
94
+ const rewritten = lines.map((line, index) => {
95
+ if (line.trim() === "" || /^[ \t]*#/.test(line)) return line;
96
+ const parsed = parseExcludeLine(line);
97
+ if (parsed === void 0) throw unreadableReleaseAgeExclude();
98
+ if (parsed.name !== name) return line;
99
+ if (ours === void 0) {
100
+ ours = { index, indent: parsed.indent, versions: parsed.versions, comment: parsed.comment };
101
+ return line;
102
+ }
103
+ if (ours.versions !== void 0 && parsed.versions !== void 0) ours.versions = [...ours.versions, ...parsed.versions.filter((item) => !ours?.versions?.includes(item))];
104
+ return "";
105
+ });
106
+ if (ours?.versions === void 0 && ours !== void 0) return yaml;
107
+ const indent = ours?.indent ?? lines.find((line) => /^[ \t]+-/.test(line))?.match(/^([ \t]+)/)?.[1] ?? " ";
108
+ const versions = ours?.versions === void 0 ? [version] : ours.versions.includes(version) ? ours.versions : [...ours.versions, version];
109
+ const entry = excludeEntry(indent, name, versions, ours?.comment ?? "");
110
+ if (ours === void 0) rewritten.push(entry);
111
+ else rewritten[ours.index] = entry;
112
+ const body = rewritten.filter((line) => line !== "").join("\n");
113
+ const prefix = yaml.slice(0, bodyStart);
114
+ const suffix = yaml.slice(bodyEnd);
115
+ const joined = `${prefix}${body}${body.length === 0 || body.endsWith("\n") ? "" : "\n"}${suffix}`;
116
+ return joined.endsWith("\n") ? joined : `${joined}
117
+ `;
118
+ }
119
+ async function guardReleaseAgeExclude(profileDir, packageSpec) {
120
+ const file = resolve(profileDir, "pnpm-workspace.yaml");
121
+ const current = existsSync(file) ? await readFile(file, "utf8") : "packages:\n - .\n";
122
+ mergeMinimumReleaseAgeExclude(current, packageSpec);
123
+ }
124
+ async function replaceTextFile(file, next) {
125
+ const tmp = `${file}.${process.pid}.tmp`;
126
+ const backup = `${file}.${process.pid}.bak`;
127
+ await writeFile(tmp, next, "utf8");
128
+ try {
129
+ await rename(tmp, file);
130
+ return;
131
+ } catch (error) {
132
+ const code = error && typeof error === "object" && "code" in error ? String(error.code) : "";
133
+ if (code !== "EEXIST" && code !== "EPERM" && code !== "EACCES") {
134
+ await unlink(tmp).catch(() => {
135
+ });
136
+ throw error;
137
+ }
138
+ }
139
+ await unlink(backup).catch(() => {
140
+ });
141
+ await rename(file, backup);
142
+ try {
143
+ await rename(tmp, file);
144
+ } catch (error) {
145
+ await rename(backup, file).catch(() => {
146
+ });
147
+ await unlink(tmp).catch(() => {
148
+ });
149
+ throw error;
150
+ }
151
+ await unlink(backup).catch(() => {
152
+ });
153
+ }
154
+ async function recordReleaseAgeExclude(profileDir, packageSpec) {
155
+ const file = resolve(profileDir, "pnpm-workspace.yaml");
156
+ const current = existsSync(file) ? await readFile(file, "utf8") : "packages:\n - .\n";
157
+ const next = mergeMinimumReleaseAgeExclude(current, packageSpec);
158
+ if (next !== current) await replaceTextFile(file, next);
159
+ }
160
+ export {
161
+ guardReleaseAgeExclude,
162
+ mergeMinimumReleaseAgeExclude,
163
+ recordReleaseAgeExclude
164
+ };
package/lib/workspace.js CHANGED
@@ -313,12 +313,8 @@ async function activeSessionErrorType() {
313
313
  activeSessionError = typeof workspace.WorkspaceActiveSessionError === "function" ? workspace.WorkspaceActiveSessionError : null;
314
314
  return activeSessionError ?? void 0;
315
315
  }
316
- function snapshotUsesProjectionKeys(cache) {
317
- return cache.cachedSnapshot.length === 2;
318
- }
319
- function projectionSnapshot(cache, header, inheritedEventCount) {
320
- if (snapshotUsesProjectionKeys(cache)) return cache.cachedSnapshot(header);
321
- return cache.cachedSnapshot(header, inheritedEventCount);
316
+ function projectionSnapshot(cache, header) {
317
+ return cache.cachedSnapshot(header);
322
318
  }
323
319
  function hostEvent(ctx, name) {
324
320
  const caller = ctx[name];
@@ -382,7 +378,7 @@ var ArchiveWorkspaceRegistry = class extends WorkspaceRegistry {
382
378
  const live = this.ctx.get("sessions")?.get(sessionId);
383
379
  if (typeof live?.snapshotEvents === "function") return live.snapshotEvents();
384
380
  const persistence = this.ctx.get("sessionPersistence");
385
- if (!persistence || typeof persistence.readFrom !== "function" && typeof persistence.open !== "function") throw new Error("\u5F53\u524D\u5BBF\u4E3B\u4E0D\u652F\u6301\u53EA\u8BFB\u4F1A\u8BDD\uFF0C\u8BF7\u6253\u5F00\u5B8C\u6574\u4F1A\u8BDD\u67E5\u770B");
381
+ if (!persistence || typeof persistence.open !== "function") throw new Error("\u5F53\u524D\u5BBF\u4E3B\u4E0D\u652F\u6301\u53EA\u8BFB\u4F1A\u8BDD\uFF0C\u8BF7\u6253\u5F00\u5B8C\u6574\u4F1A\u8BDD\u67E5\u770B");
386
382
  return (await this.readStoredProjectionSource(persistence, sessionId)).events;
387
383
  }
388
384
  /** 只读取当前宿主已知会话;路径由宿主定位,不根据错误文本或 ID 拼接。 */
@@ -686,10 +682,10 @@ var ArchiveWorkspaceRegistry = class extends WorkspaceRegistry {
686
682
  const projections = this.ctx.get("sessionProjections");
687
683
  if (cache === void 0 || typeof cache.cachedSnapshot !== "function" || typeof cache.put !== "function")
688
684
  return false;
689
- if (persistence === void 0 || typeof persistence.readFrom !== "function" && typeof persistence.open !== "function" || projections === void 0 || typeof projections.restore !== "function")
685
+ if (persistence === void 0 || typeof persistence.open !== "function" || projections === void 0 || typeof projections.restore !== "function")
690
686
  return false;
691
687
  try {
692
- if (!header.isSeeded && projectionSnapshot(cache, header, 0) !== void 0)
688
+ if (!header.isSeeded && projectionSnapshot(cache, header) !== void 0)
693
689
  return false;
694
690
  const stored = await this.readStoredProjectionSource(persistence, header.id);
695
691
  const meta = stored.meta ?? header;
@@ -706,7 +702,7 @@ var ArchiveWorkspaceRegistry = class extends WorkspaceRegistry {
706
702
  );
707
703
  return false;
708
704
  }
709
- if (projectionSnapshot(cache, meta, inheritedEventCount) !== void 0) return false;
705
+ if (projectionSnapshot(cache, meta) !== void 0) return false;
710
706
  const restored = projections.restore(
711
707
  {},
712
708
  stored.events,
@@ -736,10 +732,8 @@ var ArchiveWorkspaceRegistry = class extends WorkspaceRegistry {
736
732
  return false;
737
733
  }
738
734
  }
739
- /** 新版读句柄必须关闭;旧版仍沿用 readFrom,避免激活 Agent 或写入会话日志。 */
735
+ /** 只读句柄必须关闭,避免激活 Agent 或写入会话日志。 */
740
736
  async readStoredProjectionSource(persistence, sessionId) {
741
- if (typeof persistence.readFrom === "function")
742
- return persistence.readFrom(sessionId, 0);
743
737
  const handle = await persistence.open(sessionId, "read");
744
738
  try {
745
739
  const { events } = await handle.read(0);
@@ -777,7 +771,7 @@ var ArchiveWorkspaceRegistry = class extends WorkspaceRegistry {
777
771
  if (stopActivity && ActiveSession !== void 0) await this.stopSessionActivity(sessionId);
778
772
  });
779
773
  }
780
- /** 0.1.7 起宿主用 waterfall 报告仍在运行的回合、子代理、任务和提醒。旧宿主没有该事件。 */
774
+ /** 宿主用 waterfall 报告仍在运行的回合、子代理、任务和提醒。 */
781
775
  async sessionActivity(sessionId) {
782
776
  const waterfall = hostEvent(this.ctx, "waterfall");
783
777
  if (waterfall === void 0) return [];
@@ -1060,14 +1054,12 @@ var ArchiveWorkspaceRegistry = class extends WorkspaceRegistry {
1060
1054
  if (this.deletedSessionIds.has(header.id)) return;
1061
1055
  return super.indexHeader(header);
1062
1056
  }
1063
- /** 统一旧版头部数组与 0.1.3 的持久化快照,供父类索引和本插件枚举共用。 */
1057
+ /** 持久化列表返回快照,这里只取出头部。 */
1064
1058
  async listStoredHeaders() {
1065
- return (await this.ctx.sessionPersistence.list()).map(
1066
- (item) => "header" in item && item.header ? item.header : item
1067
- );
1059
+ return (await this.ctx.sessionPersistence.list()).map((item) => item.header);
1068
1060
  }
1069
1061
  async indexHeaders(items) {
1070
- for (const item of items) await this.indexHeader("header" in item && item.header ? item.header : item);
1062
+ for (const item of items) await this.indexHeader(item);
1071
1063
  }
1072
1064
  /** 为未处于实时状态的持久化会话发布相同的移除事件。 */
1073
1065
  async publishColdSessionRemoval(sessionId, sessions) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@michengai/dsh-archive-manager",
3
- "version": "1.0.20",
3
+ "version": "1.1.0",
4
4
  "description": "归档、恢复、收藏和永久删除会话,并诊断损坏的会话日志。 · Archive, restore, favorite, and permanently delete sessions, and diagnose damaged session logs.",
5
5
  "type": "module",
6
6
  "packageManager": "pnpm@11.22.0",
@@ -34,7 +34,7 @@
34
34
  "test": "pnpm build && node --import tsx --test test/*.test.mjs",
35
35
  "test:matrix": "pnpm build && node scripts/test-version-matrix.mjs",
36
36
  "test:latest": "pnpm build && node scripts/test-latest-compatibility.mjs",
37
- "test:compat": "pnpm build && node scripts/test-legacy-compatibility.mjs && pnpm test:matrix",
37
+ "test:compat": "pnpm build && pnpm test:matrix",
38
38
  "pack:check": "pnpm pack --dry-run",
39
39
  "verify": "pnpm test && pnpm test:compat && pnpm pack:check && node scripts/check-generated.mjs",
40
40
  "release:preflight": "pwsh -NoProfile -File scripts/release-preflight.ps1",
@@ -43,63 +43,58 @@
43
43
  "typecheck": "tsc --noEmit"
44
44
  },
45
45
  "peerDependencies": {
46
- "@deepseek-ai/cordis": ">=4.0.1 <5.0.0 || 4.0.5-alpha.1 || 4.0.5-alpha.2",
47
- "@deepseek-ai/dsh-client-connection": "0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.5-rc.3 || 0.1.7-rc.1 || 0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.2 || 0.2.1-alpha.3",
48
- "@deepseek-ai/dsh-client-locale": "0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.5-rc.3 || 0.1.7-rc.1 || 0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.2 || 0.2.1-alpha.3",
49
- "@deepseek-ai/dsh-client-store": "0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.5-rc.3 || 0.1.7-rc.1 || 0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.2 || 0.2.1-alpha.3",
50
- "@deepseek-ai/dsh-client-ui-conversation": "0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.5-rc.3 || 0.1.7-rc.1 || 0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.2 || 0.2.1-alpha.3",
51
- "@deepseek-ai/dsh-client-ui-primitives": "0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.5-rc.3 || 0.1.7-rc.1 || 0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.2 || 0.2.1-alpha.3",
52
- "@deepseek-ai/dsh-client-ui-sidebar": "0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.5-rc.3 || 0.1.7-rc.1 || 0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.2 || 0.2.1-alpha.3",
53
- "@deepseek-ai/dsh-client-ui-workspace": "0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.5-rc.3 || 0.1.7-rc.1 || 0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.2 || 0.2.1-alpha.3",
54
- "@deepseek-ai/dsh-host-webserver": "0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.5-rc.3 || 0.1.7-rc.1 || 0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.2 || 0.2.1-alpha.3",
55
- "@deepseek-ai/dsh-session": "0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.5-rc.3 || 0.1.7-rc.1 || 0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.2 || 0.2.1-alpha.3",
56
- "@deepseek-ai/dsh-session-format-catalog": "0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.5-rc.3 || 0.1.7-rc.1 || 0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.2 || 0.2.1-alpha.3",
57
- "@deepseek-ai/dsh-session-projection-cache": "0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.5-rc.3 || 0.1.7-rc.1 || 0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.2 || 0.2.1-alpha.3",
58
- "@deepseek-ai/dsh-spill-local": "0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.5-rc.3 || 0.1.7-rc.1 || 0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.2 || 0.2.1-alpha.3",
59
- "@deepseek-ai/dsh-storage-domain": "0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.5-rc.3 || 0.1.7-rc.1 || 0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.2 || 0.2.1-alpha.3",
60
- "@deepseek-ai/dsh-typert-protocol": "0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.5-rc.3 || 0.1.7-rc.1 || 0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.2 || 0.2.1-alpha.3",
61
- "@deepseek-ai/dsh-typert-registry": "0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.5-rc.3 || 0.1.7-rc.1 || 0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.2 || 0.2.1-alpha.3",
62
- "@deepseek-ai/dsh-workspace": "0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.5-rc.3 || 0.1.7-rc.1 || 0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-alpha.2 || 0.2.1-alpha.3"
46
+ "@deepseek-ai/cordis": ">=4.0.1 <5.0.0",
47
+ "@deepseek-ai/dsh-client-connection": "0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-rc.1 || 0.2.1-rc.2",
48
+ "@deepseek-ai/dsh-client-locale": "0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-rc.1 || 0.2.1-rc.2",
49
+ "@deepseek-ai/dsh-client-store": "0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-rc.1 || 0.2.1-rc.2",
50
+ "@deepseek-ai/dsh-client-ui-conversation": "0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-rc.1 || 0.2.1-rc.2",
51
+ "@deepseek-ai/dsh-client-ui-primitives": "0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-rc.1 || 0.2.1-rc.2",
52
+ "@deepseek-ai/dsh-client-ui-sidebar": "0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-rc.1 || 0.2.1-rc.2",
53
+ "@deepseek-ai/dsh-client-ui-workspace": "0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-rc.1 || 0.2.1-rc.2",
54
+ "@deepseek-ai/dsh-host-webserver": "0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-rc.1 || 0.2.1-rc.2",
55
+ "@deepseek-ai/dsh-session": "0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-rc.1 || 0.2.1-rc.2",
56
+ "@deepseek-ai/dsh-session-format-catalog": "0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-rc.1 || 0.2.1-rc.2",
57
+ "@deepseek-ai/dsh-session-projection-cache": "0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-rc.1 || 0.2.1-rc.2",
58
+ "@deepseek-ai/dsh-spill-local": "0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-rc.1 || 0.2.1-rc.2",
59
+ "@deepseek-ai/dsh-storage-domain": "0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-rc.1 || 0.2.1-rc.2",
60
+ "@deepseek-ai/dsh-typert-protocol": "0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-rc.1 || 0.2.1-rc.2",
61
+ "@deepseek-ai/dsh-typert-registry": "0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-rc.1 || 0.2.1-rc.2",
62
+ "@deepseek-ai/dsh-workspace": "0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-rc.1 || 0.2.1-rc.2"
63
63
  },
64
64
  "peerDependenciesMeta": {
65
65
  "@deepseek-ai/dsh-session-format-catalog": {
66
66
  "optional": true
67
- },
68
- "@deepseek-ai/dsh-client-store": {
69
- "optional": true
70
67
  }
71
68
  },
72
69
  "devDependencies": {
73
- "@deepseek-ai/cordis": "4.0.5-alpha.2",
74
- "@deepseek-ai/dsh-api-gateway": "0.2.1-alpha.3",
75
- "@deepseek-ai/dsh-client-connection": "0.2.1-alpha.3",
76
- "@deepseek-ai/dsh-client-locale": "0.2.1-alpha.3",
77
- "@deepseek-ai/dsh-client-store": "0.2.1-alpha.3",
78
- "@deepseek-ai/dsh-client-ui-conversation": "0.2.1-alpha.3",
79
- "@deepseek-ai/dsh-client-ui-primitives": "0.2.1-alpha.3",
80
- "@deepseek-ai/dsh-client-ui-renderer": "0.2.1-alpha.3",
81
- "@deepseek-ai/dsh-client-ui-sidebar": "0.2.1-alpha.3",
82
- "@deepseek-ai/dsh-client-ui-slots": "0.2.1-alpha.3",
83
- "@deepseek-ai/dsh-client-ui-workspace": "0.2.1-alpha.3",
84
- "@deepseek-ai/dsh-host-webserver": "0.2.1-alpha.3",
85
- "@deepseek-ai/dsh-scope": "0.2.1-alpha.3",
86
- "@deepseek-ai/dsh-session": "0.2.1-alpha.3",
87
- "@deepseek-ai/dsh-session-format-catalog": "0.2.1-alpha.3",
88
- "@deepseek-ai/dsh-session-persistence": "0.2.1-alpha.3",
89
- "@deepseek-ai/dsh-session-projection": "0.2.1-alpha.3",
90
- "@deepseek-ai/dsh-session-projection-cache": "0.2.1-alpha.3",
91
- "@deepseek-ai/dsh-spill": "0.2.1-alpha.3",
92
- "@deepseek-ai/dsh-spill-local": "0.2.1-alpha.3",
93
- "@deepseek-ai/dsh-storage": "0.2.1-alpha.3",
94
- "@deepseek-ai/dsh-storage-domain": "0.2.1-alpha.3",
95
- "@deepseek-ai/dsh-typert-protocol": "0.2.1-alpha.3",
96
- "@deepseek-ai/dsh-typert-registry": "0.2.1-alpha.3",
97
- "@deepseek-ai/dsh-workspace": "0.2.1-alpha.3",
70
+ "@deepseek-ai/cordis": "4.0.5",
71
+ "@deepseek-ai/dsh-api-gateway": "0.2.1-rc.2",
72
+ "@deepseek-ai/dsh-client-connection": "0.2.1-rc.2",
73
+ "@deepseek-ai/dsh-client-locale": "0.2.1-rc.2",
74
+ "@deepseek-ai/dsh-client-store": "0.2.1-rc.2",
75
+ "@deepseek-ai/dsh-client-ui-conversation": "0.2.1-rc.2",
76
+ "@deepseek-ai/dsh-client-ui-primitives": "0.2.1-rc.2",
77
+ "@deepseek-ai/dsh-client-ui-renderer": "0.2.1-rc.2",
78
+ "@deepseek-ai/dsh-client-ui-sidebar": "0.2.1-rc.2",
79
+ "@deepseek-ai/dsh-client-ui-slots": "0.2.1-rc.2",
80
+ "@deepseek-ai/dsh-client-ui-workspace": "0.2.1-rc.2",
81
+ "@deepseek-ai/dsh-host-webserver": "0.2.1-rc.2",
82
+ "@deepseek-ai/dsh-scope": "0.2.1-rc.2",
83
+ "@deepseek-ai/dsh-session": "0.2.1-rc.2",
84
+ "@deepseek-ai/dsh-session-format-catalog": "0.2.1-rc.2",
85
+ "@deepseek-ai/dsh-session-persistence": "0.2.1-rc.2",
86
+ "@deepseek-ai/dsh-session-projection": "0.2.1-rc.2",
87
+ "@deepseek-ai/dsh-session-projection-cache": "0.2.1-rc.2",
88
+ "@deepseek-ai/dsh-spill": "0.2.1-rc.2",
89
+ "@deepseek-ai/dsh-spill-local": "0.2.1-rc.2",
90
+ "@deepseek-ai/dsh-storage": "0.2.1-rc.2",
91
+ "@deepseek-ai/dsh-storage-domain": "0.2.1-rc.2",
92
+ "@deepseek-ai/dsh-typert-protocol": "0.2.1-rc.2",
93
+ "@deepseek-ai/dsh-typert-registry": "0.2.1-rc.2",
94
+ "@deepseek-ai/dsh-workspace": "0.2.1-rc.2",
98
95
  "@types/node": "^22.20.4",
99
96
  "@types/react": "^18.3.31",
100
97
  "@types/react-dom": "^18.0.0",
101
- "antd": "6.6.5",
102
- "dayjs": "1.11.23",
103
98
  "esbuild": "0.25.0",
104
99
  "immer": "10.1.1",
105
100
  "react": "18.3.1",