@chatcode/chatcode-cli 3.0.4-rc.1 → 3.0.4-rc.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.
Files changed (136) hide show
  1. package/README.i18n.yaml +2 -2
  2. package/README.md +2 -0
  3. package/README.zh.md +2 -0
  4. package/lib/{command-errors-BkCHTQHj.js → command-errors-BJ_ZWzUU.js} +12 -12
  5. package/lib/{command-trees-5HFyC5sI.js → command-trees-C9b7-bci.js} +2 -2
  6. package/lib/{component-identity-De91VHwW.js → component-identity-Jb1DYjke.js} +3 -3
  7. package/lib/{dist-CsDWUvQ4.js → dist-w_sIm4VD.js} +231 -231
  8. package/lib/{extension-events-CdYCRP0o.js → extension-events-DKX4LXOd.js} +26 -26
  9. package/lib/{frames-DOX-Jgk8.js → frames-B89znn_0.js} +4 -4
  10. package/lib/{host-access-Bk4xps5E.js → host-access-CMg6rsWt.js} +1 -1
  11. package/lib/{keymap-CJ1kvLR2.js → keymap-CrC4pSNH.js} +2 -2
  12. package/lib/{plugin-XR7ncbnW.js → plugin-CmyMCGfb.js} +1651 -1365
  13. package/lib/{scenes-CAmWncZD.js → scenes-Cil9RnwU.js} +3 -3
  14. package/lib/{settings-sections-CakcvBv9.js → settings-sections-jVCqXwdH.js} +3 -3
  15. package/lib/{statusBarSettings-BPPS_Usm.js → statusBarSettings-DNoBH3Cq.js} +3 -3
  16. package/lib/{supports-color-DyChQwlI.js → supports-color-CcW-FGjr.js} +2 -2
  17. package/lib/{themes-OjcUpZzw.js → themes-BdgeY3It.js} +12 -12
  18. package/lib/tui-compat-command-trees.js +1 -1
  19. package/lib/tui-compat-extensions.js +3 -3
  20. package/lib/tui-compat-plugin-host.js +5 -5
  21. package/lib/tui-compat-scenes.js +1 -1
  22. package/lib/tui-compat-settings-sections.js +1 -1
  23. package/lib/tui-compat-working-activity.js +4 -4
  24. package/lib/tui-compat-workspaces.js +1 -1
  25. package/lib/tui-compat.js +5 -5
  26. package/lib/{workspaces-XY7UdfXp.js → workspaces-DOatJRYr.js} +2 -2
  27. package/package.json +30 -29
  28. package/runtime/manifest.json +2 -2
  29. package/runtime/node_modules/@deepseek-ai/dsh-agent-default-model/lib/index.js +118 -22
  30. package/runtime/node_modules/@deepseek-ai/dsh-agent-default-model/lib/types/index.d.ts +20 -3
  31. package/runtime/node_modules/@deepseek-ai/dsh-api-remotes/lib/client.js +113 -39
  32. package/runtime/node_modules/@deepseek-ai/dsh-api-remotes/lib/index.js +4 -0
  33. package/runtime/node_modules/@deepseek-ai/dsh-api-remotes/lib/types/remote-events.d.ts +3 -0
  34. package/runtime/node_modules/@deepseek-ai/dsh-api-remotes/lib/types/remote-events.js +1 -0
  35. package/runtime/node_modules/@deepseek-ai/dsh-api-session-controller/lib/index.js +173 -34
  36. package/runtime/node_modules/@deepseek-ai/dsh-api-session-controller/lib/typert.host.js +48 -28
  37. package/runtime/node_modules/@deepseek-ai/dsh-api-session-controller/lib/typert.remote-client.js +24 -19
  38. package/runtime/node_modules/@deepseek-ai/dsh-api-session-controller/lib/types/agent.d.ts +9 -1
  39. package/runtime/node_modules/@deepseek-ai/dsh-api-session-controller/lib/types/agent.js +36 -6
  40. package/runtime/node_modules/@deepseek-ai/dsh-api-session-controller/lib/types/archived-session-gate.js +1 -1
  41. package/runtime/node_modules/@deepseek-ai/dsh-api-session-controller/lib/types/catalog.js +4 -1
  42. package/runtime/node_modules/@deepseek-ai/dsh-api-session-controller/lib/types/client/sessions/service.d.ts +1 -1
  43. package/runtime/node_modules/@deepseek-ai/dsh-api-session-controller/lib/types/commands.d.ts +2 -2
  44. package/runtime/node_modules/@deepseek-ai/dsh-api-session-controller/lib/types/commands.js +24 -8
  45. package/runtime/node_modules/@deepseek-ai/dsh-api-session-controller/lib/types/index.d.ts +4 -3
  46. package/runtime/node_modules/@deepseek-ai/dsh-api-session-controller/lib/types/index.js +31 -14
  47. package/runtime/node_modules/@deepseek-ai/dsh-api-session-controller/lib/types/list.d.ts +6 -0
  48. package/runtime/node_modules/@deepseek-ai/dsh-api-session-controller/lib/types/list.js +89 -4
  49. package/runtime/node_modules/@deepseek-ai/dsh-api-session-controller/lib/types/remote-events.d.ts +1 -1
  50. package/runtime/node_modules/@deepseek-ai/dsh-api-session-controller/lib/types/types.d.ts +18 -1
  51. package/runtime/node_modules/@deepseek-ai/dsh-api-workspace-controller/lib/client.js +30 -0
  52. package/runtime/node_modules/@deepseek-ai/dsh-api-workspace-controller/lib/index.js +83 -2
  53. package/runtime/node_modules/@deepseek-ai/dsh-api-workspace-controller/lib/typert.host.js +104 -11
  54. package/runtime/node_modules/@deepseek-ai/dsh-api-workspace-controller/lib/typert.remote-client.d.ts +5 -1
  55. package/runtime/node_modules/@deepseek-ai/dsh-api-workspace-controller/lib/typert.remote-client.js +78 -11
  56. package/runtime/node_modules/@deepseek-ai/dsh-api-workspace-controller/lib/types/client/model.d.ts +14 -1
  57. package/runtime/node_modules/@deepseek-ai/dsh-api-workspace-controller/lib/types/client/model.js +17 -0
  58. package/runtime/node_modules/@deepseek-ai/dsh-api-workspace-controller/lib/types/client/service.d.ts +15 -0
  59. package/runtime/node_modules/@deepseek-ai/dsh-api-workspace-controller/lib/types/client/service.js +12 -0
  60. package/runtime/node_modules/@deepseek-ai/dsh-api-workspace-controller/lib/types/commands.d.ts +13 -1
  61. package/runtime/node_modules/@deepseek-ai/dsh-api-workspace-controller/lib/types/commands.js +44 -2
  62. package/runtime/node_modules/@deepseek-ai/dsh-api-workspace-controller/lib/types/index.d.ts +13 -1
  63. package/runtime/node_modules/@deepseek-ai/dsh-api-workspace-controller/lib/types/index.js +22 -0
  64. package/runtime/node_modules/@deepseek-ai/dsh-api-workspace-controller/lib/types/types.d.ts +17 -0
  65. package/runtime/node_modules/@deepseek-ai/dsh-app-boot/lib/index.js +2 -1
  66. package/runtime/node_modules/@deepseek-ai/dsh-atomic-write/lib/index.js +167 -44
  67. package/runtime/node_modules/@deepseek-ai/dsh-atomic-write/lib/types/index.d.ts +14 -6
  68. package/runtime/node_modules/@deepseek-ai/dsh-atomic-write/lib/types/linux-lock.d.ts +18 -0
  69. package/runtime/node_modules/@deepseek-ai/dsh-atomic-write/lib/types/windows-lock.d.ts +7 -0
  70. package/runtime/node_modules/@deepseek-ai/dsh-client-hmr/lib/client.js +931 -7
  71. package/runtime/node_modules/@deepseek-ai/dsh-client-hmr/lib/index.js +57 -19
  72. package/runtime/node_modules/@deepseek-ai/dsh-client-hmr/lib/types/client/index.d.ts +5 -2
  73. package/runtime/node_modules/@deepseek-ai/dsh-client-hmr/lib/types/config.d.ts +12 -0
  74. package/runtime/node_modules/@deepseek-ai/dsh-client-hmr/lib/types/events.d.ts +4 -4
  75. package/runtime/node_modules/@deepseek-ai/dsh-client-hmr/lib/types/index.d.ts +3 -8
  76. package/runtime/node_modules/@deepseek-ai/dsh-client-hmr/package.json +6 -2
  77. package/runtime/node_modules/@deepseek-ai/dsh-client-ui-commands/lib/client.js +10 -0
  78. package/runtime/node_modules/@deepseek-ai/dsh-client-ui-deliverables/lib/types/client/present-open.d.ts +1 -1
  79. package/runtime/node_modules/@deepseek-ai/dsh-client-ui-model-selection/lib/client.js +8 -4
  80. package/runtime/node_modules/@deepseek-ai/dsh-client-ui-settings-account/lib/client.js +2 -2
  81. package/runtime/node_modules/@deepseek-ai/dsh-client-ui-settings-general/lib/client.js +1 -1
  82. package/runtime/node_modules/@deepseek-ai/dsh-client-ui-sidebar/lib/client.js +1 -1
  83. package/runtime/node_modules/@deepseek-ai/dsh-client-ui-workspace/lib/client.js +1917 -206
  84. package/runtime/node_modules/@deepseek-ai/dsh-client-ui-workspace/lib/types/client/ArchivedSessions.d.ts +13 -0
  85. package/runtime/node_modules/@deepseek-ai/dsh-client-ui-workspace/lib/types/client/contract/slots.d.ts +4 -0
  86. package/runtime/node_modules/@deepseek-ai/dsh-client-ui-workspace/lib/types/client/locales.d.ts +40 -0
  87. package/runtime/node_modules/@deepseek-ai/dsh-client-ui-workspace/lib/types/client/recent.d.ts +11 -0
  88. package/runtime/node_modules/@deepseek-ai/dsh-client-ui-workspace/lib/types/client/rows/RecentList.d.ts +15 -0
  89. package/runtime/node_modules/@deepseek-ai/dsh-client-ui-workspace/lib/types/client/rows/Rows.d.ts +6 -1
  90. package/runtime/node_modules/@deepseek-ai/dsh-client-ui-workspace/lib/types/client/session-actions/DeleteSession.d.ts +24 -0
  91. package/runtime/node_modules/@deepseek-ai/dsh-client-ui-workspace/lib/types/client/stores.d.ts +2 -2
  92. package/runtime/node_modules/@deepseek-ai/dsh-client-ui-workspace/lib/types/client/tree.d.ts +15 -13
  93. package/runtime/node_modules/@deepseek-ai/dsh-client-ui-workspace/package.json +3 -1
  94. package/runtime/node_modules/@deepseek-ai/dsh-commands/lib/index.js +16 -0
  95. package/runtime/node_modules/@deepseek-ai/dsh-commands/lib/typert.host.js +7 -3
  96. package/runtime/node_modules/@deepseek-ai/dsh-commands/lib/typert.remote-client.js +6 -2
  97. package/runtime/node_modules/@deepseek-ai/dsh-commands/lib/types/index.js +20 -0
  98. package/runtime/node_modules/@deepseek-ai/dsh-commands/lib/types/types.d.ts +5 -0
  99. package/runtime/node_modules/@deepseek-ai/dsh-cordis-client-runner/lib/client.js +5 -2
  100. package/runtime/node_modules/@deepseek-ai/dsh-llm-deepseek/lib/types/adapter.d.ts +1 -1
  101. package/runtime/node_modules/@deepseek-ai/dsh-llm-deepseek/lib/types/config.d.ts +3 -3
  102. package/runtime/node_modules/@deepseek-ai/dsh-llm-deepseek-account/lib/types/config.d.ts +2 -2
  103. package/runtime/node_modules/@deepseek-ai/dsh-llm-deepseek-api-key/lib/types/config.d.ts +2 -2
  104. package/runtime/node_modules/@deepseek-ai/dsh-schedule/lib/index.js +4 -0
  105. package/runtime/node_modules/@deepseek-ai/dsh-schedule/lib/typert.host.js +5 -5
  106. package/runtime/node_modules/@deepseek-ai/dsh-schedule/lib/typert.remote-client.js +5 -5
  107. package/runtime/node_modules/@deepseek-ai/dsh-schedule/lib/types/index.js +5 -0
  108. package/runtime/node_modules/@deepseek-ai/dsh-session/lib/types/index.d.ts +21 -0
  109. package/runtime/node_modules/@deepseek-ai/dsh-session-persistence/lib/index.js +12 -0
  110. package/runtime/node_modules/@deepseek-ai/dsh-session-persistence/lib/types/index.d.ts +15 -0
  111. package/runtime/node_modules/@deepseek-ai/dsh-session-persistence-jsonl/lib/index.js +95 -2
  112. package/runtime/node_modules/@deepseek-ai/dsh-session-persistence-jsonl/lib/types/index.d.ts +3 -1
  113. package/runtime/node_modules/@deepseek-ai/dsh-session-projection-cache/lib/index.js +25 -1
  114. package/runtime/node_modules/@deepseek-ai/dsh-session-projection-cache/lib/types/index.d.ts +1 -0
  115. package/runtime/node_modules/@deepseek-ai/dsh-session-projection-cache/package.json +2 -1
  116. package/runtime/node_modules/@deepseek-ai/dsh-session-query/lib/index.js +13 -0
  117. package/runtime/node_modules/@deepseek-ai/dsh-session-query/lib/types/observation.d.ts +5 -0
  118. package/runtime/node_modules/@deepseek-ai/dsh-session-query-sqlite/lib/index.js +26 -0
  119. package/runtime/node_modules/@deepseek-ai/dsh-session-query-sqlite/package.json +2 -1
  120. package/runtime/node_modules/@deepseek-ai/dsh-storage-domain/lib/index.js +5 -1
  121. package/runtime/node_modules/@deepseek-ai/dsh-storage-domain/lib/types/domain.d.ts +2 -2
  122. package/runtime/node_modules/@deepseek-ai/dsh-subagent/lib/types/control.d.ts +1 -1
  123. package/runtime/node_modules/@deepseek-ai/dsh-tianti/lib/index.js +106 -56
  124. package/runtime/node_modules/@deepseek-ai/dsh-tianti/lib/types/config.d.ts +2 -2
  125. package/runtime/node_modules/@deepseek-ai/dsh-tianti/lib/types/index.d.ts +2 -1
  126. package/runtime/node_modules/@deepseek-ai/dsh-tianti/lib/types/services/tianti/config.d.ts +4 -2
  127. package/runtime/node_modules/@deepseek-ai/dsh-tianti/lib/types/tools.d.ts +2 -2
  128. package/runtime/node_modules/@deepseek-ai/dsh-tianti/package.json +2 -0
  129. package/runtime/node_modules/@deepseek-ai/dsh-tool-cordis/lib/types/api-catalog.js +104 -13
  130. package/runtime/node_modules/@deepseek-ai/dsh-workspace/lib/index.js +215 -4
  131. package/runtime/node_modules/@deepseek-ai/dsh-workspace/lib/invariant.js +6 -1
  132. package/runtime/node_modules/@deepseek-ai/dsh-workspace/lib/types/index.d.ts +31 -0
  133. package/runtime/node_modules/@deepseek-ai/dsh-workspace/lib/types/index.js +219 -2
  134. package/runtime/node_modules/@deepseek-ai/dsh-workspace/lib/types/spec.d.ts +4 -0
  135. package/runtime/node_modules/@deepseek-ai/dsh-workspace/lib/types/spec.js +4 -0
  136. package/scripts/launch.mjs +8 -0
