@khorsheed/dsh-client-message-tools 0.1.0 → 0.2.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.
Files changed (44) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.en.md +15 -11
  3. package/README.i18n.yaml +2 -2
  4. package/README.md +35 -31
  5. package/lib/client.js +276 -131
  6. package/lib/client.js.map +1 -1
  7. package/lib/index.js +16 -15
  8. package/lib/tsconfig.client.tsbuildinfo +1 -1
  9. package/lib/tsconfig.host.tsbuildinfo +1 -1
  10. package/lib/typert.host.js +3 -3
  11. package/lib/typert.remote-client.d.ts.map +1 -1
  12. package/lib/typert.remote-client.js +3 -3
  13. package/lib/types/client/RestoredMessageView.d.ts +1 -1
  14. package/lib/types/client/RestoredMessageView.d.ts.map +1 -1
  15. package/lib/types/client/RestoredMessageView.js +20 -1
  16. package/lib/types/client/UserMessageView.d.ts +1 -1
  17. package/lib/types/client/UserMessageView.d.ts.map +1 -1
  18. package/lib/types/client/UserMessageView.js +9 -6
  19. package/lib/types/client/WithdrawnDividerView.d.ts +1 -1
  20. package/lib/types/client/WithdrawnDividerView.d.ts.map +1 -1
  21. package/lib/types/client/WithdrawnDividerView.js +11 -7
  22. package/lib/types/client/chat-hook.d.ts +36 -0
  23. package/lib/types/client/chat-hook.d.ts.map +1 -0
  24. package/lib/types/client/chat-hook.js +51 -0
  25. package/lib/types/client/dom-hider.d.ts +3 -2
  26. package/lib/types/client/dom-hider.d.ts.map +1 -1
  27. package/lib/types/client/dom-hider.js +20 -13
  28. package/lib/types/client/edit-in-place.d.ts +2 -1
  29. package/lib/types/client/edit-in-place.d.ts.map +1 -1
  30. package/lib/types/client/index.d.ts +6 -4
  31. package/lib/types/client/index.d.ts.map +1 -1
  32. package/lib/types/client/index.js +42 -8
  33. package/lib/types/client/locales.d.ts +8 -0
  34. package/lib/types/client/locales.d.ts.map +1 -1
  35. package/lib/types/client/locales.js +8 -0
  36. package/lib/types/client/slots.d.ts.map +1 -1
  37. package/lib/types/client/withdrawn-node.d.ts +3 -2
  38. package/lib/types/client/withdrawn-node.d.ts.map +1 -1
  39. package/lib/types/client/withdrawn-node.js +43 -52
  40. package/lib/types/index.d.ts.map +1 -1
  41. package/lib/types/index.js +10 -8
  42. package/lib/types/withdraw.d.ts.map +1 -1
  43. package/lib/types/withdraw.js +10 -6
  44. package/package.json +19 -18
package/lib/client.js CHANGED
@@ -5,7 +5,6 @@ window.__ModuleLoader__.load({
5
5
  var exports = module.exports;
6
6
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
7
7
  let react = require("react");
8
- let _deepseek_ai_dsh_client_runtime_client = require("@deepseek-ai/dsh-client-runtime/client");
9
8
  let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
10
9
  let react_jsx_runtime = require("react/jsx-runtime");
11
10
  //#region ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/core.js
@@ -4142,7 +4141,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4142
4141
  },
4143
4142
  sourceLocation: {
4144
4143
  "file": "packages/message-tools/src/index.ts",
4145
- "line": 133,
4144
+ "line": 135,
4146
4145
  "column": 9
4147
4146
  }
4148
4147
  },
@@ -4169,7 +4168,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4169
4168
  },
4170
4169
  sourceLocation: {
4171
4170
  "file": "packages/message-tools/src/index.ts",
4172
- "line": 95,
4171
+ "line": 97,
4173
4172
  "column": 9
4174
4173
  }
4175
4174
  },
@@ -4196,23 +4195,82 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4196
4195
  },
4197
4196
  sourceLocation: {
4198
4197
  "file": "packages/message-tools/src/index.ts",
4199
- "line": 61,
4198
+ "line": 63,
4200
4199
  "column": 9
4201
4200
  }
4202
4201
  }
4203
4202
  ]
4204
4203
  };
4205
4204
  //#endregion
4206
- //#region ../../node_modules/.pnpm/@deepseek-ai+dsh-session@0.1.1-rc.2_a4e4bb24a1f3580ac25e11cfa3c6b8cc/node_modules/@deepseek-ai/dsh-session/lib/types/surface.js
4205
+ //#region src/client/chat-hook.ts
4207
4206
  /**
4208
- * Surface layer on top of the session event log: an ordered view of events
4209
- * that produce LLM messages. The append-only log remains the source of truth.
4210
- *
4211
- * Browser-safe: web clients consume this subpath export, so it must stay free
4212
- * of `node:` imports (they break the vite bundle).
4213
- *
4214
- * @module @deepseek-ai/dsh-session/surface
4207
+ * Frozen empty chat snapshot for the degraded render path: a composition
4208
+ * without ui-chat never mounts the `conversation.chat.node` slot at all, so
4209
+ * this only guards a stray render — hook call order stays stable and every
4210
+ * selector reads the empty state.
4215
4211
  */
