@michengai/dsh-archive-manager 0.1.41 → 0.1.43

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/lib/workspace.js CHANGED
@@ -41,17 +41,6 @@ function markRemoteMethod(instance, method) {
41
41
  };
42
42
  Remote(method)(void 0, context);
43
43
  }
44
- function unknownSessionMessage(sessionId) {
45
- return `unknown session "${sessionId}" (UNKNOWN_SESSION)`;
46
- }
47
- var ArchiveUnknownSessionError = class extends Error {
48
- sessionId;
49
- constructor(sessionId) {
50
- super(unknownSessionMessage(sessionId));
51
- this.sessionId = sessionId;
52
- this.name = "ArchiveUnknownSessionError";
53
- }
54
- };
55
44
  function headerIdentity(header) {
56
45
  return {
57
46
  createdAt: header.createdAt,
@@ -67,15 +56,6 @@ const sessionIdSchema = {
67
56
  return value;
68
57
  }
69
58
  };
70
- const workspaceIdSchema = {
71
- parse(value) {
72
- if (typeof value !== "string" || value.length === 0)
73
- throw new TypeError(
74
- `workspaceId must be a non-empty string, got ${String(value)}`
75
- );
76
- return value;
77
- }
78
- };
79
59
  const archivedSetSchema = {
80
60
  parse(value) {
81
61
  if (typeof value !== "object" || value === null || Array.isArray(value))
@@ -107,28 +87,6 @@ const archivedBatchTargetSchema = {
107
87
  );
108
88
  }
109
89
  };
110
- const unarchivedBatchSchema = {
111
- parse(value) {
112
- if (typeof value !== "object" || value === null || Array.isArray(value))
113
- throw new TypeError("result must be an object");
114
- if (!Array.isArray(value.archivedSessionIds) || value.archivedSessionIds.some((id) => typeof id !== "string"))
115
- throw new TypeError("archivedSessionIds must be a string array");
116
- if (!Array.isArray(value.unarchivedSessionIds) || value.unarchivedSessionIds.some((id) => typeof id !== "string"))
117
- throw new TypeError("unarchivedSessionIds must be a string array");
118
- return value;
119
- }
120
- };
121
- const archivedWorkspaceBatchSchema = {
122
- parse(value) {
123
- if (typeof value !== "object" || value === null || Array.isArray(value))
124
- throw new TypeError("result must be an object");
125
- if (!Array.isArray(value.archivedSessionIds) || value.archivedSessionIds.some((id) => typeof id !== "string"))
126
- throw new TypeError("archivedSessionIds must be a string array");
127
- if (!Array.isArray(value.archivedSessionIdsAdded) || value.archivedSessionIdsAdded.some((id) => typeof id !== "string"))
128
- throw new TypeError("archivedSessionIdsAdded must be a string array");
129
- return value;
130
- }
131
- };
132
90
  const deletedBatchSchema = {
133
91
  parse(value) {
134
92
  if (typeof value !== "object" || value === null || Array.isArray(value))
@@ -220,64 +178,6 @@ const ARCHIVE_MANAGER_INVOCATIONS = [
220
178
  column: 1
221
179
  }
222
180
  },
223
- {
224
- id: "@michengai/dsh-archive-manager#workspaceRegistry/unarchiveSessions",
225
- service: "workspaceRegistry",
226
- namespace: "workspaceRegistry",
227
- method: "unarchiveSessions",
228
- invocation: { kind: "direct" },
229
- parameters: [
230
- {
231
- name: "target",
232
- wire: "target",
233
- source: "json",
234
- codec: {
235
- mode: "strict",
236
- typeSymbol: "@michengai/dsh-archive-manager/types#ArchivedBatchTarget",
237
- schema: archivedBatchTargetSchema
238
- }
239
- }
240
- ],
241
- result: {
242
- mode: "strict",
243
- typeSymbol: "@michengai/dsh-archive-manager/types#UnarchivedBatch",
244
- schema: unarchivedBatchSchema
245
- },
246
- sourceLocation: {
247
- file: "@michengai/dsh-archive-manager/lib/workspace.js",
248
- line: 1,
249
- column: 1
250
- }
251
- },
252
- {
253
- id: "@michengai/dsh-archive-manager#workspaceRegistry/archiveWorkspaceSessions",
254
- service: "workspaceRegistry",
255
- namespace: "workspaceRegistry",
256
- method: "archiveWorkspaceSessions",
257
- invocation: { kind: "direct" },
258
- parameters: [
259
- {
260
- name: "workspaceId",
261
- wire: "workspaceId",
262
- source: "json",
263
- codec: {
264
- mode: "strict",
265
- typeSymbol: "@deepseek-ai/dsh-workspace/types#WorkspaceId",
266
- schema: workspaceIdSchema
267
- }
268
- }
269
- ],
270
- result: {
271
- mode: "strict",
272
- typeSymbol: "@michengai/dsh-archive-manager/types#ArchivedWorkspaceBatch",
273
- schema: archivedWorkspaceBatchSchema
274
- },
275
- sourceLocation: {
276
- file: "@michengai/dsh-archive-manager/lib/workspace.js",
277
- line: 1,
278
- column: 1
279
- }
280
- },
281
181
  {
282
182
  id: "@michengai/dsh-archive-manager#workspaceRegistry/deleteArchivedSessions",
283
183
  service: "workspaceRegistry",
@@ -358,28 +258,113 @@ var ArchiveWorkspaceRegistry = class extends WorkspaceRegistry {
358
258
  deletedSessionTombstoneLimit = 4096;
359
259
  /** 被删生命周期的日志身份(createdAt/cwd):冷复用探针区分“同 id 新会话”与 stale list() 的依据。 */
360
260
  deletedIdentities = /* @__PURE__ */ new Map();
261
+ archivedSessionPathIndex = /* @__PURE__ */ new Map();
262
+ archivedSessionPathIndexKey;
361
263
  constructor(ctx) {
362
264
  super(ctx);
265
+ const indexedPath = this.host.sessionPath;
266
+ this.host.sessionPath = (id) => {
267
+ const path = indexedPath(id);
268
+ if (path !== void 0) return path;
269
+ if (this.invalidSessionPaths.has(id)) return void 0;
270
+ try {
271
+ return this.archivedWorkspacePath(id);
272
+ } catch {
273
+ return void 0;
274
+ }
275
+ };
363
276
  this.typertRemote = bindTypertRemote(this, this.name);
364
277
  markRemoteMethod(this, "unarchiveSession");
365
278
  markRemoteMethod(this, "deleteSession");
366
- markRemoteMethod(this, "unarchiveSessions");
367
- markRemoteMethod(this, "archiveWorkspaceSessions");
368
279
  markRemoteMethod(this, "deleteArchivedSessions");
369
280
  markRemoteMethod(this, "archivedSessionMetadata");
370
281
  registerHostRemote(this.ctx);
371
282
  }
283
+ /** 归档集合未变时复用反查表,避免每次 sessionPath 都扫全部工作区记账。 */
284
+ archivedWorkspacePath(sessionId) {
285
+ const state = this.requireState();
286
+ if (!state.archivedSessionIds.includes(sessionId)) return void 0;
287
+ if (this.archivedSessionPathIndexKey !== state.archivedSessionIds) {
288
+ const index = /* @__PURE__ */ new Map();
289
+ const archived = new Set(state.archivedSessionIds);
290
+ const table = this.requireTable();
291
+ for (const workspaceId of state.workspaceIds) {
292
+ const record = table.get(workspaceId);
293
+ if (record === void 0) continue;
294
+ for (const id of record.sessionIds) {
295
+ if (archived.has(id)) index.set(id, record.path);
296
+ }
297
+ }
298
+ this.archivedSessionPathIndex = index;
299
+ this.archivedSessionPathIndexKey = state.archivedSessionIds;
300
+ }
301
+ return this.archivedSessionPathIndex.get(sessionId);
302
+ }
303
+ /**
304
+ * 只有 persistence.stat 明确说文件不在时才从持久集合摘掉。
305
+ * list/header 读不出不等于文件没了;没有 stat 时宁可不落盘删除。
306
+ */
307
+ async sessionArtifactMissing(sessionId) {
308
+ const persistence = this.ctx.get("sessionPersistence");
309
+ if (typeof persistence?.stat !== "function") return false;
310
+ try {
311
+ return await persistence.stat(sessionId) === void 0;
312
+ } catch (error) {
313
+ this.ctx.logger.warn(
314
+ `archive-manager: could not stat archived session "${sessionId}": ${String(error)}`
315
+ );
316
+ return false;
317
+ }
318
+ }
319
+ /**
320
+ * 从归档集合摘掉已经确认不存在的会话。打开归档列表时调用。
321
+ * 读不出头部的标记留在持久集合里,只从本次元数据结果里隐藏。
322
+ */
323
+ async pruneUnknownArchivedSessionIds() {
324
+ return this.enqueueOperation(async () => {
325
+ const state = this.requireState();
326
+ const listed = /* @__PURE__ */ new Set();
327
+ for (const item of await this.listStoredHeaders()) {
328
+ const header = item.header ?? item;
329
+ if (typeof header?.id === "string") listed.add(header.id);
330
+ }
331
+ const sessions = this.ctx.get("sessions");
332
+ const kept = [];
333
+ const seen = /* @__PURE__ */ new Set();
334
+ for (const sessionId of state.archivedSessionIds) {
335
+ if (seen.has(sessionId)) continue;
336
+ seen.add(sessionId);
337
+ if (sessions?.get(sessionId) !== void 0) {
338
+ kept.push(sessionId);
339
+ continue;
340
+ }
341
+ if (this.deletedSessionIds.has(sessionId)) {
342
+ if (await this.coldReuseKnown(sessionId)) kept.push(sessionId);
343
+ continue;
344
+ }
345
+ if (this.headers.has(sessionId) || listed.has(sessionId)) {
346
+ kept.push(sessionId);
347
+ continue;
348
+ }
349
+ if (!await this.sessionArtifactMissing(sessionId)) kept.push(sessionId);
350
+ }
351
+ if (kept.length === state.archivedSessionIds.length && kept.every((id, index) => id === state.archivedSessionIds[index]))
352
+ return kept;
353
+ await this.setState({ ...state, archivedSessionIds: kept });
354
+ return kept;
355
+ });
356
+ }
372
357
  /**
373
358
  * 归档设置页创建时间排序所需的最小元数据。老用户可能仍有会话原文和
374
359
  * 归档标记、却没有投影缓存;这里按需从完整日志重建一次,再通知客户端
375
360
  * 刷新会话列表。已有缓存不读原文,新老 DSH 的缓存布局都走同一 put。
361
+ * 读取前只清掉文件已确认不存在的归档标记。
376
362
  */
377
363
  async archivedSessionMetadata() {
364
+ await this.pruneUnknownArchivedSessionIds();
378
365
  const items = [];
379
366
  const repairedSessionIds = [];
380
- for (const sessionId of [
381
- ...new Set(this.requireState().archivedSessionIds)
382
- ]) {
367
+ for (const sessionId of this.requireState().archivedSessionIds) {
383
368
  try {
384
369
  const header = await this.readSessionHeader(sessionId);
385
370
  if (await this.repairArchivedProjection(header))
@@ -470,17 +455,32 @@ var ArchiveWorkspaceRegistry = class extends WorkspaceRegistry {
470
455
  await handle.close();
471
456
  }
472
457
  }
458
+ /**
459
+ * 把一个已知会话加入注册表全局归档集合。已归档的 id 不写入;
460
+ * 未知 id 直接跳过,不抛 `UNKNOWN_SESSION`,避免把幽灵 id 写进集合。
461
+ * @param sessionId - 要归档的会话。
462
+ */
463
+ async archiveSession(sessionId) {
464
+ return this.enqueueOperation(async () => {
465
+ if (this.requireState().archivedSessionIds.includes(sessionId)) return;
466
+ if (!await this.sessionKnown(sessionId)) return;
467
+ const state = this.requireState();
468
+ await this.setState({
469
+ ...state,
470
+ archivedSessionIds: [...state.archivedSessionIds, sessionId]
471
+ });
472
+ });
473
+ }
473
474
  /**
474
475
  * 把一个会话移出注册表全局归档集合,恢复其正常可见性(其记账位从未
475
- * 移动,会话在原工作区位置重新出现)。幂等:未归档的已知会话直接返回
476
- * 当前集合不写入;未知会话与 `archiveSession` 一样抛错。
476
+ * 移动,会话在原工作区位置重新出现)。与官方一致:不做会话存在性检查,
477
+ * 因为从集合摘掉 id 不会引入未知引用。孤儿归档标记也会被清掉;
478
+ * 未归档的 id(含不存在的 id)不写入即返回。
477
479
  * @param sessionId - 要取消归档的会话。
478
480
  * @returns 更新后的完整归档集合。
479
481
  */
480
482
  async unarchiveSession(sessionId) {
481
483
  return this.enqueueOperation(async () => {
482
- if (!await this.sessionKnown(sessionId))
483
- throw new ArchiveUnknownSessionError(sessionId);
484
484
  const state = this.requireState();
485
485
  if (!state.archivedSessionIds.includes(sessionId))
486
486
  return { archivedSessionIds: [...state.archivedSessionIds] };
@@ -491,73 +491,33 @@ var ArchiveWorkspaceRegistry = class extends WorkspaceRegistry {
491
491
  )
492
492
  };
493
493
  await this.setState(next);
494
+ await this.restoreWorkspaceMembership(sessionId);
494
495
  return { archivedSessionIds: [...next.archivedSessionIds] };
495
496
  });
496
497
  }
497
498
  /**
498
- * 将一个工作区内所有会话加入归档集合。先确认所有待归档会话仍存在,
499
- * 再执行单次状态写入,因此未知会话不会导致项目只归档一部分。
499
+ * 恢复后重新编入路径索引;若会话已不在任何工作区记账但 cwd 仍对应某工作区,
500
+ * 则挂回去,避免「恢复并打开」时官方成员过滤把会话从原工作区抹掉。
500
501
  */
501
- async archiveWorkspaceSessions(workspaceId) {
502
- return this.enqueueOperation(async () => {
503
- workspaceId = workspaceIdSchema.parse(workspaceId);
504
- const workspace = this.requireTable().get(workspaceId);
505
- if (workspace === void 0)
506
- throw new Error(`unknown workspace "${workspaceId}"`);
507
- const state = this.requireState();
508
- const archived = new Set(state.archivedSessionIds);
509
- const archivedSessionIdsAdded = [...new Set(workspace.sessionIds)].filter(
510
- (sessionId) => !archived.has(sessionId)
511
- );
512
- for (const sessionId of archivedSessionIdsAdded) {
513
- if (!await this.sessionKnown(sessionId))
514
- throw new ArchiveUnknownSessionError(sessionId);
515
- }
516
- if (archivedSessionIdsAdded.length === 0)
517
- return {
518
- archivedSessionIds: [...state.archivedSessionIds],
519
- archivedSessionIdsAdded
520
- };
521
- const next = {
522
- ...state,
523
- archivedSessionIds: [
524
- ...state.archivedSessionIds,
525
- ...archivedSessionIdsAdded
526
- ]
527
- };
528
- await this.setState(next);
529
- return {
530
- archivedSessionIds: [...next.archivedSessionIds],
531
- archivedSessionIdsAdded
532
- };
533
- });
534
- }
535
- /**
536
- * 按宿主权威归档集合一次恢复全部、一个工作区或未分组的归档会话。
537
- * 目标全部来自已归档集合,因此即使日志已被外部移除,也会清掉陈旧归档标记。
538
- */
539
- async unarchiveSessions(target) {
540
- return this.enqueueOperation(async () => {
541
- const unarchivedSessionIds = this.archivedSessionIdsForTarget(target);
542
- if (unarchivedSessionIds.length === 0)
543
- return {
544
- archivedSessionIds: [...this.requireState().archivedSessionIds],
545
- unarchivedSessionIds: []
546
- };
547
- const restored = new Set(unarchivedSessionIds);
548
- const state = this.requireState();
549
- const next = {
550
- ...state,
551
- archivedSessionIds: state.archivedSessionIds.filter(
552
- (id) => !restored.has(id)
553
- )
554
- };
555
- await this.setState(next);
556
- return {
557
- archivedSessionIds: [...next.archivedSessionIds],
558
- unarchivedSessionIds
559
- };
560
- });
502
+ async restoreWorkspaceMembership(sessionId) {
503
+ let header;
504
+ try {
505
+ header = await this.readSessionHeader(sessionId);
506
+ await this.indexHeader(header);
507
+ } catch {
508
+ return;
509
+ }
510
+ const path = this.sessionPaths.get(sessionId);
511
+ if (path === void 0) return;
512
+ const table = this.requireTable();
513
+ for (const workspaceId of this.requireState().workspaceIds) {
514
+ const record = table.get(workspaceId);
515
+ if (record === void 0 || record.path !== path) continue;
516
+ if (record.sessionIds.includes(sessionId)) return;
517
+ const entity = this.entities.get(workspaceId);
518
+ if (entity !== void 0) await entity.attachSession(sessionId);
519
+ return;
520
+ }
561
521
  }
562
522
  /**
563
523
  * 按作用域永久删除归档会话。跨会话文件删除无法组成事务,因此继续处理
@@ -571,18 +531,10 @@ var ArchiveWorkspaceRegistry = class extends WorkspaceRegistry {
571
531
  const failures = [];
572
532
  for (const sessionId of requestedSessionIds) {
573
533
  try {
574
- await this.deleteSessionCore(sessionId);
575
- deletedSessionIds.push(sessionId);
534
+ const result = await this.deleteSessionCore(sessionId);
535
+ if (result?.skipped) skippedSessionIds.push(sessionId);
536
+ else deletedSessionIds.push(sessionId);
576
537
  } catch (error) {
577
- if (error instanceof ArchiveUnknownSessionError) {
578
- try {
579
- await this.cleanupUnknownArchivedSession(sessionId);
580
- skippedSessionIds.push(sessionId);
581
- } catch (cleanupError) {
582
- failures.push({ sessionId, message: String(cleanupError) });
583
- }
584
- continue;
585
- }
586
538
  failures.push({ sessionId, message: String(error) });
587
539
  }
588
540
  }
@@ -648,16 +600,20 @@ var ArchiveWorkspaceRegistry = class extends WorkspaceRegistry {
648
600
  * 永久删除一个会话及其全部痕迹(转录目录、工作区记账、归档标记、
649
601
  * 投影缓存行)。
650
602
  * @param sessionId - 要删除的会话。
651
- * @returns 持久化完成后的 `{ deleted: true }`。
652
- * @throws {@link ArchiveUnknownSessionError} 会话未知时抛出。
603
+ * @returns 持久化完成后的 `{ deleted: true }`。未知会话清掉残留痕迹后同样返回成功,不抛错。
653
604
  */
654
605
  async deleteSession(sessionId) {
655
- return this.enqueueOperation(() => this.deleteSessionCore(sessionId));
606
+ return this.enqueueOperation(async () => {
607
+ await this.deleteSessionCore(sessionId);
608
+ return { deleted: true };
609
+ });
656
610
  }
657
611
  /** 串行化后的删除主体(级联路径复用:它已持有操作链,绝不能再入队)。 */
658
612
  async deleteSessionCore(sessionId) {
659
- if (!await this.sessionKnown(sessionId))
660
- throw new ArchiveUnknownSessionError(sessionId);
613
+ if (!await this.sessionKnown(sessionId)) {
614
+ await this.cleanupUnknownArchivedSession(sessionId);
615
+ return { deleted: true, skipped: true };
616
+ }
661
617
  const sessions = this.ctx.get("sessions");
662
618
  const live = sessions?.get(sessionId);
663
619
  const deletedHeader = this.headers.get(sessionId) ?? live?.header;
@@ -887,7 +843,6 @@ var ArchiveWorkspaceRegistry = class extends WorkspaceRegistry {
887
843
  if (!await this.sessionKnown(childId)) continue;
888
844
  await this.deleteSessionCore(childId);
889
845
  } catch (error) {
890
- if (error instanceof ArchiveUnknownSessionError) continue;
891
846
  this.ctx.logger.warn(
892
847
  `archive-manager: cascade delete of subagent session "${childId}" (child of "${sessionId}") failed: ${String(error)}`
893
848
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@michengai/dsh-archive-manager",
3
- "version": "0.1.41",
3
+ "version": "0.1.43",
4
4
  "description": "NPM-installable DSH Web plugin for managing archived sessions.",
5
5
  "type": "module",
6
6
  "packageManager": "pnpm@11.22.0",
@@ -38,22 +38,22 @@
38
38
  },
39
39
  "peerDependencies": {
40
40
  "@deepseek-ai/cordis": "^4.0.1",
41
- "@deepseek-ai/dsh-client-connection": "0.1.0-rc.8 || 0.1.1-rc.2 || 0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2",
42
- "@deepseek-ai/dsh-client-locale": "0.1.0-rc.8 || 0.1.1-rc.2 || 0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2",
43
- "@deepseek-ai/dsh-client-runtime": "0.1.0-rc.8 || 0.1.1-rc.2 || 0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2",
44
- "@deepseek-ai/dsh-client-store": "0.1.0-rc.8 || 0.1.1-rc.2 || 0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2",
45
- "@deepseek-ai/dsh-client-ui-conversation": "0.1.0-rc.8 || 0.1.1-rc.2 || 0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2",
46
- "@deepseek-ai/dsh-client-ui-primitives": "0.1.0-rc.8 || 0.1.1-rc.2 || 0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2",
47
- "@deepseek-ai/dsh-client-ui-sidebar": "0.1.0-rc.8 || 0.1.1-rc.2 || 0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2",
48
- "@deepseek-ai/dsh-client-ui-workspace": "0.1.0-rc.8 || 0.1.1-rc.2 || 0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2",
49
- "@deepseek-ai/dsh-host-webserver": "0.1.0-rc.8 || 0.1.1-rc.2 || 0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2",
50
- "@deepseek-ai/dsh-session": "0.1.0-rc.8 || 0.1.1-rc.2 || 0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2",
51
- "@deepseek-ai/dsh-session-projection-cache": "0.1.0-rc.8 || 0.1.1-rc.2 || 0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2",
52
- "@deepseek-ai/dsh-spill-local": "0.1.0-rc.8 || 0.1.1-rc.2 || 0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2",
53
- "@deepseek-ai/dsh-storage-domain": "0.1.0-rc.8 || 0.1.1-rc.2 || 0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2",
54
- "@deepseek-ai/dsh-typert-protocol": "0.1.0-rc.8 || 0.1.1-rc.2 || 0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2",
55
- "@deepseek-ai/dsh-typert-registry": "0.1.0-rc.8 || 0.1.1-rc.2 || 0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2",
56
- "@deepseek-ai/dsh-workspace": "0.1.0-rc.8 || 0.1.1-rc.2 || 0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2"
41
+ "@deepseek-ai/dsh-client-connection": "0.1.0-rc.8 || 0.1.1-rc.2 || 0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.6-alpha.1",
42
+ "@deepseek-ai/dsh-client-locale": "0.1.0-rc.8 || 0.1.1-rc.2 || 0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.6-alpha.1",
43
+ "@deepseek-ai/dsh-client-runtime": "0.1.0-rc.8 || 0.1.1-rc.2 || 0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.6-alpha.1",
44
+ "@deepseek-ai/dsh-client-store": "0.1.0-rc.8 || 0.1.1-rc.2 || 0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.6-alpha.1",
45
+ "@deepseek-ai/dsh-client-ui-conversation": "0.1.0-rc.8 || 0.1.1-rc.2 || 0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.6-alpha.1",
46
+ "@deepseek-ai/dsh-client-ui-primitives": "0.1.0-rc.8 || 0.1.1-rc.2 || 0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.6-alpha.1",
47
+ "@deepseek-ai/dsh-client-ui-sidebar": "0.1.0-rc.8 || 0.1.1-rc.2 || 0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.6-alpha.1",
48
+ "@deepseek-ai/dsh-client-ui-workspace": "0.1.0-rc.8 || 0.1.1-rc.2 || 0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.6-alpha.1",
49
+ "@deepseek-ai/dsh-host-webserver": "0.1.0-rc.8 || 0.1.1-rc.2 || 0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.6-alpha.1",
50
+ "@deepseek-ai/dsh-session": "0.1.0-rc.8 || 0.1.1-rc.2 || 0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.6-alpha.1",
51
+ "@deepseek-ai/dsh-session-projection-cache": "0.1.0-rc.8 || 0.1.1-rc.2 || 0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.6-alpha.1",
52
+ "@deepseek-ai/dsh-spill-local": "0.1.0-rc.8 || 0.1.1-rc.2 || 0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.6-alpha.1",
53
+ "@deepseek-ai/dsh-storage-domain": "0.1.0-rc.8 || 0.1.1-rc.2 || 0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.6-alpha.1",
54
+ "@deepseek-ai/dsh-typert-protocol": "0.1.0-rc.8 || 0.1.1-rc.2 || 0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.6-alpha.1",
55
+ "@deepseek-ai/dsh-typert-registry": "0.1.0-rc.8 || 0.1.1-rc.2 || 0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.6-alpha.1",
56
+ "@deepseek-ai/dsh-workspace": "0.1.0-rc.8 || 0.1.1-rc.2 || 0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.6-alpha.1"
57
57
  },
58
58
  "peerDependenciesMeta": {
59
59
  "@deepseek-ai/dsh-client-runtime": {
@@ -65,30 +65,30 @@
65
65
  },
66
66
  "devDependencies": {
67
67
  "@deepseek-ai/cordis": "4.0.2",
68
- "@deepseek-ai/dsh-api-gateway": "0.1.5-rc.2",
69
- "@deepseek-ai/dsh-client-connection": "0.1.5-rc.2",
70
- "@deepseek-ai/dsh-client-locale": "0.1.5-rc.2",
71
- "@deepseek-ai/dsh-client-store": "0.1.5-rc.2",
72
- "@deepseek-ai/dsh-client-ui-conversation": "0.1.5-rc.2",
73
- "@deepseek-ai/dsh-client-ui-primitives": "0.1.5-rc.2",
74
- "@deepseek-ai/dsh-client-ui-renderer": "0.1.5-rc.2",
75
- "@deepseek-ai/dsh-client-ui-sidebar": "0.1.5-rc.2",
76
- "@deepseek-ai/dsh-client-ui-slots": "0.1.5-rc.2",
77
- "@deepseek-ai/dsh-client-ui-workspace": "0.1.5-rc.2",
78
- "@deepseek-ai/dsh-host-webserver": "0.1.5-rc.2",
79
- "@deepseek-ai/dsh-invariants": "0.1.5-rc.2",
80
- "@deepseek-ai/dsh-scope": "0.1.5-rc.2",
81
- "@deepseek-ai/dsh-session": "0.1.5-rc.2",
82
- "@deepseek-ai/dsh-session-persistence": "0.1.5-rc.2",
83
- "@deepseek-ai/dsh-session-projection": "0.1.5-rc.2",
84
- "@deepseek-ai/dsh-session-projection-cache": "0.1.5-rc.2",
85
- "@deepseek-ai/dsh-spill": "0.1.5-rc.2",
86
- "@deepseek-ai/dsh-spill-local": "0.1.5-rc.2",
87
- "@deepseek-ai/dsh-storage": "0.1.5-rc.2",
88
- "@deepseek-ai/dsh-storage-domain": "0.1.5-rc.2",
89
- "@deepseek-ai/dsh-typert-protocol": "0.1.5-rc.2",
90
- "@deepseek-ai/dsh-typert-registry": "0.1.5-rc.2",
91
- "@deepseek-ai/dsh-workspace": "0.1.5-rc.2",
68
+ "@deepseek-ai/dsh-api-gateway": "0.1.6-alpha.1",
69
+ "@deepseek-ai/dsh-client-connection": "0.1.6-alpha.1",
70
+ "@deepseek-ai/dsh-client-locale": "0.1.6-alpha.1",
71
+ "@deepseek-ai/dsh-client-store": "0.1.6-alpha.1",
72
+ "@deepseek-ai/dsh-client-ui-conversation": "0.1.6-alpha.1",
73
+ "@deepseek-ai/dsh-client-ui-primitives": "0.1.6-alpha.1",
74
+ "@deepseek-ai/dsh-client-ui-renderer": "0.1.6-alpha.1",
75
+ "@deepseek-ai/dsh-client-ui-sidebar": "0.1.6-alpha.1",
76
+ "@deepseek-ai/dsh-client-ui-slots": "0.1.6-alpha.1",
77
+ "@deepseek-ai/dsh-client-ui-workspace": "0.1.6-alpha.1",
78
+ "@deepseek-ai/dsh-host-webserver": "0.1.6-alpha.1",
79
+ "@deepseek-ai/dsh-invariants": "0.1.6-alpha.1",
80
+ "@deepseek-ai/dsh-scope": "0.1.6-alpha.1",
81
+ "@deepseek-ai/dsh-session": "0.1.6-alpha.1",
82
+ "@deepseek-ai/dsh-session-persistence": "0.1.6-alpha.1",
83
+ "@deepseek-ai/dsh-session-projection": "0.1.6-alpha.1",
84
+ "@deepseek-ai/dsh-session-projection-cache": "0.1.6-alpha.1",
85
+ "@deepseek-ai/dsh-spill": "0.1.6-alpha.1",
86
+ "@deepseek-ai/dsh-spill-local": "0.1.6-alpha.1",
87
+ "@deepseek-ai/dsh-storage": "0.1.6-alpha.1",
88
+ "@deepseek-ai/dsh-storage-domain": "0.1.6-alpha.1",
89
+ "@deepseek-ai/dsh-typert-protocol": "0.1.6-alpha.1",
90
+ "@deepseek-ai/dsh-typert-registry": "0.1.6-alpha.1",
91
+ "@deepseek-ai/dsh-workspace": "0.1.6-alpha.1",
92
92
  "react": "18.3.1",
93
93
  "react-dom": "18.3.1",
94
94
  "esbuild": "0.25.0",