@@ -1,6 +1,7 @@
1
1
  import { randomUUID } from "node:crypto";
2
2
  import { mkdir, realpath, stat } from "node:fs/promises";
3
3
  import { Service } from "@deepseek-ai/cordis";
4
+ import { SessionAlreadyOwnedError } from "@deepseek-ai/dsh-session-persistence";
4
5
  import { posix, win32 } from "node:path";
5
6
  import { z } from "zod";
6
7
  import { brandString } from "@deepseek-ai/dsh-brand";
@@ -252,7 +253,11 @@ const workspaceDomainState = z.object({
252
253
  workspaceIds: z.array(workspaceId),
253
254
  archivedSessionIds: z.array(sessionId).default([]),
254
255
  pinnedSessionIds: z.array(sessionId).default([]),
255
- pendingMutation: workspacePendingMutation.optional()
256
+ pendingMutation: workspacePendingMutation.optional(),
257
+ /** Payload deletion committed identities; old processes must never restore these Sessions. */
258
+ deletedSessionIds: z.array(sessionId).optional(),
259
+ /** Complete deletion scope retained until payloads and secondary owners finish cleanup. */
260
+ pendingSessionDeletion: z.array(sessionId).optional()
256
261
  });
257
262
  /**
258
263
  * The workspace domain spec: one `workspaces` table keyed by
@@ -282,6 +287,64 @@ const workspaceDomainSpec = defineDomain({
282
287
  * domain data form.
283
288
  * @module @deepseek-ai/dsh-workspace
284
289
  */