4212
+ const EMPTY_CHAT = {
4213
+ order: [],
4214
+ nodes: {
4215
+ get: () => void 0,
4216
+ source: () => ({
4217
+ getSnapshot: () => void 0,
4218
+ subscribe: () => () => {}
4219
+ }),
4220
+ processSource: () => ({
4221
+ getSnapshot: () => void 0,
4222
+ subscribe: () => () => {}
4223
+ }),
4224
+ values: () => []
4225
+ },
4226
+ locations: {
4227
+ getTurn: () => [],
4228
+ getStep: () => []
4229
+ },
4230
+ navigation: { items: () => [] },
4231
+ timeline: {
4232
+ turnOrder: [],
4233
+ turns: /* @__PURE__ */ new Map()
4234
+ },
4235
+ legacy: {
4236
+ nodes: [],
4237
+ turnTimings: /* @__PURE__ */ new Map(),
4238
+ turnEnds: /* @__PURE__ */ new Map(),
4239
+ partial: null,
4240
+ runningCalls: []
4241
+ }
4242
+ };
4243
+ /**
4244
+ * Pick the live chat hook from the entry's composed props (`useChat` is a
4245
+ * session standard prop on 0.1.2), degrading to the frozen empty snapshot
4246
+ * when the framework composed none.
4247
+ * @param props - the entry's composed props.
4248
+ * @returns the chat selector hook.
4249
+ */
4250
+ function chatHookOf(props) {
4251
+ const direct = props.useChat;
4252
+ if (direct !== void 0) return direct;
4253
+ return (selector) => selector(EMPTY_CHAT);
4254
+ }
4255
+ /**
4256
+ * Resolve the apply-world chat source for one session.
4257
+ * @param ctx - client root context.
4258
+ * @param sessionId - owning session.
4259
+ * @returns the conversation binding's chat target (its snapshot is undefined
4260
+ * until the first subscription activates the view), or undefined when the
4261
+ * uiConversation service or the session binding is absent.
4262
+ */
4263
+ function chatSourceOf(ctx, sessionId) {
4264
+ const uiConversation = ctx.get("uiConversation");
4265
+ if (uiConversation === void 0) return void 0;
4266
+ try {
4267
+ return uiConversation.binding(sessionId).target("chat");
4268
+ } catch {
4269
+ return;
4270
+ }
4271
+ }
4272
+ //#endregion
4273
+ //#region ../../node_modules/.pnpm/@deepseek-ai+dsh-session@0.1.2-rc.1_@deepseek-ai+cordis@4.0.1_@deepseek-ai+dsh-scope@0._5663fee33a080ce0d83159e01d0d0704/node_modules/@deepseek-ai/dsh-session/lib/types/surface.js
4216
4274
  /** Runtime counterpart of the message-producing event union. */
