dsh-edge 0.2.0-alpha.2 → 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 (43) hide show
  1. package/README.i18n.yaml +2 -2
  2. package/README.md +6 -6
  3. package/README.zh.md +6 -6
  4. package/THIRD_PARTY_NOTICES.md +387 -1131
  5. package/dist/assets/index-BNMwCG9c.css +1 -0
  6. package/dist/assets/index-CA9Bpko5.js +96 -0
  7. package/dist/assets/langs/{php-D-uCvoST.js → php-DDkx9sim.js} +2 -2
  8. package/dist/assets/langs/{ruby-DEItuUFs.js → ruby-DCxyoPen.js} +2 -2
  9. package/dist/assets/{vendor-Cjbwl5VI.js → vendor-D22_Mp1f.js} +2 -2
  10. package/dist/index.html +26 -5
  11. package/dist/plugins/@deepseek-ai/dsh-api-remotes/client.js +166 -27
  12. package/dist/plugins/@deepseek-ai/dsh-client-connection/client.js +136 -19
  13. package/dist/plugins/@deepseek-ai/dsh-client-locale/client.js +51 -12
  14. package/dist/plugins/@deepseek-ai/dsh-client-modules/client.js +188 -123
  15. package/dist/plugins/@deepseek-ai/dsh-client-runtime/client.js +43 -8
  16. package/dist/plugins/@deepseek-ai/dsh-client-ui-agent-preset/client.js +54 -54
  17. package/dist/plugins/@deepseek-ai/dsh-client-ui-brand-official/client.js +50 -0
  18. package/dist/plugins/@deepseek-ai/dsh-client-ui-commands/client.js +46 -17
  19. package/dist/plugins/@deepseek-ai/dsh-client-ui-conversation/client.js +805 -486
  20. package/dist/plugins/@deepseek-ai/dsh-client-ui-deliverables/client.js +5 -5
  21. package/dist/plugins/@deepseek-ai/dsh-client-ui-input-trigger/client.js +82 -26
  22. package/dist/plugins/@deepseek-ai/dsh-client-ui-jobs/client.js +7 -7
  23. package/dist/plugins/@deepseek-ai/dsh-client-ui-layout/client.js +2 -2
  24. package/dist/plugins/@deepseek-ai/dsh-client-ui-model-selection/client.js +18 -18
  25. package/dist/plugins/@deepseek-ai/dsh-client-ui-permission-presets/client.js +96 -82
  26. package/dist/plugins/@deepseek-ai/dsh-client-ui-renderer/client.js +989 -0
  27. package/dist/plugins/@deepseek-ai/dsh-client-ui-settings/client.js +1177 -67
  28. package/dist/plugins/@deepseek-ai/dsh-client-ui-settings-general/client.js +61 -65
  29. package/dist/plugins/@deepseek-ai/dsh-client-ui-sidebar/client.js +51 -21
  30. package/dist/plugins/@deepseek-ai/dsh-client-ui-skill/client.js +12 -12
  31. package/dist/plugins/@deepseek-ai/dsh-client-ui-subagent/client.js +18 -45
  32. package/dist/plugins/@deepseek-ai/dsh-client-ui-theme/client.js +46 -3
  33. package/dist/plugins/@deepseek-ai/dsh-client-ui-tool/client.js +102 -62
  34. package/dist/plugins/@deepseek-ai/dsh-client-ui-trajectory/client.js +143 -142
  35. package/dist/plugins/@deepseek-ai/dsh-client-ui-user-questions/client.js +25 -25
  36. package/dist/plugins/@deepseek-ai/dsh-client-ui-workflow-run/client.js +261 -86
  37. package/dist/plugins/@deepseek-ai/dsh-client-ui-workspace/client.js +72 -62
  38. package/package.json +22 -22
  39. package/scripts/legal-files.mjs +2 -1
  40. package/worker/direct/index.js +692 -688
  41. package/worker/isolated/index.js +469 -465
  42. package/dist/assets/index-C-1AiF3k.js +0 -112
  43. package/dist/assets/index-CSGf6Qzd.css +0 -1
@@ -10,7 +10,6 @@ window.__ModuleLoader__.load({
10
10
  let react_jsx_runtime = require("react/jsx-runtime");
11
11
  let react = require("react");
12
12
  let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
13
- let _deepseek_ai_dsh_client_ui_attachment = require("@deepseek-ai/dsh-client-ui-attachment");
14
13
  //#region lib/types/client/stores.js
15
14
  /**
16
15
  * Per-session chat store shared by conversation and details registrations.
@@ -126,17 +125,19 @@ window.__ModuleLoader__.load({
126
125
  * @param text - serialized prompt text.
127
126
  * @param imageIds - ordered draft-local attachment ids.
128
127
  * @param mode - queue or steer delivery selected by composer policy.
128
+ * @param signal - optional cancellation for the complete Host admission.
129
+ * @returns the Host admission outcome; local attachment preparation failures reject.
129
130
  */
130
- async sendSession(session, text, imageIds, mode) {
131
+ async sendSession(session, text, imageIds, mode, signal) {
131
132
  const attachments = this.draftImages(imageIds);
132
133
  if (attachments.length !== imageIds.length) throw new Error("conversation.sendSession: one or more draft images are no longer available");
133
134
  const content = [...await this.serializeImages(attachments.map((attachment) => attachment.file)), ...text === "" ? [] : [{
134
135
  type: "text",
135
136
  text
136
137
  }]];
137
- const result = await session.prompt(content, mode);
138
- if (!result.ok) throw new Error(`conversation.send failed: ${result.error.code}: ${result.error.message}`);
138
+ if (!(await session.prompt(content, mode, signal)).ok) return { kind: "error" };
139
139
  this.releaseDraftImages(attachments);
140
+ return { kind: "success" };
140
141
  }
141
142
  /**
142
143
  * Create runtime-only draft images and their object URLs.
@@ -166,6 +167,18 @@ window.__ModuleLoader__.load({
166
167
  return attachments;
167
168
  }
168
169
  /**
170
+ * Serialize ordered draft images to command-submit wire payloads without
171
+ * sending or releasing them (the composer releases only after the command
172
+ * settles successfully).
173
+ * @param imageIds - ordered draft-local attachment ids.
174
+ * @returns base64 payloads in id order.
175
+ */
176
+ async serializeDraftImages(imageIds) {
177
+ const attachments = this.draftImages(imageIds);
178
+ if (attachments.length !== imageIds.length) throw new Error("conversation.serializeDraftImages: one or more draft images are no longer available");
179
+ return Promise.all(attachments.map((attachment) => this.encodeImage(attachment.file)));
180
+ }
181
+ /**
169
182
  * Release one browser-owned draft image and preview URL.
170
183
  * @param id - draft attachment id.
171
184
  */
@@ -271,10 +284,16 @@ window.__ModuleLoader__.load({
271
284
  serializeImages(images) {
272
285
  return Promise.all(images.map(async (file) => ({
273
286
  type: "image",
287
+ ...await this.encodeImage(file)
288
+ })));
289
+ }
290
+ /** Canonical base64 wire form of one browser image file. */
291
+ async encodeImage(file) {
292
+ return {
274
293
  mediaType: imageMediaType(file.type),
275
294
  data: bytesToBase64(new Uint8Array(await file.arrayBuffer())),
276
295
  ...file.name === "" ? {} : { name: file.name }
277
- })));
296
+ };
278
297
  }
279
298
  };