290
+ var __addDisposableResource = function(env, value, async) {
291
+ if (value !== null && value !== void 0) {
292
+ if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
293
+ var dispose, inner;
294
+ if (async) {
295
+ if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
296
+ dispose = value[Symbol.asyncDispose];
297
+ }
298
+ if (dispose === void 0) {
299
+ if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
300
+ dispose = value[Symbol.dispose];
301
+ if (async) inner = dispose;
302
+ }
303
+ if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
304
+ if (inner) dispose = function() {
305
+ try {
306
+ inner.call(this);
307
+ } catch (e) {
308
+ return Promise.reject(e);
309
+ }
310
+ };
311
+ env.stack.push({
312
+ value,
313
+ dispose,
314
+ async
315
+ });
316
+ } else if (async) env.stack.push({ async: true });
317
+ return value;
318
+ };
319
+ var __disposeResources = (function(SuppressedError) {
320
+ return function(env) {
321
+ function fail(e) {
322
+ env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
323
+ env.hasError = true;
324
+ }
325
+ var r, s = 0;
326
+ function next() {
327
+ while (r = env.stack.pop()) try {
328
+ if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
329
+ if (r.dispose) {
330
+ var result = r.dispose.call(r.value);
331
+ if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) {
332
+ fail(e);
333
+ return next();
334
+ });
335
+ } else s |= 1;
336
+ } catch (e) {
337
+ fail(e);
338
+ }
339
+ if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
340
+ if (env.hasError) throw env.error;
341
+ }
342
+ return next();
343
+ };
344
+ })(typeof SuppressedError === "function" ? SuppressedError : function(error, suppressed, message) {
345
+ var e = new Error(message);
346
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
347
+ });
285
348
  /**
286
349
  * Brand a string as a {@link WorkspaceId}.
287
350
  * @param id - Raw workspace id string.
@@ -338,6 +401,21 @@ var WorkspaceArchivedSessionPinError = class extends Error {
338
401
  this.name = "WorkspaceArchivedSessionPinError";
339
402
  }
340
403
  };
404
+ /** Permanent deletion requires an archived root and no active Session ownership. */
405
+ var WorkspaceSessionDeletionError = class extends Error {
406
+ sessionId;
407
+ reason;
408
+ /**
409
+ * @param sessionId - identity whose lifecycle prevents the requested operation.
410
+ * @param reason - stable refusal discriminant shared by the Web and TUI.
411
+ */
412
+ constructor(sessionId, reason) {
413
+ super(`cannot delete session '${sessionId}': ${reason}`);
414
+ this.sessionId = sessionId;
415
+ this.reason = reason;
416
+ this.name = "WorkspaceSessionDeletionError";
417
+ }
418
+ };
341
419
  /** A workspace reorder named a source or anchor absent from the durable registry order. */