4217
4275
  const SURFACE_EVENT_TYPES = /* @__PURE__ */ new Set([
4218
4276
  "user/message",
@@ -4302,6 +4360,24 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4302
4360
  //#endregion
4303
4361
  //#region src/client/withdrawn-node.ts
4304
4362
  /**
4363
+ * Materialize one final chat-target node. The Definition contract's
4364
+ * buildViewNode returns the ConversationViewNode base (key/kind/id/target/
4365
+ * data), so the chat extras (anchorSeq/location/visibility) go through this
4366
+ * explicitly typed builder instead of an excess-checked literal.
4367
+ */
4368
+ function chatViewNode(context, kind, anchorSeq, data) {
4369
+ return {
4370
+ key: context.key,
4371
+ kind,
4372
+ id: context.id,
4373
+ target: "chat",
4374
+ anchorSeq,
4375
+ location: context.start?.location ?? { kind: "unresolved" },
4376
+ visibility: "visible",
4377
+ data
4378
+ };
4379
+ }
4380
+ /**
4305
4381
  * The withdrawal divider Definition: one single-event Context per
4306
4382
  * message-tools replacement event, anchored at the replacement's seq so the
4307
4383
  * divider sits exactly where the span was hidden.
@@ -4309,10 +4385,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4309
4385
  const withdrawnDividerDefinition = {
4310
4386
  kind: "message-tools-withdrawn",
4311
4387
  target: "chat",
4312
- match: (event) => isMessageToolsReplacement(event) ? {
4313
- id: String(event.seq),
4314
- role: "start"
4315
- } : null,
4388
+ match: (event) => {
4389
+ if (event.type !== "user/message") return null;
4390
+ return isMessageToolsReplacement(event) ? {
4391
+ id: String(event.seq),
4392
+ role: "start"
4393
+ } : null;
4394
+ },
4316
4395
  start: (_context, match) => {
4317
4396
  const event = match.event;
4318
4397
  if (!isMessageToolsReplacement(event)) throw new Error("message-tools-withdrawn start requires a message-tools replacement event");
@@ -4322,16 +4401,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4322
4401
  };
4323
4402
  },
4324
4403
  update: (context) => context.state,
4325
- buildViewNode: (context) => context.state === void 0 ? null : {
4326
- key: context.key,
4327
- kind: "message-tools-withdrawn",
4328
- id: context.id,
4329
- target: "chat",
4330
- anchorSeq: context.state.seq,
4331
- location: context.start?.location ?? { kind: "unresolved" },
4332
- visibility: "visible",
4333
- data: context.state
4334
- }
4404
+ buildViewNode: (context) => context.state === void 0 ? null : chatViewNode(context, "message-tools-withdrawn", context.state.seq, context.state)
4335
4405
  };
4336
4406
  /**
4337
4407
  * The edited-bubble Definition: one single-event Context per message-tools
@@ -4342,10 +4412,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4342
4412
  const editedMessageDefinition = {
4343
4413
  kind: "message-tools-edited",
4344
4414
  target: "chat",
4345
- match: (event) => isMessageToolsEdit(event) ? {
4346
- id: String(event.seq),
4347
- role: "start"
4348
- } : null,
4415
+ match: (event) => {
4416
+ if (event.type !== "user/message") return null;
4417
+ return isMessageToolsEdit(event) ? {
4418
+ id: String(event.seq),
4419
+ role: "start"
4420
+ } : null;
4421
+ },
4349
4422
  start: (_context, match) => {
4350
4423
  const event = match.event;
4351
4424
  if (!isMessageToolsEdit(event)) throw new Error("message-tools-edited start requires a message-tools edit replacement event");
@@ -4357,16 +4430,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4357
4430
  };
4358
4431
  },
4359
4432
  update: (context) => context.state,
4360
- buildViewNode: (context) => context.state === void 0 ? null : {
4361
- key: context.key,
4362
- kind: "message-tools-edited",
4363
- id: context.id,
4364
- target: "chat",
4365
- anchorSeq: context.state.seq,
4366
- location: context.start?.location ?? { kind: "unresolved" },
4367
- visibility: "visible",
4368
- data: context.state
4369
- }
4433
+ buildViewNode: (context) => context.state === void 0 ? null : chatViewNode(context, "message-tools-edited", context.state.seq, context.state)
4370
4434
  };
4371
4435
  /**
4372
4436
  * Fold the hidden seq spans out of the live chat nodes, flattened to
@@ -4405,10 +4469,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4405
4469
  const restoredMessageDefinition = {
4406
4470
  kind: "message-tools-restored",
4407
4471
  target: "chat",
4408
- match: (event) => isMessageToolsRestore(event) ? {
4409
- id: String(event.seq),
4410
- role: "start"
4411
- } : null,
4472
+ match: (event) => {
4473
+ if (event.type !== "user/message") return null;
4474
+ return isMessageToolsRestore(event) ? {
4475
+ id: String(event.seq),
4476
+ role: "start"
4477
+ } : null;
4478
+ },
4412
4479
  start: (_context, match) => {
4413
4480
  const event = match.event;
4414
4481
  if (!isMessageToolsRestore(event)) throw new Error("message-tools-restored start requires a message-tools restore event");
@@ -4421,16 +4488,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4421
4488
  };
4422
4489
  },
4423
4490
  update: (context) => context.state,
4424
- buildViewNode: (context) => context.state === void 0 ? null : {
4425
- key: context.key,
4426
- kind: "message-tools-restored",
4427
- id: context.id,
4428
- target: "chat",
4429
- anchorSeq: context.state.seq,
4430
- location: context.start?.location ?? { kind: "unresolved" },
4431
- visibility: "visible",
4432
- data: context.state
4433
- }
4491
+ buildViewNode: (context) => context.state === void 0 ? null : chatViewNode(context, "message-tools-restored", context.state.seq, context.state)
4434
4492
  };
4435
4493
  /**
4436
4494
  * The restore-assistant-line Definition: one single-event Context per
@@ -4442,10 +4500,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4442
4500
  const restoredAssistantMessageDefinition = {
4443
4501
  kind: "message-tools-restored-assistant",
4444
4502
  target: "chat",
4445
- match: (event) => isMessageToolsRestoreAssistant(event) ? {
4446
- id: String(event.seq),
4447
- role: "start"
4448
- } : null,
4503
+ match: (event) => {
4504
+ if (event.type !== "user/message") return null;
4505
+ return isMessageToolsRestoreAssistant(event) ? {
4506
+ id: String(event.seq),
4507
+ role: "start"
4508
+ } : null;
4509
+ },
4449
4510
  start: (_context, match) => {
4450
4511
  const event = match.event;
4451
4512
  if (!isMessageToolsRestoreAssistant(event)) throw new Error("message-tools-restored-assistant start requires a restore-assistant replay event");
@@ -4457,16 +4518,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4457
4518
  };
4458
4519
  },
4459
4520
  update: (context) => context.state,
4460
- buildViewNode: (context) => context.state === void 0 ? null : {
4461
- key: context.key,
4462
- kind: "message-tools-restored-assistant",
4463
- id: context.id,
4464
- target: "chat",
4465
- anchorSeq: context.state.seq,
4466
- location: context.start?.location ?? { kind: "unresolved" },
4467
- visibility: "visible",
4468
- data: context.state
4469
- }
4521
+ buildViewNode: (context) => context.state === void 0 ? null : chatViewNode(context, "message-tools-restored-assistant", context.state.seq, context.state)
4470
4522
  };
4471
4523
  /**
4472
4524
  * Count the user-visible messages hidden by one withdrawn span. This mirrors
@@ -4638,9 +4690,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4638
4690
  let retryObserver;
4639
4691
  let retryTimer;
4640
4692
  let latest;
4641
- const applyRules = (snapshot) => {
4642
- latest = snapshot;
4643
- const nodes = snapshot.chat.nodes.values();
4693
+ const applyRules = (chat) => {
4694
+ latest = chat;
4695
+ const nodes = chat.nodes.values();
4644
4696
  const ranges = foldHiddenRanges(nodes);
4645
4697
  const nextSignature = `${ranges.join(",")}:${nodes.length}`;
4646
4698
  if (nextSignature === signature) return;
@@ -4699,14 +4751,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4699
4751
  else failProbe();
4700
4752
  }, probeRetryWindowMs);
4701
4753
  };
4702
- const onSnapshot = (snapshot) => {
4703
- latest = snapshot;
4754
+ const onSnapshot = (chat) => {
4755
+ latest = chat;
4704
4756
  if (disabled) return;
4705
4757
  if (probed) {
4706
- applyRules(snapshot);
4758
+ applyRules(chat);
4707
4759
  return;
4708
4760
  }
4709
- if (hiddenFlowKeys(snapshot.chat.nodes.values()).length === 0) return;
4761
+ if (hiddenFlowKeys(chat.nodes.values()).length === 0) return;
4710
4762
  if (probeScheduled || retrying) return;
4711
4763
  probeScheduled = true;
4712
4764
  nextFrame(() => {
@@ -4727,19 +4779,19 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4727
4779
  signature = "";
4728
4780
  style.textContent = "";
4729
4781
  if (current === void 0) return;
4730
- const binding = ctx.sessions.binding(current);
4731
- if (binding === void 0) return;
4732
- onSnapshot(binding.session.getSnapshot());
4733
- stopSession = binding.session.subscribe(() => {
4734
- onSnapshot(binding.session.getSnapshot());
4735
- });
4782
+ const source = chatSourceOf(ctx, current);
4783
+ if (source === void 0) return;
4784
+ const publish = () => {
4785
+ const chat = source.getSnapshot();
4786
+ if (chat !== void 0) onSnapshot(chat);
4787
+ };
4788
+ publish();
4789
+ stopSession = source.subscribe(publish);
4736
4790
  };
4737
4791
  const stopList = ctx.sessions.list.subscribe(bindCurrent);
4738
- const stopProvide = ctx.sessions.currentProvideInfo.subscribe(bindCurrent);
4739
4792
  bindCurrent();
4740
4793
  return () => {
4741
4794
  stopList();
4742
- stopProvide();
4743
4795
  stopSession?.();
4744
4796
  stopRetry();
4745
4797
  style.remove();
@@ -4888,6 +4940,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4888
4940
  "model.empty": "暂无可用模型",
4889
4941
  "model.selectFailed": "模型切换失败",
4890
4942
  "message.extraBlock": "附加内容块",
4943
+ "close": "关闭",
4944
+ "markdown.copy": "复制",
4945
+ "markdown.copied": "已复制",
4946
+ "markdown.footnotes": "脚注",
4891
4947
  "json.truncated": "… 已截断,共 {total} 字符"
4892
4948
  };
4893
4949
  /** English dictionary, checked complete against the zh key set. */
@@ -4920,9 +4976,45 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4920
4976
  "model.empty": "No models available",
4921
4977
  "model.selectFailed": "Could not switch model",
4922
4978
  "message.extraBlock": "Extra content block",
4979
+ "close": "Close",
4980
+ "markdown.copy": "Copy",
4981
+ "markdown.copied": "Copied",
4982
+ "markdown.footnotes": "Footnotes",
4923
4983
  "json.truncated": "… truncated, {total} characters total"
4924
4984
  };
4925
4985
  //#endregion
4986
+ //#region ../../node_modules/.pnpm/zustand@4.4.7_@types+react@18.3.31_immer@10.2.0_react@18.3.1/node_modules/zustand/esm/shallow.mjs
4987
+ function shallow$1(objA, objB) {
4988
+ if (Object.is(objA, objB)) return true;
4989
+ if (typeof objA !== "object" || objA === null || typeof objB !== "object" || objB === null) return false;
4990
+ if (objA instanceof Map && objB instanceof Map) {
4991
+ if (objA.size !== objB.size) return false;
4992
+ for (const [key, value] of objA) if (!Object.is(value, objB.get(key))) return false;
4993
+ return true;
4994
+ }
4995
+ if (objA instanceof Set && objB instanceof Set) {
4996
+ if (objA.size !== objB.size) return false;
4997
+ for (const value of objA) if (!objB.has(value)) return false;
4998
+ return true;
4999
+ }
5000
+ const keysA = Object.keys(objA);
5001
+ if (keysA.length !== Object.keys(objB).length) return false;
5002
+ for (let i = 0; i < keysA.length; i++) if (!Object.prototype.hasOwnProperty.call(objB, keysA[i]) || !Object.is(objA[keysA[i]], objB[keysA[i]])) return false;
5003
+ return true;
5004
+ }
5005
+ //#endregion
5006
+ //#region ../../node_modules/.pnpm/@deepseek-ai+dsh-client-store@0.1.2-rc.1_@deepseek-ai+cordis@4.0.1_@types+react@18.3.31_react@18.3.1/node_modules/@deepseek-ai/dsh-client-store/lib/index.js
5007
+ /**
5008
+ * Shallow equality for selector slices (zustand/shallow semantics; travels
5009
+ * with the engine so hook consumers need no zustand dependency).
5010
+ * @param a - left value.
5011
+ * @param b - right value.
5012
+ * @returns whether the values are shallowly equal.
5013
+ */
5014
+ function shallowEqual(a, b) {
5015
+ return shallow$1(a, b);
5016
+ }
5017
+ //#endregion
4926
5018
  //#region src/client/icons.tsx
4927
5019
  /**
4928
5020
  * Undo arrow (withdraw/restore), rotate-ccw style: a near-full circle arc
@@ -4964,7 +5056,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4964
5056
  if (text !== "") steps.backfill(text);
4965
5057
  }
4966
5058
  //#endregion
4967
- //#region \0dsh-css:/Users/zhuyudan/code/dsh-plugins/packages/message-tools/src/client/ModelChip.module.css.mjs
5059
+ //#region \0dsh-css:src/client/ModelChip.module.css.mjs
4968
5060
  const css$3 = ".he-h5G_chip{align-items:center;gap:6px;display:flex;position:relative}.he-h5G_trigger{height:28px;color:var(--dsw-alias-label-secondary,var(--dsw-alias-label-primary));cursor:pointer;background:0 0;border:none;border-radius:24px;align-items:center;gap:4px;padding:0 8px;font-size:13px;font-weight:500;display:inline-flex}.he-h5G_trigger:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover,var(--dsw-alias-bg-layer-1))}.he-h5G_trigger:disabled{cursor:default;opacity:.6}.he-h5G_triggerEffort{color:var(--dsw-alias-label-tertiary,var(--dsw-alias-label-primary-dimmed))}.he-h5G_menu{z-index:20;border:1px solid var(--dsw-alias-border-l1,var(--dsw-alias-border-l2,var(--dsw-alias-label-primary-dimmed)));background:var(--dsw-alias-bg-base,var(--dsw-alias-bg-layer-1));min-width:220px;max-height:320px;box-shadow:0 4px 16px var(--dsw-alias-shadow,var(--dsw-alias-border-l2,#0000001f));border-radius:8px;padding:4px;position:absolute;bottom:calc(100% + 4px);left:0;overflow-y:auto}.he-h5G_group+.he-h5G_group{margin-top:4px}.he-h5G_groupTitle{color:var(--dsw-alias-label-tertiary,var(--dsw-alias-label-primary-dimmed));padding:4px 8px;font-size:12px;line-height:18px}.he-h5G_option{width:100%;color:var(--dsw-alias-label-primary,var(--dsw-alias-label-secondary));text-align:left;cursor:pointer;background:0 0;border:none;border-radius:6px;justify-content:space-between;align-items:center;gap:8px;padding:6px 8px;font-size:13px;line-height:20px;display:flex}.he-h5G_option:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover,var(--dsw-alias-bg-layer-1))}.he-h5G_option:disabled{cursor:default;opacity:.6}.he-h5G_check{width:16px;color:var(--dsw-alias-label-primary,var(--dsw-alias-label-secondary));flex:none;display:inline-flex}.he-h5G_empty{color:var(--dsw-alias-label-tertiary,var(--dsw-alias-label-primary-dimmed));padding:8px;font-size:13px}.he-h5G_selectFailed{color:var(--dsw-alias-state-error-primary,var(--dsw-alias-label-secondary));white-space:nowrap;font-size:12px}";
4969
5061
  const tagId$3 = "@khorsheed/dsh-client-message-tools/ModelChip.module.css";
4970
5062
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$3) + "]") === null) {
@@ -4975,16 +5067,16 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4975
5067
  document.head.appendChild(tag);
4976
5068
  }
4977
5069
  var ModelChip_module_css_default = {
4978
- "triggerEffort": "he-h5G_triggerEffort",
4979
- "groupTitle": "he-h5G_groupTitle",
4980
5070
  "chip": "he-h5G_chip",
4981
- "check": "he-h5G_check",
4982
- "trigger": "he-h5G_trigger",
4983
- "option": "he-h5G_option",
5071
+ "groupTitle": "he-h5G_groupTitle",
4984
5072
  "empty": "he-h5G_empty",
4985
5073
  "selectFailed": "he-h5G_selectFailed",
4986
- "group": "he-h5G_group",
4987
- "menu": "he-h5G_menu"
5074
+ "triggerEffort": "he-h5G_triggerEffort",
5075
+ "menu": "he-h5G_menu",
5076
+ "trigger": "he-h5G_trigger",
5077
+ "check": "he-h5G_check",
5078
+ "option": "he-h5G_option",
5079
+ "group": "he-h5G_group"
4988
5080
  };
4989
5081
  //#endregion
4990
5082
  //#region src/client/ModelChip.tsx
@@ -5156,7 +5248,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5156
5248
  });
5157
5249
  }
5158
5250
  //#endregion
5159
- //#region \0dsh-css:/Users/zhuyudan/code/dsh-plugins/packages/message-tools/src/client/UserMessageView.module.css.mjs
5251
+ //#region \0dsh-css:src/client/UserMessageView.module.css.mjs
5160
5252
  const css$2 = ".kCWYAa_userRow{flex-direction:column;align-items:flex-end;gap:6px;display:flex}.kCWYAa_userStack{flex-direction:column;align-items:flex-end;gap:8px;min-width:0;max-width:min(525px,82%);display:flex}.kCWYAa_bubble{background:var(--dsw-specific-bubble,var(--dsw-alias-bg-layer-1));max-width:100%;color:var(--dsw-alias-label-primary,var(--dsw-alias-label-secondary));border-radius:22px;padding:10px 16px;font-size:16px;line-height:24px}.kCWYAa_refChip{color:var(--dsw-alias-label-primary,var(--dsw-alias-label-secondary));white-space:nowrap;vertical-align:baseline;background:#6187d838;border-radius:6px;margin:0 2px;padding:0 8px;font-size:.85em;line-height:1.6;display:inline-block}.kCWYAa_actions{align-items:center;gap:10px;height:28px;display:flex}.kCWYAa_action{width:28px;height:28px;color:var(--dsw-alias-label-tertiary,var(--dsw-alias-label-primary-dimmed));cursor:pointer;background:0 0;border:none;border-radius:28px;justify-content:center;align-items:center;padding:6px;display:inline-flex}.kCWYAa_action:hover{background:var(--dsw-alias-interactive-bg-hover,var(--dsw-alias-bg-layer-1));color:var(--dsw-alias-label-secondary,var(--dsw-alias-label-primary))}.kCWYAa_editor{border:1px solid var(--dsw-alias-border-l1,var(--dsw-alias-border-l2,var(--dsw-alias-label-primary-dimmed)));background:var(--dsw-alias-bg-base,var(--dsw-alias-bg-layer-1));border-radius:8px;flex-direction:column;gap:8px;width:100%;padding:12px;display:flex}.kCWYAa_editorInput{border:1px solid var(--dsw-alias-border-l2,var(--dsw-alias-border-l1,var(--dsw-alias-label-primary-dimmed)));resize:none;width:100%;max-height:240px;color:var(--dsw-alias-label-primary,var(--dsw-alias-label-secondary));font:inherit;background:0 0;border-radius:6px;outline:none;padding:8px;overflow-y:auto}.kCWYAa_editorActions{justify-content:flex-end;align-items:center;gap:8px;display:flex}.kCWYAa_editorTrailing{align-items:center;margin-right:auto;display:flex}.kCWYAa_actionError{color:var(--dsw-alias-state-error-primary,var(--dsw-alias-label-secondary));align-self:flex-end;padding:2px 4px;font-size:13px;line-height:20px}.kCWYAa_editedLabel{color:var(--dsw-alias-label-tertiary,var(--dsw-alias-label-primary-dimmed));align-self:flex-end;font-size:12px;line-height:18px}";
5161
5253
  const tagId$2 = "@khorsheed/dsh-client-message-tools/UserMessageView.module.css";
5162
5254
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$2) + "]") === null) {
@@ -5167,18 +5259,18 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5167
5259
  document.head.appendChild(tag);
5168
5260
  }
5169
5261
  var UserMessageView_module_css_default = {
5170
- "actions": "kCWYAa_actions",
5262
+ "userRow": "kCWYAa_userRow",
5171
5263
  "bubble": "kCWYAa_bubble",
5264
+ "action": "kCWYAa_action",
5265
+ "editedLabel": "kCWYAa_editedLabel",
5172
5266
  "refChip": "kCWYAa_refChip",
5173
5267
  "editorActions": "kCWYAa_editorActions",
5174
- "editorTrailing": "kCWYAa_editorTrailing",
5175
- "editedLabel": "kCWYAa_editedLabel",
5176
- "userStack": "kCWYAa_userStack",
5177
- "userRow": "kCWYAa_userRow",
5178
- "action": "kCWYAa_action",
5179
5268
  "editorInput": "kCWYAa_editorInput",
5180
- "actionError": "kCWYAa_actionError",
5181
- "editor": "kCWYAa_editor"
5269
+ "editor": "kCWYAa_editor",
5270
+ "userStack": "kCWYAa_userStack",
5271
+ "actions": "kCWYAa_actions",
5272
+ "editorTrailing": "kCWYAa_editorTrailing",
5273
+ "actionError": "kCWYAa_actionError"
5182
5274
  };
5183
5275
  //#endregion
5184
5276
  //#region src/client/UserMessageView.tsx
@@ -5194,8 +5286,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5194
5286
  * marks the spot.
5195
5287
  */
5196
5288
  /** Selector identity kept module-level so uSES memoization holds. */
5197
- function selectHiddenRanges(snapshot) {
5198
- return foldHiddenRanges(snapshot.chat.nodes.values());
5289
+ function selectHiddenRanges(chat) {
5290
+ return foldHiddenRanges(chat.nodes.values());
5199
5291
  }
5200
5292
  /** Split user content into joined text, images, and leftover blocks. */
5201
5293
  function contentParts(content) {
@@ -5340,8 +5432,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5340
5432
  });
5341
5433
  }