280
299
  function imageMediaType(value) {
@@ -348,6 +367,18 @@ window.__ModuleLoader__.load({
348
367
  subscribe: (fn) => session.subscribe(fn)
349
368
  };
350
369
  }
370
+ //#endregion
371
+ //#region lib/types/client/input/machine.js
372
+ const REFERENCE_PLACEHOLDER_RE = /[\uE100-\uE11D\uFFFC]/gu;
373
+ /**
374
+ * Build the inline draft text whose leading marker is decorated as the
375
+ * reference icon in the backdrop.
376
+ * @param reference - reference insertion with its cached display projection.
377
+ * @returns display text with one marker glyph followed by the complete label.
378
+ */
379
+ function referenceDraftText(reference) {
380
+ return `@${reference.label}`;
381
+ }
351
382
  /** The machine never writes the queue; the wiring layer overlays the queue store's projection. */
352
383
  const EMPTY_QUEUE$1 = [];
353
384
  /** Undo ring depth (bounded self-managed transaction log). */
@@ -391,6 +422,24 @@ window.__ModuleLoader__.load({
391
422
  };
392
423
  }
393
424
  /**
425
+ * Expand the draft's reference ranges into their occurrences' clipboard text
426
+ * for persistence and clipboard projection. Table order is offset order, so
427
+ * one linear walk pairs ranges with entries.
428
+ * @param state - published input state.
429
+ * @returns the plain-text projection of the draft.
430
+ */
431
+ function projectClipboard(state) {
432
+ const { draft, occurrences } = state;
433
+ if (occurrences.length === 0) return draft;
434
+ let out = "";
435
+ let cursor = 0;
436
+ for (const o of occurrences) {
437
+ out += draft.slice(cursor, o.offset) + o.clipboardText;
438
+ cursor = o.offset + o.length;
439
+ }
440
+ return out + draft.slice(cursor);
441
+ }
442
+ /**
394
443
  * Pure input machine, one instance per session (per-session isolation is by
395
444
  * construction). The machine constructs one AbortController per SubmitAttempt
396
445
  * at enter time and aborts it itself on release; the shell never aborts, it
@@ -429,7 +478,8 @@ window.__ModuleLoader__.load({
429
478
  phase: this.phase,
430
479
  ...c ? { claim: {
431
480
  token: c.token,
432
- ...c.hint !== void 0 ? { hint: c.hint } : {}
481
+ ...c.hint !== void 0 ? { hint: c.hint } : {},
482
+ ...c.images === true ? { images: true } : {}
433
483
  } } : {},
434
484
  occurrences: this.occurrences,
435
485
  ...this.paste !== void 0 ? { paste: this.paste } : {},
@@ -481,14 +531,14 @@ window.__ModuleLoader__.load({
481
531
  }
482
532
  /**
483
533
  * Reconcile the occurrence table with one edit (old-draft coordinates):
484
- * entries past the range shift by the length delta; entries whose
485
- * placeholder sits inside the replaced range go away whole (a
486
- * deletion/replacement intersecting a placeholder acts on the whole chip).
534
+ * entries past the range shift by the length delta; an edit that intersects
535
+ * a reference range removes its structured occurrence and leaves the edited
536
+ * characters as ordinary draft text.
487
537
  */
488
538
  reconcile(range) {
489
539
  const delta = range.insertedLength - (range.end - range.start);
490
540
  const kept = [];
491
- for (const o of this.occurrences) if (o.offset < range.start) kept.push(o);
541
+ for (const o of this.occurrences) if (o.offset + o.length <= range.start) kept.push(o);
492
542
  else if (o.offset >= range.end) kept.push(delta === 0 ? o : {
493
543
  ...o,
494
544
  offset: o.offset + delta
@@ -503,14 +553,16 @@ window.__ModuleLoader__.load({
503
553
  }
504
554
  }
505
555
  /** Mint one occurrence at a draft offset. */
506
- mint(reference, offset) {
556
+ mint(reference, offset, length) {
507
557
  this.occurrenceSeq += 1;
508
558
  return {
509
559
  occurrenceId: this.occurrenceSeq,
510
560
  source: reference.source,
511
561
  ref: reference.ref,
512
562
  offset,
563
+ length,
513
564
  label: reference.label,
565
+ ...reference.appearance === void 0 ? {} : { appearance: reference.appearance },
514
566
  clipboardText: reference.clipboardText
515
567
  };
516
568
  }
@@ -567,22 +619,24 @@ window.__ModuleLoader__.load({
567
619
  return [];
568
620
  }
569
621
  /**
570
- * Shared chip-insertion transaction: replace [span) with one placeholder
622
+ * Shared reference-insertion transaction: replace [span) with one inline
571
623
  * occurrence (insert-ref and paste-upgrade both land here). A separating
572
- * space follows the chip unless one is already next.
573
- * @returns the inserted length (placeholder plus optional gap).
624
+ * space follows the reference unless one is already next.
625
+ * @returns the inserted length (display text plus optional gap).
574
626
  */
575
627
  replaceSpanWithChip(reference, span) {
576
628
  this.pushTxn();
577
629
  this.typingRun = void 0;
578
630
  const tail = this.draft.slice(span.end);
579
- const inserted = "" + (tail.length === 0 || tail[0] !== " " ? " " : "");
631
+ const gap = tail.length === 0 || tail[0] !== " " ? " " : "";
632
+ const displayText = referenceDraftText(reference);
633
+ const inserted = displayText + gap;
580
634
  this.reconcile({
581
635
  start: span.start,
582
636
  end: span.end,
583
637
  insertedLength: inserted.length
584
638
  });
585
- this.withMinted([this.mint(reference, span.start)]);
639
+ this.withMinted([this.mint(reference, span.start, displayText.length)]);
586
640
  this.adopt(this.draft.slice(0, span.start) + inserted + tail);
587
641
  this.watchClaim();
588
642
  return inserted.length;
@@ -671,7 +725,7 @@ window.__ModuleLoader__.load({
671
725
  return [];
672
726
  }
673
727
  /**
674
- * Paste as one transaction: the text (U+FFFC-sanitized) replaces the
728
+ * Paste as one transaction: the text (reference-placeholder-sanitized) replaces the
675
729
  * selection; hot-snapshot sync matches componentize inside the SAME
676
730
  * transaction (one undo returns to pre-paste); a match attempt opens for
677
731
  * the async remainder while the phase still accepts reference mutations.
@@ -679,7 +733,7 @@ window.__ModuleLoader__.load({
679
733
  onPasteBegin(rawText, selection, components = [], generation = 0) {
680
734
  const { start, end } = selection;
681
735
  if (start < 0 || start > end || end > this.draft.length) return [];
682
- const text = rawText.split("").join("");
736
+ const text = rawText.replace(REFERENCE_PLACEHOLDER_RE, "");
683
737
  this.pushTxn(selection);
684
738
  this.typingRun = void 0;
685
739
  const sorted = [...components].sort((a, b) => a.start - b.start);
@@ -688,8 +742,9 @@ window.__ModuleLoader__.load({
688
742
  let cursor = 0;
689
743
  for (const c of sorted) {
690
744
  inserted += text.slice(cursor, c.start);
691
- minted.push(this.mint(c.reference, start + inserted.length));
692
- inserted += "";
745
+ const displayText = referenceDraftText(c.reference);
746
+ minted.push(this.mint(c.reference, start + inserted.length, displayText.length));
747
+ inserted += displayText;
693
748
  cursor = c.end;
694
749
  }
695
750
  inserted += text.slice(cursor);
@@ -775,8 +830,11 @@ window.__ModuleLoader__.load({
775
830
  draft: this.draft
776
831
  }];
777
832
  }
833
+ const attempt = this.beginAttempt(mode);
834
+ this.phase = "submitting";
778
835
  return [{
779
836
  type: "default-sink",
837
+ attempt,
780
838
  draft: this.draft,
781
839
  mode
782
840
  }];
@@ -794,13 +852,18 @@ window.__ModuleLoader__.load({
794
852
  args: argsAfter(attempt.draftSnapshot, outcome.claim.token)
795
853
  }];
796
854
  }
855
+ if (outcome === void 0) {
856
+ this.phase = "submitting";
857
+ return [{
858
+ type: "default-sink",
859
+ attempt,
860
+ draft: attempt.draftSnapshot,
861
+ mode: attempt.mode
862
+ }];
863
+ }
797
864
  this.inflight = void 0;
798
865
  this.phase = "plain";
799
- return outcome === void 0 ? [{
800
- type: "default-sink",
801
- draft: attempt.draftSnapshot,
802
- mode: attempt.mode
803
- }] : [];
866
+ return [];
804
867
  }
805
868
  onAdjudicationFailed(attempt, message) {
806
869
  if (this.phase !== "adjudicating" || this.inflight?.attempt.seq !== attempt.seq) return [];
@@ -820,7 +883,8 @@ window.__ModuleLoader__.load({
820
883
  this.phase = "plain";
821
884
  this.claim = void 0;
822
885
  this.occurrences = [];
823
- this.adopt("");
886
+ const snapshot = flight.attempt.draftSnapshot;
887
+ this.adopt(this.draft !== snapshot && this.draft.startsWith(snapshot) ? this.draft.slice(snapshot.length) : "");
824
888
  this.log = [];
825
889
  this.redoStack = [];
826
890
  this.typingRun = void 0;
@@ -831,10 +895,10 @@ window.__ModuleLoader__.load({
831
895
  text: ev.outcome.text
832
896
  }] : [];
833
897
  }
834
- const text = ev.message ?? ev.outcome?.text ?? "command failed";
898
+ const text = ev.message ?? ev.outcome?.text;
835
899
  if (this.draft === flight.attempt.draftSnapshot && this.claim !== void 0 && this.draft.startsWith(this.claim.token)) {
836
900
  this.phase = "claimed";
837
- return [{
901
+ return text === void 0 ? [] : [{
838
902
  type: "notice",
839
903
  level: "error",
840
904
  text
@@ -842,15 +906,15 @@ window.__ModuleLoader__.load({
842
906
  }
843
907
  this.phase = "plain";
844
908
  this.claim = void 0;
845
- return [{
909
+ return text === void 0 ? [] : [{
846
910
  type: "notice",
847
911
  level: "error",
848
912
  text
849
913
  }];
850
914
  }
851
- /** Ordinary send accepted: clear as a commit (no undo unit; sent content
852
- * must not be resurrectable — same discipline as submit-settled success). */
915
+ /** Cut undo state after an accepted image-only send. */
853
916
  onSendCommitted() {
917
+ if (this.phase !== "plain") return [];
854
918
  this.claim = void 0;
855
919
  this.occurrences = [];
856
920
  this.adopt("");
@@ -893,7 +957,7 @@ window.__ModuleLoader__.load({
893
957
  deps;
894
958
  /** Published machine state + queue overlay (the InputZone currency source). */
895
959
  state;
896
- /** Latest surfaced notice (null after clear); the wiring renders it beside the error strip. */
960
+ /** Latest surfaced notice (null after clear); the bar renders errors as banners and information inline. */
897
961
  notices = (0, _deepseek_ai_dsh_client_runtime_client.createSnapshotStore)(null);
898
962
  /** The public provide-channel action face (one stable identity per session). */
899
963
  actions = {
@@ -913,10 +977,12 @@ window.__ModuleLoader__.load({
913
977
  };
914
978
  core = new InputMachine({ now: () => Date.now() });
915
979
  noticeSeq = 0;
916
- lastDraft = "";
980
+ lastMirroredDraft = "";
917
981
  imageIds = [];
982
+ /** One image-only send at a time: Enter during the Host round-trip is a no-op. */
983
+ imageSendInFlight = false;
918
984
  disposed = false;
919
- /** Draft persistence mirror (chat store write; receives the clipboard projection, never raw placeholders). */
985
+ /** Draft persistence mirror (chat store write; receives the clipboard projection, never display-only ranges). */
920
986
  mirrorFn;
921
987
  constructor(deps) {
922
988
  this.deps = deps;
@@ -946,8 +1012,13 @@ window.__ModuleLoader__.load({
946
1012
  this.publish();
947
1013
  return true;
948
1014
  }
949
- /** Remove one image id from this draft. */
1015
+ /**
1016
+ * Remove one image id from this draft. Busy admission phases refuse, like
1017
+ * {@link addImages}: a removal landing while a command submit serializes
1018
+ * would otherwise vanish from the rail yet still ride the in-flight send.
1019
+ */
950
1020
  removeImage(id) {
1021
+ if (this.snapshot.phase === "adjudicating" || this.snapshot.phase === "submitting") return;
951
1022
  const next = this.imageIds.filter((candidate) => candidate !== id);
952
1023
  if (next.length === this.imageIds.length) return;
953
1024
  this.imageIds = next;
@@ -965,15 +1036,6 @@ window.__ModuleLoader__.load({
965
1036
  this.publish();
966
1037
  }
967
1038
  /**
968
- * Restore a failed attempt before any images added after its admission.
969
- * @param ids - failed attempt image ids.
970
- */
971
- restoreImages(ids) {
972
- const current = new Set(this.imageIds);
973
- this.imageIds = [...ids.filter((id) => !current.has(id)), ...this.imageIds];
974
- this.publish();
975
- }
976
- /**
977
1039
  * Clear the draft as a successful-send commit: no undo unit is recorded and
978
1040
  * the undo history is cut, so Ctrl/Cmd-Z cannot resurrect sent content
979
1041
  * (the command path gets the same discipline from submit-settled success).
@@ -1021,7 +1083,24 @@ window.__ModuleLoader__.load({
1021
1083
  */
1022
1084
  submit(mode = "queue") {
1023
1085
  if (this.snapshot.draft.trim() === "" && this.imageIds.length > 0) {
1024
- if (this.snapshot.phase === "plain") this.deps.defaultSink("", [...this.imageIds], mode);
1086
+ if (this.snapshot.phase === "plain" && !this.imageSendInFlight) {
1087
+ const imageIds = [...this.imageIds];
1088
+ this.imageSendInFlight = true;
1089
+ this.deps.defaultSink("", imageIds, mode, new AbortController().signal).then((outcome) => {
1090
+ this.imageSendInFlight = false;
1091
+ if (this.disposed) return;
1092
+ if (outcome.kind === "success") this.commitSend(imageIds);
1093
+ else if (outcome.text !== void 0) this.notify("error", outcome.text);
1094
+ }, (error) => {
1095
+ this.imageSendInFlight = false;
1096
+ if (!this.disposed) this.notify("error", error instanceof Error ? error.message : String(error));
1097
+ });
1098
+ }
1099
+ return;
1100
+ }
1101
+ const before = this.snapshot;
1102
+ if (before.phase === "claimed" && this.imageIds.length > 0 && before.claim?.images !== true) {
1103
+ this.notify("error", this.deps.commandImages.unsupportedNotice(before.claim?.token ?? before.draft));
1025
1104
  return;
1026
1105
  }
1027
1106
  this.run(this.core.dispatch({
@@ -1149,13 +1228,19 @@ window.__ModuleLoader__.load({
1149
1228
  * a scan-derived decoration, never state.
1150
1229
  * @param text - the plain reference text to splice in (e.g. `/name `).
1151
1230
  * @param span - pick-time span snapshot (draftRev CAS).
1231
+ * @param keepCompleting - re-track at the caret after the splice so an open
1232
+ * token (a directory pick's trailing slash) reopens the menu.
1152
1233
  * @returns whether the text was applied.
1153
1234
  */
1154
- insertText(text, span) {
1235
+ insertText(text, span, keepCompleting = false) {
1155
1236
  const snapshot = this.core.state;
1156
1237
  if (span.draftRev !== snapshot.draftRev) return false;
1157
1238
  const draft = snapshot.draft;
1158
1239
  this.setDraft(draft.slice(0, span.start) + text + draft.slice(span.end));
1240
+ if (keepCompleting) {
1241
+ const next = this.snapshot;
1242
+ this.deps.inputTriggers?.()?.track(next.draft, span.start + text.length, { tier: guardOf(next.phase) }, next.draftRev);
1243
+ }
1159
1244
  return true;
1160
1245
  }
1161
1246
  /**
@@ -1215,23 +1300,23 @@ window.__ModuleLoader__.load({
1215
1300
  this.beginSubmit(fx.attempt, fx.claim, fx.args);
1216
1301
  return;
1217
1302
  case "default-sink":
1218
- this.sinkSerialized(fx.draft, fx.mode);
1303
+ this.sinkSerialized(fx.attempt, fx.draft, fx.mode);
1219
1304
  return;
1220
1305
  default: return;
1221
1306
  }
1222
1307
  }
1223
1308
  /**
1224
1309
  * Prompt serialization before the sink: expand each
1225
- * placeholder to its owner's model form via the session controller's
1310
+ * inline reference range to its owner's model form via the session controller's
1226
1311
  * codec routing. Owner missing / serialize failure / disposal blocks the
1227
1312
  * send — notice + draft and chips retained, never a silent downgrade to
1228
1313
  * the clipboard text. Chip-free drafts skip the async detour.
1229
1314
  */
1230
- sinkSerialized(draft, mode) {
1315
+ sinkSerialized(attempt, draft, mode) {
1231
1316
  const imageIds = [...this.imageIds];
1232
1317
  const occurrences = this.core.state.occurrences;
1233
1318
  if (occurrences.length === 0) {
1234
- this.deps.defaultSink(draft.trim(), imageIds, mode);
1319
+ this.settleSubmit(attempt, this.deps.defaultSink(draft.trim(), imageIds, mode, attempt.signal), imageIds);
1235
1320
  return;
1236
1321
  }
1237
1322
  const inputTriggers = this.deps.inputTriggers?.();
@@ -1240,6 +1325,7 @@ window.__ModuleLoader__.load({
1240
1325
  if (inputTriggers === void 0) throw new Error(`no serializer for reference source "${o.source}"`);
1241
1326
  return {
1242
1327
  offset: o.offset,
1328
+ length: o.length,
1243
1329
  text: await inputTriggers.serializeReference(o.source, o.ref, controller.signal)
1244
1330
  };
1245
1331
  })).then((parts) => {
@@ -1248,15 +1334,44 @@ window.__ModuleLoader__.load({
1248
1334
  let cursor = 0;
1249
1335
  for (const part of parts) {
1250
1336
  out += draft.slice(cursor, part.offset) + part.text;
1251
- cursor = part.offset + 1;
1337
+ cursor = part.offset + part.length;
1252
1338
  }
1253
1339
  out += draft.slice(cursor);
1254
- this.deps.defaultSink(out.trim(), imageIds, mode);
1340
+ this.settleSubmit(attempt, this.deps.defaultSink(out.trim(), imageIds, mode, attempt.signal), imageIds);
1255
1341
  }, (error) => {
1256
1342
  controller.abort();
1257
- if (this.disposed) return;
1343
+ if (this.dead(attempt)) return;
1258
1344
  const message = error instanceof Error ? error.message : String(error);
1259
- this.notify("error", message);
1345
+ this.run(this.core.dispatch({
1346
+ type: "submit-settled",
1347
+ attempt,
1348
+ ok: false,
1349
+ message
1350
+ }));
1351
+ });
1352
+ }
1353
+ /** Settle one admission attempt; successful sends consume only their captured images. */
1354
+ settleSubmit(attempt, pending, imageIds = []) {
1355
+ pending.then((outcome) => {
1356
+ if (this.dead(attempt)) return;
1357
+ if (outcome.kind === "success" && imageIds.length > 0) {
1358
+ const submitted = new Set(imageIds);
1359
+ this.imageIds = this.imageIds.filter((id) => !submitted.has(id));
1360
+ }
1361
+ this.run(this.core.dispatch({
1362
+ type: "submit-settled",
1363
+ attempt,
1364
+ ok: outcome.kind === "success",
1365
+ outcome
1366
+ }));
1367
+ }, (error) => {
1368
+ if (this.dead(attempt)) return;
1369
+ this.run(this.core.dispatch({
1370
+ type: "submit-settled",
1371
+ attempt,
1372
+ ok: false,
1373
+ message: error instanceof Error ? error.message : String(error)
1374
+ }));
1260
1375
  });
1261
1376
  }
1262
1377
  /** Enter adjudication: poll the session controller; failure = notice + draft retained (never a silent downgrade). */
@@ -1270,7 +1385,7 @@ window.__ModuleLoader__.load({
1270
1385
  }));
1271
1386
  return;
1272
1387
  }
1273
- inputTriggers.adjudicate(draft.trim(), attempt.signal).then((outcome) => {
1388
+ inputTriggers.adjudicate(draft.trim(), attempt.signal, { images: this.imageIds.length }).then((outcome) => {
1274
1389
  if (this.dead(attempt)) return;
1275
1390
  this.run(this.core.dispatch({
1276
1391
  type: "adjudicated",
@@ -1287,15 +1402,32 @@ window.__ModuleLoader__.load({
1287
1402
  }));
1288
1403
  });
1289
1404
  }
1290
- /** The submit transaction: claim.submit against the session scope; ok maps from the outcome kind. */
1405
+ /**
1406
+ * The submit transaction: claim.submit against the session scope; ok maps
1407
+ * from the outcome kind. An accepting claim receives the serialized draft
1408
+ * images, which are cleared and released only on a success outcome; a
1409
+ * failure (serialize, transport, or handler error) keeps draft and images
1410
+ * for correction.
1411
+ */
1291
1412
  beginSubmit(attempt, claim, args) {
1292
- Promise.resolve().then(() => claim.submit(args, this.deps.actx)).then((outcome) => {
1293
- if (this.dead(attempt)) return;
1413
+ const imageIds = claim.images === true ? [...this.imageIds] : [];
1414
+ Promise.resolve().then(async () => {
1415
+ const images = imageIds.length > 0 ? await this.deps.commandImages.serialize(imageIds) : [];
1416
+ if (this.dead(attempt)) return void 0;
1417
+ return claim.submit(args, this.deps.actx, images);
1418
+ }).then((outcome) => {
1419
+ if (outcome === void 0 || this.dead(attempt)) return;
1420
+ if (outcome.kind === "success" && imageIds.length > 0) {
1421
+ const submitted = new Set(imageIds);
1422
+ this.imageIds = this.imageIds.filter((id) => !submitted.has(id));
1423
+ this.deps.commandImages.release(imageIds);
1424
+ }
1294
1425
  this.run(this.core.dispatch({
1295
1426
  type: "submit-settled",
1296
1427
  attempt,
1297
1428
  ok: outcome.kind === "success",
1298
- outcome
1429
+ outcome,
1430
+ ...outcome.kind === "error" && outcome.text === void 0 ? { message: "command failed" } : {}
1299
1431
  }));
1300
1432
  }, (error) => {
1301
1433
  if (this.dead(attempt)) return;
@@ -1322,9 +1454,10 @@ window.__ModuleLoader__.load({
1322
1454
  publish() {
1323
1455
  const next = this.compose();
1324
1456
  this.state.set(next);
1325
- if (next.draft !== this.lastDraft) {
1326
- this.lastDraft = next.draft;
1327
- this.mirrorFn?.(next.draft);
1457
+ const mirroredDraft = projectClipboard(next);
1458
+ if (mirroredDraft !== this.lastMirroredDraft) {
1459
+ this.lastMirroredDraft = mirroredDraft;
1460
+ this.mirrorFn?.(mirroredDraft);
1328
1461
  }
1329
1462
  }
1330
1463
  };
@@ -1370,11 +1503,17 @@ window.__ModuleLoader__.load({
1370
1503
  inputTriggers: () => this.controller(actx),
1371
1504
  popup: () => this.popup(actx),
1372
1505
  queue: queueReadFaceOf(session),
1373
- defaultSink: (text, imageIds, mode) => {
1374
- this.sink(session, text, imageIds, mode);
1375
- },
1506
+ defaultSink: (text, imageIds, mode, signal) => this.sink(session, text, imageIds, mode, signal),
1376
1507
  steerQueue: () => {
1377
1508
  this.steerQueue(session, shell);
1509
+ },
1510
+ commandImages: {
1511
+ serialize: (ids) => this.conversation().serializeDraftImages(ids),
1512
+ release: (ids) => {
1513
+ const conversation = this.rootCtx.get("conversation");
1514
+ for (const imageId of ids) conversation?.releaseDraftImage(imageId);
1515
+ },
1516
+ unsupportedNotice: (token) => this.t("command.imagesUnsupported", { command: token.trim().replace(/^\//u, "") })
1378
1517
  }
1379
1518
  });
1380
1519
  this.shells.set(id, shell);
@@ -1383,7 +1522,7 @@ window.__ModuleLoader__.load({
1383
1522
  actx.on("slash/input-begin-command", (req) => shell.beginCommand(req.claim, req.span) ? true : void 0),
1384
1523
  actx.on("slash/input-insert-reference", (req) => shell.insertReference(req.reference, req.span) ? true : void 0),
1385
1524
  actx.on("slash/input-consume-token", (req) => shell.consumeToken(req.guard) ? true : void 0),
1386
- actx.on("slash/input-insert-text", (req) => shell.insertText(req.text, req.span) ? true : void 0)
1525
+ actx.on("slash/input-insert-text", (req) => shell.insertText(req.text, req.span, req.continue === true) ? true : void 0)
1387
1526
  ];
1388
1527
  return () => {
1389
1528
  for (const off of offs) off();
@@ -1433,21 +1572,11 @@ window.__ModuleLoader__.load({
1433
1572
  * Default sink: optimistic clear + prompt. The session is always a real
1434
1573
  * host entity (materialized when its workspace was picked), so there is
1435
1574
  * exactly one path; a failed first prompt is an ordinary prompt failure
1436
- * (error strip via promptError, draft restored only while untouched).
1575
+ * (banner via promptError, draft restored only while untouched).
1437
1576
  */
1438
- sink(session, text, imageIds, mode) {
1439
- if (text === "" && imageIds.length === 0) return;
1440
- const shell = this.shells.get(session.sessionId);
1441
- shell?.commitSend(imageIds);
1442
- this.conversation().sendSession(session, text, imageIds, mode).catch(() => {
1443
- if (this.shells.get(session.sessionId) === shell) {
1444
- shell?.restoreImages(imageIds);
1445
- if (shell?.snapshot.draft === "") shell.setDraft(text);
1446
- return;
1447
- }
1448
- const conversation = this.rootCtx.get("conversation");
1449
- for (const id of imageIds) conversation?.releaseDraftImage(id);
1450
- });
1577
+ sink(session, text, imageIds, mode, signal) {
1578
+ if (text === "" && imageIds.length === 0) return Promise.resolve({ kind: "success" });
1579
+ return this.conversation().sendSession(session, text, imageIds, mode, signal);
1451
1580
  }
1452
1581
  /**
1453
1582
  * Steer every still-pending queued message into the running turn, in FIFO
@@ -2376,6 +2505,7 @@ window.__ModuleLoader__.load({
2376
2505
  //#region lib/types/client/input/decorations.js
2377
2506
  /** Token matcher: a trigger char at line start or after whitespace, then a word-ish name (never crosses \n). */
2378
2507
  const TEXT_REF_RE = /(^|\s)([/@])([\w-]+)/g;
2508
+ const FOLDER_REF_RE = /(^|\s)(@(?:"[^"\n]*\/|[^\s"]+\/))/g;
2379
2509
  /**
2380
2510
  * Scan the draft for plain-text reference tokens against the hot lexicons.
2381
2511
  * Word-boundary discipline: the trigger must sit at the draft
@@ -2386,23 +2516,38 @@ window.__ModuleLoader__.load({
2386
2516
  * @returns matched ranges in draft order.
2387
2517
  */
2388
2518
  function scanTextRefs(draft, lexicon) {
2389
- if (lexicon.size === 0 || draft === "") return [];
2519
+ if (draft === "") return [];
2390
2520
  const out = [];
2391
- TEXT_REF_RE.lastIndex = 0;
2392
- let m;
2393
- while ((m = TEXT_REF_RE.exec(draft)) !== null) {
2394
- const trigger = m[2];
2395
- const name = m[3] ?? "";
2396
- if (lexicon.get(trigger)?.includes(name)) {
2397
- const start = m.index + (m[1]?.length ?? 0);
2398
- out.push({
2399
- start,
2400
- end: start + 1 + name.length,
2401
- trigger
2402
- });
2521
+ if (lexicon.size > 0) {
2522
+ TEXT_REF_RE.lastIndex = 0;
2523
+ let m;
2524
+ while ((m = TEXT_REF_RE.exec(draft)) !== null) {
2525
+ const trigger = m[2];
2526
+ const name = m[3] ?? "";
2527
+ if (lexicon.get(trigger)?.includes(name)) {
2528
+ const start = m.index + (m[1]?.length ?? 0);
2529
+ out.push({
2530
+ start,
2531
+ end: start + 1 + name.length,
2532
+ trigger
2533
+ });
2534
+ }
2403
2535
  }
2404
2536
  }
2405
- return out;
2537
+ FOLDER_REF_RE.lastIndex = 0;
2538
+ let folder;
2539
+ while ((folder = FOLDER_REF_RE.exec(draft)) !== null) {
2540
+ const token = folder[2] ?? "";
2541
+ const start = folder.index + (folder[1]?.length ?? 0);
2542
+ const end = start + token.length;
2543
+ if (!out.some((range) => range.start < end && range.end > start)) out.push({
2544
+ start,
2545
+ end,
2546
+ trigger: "@",
2547
+ appearance: "folder"
2548
+ });
2549
+ }
2550
+ return out.sort((left, right) => left.start - right.start);
2406
2551
  }
2407
2552
  /** The empty lexicon (default: zero text-ref decorations, old call sites unchanged). */
2408
2553
  const EMPTY_LEXICON$1 = /* @__PURE__ */ new Map();
@@ -2422,7 +2567,10 @@ window.__ModuleLoader__.load({
2422
2567
  const chips = occurrences.map((o) => ({
2423
2568
  occurrenceId: o.occurrenceId,
2424
2569
  offset: o.offset,
2570
+ length: o.length,
2571
+ text: draft.slice(o.offset, o.offset + o.length),
2425
2572
  label: o.label,
2573
+ ...o.appearance === void 0 ? {} : { appearance: o.appearance },
2426
2574
  invalid: o.invalid === true
2427
2575
  }));
2428
2576
  const hint = claimActive && claim.hint !== void 0 && draft.slice(claim.token.length).trim() === "" ? claim.hint : null;
@@ -2435,9 +2583,7 @@ window.__ModuleLoader__.load({
2435
2583
  }
2436
2584
  //#endregion
2437
2585
  //#region lib/types/client/image-labels.js
2438
- /** Bridges the `conversation` locale namespace to the zero-cordis attachment
2439
- * atoms' label props (`@deepseek-ai/dsh-client-ui-attachment` reads no
2440
- * application state; owners resolve every string). */
2586
+ /** Attachment error and limit copy owned by the conversation input flow. */
2441
2587
  /**
2442
2588
  * Byte count as user-facing megabytes (`10MB`, `2.5MB`).
2443
2589
  * @param bytes - the byte count.
@@ -2462,6 +2608,9 @@ window.__ModuleLoader__.load({
2462
2608
  case "MODEL_DOES_NOT_SUPPORT_IMAGES": return t("image.modelUnsupported");
2463
2609
  case "SUBAGENT_IMAGE_UNSUPPORTED": return t("image.subagentUnsupported");
2464
2610
  case "IMAGE_TOO_MANY_PIXELS": return t("image.tooManyPixels");
2611
+ case "IMAGE_DIMENSION_TOO_LARGE":
2612
+ if (limits !== void 0) return t("image.dimensionTooLarge", { size: limits.maxImageDimension });
2613
+ break;
2465
2614
  case "INVALID_IMAGE":
2466
2615
  case "IMAGE_TYPE_MISMATCH": return t("image.unsupportedType");
2467
2616
  case "TOO_MANY_IMAGES":
@@ -2477,61 +2626,36 @@ window.__ModuleLoader__.load({
2477
2626
  }
2478
2627
  return t("image.sendFailed", { reason });
2479
2628
  }
2629
+ //#endregion
2630
+ //#region lib/types/client/reference/ReferenceIcon.js
2480
2631
  /**
2481
- * Resolve the original-image lightbox strings.
2482
- * @param t - the conversation-namespace translate.
2483
- * @returns the lightbox dialog and close-control labels.
2484
- */
2485
- function lightboxLabels(t) {
2486
- return {
2487
- dialog: t("image.preview"),
2488
- close: t("image.closePreview")
2489
- };
2490
- }
2491
- /**
2492
- * Resolve the chat-history image strings.
2493
- * @param t - the conversation-namespace translate.
2494
- * @returns the message-image labels including the forwarded lightbox strings.
2495
- */
2496
- function messageImageLabels(t) {
2497
- return {
2498
- image: t("image.label"),
2499
- open: t("image.openOriginal"),
2500
- openNamed: (label) => t("image.openOriginalLabel", { label }),
2501
- loading: t("image.loading"),
2502
- loadFailed: t("image.loadFailed"),
2503
- lightbox: lightboxLabels(t)
2504
- };
2505
- }
2506
- /**
2507
- * Resolve the full-page drop overlay strings.
2508
- * @param t - the conversation-namespace translate.
2509
- * @param accepting - whether drops are currently accepted.
2510
- * @param limits - per-message limits for the desc line, when known.
2511
- * @returns the overlay title, with the limits desc while accepting.
2512
- */
2513
- function dropOverlayLabels(t, accepting, limits) {
2514
- if (!accepting) return { title: t("image.dropBlocked") };
2515
- return {
2516
- title: t("image.dropTitle"),
2517
- desc: limits === void 0 ? void 0 : t("image.dropDesc", {
2518
- count: limits.count,
2519
- size: limits.size
2520
- })
2521
- };
2522
- }
2523
- /**
2524
- * Resolve the composer draft-image rail strings.
2525
- * @param t - the conversation-namespace translate.
2526
- * @returns the rail group, open-tooltip, and paging-arrow labels.
2632
+ * Render the icon that identifies one inline reference domain.
2633
+ * @param props - Reference kind, optional size, and optional CSS class.
2634
+ * @returns The corresponding current-color SVG glyph.
2527
2635
  */
2528
- function attachmentRailLabels(t) {
2529
- return {
2530
- group: t("image.pending"),
2531
- open: t("image.openOriginal"),
2532
- scrollLeft: t("image.scrollLeft"),
2533
- scrollRight: t("image.scrollRight")
2534
- };
2636
+ function ReferenceIcon({ kind, size = 16, className }) {
2637
+ switch (kind) {
2638
+ case "session": return (0, react_jsx_runtime.jsx)("svg", {
2639
+ width: size,
2640
+ height: size,
2641
+ className,
2642
+ viewBox: "0 0 16 16",
2643
+ fill: "none",
2644
+ "aria-hidden": true,
2645
+ children: (0, react_jsx_runtime.jsx)("path", {
2646
+ d: "M8 0.597656C3.91296 0.597656 0.599716 3.91103 0.599609 7.99805C0.599609 9.13171 0.854567 10.2079 1.31152 11.1699L1.59277 11.7607L2.77441 11.1992L2.49414 10.6084L2.36035 10.3076C2.06865 9.59612 1.90723 8.81645 1.90723 7.99805C1.90733 4.63362 4.63554 1.90625 8 1.90625C11.3644 1.90635 14.0917 4.63368 14.0918 7.99805C14.0918 11.3625 11.3644 14.0907 8 14.0908C7.311 14.0908 6.80642 14.0414 6.35938 13.918C5.919 13.7963 5.50105 13.5929 5.00098 13.2441C4.26805 12.7329 3.21756 12.5526 2.35156 13.0996L2.33789 13.1084L2.32422 13.1182L1.74805 13.5234L2.18164 14.8184L3.05957 14.2002C3.37505 14.0068 3.84248 14.0319 4.25195 14.3174C4.84447 14.7307 5.39718 15.009 6.01172 15.1787C6.61963 15.3465 7.25579 15.3984 8 15.3984C12.087 15.3983 15.4004 12.0851 15.4004 7.99805C15.4003 3.9111 12.087 0.59776 8 0.597656ZM4.56836 8.50977V9.80371H8.12402V8.50977H4.56836ZM4.56836 7.30078H11.4619V6.00684H4.56836V7.30078Z",
2647
+ fill: "currentColor"
2648
+ })
2649
+ });
2650
+ case "file": return (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconBrowseOutline16, {
2651
+ size,
2652
+ className
2653
+ });
2654
+ case "folder": return (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconFolderClose16, {
2655
+ size,
2656
+ className
2657
+ });
2658
+ }
2535
2659
  }
2536
2660
  //#endregion
2537
2661
  //#region lib/types/client/chat/message-chrome.js
@@ -2881,23 +3005,23 @@ window.__ModuleLoader__.load({
2881
3005
  document.head.appendChild(tag);
2882
3006
  }
2883
3007
  var ContextMeter_module_css_default = {
2884
- "header": "JObwrW_header",
2885
- "headline": "JObwrW_headline",
2886
- "segment": "JObwrW_segment",
3008
+ "bar": "JObwrW_bar",
3009
+ "colorMessages": "JObwrW_colorMessages",
2887
3010
  "colorSystem": "JObwrW_colorSystem",
3011
+ "colorTools": "JObwrW_colorTools",
3012
+ "figures": "JObwrW_figures",
2888
3013
  "fill": "JObwrW_fill",
2889
- "row": "JObwrW_row",
2890
- "track": "JObwrW_track",
3014
+ "header": "JObwrW_header",
3015
+ "headline": "JObwrW_headline",
3016
+ "panel": "JObwrW_panel",
3017
+ "percent": "JObwrW_percent",
2891
3018
  "root": "JObwrW_root",
3019
+ "row": "JObwrW_row",
2892
3020
  "rows": "JObwrW_rows",
2893
- "bar": "JObwrW_bar",
2894
- "figures": "JObwrW_figures",
3021
+ "segment": "JObwrW_segment",
2895
3022
  "swatch": "JObwrW_swatch",
2896
- "trigger": "JObwrW_trigger",
2897
- "panel": "JObwrW_panel",
2898
- "colorTools": "JObwrW_colorTools",
2899
- "colorMessages": "JObwrW_colorMessages",
2900
- "percent": "JObwrW_percent"
3023
+ "track": "JObwrW_track",
3024
+ "trigger": "JObwrW_trigger"
2901
3025
  };
2902
3026
  //#endregion
2903
3027
  //#region lib/types/client/skeleton/ContextMeter.js
@@ -3069,11 +3193,11 @@ window.__ModuleLoader__.load({
3069
3193
  document.head.appendChild(tag);
3070
3194
  }
3071
3195
  var PermissionSelect_module_css_default = {
3072
- "triggerIcon": "Sh0Q9G_triggerIcon",
3073
- "chevronOpen": "Sh0Q9G_chevronOpen",
3074
- "triggerLabel": "Sh0Q9G_triggerLabel",
3075
3196
  "chevron": "Sh0Q9G_chevron",
3076
- "trigger": "Sh0Q9G_trigger"
3197
+ "chevronOpen": "Sh0Q9G_chevronOpen",
3198
+ "trigger": "Sh0Q9G_trigger",
3199
+ "triggerIcon": "Sh0Q9G_triggerIcon",
3200
+ "triggerLabel": "Sh0Q9G_triggerLabel"
3077
3201
  };
3078
3202
  //#endregion
3079
3203
  //#region lib/types/client/skeleton/PermissionSelect.js
@@ -3298,7 +3422,7 @@ window.__ModuleLoader__.load({
3298
3422
  }
3299
3423
  //#endregion
3300
3424
  //#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-conversation/src/client/skeleton/InputBar.module.css.mjs
3301
- const css$17 = "@font-face{font-family:DshChipCell;src:url(data:font/ttf;base64,AAEAAAAKAIAAAwAgT1MvMkT8SmIAAAEoAAAAYGNtYXAADQBPAAABkAAAADRnbHlmAAAAAAAAAcwAAAABaGVhZCwtPGoAAACsAAAANmhoZWEDIg7bAAAA5AAAACRobXR4EZQAAAAAAYgAAAAIbG9jYQAAAAAAAAHEAAAABm1heHAAAwACAAABCAAAACBuYW1lvljk2gAAAdAAAABscG9zdNNweNQAAAI8AAAALQABAAAAAQAAdia1tV8PPPUAAwPoAAAAAOaLfcUAAAAA5ot9xQAAAAAAAAAAAAAAAwACAAAAAAAAAAEAAAMg/zgAAA+gAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAACAAEAAAACAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAwjKAZAABQAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAPz8/PwAA//z//AMg/zgAAAMgAMgAAAAAAAAAAAAAAAAAAAAgAAAB9AAAD6AAAAAAAAIAAAADAAAAFAADAAEAAAAUAAQAIAAAAAQABAABAAD//P//AAD//P//AAUAAQAAAAAAAAAAAAAAAAAAAAAAAAAEADYAAQAAAAAAAQALAAAAAQAAAAAAAgAHAAsAAwABBAkAAQAWABIAAwABBAkAAgAOAChEc2hDaGlwQ2VsbFJlZ3VsYXIARABzAGgAQwBoAGkAcABDAGUAbABsAFIAZQBnAHUAbABhAHIAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAABAgZvYmpyZXAAAAA=)format(\"truetype\")}.uV2eYG_root{padding:0 var(--dsh-composer-side-clearance) 8px;flex-direction:column;align-items:center;display:flex}.uV2eYG_hero{padding:0 var(--dsh-composer-side-clearance)}.uV2eYG_notice{width:100%;max-width:var(--dsh-composer-card-max-width);background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-secondary);border-radius:8px;margin-bottom:6px;padding:4px 8px;font-size:12px;line-height:18px}.uV2eYG_noticeError{background:var(--dsw-alias-interactive-bg-hover-danger);color:var(--dsw-alias-state-error-primary)}.uV2eYG_card{box-sizing:border-box;width:100%;max-width:var(--dsh-composer-card-max-width);border:1px solid var(--dsw-alias-border-l2-darkmode-thin);background:var(--dsw-specific-input-major);box-shadow:var(--dsw-shadow-lv2);--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2);border-radius:22px;flex-direction:column;gap:12px;padding-top:10px;font-size:16px;line-height:24px;display:flex;position:relative}.uV2eYG_cardWorkspaceTrigger{cursor:pointer;border-color:#0000}.uV2eYG_cardWorkspaceTrigger:after{content:\"\";background:var(--dsw-alias-border-l4);pointer-events:none;border-radius:22px;transition:background-color .1s;position:absolute;inset:-1px;-webkit-mask:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Crect width='100%25' height='100%25' fill='none' rx='22' ry='22' stroke='black' stroke-width='2' stroke-dasharray='4 4'/%3E%3C/svg%3E\");mask:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Crect width='100%25' height='100%25' fill='none' rx='22' ry='22' stroke='black' stroke-width='2' stroke-dasharray='4 4'/%3E%3C/svg%3E\")}.uV2eYG_cardWorkspaceTrigger :disabled{pointer-events:none}.uV2eYG_cardWorkspaceTrigger:hover:after{background:var(--dsw-alias-state-business-primary)}.uV2eYG_accessory{align-items:center;gap:8px;padding:10px 12px 0;display:flex}.uV2eYG_attachments{min-width:0;padding:4px 12px 0}.uV2eYG_overlayAnchor{height:0;position:absolute;inset:0 0 auto}.uV2eYG_scroll{max-height:var(--dsh-composer-text-max-height);overflow-y:auto}.uV2eYG_grow{position:relative}.uV2eYG_backdrop{color:var(--dsw-alias-label-primary);pointer-events:none;position:absolute;inset:0;overflow:hidden}.uV2eYG_hlToken{color:var(--dsw-alias-state-warn-label);background-color:#0000}.uV2eYG_hlSegment{color:#0000;background-color:#0000;border-radius:4px}.uV2eYG_hint{color:var(--dsw-alias-label-caption)}.uV2eYG_pending{background:var(--dsw-alias-state-business-primary);border-radius:50%;width:8px;height:8px;animation:1s ease-in-out infinite alternate uV2eYG_input-pending}@keyframes uV2eYG_input-pending{0%{opacity:.35}to{opacity:1}}.uV2eYG_input{resize:none;color:#0000;width:100%;height:100%;caret-color:var(--dsw-alias-state-business-primary);background:0 0;border:none;outline:none;position:absolute;inset:0;overflow:hidden}.uV2eYG_input,.uV2eYG_mirror,.uV2eYG_backdrop{box-sizing:border-box;font-family:\"DshChipCell\", var(--dsw-font-family);font-size:inherit;line-height:inherit;white-space:pre-wrap;word-break:break-word;overflow-wrap:anywhere;padding:4px 12px 0 16px}.uV2eYG_input::placeholder{color:var(--dsw-alias-label-caption);user-select:none}.uV2eYG_input:disabled{color:var(--dsw-alias-label-tertiary);cursor:not-allowed}.uV2eYG_input[aria-haspopup=menu]{cursor:pointer}.uV2eYG_mirror{visibility:hidden;pointer-events:none}.uV2eYG_hero .uV2eYG_mirror{min-height:52px}.uV2eYG_row{justify-content:space-between;align-items:center;gap:12px;min-width:0;padding:2px 8px 6px;display:flex;container-type:inline-size}.uV2eYG_tools,.uV2eYG_modes,.uV2eYG_trailing{align-items:center;min-width:0;display:flex}.uV2eYG_tools{gap:16px}.uV2eYG_modes{gap:12px}.uV2eYG_trailing{flex:none;gap:12px}.uV2eYG_add{background:var(--dsw-specific-selector);width:28px;height:28px;color:var(--dsw-alias-label-primary);cursor:pointer;border:none;border-radius:999px;flex:none;place-items:center;display:grid}.uV2eYG_add:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-solid)}.uV2eYG_add:disabled{opacity:.5;cursor:default}.uV2eYG_select{max-width:220px;height:28px;color:var(--dsw-alias-label-secondary);white-space:nowrap;cursor:pointer;appearance:none;background-color:#0000;background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12' fill='none'%3E%3Cpath d='M3 4.5L6 7.5L9 4.5' stroke='%2381858C' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\");background-position:right 4px center;background-repeat:no-repeat;background-size:12px 12px;border:none;border-radius:8px;outline:none;padding:0 20px 0 8px;font-size:13px;font-weight:500;line-height:20px}.uV2eYG_select:hover:not(:disabled){background-color:var(--dsw-alias-interactive-bg-hover)}.uV2eYG_select:disabled{opacity:.5;cursor:default}.uV2eYG_primary{background:var(--dsw-alias-button-info-fill);color:#fff;cursor:pointer;border:none;border-radius:999px;flex:none;place-items:center;width:34px;height:34px;transition:background-color .1s;display:grid;transform:translateY(-2px)}.uV2eYG_primary:hover:not(:disabled){background:var(--dsw-alias-button-info-hover)}.uV2eYG_primary:disabled{opacity:.4;cursor:default}.uV2eYG_retry{color:inherit;cursor:pointer;background:0 0;border:1px solid;border-radius:4px;margin-left:8px;padding:1px 8px;font-size:12px}.uV2eYG_textRef{color:var(--dsw-alias-state-business-primary);-webkit-box-decoration-break:clone;box-decoration-break:clone;background-color:#0000}.uV2eYG_textRef:after{display:none}.uV2eYG_chip{background:#6187d838;border-radius:6px;position:relative}.uV2eYG_chip:before{content:\"\";color:#0000}.uV2eYG_chipLabel{width:calc(138.889% - 10px);color:var(--dsw-alias-label-primary);white-space:nowrap;justify-content:center;align-items:center;display:flex;position:absolute;top:50%;left:50%;overflow:hidden;transform:translate(-50%,-50%)scale(.72)}.uV2eYG_chipInvalid{opacity:.7;background:#d8616133;text-decoration:line-through}";
3425
+ const css$17 = ".uV2eYG_root{padding:0 var(--dsh-composer-side-clearance) 8px;flex-direction:column;align-items:center;display:flex}.uV2eYG_hero{padding:0 var(--dsh-composer-side-clearance)}.uV2eYG_notice{width:100%;max-width:var(--dsh-composer-card-max-width);background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-secondary);border-radius:8px;margin-bottom:6px;padding:4px 8px;font-size:12px;line-height:18px}.uV2eYG_card{box-sizing:border-box;width:100%;max-width:var(--dsh-composer-card-max-width);border:1px solid var(--dsw-alias-border-l2-darkmode-thin);background:var(--dsw-specific-input-major);box-shadow:var(--dsw-shadow-lv2);--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2);border-radius:22px;flex-direction:column;gap:12px;padding-top:10px;font-size:16px;line-height:24px;display:flex;position:relative}.uV2eYG_cardWorkspaceTrigger{cursor:pointer;border-color:#0000}.uV2eYG_cardWorkspaceTrigger:after{content:\"\";background:var(--dsw-alias-border-l4);pointer-events:none;border-radius:22px;transition:background-color .1s;position:absolute;inset:-1px;-webkit-mask:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Crect width='100%25' height='100%25' fill='none' rx='22' ry='22' stroke='black' stroke-width='2' stroke-dasharray='4 4'/%3E%3C/svg%3E\");mask:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Crect width='100%25' height='100%25' fill='none' rx='22' ry='22' stroke='black' stroke-width='2' stroke-dasharray='4 4'/%3E%3C/svg%3E\")}.uV2eYG_cardWorkspaceTrigger :disabled{pointer-events:none}.uV2eYG_cardWorkspaceTrigger:hover:after{background:var(--dsw-alias-state-business-primary)}.uV2eYG_accessory{align-items:center;gap:8px;padding:10px 12px 0;display:flex}.uV2eYG_overlayAnchor{height:0;position:absolute;inset:0 0 auto}.uV2eYG_scroll{max-height:var(--dsh-composer-text-max-height);overflow-y:auto}.uV2eYG_grow{position:relative}.uV2eYG_backdrop{color:var(--dsw-alias-label-primary);pointer-events:none;position:absolute;inset:0;overflow:hidden}.uV2eYG_backdropDisabled,.uV2eYG_backdropDisabled :is(.uV2eYG_hlToken,.uV2eYG_hint,.uV2eYG_textRef,.uV2eYG_chip,.uV2eYG_chipInvalid){color:var(--dsw-alias-label-tertiary)}.uV2eYG_hlToken{color:var(--dsw-alias-state-warn-label);background-color:#0000}.uV2eYG_hlSegment{color:#0000;background-color:#0000;border-radius:4px}.uV2eYG_hint{color:var(--dsw-alias-label-caption)}.uV2eYG_pending{background:var(--dsw-alias-state-business-primary);border-radius:50%;width:8px;height:8px;animation:1s ease-in-out infinite alternate uV2eYG_input-pending}@keyframes uV2eYG_input-pending{0%{opacity:.35}to{opacity:1}}.uV2eYG_input{resize:none;color:#0000;-webkit-text-fill-color:transparent;width:100%;height:100%;caret-color:var(--dsw-alias-state-business-primary);background:0 0;border:none;outline:none;position:absolute;inset:0;overflow:hidden}.uV2eYG_input,.uV2eYG_mirror,.uV2eYG_backdrop{box-sizing:border-box;font-family:var(--dsw-font-family);font-size:inherit;line-height:inherit;white-space:pre-wrap;word-break:break-word;overflow-wrap:anywhere;padding:4px 12px 0 16px}.uV2eYG_input::placeholder{color:var(--dsw-alias-label-caption);-webkit-text-fill-color:var(--dsw-alias-label-caption);user-select:none}.uV2eYG_input:disabled{color:#0000;-webkit-text-fill-color:transparent;cursor:not-allowed}.uV2eYG_input[aria-haspopup=menu]{cursor:pointer}.uV2eYG_mirror{visibility:hidden;pointer-events:none}.uV2eYG_hero .uV2eYG_mirror{min-height:52px}.uV2eYG_row{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:12px;min-width:0;padding:2px 8px 6px;display:flex;container-type:inline-size}.uV2eYG_tools,.uV2eYG_modes,.uV2eYG_trailing{align-items:center;min-width:0;display:flex}.uV2eYG_tools{gap:16px}.uV2eYG_modes{gap:12px}.uV2eYG_trailing{flex:none;gap:12px;margin-left:auto}.uV2eYG_add{background:var(--dsw-specific-selector);width:28px;height:28px;color:var(--dsw-alias-label-primary);cursor:pointer;border:none;border-radius:999px;flex:none;place-items:center;display:grid}.uV2eYG_add:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-solid)}.uV2eYG_add:disabled{opacity:.5;cursor:default}.uV2eYG_select{max-width:220px;height:28px;color:var(--dsw-alias-label-secondary);white-space:nowrap;cursor:pointer;appearance:none;background-color:#0000;background-image:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12' fill='none'%3E%3Cpath d='M3 4.5L6 7.5L9 4.5' stroke='%2381858C' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\");background-position:right 4px center;background-repeat:no-repeat;background-size:12px 12px;border:none;border-radius:8px;outline:none;padding:0 20px 0 8px;font-size:13px;font-weight:500;line-height:20px}.uV2eYG_select:hover:not(:disabled){background-color:var(--dsw-alias-interactive-bg-hover)}.uV2eYG_select:disabled{opacity:.5;cursor:default}.uV2eYG_primary{background:var(--dsw-alias-button-info-fill);color:#fff;cursor:pointer;border:none;border-radius:999px;flex:none;place-items:center;width:34px;height:34px;transition:background-color .1s;display:grid;transform:translateY(-2px)}.uV2eYG_primary:hover:not(:disabled){background:var(--dsw-alias-button-info-hover)}.uV2eYG_primary:disabled{opacity:.4;cursor:default}.uV2eYG_retry{color:inherit;cursor:pointer;background:0 0;border:1px solid;border-radius:4px;margin-left:8px;padding:1px 8px;font-size:12px}.uV2eYG_textRef{color:var(--dsw-alias-state-business-primary);-webkit-box-decoration-break:clone;box-decoration-break:clone;background-color:#0000}.uV2eYG_textRef:after{display:none}.uV2eYG_textRefTrigger{position:relative}.uV2eYG_textRefTriggerGlyph{color:#0000}.uV2eYG_textRefIcon{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}.uV2eYG_chip{color:var(--dsw-alias-state-business-primary);-webkit-box-decoration-break:clone;box-decoration-break:clone;background:0 0;position:relative}.uV2eYG_chipTrigger{position:relative}.uV2eYG_chipTriggerGlyph{color:#0000}.uV2eYG_chipIcon{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}.uV2eYG_chipInvalid{opacity:.7;color:var(--dsw-alias-state-error-primary);text-decoration:line-through}";
3302
3426
  const tagId$17 = "@deepseek-ai/dsh-client-ui-conversation/InputBar.module.css";
3303
3427
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$17) + "]") === null) {
3304
3428
  const tag = document.createElement("style");
@@ -3308,37 +3432,41 @@ window.__ModuleLoader__.load({
3308
3432
  document.head.appendChild(tag);
3309
3433
  }
3310
3434
  var InputBar_module_css_default = {
3311
- "hlSegment": "uV2eYG_hlSegment",
3312
- "textRef": "uV2eYG_textRef",
3313
- "trailing": "uV2eYG_trailing",
3314
- "noticeError": "uV2eYG_noticeError",
3315
- "backdrop": "uV2eYG_backdrop",
3316
- "scroll": "uV2eYG_scroll",
3317
- "add": "uV2eYG_add",
3318
- "chipInvalid": "uV2eYG_chipInvalid",
3319
- "mirror": "uV2eYG_mirror",
3320
- "chipLabel": "uV2eYG_chipLabel",
3321
3435
  "accessory": "uV2eYG_accessory",
3436
+ "add": "uV2eYG_add",
3437
+ "backdrop": "uV2eYG_backdrop",
3438
+ "backdropDisabled": "uV2eYG_backdropDisabled",
3322
3439
  "card": "uV2eYG_card",
3323
- "retry": "uV2eYG_retry",
3440
+ "cardWorkspaceTrigger": "uV2eYG_cardWorkspaceTrigger",
3441
+ "chip": "uV2eYG_chip",
3442
+ "chipIcon": "uV2eYG_chipIcon",
3443
+ "chipInvalid": "uV2eYG_chipInvalid",
3444
+ "chipTrigger": "uV2eYG_chipTrigger",
3445
+ "chipTriggerGlyph": "uV2eYG_chipTriggerGlyph",
3446
+ "grow": "uV2eYG_grow",
3324
3447
  "hero": "uV2eYG_hero",
3325
- "select": "uV2eYG_select",
3326
3448
  "hint": "uV2eYG_hint",
3449
+ "hlSegment": "uV2eYG_hlSegment",
3327
3450
  "hlToken": "uV2eYG_hlToken",
3328
- "overlayAnchor": "uV2eYG_overlayAnchor",
3329
3451
  "input": "uV2eYG_input",
3330
- "row": "uV2eYG_row",
3331
- "pending": "uV2eYG_pending",
3332
- "modes": "uV2eYG_modes",
3333
3452
  "input-pending": "uV2eYG_input-pending",
3334
- "attachments": "uV2eYG_attachments",
3335
- "chip": "uV2eYG_chip",
3336
- "cardWorkspaceTrigger": "uV2eYG_cardWorkspaceTrigger",
3337
- "grow": "uV2eYG_grow",
3453
+ "mirror": "uV2eYG_mirror",
3454
+ "modes": "uV2eYG_modes",
3455
+ "notice": "uV2eYG_notice",
3456
+ "overlayAnchor": "uV2eYG_overlayAnchor",
3457
+ "pending": "uV2eYG_pending",
3338
3458
  "primary": "uV2eYG_primary",
3459
+ "retry": "uV2eYG_retry",
3339
3460
  "root": "uV2eYG_root",
3461
+ "row": "uV2eYG_row",
3462
+ "scroll": "uV2eYG_scroll",
3463
+ "select": "uV2eYG_select",
3464
+ "textRef": "uV2eYG_textRef",
3465
+ "textRefIcon": "uV2eYG_textRefIcon",
3466
+ "textRefTrigger": "uV2eYG_textRefTrigger",
3467
+ "textRefTriggerGlyph": "uV2eYG_textRefTriggerGlyph",
3340
3468
  "tools": "uV2eYG_tools",
3341
- "notice": "uV2eYG_notice"
3469
+ "trailing": "uV2eYG_trailing"
3342
3470
  };
3343
3471
  //#endregion
3344
3472
  //#region lib/types/client/skeleton/InputBar.js
@@ -3371,8 +3499,6 @@ window.__ModuleLoader__.load({
3371
3499
  const draft = input?.draft ?? "";
3372
3500
  const attachments = (0, react.useMemo)(() => input === void 0 || draftImages === void 0 ? [] : draftImages(input.imageIds), [draftImages, input?.imageIds]);
3373
3501
  const empty = draft.trim() === "" && attachments.length === 0;
3374
- const [preview, setPreview] = (0, react.useState)(null);
3375
- const [dragActive, setDragActive] = (0, react.useState)(false);
3376
3502
  const [toast, setToast] = (0, react.useState)(null);
3377
3503
  const toastSeq = (0, react.useRef)(0);
3378
3504
  const showToast = (0, react.useCallback)((text) => {
@@ -3395,9 +3521,11 @@ window.__ModuleLoader__.load({
3395
3521
  t,
3396
3522
  imageLimits
3397
3523
  ]);
3524
+ (0, react.useEffect)(() => {
3525
+ if (notice?.level === "error") showToast(notice.text);
3526
+ }, [notice, showToast]);
3398
3527
  const inputRef = (0, react.useRef)(null);
3399
3528
  const cardRef = (0, react.useRef)(null);
3400
- const dragDepthRef = (0, react.useRef)(0);
3401
3529
  const scrollRef = (0, react.useRef)(null);
3402
3530
  const mirrorRef = (0, react.useRef)(null);
3403
3531
  const safari = (0, react.useMemo)(() => isSafariBrowser(navigator), []);
@@ -3434,9 +3562,6 @@ window.__ModuleLoader__.load({
3434
3562
  safariNativeShrinkRef.current = false;
3435
3563
  if (safari && nativeShrink) repairSafariTextareaLayout(inputRef.current);
3436
3564
  }, [draft, safari]);
3437
- (0, react.useEffect)(() => {
3438
- if (preview !== null && !attachments.some((attachment) => attachment.id === preview.id)) setPreview(null);
3439
- }, [attachments, preview]);
3440
3565
  const revealCaret = (caret) => {
3441
3566
  const scrollEl = scrollRef.current;
3442
3567
  const mirrorEl = mirrorRef.current;
@@ -3492,6 +3617,10 @@ window.__ModuleLoader__.load({
3492
3617
  el.removeEventListener("wheel", onWheel);
3493
3618
  };
3494
3619
  }, []);
3620
+ const selectionOf = (el) => ({
3621
+ start: el.selectionStart ?? 0,
3622
+ end: el.selectionEnd ?? el.selectionStart ?? 0
3623
+ });
3495
3624
  const onKeyDown = (e) => {
3496
3625
  if (workspaceTrigger) {
3497
3626
  if (e.key === "Enter" || e.key === " ") {
@@ -3500,9 +3629,28 @@ window.__ModuleLoader__.load({
3500
3629
  }
3501
3630
  return;
3502
3631
  }
3503
- if (keyboard === void 0 || inputActions === void 0) return;
3632
+ if (input === void 0 || keyboard === void 0 || inputActions === void 0) return;
3504
3633
  if (e.key === "Enter" && e.shiftKey) return;
3505
3634
  const composing = composingRef.current || e.nativeEvent.isComposing || e.nativeEvent.keyCode === 229;
3635
+ if (!composing && !machineBusy && !locked && (e.key === "Backspace" || e.key === "Delete")) {
3636
+ const selection = selectionOf(e.currentTarget);
3637
+ if (selection.start === selection.end) {
3638
+ const occurrence = input.occurrences.find((o) => e.key === "Backspace" ? o.offset + o.length === selection.start : o.offset === selection.start);
3639
+ if (occurrence !== void 0) {
3640
+ e.preventDefault();
3641
+ const start = occurrence.offset;
3642
+ const end = occurrence.offset + occurrence.length;
3643
+ keyboard.setDraft(draft.slice(0, start) + draft.slice(end), {
3644
+ start,
3645
+ end,
3646
+ insertedLength: 0
3647
+ });
3648
+ restoreCaret(e.currentTarget, start);
3649
+ keyboard.track(keyboard.snapshot.draft, start);
3650
+ return;
3651
+ }
3652
+ }
3653
+ }
3506
3654
  if (e.key === "ArrowUp" || e.key === "ArrowDown") {
3507
3655
  if (keyboard.arbitrate(e.key === "ArrowUp" ? "up" : "down", composing) === "consumed") e.preventDefault();
3508
3656
  return;
@@ -3548,34 +3696,31 @@ window.__ModuleLoader__.load({
3548
3696
  keyboard.setDraft(next);
3549
3697
  keyboard.track(next, e.target.selectionStart ?? next.length);
3550
3698
  };
3551
- const selectionOf = (el) => ({
3552
- start: el.selectionStart ?? 0,
3553
- end: el.selectionEnd ?? el.selectionStart ?? 0
3554
- });
3555
3699
  const onCopyOrCut = (e, cut) => {
3556
3700
  if (input === void 0 || keyboard === void 0) return;
3557
3701
  const el = e.currentTarget;
3558
3702
  const { start, end } = selectionOf(el);
3559
3703
  if (start === end) return;
3560
- draft.slice(start, end);
3561
- const touched = input.occurrences.filter((o) => o.offset >= start && o.offset < end);
3704
+ const touched = input.occurrences.filter((o) => o.offset < end && o.offset + o.length > start);
3562
3705
  if (touched.length === 0 && !cut) return;
3563
3706
  e.preventDefault();
3707
+ const copyStart = touched.reduce((value, o) => Math.min(value, o.offset), start);
3708
+ const copyEnd = touched.reduce((value, o) => Math.max(value, o.offset + o.length), end);
3564
3709
  let text = "";
3565
- let cursor = start;
3710
+ let cursor = copyStart;
3566
3711
  for (const o of touched) {
3567
3712
  text += draft.slice(cursor, o.offset) + o.clipboardText;
3568
- cursor = o.offset + 1;
3713
+ cursor = o.offset + o.length;
3569
3714
  }
3570
- text += draft.slice(cursor, end);
3715
+ text += draft.slice(cursor, copyEnd);
3571
3716
  e.clipboardData.setData("text/plain", text);
3572
3717
  if (cut && !machineBusy && !locked) {
3573
- keyboard.setDraft(draft.slice(0, start) + draft.slice(end), {
3574
- start,
3575
- end,
3718
+ keyboard.setDraft(draft.slice(0, copyStart) + draft.slice(copyEnd), {
3719
+ start: copyStart,
3720
+ end: copyEnd,
3576
3721
  insertedLength: 0
3577
3722
  });
3578
- restoreCaret(el, start);
3723
+ restoreCaret(el, copyStart);
3579
3724
  }
3580
3725
  };
3581
3726
  const onPaste = (e) => {
@@ -3614,60 +3759,6 @@ window.__ModuleLoader__.load({
3614
3759
  t
3615
3760
  ]);
3616
3761
  const canAcceptDrop = !locked && !machineBusy && imageLimits !== void 0 && addImages !== void 0;
3617
- (0, react.useEffect)(() => {
3618
- const hasFiles = (event) => event.dataTransfer?.types.includes("Files") ?? false;
3619
- const reset = () => {
3620
- dragDepthRef.current = 0;
3621
- setDragActive(false);
3622
- };
3623
- const onDragEnter = (event) => {
3624
- if (!hasFiles(event)) return;
3625
- event.preventDefault();
3626
- dragDepthRef.current += 1;
3627
- setDragActive(true);
3628
- };
3629
- const onDragOver = (event) => {
3630
- if (!hasFiles(event) || event.dataTransfer === null) return;
3631
- event.preventDefault();
3632
- event.dataTransfer.dropEffect = canAcceptDrop ? "copy" : "none";
3633
- };
3634
- const onDragLeave = (event) => {
3635
- if (!hasFiles(event)) return;
3636
- dragDepthRef.current = Math.max(0, dragDepthRef.current - 1);
3637
- if (dragDepthRef.current === 0) setDragActive(false);
3638
- const leavingViewport = event.clientX <= 0 || event.clientY <= 0 || event.clientX >= window.innerWidth || event.clientY >= window.innerHeight;
3639
- if ((event.target === document.documentElement || event.target === document.body) && leavingViewport) reset();
3640
- };
3641
- const onDrop = (event) => {
3642
- if (!hasFiles(event)) return;
3643
- event.preventDefault();
3644
- reset();
3645
- if (!canAcceptDrop) return;
3646
- intakeImages([...event.dataTransfer?.files ?? []]);
3647
- };
3648
- document.addEventListener("dragenter", onDragEnter);
3649
- document.addEventListener("dragover", onDragOver);
3650
- document.addEventListener("dragleave", onDragLeave);
3651
- document.addEventListener("drop", onDrop);
3652
- window.addEventListener("dragend", reset);
3653
- return () => {
3654
- document.removeEventListener("dragenter", onDragEnter);
3655
- document.removeEventListener("dragover", onDragOver);
3656
- document.removeEventListener("dragleave", onDragLeave);
3657
- document.removeEventListener("drop", onDrop);
3658
- window.removeEventListener("dragend", reset);
3659
- };
3660
- }, [canAcceptDrop, intakeImages]);
3661
- const closePreview = (0, react.useCallback)(() => {
3662
- setPreview(null);
3663
- }, []);
3664
- const railItems = (0, react.useMemo)(() => attachments.map((attachment) => ({
3665
- id: attachment.id,
3666
- previewUrl: attachment.previewUrl,
3667
- alt: attachment.file.name || t("image.pending"),
3668
- removeLabel: t("image.remove", { name: attachment.file.name }),
3669
- attachment
3670
- })), [attachments, t]);
3671
3762
  const onSelect = (e) => {
3672
3763
  if (keyboard !== void 0 && keyboard.snapshot.paste !== void 0) keyboard.invalidatePaste();
3673
3764
  };
@@ -3727,23 +3818,42 @@ window.__ModuleLoader__.load({
3727
3818
  pushPlain(b.at);
3728
3819
  if (b.kind === "chip") {
3729
3820
  const chip = b.chip;
3730
- backdrop.push((0, react_jsx_runtime.jsx)("span", {
3821
+ backdrop.push((0, react_jsx_runtime.jsxs)("span", {
3731
3822
  className: clsx(InputBar_module_css_default.chip, chip.invalid && InputBar_module_css_default.chipInvalid),
3732
3823
  "data-decoration": "chip",
3824
+ "data-reference-appearance": chip.appearance,
3733
3825
  "data-occurrence": chip.occurrenceId,
3734
3826
  "data-invalid": chip.invalid || void 0,
3735
3827
  title: chip.label,
3736
- children: (0, react_jsx_runtime.jsx)("span", {
3737
- className: InputBar_module_css_default.chipLabel,
3738
- children: chip.label
3739
- })
3828
+ children: [chip.appearance === void 0 ? chip.text[0] : (0, react_jsx_runtime.jsxs)("span", {
3829
+ className: InputBar_module_css_default.chipTrigger,
3830
+ children: [(0, react_jsx_runtime.jsx)("span", {
3831
+ className: InputBar_module_css_default.chipTriggerGlyph,
3832
+ children: chip.text[0]
3833
+ }), (0, react_jsx_runtime.jsx)(ReferenceIcon, {
3834
+ kind: chip.appearance,
3835
+ size: 16,
3836
+ className: InputBar_module_css_default.chipIcon
3837
+ })]
3838
+ }), (0, react_jsx_runtime.jsx)("span", { children: chip.text.slice(1) })]
3740
3839
  }, `chip-${chip.occurrenceId}`));
3741
- cursor = chip.offset + 1;
3840
+ cursor = chip.offset + chip.length;
3742
3841
  } else {
3842
+ const text = draft.slice(b.ref.start, b.ref.end);
3743
3843
  backdrop.push((0, react_jsx_runtime.jsx)("mark", {
3744
3844
  className: InputBar_module_css_default.textRef,
3745
3845
  "data-decoration": "text-ref",
3746
- children: draft.slice(b.ref.start, b.ref.end)
3846
+ children: b.ref.appearance === "folder" ? (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsxs)("span", {
3847
+ className: InputBar_module_css_default.textRefTrigger,
3848
+ children: [(0, react_jsx_runtime.jsx)("span", {
3849
+ className: InputBar_module_css_default.textRefTriggerGlyph,
3850
+ children: text[0]
3851
+ }), (0, react_jsx_runtime.jsx)(ReferenceIcon, {
3852
+ kind: "folder",
3853
+ size: 16,
3854
+ className: InputBar_module_css_default.textRefIcon
3855
+ })]
3856
+ }), text.slice(1)] }) : text
3747
3857
  }, `ref-${b.ref.start}`));
3748
3858
  cursor = b.ref.end;
3749
3859
  }
@@ -3764,21 +3874,14 @@ window.__ModuleLoader__.load({
3764
3874
  return (0, react_jsx_runtime.jsxs)("div", {
3765
3875
  className: clsx(InputBar_module_css_default.root, variant === "hero" && InputBar_module_css_default.hero),
3766
3876
  children: [
3767
- dragActive && (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_attachment.DropOverlay, {
3768
- disabled: !canAcceptDrop,
3769
- labels: dropOverlayLabels(t, canAcceptDrop, imageLimits === void 0 ? void 0 : {
3770
- count: imageLimits.maxImagesPerMessage,
3771
- size: imageSizeText(imageLimits.maxImageBytes)
3772
- })
3773
- }),
3774
3877
  toast !== null && (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Toast, {
3775
3878
  text: toast.text,
3776
3879
  icon: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconWarningOutline16, {}),
3777
3880
  anchor: cardRef.current,
3778
3881
  onDone: dismissToast
3779
3882
  }, toast.seq),
3780
- notice !== null && (0, react_jsx_runtime.jsx)("div", {
3781
- className: clsx(InputBar_module_css_default.notice, notice.level === "error" && InputBar_module_css_default.noticeError),
3883
+ notice?.level === "info" && (0, react_jsx_runtime.jsx)("div", {
3884
+ className: InputBar_module_css_default.notice,
3782
3885
  role: "status",
3783
3886
  children: notice.text
3784
3887
  }),
@@ -3799,18 +3902,17 @@ window.__ModuleLoader__.load({
3799
3902
  className: InputBar_module_css_default.accessory,
3800
3903
  children: accessory
3801
3904
  }),
3802
- railItems.length > 0 && (0, react_jsx_runtime.jsx)("div", {
3803
- className: InputBar_module_css_default.attachments,
3804
- children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_attachment.AttachmentRail, {
3805
- items: railItems,
3806
- labels: attachmentRailLabels(t),
3807
- onOpen: (item) => {
3808
- setPreview(item.attachment);
3809
- },
3810
- onRemove: (item) => {
3811
- removeImage?.(item.attachment.id);
3812
- }
3813
- })
3905
+ renderSlot("conversation.input.attachments", {
3906
+ attachments,
3907
+ canAcceptDrop,
3908
+ onAddImages: intakeImages,
3909
+ onRemoveImage: (id) => {
3910
+ removeImage?.(id);
3911
+ },
3912
+ dropLimits: imageLimits === void 0 ? void 0 : {
3913
+ count: imageLimits.maxImagesPerMessage,
3914
+ size: imageSizeText(imageLimits.maxImageBytes)
3915
+ }
3814
3916
  }),
3815
3917
  (0, react_jsx_runtime.jsx)("div", {
3816
3918
  ref: scrollRef,
@@ -3821,8 +3923,9 @@ window.__ModuleLoader__.load({
3821
3923
  children: [
3822
3924
  (0, react_jsx_runtime.jsx)("div", {
3823
3925
  "aria-hidden": true,
3824
- className: InputBar_module_css_default.backdrop,
3926
+ className: clsx(InputBar_module_css_default.backdrop, textareaDisabled && InputBar_module_css_default.backdropDisabled),
3825
3927
  "data-input-backdrop": true,
3928
+ "data-disabled": textareaDisabled || void 0,
3826
3929
  children: backdrop
3827
3930
  }),
3828
3931
  (0, react_jsx_runtime.jsx)("textarea", {
@@ -3964,12 +4067,6 @@ window.__ModuleLoader__.load({
3964
4067
  })
3965
4068
  ]
3966
4069
  }),
3967
- preview !== null && (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_attachment.ImageLightbox, {
3968
- src: preview.previewUrl,
3969
- alt: preview.file.name || t("image.original"),
3970
- labels: lightboxLabels(t),
3971
- onClose: closePreview
3972
- }),
3973
4070
  footer
3974
4071
  ]
3975
4072
  });
@@ -3986,12 +4083,12 @@ window.__ModuleLoader__.load({
3986
4083
  document.head.appendChild(tag);
3987
4084
  }
3988
4085
  var EnterBehaviorRow_module_css_default = {
4086
+ "chevron": "T1PP_q_chevron",
3989
4087
  "desc": "T1PP_q_desc",
4088
+ "row": "T1PP_q_row",
3990
4089
  "rowText": "T1PP_q_rowText",
3991
4090
  "selector": "T1PP_q_selector",
3992
- "chevron": "T1PP_q_chevron",
3993
- "title": "T1PP_q_title",
3994
- "row": "T1PP_q_row"
4091
+ "title": "T1PP_q_title"
3995
4092
  };
3996
4093
  //#endregion
3997
4094
  //#region lib/types/client/settings/EnterBehaviorRow.js
@@ -4054,7 +4151,7 @@ window.__ModuleLoader__.load({
4054
4151
  }
4055
4152
  //#endregion
4056
4153
  //#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-conversation/src/client/chat/MessageItem.module.css.mjs
4057
- const css$15 = ".gdEzaW_userRow{flex-direction:column;align-items:flex-end;gap:6px;display:flex}.gdEzaW_userStack{flex-direction:column;align-items:flex-end;gap:8px;min-width:0;max-width:min(525px,82%);display:flex}.gdEzaW_bubble{background:var(--dsw-specific-bubble);max-width:100%;color:var(--dsw-alias-label-primary);border-radius:22px;padding:10px 16px;font-size:16px;line-height:24px}.gdEzaW_contextRow,.gdEzaW_compactionRow{padding:2px 0}.gdEzaW_compactionButton{width:100%;min-width:0;height:24px;color:inherit;font:inherit;text-align:left;background:0 0;border:none;border-radius:6px;align-items:center;padding:0;display:flex}.gdEzaW_compactionButton:not(:disabled){cursor:pointer}.gdEzaW_compactionButton:not(:disabled):hover{background:var(--dsw-alias-interactive-bg-hover)}.gdEzaW_compactionLeading{width:16px;height:16px;color:var(--dsw-alias-label-secondary);flex:none;place-items:center;margin-right:6px;display:inline-grid}.gdEzaW_compactionContextIcon,.gdEzaW_compactionDisclosureIcon{grid-area:1/1;justify-content:center;align-items:center;display:inline-flex}.gdEzaW_compactionDisclosureIcon,.gdEzaW_compactionButton:not(:disabled):hover .gdEzaW_compactionContextIcon,.gdEzaW_compactionButton:not(:disabled):focus-visible .gdEzaW_compactionContextIcon{opacity:0}.gdEzaW_compactionButton:not(:disabled):hover .gdEzaW_compactionDisclosureIcon,.gdEzaW_compactionButton:not(:disabled):focus-visible .gdEzaW_compactionDisclosureIcon{opacity:1}.gdEzaW_compactionTitle{color:var(--dsw-alias-label-primary-dimmed);flex:none;font-size:14px;line-height:24px}.gdEzaW_compactionSep{background:var(--dsw-alias-label-caption);border-radius:1px;flex:none;width:2px;height:2px;margin:0 8px}.gdEzaW_compactionSummary{min-width:0;color:var(--dsw-alias-label-tertiary);text-overflow:ellipsis;white-space:nowrap;flex:auto;font-size:14px;line-height:24px;overflow:hidden}.gdEzaW_compactionBody{color:var(--dsw-alias-label-tertiary);padding:4px 0 4px 22px;font-size:14px;line-height:24px}.gdEzaW_retryRow{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:20px}.gdEzaW_retrySummary{width:fit-content;color:inherit;cursor:pointer;user-select:none;border-radius:3px;align-items:center;gap:7px;padding:2px 0;list-style:none;display:inline-flex}.gdEzaW_retrySummary::-webkit-details-marker{display:none}.gdEzaW_retrySummary:after{content:\"\";opacity:.8;border-bottom:1.5px solid;border-right:1.5px solid;width:6px;height:6px;transition:transform .12s;transform:rotate(-45deg)}.gdEzaW_retrySummary:hover{color:var(--dsw-alias-label-secondary)}.gdEzaW_retrySummary:focus-visible{outline:1.5px solid var(--dsw-alias-button-info-fill);outline-offset:2px}.gdEzaW_retryText{color:inherit}.gdEzaW_retryRow[data-active] .gdEzaW_retryText{background:linear-gradient(90deg, var(--dsw-alias-label-tertiary) 0%, var(--dsw-alias-label-tertiary) 40%, var(--dsw-alias-label-secondary) 50%, var(--dsw-alias-label-tertiary) 60%, var(--dsw-alias-label-tertiary) 100%);color:#0000;background-position:100%;background-size:200% 100%;background-clip:text;animation:1.6s ease-in-out infinite gdEzaW_retry-shimmer}.gdEzaW_retryRow[open] .gdEzaW_retrySummary:after{transform:rotate(45deg)}.gdEzaW_retryDetails{overflow-wrap:anywhere;gap:2px;margin-top:3px;padding-left:14px;font-size:12px;line-height:18px;display:grid}.gdEzaW_retryDetailLabel{color:var(--dsw-alias-label-secondary)}.gdEzaW_turnErrorRow{grid-template-columns:10px minmax(0,1fr) auto;align-items:start;gap:8px;padding:2px 0;font-size:13px;line-height:20px;display:grid}.gdEzaW_turnErrorDot{margin-top:5px}.gdEzaW_turnErrorCopy{overflow-wrap:anywhere;min-width:0}.gdEzaW_turnErrorTitle{color:var(--dsw-alias-state-error-primary);margin-right:6px;font-weight:600}.gdEzaW_turnErrorMessage{color:var(--dsw-alias-label-secondary)}.gdEzaW_turnErrorCode{color:var(--dsw-alias-label-tertiary);font:var(--dsw-font-markdown-code-block-small)}.gdEzaW_maxTokensTitle{color:var(--dsw-alias-state-warn-primary);margin-right:6px;font-weight:600}@keyframes gdEzaW_retry-shimmer{0%{background-position:100%}to{background-position:0}}@media (prefers-reduced-motion:reduce){.gdEzaW_retryRow[data-active] .gdEzaW_retryText{color:inherit;background:0 0;animation:none}}.gdEzaW_refChip{color:var(--dsw-alias-label-primary);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}";
4154
+ const css$15 = ".gdEzaW_userRow{flex-direction:column;align-items:flex-end;gap:6px;display:flex}.gdEzaW_userStack{flex-direction:column;align-items:flex-end;gap:8px;min-width:0;max-width:min(525px,82%);display:flex}.gdEzaW_bubble{background:var(--dsw-specific-bubble);max-width:100%;color:var(--dsw-alias-label-primary);border-radius:22px;padding:10px 16px;font-size:16px;line-height:24px}.gdEzaW_referenceSummary{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}.gdEzaW_contextRow,.gdEzaW_compactionRow{padding:2px 0}.gdEzaW_compactionButton{width:100%;min-width:0;height:24px;color:inherit;font:inherit;text-align:left;background:0 0;border:none;border-radius:6px;align-items:center;padding:0;display:flex}.gdEzaW_compactionButton:not(:disabled){cursor:pointer}.gdEzaW_compactionButton:not(:disabled):hover{background:var(--dsw-alias-interactive-bg-hover)}.gdEzaW_compactionLeading{width:16px;height:16px;color:var(--dsw-alias-label-secondary);flex:none;place-items:center;margin-right:6px;display:inline-grid}.gdEzaW_compactionContextIcon,.gdEzaW_compactionDisclosureIcon{grid-area:1/1;justify-content:center;align-items:center;display:inline-flex}.gdEzaW_compactionDisclosureIcon,.gdEzaW_compactionButton:not(:disabled):hover .gdEzaW_compactionContextIcon,.gdEzaW_compactionButton:not(:disabled):focus-visible .gdEzaW_compactionContextIcon{opacity:0}.gdEzaW_compactionButton:not(:disabled):hover .gdEzaW_compactionDisclosureIcon,.gdEzaW_compactionButton:not(:disabled):focus-visible .gdEzaW_compactionDisclosureIcon{opacity:1}.gdEzaW_compactionTitle{color:var(--dsw-alias-label-primary-dimmed);flex:none;font-size:14px;line-height:24px}.gdEzaW_compactionSep{background:var(--dsw-alias-label-caption);border-radius:1px;flex:none;width:2px;height:2px;margin:0 8px}.gdEzaW_compactionSummary{min-width:0;color:var(--dsw-alias-label-tertiary);text-overflow:ellipsis;white-space:nowrap;flex:auto;font-size:14px;line-height:24px;overflow:hidden}.gdEzaW_compactionBody{color:var(--dsw-alias-label-tertiary);padding:4px 0 4px 22px;font-size:14px;line-height:24px}.gdEzaW_retryRow{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:20px}.gdEzaW_retrySummary{width:fit-content;color:inherit;cursor:pointer;user-select:none;border-radius:3px;align-items:center;gap:7px;padding:2px 0;list-style:none;display:inline-flex}.gdEzaW_retrySummary::-webkit-details-marker{display:none}.gdEzaW_retrySummary:after{content:\"\";opacity:.8;border-bottom:1.5px solid;border-right:1.5px solid;width:6px;height:6px;transition:transform .12s;transform:rotate(-45deg)}.gdEzaW_retrySummary:hover{color:var(--dsw-alias-label-secondary)}.gdEzaW_retrySummary:focus-visible{outline:1.5px solid var(--dsw-alias-button-info-fill);outline-offset:2px}.gdEzaW_retryText{color:inherit}.gdEzaW_retryRow[data-active] .gdEzaW_retryText{background:linear-gradient(90deg, var(--dsw-alias-label-tertiary) 0%, var(--dsw-alias-label-tertiary) 40%, var(--dsw-alias-label-secondary) 50%, var(--dsw-alias-label-tertiary) 60%, var(--dsw-alias-label-tertiary) 100%);color:#0000;background-position:100%;background-size:200% 100%;background-clip:text;animation:1.6s ease-in-out infinite gdEzaW_retry-shimmer}.gdEzaW_retryRow[open] .gdEzaW_retrySummary:after{transform:rotate(45deg)}.gdEzaW_retryDetails{overflow-wrap:anywhere;gap:2px;margin-top:3px;padding-left:14px;font-size:12px;line-height:18px;display:grid}.gdEzaW_retryDetailLabel{color:var(--dsw-alias-label-secondary)}.gdEzaW_turnErrorRow{grid-template-columns:10px minmax(0,1fr) auto;align-items:start;gap:8px;padding:2px 0;font-size:13px;line-height:20px;display:grid}.gdEzaW_turnErrorDot{margin-top:5px}.gdEzaW_turnErrorCopy{overflow-wrap:anywhere;min-width:0}.gdEzaW_turnErrorTitle{color:var(--dsw-alias-state-error-primary);margin-right:6px;font-weight:600}.gdEzaW_turnErrorMessage{color:var(--dsw-alias-label-secondary)}.gdEzaW_turnErrorCode{color:var(--dsw-alias-label-tertiary);font:var(--dsw-font-markdown-code-block-small)}.gdEzaW_maxTokensTitle{color:var(--dsw-alias-state-warn-primary);margin-right:6px;font-weight:600}@keyframes gdEzaW_retry-shimmer{0%{background-position:100%}to{background-position:0}}@media (prefers-reduced-motion:reduce){.gdEzaW_retryRow[data-active] .gdEzaW_retryText{color:inherit;background:0 0;animation:none}}.gdEzaW_refChip{color:var(--dsw-alias-state-business-primary);white-space:nowrap;vertical-align:baseline;align-items:center;gap:4px;margin:0 2px;font-weight:500;display:inline-flex}.gdEzaW_refIcon{flex:none}";
4058
4155
  const tagId$15 = "@deepseek-ai/dsh-client-ui-conversation/MessageItem.module.css";
4059
4156
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$15) + "]") === null) {
4060
4157
  const tag = document.createElement("style");
@@ -4064,33 +4161,35 @@ window.__ModuleLoader__.load({
4064
4161
  document.head.appendChild(tag);
4065
4162
  }
4066
4163
  var MessageItem_module_css_default = {
4067
- "retry-shimmer": "gdEzaW_retry-shimmer",
4068
- "retrySummary": "gdEzaW_retrySummary",
4069
- "retryText": "gdEzaW_retryText",
4164
+ "bubble": "gdEzaW_bubble",
4165
+ "compactionBody": "gdEzaW_compactionBody",
4166
+ "compactionButton": "gdEzaW_compactionButton",
4167
+ "compactionContextIcon": "gdEzaW_compactionContextIcon",
4168
+ "compactionDisclosureIcon": "gdEzaW_compactionDisclosureIcon",
4169
+ "compactionLeading": "gdEzaW_compactionLeading",
4070
4170
  "compactionRow": "gdEzaW_compactionRow",
4071
- "retryRow": "gdEzaW_retryRow",
4072
- "retryDetailLabel": "gdEzaW_retryDetailLabel",
4073
- "refChip": "gdEzaW_refChip",
4074
- "turnErrorTitle": "gdEzaW_turnErrorTitle",
4075
- "retryDetails": "gdEzaW_retryDetails",
4076
4171
  "compactionSep": "gdEzaW_compactionSep",
4077
- "turnErrorCopy": "gdEzaW_turnErrorCopy",
4078
- "turnErrorMessage": "gdEzaW_turnErrorMessage",
4079
- "compactionDisclosureIcon": "gdEzaW_compactionDisclosureIcon",
4080
- "contextRow": "gdEzaW_contextRow",
4081
4172
  "compactionSummary": "gdEzaW_compactionSummary",
4173
+ "compactionTitle": "gdEzaW_compactionTitle",
4174
+ "contextRow": "gdEzaW_contextRow",
4175
+ "maxTokensTitle": "gdEzaW_maxTokensTitle",
4176
+ "refChip": "gdEzaW_refChip",
4177
+ "refIcon": "gdEzaW_refIcon",
4178
+ "referenceSummary": "gdEzaW_referenceSummary",
4179
+ "retry-shimmer": "gdEzaW_retry-shimmer",
4180
+ "retryDetailLabel": "gdEzaW_retryDetailLabel",
4181
+ "retryDetails": "gdEzaW_retryDetails",
4182
+ "retryRow": "gdEzaW_retryRow",
4183
+ "retrySummary": "gdEzaW_retrySummary",
4184
+ "retryText": "gdEzaW_retryText",
4082
4185
  "turnErrorCode": "gdEzaW_turnErrorCode",
4186
+ "turnErrorCopy": "gdEzaW_turnErrorCopy",
4083
4187
  "turnErrorDot": "gdEzaW_turnErrorDot",
4188
+ "turnErrorMessage": "gdEzaW_turnErrorMessage",
4084
4189
  "turnErrorRow": "gdEzaW_turnErrorRow",
4085
- "maxTokensTitle": "gdEzaW_maxTokensTitle",
4086
- "compactionTitle": "gdEzaW_compactionTitle",
4087
- "compactionButton": "gdEzaW_compactionButton",
4088
- "bubble": "gdEzaW_bubble",
4089
- "userStack": "gdEzaW_userStack",
4090
- "compactionContextIcon": "gdEzaW_compactionContextIcon",
4091
- "compactionLeading": "gdEzaW_compactionLeading",
4092
- "compactionBody": "gdEzaW_compactionBody",
4093
- "userRow": "gdEzaW_userRow"
4190
+ "turnErrorTitle": "gdEzaW_turnErrorTitle",
4191
+ "userRow": "gdEzaW_userRow",
4192
+ "userStack": "gdEzaW_userStack"
4094
4193
  };
4095
4194
  //#endregion
4096
4195
  //#region lib/types/client/chat/CompactionItem.js
@@ -4162,29 +4261,29 @@ window.__ModuleLoader__.load({
4162
4261
  document.head.appendChild(tag);
4163
4262
  }
4164
4263
  var ContextBody_module_css_default = {
4165
- "filePath": "NM4-hq_filePath",
4166
- "fileAction": "NM4-hq_fileAction",
4264
+ "catalogNotice": "NM4-hq_catalogNotice",
4265
+ "entries": "NM4-hq_entries",
4266
+ "entry": "NM4-hq_entry",
4267
+ "entryDescription": "NM4-hq_entryDescription",
4167
4268
  "entryName": "NM4-hq_entryName",
4168
- "file": "NM4-hq_file",
4169
- "relaySender": "NM4-hq_relaySender",
4269
+ "field": "NM4-hq_field",
4270
+ "fieldKey": "NM4-hq_fieldKey",
4271
+ "fieldValue": "NM4-hq_fieldValue",
4170
4272
  "fields": "NM4-hq_fields",
4273
+ "file": "NM4-hq_file",
4274
+ "fileAction": "NM4-hq_fileAction",
4275
+ "filePath": "NM4-hq_filePath",
4276
+ "files": "NM4-hq_files",
4277
+ "recall": "NM4-hq_recall",
4171
4278
  "recallCounts": "NM4-hq_recallCounts",
4172
- "fieldValue": "NM4-hq_fieldValue",
4173
- "field": "NM4-hq_field",
4174
- "entries": "NM4-hq_entries",
4175
- "recalls": "NM4-hq_recalls",
4176
- "catalogNotice": "NM4-hq_catalogNotice",
4177
4279
  "recallLabel": "NM4-hq_recallLabel",
4178
- "fieldKey": "NM4-hq_fieldKey",
4280
+ "recalls": "NM4-hq_recalls",
4281
+ "relaySender": "NM4-hq_relaySender",
4282
+ "section": "NM4-hq_section",
4179
4283
  "sectionName": "NM4-hq_sectionName",
4180
- "recall": "NM4-hq_recall",
4284
+ "sectionText": "NM4-hq_sectionText",
4181
4285
  "sections": "NM4-hq_sections",
4182
- "entry": "NM4-hq_entry",
4183
- "text": "NM4-hq_text",
4184
- "entryDescription": "NM4-hq_entryDescription",
4185
- "files": "NM4-hq_files",
4186
- "section": "NM4-hq_section",
4187
- "sectionText": "NM4-hq_sectionText"
4286
+ "text": "NM4-hq_text"
4188
4287
  };
4189
4288
  //#endregion
4190
4289
  //#region lib/types/client/chat/ContextBody.js
@@ -4719,12 +4818,12 @@ window.__ModuleLoader__.load({
4719
4818
  document.head.appendChild(tag);
4720
4819
  }
4721
4820
  var ContextInjectionRow_module_css_default = {
4722
- "chevron": "pC0e7a_chevron",
4723
- "source": "pC0e7a_source",
4724
- "summary": "pC0e7a_summary",
4725
4821
  "body": "pC0e7a_body",
4822
+ "chevron": "pC0e7a_chevron",
4823
+ "root": "pC0e7a_root",
4726
4824
  "sep": "pC0e7a_sep",
4727
- "root": "pC0e7a_root"
4825
+ "source": "pC0e7a_source",
4826
+ "summary": "pC0e7a_summary"
4728
4827
  };
4729
4828
  //#endregion
4730
4829
  //#region lib/types/client/chat/ContextInjectionRow.js
@@ -4748,7 +4847,10 @@ window.__ModuleLoader__.load({
4748
4847
  });
4749
4848
  return (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.DisclosureRow, {
4750
4849
  className: ContextInjectionRow_module_css_default.root,
4751
- icon: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconBrowseOutline16, { size: 14 }),
4850
+ icon: provenance.role === "recall" ? (0, react_jsx_runtime.jsx)("span", {
4851
+ "data-context-recall-icon": true,
4852
+ children: (0, react_jsx_runtime.jsx)(ReferenceIcon, { kind: "session" })
4853
+ }) : (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconBrowseOutline16, { size: 14 }),
4752
4854
  chevronClassName: ContextInjectionRow_module_css_default.chevron,
4753
4855
  title: t(provenance.role === "recall" ? "message.contextRecall" : "message.contextInjection"),
4754
4856
  collapsedContent: provenance.label === null ? void 0 : (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
@@ -4819,11 +4921,11 @@ window.__ModuleLoader__.load({
4819
4921
  document.head.appendChild(tag);
4820
4922
  }
4821
4923
  var MessageIconActions_module_css_default = {
4924
+ "action": "p-xYUq_action",
4822
4925
  "actions": "p-xYUq_actions",
4823
- "timeStart": "p-xYUq_timeStart",
4824
4926
  "runTimeDot": "p-xYUq_runTimeDot",
4825
- "action": "p-xYUq_action",
4826
4927
  "timeEnd": "p-xYUq_timeEnd",
4928
+ "timeStart": "p-xYUq_timeStart",
4827
4929
  "visuallyHidden": "p-xYUq_visuallyHidden"
4828
4930
  };
4829
4931
  //#endregion
@@ -5072,28 +5174,62 @@ window.__ModuleLoader__.load({
5072
5174
  * scan as the composer, minus the lexicon: sent tokens were validated at
5073
5175
  * compose time, so shape alone decorates).
5074
5176
  */
5075
- function projectUserText(text) {
5076
- const re = /(^|\s)([/@][\w-]+)(?=\s|$)/g;
5077
- const parts = [];
5078
- let cursor = 0;
5177
+ function projectUserText(text, sessionLabels) {
5178
+ const ranges = [];
5179
+ for (const rawLabel of [...new Set(sessionLabels)].sort((a, b) => b.length - a.length)) {
5180
+ const label = `@${rawLabel}`;
5181
+ let start = text.indexOf(label);
5182
+ while (start >= 0) {
5183
+ ranges.push({
5184
+ start,
5185
+ end: start + label.length,
5186
+ label,
5187
+ kind: "session"
5188
+ });
5189
+ start = text.indexOf(label, start + label.length);
5190
+ }
5191
+ }
5192
+ const re = /(^|\s)(\/[\w-]+|@"[^"\n]+"|@[^\s]+)/gu;
5079
5193
  let m;
5080
5194
  while ((m = re.exec(text)) !== null) {
5081
5195
  const tokenStart = m.index + (m[1]?.length ?? 0);
5082
- const label = m[2] ?? "";
5196
+ const rawLabel = m[2] ?? "";
5197
+ const label = rawLabel.startsWith("@\"") ? rawLabel : rawLabel.replace(/[.,;:!?,。;:!?]+$/gu, "");
5198
+ if (label.length <= 1) continue;
5199
+ ranges.push({
5200
+ start: tokenStart,
5201
+ end: tokenStart + label.length,
5202
+ label,
5203
+ kind: "plain"
5204
+ });
5205
+ }
5206
+ ranges.sort((a, b) => a.start - b.start || (a.kind === b.kind ? b.end - a.end : a.kind === "session" ? -1 : 1));
5207
+ const parts = [];
5208
+ let cursor = 0;
5209
+ for (const range of ranges) {
5210
+ if (range.start < cursor) continue;
5211
+ const { start: tokenStart, end, label, kind } = range;
5083
5212
  if (tokenStart > cursor) parts.push((0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.MessageText, { text: text.slice(cursor, tokenStart) }, cursor));
5084
- parts.push((0, react_jsx_runtime.jsx)("span", {
5213
+ const referenceKind = kind === "session" ? "session" : label.startsWith("@") ? label.endsWith("/") ? "folder" : "file" : void 0;
5214
+ const displayLabel = referenceKind === void 0 ? label : referenceKind === "session" ? label.slice(1) : label.slice(1).replace(/^"|"$/gu, "").split(/[\\/]/u).filter(Boolean).at(-1) ?? label.slice(1);
5215
+ parts.push((0, react_jsx_runtime.jsxs)("span", {
5085
5216
  className: MessageItem_module_css_default.refChip,
5086
- "data-ref-chip": label.startsWith("@") ? "subagent" : "skill",
5087
- children: label
5217
+ "data-ref-chip": referenceKind ?? "skill",
5218
+ title: label,
5219
+ children: [referenceKind !== void 0 && (0, react_jsx_runtime.jsx)(ReferenceIcon, {
5220
+ kind: referenceKind,
5221
+ size: 16,
5222
+ className: MessageItem_module_css_default.refIcon
5223
+ }), displayLabel]
5088
5224
  }, tokenStart));
5089
- cursor = tokenStart + label.length;
5225
+ cursor = end;
5090
5226
  }
5091
5227
  if (parts.length === 0) return (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.MessageText, { text });
5092
5228
  if (cursor < text.length) parts.push((0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.MessageText, { text: text.slice(cursor) }, cursor));
5093
5229
  return (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: parts });
5094
5230
  }
5095
5231
  /** Right-aligned bubble shared by user and steering rows. */
5096
- function UserStyleBubble({ content, imageLoader, actions, pending = false, t }) {
5232
+ function UserStyleBubble({ content, renderMessageImages, actions, pending = false, referenceLabels = [], t }) {
5097
5233
  const { text, images, rest } = contentParts(content);
5098
5234
  const truncated = (total) => t("json.truncated", { total });
5099
5235
  const showBubble = text !== "" || rest.length > 0;
@@ -5103,19 +5239,24 @@ window.__ModuleLoader__.load({
5103
5239
  "data-time-hover-root": true,
5104
5240
  children: [(0, react_jsx_runtime.jsxs)("div", {
5105
5241
  className: MessageItem_module_css_default.userStack,
5106
- children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_attachment.ImageGallery, {
5107
- images,
5108
- load: imageLoader,
5109
- align: "end",
5110
- labels: messageImageLabels(t)
5111
- }), showBubble && (0, react_jsx_runtime.jsxs)("div", {
5112
- className: MessageItem_module_css_default.bubble,
5113
- children: [projectUserText(text), rest.map((block, i) => (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.JsonBlock, {
5114
- label: t("message.extraBlock"),
5115
- payload: block,
5116
- truncatedLabel: truncated
5117
- }, i))]
5118
- })]
5242
+ children: [
5243
+ renderMessageImages({
5244
+ images,
5245
+ align: "end"
5246
+ }),
5247
+ showBubble && (0, react_jsx_runtime.jsxs)("div", {
5248
+ className: MessageItem_module_css_default.bubble,
5249
+ children: [projectUserText(text, referenceLabels), rest.map((block, i) => (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.JsonBlock, {
5250
+ label: t("message.extraBlock"),
5251
+ payload: block,
5252
+ truncatedLabel: truncated
5253
+ }, i))]
5254
+ }),
5255
+ referenceLabels.length > 0 && (0, react_jsx_runtime.jsx)("div", {
5256
+ className: MessageItem_module_css_default.referenceSummary,
5257
+ children: t("message.referenceSummary", { labels: referenceLabels.join(t("message.referenceSeparator")) })
5258
+ })
5259
+ ]
5119
5260
  }), actions?.(text)]
5120
5261
  });
5121
5262
  }
@@ -5125,10 +5266,10 @@ window.__ModuleLoader__.load({
5125
5266
  * @param props - Pending message content and conversation translator.
5126
5267
  * @returns the pending steering bubble.
5127
5268
  */
5128
- function PendingSteeringBubble({ content, loadImage, t }) {
5269
+ function PendingSteeringBubble({ content, renderMessageImages, t }) {
5129
5270
  return (0, react_jsx_runtime.jsx)(UserStyleBubble, {
5130
5271
  content,
5131
- imageLoader: loadImage ?? (() => Promise.reject(new Error(t("image.serviceUnavailable")))),
5272
+ renderMessageImages,
5132
5273
  pending: true,
5133
5274
  t,
5134
5275
  actions: (text) => (0, react_jsx_runtime.jsx)(MessageIconActions, {
@@ -5140,11 +5281,12 @@ window.__ModuleLoader__.load({
5140
5281
  });
5141
5282
  }
5142
5283
  /** User and admitted-steering keyed Chat renderer. */
5143
- const UserMessageNodeView = (0, react.memo)(function UserMessageNodeView({ node, loadImage, t }) {
5284
+ const UserMessageNodeView = (0, react.memo)(function UserMessageNodeView({ node, renderMessageImages, t }) {
5144
5285
  const data = node.data;
5145
5286
  return (0, react_jsx_runtime.jsx)(UserStyleBubble, {
5146
5287
  content: data.content,
5147
- imageLoader: loadImage,
5288
+ renderMessageImages,
5289
+ ...data.referenceLabels === void 0 ? {} : { referenceLabels: data.referenceLabels },
5148
5290
  t,
5149
5291
  actions: (text) => (0, react_jsx_runtime.jsx)(MessageIconActions, {
5150
5292
  text,
@@ -5207,7 +5349,7 @@ window.__ModuleLoader__.load({
5207
5349
  });
5208
5350
  //#endregion
5209
5351
  //#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-conversation/src/client/chat/ChatView.module.css.mjs
5210
- const css$11 = ".Md3f7G_root{flex-direction:column;flex:auto;min-height:0;display:flex;position:relative}.Md3f7G_scroll{min-height:0;padding:16px calc(var(--dsh-composer-side-clearance) + 16px);flex:auto;overflow-y:auto}[data-conversation-scroll] .Md3f7G_root{flex:none;height:auto;min-height:auto}[data-conversation-scroll] .Md3f7G_scroll{flex:none;min-height:auto;overflow:visible}.Md3f7G_column{max-width:var(--dsh-chat-content-width);flex-direction:column;gap:16px;width:100%;margin:0 auto;display:flex}.Md3f7G_flowItem{min-width:0}.Md3f7G_flowItem:empty{display:none}.Md3f7G_callRow{border-radius:6px}.Md3f7G_turnStatus{height:26px;font:var(--dsw-font-s-strong-14);white-space:nowrap;background:linear-gradient(90deg, var(--dsw-static-deepseek-500) 0%, var(--dsw-static-deepseek-500) 40%, var(--dsw-static-deepseek-200) 50%, var(--dsw-static-deepseek-500) 60%, var(--dsw-static-deepseek-500) 100%);color:#0000;-webkit-text-fill-color:transparent;background-position:100% 0;background-size:250% 100%;-webkit-background-clip:text;background-clip:text;flex:none;align-self:flex-start;align-items:center;animation:1.8s linear infinite Md3f7G_dsh-turn-status-shimmer;display:inline-flex}.Md3f7G_turnStatusClock{font:var(--dsw-font-xs-13);font-variant-numeric:tabular-nums;color:var(--dsw-alias-label-caption);-webkit-text-fill-color:var(--dsw-alias-label-caption);margin-left:8px;font-weight:400}@keyframes Md3f7G_dsh-turn-status-shimmer{to{background-position:0 0}}@media (prefers-reduced-motion:reduce){.Md3f7G_turnStatus{background-position:0 0;background-size:100% 100%;animation:none}}.Md3f7G_hint{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}.Md3f7G_openError{color:var(--dsw-alias-state-error-primary);font-size:12px;line-height:18px}.Md3f7G_older{justify-content:center;display:flex}.Md3f7G_older button{color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-interactive-bg-hover-solid);cursor:pointer;border:none;border-radius:14px;padding:4px 12px;font-size:12px}.Md3f7G_older button:disabled{cursor:default;opacity:.6}.Md3f7G_toBottomSlot{z-index:8;height:0;padding-right:max(0px, calc((100% - var(--dsh-chat-content-width)) / 2));pointer-events:none;justify-content:flex-end;display:flex;position:sticky;bottom:16px}[data-conversation-scroll] .Md3f7G_toBottomSlot{bottom:calc(var(--dsh-composer-height,152px) + 16px)}.Md3f7G_toBottom{border:1px solid var(--dsw-alias-border-l2);width:34px;height:34px;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-button-floating-fill);box-shadow:var(--dsw-shadow-lv2);cursor:pointer;pointer-events:auto;border-radius:100px;justify-content:center;align-items:center;margin-top:-34px;padding:0;display:flex}.Md3f7G_toBottom:hover{background:var(--dsw-alias-button-floating-hover)}";
5352
+ const css$11 = ".Md3f7G_root{flex-direction:column;flex:auto;min-height:0;display:flex;position:relative}.Md3f7G_scroll{min-height:0;padding:16px calc(var(--dsh-composer-side-clearance) + 16px);flex:auto;overflow-y:auto}[data-conversation-scroll] .Md3f7G_root{flex:none;height:auto;min-height:auto}[data-conversation-scroll] .Md3f7G_scroll{flex:none;min-height:auto;overflow:visible}.Md3f7G_column{max-width:var(--dsh-chat-content-width);flex-direction:column;gap:16px;width:100%;margin:0 auto;display:flex}.Md3f7G_flowItem{min-width:0}.Md3f7G_flowItem:empty{display:none}.Md3f7G_callRow{border-radius:6px}.Md3f7G_turnStatus{height:26px;font:var(--dsw-font-s-strong-14);white-space:nowrap;background:linear-gradient(90deg, var(--dsw-static-deepseek-500) 0%, var(--dsw-static-deepseek-500) 40%, var(--dsw-static-deepseek-200) 50%, var(--dsw-static-deepseek-500) 60%, var(--dsw-static-deepseek-500) 100%);color:#0000;-webkit-text-fill-color:transparent;background-position:100% 0;background-size:250% 100%;-webkit-background-clip:text;background-clip:text;flex:none;align-self:flex-start;align-items:center;animation:1.8s linear infinite Md3f7G_dsh-turn-status-shimmer;display:inline-flex}.Md3f7G_turnStatusClock{font:var(--dsw-font-xs-13);font-variant-numeric:tabular-nums;color:var(--dsw-alias-label-caption);-webkit-text-fill-color:var(--dsw-alias-label-caption);margin-left:8px;font-weight:400}@keyframes Md3f7G_dsh-turn-status-shimmer{to{background-position:0 0}}@media (prefers-reduced-motion:reduce){.Md3f7G_turnStatus{background-position:0 0;background-size:100% 100%;animation:none}}.Md3f7G_hint{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}.Md3f7G_openError{color:var(--dsw-alias-state-error-primary);font-size:12px;line-height:18px}.Md3f7G_older{justify-content:center;display:flex}.Md3f7G_older button{color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-interactive-bg-hover-solid);cursor:pointer;border:none;border-radius:14px;padding:4px 12px;font-size:12px}.Md3f7G_older button:disabled{cursor:default;opacity:.6}.Md3f7G_toBottomSlot{z-index:8;height:0;padding-right:max(0px, calc((100% - var(--dsh-chat-content-width)) / 2));pointer-events:none;justify-content:flex-end;display:flex;position:sticky;bottom:16px}[data-conversation-scroll] .Md3f7G_toBottomSlot{bottom:calc(var(--dsh-composer-height,152px) + 16px)}.Md3f7G_toBottom{border:1px solid var(--dsw-alias-border-l2);width:34px;height:34px;color:var(--dsw-alias-label-primary);background:var(--dsw-alias-button-floating-fill);box-shadow:var(--dsw-shadow-lv2);cursor:pointer;pointer-events:auto;border-radius:100px;justify-content:center;align-items:center;margin-top:-34px;padding:0;display:flex}.Md3f7G_toBottom:hover{background:var(--dsw-alias-button-floating-hover)}.Md3f7G_modalAction{min-width:72px}";
5211
5353
  const tagId$11 = "@deepseek-ai/dsh-client-ui-conversation/ChatView.module.css";
5212
5354
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$11) + "]") === null) {
5213
5355
  const tag = document.createElement("style");
@@ -5217,24 +5359,25 @@ window.__ModuleLoader__.load({
5217
5359
  document.head.appendChild(tag);
5218
5360
  }
5219
5361
  var ChatView_module_css_default = {
5220
- "dsh-turn-status-shimmer": "Md3f7G_dsh-turn-status-shimmer",
5221
- "turnStatusClock": "Md3f7G_turnStatusClock",
5222
5362
  "callRow": "Md3f7G_callRow",
5363
+ "column": "Md3f7G_column",
5364
+ "dsh-turn-status-shimmer": "Md3f7G_dsh-turn-status-shimmer",
5365
+ "flowItem": "Md3f7G_flowItem",
5223
5366
  "hint": "Md3f7G_hint",
5224
- "root": "Md3f7G_root",
5225
- "openError": "Md3f7G_openError",
5367
+ "modalAction": "Md3f7G_modalAction",
5226
5368
  "older": "Md3f7G_older",
5227
- "flowItem": "Md3f7G_flowItem",
5369
+ "openError": "Md3f7G_openError",
5370
+ "root": "Md3f7G_root",
5371
+ "scroll": "Md3f7G_scroll",
5372
+ "toBottom": "Md3f7G_toBottom",
5228
5373
  "toBottomSlot": "Md3f7G_toBottomSlot",
5229
5374
  "turnStatus": "Md3f7G_turnStatus",
5230
- "column": "Md3f7G_column",
5231
- "toBottom": "Md3f7G_toBottom",
5232
- "scroll": "Md3f7G_scroll"
5375
+ "turnStatusClock": "Md3f7G_turnStatusClock"
5233
5376
  };
5234
5377
  //#endregion
5235
5378
  //#region lib/types/client/chat/ChatNodeSeat.js
5236
5379
  /** Subscribe and dispatch one stable Context key without observing sibling Nodes. */
5237
- const ChatNodeSeat = (0, react.memo)(function ChatNodeSeat({ nodeKey, selectedCallId, cwd, openFile, inspectCall, forkAt, loadImage, fileMentions, useSession, renderSlot, t }) {
5380
+ const ChatNodeSeat = (0, react.memo)(function ChatNodeSeat({ nodeKey, selectedCallId, cwd, openFile, inspectCall, forkAt, renderMessageImages, fileMentions, useSession, renderSlot, t }) {
5238
5381
  const node = useSession((snapshot) => snapshot.chat.nodes.get(nodeKey));
5239
5382
  const routedNode = node;
5240
5383
  const owner = (0, react.useMemo)(() => node === void 0 ? null : {
@@ -5243,7 +5386,7 @@ window.__ModuleLoader__.load({
5243
5386
  openFile,
5244
5387
  inspectCall,
5245
5388
  forkAt,
5246
- loadImage,
5389
+ renderMessageImages,
5247
5390
  fileMentions
5248
5391
  }, [
5249
5392
  node,
@@ -5252,7 +5395,7 @@ window.__ModuleLoader__.load({
5252
5395
  openFile,
5253
5396
  inspectCall,
5254
5397
  forkAt,
5255
- loadImage,
5398
+ renderMessageImages,
5256
5399
  fileMentions
5257
5400
  ]);
5258
5401
  if (routedNode === void 0 || owner === null) return null;
@@ -5330,6 +5473,15 @@ window.__ModuleLoader__.load({
5330
5473
  scrollTop: scrollport.scrollTop
5331
5474
  };
5332
5475
  }
5476
+ /** Host/OS refusal text for the file-open dialog; empty throws keep a locale fallback. */
5477
+ function openFailureMessage(error, fallback) {
5478
+ const message = error instanceof Error ? error.message : String(error);
5479
+ return message === "" ? fallback : message;
5480
+ }
5481
+ /** ProducedFiles opens the session workspace as `.`. */
5482
+ function isFolderOpenPath(path) {
5483
+ return path === ".";
5484
+ }
5333
5485
  function runningTurnStartTime(timeline) {
5334
5486
  let latest = null;
5335
5487
  for (const turn of timeline.turns.values()) if (turn.status === "open" && turn.start !== void 0) latest = turn.start.time;
@@ -5378,7 +5530,35 @@ window.__ModuleLoader__.load({
5378
5530
  const hasMore = useSession((s) => s.hasMore);
5379
5531
  const loadingOlder = useSession((s) => s.loadingOlder);
5380
5532
  const selectedCallId = useStore((s) => s.selection?.callId);
5533
+ const [fileOpenError, setFileOpenError] = (0, react.useState)(null);
5534
+ const [fileOpenBusy, setFileOpenBusy] = (0, react.useState)(false);
5535
+ const fileOpenRequest = (0, react.useRef)(0);
5536
+ const requestOpenFile = (0, react.useCallback)((path) => {
5537
+ const id = ++fileOpenRequest.current;
5538
+ setFileOpenBusy(true);
5539
+ openFile(path).then(() => {
5540
+ if (id !== fileOpenRequest.current) return;
5541
+ setFileOpenError(null);
5542
+ setFileOpenBusy(false);
5543
+ }, (error) => {
5544
+ if (id !== fileOpenRequest.current) return;
5545
+ setFileOpenError({
5546
+ path,
5547
+ message: openFailureMessage(error, t(isFolderOpenPath(path) ? "fileOpen.folderUnknown" : "fileOpen.unknown"))
5548
+ });
5549
+ setFileOpenBusy(false);
5550
+ });
5551
+ }, [openFile, t]);
5552
+ const closeFileOpenError = (0, react.useCallback)(() => {
5553
+ fileOpenRequest.current += 1;
5554
+ setFileOpenError(null);
5555
+ setFileOpenBusy(false);
5556
+ }, []);
5381
5557
  const pendingSteering = (0, react.useMemo)(() => inbox.filter((item) => item.placement === "steering"), [inbox]);
5558
+ const renderMessageImages = (0, react.useCallback)((owner) => renderSlot("conversation.message.images", {
5559
+ ...owner,
5560
+ loadImage
5561
+ }), [loadImage, renderSlot]);
5382
5562
  const runningTurnStart = (0, react.useMemo)(() => runningTurnStartTime(timeline), [timeline]);
5383
5563
  const listRef = (0, react.useRef)(null);
5384
5564
  const columnRef = (0, react.useRef)(null);
@@ -5538,9 +5718,9 @@ window.__ModuleLoader__.load({
5538
5718
  }
5539
5719
  loadOlder();
5540
5720
  };
5541
- return (0, react_jsx_runtime.jsx)("div", {
5721
+ return (0, react_jsx_runtime.jsxs)("div", {
5542
5722
  className: ChatView_module_css_default.root,
5543
- children: (0, react_jsx_runtime.jsxs)("div", {
5723
+ children: [(0, react_jsx_runtime.jsxs)("div", {
5544
5724
  ref: listRef,
5545
5725
  className: ChatView_module_css_default.scroll,
5546
5726
  children: [(0, react_jsx_runtime.jsxs)("div", {
@@ -5573,10 +5753,10 @@ window.__ModuleLoader__.load({
5573
5753
  useSession,
5574
5754
  selectedCallId,
5575
5755
  cwd,
5576
- openFile,
5756
+ openFile: requestOpenFile,
5577
5757
  inspectCall,
5578
5758
  forkAt,
5579
- loadImage,
5759
+ renderMessageImages,
5580
5760
  fileMentions,
5581
5761
  renderSlot,
5582
5762
  t
@@ -5587,7 +5767,7 @@ window.__ModuleLoader__.load({
5587
5767
  }),
5588
5768
  pendingSteering.map((item) => (0, react_jsx_runtime.jsx)(PendingSteeringBubble, {
5589
5769
  content: item.content,
5590
- loadImage,
5770
+ renderMessageImages,
5591
5771
  t
5592
5772
  }, item.id))
5593
5773
  ]
@@ -5605,7 +5785,38 @@ window.__ModuleLoader__.load({
5605
5785
  children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutline14, {})
5606
5786
  })
5607
5787
  })]
5608
- })
5788
+ }), fileOpenError !== null && (0, react_jsx_runtime.jsx)(FileOpenErrorDialog, {
5789
+ path: fileOpenError.path,
5790
+ message: fileOpenError.message,
5791
+ busy: fileOpenBusy,
5792
+ onClose: closeFileOpenError,
5793
+ onRetry: () => {
5794
+ requestOpenFile(fileOpenError.path);
5795
+ },
5796
+ t
5797
+ })]
5798
+ });
5799
+ }
5800
+ /** In-page Host open-path refusal: the wire reason plus a retry of the same path. */
5801
+ function FileOpenErrorDialog({ path, message, busy, onClose, onRetry, t }) {
5802
+ return (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
5803
+ open: true,
5804
+ onClose,
5805
+ closeLabel: t("close"),
5806
+ title: t(isFolderOpenPath(path) ? "fileOpen.folderTitle" : "fileOpen.title"),
5807
+ description: message,
5808
+ footer: (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
5809
+ variant: "outline",
5810
+ className: ChatView_module_css_default.modalAction,
5811
+ onClick: onClose,
5812
+ children: t("cancel")
5813
+ }), (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
5814
+ variant: "primary",
5815
+ className: ChatView_module_css_default.modalAction,
5816
+ disabled: busy,
5817
+ onClick: onRetry,
5818
+ children: t("retry")
5819
+ })] })
5609
5820
  });
5610
5821
  }
5611
5822
  //#endregion
@@ -5706,15 +5917,15 @@ window.__ModuleLoader__.load({
5706
5917
  document.head.appendChild(tag);
5707
5918
  }
5708
5919
  var ApprovalPanel_module_css_default = {
5709
- "reject": "bqrRRG_reject",
5710
5920
  "actionRow": "bqrRRG_actionRow",
5711
- "dot": "bqrRRG_dot",
5712
- "strip": "bqrRRG_strip",
5713
5921
  "body": "bqrRRG_body",
5714
- "command": "bqrRRG_command",
5715
5922
  "card": "bqrRRG_card",
5923
+ "command": "bqrRRG_command",
5924
+ "dot": "bqrRRG_dot",
5925
+ "headline": "bqrRRG_headline",
5926
+ "reject": "bqrRRG_reject",
5716
5927
  "root": "bqrRRG_root",
5717
- "headline": "bqrRRG_headline"
5928
+ "strip": "bqrRRG_strip"
5718
5929
  };
5719
5930
  //#endregion
5720
5931
  //#region lib/types/client/skeleton/ApprovalPanel.js
@@ -5849,6 +6060,7 @@ window.__ModuleLoader__.load({
5849
6060
  "image.fileTooLarge": "单张图片不能超过 {size}",
5850
6061
  "image.totalTooLarge": "图片总大小超过 {size},请移除部分图片",
5851
6062
  "image.tooManyPixels": "图片分辨率过大,请压缩后重试",
6063
+ "image.dimensionTooLarge": "图片宽高不能超过 {size}px,请缩小后重试",
5852
6064
  "image.modelUnsupported": "当前模型不支持图片,请切换支持图片的模型",
5853
6065
  "image.subagentUnsupported": "子智能体会话暂不支持图片",
5854
6066
  "image.sendFailed": "图片发送失败({reason}),请重新添加图片后再试",
@@ -5894,9 +6106,15 @@ window.__ModuleLoader__.load({
5894
6106
  "chat.loadError": "历史加载失败:{message}({code})",
5895
6107
  "chat.loadOlder": "加载更早",
5896
6108
  "chat.toBottom": "回到底部",
6109
+ "fileOpen.title": "无法打开文件",
6110
+ "fileOpen.unknown": "无法打开此文件",
6111
+ "fileOpen.folderTitle": "无法打开文件夹",
6112
+ "fileOpen.folderUnknown": "无法打开此文件夹",
5897
6113
  "message.extraBlock": "附加内容块",
5898
6114
  "message.contextInjection": "上下文注入",
5899
6115
  "message.contextRecall": "跨会话召回",
6116
+ "message.referenceSummary": "引用会话 · {labels}",
6117
+ "message.referenceSeparator": "、",
5900
6118
  "message.context.instructions.loaded": "已载入",
5901
6119
  "message.context.instructions.added": "已新增",
5902
6120
  "message.context.instructions.updated": "已更新",
@@ -5936,6 +6154,7 @@ window.__ModuleLoader__.load({
5936
6154
  "command.failed": "命令失败",
5937
6155
  "command.done": "已完成",
5938
6156
  "command.title": "命令",
6157
+ "command.imagesUnsupported": "/{command} 不接受图片附件,请先移除图片",
5939
6158
  "approval.waiting": "等待审批",
5940
6159
  "approval.detail.aria": "审批详情",
5941
6160
  "approval.escalation": "工具 {toolName} 请求越权执行",
@@ -6014,6 +6233,7 @@ window.__ModuleLoader__.load({
6014
6233
  "image.fileTooLarge": "Each image must be smaller than {size}",
6015
6234
  "image.totalTooLarge": "Images exceed {size} in total; remove some and try again",
6016
6235
  "image.tooManyPixels": "Image resolution is too high; compress it and try again",
6236
+ "image.dimensionTooLarge": "Image sides must be at most {size}px; downscale it and try again",
6017
6237
  "image.modelUnsupported": "The current model does not support images; switch to a model that does",
6018
6238
  "image.subagentUnsupported": "Subagent sessions do not support images yet",
6019
6239
  "image.sendFailed": "Sending images failed ({reason}); re-add them and try again",
@@ -6059,9 +6279,15 @@ window.__ModuleLoader__.load({
6059
6279
  "chat.loadError": "Failed to load history: {message} ({code})",
6060
6280
  "chat.loadOlder": "Load earlier",
6061
6281
  "chat.toBottom": "Back to bottom",
6282
+ "fileOpen.title": "Couldn’t open file",
6283
+ "fileOpen.unknown": "Couldn’t open this file",
6284
+ "fileOpen.folderTitle": "Couldn’t open folder",
6285
+ "fileOpen.folderUnknown": "Couldn’t open this folder",
6062
6286
  "message.extraBlock": "Extra content block",
6063
6287
  "message.contextInjection": "Context injection",
6064
6288
  "message.contextRecall": "Session recall",
6289
+ "message.referenceSummary": "Referenced session · {labels}",
6290
+ "message.referenceSeparator": ", ",
6065
6291
  "message.context.instructions.loaded": "loaded",
6066
6292
  "message.context.instructions.added": "added",
6067
6293
  "message.context.instructions.updated": "updated",
@@ -6101,6 +6327,7 @@ window.__ModuleLoader__.load({
6101
6327
  "command.failed": "Command failed",
6102
6328
  "command.done": "Completed",
6103
6329
  "command.title": "Command",
6330
+ "command.imagesUnsupported": "/{command} does not accept image attachments; remove them first",
6104
6331
  "approval.waiting": "Waiting for approval",
6105
6332
  "approval.detail.aria": "Approval details",
6106
6333
  "approval.escalation": "Tool {toolName} requests privileged execution",
@@ -6153,21 +6380,21 @@ window.__ModuleLoader__.load({
6153
6380
  document.head.appendChild(tag);
6154
6381
  }
6155
6382
  var TodoPanel_module_css_default = {
6156
- "item": "lXshSW_item",
6157
- "header": "lXshSW_header",
6158
- "todo-progress-spin": "lXshSW_todo-progress-spin",
6159
- "glyph": "lXshSW_glyph",
6160
- "content": "lXshSW_content",
6161
- "glyphProgress": "lXshSW_glyphProgress",
6162
6383
  "body": "lXshSW_body",
6163
- "glyphCompleted": "lXshSW_glyphCompleted",
6164
- "root": "lXshSW_root",
6165
6384
  "chevron": "lXshSW_chevron",
6385
+ "content": "lXshSW_content",
6386
+ "glyph": "lXshSW_glyph",
6387
+ "glyphCompleted": "lXshSW_glyphCompleted",
6388
+ "glyphPending": "lXshSW_glyphPending",
6389
+ "glyphProgress": "lXshSW_glyphProgress",
6390
+ "header": "lXshSW_header",
6391
+ "item": "lXshSW_item",
6166
6392
  "lead": "lXshSW_lead",
6167
6393
  "list": "lXshSW_list",
6168
6394
  "progress": "lXshSW_progress",
6169
- "glyphPending": "lXshSW_glyphPending",
6170
- "title": "lXshSW_title"
6395
+ "root": "lXshSW_root",
6396
+ "title": "lXshSW_title",
6397
+ "todo-progress-spin": "lXshSW_todo-progress-spin"
6171
6398
  };
6172
6399
  //#endregion
6173
6400
  //#region lib/types/client/skeleton/TodoPanel.js
@@ -6360,18 +6587,18 @@ window.__ModuleLoader__.load({
6360
6587
  document.head.appendChild(tag);
6361
6588
  }
6362
6589
  var QueueDock_module_css_default = {
6363
- "chevron": "_7yHdaG_chevron",
6364
- "row": "_7yHdaG_row",
6365
- "editor": "_7yHdaG_editor",
6590
+ "action": "_7yHdaG_action",
6366
6591
  "actions": "_7yHdaG_actions",
6367
- "list": "_7yHdaG_list",
6368
- "preview": "_7yHdaG_preview",
6592
+ "chevron": "_7yHdaG_chevron",
6593
+ "count": "_7yHdaG_count",
6369
6594
  "dock": "_7yHdaG_dock",
6370
- "action": "_7yHdaG_action",
6595
+ "editor": "_7yHdaG_editor",
6596
+ "header": "_7yHdaG_header",
6371
6597
  "lead": "_7yHdaG_lead",
6598
+ "list": "_7yHdaG_list",
6372
6599
  "panel": "_7yHdaG_panel",
6373
- "count": "_7yHdaG_count",
6374
- "header": "_7yHdaG_header"
6600
+ "preview": "_7yHdaG_preview",
6601
+ "row": "_7yHdaG_row"
6375
6602
  };
6376
6603
  //#endregion
6377
6604
  //#region lib/types/client/queue/QueueDock.js
@@ -6629,23 +6856,23 @@ window.__ModuleLoader__.load({
6629
6856
  document.head.appendChild(tag);
6630
6857
  }
6631
6858
  var HeroShell_module_css_default = {
6632
- "folder": "pXSMma_folder",
6633
- "previewBadge": "pXSMma_previewBadge",
6634
- "modalError": "pXSMma_modalError",
6635
- "workspace": "pXSMma_workspace",
6859
+ "body": "pXSMma_body",
6636
6860
  "chevron": "pXSMma_chevron",
6637
- "modalAction": "pXSMma_modalAction",
6638
- "workspaceRow": "pXSMma_workspaceRow",
6639
- "headline": "pXSMma_headline",
6640
- "stack": "pXSMma_stack",
6641
6861
  "fish": "pXSMma_fish",
6642
- "root": "pXSMma_root",
6643
6862
  "fishHitbox": "pXSMma_fishHitbox",
6644
- "modalInput": "pXSMma_modalInput",
6863
+ "folder": "pXSMma_folder",
6864
+ "headline": "pXSMma_headline",
6865
+ "headlineText": "pXSMma_headlineText",
6645
6866
  "hero-fish-swim": "pXSMma_hero-fish-swim",
6867
+ "modalAction": "pXSMma_modalAction",
6868
+ "modalError": "pXSMma_modalError",
6869
+ "modalInput": "pXSMma_modalInput",
6870
+ "previewBadge": "pXSMma_previewBadge",
6871
+ "root": "pXSMma_root",
6872
+ "stack": "pXSMma_stack",
6873
+ "workspace": "pXSMma_workspace",
6646
6874
  "workspaceLabel": "pXSMma_workspaceLabel",
6647
- "headlineText": "pXSMma_headlineText",
6648
- "body": "pXSMma_body"
6875
+ "workspaceRow": "pXSMma_workspaceRow"
6649
6876
  };
6650
6877
  //#endregion
6651
6878
  //#region lib/types/client/skeleton/EmptyHero.js
@@ -6755,7 +6982,7 @@ window.__ModuleLoader__.load({
6755
6982
  * @param props - see {@link HeroShellProps}.
6756
6983
  * @returns the centered hero element tree.
6757
6984
  */
6758
- function HeroShell({ t, children }) {
6985
+ function HeroShell({ t, renderSlot, children }) {
6759
6986
  return (0, react_jsx_runtime.jsxs)("div", {
6760
6987
  className: HeroShell_module_css_default.root,
6761
6988
  children: [(0, react_jsx_runtime.jsxs)("div", {
@@ -6765,10 +6992,13 @@ window.__ModuleLoader__.load({
6765
6992
  children: [
6766
6993
  (0, react_jsx_runtime.jsx)("span", {
6767
6994
  className: HeroShell_module_css_default.fishHitbox,
6768
- children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.FishLogo, {
6995
+ children: renderSlot("conversation.hero.brand.mark", {
6769
6996
  size: 34,
6770
6997
  className: HeroShell_module_css_default.fish
6771
- })
6998
+ }, { fallback: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.FishLogo, {
6999
+ size: 34,
7000
+ className: HeroShell_module_css_default.fish
7001
+ }) })
6772
7002
  }),
6773
7003
  (0, react_jsx_runtime.jsx)("span", {
6774
7004
  className: HeroShell_module_css_default.headlineText,
@@ -6795,28 +7025,28 @@ window.__ModuleLoader__.load({
6795
7025
  document.head.appendChild(tag);
6796
7026
  }
6797
7027
  var ConversationRoot_module_css_default = {
6798
- "titleRow": "wSkVaW_titleRow",
6799
- "viewArea": "wSkVaW_viewArea",
6800
- "headerUtilities": "wSkVaW_headerUtilities",
6801
7028
  "composerHero": "wSkVaW_composerHero",
6802
- "crumbs": "wSkVaW_crumbs",
6803
7029
  "composerSeat": "wSkVaW_composerSeat",
6804
- "tabs": "wSkVaW_tabs",
6805
- "heroGlow": "wSkVaW_heroGlow",
6806
- "tabActive": "wSkVaW_tabActive",
6807
- "crumbSep": "wSkVaW_crumbSep",
7030
+ "composerStack": "wSkVaW_composerStack",
7031
+ "crumb": "wSkVaW_crumb",
6808
7032
  "crumbCurrent": "wSkVaW_crumbCurrent",
7033
+ "crumbSeg": "wSkVaW_crumbSeg",
7034
+ "crumbSep": "wSkVaW_crumbSep",
7035
+ "crumbs": "wSkVaW_crumbs",
7036
+ "header": "wSkVaW_header",
6809
7037
  "headerActions": "wSkVaW_headerActions",
6810
- "composerStack": "wSkVaW_composerStack",
7038
+ "headerHidden": "wSkVaW_headerHidden",
7039
+ "headerUtilities": "wSkVaW_headerUtilities",
7040
+ "heroGlow": "wSkVaW_heroGlow",
7041
+ "heroWorkspaceRow": "wSkVaW_heroWorkspaceRow",
7042
+ "root": "wSkVaW_root",
6811
7043
  "scrollBody": "wSkVaW_scrollBody",
6812
7044
  "tab": "wSkVaW_tab",
6813
- "crumbSeg": "wSkVaW_crumbSeg",
6814
- "root": "wSkVaW_root",
6815
- "headerHidden": "wSkVaW_headerHidden",
7045
+ "tabActive": "wSkVaW_tabActive",
7046
+ "tabs": "wSkVaW_tabs",
6816
7047
  "titleCluster": "wSkVaW_titleCluster",
6817
- "header": "wSkVaW_header",
6818
- "crumb": "wSkVaW_crumb",
6819
- "heroWorkspaceRow": "wSkVaW_heroWorkspaceRow"
7048
+ "titleRow": "wSkVaW_titleRow",
7049
+ "viewArea": "wSkVaW_viewArea"
6820
7050
  };
6821
7051
  //#endregion
6822
7052
  //#region lib/types/client/skeleton/ConversationRoot.js
@@ -6915,7 +7145,10 @@ window.__ModuleLoader__.load({
6915
7145
  className: clsx(ConversationRoot_module_css_default.composerStack, hero && ConversationRoot_module_css_default.composerHero),
6916
7146
  children: [
6917
7147
  hero && (0, react_jsx_runtime.jsx)(HeroGlow, { className: ConversationRoot_module_css_default.heroGlow }),
6918
- hero && (0, react_jsx_runtime.jsx)(HeroShell, { t }),
7148
+ hero && (0, react_jsx_runtime.jsx)(HeroShell, {
7149
+ t,
7150
+ renderSlot
7151
+ }),
6919
7152
  hero && heroWorkspaceRow,
6920
7153
  zone !== void 0 && renderSlot("conversation.input.dock", zone),
6921
7154
  inputBar
@@ -7092,15 +7325,15 @@ window.__ModuleLoader__.load({
7092
7325
  document.head.appendChild(tag);
7093
7326
  }
7094
7327
  var DetailsPanel_module_css_default = {
7095
- "code": "ydkMvW_code",
7096
- "close": "ydkMvW_close",
7097
7328
  "body": "ydkMvW_body",
7098
- "section": "ydkMvW_section",
7329
+ "close": "ydkMvW_close",
7330
+ "code": "ydkMvW_code",
7099
7331
  "empty": "ydkMvW_empty",
7100
7332
  "header": "ydkMvW_header",
7101
- "title": "ydkMvW_title",
7102
7333
  "root": "ydkMvW_root",
7103
- "sectionLabel": "ydkMvW_sectionLabel"
7334
+ "section": "ydkMvW_section",
7335
+ "sectionLabel": "ydkMvW_sectionLabel",
7336
+ "title": "ydkMvW_title"
7104
7337
  };
7105
7338
  //#endregion
7106
7339
  //#region lib/types/client/skeleton/DetailsPanel.js
@@ -7374,7 +7607,8 @@ window.__ModuleLoader__.load({
7374
7607
  stepStartTime: context.start?.event.time ?? null,
7375
7608
  firstTokenTime: state.firstTokenTime ?? null,
7376
7609
  completedTime: event.time
7377
- }
7610
+ },
7611
+ ...event.data.interrupted === true ? { interrupted: true } : {}
7378
7612
  };
7379
7613
  }
7380
7614
  const location = context.start?.location ?? context.matches.at(-1)?.location;
@@ -7642,6 +7876,76 @@ window.__ModuleLoader__.load({
7642
7876
  function orderedVisible(nodes) {
7643
7877
  return nodes.filter((node) => node.visibility === "visible").sort((left, right) => left.anchorSeq - right.anchorSeq || left.key.localeCompare(right.key));
7644
7878
  }
7879
+ function referenceMessageSeq(node) {
7880
+ const candidate = node;
7881
+ return candidate.kind === "user" || candidate.kind === "steering" ? candidate.data.seq : void 0;
7882
+ }
7883
+ function followingRecall(node) {
7884
+ const candidate = node;
7885
+ if (candidate.kind !== "context") return void 0;
7886
+ return {
7887
+ messageSeq: candidate.data.seq - 1,
7888
+ labels: (0, _deepseek_ai_dsh_client_runtime_client.sessionRecallLabels)(candidate.data.source)
7889
+ };
7890
+ }
7891
+ function withReferenceLabels(node, labels) {
7892
+ const candidate = node;
7893
+ if (candidate.kind !== "user" && candidate.kind !== "steering") return node;
7894
+ const current = candidate.data.referenceLabels ?? EMPTY_KEYS;
7895
+ const hasLabels = Object.hasOwn(candidate.data, "referenceLabels");
7896
+ if (sameReferences$1(current, labels) && hasLabels === labels.length > 0) return node;
7897
+ const data = { ...candidate.data };
7898
+ if (labels.length === 0) delete data.referenceLabels;
7899
+ else data.referenceLabels = labels;
7900
+ return {
7901
+ ...candidate,
7902
+ data
7903
+ };
7904
+ }
7905
+ /** Associates a direct message with the sourced recall event that immediately follows it. */
7906
+ var ReferenceLabelProjector = class {
7907
+ messagesBySeq = /* @__PURE__ */ new Map();
7908
+ labelsByMessageSeq = /* @__PURE__ */ new Map();
7909
+ replace(nodes) {
7910
+ this.messagesBySeq.clear();
7911
+ this.labelsByMessageSeq.clear();
7912
+ for (const node of nodes) {
7913
+ const messageSeq = referenceMessageSeq(node);
7914
+ if (messageSeq !== void 0) this.messagesBySeq.set(messageSeq, node.key);
7915
+ const recall = followingRecall(node);
7916
+ if (recall !== void 0 && recall.labels.length > 0) this.labelsByMessageSeq.set(recall.messageSeq, recall.labels);
7917
+ }
7918
+ return nodes.map((node) => {
7919
+ const messageSeq = referenceMessageSeq(node);
7920
+ return messageSeq === void 0 ? node : withReferenceLabels(node, this.labelsByMessageSeq.get(messageSeq) ?? EMPTY_KEYS);
7921
+ });
7922
+ }
7923
+ apply(upserts, store) {
7924
+ const byKey = new Map(upserts.map((node) => [node.key, node]));
7925
+ const affected = /* @__PURE__ */ new Set();
7926
+ for (const node of upserts) {
7927
+ const messageSeq = referenceMessageSeq(node);
7928
+ if (messageSeq !== void 0) {
7929
+ this.messagesBySeq.set(messageSeq, node.key);
7930
+ affected.add(messageSeq);
7931
+ }
7932
+ const recall = followingRecall(node);
7933
+ if (recall === void 0) continue;
7934
+ const current = this.labelsByMessageSeq.get(recall.messageSeq);
7935
+ if (recall.labels.length === 0) this.labelsByMessageSeq.delete(recall.messageSeq);
7936
+ else this.labelsByMessageSeq.set(recall.messageSeq, current !== void 0 && sameReferences$1(current, recall.labels) ? current : recall.labels);
7937
+ affected.add(recall.messageSeq);
7938
+ }
7939
+ for (const messageSeq of affected) {
7940
+ const key = this.messagesBySeq.get(messageSeq);
7941
+ if (key === void 0) continue;
7942
+ const node = byKey.get(key) ?? store.get(key);
7943
+ if (node === void 0) continue;
7944
+ byKey.set(key, withReferenceLabels(node, this.labelsByMessageSeq.get(messageSeq) ?? EMPTY_KEYS));
7945
+ }
7946
+ return [...byKey.values()];
7947
+ }
7948
+ };
7645
7949
  const EMPTY_CONTRIBUTION = {
7646
7950
  anchorSeq: 0,
7647
7951
  nodes: EMPTY_LIST,
@@ -7832,6 +8136,7 @@ window.__ModuleLoader__.load({
7832
8136
  store = new MutableChatNodeStore();
7833
8137
  locations = new MutableChatLocationIndex();
7834
8138
  legacy = new LegacySliceBuilder();
8139
+ referenceLabels = new ReferenceLabelProjector();
7835
8140
  order = EMPTY_KEYS;
7836
8141
  empty;
7837
8142
  constructor() {
@@ -7841,28 +8146,30 @@ window.__ModuleLoader__.load({
7841
8146
  });
7842
8147
  }
7843
8148
  replace(input) {
7844
- this.store.replace(input.nodes);
7845
- this.order = orderedVisible(input.nodes).map((node) => node.key);
8149
+ const nodes = this.referenceLabels.replace(input.nodes);
8150
+ this.store.replace(nodes);
8151
+ this.order = orderedVisible(nodes).map((node) => node.key);
7846
8152
  this.locations.rebuild(this.order, this.store);
7847
- return this.snapshot(input.timeline, this.legacy.replace(input.nodes, input.timeline));
8153
+ return this.snapshot(input.timeline, this.legacy.replace(nodes, input.timeline));
7848
8154
  }
7849
8155
  apply(input) {
8156
+ const upserts = this.referenceLabels.apply(input.upserts, this.store);
7850
8157
  let structural = false;
7851
8158
  const contentOnly = [];
7852
- for (const node of input.upserts) {
8159
+ for (const node of upserts) {
7853
8160
  const previous = this.store.get(node.key);
7854
8161
  const nodeStructural = previous === void 0 || previous.anchorSeq !== node.anchorSeq || previous.visibility !== node.visibility || locationIdentity(previous.location) !== locationIdentity(node.location);
7855
8162
  structural ||= nodeStructural;
7856
8163
  if (!nodeStructural) contentOnly.push(node);
7857
8164
  }
7858
- this.store.upsert(input.upserts);
8165
+ this.store.upsert(upserts);
7859
8166
  if (structural) {
7860
8167
  const next = orderedVisible(this.store.values()).map((node) => node.key);
7861
8168
  this.order = sameReferences$1(this.order, next) ? this.order : next;
7862
8169
  this.locations.rebuild(this.order, this.store);
7863
8170
  }
7864
8171
  this.locations.touch(contentOnly);
7865
- return this.snapshot(input.timeline, this.legacy.apply(input.upserts, input.timeline));
8172
+ return this.snapshot(input.timeline, this.legacy.apply(upserts, input.timeline));
7866
8173
  }
7867
8174
  snapshot(timeline, legacy = this.legacy.replace(EMPTY_LIST, timeline)) {
7868
8175
  return {
@@ -8953,14 +9260,14 @@ window.__ModuleLoader__.load({
8953
9260
  document.head.appendChild(tag);
8954
9261
  }
8955
9262
  var ReasoningRow_module_css_default = {
8956
- "leading": "QWLzlG_leading",
8957
- "dsh-reasoning-row-sweep": "QWLzlG_dsh-reasoning-row-sweep",
8958
9263
  "chevron": "QWLzlG_chevron",
8959
- "separator": "QWLzlG_separator",
8960
- "thinkBody": "QWLzlG_thinkBody",
9264
+ "dsh-reasoning-row-sweep": "QWLzlG_dsh-reasoning-row-sweep",
9265
+ "leading": "QWLzlG_leading",
9266
+ "root": "QWLzlG_root",
8961
9267
  "row": "QWLzlG_row",
9268
+ "separator": "QWLzlG_separator",
8962
9269
  "summary": "QWLzlG_summary",
8963
- "root": "QWLzlG_root",
9270
+ "thinkBody": "QWLzlG_thinkBody",
8964
9271
  "title": "QWLzlG_title"
8965
9272
  };
8966
9273
  //#endregion
@@ -9046,16 +9353,15 @@ window.__ModuleLoader__.load({
9046
9353
  document.head.appendChild(tag);
9047
9354
  }
9048
9355
  var AssistantMarkdown_module_css_default = {
9049
- "body": "Sxvs8a_body",
9050
9356
  "actions": "Sxvs8a_actions",
9051
- "stopped": "Sxvs8a_stopped",
9052
- "root": "Sxvs8a_root"
9357
+ "body": "Sxvs8a_body",
9358
+ "root": "Sxvs8a_root",
9359
+ "stopped": "Sxvs8a_stopped"
9053
9360
  };
9054
9361
  //#endregion
9055
9362
  //#region lib/types/client/chat/AssistantMarkdown.js
9056
9363
  /** Reasoning block as the Think variant summary row (figma 39:28304). */
9057
- const AssistantMarkdown = (0, react.memo)(function AssistantMarkdown({ blocks, streaming, interrupted, loadImage, mentions, t }) {
9058
- const imageLoader = loadImage ?? (() => Promise.reject(new Error(t("image.serviceUnavailable"))));
9364
+ const AssistantMarkdown = (0, react.memo)(function AssistantMarkdown({ blocks, streaming, interrupted, renderMessageImages, mentions, t }) {
9059
9365
  const codeLabels = (0, react.useMemo)(() => ({
9060
9366
  copyLabel: t("copy"),
9061
9367
  copiedLabel: t("copied")
@@ -9091,12 +9397,10 @@ window.__ModuleLoader__.load({
9091
9397
  group.push(next);
9092
9398
  i += 1;
9093
9399
  }
9094
- rendered.push((0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_attachment.ImageGallery, {
9095
- images: group,
9096
- load: imageLoader,
9097
- align: "start",
9098
- labels: messageImageLabels(t)
9099
- }, start));
9400
+ rendered.push((0, react_jsx_runtime.jsx)(react.Fragment, { children: renderMessageImages({
9401
+ images: group.map(({ attachment }) => ({ attachment })),
9402
+ align: "start"
9403
+ }) }, start));
9100
9404
  break;
9101
9405
  }
9102
9406
  case "tool-call": break;
@@ -9122,7 +9426,7 @@ window.__ModuleLoader__.load({
9122
9426
  //#endregion
9123
9427
  //#region lib/types/client/chat/AssistantNodeView.js
9124
9428
  /** Streaming, settled, and interrupted Assistant states share one keyed renderer instance. */
9125
- const AssistantNodeView = (0, react.memo)(function AssistantNodeView({ node, useTurnData, openFile, loadImage, fileMentions, t }) {
9429
+ const AssistantNodeView = (0, react.memo)(function AssistantNodeView({ node, useTurnData, openFile, renderMessageImages, fileMentions, t }) {
9126
9430
  const data = node.data;
9127
9431
  const turn = node.location.kind === "turn" || node.location.kind === "step" ? node.location.turn : void 0;
9128
9432
  const tail = useTurnData("turn-tail");
@@ -9145,7 +9449,7 @@ window.__ModuleLoader__.load({
9145
9449
  blocks: data.blocks,
9146
9450
  streaming: data.status === "running",
9147
9451
  interrupted: data.status === "interrupted",
9148
- loadImage,
9452
+ renderMessageImages,
9149
9453
  mentions,
9150
9454
  t
9151
9455
  });
@@ -9162,14 +9466,14 @@ window.__ModuleLoader__.load({
9162
9466
  document.head.appendChild(tag);
9163
9467
  }
9164
9468
  var GenericCommandCard_module_css_default = {
9165
- "root": "_Xvjua_root",
9166
- "dsh-command-row-sweep": "_Xvjua_dsh-command-row-sweep",
9167
- "separator": "_Xvjua_separator",
9168
9469
  "body": "_Xvjua_body",
9169
- "row": "_Xvjua_row",
9470
+ "chevron": "_Xvjua_chevron",
9471
+ "dsh-command-row-sweep": "_Xvjua_dsh-command-row-sweep",
9170
9472
  "leading": "_Xvjua_leading",
9473
+ "root": "_Xvjua_root",
9474
+ "row": "_Xvjua_row",
9475
+ "separator": "_Xvjua_separator",
9171
9476
  "summary": "_Xvjua_summary",
9172
- "chevron": "_Xvjua_chevron",
9173
9477
  "title": "_Xvjua_title"
9174
9478
  };
9175
9479
  //#endregion
@@ -9589,6 +9893,10 @@ window.__ModuleLoader__.load({
9589
9893
  kind: "list",
9590
9894
  scope: "session"
9591
9895
  },
9896
+ "conversation.hero.brand.mark": {
9897
+ kind: "single",
9898
+ scope: "root"
9899
+ },
9592
9900
  "conversation.hero.workspace": {
9593
9901
  kind: "single",
9594
9902
  scope: "root"
@@ -9662,6 +9970,10 @@ window.__ModuleLoader__.load({
9662
9970
  name: "conversation.composer.bar",
9663
9971
  locale: NS,
9664
9972
  children: {
9973
+ "conversation.input.attachments": {
9974
+ kind: "single",
9975
+ scope: "session-maybe"
9976
+ },
9665
9977
  "conversation.input.plan": {
9666
9978
  kind: "single",
9667
9979
  scope: "session"
@@ -9714,6 +10026,7 @@ window.__ModuleLoader__.load({
9714
10026
  inputTriggers.toggleSource("command", {
9715
10027
  trigger: "/",
9716
10028
  query: "",
10029
+ quoted: false,
9717
10030
  position: snapshot.draft.slice(0, selection.start).trim() === "" ? "leading" : "inline",
9718
10031
  span: {
9719
10032
  ...selection,
@@ -9750,11 +10063,17 @@ window.__ModuleLoader__.load({
9750
10063
  order: 0,
9751
10064
  label: () => t("view.chat"),
9752
10065
  locale: NS,
9753
- children: { "conversation.chat.node": {
9754
- kind: "keyed",
9755
- scope: "session",
9756
- inject: CHAT_NODE_INJECT
9757
- } },
10066
+ children: {
10067
+ "conversation.chat.node": {
10068
+ kind: "keyed",
10069
+ scope: "session",
10070
+ inject: CHAT_NODE_INJECT
10071
+ },
10072
+ "conversation.message.images": {
10073
+ kind: "single",
10074
+ scope: "session"
10075
+ }
10076
+ },
9758
10077
  store: chatStore,
9759
10078
  inject: (sessionId, actions) => {
9760
10079
  const conversation = concreteConversation(ctx);
@@ -9767,7 +10086,7 @@ window.__ModuleLoader__.load({
9767
10086
  fileMentions: (owner) => ctx.get("chatFileMentions")?.forClosing(owner),
9768
10087
  openFile: (path) => {
9769
10088
  const cwd = sessions.list.getSnapshot().byId[sessionId]?.cwd;
9770
- workspaces.openPath((0, _deepseek_ai_dsh_client_runtime_client.resolveWorkspacePath)(cwd, path)).catch(() => {});
10089
+ return workspaces.openPath((0, _deepseek_ai_dsh_client_runtime_client.resolveWorkspacePath)(cwd, path));
9771
10090
  },
9772
10091
  loadOlder: () => {
9773
10092
  scoped.loadOlder();