342
420
  var WorkspaceOrderInvalidError = class extends Error {
343
421
  workspaceId;
@@ -403,6 +481,7 @@ var WorkspaceRegistry = class extends Service {
403
481
  await domain.refresh();
404
482
  this.state = domain.global.get();
405
483
  await this.recoverPendingMutation();
484
+ await this.recoverSessionDeletion();
406
485
  this.validateStoredState(this.requireState());
407
486
  if (!this.requireState().initialized) {
408
487
  const headers = await this.listStoredHeaders();
@@ -550,6 +629,130 @@ var WorkspaceRegistry = class extends Service {
550
629
  get archivedSessionIds() {
551
630
  return this.requireState().archivedSessionIds;
552
631
  }
632
+ /** Permanently deleted identities retained for cross-process invalidation and stale-operation refusal. */
633
+ get deletedSessionIds() {
634
+ return this.requireState().deletedSessionIds ?? [];
635
+ }
636
+ /**
637
+ * Permanently delete an archived, inactive root and its owned subagent descendants.
638
+ * Independent forks are preserved. Reserve every writer before recording a recovery
639
+ * marker; a failure after that marker is retried on refresh or restart.
640
+ * @param sessionId - archived root identity; repeated deletion is idempotent.
641
+ * @param expectedIds - identities confirmed by the user; a changed scope refuses deletion.
642
+ * @returns deleted root and descendant identities after durable cleanup.
643
+ */
644
+ deleteSession(sessionId, expectedIds) {
645
+ return this.enqueueOperation(async () => {
646
+ const env_1 = {
647
+ stack: [],
648
+ error: void 0,
649
+ hasError: false
650
+ };
651
+ try {
652
+ if (this.deletedSessionIds.includes(sessionId)) return [sessionId];
653
+ if (!this.archivedSessionIds.includes(sessionId)) throw new WorkspaceSessionDeletionError(sessionId, "not-archived");
654
+ const ids = new Set(await this.collectSessionDeletionScope(sessionId));
655
+ if (expectedIds !== void 0 && (expectedIds.length !== ids.size || new Set(expectedIds).size !== ids.size || expectedIds.some((id) => !ids.has(id)))) throw new WorkspaceSessionDeletionError(sessionId, "scope-changed");
656
+ for (const id of ids) {
657
+ const activity = await this.ctx.waterfall("workspace/session-activity", { sessionId: id }, () => Promise.resolve([]));
658
+ if (activity.length > 0) throw new WorkspaceActiveSessionError(id, activity);
659
+ }
660
+ const targets = [...ids];
661
+ await this.ctx.parallel("session/delete-release", { sessionIds: targets });
662
+ for (const id of ids) if (this.ctx.get("sessions")?.get(id) !== void 0) throw new WorkspaceSessionDeletionError(id, "in-use");
663
+ const reservation = __addDisposableResource(env_1, await this.ctx.sessionPersistence.prepareDeletion(targets).catch((error) => {
664
+ if (error instanceof SessionAlreadyOwnedError) throw new WorkspaceSessionDeletionError(sessionId, "in-use");
665
+ throw error;
666
+ }), true);
667
+ await this.setState({
668
+ ...this.requireState(),
669
+ pendingSessionDeletion: targets
670
+ });
671
+ await reservation.commit();
672
+ await this.finishSessionDeletion(targets);
673
+ return targets;
674
+ } catch (e_1) {
675
+ env_1.error = e_1;
676
+ env_1.hasError = true;
677
+ } finally {
678
+ const result_1 = __disposeResources(env_1);
679
+ if (result_1) await result_1;
680
+ }
681
+ });
682
+ }
683
+ /**
684
+ * Preview the root and owned descendants without opening their histories.
685
+ * @param sessionId - archived root to preview.
686
+ * @returns identities to show in the deletion confirmation.
687
+ */
688
+ sessionDeletionScope(sessionId) {
689
+ return this.enqueueOperation(async () => {
690
+ if (!this.archivedSessionIds.includes(sessionId)) throw new WorkspaceSessionDeletionError(sessionId, "not-archived");
691
+ return this.collectSessionDeletionScope(sessionId);
692
+ });
693
+ }
694
+ async collectSessionDeletionScope(sessionId) {
695
+ const headers = await this.listStoredHeaders();
696
+ const ids = new Set([sessionId]);
697
+ for (let changed = true; changed;) {
698
+ changed = false;
699
+ for (const header of headers) if (header.origin === "subagent" && header.parentSession !== void 0 && ids.has(header.parentSession) && !ids.has(header.id)) {
700
+ ids.add(header.id);
701
+ changed = true;
702
+ }
703
+ }
704
+ return [...ids];
705
+ }
706
+ async recoverSessionDeletion() {
707
+ const env_2 = {
708
+ stack: [],
709
+ error: void 0,
710
+ hasError: false
711
+ };
712
+ try {
713
+ const ids = this.requireState().pendingSessionDeletion;
714
+ if (ids === void 0) return;
715
+ await __addDisposableResource(env_2, await this.ctx.sessionPersistence.prepareDeletion(ids), true).commit();
716
+ await this.finishSessionDeletion(ids);
717
+ } catch (e_2) {
718
+ env_2.error = e_2;
719
+ env_2.hasError = true;
720
+ } finally {
721
+ const result_2 = __disposeResources(env_2);
722
+ if (result_2) await result_2;
723
+ }
724
+ }
725
+ notifyDeleted(ids) {
726
+ try {
727
+ this.ctx.emit("session/deleted", ids);
728
+ } catch (error) {
729
+ this.ctx.logger.warn(`workspace: deletion listener failed: ${String(error)}`);
730
+ }
731
+ }
732
+ async finishSessionDeletion(ids) {
733
+ await this.ctx.parallel("session/deleting", { sessionIds: ids });
734
+ const removed = new Set(ids);
735
+ for (const [id, record] of this.requireTable().entries()) if (record.sessionIds.some((member) => removed.has(member))) await this.requireTable().update(id, (current) => ({
736
+ ...current,
737
+ sessionIds: current.sessionIds.filter((member) => !removed.has(member)),
738
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
739
+ }));
740
+ const state = this.requireState();
741
+ await this.setState({
742
+ ...state,
743
+ archivedSessionIds: state.archivedSessionIds.filter((id) => !removed.has(id)),
744
+ pinnedSessionIds: state.pinnedSessionIds.filter((id) => !removed.has(id)),
745
+ deletedSessionIds: [...new Set([...state.deletedSessionIds ?? [], ...ids])],
746
+ pendingSessionDeletion: void 0
747
+ });
748
+ for (const id of ids) {
749
+ this.headers.delete(id);
750
+ this.sessionPaths.delete(id);
751
+ this.invalidSessionPaths.delete(id);
752
+ }
753
+ this.rebuildEntities();
754
+ this.notifyDeleted(ids);
755
+ }
553
756
  /**
554
757
  * Archive one session durably. The session must exist (live or in session
555
758
  * persistence); its workspace accounting — or lack of one — is irrelevant.
@@ -596,6 +799,7 @@ var WorkspaceRegistry = class extends Service {
596
799
  */
597
800
  unarchiveSession(sessionId) {
598
801
  return this.enqueueOperation(async () => {
802
+ if (this.deletedSessionIds.includes(sessionId)) throw new WorkspaceSessionDeletionError(sessionId, "deleted");
599
803
  const state = this.requireState();
600
804
  if (!state.archivedSessionIds.includes(sessionId)) return;
601
805
  await this.setState({
@@ -656,6 +860,7 @@ var WorkspaceRegistry = class extends Service {
656
860
  * masquerade as an unknown session.
657
861
  */
658
862
  async sessionKnown(id) {
863
+ if (this.deletedSessionIds.includes(id)) return false;
659
864
  if (this.ctx.get("sessions")?.get(id) !== void 0) return true;
660
865
  if (this.headers.has(id)) return true;
661
866
  await this.indexHeaders(await this.listStoredHeaders());
@@ -939,12 +1144,14 @@ var WorkspaceRegistry = class extends Service {
939
1144
  }
940
1145
  /** Every stored session's header, projected from the persistence snapshot listing. */
941
1146
  async listStoredHeaders() {
942
- return (await this.ctx.sessionPersistence.list()).map((snapshot) => snapshot.header);
1147
+ const snapshots = await this.ctx.sessionPersistence.list();
1148
+ const deleted = new Set(this.deletedSessionIds);
1149
+ return snapshots.map((snapshot) => snapshot.header).filter((header) => !deleted.has(header.id));
943
1150
  }
944
1151
  async indexLiveSessions() {
945
1152
  const sessions = this.ctx.get("sessions");
946
1153
  if (sessions === void 0) return;
947
- await this.indexHeaders(sessions.list().map((session) => session.header));
1154
+ await this.indexHeaders(sessions.list().filter((session) => !this.deletedSessionIds.includes(session.id)).map((session) => session.header));
948
1155
  }
949
1156
  reportFilteredCandidates() {
950
1157
  for (const entity of this.entities.values()) {
@@ -990,6 +1197,7 @@ var WorkspaceRegistry = class extends Service {
990
1197
  if (domain === void 0) throw new Error("workspace registry is not started yet");
991
1198
  return await domain.exclusive(async () => {
992
1199
  const before = JSON.stringify([...this.entities.values()].map((entity) => [entity.id, entity.sessionIds]));
1200
+ const previousDeleted = new Set(this.deletedSessionIds);
993
1201
  await domain.refresh();
994
1202
  const changed = this.snapshotIdentity() !== this.refreshedState;
995
1203
  this.state = domain.global.get();
@@ -1000,6 +1208,9 @@ var WorkspaceRegistry = class extends Service {
1000
1208
  this.rebuildEntities();
1001
1209
  }
1002
1210
  await this.recoverPendingMutation();
1211
+ await this.recoverSessionDeletion();
1212
+ const newlyDeleted = this.deletedSessionIds.filter((id) => !previousDeleted.has(id));
1213
+ if (newlyDeleted.length > 0) this.notifyDeleted(newlyDeleted);
1003
1214
  this.validateStoredState(this.requireState());
1004
1215
  const after = JSON.stringify([...this.entities.values()].map((entity) => [entity.id, entity.sessionIds]));
1005
1216
  if (changed || before !== after) try {
@@ -1022,4 +1233,4 @@ var WorkspaceRegistry = class extends Service {
1022
1233
  };
1023
1234
  const sameSessionIds = (left, right) => left.length === right.length && left.every((id, index) => id === right[index]);
1024
1235
  //#endregion
1025
- export { WorkspaceActiveSessionError, WorkspaceArchivedSessionPinError, WorkspaceId, WorkspaceMoveInvalidError, WorkspaceOrderInvalidError, WorkspaceRegistry, WorkspaceRegistry as default, WorkspaceUnknownSessionError, realpathNormalize, workspaceDomainSpec, workspaceDomainState, workspaceRecord };
1236
+ export { WorkspaceActiveSessionError, WorkspaceArchivedSessionPinError, WorkspaceId, WorkspaceMoveInvalidError, WorkspaceOrderInvalidError, WorkspaceRegistry, WorkspaceRegistry as default, WorkspaceSessionDeletionError, WorkspaceUnknownSessionError, realpathNormalize, workspaceDomainSpec, workspaceDomainState, workspaceRecord };
@@ -1,6 +1,7 @@
1
1
  import "node:crypto";
2
2
  import "node:fs/promises";
3
3
  import { Service } from "@deepseek-ai/cordis";
4
+ import "@deepseek-ai/dsh-session-persistence";
4
5
  import "node:path";
5
6
  import { z } from "zod";
6
7
  import { brandString } from "@deepseek-ai/dsh-brand";
@@ -51,7 +52,11 @@ defineDomain({
51
52
  workspaceIds: z.array(workspaceId),
52
53
  archivedSessionIds: z.array(sessionId).default([]),
53
54
  pinnedSessionIds: z.array(sessionId).default([]),
54
- pendingMutation: workspacePendingMutation.optional()
55
+ pendingMutation: workspacePendingMutation.optional(),
56
+ /** Payload deletion committed identities; old processes must never restore these Sessions. */
57
+ deletedSessionIds: z.array(sessionId).optional(),
58
+ /** Complete deletion scope retained until payloads and secondary owners finish cleanup. */
59
+ pendingSessionDeletion: z.array(sessionId).optional()
55
60
  }),
56
61
  initial: {
57
62
  initialized: false,
@@ -55,6 +55,16 @@ export declare class WorkspaceArchivedSessionPinError extends Error {
55
55
  */
56
56
  constructor(sessionId: SessionId);
57
57
  }
58
+ /** Permanent deletion requires an archived root and no active Session ownership. */
59
+ export declare class WorkspaceSessionDeletionError extends Error {
60
+ readonly sessionId: SessionId;
61
+ readonly reason: 'not-archived' | 'in-use' | 'deleted' | 'scope-changed';
62
+ /**
63
+ * @param sessionId - identity whose lifecycle prevents the requested operation.
64
+ * @param reason - stable refusal discriminant shared by the Web and TUI.
65
+ */
66
+ constructor(sessionId: SessionId, reason: 'not-archived' | 'in-use' | 'deleted' | 'scope-changed');
67
+ }
58
68
  /** A workspace reorder named a source or anchor absent from the durable registry order. */
59
69
  export declare class WorkspaceOrderInvalidError extends Error {
60
70
  readonly workspaceId: WorkspaceId;
@@ -202,6 +212,27 @@ export declare class WorkspaceRegistry extends Service {
202
212
  * @returns the archived session ids in archive order.
203
213
  */
204
214
  get archivedSessionIds(): readonly SessionId[];
215
+ /** Permanently deleted identities retained for cross-process invalidation and stale-operation refusal. */
216
+ get deletedSessionIds(): readonly SessionId[];
217
+ /**
218
+ * Permanently delete an archived, inactive root and its owned subagent descendants.
219
+ * Independent forks are preserved. Reserve every writer before recording a recovery
220
+ * marker; a failure after that marker is retried on refresh or restart.
221
+ * @param sessionId - archived root identity; repeated deletion is idempotent.
222
+ * @param expectedIds - identities confirmed by the user; a changed scope refuses deletion.
223
+ * @returns deleted root and descendant identities after durable cleanup.
224
+ */
225
+ deleteSession(sessionId: SessionId, expectedIds?: readonly SessionId[]): Promise<readonly SessionId[]>;
226
+ /**
227
+ * Preview the root and owned descendants without opening their histories.
228
+ * @param sessionId - archived root to preview.
229
+ * @returns identities to show in the deletion confirmation.
230
+ */
231
+ sessionDeletionScope(sessionId: SessionId): Promise<readonly SessionId[]>;
232
+ private collectSessionDeletionScope;
233
+ private recoverSessionDeletion;
234
+ private notifyDeleted;
235
+ private finishSessionDeletion;
205
236
  /**
206
237
  * Archive one session durably. The session must exist (live or in session
207
238
  * persistence); its workspace accounting — or lack of one — is irrelevant.
@@ -4,9 +4,62 @@
4
4
  * domain data form.
5
5
  * @module @deepseek-ai/dsh-workspace
6
6
  */
7
+ var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) {
8
+ if (value !== null && value !== void 0) {
9
+ if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
10
+ var dispose, inner;
11
+ if (async) {
12
+ if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
13
+ dispose = value[Symbol.asyncDispose];
14
+ }
15
+ if (dispose === void 0) {
16
+ if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
17
+ dispose = value[Symbol.dispose];
18
+ if (async) inner = dispose;
19
+ }
20
+ if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
21
+ if (inner) dispose = function() { try { inner.call(this); } catch (e) { return Promise.reject(e); } };
22
+ env.stack.push({ value: value, dispose: dispose, async: async });
23
+ }
24
+ else if (async) {
25
+ env.stack.push({ async: true });
26
+ }
27
+ return value;
28
+ };
29
+ var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) {
30
+ return function (env) {
31
+ function fail(e) {
32
+ env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
33
+ env.hasError = true;
34
+ }
35
+ var r, s = 0;
36
+ function next() {
37
+ while (r = env.stack.pop()) {
38
+ try {
39
+ if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
40
+ if (r.dispose) {
41
+ var result = r.dispose.call(r.value);
42
+ if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) { fail(e); return next(); });
43
+ }
44
+ else s |= 1;
45
+ }
46
+ catch (e) {
47
+ fail(e);
48
+ }
49
+ }
50
+ if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
51
+ if (env.hasError) throw env.error;
52
+ }
53
+ return next();
54
+ };
55
+ })(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
56
+ var e = new Error(message);
57
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
58
+ });
7
59
  import { randomUUID } from 'node:crypto';
8
60
  import { mkdir, stat } from 'node:fs/promises';
9
61
  import { Service } from '@deepseek-ai/cordis';
62
+ import { SessionAlreadyOwnedError } from '@deepseek-ai/dsh-session-persistence';
10
63
  import { WorkspaceEntity } from "./entity.js";
11
64
  export { WorkspaceMoveInvalidError } from "./entity.js";
12
65
  import { defaultWorkspaceTitle, fullyQualifiedWorkspacePath, realpathNormalize } from "./paths.js";
@@ -69,6 +122,21 @@ export class WorkspaceArchivedSessionPinError extends Error {
69
122
  this.name = 'WorkspaceArchivedSessionPinError';
70
123
  }
71
124
  }
125
+ /** Permanent deletion requires an archived root and no active Session ownership. */
126
+ export class WorkspaceSessionDeletionError extends Error {
127
+ sessionId;
128
+ reason;
129
+ /**
130
+ * @param sessionId - identity whose lifecycle prevents the requested operation.
131
+ * @param reason - stable refusal discriminant shared by the Web and TUI.
132
+ */
133
+ constructor(sessionId, reason) {
134
+ super(`cannot delete session '${sessionId}': ${reason}`);
135
+ this.sessionId = sessionId;
136
+ this.reason = reason;
137
+ this.name = 'WorkspaceSessionDeletionError';
138
+ }
139
+ }
72
140
  /** A workspace reorder named a source or anchor absent from the durable registry order. */
73
141
  export class WorkspaceOrderInvalidError extends Error {
74
142
  workspaceId;
@@ -134,6 +202,7 @@ export class WorkspaceRegistry extends Service {
134
202
  await domain.refresh();
135
203
  this.state = domain.global.get();
136
204
  await this.recoverPendingMutation();
205
+ await this.recoverSessionDeletion();
137
206
  this.validateStoredState(this.requireState());
138
207
  if (!this.requireState().initialized) {
139
208
  const headers = await this.listStoredHeaders();
@@ -296,6 +365,144 @@ export class WorkspaceRegistry extends Service {
296
365
  get archivedSessionIds() {
297
366
  return this.requireState().archivedSessionIds;
298
367
  }
368
+ /** Permanently deleted identities retained for cross-process invalidation and stale-operation refusal. */
369
+ get deletedSessionIds() {
370
+ return this.requireState().deletedSessionIds ?? [];
371
+ }
372
+ /**
373
+ * Permanently delete an archived, inactive root and its owned subagent descendants.
374
+ * Independent forks are preserved. Reserve every writer before recording a recovery
375
+ * marker; a failure after that marker is retried on refresh or restart.
376
+ * @param sessionId - archived root identity; repeated deletion is idempotent.
377
+ * @param expectedIds - identities confirmed by the user; a changed scope refuses deletion.
378
+ * @returns deleted root and descendant identities after durable cleanup.
379
+ */
380
+ deleteSession(sessionId, expectedIds) {
381
+ return this.enqueueOperation(async () => {
382
+ const env_1 = { stack: [], error: void 0, hasError: false };
383
+ try {
384
+ if (this.deletedSessionIds.includes(sessionId))
385
+ return [sessionId];
386
+ if (!this.archivedSessionIds.includes(sessionId))
387
+ throw new WorkspaceSessionDeletionError(sessionId, 'not-archived');
388
+ const ids = new Set(await this.collectSessionDeletionScope(sessionId));
389
+ if (expectedIds !== undefined && (expectedIds.length !== ids.size
390
+ || new Set(expectedIds).size !== ids.size || expectedIds.some(id => !ids.has(id)))) {
391
+ throw new WorkspaceSessionDeletionError(sessionId, 'scope-changed');
392
+ }
393
+ for (const id of ids) {
394
+ const activity = await this.ctx.waterfall('workspace/session-activity', { sessionId: id }, () => Promise.resolve([]));
395
+ if (activity.length > 0)
396
+ throw new WorkspaceActiveSessionError(id, activity);
397
+ }
398
+ const targets = [...ids];
399
+ await this.ctx.parallel('session/delete-release', { sessionIds: targets });
400
+ for (const id of ids) {
401
+ if (this.ctx.get('sessions')?.get(id) !== undefined)
402
+ throw new WorkspaceSessionDeletionError(id, 'in-use');
403
+ }
404
+ const reservation = __addDisposableResource(env_1, await this.ctx.sessionPersistence.prepareDeletion(targets).catch((error) => {
405
+ if (error instanceof SessionAlreadyOwnedError)
406
+ throw new WorkspaceSessionDeletionError(sessionId, 'in-use');
407
+ throw error;
408
+ }), true);
409
+ await this.setState({ ...this.requireState(), pendingSessionDeletion: targets });
410
+ await reservation.commit();
411
+ await this.finishSessionDeletion(targets);
412
+ return targets;
413
+ }
414
+ catch (e_1) {
415
+ env_1.error = e_1;
416
+ env_1.hasError = true;
417
+ }
418
+ finally {
419
+ const result_1 = __disposeResources(env_1);
420
+ if (result_1)
421
+ await result_1;
422
+ }
423
+ });
424
+ }
425
+ /**
426
+ * Preview the root and owned descendants without opening their histories.
427
+ * @param sessionId - archived root to preview.
428
+ * @returns identities to show in the deletion confirmation.
429
+ */
430
+ sessionDeletionScope(sessionId) {
431
+ return this.enqueueOperation(async () => {
432
+ if (!this.archivedSessionIds.includes(sessionId))
433
+ throw new WorkspaceSessionDeletionError(sessionId, 'not-archived');
434
+ return this.collectSessionDeletionScope(sessionId);
435
+ });
436
+ }
437
+ async collectSessionDeletionScope(sessionId) {
438
+ const headers = await this.listStoredHeaders();
439
+ const ids = new Set([sessionId]);
440
+ for (let changed = true; changed;) {
441
+ changed = false;
442
+ for (const header of headers) {
443
+ if (header.origin === 'subagent' && header.parentSession !== undefined
444
+ && ids.has(header.parentSession) && !ids.has(header.id)) {
445
+ ids.add(header.id);
446
+ changed = true;
447
+ }
448
+ }
449
+ }
450
+ return [...ids];
451
+ }
452
+ async recoverSessionDeletion() {
453
+ const env_2 = { stack: [], error: void 0, hasError: false };
454
+ try {
455
+ const ids = this.requireState().pendingSessionDeletion;
456
+ if (ids === undefined)
457
+ return;
458
+ const reservation = __addDisposableResource(env_2, await this.ctx.sessionPersistence.prepareDeletion(ids), true);
459
+ await reservation.commit();
460
+ await this.finishSessionDeletion(ids);
461
+ }
462
+ catch (e_2) {
463
+ env_2.error = e_2;
464
+ env_2.hasError = true;
465
+ }
466
+ finally {
467
+ const result_2 = __disposeResources(env_2);
468
+ if (result_2)
469
+ await result_2;
470
+ }
471
+ }
472
+ notifyDeleted(ids) {
473
+ try {
474
+ this.ctx.emit('session/deleted', ids);
475
+ }
476
+ catch (error) {
477
+ this.ctx.logger.warn(`workspace: deletion listener failed: ${String(error)}`);
478
+ }
479
+ }
480
+ async finishSessionDeletion(ids) {
481
+ await this.ctx.parallel('session/deleting', { sessionIds: ids });
482
+ const removed = new Set(ids);
483
+ for (const [id, record] of this.requireTable().entries()) {
484
+ if (record.sessionIds.some(member => removed.has(member))) {
485
+ await this.requireTable().update(id, current => ({
486
+ ...current, sessionIds: current.sessionIds.filter(member => !removed.has(member)), updatedAt: new Date().toISOString(),
487
+ }));
488
+ }
489
+ }
490
+ const state = this.requireState();
491
+ await this.setState({
492
+ ...state,
493
+ archivedSessionIds: state.archivedSessionIds.filter(id => !removed.has(id)),
494
+ pinnedSessionIds: state.pinnedSessionIds.filter(id => !removed.has(id)),
495
+ deletedSessionIds: [...new Set([...(state.deletedSessionIds ?? []), ...ids])],
496
+ pendingSessionDeletion: undefined,
497
+ });
498
+ for (const id of ids) {
499
+ this.headers.delete(id);
500
+ this.sessionPaths.delete(id);
501
+ this.invalidSessionPaths.delete(id);
502
+ }
503
+ this.rebuildEntities();
504
+ this.notifyDeleted(ids);
505
+ }
299
506
  /**
300
507
  * Archive one session durably. The session must exist (live or in session
301
508
  * persistence); its workspace accounting — or lack of one — is irrelevant.
@@ -349,6 +556,8 @@ export class WorkspaceRegistry extends Service {
349
556
  */
350
557
  unarchiveSession(sessionId) {
351
558
  return this.enqueueOperation(async () => {
559
+ if (this.deletedSessionIds.includes(sessionId))
560
+ throw new WorkspaceSessionDeletionError(sessionId, 'deleted');
352
561
  // The chain slot serializes against every other registry write, so this
353
562
  // check-then-write pair cannot interleave with a concurrent archive.
354
563
  const state = this.requireState();
@@ -422,6 +631,8 @@ export class WorkspaceRegistry extends Service {
422
631
  * masquerade as an unknown session.
423
632
  */
424
633
  async sessionKnown(id) {
634
+ if (this.deletedSessionIds.includes(id))
635
+ return false;
425
636
  if (this.ctx.get('sessions')?.get(id) !== undefined)
426
637
  return true;
427
638
  if (this.headers.has(id))
@@ -766,13 +977,14 @@ export class WorkspaceRegistry extends Service {
766
977
  /** Every stored session's header, projected from the persistence snapshot listing. */
767
978
  async listStoredHeaders() {
768
979
  const snapshots = await this.ctx.sessionPersistence.list();
769
- return snapshots.map(snapshot => snapshot.header);
980
+ const deleted = new Set(this.deletedSessionIds);
981
+ return snapshots.map(snapshot => snapshot.header).filter(header => !deleted.has(header.id));
770
982
  }
771
983
  async indexLiveSessions() {
772
984
  const sessions = this.ctx.get('sessions');
773
985
  if (sessions === undefined)
774
986
  return;
775
- await this.indexHeaders(sessions.list().map(session => session.header));
987
+ await this.indexHeaders(sessions.list().filter(session => !this.deletedSessionIds.includes(session.id)).map(session => session.header));
776
988
  }
777
989
  reportFilteredCandidates() {
778
990
  for (const entity of this.entities.values()) {
@@ -829,6 +1041,7 @@ export class WorkspaceRegistry extends Service {
829
1041
  throw new Error('workspace registry is not started yet');
830
1042
  return await domain.exclusive(async () => {
831
1043
  const before = JSON.stringify([...this.entities.values()].map(entity => [entity.id, entity.sessionIds]));
1044
+ const previousDeleted = new Set(this.deletedSessionIds);
832
1045
  await domain.refresh();
833
1046
  const changed = this.snapshotIdentity() !== this.refreshedState;
834
1047
  this.state = domain.global.get();
@@ -839,6 +1052,10 @@ export class WorkspaceRegistry extends Service {
839
1052
  this.rebuildEntities();
840
1053
  }
841
1054
  await this.recoverPendingMutation();
1055
+ await this.recoverSessionDeletion();
1056
+ const newlyDeleted = this.deletedSessionIds.filter(id => !previousDeleted.has(id));
1057
+ if (newlyDeleted.length > 0)
1058
+ this.notifyDeleted(newlyDeleted);
842
1059
  this.validateStoredState(this.requireState());
843
1060
  const after = JSON.stringify([...this.entities.values()].map(entity => [entity.id, entity.sessionIds]));
844
1061
  if (changed || before !== after) {
@@ -46,6 +46,8 @@ export declare const workspaceDomainState: z.ZodObject<{
46
46
  operation: z.ZodLiteral<"delete">;
47
47
  workspaceId: z.ZodPipe<z.ZodString, z.ZodTransform<WorkspaceId, string>>;
48
48
  }, z.core.$strip>], "operation">>;
49
+ deletedSessionIds: z.ZodOptional<z.ZodArray<z.ZodPipe<z.ZodString, z.ZodTransform<SessionId, string>>>>;
50
+ pendingSessionDeletion: z.ZodOptional<z.ZodArray<z.ZodPipe<z.ZodString, z.ZodTransform<SessionId, string>>>>;
49
51
  }, z.core.$strip>;
50
52
  /** Durable registry state inferred from {@link workspaceDomainState}. */
51
53
  export type WorkspaceDomainState = z.infer<typeof workspaceDomainState>;
@@ -72,6 +74,8 @@ export declare const workspaceDomainSpec: {
72
74
  operation: z.ZodLiteral<"delete">;
73
75
  workspaceId: z.ZodPipe<z.ZodString, z.ZodTransform<WorkspaceId, string>>;
74
76
  }, z.core.$strip>], "operation">>;
77
+ deletedSessionIds: z.ZodOptional<z.ZodArray<z.ZodPipe<z.ZodString, z.ZodTransform<SessionId, string>>>>;
78
+ pendingSessionDeletion: z.ZodOptional<z.ZodArray<z.ZodPipe<z.ZodString, z.ZodTransform<SessionId, string>>>>;
75
79
  }, z.core.$strip>;
76
80
  initial: {
77
81
  initialized: boolean;