5342
5434
  /** The shadowed user-message view: bubble plus copy/edit/withdraw actions. */
5343
- const UserMessageView = (0, react.memo)(function UserMessageView({ node, renderMessageImages, t, useSession, editMessage, withdrawMessage, backfillDraft, useModelDirectory, modelsAvailable, loadModels, selectModel }) {
5344
- const ranges = useSession(selectHiddenRanges, _deepseek_ai_dsh_client_runtime_client.shallowEqual);
5435
+ const UserMessageView = (0, react.memo)(function UserMessageView({ node, renderMessageImages, t, editMessage, withdrawMessage, backfillDraft, useModelDirectory, modelsAvailable, loadModels, selectModel, ...standard }) {
5436
+ const ranges = chatHookOf(standard)(selectHiddenRanges, shallowEqual);
5345
5437
  const [editing, setEditing] = (0, react.useState)(false);
5346
5438
  const [confirming, setConfirming] = (0, react.useState)(false);
5347
5439
  const [acknowledged, setAcknowledged] = (0, react.useState)(false);
@@ -5480,6 +5572,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5480
5572
  description: t("withdraw.description"),
5481
5573
  acknowledgeLabel: t("withdraw.acknowledge"),
5482
5574
  cancelLabel: t("cancel"),
5575
+ closeLabel: t("close"),
5483
5576
  confirmLabel: t("withdraw.confirm"),
5484
5577
  acknowledged,
5485
5578
  disabled: busy,
@@ -5494,7 +5587,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5494
5587
  });
5495
5588
  });
5496
5589
  //#endregion
5497
- //#region \0dsh-css:/Users/zhuyudan/code/dsh-plugins/packages/message-tools/src/client/RestoredMessageView.module.css.mjs
5590
+ //#region \0dsh-css:src/client/RestoredMessageView.module.css.mjs
5498
5591
  const css$1 = ".hDMXAG_restoredLabel{color:var(--dsw-alias-label-tertiary,var(--dsw-alias-label-primary-dimmed));align-items:center;gap:4px;font-size:12px;line-height:18px;display:inline-flex}.hDMXAG_restoredAssistantRow{color:var(--dsw-alias-label-primary,var(--dsw-alias-label-secondary));flex-direction:column;align-items:flex-start;gap:4px;display:flex}";
5499
5592
  const tagId$1 = "@khorsheed/dsh-client-message-tools/RestoredMessageView.module.css";
5500
5593
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
@@ -5505,24 +5598,48 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5505
5598
  document.head.appendChild(tag);
5506
5599
  }
5507
5600
  var RestoredMessageView_module_css_default = {
5508
- "restoredAssistantRow": "hDMXAG_restoredAssistantRow",
5509
- "restoredLabel": "hDMXAG_restoredLabel"
5601
+ "restoredLabel": "hDMXAG_restoredLabel",
5602
+ "restoredAssistantRow": "hDMXAG_restoredAssistantRow"
5510
5603
  };
5511
5604
  //#endregion
5512
5605
  //#region src/client/RestoredMessageView.tsx
5606
+ /**
5607
+ * Restored-assistant line ('message-tools-restored-assistant' keyed
5608
+ * renderer): one withdrawn assistant reply's text replayed at the
5609
+ * conversation tail by a restore. The body renders through the official
5610
+ * `MarkdownText` (the same public renderer behind ui-conversation's
5611
+ * AssistantMarkdown), so typography, code blocks, and lists match a native
5612
+ * assistant reply; the「已恢复 · 助手回复」caption stays as a small tertiary
5613
+ * marker. The model-facing frame text is not displayed (stripped in the
5614
+ * Definition). No action row: the group's user bubbles already carry copy.
5615
+ */
5616
+ /** Localized Markdown chrome (code-fence copy buttons, footnotes) over the message-tools namespace. */
5617
+ function markdownLabels(t) {
5618
+ return {
5619
+ code: {
5620
+ copyLabel: t("markdown.copy"),
5621
+ copiedLabel: t("markdown.copied")
5622
+ },
5623
+ footnotes: t("markdown.footnotes")
5624
+ };
5625
+ }
5513
5626
  /** The restored assistant line: caption plus the reply body in official markdown chrome. */
5514
5627
  function RestoredMessageView({ node, t }) {
5515
5628
  const data = node.data;
5629
+ const labels = (0, react.useMemo)(() => markdownLabels(t), [t]);
5516
5630
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5517
5631
  className: RestoredMessageView_module_css_default.restoredAssistantRow,
5518
5632
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
5519
5633
  className: RestoredMessageView_module_css_default.restoredLabel,
5520
5634
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconUndoOutline16, {}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("restored.assistant") })]
5521
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.MarkdownText, { text: data.text })]
5635
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.MarkdownText, {
5636
+ text: data.text,
5637
+ labels
5638
+ })]
5522
5639
  });
5523
5640
  }
5524
5641
  //#endregion
5525
- //#region \0dsh-css:/Users/zhuyudan/code/dsh-plugins/packages/message-tools/src/client/WithdrawnDividerView.module.css.mjs
5642
+ //#region \0dsh-css:src/client/WithdrawnDividerView.module.css.mjs
5526
5643
  const css = ".JtQ9hG_row{padding:2px 0}.JtQ9hG_marker{width:100%;min-width:0;height:24px;color:inherit;font:inherit;text-align:left;cursor:pointer;background:0 0;border:none;border-radius:6px;align-items:center;padding:0;display:flex}.JtQ9hG_marker:hover{background:var(--dsw-alias-interactive-bg-hover,var(--dsw-alias-bg-layer-1))}.JtQ9hG_leading{width:16px;height:16px;color:var(--dsw-alias-label-secondary,var(--dsw-alias-label-primary));flex:none;justify-content:center;align-items:center;margin-right:6px;display:inline-flex}.JtQ9hG_title{color:var(--dsw-alias-label-primary-dimmed,var(--dsw-alias-label-tertiary));flex:none;font-size:14px;line-height:24px}.JtQ9hG_badge{color:var(--dsw-alias-label-tertiary,var(--dsw-alias-label-primary-dimmed));flex:none;align-items:center;gap:4px;margin-left:10px;font-size:12px;line-height:18px;display:inline-flex}.JtQ9hG_body{padding:4px 0 4px 22px}.JtQ9hG_empty{color:var(--dsw-alias-label-tertiary,var(--dsw-alias-label-primary-dimmed));font-size:13px;line-height:20px}.JtQ9hG_entryUser,.JtQ9hG_entryAssistant{color:var(--dsw-alias-label-secondary,var(--dsw-alias-label-primary));padding:4px 0;font-size:14px;line-height:22px}.JtQ9hG_entryKind{color:var(--dsw-alias-label-tertiary,var(--dsw-alias-label-primary-dimmed));margin-bottom:2px;font-size:12px;line-height:18px}.JtQ9hG_entryUser{border-left:2px solid var(--dsw-alias-border-l2,var(--dsw-alias-label-primary-dimmed));padding-left:8px}.JtQ9hG_entryAssistant{border-left:2px solid var(--dsw-alias-border-l1,var(--dsw-alias-border-l2,var(--dsw-alias-label-primary-dimmed)));padding-left:8px}.JtQ9hG_restoreRow{align-items:center;gap:8px;padding-top:8px;display:flex}.JtQ9hG_restoreFailed{color:var(--dsw-alias-state-error-primary,var(--dsw-alias-label-secondary));font-size:12px}";
5527
5644
  const tagId = "@khorsheed/dsh-client-message-tools/WithdrawnDividerView.module.css";
5528
5645
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
@@ -5533,18 +5650,18 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5533
5650
  document.head.appendChild(tag);
5534
5651
  }
5535
5652
  var WithdrawnDividerView_module_css_default = {
5536
- "entryKind": "JtQ9hG_entryKind",
5653
+ "row": "JtQ9hG_row",
5654
+ "marker": "JtQ9hG_marker",
5655
+ "restoreRow": "JtQ9hG_restoreRow",
5656
+ "badge": "JtQ9hG_badge",
5657
+ "restoreFailed": "JtQ9hG_restoreFailed",
5537
5658
  "leading": "JtQ9hG_leading",
5538
5659
  "title": "JtQ9hG_title",
5539
- "entryUser": "JtQ9hG_entryUser",
5540
5660
  "body": "JtQ9hG_body",
5541
5661
  "entryAssistant": "JtQ9hG_entryAssistant",
5542
- "badge": "JtQ9hG_badge",
5543
- "marker": "JtQ9hG_marker",
5544
- "restoreRow": "JtQ9hG_restoreRow",
5545
- "restoreFailed": "JtQ9hG_restoreFailed",
5546
5662
  "empty": "JtQ9hG_empty",
5547
- "row": "JtQ9hG_row"
5663
+ "entryUser": "JtQ9hG_entryUser",
5664
+ "entryKind": "JtQ9hG_entryKind"
5548
5665
  };
5549
5666
  //#endregion
5550
5667
  //#region src/client/WithdrawnDividerView.tsx
@@ -5561,20 +5678,21 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5561
5678
  * once withdrawals backfill the draft automatically.
5562
5679
  */
5563
5680
  /** The withdrawal divider: collapsed marker row plus the expandable replay. */
5564
- function WithdrawnDividerView({ node, t, useSession, restoreMessage }) {
5681
+ function WithdrawnDividerView({ node, t, restoreMessage, ...standard }) {
5565
5682
  const data = node.data;
5566
5683
  const [expanded, setExpanded] = (0, react.useState)(false);
5567
5684
  const [entries, setEntries] = (0, react.useState)(null);
5568
5685
  const [busy, setBusy] = (0, react.useState)(false);
5569
5686
  const [failed, setFailed] = (0, react.useState)(false);
5570
- const nodesStore = useSession((snapshot) => snapshot.chat.nodes);
5571
- const count = useSession((snapshot) => countHiddenInSpan(snapshot.chat.nodes.values(), data.hiddenStartSeq, data.seq));
5572
- const restored = useSession((snapshot) => {
5573
- const nodes = snapshot.chat.nodes.values();
5687
+ const useChatSlice = chatHookOf(standard);
5688
+ const nodesStore = useChatSlice((chat) => chat.nodes);
5689
+ const count = useChatSlice((chat) => countHiddenInSpan(chat.nodes.values(), data.hiddenStartSeq, data.seq));
5690
+ const restored = useChatSlice((chat) => {
5691
+ const nodes = chat.nodes.values();
5574
5692
  return hasRestoreForSpan(nodes, data.hiddenStartSeq, foldHiddenRanges(nodes));
5575
5693
  });
5576
- const superseded = useSession((snapshot) => {
5577
- const nodes = snapshot.chat.nodes.values();
5694
+ const superseded = useChatSlice((chat) => {
5695
+ const nodes = chat.nodes.values();
5578
5696
  return isRestoreSuperseded(nodes, data.hiddenStartSeq, foldHiddenRanges(nodes));
5579
5697
  });
5580
5698
  const toggle = () => {
@@ -5663,23 +5781,42 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5663
5781
  });
5664
5782
  /**
5665
5783
  * Required services: slots, sessions, the remote channel, the scope-addressed
5666
- * conversation service, conversation node registration, and the copy.
5784
+ * conversation service, and the copy.
5667
5785
  * `remote.messageTools` is deliberately NOT an inject: this plugin both
5668
5786
  * mounts the namespace (through `$mount` below) and consumes it, and the
5669
5787
  * Cordis property proxy only resolves services declared in `inject` or
5670
5788
  * provided by an ancestor fiber. Declaring it would deadlock the loader; the
5671
5789
  * namespace is read back from the global store with `ctx.get` after the
5672
- * awaited mount.
5790
+ * awaited mount. The event-Definition registry (`uiConversation.events`) is
5791
+ * likewise NOT a static inject: the deferred ctx.inject arm keeps the
5792
+ * registration independent of ui-conversation's own mount order.
5673
5793
  */
5674
5794
  const inject = [
5675
5795
  "slots",
5676
5796
  "sessions",
5677
5797
  "remote",
5678
5798
  "conversation",
5679
- "conversationEvents",
5680
5799
  "locale"
5681
5800
  ];
5682
5801
  /**
5802
+ * Register the four message-tools event Definitions against ui-conversation's
5803
+ * event registry (host 0.1.2 folded the standalone registry service into
5804
+ * `uiConversation.events`, upstream commit be531688f3). The registry is live
5805
+ * (a registration re-assembles mounted views), so the deferred arm needs no
5806
+ * ordering against ui-conversation's own apply; a composition without the
5807
+ * service never fires it and simply has no chat projection at all.
5808
+ * @param ctx - client root context.
5809
+ */
5810
+ function registerEventDefinitions(ctx) {
5811
+ ctx.inject(["uiConversation"], (lctx) => {
5812
+ const registry = lctx.uiConversation.events;
5813
+ registry.register(withdrawnDividerDefinition);
5814
+ registry.register(restoredMessageDefinition);
5815
+ registry.register(restoredAssistantMessageDefinition);
5816
+ registry.register(editedMessageDefinition);
5817
+ });
5818
+ }
5819
+ /**
5683
5820
  * Client plugin body: mount the Remote, register the dictionaries, the
5684
5821
  * withdrawal divider Definition, and the two `conversation.chat.node` entries
5685
5822
  * (the divider row and the shadowed user renderer).
@@ -5721,10 +5858,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5721
5858
  en
5722
5859
  }), "message-tools: dictionaries");
5723
5860
  const t = ctx.locale.bind(NS);
5724
- ctx.conversationEvents.register(withdrawnDividerDefinition);
5725
- ctx.conversationEvents.register(restoredMessageDefinition);
5726
- ctx.conversationEvents.register(restoredAssistantMessageDefinition);
5727
- ctx.conversationEvents.register(editedMessageDefinition);
5861
+ registerEventDefinitions(ctx);
5728
5862
  ctx.effect(() => installDomHider(ctx), "message-tools: dom hider");
5729
5863
  ctx.slots.inject("conversation.chat.node", () => ctx.slots.register({
5730
5864
  name: "conversation.chat.node",
@@ -5761,7 +5895,18 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5761
5895
  if (!carried.ok) throw new Error(`messageTools.edit transport: ${carried.error.code}`);
5762
5896
  if (!carried.value.ok) throw new Error(`messageTools.edit rejected: ${carried.value.error.code}`);
5763
5897
  };
5764
- const waitIdle = () => waitForTurnSettled(() => ctx.sessions.binding(sessionId)?.session.getSnapshot());
5898
+ const settleSnapshot = () => {
5899
+ const session = ctx.sessions.binding(sessionId)?.session.getSnapshot();
5900
+ if (session === void 0) return void 0;
5901
+ const chat = chatSourceOf(ctx, sessionId)?.getSnapshot();
5902
+ if (chat === void 0) return void 0;
5903
+ return {
5904
+ running: session.running,
5905
+ runningCalls: chat.legacy.runningCalls,
5906
+ chat
5907
+ };
5908
+ };
5909
+ const waitIdle = () => waitForTurnSettled(settleSnapshot);
5765
5910
  return {
5766
5911
  editMessage: (targetSeq, text) => editInPlace({
5767
5912
  cancel: () => conversation.cancel(),