dsh-model-everything 0.5.2 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/client.js CHANGED
@@ -29,9 +29,13 @@ window.__ModuleLoader__.load({
29
29
  TOOL_NAMES: () => TOOL_NAMES,
30
30
  WHITEBOARD_ID: () => WHITEBOARD_ID,
31
31
  WHITEBOARD_SAMPLE: () => WHITEBOARD_SAMPLE,
32
+ annotationPanel: () => annotationPanel,
32
33
  default: () => factory,
33
34
  mountWhiteboard: () => mountWhiteboard,
35
+ onMessageSent: () => onMessageSent,
36
+ setPendingBlock: () => setPendingBlock,
34
37
  themeMode: () => themeMode,
38
+ updateDockLayer: () => updateDockLayer,
35
39
  viewFor: () => viewFor,
36
40
  whiteboardFor: () => whiteboardFor
37
41
  });
@@ -1726,12 +1730,12 @@ window.__ModuleLoader__.load({
1726
1730
  }
1727
1731
 
1728
1732
  // src/render/symbol.ts
1729
- function cubicPoint(curve, t) {
1730
- const u = 1 - t;
1733
+ function cubicPoint(curve, t2) {
1734
+ const u = 1 - t2;
1731
1735
  const a = u * u * u;
1732
- const b = 3 * u * u * t;
1733
- const c = 3 * u * t * t;
1734
- const d = t * t * t;
1736
+ const b = 3 * u * u * t2;
1737
+ const c = 3 * u * t2 * t2;
1738
+ const d = t2 * t2 * t2;
1735
1739
  return {
1736
1740
  x: a * curve.from.x + b * curve.c1.x + c * curve.c2.x + d * curve.to.x,
1737
1741
  y: a * curve.from.y + b * curve.c1.y + c * curve.c2.y + d * curve.to.y
@@ -2081,6 +2085,7 @@ window.__ModuleLoader__.load({
2081
2085
  const text2 = textOf(node);
2082
2086
  shapes.push({
2083
2087
  kind: "box",
2088
+ id: node.id,
2084
2089
  x: box.x,
2085
2090
  y: box.y,
2086
2091
  width: box.width,
@@ -3497,7 +3502,7 @@ window.__ModuleLoader__.load({
3497
3502
  caption: (shape, colours) => {
3498
3503
  const colour = colours[shape.colour];
3499
3504
  const lines = shape.lines.map((line, index) => '<tspan x="' + n(shape.x) + '" dy="' + (index === 0 ? 0 : 15) + '">' + escape(line) + "</tspan>").join("");
3500
- return '<text x="' + n(shape.x) + '" y="' + n(shape.y + 11) + '" font-size="10" text-anchor="middle" fill="' + colour + '">' + lines + "</text>";
3505
+ return '<text x="' + n(shape.x) + '" y="' + n(shape.y + 11) + '" font-size="10" fill="' + colour + '">' + lines + "</text>";
3501
3506
  }
3502
3507
  };
3503
3508
  function dash(shape) {
@@ -3568,7 +3573,9 @@ window.__ModuleLoader__.load({
3568
3573
  dropped += 1;
3569
3574
  continue;
3570
3575
  }
3571
- body.push(writer(shape, colours));
3576
+ const drawn = writer(shape, colours);
3577
+ const nodeId = shape.id;
3578
+ body.push(shape.kind === "box" && typeof nodeId === "string" ? '<g data-node-id="' + escape(nodeId) + '">' + drawn + "</g>" : drawn);
3572
3579
  }
3573
3580
  const header = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ' + n(canvas.width) + " " + n(canvas.height) + '" width="' + n(canvas.width) + '" height="' + n(canvas.height) + '" role="img"' + (label === void 0 ? "" : ' aria-label="' + escape(label) + '"') + ' font-family="system-ui, -apple-system, Segoe UI, sans-serif">';
3574
3581
  const background = '<rect x="0" y="0" width="' + n(canvas.width) + '" height="' + n(canvas.height) + '" fill="' + colours.background + '" />';
@@ -3681,8 +3688,409 @@ window.__ModuleLoader__.load({
3681
3688
  };
3682
3689
  }
3683
3690
 
3691
+ // src/annotation.ts
3692
+ function annotationBlock(annotations) {
3693
+ const count = annotations.length;
3694
+ const lines = [
3695
+ "Diagram annotations - " + String(count) + (count === 1 ? " item" : " items") + " (numbers match the picture).",
3696
+ 'Please answer each item separately, and start each answer with "Annotation N:".'
3697
+ ];
3698
+ const caption = (annotations[0]?.caption ?? "").trim();
3699
+ if (caption !== "") lines.push("Drawing: " + caption);
3700
+ annotations.forEach((annotation, index) => {
3701
+ const label = (annotation.label ?? "").trim();
3702
+ const node = label === "" || label === annotation.nodeId ? annotation.nodeId : label + " (" + annotation.nodeId + ")";
3703
+ const note = (annotation.note ?? "").trim();
3704
+ lines.push("");
3705
+ lines.push("Diagram note [" + String(index + 1) + "] node " + node + " - " + (note === "" ? "(marked, no note)" : note));
3706
+ });
3707
+ lines.push("", "Question:");
3708
+ return lines.join(String.fromCharCode(10));
3709
+ }
3710
+ var COMPOSER_MARKS = [
3711
+ "[data-focus-flow] textarea",
3712
+ "textarea[data-focus-flow]",
3713
+ '[data-focus-flow] [contenteditable="true"]',
3714
+ '[data-focus-flow][contenteditable="true"]',
3715
+ // No marker on this host - measured, not assumed. Everything this plugin writes carries
3716
+ // `data-dme-own`, so what remains is somebody else's writing surface.
3717
+ "textarea:not([data-dme-own])",
3718
+ '[contenteditable="true"]:not([data-dme-own])'
3719
+ ];
3720
+ function findComposer(doc) {
3721
+ if (doc === void 0) return void 0;
3722
+ try {
3723
+ for (const mark of COMPOSER_MARKS) {
3724
+ const found = doc.querySelector(mark);
3725
+ if (found !== null && typeof found === "object") return found;
3726
+ }
3727
+ const marked = doc.querySelector("[data-focus-flow]");
3728
+ if (marked !== null && typeof marked === "object") {
3729
+ const inner = marked.querySelector?.('textarea, [contenteditable="true"]');
3730
+ if (inner !== null && inner !== void 0 && typeof inner === "object") return inner;
3731
+ }
3732
+ return void 0;
3733
+ } catch {
3734
+ return void 0;
3735
+ }
3736
+ }
3737
+ function eventOf(type, init) {
3738
+ const scope = globalThis;
3739
+ if (scope.Event === void 0) return void 0;
3740
+ try {
3741
+ return new scope.Event(type, init);
3742
+ } catch {
3743
+ return void 0;
3744
+ }
3745
+ }
3746
+ function setValue(element, next) {
3747
+ const scope = globalThis;
3748
+ for (const ctor of [scope.HTMLTextAreaElement, scope.HTMLInputElement]) {
3749
+ const descriptor = ctor === void 0 ? void 0 : Object.getOwnPropertyDescriptor(ctor.prototype, "value");
3750
+ if (descriptor !== void 0 && typeof descriptor.set === "function") {
3751
+ descriptor.set.call(element, next);
3752
+ return;
3753
+ }
3754
+ }
3755
+ element.value = next;
3756
+ }
3757
+ function fillComposer(doc, text2) {
3758
+ const composer = findComposer(doc);
3759
+ if (composer === void 0) return "no-composer";
3760
+ const isField = typeof composer.value === "string" || composer.tagName === "TEXTAREA" || composer.tagName === "INPUT";
3761
+ if (isField) {
3762
+ const current = typeof composer.value === "string" ? composer.value : "";
3763
+ setValue(composer, current.trim() === "" ? text2 : current.replace(/\s*$/, "") + "\n\n" + text2);
3764
+ } else {
3765
+ if (composer.focus !== void 0) composer.focus();
3766
+ const editing = globalThis;
3767
+ const escapeHtml = (value) => value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
3768
+ const insertHtml = () => {
3769
+ const command = editing.document?.execCommand;
3770
+ if (command === void 0 || editing.document === void 0) return false;
3771
+ const html = text2.split(String.fromCharCode(10)).map(escapeHtml).join("<br>");
3772
+ return command.call(editing.document, "insertHTML", false, html) === true;
3773
+ };
3774
+ const insertLines = () => {
3775
+ const command = editing.document?.execCommand;
3776
+ if (command === void 0 || editing.document === void 0) return false;
3777
+ const lines = text2.split(String.fromCharCode(10));
3778
+ for (let index = 0; index < lines.length; index += 1) {
3779
+ if (index > 0 && command.call(editing.document, "insertParagraph", false, "") !== true) return false;
3780
+ if (lines[index] !== "" && command.call(editing.document, "insertText", false, lines[index]) !== true) return false;
3781
+ }
3782
+ return true;
3783
+ };
3784
+ const inserted = insertHtml() || insertLines();
3785
+ if (!inserted) {
3786
+ const current = typeof composer.textContent === "string" ? composer.textContent : "";
3787
+ composer.textContent = current.trim() === "" ? text2 : current.replace(/\s*$/, "") + "\n\n" + text2;
3788
+ }
3789
+ }
3790
+ const input = eventOf("input", { bubbles: true });
3791
+ if (input !== void 0 && composer.dispatchEvent !== void 0) composer.dispatchEvent(input);
3792
+ if (composer.focus !== void 0) composer.focus();
3793
+ return "filled";
3794
+ }
3795
+ function submitComposer(doc) {
3796
+ const composer = findComposer(doc);
3797
+ if (composer === void 0 || composer.dispatchEvent === void 0) return false;
3798
+ const scope = globalThis;
3799
+ if (scope.KeyboardEvent === void 0) return false;
3800
+ try {
3801
+ composer.dispatchEvent(new scope.KeyboardEvent("keydown", { key: "Enter", code: "Enter", bubbles: true, cancelable: true }));
3802
+ return true;
3803
+ } catch {
3804
+ return false;
3805
+ }
3806
+ }
3807
+ function composerRect(doc) {
3808
+ const composer = findComposer(doc);
3809
+ const inner = composer?.querySelector?.('textarea, [contenteditable="true"]');
3810
+ const surface = inner !== null && inner !== void 0 && typeof inner === "object" ? inner : composer;
3811
+ const measure2 = surface?.getBoundingClientRect;
3812
+ if (surface === void 0 || typeof measure2 !== "function") return void 0;
3813
+ try {
3814
+ const rect = measure2.call(surface);
3815
+ return { left: rect.left, top: rect.top, width: rect.width, height: rect.height };
3816
+ } catch {
3817
+ return void 0;
3818
+ }
3819
+ }
3820
+ function prependBlock(document, annotations, caption) {
3821
+ if (annotations.length === 0) return "";
3822
+ const block = annotationBlock(annotations.map((annotation) => ({ ...annotation, caption })));
3823
+ const composer = findComposer(document);
3824
+ if (composer === void 0) return "\u6CA1\u627E\u5230\u8F93\u5165\u6846\uFF1A\u5148\u628A\u56FE\u8D34\u8FDB\u4F1A\u8BDD\uFF0C\u6216\u624B\u52A8\u590D\u5236\u8FD9\u6BB5\u6587\u5B57";
3825
+ const isField = typeof composer.value === "string" || composer.tagName === "TEXTAREA" || composer.tagName === "INPUT";
3826
+ if (isField) {
3827
+ const current = typeof composer.value === "string" ? composer.value : "";
3828
+ setValue(composer, current.trim() === "" ? block : block + String.fromCharCode(10, 10) + current);
3829
+ } else if (fillComposer(document, block) === "no-composer") {
3830
+ return "\u6CA1\u627E\u5230\u8F93\u5165\u6846\uFF1A\u5148\u628A\u56FE\u8D34\u8FDB\u4F1A\u8BDD\uFF0C\u6216\u624B\u52A8\u590D\u5236\u8FD9\u6BB5\u6587\u5B57";
3831
+ }
3832
+ const input = eventOf("input", { bubbles: true });
3833
+ if (input !== void 0 && composer.dispatchEvent !== void 0) composer.dispatchEvent(input);
3834
+ return "\u5DF2\u653E\u5165\u8F93\u5165\u6846\uFF08" + String(annotations.length) + " \u6761\u56FE\u6CE8\uFF09";
3835
+ }
3836
+ function withoutEmptyQuestion(block) {
3837
+ return block.replace(/\n+Question:\s*$/, "");
3838
+ }
3839
+
3840
+ // src/transcript.ts
3841
+ var TRANSCRIPT_MARKER = "Diagram annotations -";
3842
+ var QUESTION = "Question:";
3843
+ var HANDLED = "data-dme-annotated";
3844
+ var ORIGINAL = "data-dme-annotation-text";
3845
+ var SELECTOR = "div, p, span, li";
3846
+ var BORDER = "1px solid var(--dsw-alias-border-l1, rgba(127,127,127,0.35))";
3847
+ function annotationCountOf(text2) {
3848
+ const found = /Diagram annotations - (\d+)/.exec(text2);
3849
+ return found === null ? null : Number(found[1]);
3850
+ }
3851
+ function itemsOf(text2) {
3852
+ const items = [];
3853
+ for (const raw of text2.split(String.fromCharCode(10))) {
3854
+ const line = raw.trim();
3855
+ const head = /^Diagram note \[(\d+)\] node (.+)$/.exec(line);
3856
+ if (head !== null) {
3857
+ const rest = head[2];
3858
+ const dash2 = rest.lastIndexOf(" - ");
3859
+ items.push({ index: Number(head[1]), node: dash2 === -1 ? rest : rest.slice(0, dash2), note: dash2 === -1 ? "" : rest.slice(dash2 + 3) });
3860
+ continue;
3861
+ }
3862
+ const note = /^Note: (.*)$/.exec(line);
3863
+ if (note !== null && items.length > 0) items[items.length - 1].note = note[1];
3864
+ }
3865
+ return items;
3866
+ }
3867
+ function textNodesOf(root) {
3868
+ const out = [];
3869
+ const visit = (node) => {
3870
+ const children = node.childNodes;
3871
+ if (children === void 0 || children === null || children.length === 0) {
3872
+ if (typeof node.nodeValue === "string") out.push(node);
3873
+ return;
3874
+ }
3875
+ for (let index = 0; index < children.length; index += 1) visit(children[index]);
3876
+ };
3877
+ visit(root);
3878
+ return out;
3879
+ }
3880
+ function cutTextNodes(nodes, cut2) {
3881
+ let position = 0;
3882
+ let done = false;
3883
+ for (const node of nodes) {
3884
+ const value = typeof node.nodeValue === "string" ? node.nodeValue : "";
3885
+ const length = value.length;
3886
+ if (done) {
3887
+ position += length;
3888
+ continue;
3889
+ }
3890
+ if (cut2 <= position + length) {
3891
+ node.nodeValue = value.slice(cut2 - position).replace(/^\s+/, "");
3892
+ done = true;
3893
+ } else {
3894
+ node.nodeValue = "";
3895
+ }
3896
+ position += length;
3897
+ }
3898
+ return done;
3899
+ }
3900
+ function isForeign(node) {
3901
+ for (const name of ["data-annotation-for-dsh", "data-annotation-overlay", "data-annotation-chip", "data-annotation-tip-layer"]) {
3902
+ const value = node.getAttribute?.(name);
3903
+ if (value !== void 0 && value !== null) return true;
3904
+ }
3905
+ return false;
3906
+ }
3907
+ function holdsAnotherBlock(node) {
3908
+ const inner = node.querySelectorAll?.(SELECTOR);
3909
+ if (inner === void 0 || inner === null) return false;
3910
+ for (let index = 0; index < inner.length; index += 1) {
3911
+ const text2 = inner[index].textContent;
3912
+ if (typeof text2 === "string" && text2.indexOf(TRANSCRIPT_MARKER) !== -1) return true;
3913
+ }
3914
+ return false;
3915
+ }
3916
+ function cardFor(doc, items, title, full) {
3917
+ const card = doc.createElement?.("div");
3918
+ if (card === void 0) return void 0;
3919
+ styleOf(card, {
3920
+ position: "fixed",
3921
+ zIndex: "40",
3922
+ display: "none",
3923
+ maxWidth: "360px",
3924
+ padding: "8px 10px",
3925
+ borderRadius: "10px",
3926
+ background: "var(--dsw-alias-bg-overlay, var(--dsw-alias-bg-layer-1, Canvas))",
3927
+ border: BORDER,
3928
+ boxShadow: "0 10px 30px rgba(0,0,0,0.28)",
3929
+ color: "var(--dsw-alias-label-primary, CanvasText)",
3930
+ font: "12px system-ui, sans-serif"
3931
+ });
3932
+ const head = doc.createElement?.("div");
3933
+ if (head !== void 0) {
3934
+ head.textContent = title;
3935
+ styleOf(head, {
3936
+ color: "var(--dsw-alias-label-secondary, GrayText)",
3937
+ paddingBottom: "6px",
3938
+ marginBottom: "4px",
3939
+ borderBottom: BORDER,
3940
+ fontSize: "11px"
3941
+ });
3942
+ card.appendChild?.(head);
3943
+ }
3944
+ for (const item of items) {
3945
+ const row = doc.createElement?.("div");
3946
+ if (row === void 0) continue;
3947
+ styleOf(row, { display: "flex", gap: "6px", alignItems: "flex-start", padding: "3px 0" });
3948
+ const badge = doc.createElement?.("span");
3949
+ if (badge !== void 0) {
3950
+ badge.textContent = String(item.index);
3951
+ styleOf(badge, {
3952
+ flex: "0 0 auto",
3953
+ width: "16px",
3954
+ height: "16px",
3955
+ lineHeight: "16px",
3956
+ textAlign: "center",
3957
+ borderRadius: "8px",
3958
+ fontSize: "10px",
3959
+ background: "var(--dsw-alias-brand-primary, #2563eb)",
3960
+ color: "#fff"
3961
+ });
3962
+ row.appendChild?.(badge);
3963
+ }
3964
+ const body = doc.createElement?.("div");
3965
+ if (body !== void 0) {
3966
+ body.textContent = item.node + (item.note === "" ? "" : String.fromCharCode(10) + item.note);
3967
+ styleOf(body, { flex: "1 1 auto", whiteSpace: "pre-wrap", wordBreak: "break-word" });
3968
+ row.appendChild?.(body);
3969
+ }
3970
+ card.appendChild?.(row);
3971
+ }
3972
+ const more = doc.createElement?.("div");
3973
+ if (more !== void 0) {
3974
+ more.textContent = full;
3975
+ styleOf(more, {
3976
+ display: "none",
3977
+ marginTop: "6px",
3978
+ paddingTop: "6px",
3979
+ borderTop: BORDER,
3980
+ fontSize: "11px",
3981
+ whiteSpace: "pre-wrap",
3982
+ color: "var(--dsw-alias-label-secondary, GrayText)",
3983
+ maxHeight: "40vh",
3984
+ overflow: "auto"
3985
+ });
3986
+ card.appendChild?.(more);
3987
+ }
3988
+ return card;
3989
+ }
3990
+ function styleOf(node, map) {
3991
+ const decl = node.style;
3992
+ if (typeof decl?.setProperty === "function") {
3993
+ const target = decl;
3994
+ for (const key of Object.keys(map)) {
3995
+ const value = map[key];
3996
+ if (value === void 0) continue;
3997
+ target.setProperty(key.replace(/[A-Z]/g, (letter) => "-" + letter.toLowerCase()), value);
3998
+ }
3999
+ return;
4000
+ }
4001
+ node.style = map;
4002
+ }
4003
+ function chipFor(doc, label, title, text2) {
4004
+ const chip = doc.createElement?.("div");
4005
+ if (chip === void 0) return void 0;
4006
+ chip.textContent = label;
4007
+ chip.setAttribute?.("role", "button");
4008
+ styleOf(chip, {
4009
+ display: "inline-flex",
4010
+ alignItems: "center",
4011
+ height: "20px",
4012
+ padding: "0 8px",
4013
+ margin: "4px 0 0",
4014
+ fontSize: "11px",
4015
+ lineHeight: "20px",
4016
+ borderRadius: "10px",
4017
+ verticalAlign: "middle",
4018
+ userSelect: "none",
4019
+ border: BORDER,
4020
+ background: "var(--dsw-alias-bg-layer-2, rgba(127,127,127,0.10))",
4021
+ color: "var(--dsw-alias-label-secondary, GrayText)",
4022
+ cursor: "pointer",
4023
+ maxWidth: "100%"
4024
+ });
4025
+ const card = cardFor(doc, itemsOf(text2), title, text2);
4026
+ if (card === void 0) return chip;
4027
+ const place2 = () => {
4028
+ const box = chip.getBoundingClientRect?.();
4029
+ styleOf(card, box === void 0 ? { display: "block" } : { display: "block", left: String(Math.max(8, box.left)) + "px", top: String(box.top + box.height + 6) + "px" });
4030
+ };
4031
+ const hide = () => {
4032
+ styleOf(card, { display: "none" });
4033
+ };
4034
+ chip.addEventListener?.("mouseenter", place2);
4035
+ chip.addEventListener?.("mouseleave", hide);
4036
+ chip.addEventListener?.("click", () => {
4037
+ if ((card.style ?? {}).display === "block") {
4038
+ hide();
4039
+ } else {
4040
+ place2();
4041
+ }
4042
+ });
4043
+ chip.appendChild?.(card);
4044
+ return chip;
4045
+ }
4046
+ function decorateTranscript(doc, label = "Notes", title = "Notes in this message") {
4047
+ if (doc === void 0 || typeof doc.querySelectorAll !== "function") return 0;
4048
+ let nodes;
4049
+ try {
4050
+ nodes = doc.querySelectorAll(SELECTOR);
4051
+ } catch {
4052
+ return 0;
4053
+ }
4054
+ let folded = 0;
4055
+ for (let index = 0; index < nodes.length; index += 1) {
4056
+ const element = nodes[index];
4057
+ const text2 = typeof element.textContent === "string" ? element.textContent : "";
4058
+ if (!text2.includes(TRANSCRIPT_MARKER)) continue;
4059
+ if (element.getAttribute?.(HANDLED) === "1") continue;
4060
+ if (isForeign(element)) continue;
4061
+ if (holdsAnotherBlock(element)) continue;
4062
+ const texts = textNodesOf(element);
4063
+ if (texts.length === 0) continue;
4064
+ const joined = texts.map((node) => typeof node.nodeValue === "string" ? node.nodeValue : "").join("");
4065
+ if (!joined.includes(TRANSCRIPT_MARKER)) continue;
4066
+ const at = joined.lastIndexOf(QUESTION);
4067
+ const cut2 = at === -1 ? joined.length : at + QUESTION.length;
4068
+ const count = annotationCountOf(joined);
4069
+ const chip = chipFor(doc, label + (count === null ? "" : " \xD7" + String(count)), title, joined);
4070
+ if (chip === void 0) continue;
4071
+ try {
4072
+ if (!cutTextNodes(texts, cut2)) continue;
4073
+ element.setAttribute?.(ORIGINAL, joined);
4074
+ element.setAttribute?.(HANDLED, "1");
4075
+ const parent = element.parentNode;
4076
+ if (parent?.insertBefore !== void 0) parent.insertBefore(chip, element.nextSibling ?? null);
4077
+ else element.appendChild?.(chip);
4078
+ folded += 1;
4079
+ } catch {
4080
+ }
4081
+ }
4082
+ return folded;
4083
+ }
4084
+ function startTranscriptDecoration(doc, label = "Notes", title = "Notes in this message") {
4085
+ decorateTranscript(doc, label, title);
4086
+ return () => {
4087
+ };
4088
+ }
4089
+
3684
4090
  // src/client.ts
3685
- var TOOL_NAMES = ["model_verify"];
4091
+ var services;
4092
+ var DRAWING_TOOL = "diagram_render";
4093
+ var TOOL_NAMES = ["model_verify", DRAWING_TOOL];
3686
4094
  function themeMode() {
3687
4095
  try {
3688
4096
  const scope = globalThis;
@@ -3703,8 +4111,1040 @@ window.__ModuleLoader__.load({
3703
4111
  }
3704
4112
  var WHITEBOARD_ID = "model-everything-diagram";
3705
4113
  var WHITEBOARD_SAMPLE = ["graph TD", " a[Idea] --> b{Feasible?}", " b -->|yes| c[Build]", " b -->|no| d[Revise]", " d --> a"].join("\n");
4114
+ function argOf(args, key) {
4115
+ if (args === null || typeof args !== "object") return void 0;
4116
+ const view = args;
4117
+ if (typeof view.value === "function") return view.value(key);
4118
+ return args[key];
4119
+ }
4120
+ var MESSAGES = {
4121
+ note: { en: "Note", zh: "\u6279\u6CE8" },
4122
+ noteOn: { en: "Note: on", zh: "\u6279\u6CE8: \u5F00" },
4123
+ noteHint: { en: "Click a node to mark it", zh: "\u70B9\u4E00\u4E2A\u8282\u70B9\u6807\u8BB0\u5B83" },
4124
+ node: { en: "Node", zh: "\u8282\u70B9" },
4125
+ add: { en: "Add", zh: "\u52A0\u5165" },
4126
+ addAndSend: { en: "Add & send", zh: "\u52A0\u5165\u5E76\u53D1\u9001" },
4127
+ close: { en: "Close", zh: "\u5173\u95ED" },
4128
+ send: { en: "Send", zh: "\u53D1\u9001" },
4129
+ clear: { en: "Clear", zh: "\u6E05\u7A7A" },
4130
+ remove: { en: "Remove", zh: "\u5220\u9664" },
4131
+ markedOnly: { en: "(marked only)", zh: "(\u53EA\u6807\u8BB0)" },
4132
+ pending: { en: "Notes", zh: "\u56FE\u6CE8" },
4133
+ fold: { en: "hide", zh: "\u6536\u8D77" },
4134
+ carried: { en: "Notes in this message", zh: "\u672C\u6D88\u606F\u643A\u5E26\u56FE\u6CE8" },
4135
+ zoomOut: { en: "Zoom out", zh: "\u7F29\u5C0F" },
4136
+ zoomIn: { en: "Zoom in", zh: "\u653E\u5927" },
4137
+ actualSize: { en: "Actual size", zh: "\u5B9E\u9645\u5927\u5C0F" },
4138
+ full: { en: "\u2922 Full", zh: "\u2922 \u5168\u5C4F" },
4139
+ exitFull: { en: "\u2921 Exit", zh: "\u2921 \u9000\u51FA" },
4140
+ diagram: { en: "Diagram", zh: "\u56FE" },
4141
+ fitOn: { en: "fit: on", zh: "fit: on" },
4142
+ fitOff: { en: "fit: off", zh: "fit: off" },
4143
+ scheme: { en: "Colours", zh: "\u914D\u8272" },
4144
+ unfold: { en: "unfold", zh: "\u5C55\u5F00" },
4145
+ placeholder: { en: "A note about this node\u2026 (Ctrl+Enter adds and sends)", zh: "\u6279\u6CE8\u2026\uFF08Ctrl+Enter \u52A0\u5165\u5E76\u53D1\u9001\uFF09" }
4146
+ };
4147
+ function languageOf() {
4148
+ const scope = globalThis;
4149
+ const asked = (scope.document?.documentElement?.lang ?? scope.navigator?.language ?? "en").toLowerCase();
4150
+ return asked.startsWith("zh") ? "zh" : "en";
4151
+ }
4152
+ function t(key) {
4153
+ return MESSAGES[key][languageOf()];
4154
+ }
4155
+ var TOKEN = {
4156
+ surface: "var(--dsw-alias-bg-overlay, var(--dsw-alias-bg-layer-1, Canvas))",
4157
+ border: "var(--dsw-alias-border-l1, rgba(127,127,127,0.35))",
4158
+ text: "var(--dsw-alias-label-primary, CanvasText)",
4159
+ dim: "var(--dsw-alias-label-secondary, GrayText)",
4160
+ accent: "var(--dsw-alias-brand-primary, #2563eb)"
4161
+ };
4162
+ function annotationPanel(h, state, actions, options = {}) {
4163
+ const button = (label, onClick, accent = false) => h("button", { type: "button", onClick, style: { fontSize: "12px", padding: "2px 8px", borderRadius: "6px", border: "1px solid " + TOKEN.border, background: "transparent", color: accent ? TOKEN.accent : TOKEN.text, cursor: "pointer" } }, label);
4164
+ const editor = state.picked === null ? null : h(
4165
+ "div",
4166
+ {
4167
+ style: {
4168
+ ...options.floating === false ? {} : { position: "absolute", left: (state.anchor?.left ?? 10) + "px", top: (state.anchor?.top ?? 10) + "px", zIndex: 20 },
4169
+ width: "min(260px, calc(100% - 16px))",
4170
+ boxSizing: "border-box",
4171
+ display: "flex",
4172
+ flexDirection: "column",
4173
+ gap: "6px",
4174
+ padding: "8px",
4175
+ borderRadius: "10px",
4176
+ background: TOKEN.surface,
4177
+ border: "1px solid " + TOKEN.border,
4178
+ color: TOKEN.text,
4179
+ boxShadow: "0 8px 24px rgba(0,0,0,0.28)"
4180
+ }
4181
+ },
4182
+ h("div", { style: { fontSize: "12px", color: TOKEN.dim } }, t("node") + " " + state.picked.id),
4183
+ h("textarea", {
4184
+ "data-dme-own": "1",
4185
+ value: state.note,
4186
+ rows: 3,
4187
+ placeholder: t("placeholder"),
4188
+ style: { width: "100%", boxSizing: "border-box", font: "12px system-ui, sans-serif", padding: "6px", borderRadius: "6px", border: "1px solid " + TOKEN.border, background: "transparent", color: TOKEN.text, resize: "vertical" },
4189
+ onInput: (event) => actions.onNote(String(event?.target?.value ?? "")),
4190
+ onKeyDown: (event) => {
4191
+ if (event?.key === "Enter" && (event?.ctrlKey === true || event?.metaKey === true)) {
4192
+ event.preventDefault?.();
4193
+ actions.onAdd();
4194
+ }
4195
+ }
4196
+ }),
4197
+ h("div", { style: { display: "flex", gap: "6px", justifyContent: "flex-end" } }, button("\u5173\u95ED", actions.onCancel), button("\u52A0\u5165", actions.onAdd))
4198
+ );
4199
+ const docked = options.floating !== false && options.document !== void 0 ? composerRect(options.document) : void 0;
4200
+ const chip = state.pending.length === 0 || options.dockChip === false ? null : h(
4201
+ "div",
4202
+ {
4203
+ style: {
4204
+ position: "fixed",
4205
+ zIndex: 30,
4206
+ left: (docked === void 0 ? 16 : docked.left) + "px",
4207
+ transform: "translate(" + String(state.dockFix?.dx ?? 0) + "px, " + String(state.dockFix?.dy ?? 0) + "px)",
4208
+ // Anchored to the composer's own top edge, in the gap above it: the count is in sight while the
4209
+ // reader is typing, and never covers the box they are typing into.
4210
+ top: (docked === void 0 ? 16 : Math.max(8, docked.top - 46)) + "px",
4211
+ // Hugs its two buttons. A fixed width turned the control into a wide empty bar across the composer.
4212
+ display: "flex",
4213
+ flexDirection: "column",
4214
+ gap: "6px",
4215
+ padding: "6px 10px",
4216
+ borderRadius: "12px",
4217
+ width: "max-content",
4218
+ // The composer's own surface and hairline: the control reads as part of that box, not as a dialog.
4219
+ background: "var(--dsw-alias-bg-layer-1, " + TOKEN.surface + ")",
4220
+ border: "1px solid var(--dsw-alias-border-l2, " + TOKEN.border + ")",
4221
+ color: TOKEN.text,
4222
+ boxShadow: "0 8px 24px rgba(0,0,0,0.22)",
4223
+ font: "12px system-ui, sans-serif"
4224
+ }
4225
+ },
4226
+ h(
4227
+ "div",
4228
+ { "data-dme-dock": "1", style: { display: "flex", alignItems: "center", gap: "6px" } },
4229
+ h("button", { type: "button", title: "\u5C55\u5F00\uFF0C\u9010\u4E2A\u5220\u9664", onClick: () => actions.onToggle(), style: { fontSize: "12px", padding: "1px 6px", borderRadius: "6px", border: "1px solid " + TOKEN.border, background: "transparent", color: TOKEN.text, cursor: "pointer" } }, t("pending") + " \xD7" + String(state.pending.length)),
4230
+ button(t("send"), actions.onSend, true)
4231
+ ),
4232
+ state.open ? h(
4233
+ "div",
4234
+ { style: { display: "flex", flexDirection: "column", gap: "2px" } },
4235
+ ...state.pending.map(
4236
+ (item, index) => h(
4237
+ "div",
4238
+ { style: { display: "flex", alignItems: "center", gap: "6px" } },
4239
+ h("span", { style: { color: TOKEN.dim, fontSize: "11px" } }, item.nodeId),
4240
+ h("span", { style: { flex: "1 1 auto", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" } }, item.note === "" ? t("markedOnly") : item.note),
4241
+ button(t("remove"), () => actions.onRemove(index))
4242
+ )
4243
+ )
4244
+ ) : null
4245
+ );
4246
+ const mode = state.picked === null && state.pending.length === 0 ? h("div", { style: { fontSize: "11px", color: TOKEN.dim, padding: "2px 4px" } }, t("noteHint")) : null;
4247
+ return h(
4248
+ "div",
4249
+ { style: { display: "flex", flexDirection: "column", gap: "2px", color: TOKEN.text } },
4250
+ mode,
4251
+ chip,
4252
+ editor,
4253
+ state.status === "" ? null : h("div", { style: { fontSize: "11px", color: TOKEN.dim, padding: "0 4px" } }, state.status)
4254
+ );
4255
+ }
4256
+ function sourceOf(block) {
4257
+ const record2 = (value) => value !== null && typeof value === "object" ? value : void 0;
4258
+ const asText = (value) => typeof value === "string" && value.trim() !== "" ? value : void 0;
4259
+ const fromJson = (value) => {
4260
+ const raw = asText(value);
4261
+ if (raw === void 0) return void 0;
4262
+ try {
4263
+ return asText(record2(JSON.parse(raw))?.source);
4264
+ } catch {
4265
+ return void 0;
4266
+ }
4267
+ };
4268
+ const frame = record2(block);
4269
+ if (frame === void 0) return void 0;
4270
+ const fromMeta = asText(record2(frame.meta)?.source);
4271
+ if (fromMeta !== void 0) return fromMeta;
4272
+ const args = record2(frame.args);
4273
+ if (args !== void 0 && typeof args.value === "function") {
4274
+ const lazy = asText(args.value("source"));
4275
+ if (lazy !== void 0) return lazy;
4276
+ }
4277
+ const plain = asText(args?.source) ?? fromJson(frame.args);
4278
+ if (plain !== void 0) return plain;
4279
+ const call = record2(frame.call);
4280
+ const fromCall = asText(call?.source) ?? fromJson(call?.input) ?? fromJson(call?.arguments);
4281
+ if (fromCall !== void 0) return fromCall;
4282
+ return asText(record2(frame.meta)?.source);
4283
+ }
4284
+ function drawingCard(React, props, overrides) {
4285
+ const block = props.block ?? {};
4286
+ const source = sourceOf(props.block) ?? argOf(block.args, "source");
4287
+ const asked = argOf(block.args, "scheme");
4288
+ const scheme = schemeNames().includes(asked) ? asked : "default";
4289
+ const payload = props.block?.result;
4290
+ const returned = payload !== null && typeof payload === "object" ? payload.svg : void 0;
4291
+ const markup = typeof returned === "string" && returned !== "" ? returned : null;
4292
+ const hasDrawing = markup !== null || typeof source === "string" && source.trim() !== "";
4293
+ const useState = React.useState;
4294
+ if (useState === void 0) return cardSurface(React, source, markup, scheme, overrides, null, null, null, null);
4295
+ const [annotate, setAnnotate] = useState(false);
4296
+ const [picked, setPicked] = useState(null);
4297
+ const [note, setNote] = useState("");
4298
+ const [status, setStatus] = useState("");
4299
+ const document = globalThis.document;
4300
+ const caption = typeof source === "string" ? source.split(String.fromCharCode(10)).map((line) => line.trim()).find((line) => line !== "") ?? "" : "";
4301
+ const [pending, setPending] = useState([]);
4302
+ const [open, setOpen] = useState(false);
4303
+ const [sent, setSent] = useState("");
4304
+ const [report, setReport] = useState("");
4305
+ const [, setDockTick] = useState(0);
4306
+ const [dockFix, setDockFix] = useState({ dx: 0, dy: 0 });
4307
+ React.useEffect?.(() => {
4308
+ const doc = globalThis.document;
4309
+ const composer = findComposer(doc);
4310
+ const bump = () => setDockTick((n2) => n2 + 1);
4311
+ const scope = globalThis;
4312
+ scope.addEventListener?.("resize", bump);
4313
+ let observer;
4314
+ if (composer !== void 0 && composer !== null && scope.ResizeObserver !== void 0) {
4315
+ try {
4316
+ observer = new scope.ResizeObserver(bump);
4317
+ observer.observe(composer);
4318
+ } catch {
4319
+ observer = void 0;
4320
+ }
4321
+ }
4322
+ return () => {
4323
+ scope.removeEventListener?.("resize", bump);
4324
+ observer?.disconnect();
4325
+ };
4326
+ }, []);
4327
+ React.useEffect?.(() => {
4328
+ const doc = globalThis.document;
4329
+ const chip = doc?.querySelector?.("[data-dme-dock]");
4330
+ const surface = composerRect(doc);
4331
+ const landed = chip?.getBoundingClientRect?.();
4332
+ if (surface === void 0 || landed === void 0) return;
4333
+ const dx = Math.round(surface.left - landed.left);
4334
+ const dy = Math.round(surface.top - landed.height - 8 - landed.top);
4335
+ if (Math.abs(dx) > 1 || Math.abs(dy) > 1) setDockFix((was) => ({ dx: was.dx + dx, dy: was.dy + dy }));
4336
+ });
4337
+ const [anchor2, setAnchor] = useState(void 0);
4338
+ setPendingBlock(pending.length === 0 ? "" : annotationBlock(pending.map((item) => ({ ...item, caption }))));
4339
+ React.useEffect?.(() => {
4340
+ try {
4341
+ return onMessageSent(() => {
4342
+ setPending([]);
4343
+ setStatus("");
4344
+ });
4345
+ } catch {
4346
+ return void 0;
4347
+ }
4348
+ }, []);
4349
+ const [zoom, setZoom] = useState(1);
4350
+ const [full, setFull] = useState(false);
4351
+ if (!hasDrawing) {
4352
+ const keys = props.block === null || typeof props.block !== "object" ? "none" : Object.keys(props.block).join(",");
4353
+ return React.createElement("div", { style: { fontSize: "12px", opacity: 0.7 } }, "no drawing in this call \xB7 block: " + (keys === "" ? "empty" : keys));
4354
+ }
4355
+ const sendAll = (list) => {
4356
+ if (list.length === 0) return;
4357
+ const text2 = annotationBlock(list.map((item) => ({ ...item, caption })));
4358
+ void (async () => {
4359
+ if (placeBlock(text2)) {
4360
+ const label = "\u56FE\u6CE8 \xD7" + String(list.length);
4361
+ attachBelowBubble(label, "");
4362
+ setSent("\u5DF2\u53D1\u9001 " + label);
4363
+ attachSentChip(label);
4364
+ setStatus("\u5DF2\u653E\u5165\u8F93\u5165\u6846\u5E76\u63D0\u4EA4\uFF08" + String(list.length) + " \u6761\u56FE\u6CE8\uFF09");
4365
+ setPending([]);
4366
+ submitDraft();
4367
+ return;
4368
+ }
4369
+ const said = prependBlock(document, list, caption);
4370
+ setStatus(said);
4371
+ if (!said.startsWith("\u5DF2")) return;
4372
+ setPending([]);
4373
+ submitComposer(document);
4374
+ })();
4375
+ };
4376
+ const onPick = (event) => {
4377
+ if (!annotate) return;
4378
+ const id = event?.target?.closest?.("[data-node-id]")?.getAttribute?.("data-node-id");
4379
+ if (typeof id === "string" && id !== "") {
4380
+ const pointer = event;
4381
+ const frame = pointer.currentTarget?.getBoundingClientRect?.();
4382
+ const node = pointer.target?.closest?.("[data-node-id]")?.getBoundingClientRect?.();
4383
+ if (frame !== void 0 && node !== void 0) {
4384
+ const width = 250;
4385
+ const left = Math.max(4, Math.min(node.left - frame.left + node.width + 10, Math.max(4, frame.width - width)));
4386
+ const top = Math.max(4, Math.min(node.top - frame.top, Math.max(4, frame.height - 40)));
4387
+ setAnchor({ left, top });
4388
+ }
4389
+ setPicked({ id });
4390
+ setStatus("");
4391
+ return;
4392
+ }
4393
+ if (note.trim() === "") setPicked(null);
4394
+ };
4395
+ const toggle = React.createElement(
4396
+ "div",
4397
+ { style: { display: "flex", gap: "6px", alignItems: "center" } },
4398
+ React.createElement("button", { type: "button", title: "Point at a node and send a note about it", onClick: () => {
4399
+ setAnnotate(!annotate);
4400
+ setStatus("");
4401
+ if (annotate) {
4402
+ setPicked(null);
4403
+ setNote("");
4404
+ }
4405
+ }, style: { fontSize: "11px", lineHeight: "16px", padding: "1px 6px", borderRadius: "5px", border: "1px solid " + TOKEN.border, background: "transparent", color: TOKEN.text, cursor: "pointer" } }, annotate ? t("noteOn") : t("note")),
4406
+ annotate && picked === null ? React.createElement("span", { style: { fontSize: "11px", opacity: 0.7 } }, "\u70B9\u4E00\u4E2A\u8282\u70B9") : null,
4407
+ React.createElement("button", {
4408
+ type: "button",
4409
+ onClick: () => {
4410
+ try {
4411
+ setReport(domReport());
4412
+ } catch (error) {
4413
+ setReport("report failed: " + String(error?.message ?? error));
4414
+ }
4415
+ },
4416
+ style: { fontSize: "11px", lineHeight: "16px", padding: "1px 6px", borderRadius: "5px", border: "1px solid " + TOKEN.border, background: "transparent", color: TOKEN.dim, cursor: "pointer" }
4417
+ }, "\u8BCA\u65AD"),
4418
+ sent === "" ? null : React.createElement("span", {
4419
+ style: { fontSize: "11px", lineHeight: "16px", padding: "1px 6px", borderRadius: "9px", border: "1px solid " + TOKEN.border, color: TOKEN.dim, whiteSpace: "nowrap" }
4420
+ }, sent)
4421
+ );
4422
+ updateDockLayer(pending, open, {
4423
+ onToggle: () => setOpen(!open),
4424
+ onSend: () => sendAll(pending),
4425
+ onRemove: (index) => setPending(pending.filter((_, at) => at !== index))
4426
+ });
4427
+ const panel = annotate ? annotationPanel(
4428
+ (type, options, ...children) => React.createElement(type, options, ...children),
4429
+ { picked, note, pending, status, anchor: anchor2, open, dockFix },
4430
+ {
4431
+ onNote: setNote,
4432
+ onAdd: () => {
4433
+ if (picked === null) return;
4434
+ const merged = [...pending, { nodeId: picked.id, note }];
4435
+ setPending(merged);
4436
+ setNote("");
4437
+ setPicked(null);
4438
+ setStatus("\u5DF2\u653E\u5165\u8F93\u5165\u6846\uFF0C\u76F4\u63A5\u56DE\u8F66\u5373\u53EF");
4439
+ },
4440
+ onAddAndSend: () => {
4441
+ if (picked === null) return;
4442
+ const merged = [...pending, { nodeId: picked.id, note }];
4443
+ setNote("");
4444
+ setPicked(null);
4445
+ sendAll(merged);
4446
+ },
4447
+ onSend: () => sendAll(pending),
4448
+ onClear: () => {
4449
+ setPending([]);
4450
+ setStatus("");
4451
+ },
4452
+ onCancel: () => {
4453
+ setPicked(null);
4454
+ setNote("");
4455
+ setStatus("");
4456
+ },
4457
+ onToggle: () => setOpen(!open),
4458
+ onRemove: (index) => setPending(pending.filter((_, at) => at !== index))
4459
+ },
4460
+ // The count is the body-level layer; this panel keeps the editor, which still needs its anchor.
4461
+ { document, dockChip: false }
4462
+ ) : null;
4463
+ const reportPanel = report === "" ? null : React.createElement("pre", {
4464
+ style: { margin: "6px 0 0", padding: "8px", borderRadius: "8px", border: "1px solid " + TOKEN.border, background: "rgba(127,127,127,0.08)", font: "11px ui-monospace, monospace", whiteSpace: "pre-wrap", userSelect: "text", maxHeight: "220px", overflow: "auto" }
4465
+ }, report);
4466
+ return cardSurface(React, source, markup, scheme, overrides, onPick, toggle, panel, reportPanel, { zoom: Number(zoom), full: Boolean(full), onZoom: (next) => setZoom(next), onFull: (next) => setFull(next) });
4467
+ }
4468
+ function cardSurface(React, source, returned, scheme, overrides, onClick, toggle, panel, report, view = { zoom: 1, full: false, onZoom: () => {
4469
+ }, onFull: () => {
4470
+ } }) {
4471
+ if (returned === null && (typeof source !== "string" || source.trim() === "")) {
4472
+ return React.createElement("div", { style: { fontSize: "12px", opacity: 0.7 } }, "no drawing in this call");
4473
+ }
4474
+ const drawn = returned === null ? render({ source: String(source), folded: [] }, overrides, { mode: themeMode(), scheme }) : { markup: returned, refused: [], colours: palette(overrides, { mode: themeMode(), scheme }) };
4475
+ const scaled = drawn.markup.replace("<svg ", '<svg style="max-width: 100%; height: auto; display: block; margin: 0 auto" ');
4476
+ const refused = drawn.refused.length === 0 ? null : React.createElement("pre", { style: { fontSize: "11px", color: "#b7791f", whiteSpace: "pre-wrap", margin: "6px 8px" } }, drawn.refused.join(String.fromCharCode(10)));
4477
+ const chrome = { border: "1px solid " + TOKEN.border, borderRadius: "8px", overflow: "hidden", background: TOKEN.surface, color: TOKEN.text };
4478
+ const button = (label, onPress, title) => React.createElement("button", { type: "button", title, onClick: onPress, style: { fontSize: "11px", lineHeight: "16px", padding: "1px 6px", borderRadius: "5px", border: "1px solid " + TOKEN.border, background: "transparent", color: TOKEN.text, cursor: "pointer" } }, label);
4479
+ const header = React.createElement(
4480
+ "div",
4481
+ { style: { display: "flex", gap: "6px", alignItems: "center", padding: "3px 8px", borderBottom: "1px solid " + TOKEN.border, fontSize: "12px", color: TOKEN.dim } },
4482
+ React.createElement("span", null, t("diagram")),
4483
+ React.createElement("span", { style: { opacity: 0.7 } }, typeof source === "string" ? source.split(String.fromCharCode(10)).map((line) => line.trim()).find((line) => line !== "") ?? "" : ""),
4484
+ React.createElement(
4485
+ "span",
4486
+ { style: { marginLeft: "auto", display: "flex", gap: "4px", alignItems: "center" } },
4487
+ button("\u2212", () => view.onZoom(Math.max(0.5, Math.round((view.zoom - 0.25) * 100) / 100)), t("zoomOut")),
4488
+ button(Math.round(view.zoom * 100) + "%", () => view.onZoom(1), t("actualSize")),
4489
+ button("+", () => view.onZoom(Math.min(3, Math.round((view.zoom + 0.25) * 100) / 100)), t("zoomIn")),
4490
+ button(view.full ? t("exitFull") : t("full"), () => view.onFull(!view.full), t("full")),
4491
+ toggle
4492
+ )
4493
+ );
4494
+ const drawing = React.createElement(
4495
+ "div",
4496
+ {
4497
+ // CSS zoom, not a transform: it reflows, so the scroll area grows with the picture and nothing is clipped.
4498
+ style: { zoom: view.zoom, cursor: onClick === null ? void 0 : "crosshair" },
4499
+ onClick: onClick === null ? void 0 : onClick,
4500
+ dangerouslySetInnerHTML: { __html: scaled }
4501
+ }
4502
+ );
4503
+ const body = React.createElement(
4504
+ "div",
4505
+ { style: { position: "relative", background: drawn.colours.background, padding: "6px", maxHeight: view.full ? "none" : "260px", overflow: "auto", flex: "1 1 auto", minHeight: "0" } },
4506
+ drawing,
4507
+ panel,
4508
+ report
4509
+ );
4510
+ const frame = view.full ? { position: "fixed", inset: "16px", zIndex: 60, display: "flex", flexDirection: "column", ...chrome, boxShadow: "0 12px 40px rgba(0,0,0,0.35)" } : { display: "flex", flexDirection: "column", ...chrome };
4511
+ const children = [header, body, refused].filter((child) => child !== null);
4512
+ return React.createElement("div", { style: frame }, ...children);
4513
+ }
4514
+ function currentSessionId() {
4515
+ const sessions = services?.get?.("sessions");
4516
+ const snapshot = sessions?.list?.getSnapshot?.();
4517
+ if (typeof snapshot?.current === "string" && snapshot.current !== "") return snapshot.current;
4518
+ const workspace = services?.get?.("uiWorkspace");
4519
+ const main = workspace?.mainReference?.sessionId;
4520
+ if (typeof main === "string" && main !== "") return main;
4521
+ const picked = workspace?.selection?.getSnapshot?.()?.sessionId;
4522
+ if (typeof picked === "string" && picked !== "") return picked;
4523
+ const storage = globalThis.localStorage;
4524
+ const raw = storage?.getItem?.("dsh.sessions.current");
4525
+ if (typeof raw === "string" && raw !== "") {
4526
+ try {
4527
+ const parsed = JSON.parse(raw);
4528
+ if (typeof parsed?.sessionId === "string" && parsed.sessionId !== "") return parsed.sessionId;
4529
+ } catch {
4530
+ }
4531
+ }
4532
+ return void 0;
4533
+ }
4534
+ function draftShell() {
4535
+ const conversation = services?.get?.("conversation");
4536
+ const sessions = services?.get?.("sessions");
4537
+ if (conversation?.input?.for === void 0 || sessions?.scope === void 0) return void 0;
4538
+ const id = currentSessionId();
4539
+ if (id === void 0) return void 0;
4540
+ try {
4541
+ return conversation.input.for(sessions.scope(id));
4542
+ } catch {
4543
+ return void 0;
4544
+ }
4545
+ }
4546
+ var placedText = "";
4547
+ function replaceBlock(text2) {
4548
+ const shell = draftShell();
4549
+ if (shell === void 0 || typeof shell.setDraft !== "function") return false;
4550
+ const snapshot = shell.state?.getSnapshot?.();
4551
+ const current = typeof snapshot?.draft === "string" ? String(snapshot.draft) : "";
4552
+ let rest = current;
4553
+ if (placedText !== "" && rest.includes(placedText)) rest = rest.split(placedText).join("");
4554
+ rest = rest.replace(/^[\r\n]+/, "").replace(/\s+$/, "");
4555
+ const next = text2 === "" ? rest : rest === "" ? text2 : rest + String.fromCharCode(10, 10) + text2;
4556
+ try {
4557
+ shell.setDraft(next);
4558
+ placedText = text2;
4559
+ return true;
4560
+ } catch {
4561
+ return false;
4562
+ }
4563
+ }
4564
+ var pendingBlock = "";
4565
+ var enterWatch = null;
4566
+ function setPendingBlock(text2) {
4567
+ pendingBlock = text2;
4568
+ installEnterCapture();
4569
+ }
4570
+ function findBlockElement(doc) {
4571
+ const all = Array.from(doc.querySelectorAll("div, p, span"));
4572
+ const hits = all.filter((node) => String(node.textContent ?? "").indexOf("Diagram annotations -") !== -1);
4573
+ let best;
4574
+ let bestArea = Number.POSITIVE_INFINITY;
4575
+ for (const node of hits) {
4576
+ const box = node.getBoundingClientRect?.();
4577
+ const area = box === void 0 || box === null ? Number.POSITIVE_INFINITY : box.width * box.height;
4578
+ if (area > 0 && area < bestArea) {
4579
+ bestArea = area;
4580
+ best = node;
4581
+ }
4582
+ }
4583
+ return best;
4584
+ }
4585
+ function insertChipAfter(doc, element, label) {
4586
+ try {
4587
+ const existing = Array.from(doc.querySelectorAll("[data-dme-chip]"));
4588
+ if (existing.some((old) => String(old.textContent ?? "") === label)) return;
4589
+ for (const old of existing) old.remove?.();
4590
+ const chip = doc.createElement("span");
4591
+ chip.setAttribute("data-dme-own", "1");
4592
+ chip.setAttribute("data-dme-chip", "1");
4593
+ chip.textContent = label;
4594
+ chip.style.cssText = "position:fixed;z-index:1140;display:inline-block;padding:1px 8px;border-radius:9px;font:11px system-ui;border:1px solid var(--dsw-alias-border-l1, rgba(127,127,127,0.35));color:var(--dsw-alias-label-secondary, #9aa0a6);background:var(--dsw-alias-bg-layer-1, rgba(30,30,32,0.92))";
4595
+ doc.body.appendChild(chip);
4596
+ chipAnchor = element;
4597
+ placeChip(doc);
4598
+ const timer2 = globalThis.setTimeout;
4599
+ if (typeof timer2 === "function") {
4600
+ for (const delay of [300, 900, 2e3, 3500]) timer2(() => {
4601
+ try {
4602
+ placeChip(doc);
4603
+ } catch {
4604
+ }
4605
+ }, delay);
4606
+ }
4607
+ const scope = globalThis;
4608
+ if (!chipScrollWatched && typeof scope.addEventListener === "function") {
4609
+ chipScrollWatched = true;
4610
+ scope.addEventListener("scroll", () => {
4611
+ try {
4612
+ const live = doc.querySelector("[data-dme-chip]");
4613
+ const anchor2 = chipAnchor;
4614
+ const box2 = anchor2?.getBoundingClientRect?.();
4615
+ if (live === null || box2 === void 0 || box2 === null) return;
4616
+ live.style.setProperty("left", String(Math.round(box2.left)) + "px");
4617
+ live.style.setProperty("top", String(Math.round(box2.bottom) + 4) + "px");
4618
+ } catch {
4619
+ }
4620
+ });
4621
+ }
4622
+ } catch {
4623
+ }
4624
+ }
4625
+ function placeChip(doc) {
4626
+ const chip = doc?.querySelector?.("[data-dme-chip]");
4627
+ if (chip === null || chip === void 0) return;
4628
+ if (chipAnchor === void 0 || chipAnchor.isConnected === false) chipAnchor = findBlockElement(doc);
4629
+ const anchor2 = chipAnchor;
4630
+ if (anchor2 === void 0) return;
4631
+ const box = anchor2.getBoundingClientRect?.();
4632
+ if (box === void 0 || box === null) return;
4633
+ if (box.width === 0) {
4634
+ return;
4635
+ }
4636
+ const view = globalThis;
4637
+ const outside = box.bottom < 0 || box.top > Number(view.innerHeight ?? 0);
4638
+ chip.style.setProperty("display", outside ? "none" : "inline-block");
4639
+ if (outside) return;
4640
+ chip.style.setProperty("left", String(Math.max(8, Math.round(box.left))) + "px");
4641
+ chip.style.setProperty("top", String(Math.max(8, Math.round(box.bottom) + 4)) + "px");
4642
+ }
4643
+ function attachBelowBubble(label, typed) {
4644
+ const doc = globalThis.document;
4645
+ const timer = globalThis.setTimeout;
4646
+ if (doc === void 0 || typeof timer !== "function") return;
4647
+ const wanted = typed.trim();
4648
+ let tries = 0;
4649
+ const attempt = () => {
4650
+ tries += 1;
4651
+ try {
4652
+ const all = Array.from(doc.querySelectorAll("div, p, span"));
4653
+ let hit;
4654
+ if (wanted !== "") {
4655
+ const hits = all.filter((node) => String(node.textContent ?? "").trim().startsWith(wanted) && node.parentElement);
4656
+ hit = hits[hits.length - 1];
4657
+ } else {
4658
+ hit = findBlockElement(doc);
4659
+ }
4660
+ chipAttempt = hit === void 0 ? "not found, try " + String(tries) : "found";
4661
+ if (hit !== void 0) {
4662
+ insertChipAfter(doc, hit, label);
4663
+ return;
4664
+ }
4665
+ } catch {
4666
+ }
4667
+ if (tries < 20) timer(attempt, 500);
4668
+ };
4669
+ timer(attempt, 300);
4670
+ }
4671
+ function attachSentChip(label) {
4672
+ const doc = globalThis.document;
4673
+ const timer = globalThis.setTimeout;
4674
+ if (doc === void 0 || typeof timer !== "function") return;
4675
+ let tries = 0;
4676
+ const attempt = () => {
4677
+ tries += 1;
4678
+ const anchor2 = doc.querySelector?.("[data-annotation-chip]");
4679
+ const bubble = anchor2?.parentElement;
4680
+ const row = bubble?.parentElement;
4681
+ const made = doc.createElement?.("span");
4682
+ if (made !== void 0 && bubble !== void 0 && bubble !== null && row !== void 0 && row !== null) {
4683
+ made.textContent = label;
4684
+ made.setAttribute?.("data-dme-own", "1");
4685
+ made.style.cssText = "display:inline-block;margin:4px 8px 0;padding:1px 8px;border-radius:9px;font:11px system-ui;border:1px solid var(--dsw-alias-border-l1, rgba(127,127,127,0.35));color:var(--dsw-alias-label-secondary, #9aa0a6)";
4686
+ try {
4687
+ row.insertBefore(made, bubble.nextSibling);
4688
+ return;
4689
+ } catch {
4690
+ }
4691
+ }
4692
+ if (tries < 8) timer(attempt, 250);
4693
+ };
4694
+ timer(attempt, 300);
4695
+ }
4696
+ var dockReact;
4697
+ var dockEl;
4698
+ var dockRetries = 0;
4699
+ var chipAttempt = "not attempted";
4700
+ var chipAnchor;
4701
+ var chipScrollWatched = false;
4702
+ var dockReceipt = "";
4703
+ var receiptTimer;
4704
+ function publishDockReceipt(text2) {
4705
+ dockReceipt = text2;
4706
+ const scope = globalThis;
4707
+ if (scope.clearTimeout !== void 0) scope.clearTimeout(receiptTimer);
4708
+ receiptTimer = scope.setTimeout?.(() => {
4709
+ dockReceipt = "";
4710
+ try {
4711
+ scheduleDock();
4712
+ } catch {
4713
+ }
4714
+ }, 8e3);
4715
+ }
4716
+ var dockObserver;
4717
+ var dockFrame;
4718
+ function ensureDock() {
4719
+ if (dockEl !== void 0 && dockEl.isConnected !== false) return dockEl;
4720
+ const doc = globalThis.document;
4721
+ if (doc?.body === void 0 || typeof doc.createElement !== "function") return void 0;
4722
+ for (const old of Array.from(doc.querySelectorAll("[data-dme-dock]"))) old.remove?.();
4723
+ const el = doc.createElement("div");
4724
+ el.setAttribute("data-dme-dock", "1");
4725
+ el.setAttribute("data-dme-own", "1");
4726
+ el.style.cssText = "position:fixed;z-index:1140;display:none;align-items:center;gap:6px;padding:4px 8px;border-radius:11px;border:1px solid var(--dsw-alias-border-l2, rgba(127,127,127,0.35));background:var(--dsw-alias-bg-layer-1, #2c2c2e);box-shadow:0 8px 24px rgba(0,0,0,0.24);font:11px var(--dsw-font-family, system-ui);color:var(--dsw-alias-label-primary, #eee)";
4727
+ doc.body.appendChild(el);
4728
+ dockEl = el;
4729
+ return el;
4730
+ }
4731
+ function scheduleDock() {
4732
+ const raf = globalThis.requestAnimationFrame;
4733
+ if (dockFrame !== void 0 || typeof raf !== "function") {
4734
+ updateDockChip();
4735
+ return;
4736
+ }
4737
+ dockFrame = raf(() => {
4738
+ dockFrame = void 0;
4739
+ updateDockChip();
4740
+ });
4741
+ }
4742
+ function observeDockAnchor() {
4743
+ const doc = globalThis.document;
4744
+ const card = doc?.querySelector?.("[data-composer-card]");
4745
+ if (card === null || card === void 0) return;
4746
+ const Observer = globalThis.ResizeObserver;
4747
+ if (Observer === void 0) return;
4748
+ try {
4749
+ dockObserver?.disconnect();
4750
+ const fresh = new Observer(() => {
4751
+ scheduleDock();
4752
+ });
4753
+ fresh.observe(card);
4754
+ dockObserver = fresh;
4755
+ } catch {
4756
+ dockObserver = void 0;
4757
+ }
4758
+ }
4759
+ function updateDockChip() {
4760
+ const state = dockReact;
4761
+ const el = ensureDock();
4762
+ if (state === void 0 || el === void 0) return;
4763
+ const doc = globalThis.document;
4764
+ if (state.count === 0) {
4765
+ if (dockReceipt === "") {
4766
+ el.style.display = "none";
4767
+ return;
4768
+ }
4769
+ el.textContent = "";
4770
+ const note = doc.createElement("span");
4771
+ note.textContent = dockReceipt;
4772
+ note.style.cssText = "opacity:.75";
4773
+ el.appendChild(note);
4774
+ el.style.display = "flex";
4775
+ const cardRect2 = doc.querySelector("[data-composer-card]")?.getBoundingClientRect?.();
4776
+ if (cardRect2 === void 0) {
4777
+ el.style.left = "16px";
4778
+ el.style.top = "16px";
4779
+ return;
4780
+ }
4781
+ const w = Number(el.offsetWidth) || 100;
4782
+ const h = Number(el.offsetHeight) || 24;
4783
+ el.style.left = Math.max(8, Math.min(cardRect2.left, Number(globalThis.innerWidth ?? 0) - w - 8)) + "px";
4784
+ el.style.top = Math.max(8, cardRect2.top - h - 8) + "px";
4785
+ return;
4786
+ }
4787
+ const create = (tag) => doc.createElement(tag);
4788
+ el.textContent = "";
4789
+ const toggle = create("button");
4790
+ toggle.textContent = t("pending") + " \xD7" + String(state.count);
4791
+ toggle.style.cssText = "font:11px inherit;padding:1px 6px;border-radius:6px;border:1px solid var(--dsw-alias-border-l2, rgba(127,127,127,0.35));background:transparent;color:inherit;cursor:pointer";
4792
+ toggle.addEventListener("click", () => state.handlers.onToggle());
4793
+ el.appendChild(toggle);
4794
+ const send = create("button");
4795
+ send.textContent = t("send");
4796
+ send.style.cssText = "font:11px inherit;padding:1px 8px;border-radius:6px;border:1px solid var(--dsw-alias-brand-primary,#2563eb);background:var(--dsw-alias-brand-primary,#2563eb);color:#fff;cursor:pointer";
4797
+ send.addEventListener("click", () => state.handlers.onSend());
4798
+ el.appendChild(send);
4799
+ if (state.open && state.items.length > 0) {
4800
+ for (const [index, item] of state.items.entries()) {
4801
+ const line = create("span");
4802
+ line.textContent = item.nodeId + ":" + (item.note === "" ? t("markedOnly") : item.note);
4803
+ line.title = "\u70B9\u51FB\u5220\u9664";
4804
+ line.style.cssText = "cursor:pointer;opacity:.85";
4805
+ line.addEventListener("click", () => state.handlers.onRemove(index));
4806
+ el.appendChild(line);
4807
+ }
4808
+ }
4809
+ el.style.display = "flex";
4810
+ observeDockAnchor();
4811
+ const surface = findComposer(doc) ?? doc.querySelector('textarea, [contenteditable="true"]');
4812
+ const rect = surface?.getBoundingClientRect?.();
4813
+ const cardEl = doc.querySelector("[data-composer-card]") ?? null;
4814
+ const seatEl = cardEl?.closest?.("[data-composer-seat]") ?? null;
4815
+ const cardRect = cardEl?.getBoundingClientRect?.() ?? null;
4816
+ void surface;
4817
+ const width = Number(el.offsetWidth) || 100;
4818
+ const height = Number(el.offsetHeight) || 26;
4819
+ if (rect === void 0 && cardRect === null) {
4820
+ el.style.left = "16px";
4821
+ el.style.top = "16px";
4822
+ return;
4823
+ }
4824
+ const view = globalThis;
4825
+ const anchor2 = cardRect ?? rect;
4826
+ const seatTop = seatEl?.getBoundingClientRect?.()?.top;
4827
+ const topEdge = Math.min(anchor2.top, typeof seatTop === "number" ? seatTop : anchor2.top);
4828
+ const left = Math.max(8, Math.min(anchor2.left, Number(view.innerWidth ?? 0) - width - 8));
4829
+ el.style.left = left + "px";
4830
+ el.style.top = Math.max(8, topEdge - height - 6) + "px";
4831
+ observeDivider(doc);
4832
+ observeSurface(doc, surface);
4833
+ const scope2 = globalThis;
4834
+ if (left <= 8 && dockRetries < 12 && typeof scope2.setTimeout === "function") {
4835
+ dockRetries += 1;
4836
+ scope2.setTimeout(() => {
4837
+ try {
4838
+ updateDockChip();
4839
+ } catch {
4840
+ }
4841
+ }, 250);
4842
+ } else if (left > 8) {
4843
+ dockRetries = 0;
4844
+ }
4845
+ }
4846
+ function updateDockLayer(items, open, handlers) {
4847
+ dockReact = { count: items.length, open, items, handlers };
4848
+ bumpDock();
4849
+ if (dockSlotMounted) return;
4850
+ try {
4851
+ scheduleDock();
4852
+ } catch {
4853
+ }
4854
+ }
4855
+ var dockSlotMounted = false;
4856
+ var dockVersion = 0;
4857
+ var dockSubs = /* @__PURE__ */ new Set();
4858
+ function bumpDock() {
4859
+ dockVersion += 1;
4860
+ for (const listener of Array.from(dockSubs)) {
4861
+ try {
4862
+ listener();
4863
+ } catch {
4864
+ }
4865
+ }
4866
+ }
4867
+ function dockSlotView(React) {
4868
+ return function DockSlot() {
4869
+ const [, setVersion] = (React.useState ?? ((initial) => [initial, () => {
4870
+ }]))(0);
4871
+ React.useEffect?.(() => {
4872
+ dockSlotMounted = true;
4873
+ const listener = () => setVersion(dockVersion);
4874
+ dockSubs.add(listener);
4875
+ return () => {
4876
+ dockSubs.delete(listener);
4877
+ dockSlotMounted = false;
4878
+ };
4879
+ }, []);
4880
+ const [pad, setPad] = (React.useState ?? ((initial) => [initial, () => {
4881
+ }]))({ left: 0, right: 0 });
4882
+ const [diag, setDiag] = (React.useState ?? ((initial) => [initial, () => {
4883
+ }]))("");
4884
+ React.useEffect?.(() => {
4885
+ const doc = globalThis.document;
4886
+ const timer = globalThis.setTimeout;
4887
+ const measure2 = () => {
4888
+ try {
4889
+ const slot = doc?.querySelector?.("[data-dme-dock-slot]");
4890
+ const card = findComposer(doc) ?? doc?.querySelector?.('textarea, [contenteditable="true"]');
4891
+ if (slot === null || slot === void 0 || card === null || card === void 0) return;
4892
+ const s = slot.getBoundingClientRect();
4893
+ const c = card.getBoundingClientRect();
4894
+ const next = { left: Math.max(0, Math.round(c.left - s.left)), right: Math.max(0, Math.round(s.right - c.right)) };
4895
+ setPad(next);
4896
+ setDiag(" L" + String(next.left) + " R" + String(next.right) + " s" + String(Math.round(s.left)) + " c" + String(Math.round(c.left)) + " w" + String(Math.round(c.width)));
4897
+ } catch {
4898
+ }
4899
+ };
4900
+ if (typeof timer === "function") {
4901
+ for (const delay of [0, 100, 250, 500, 900, 1500, 2400]) timer(measure2, delay);
4902
+ }
4903
+ const scope = globalThis;
4904
+ scope.addEventListener?.("resize", measure2);
4905
+ const Observer = globalThis.ResizeObserver;
4906
+ let watcher;
4907
+ if (Observer !== void 0) {
4908
+ try {
4909
+ watcher = new Observer(measure2);
4910
+ watcher.observe(doc?.body);
4911
+ } catch {
4912
+ watcher = void 0;
4913
+ }
4914
+ }
4915
+ return () => {
4916
+ watcher?.disconnect();
4917
+ scope.removeEventListener?.("resize", measure2);
4918
+ };
4919
+ }, []);
4920
+ const state = dockReact;
4921
+ if (state === void 0 || state.count === 0) return null;
4922
+ let livePad = pad;
4923
+ try {
4924
+ const doc = globalThis.document;
4925
+ const slotEl = doc?.querySelector?.("[data-dme-dock-slot]");
4926
+ const surfaceEl = findComposer(doc) ?? doc?.querySelector?.('textarea, [contenteditable="true"]');
4927
+ const sr = slotEl?.getBoundingClientRect?.();
4928
+ const cr = surfaceEl?.getBoundingClientRect?.();
4929
+ if (sr !== void 0 && sr !== null && cr !== void 0 && cr !== null) {
4930
+ livePad = { left: Math.max(0, Math.round(cr.left - sr.left)), right: Math.max(0, Math.round(sr.right - cr.right)) };
4931
+ }
4932
+ } catch {
4933
+ }
4934
+ return React.createElement(
4935
+ "div",
4936
+ {
4937
+ "data-dme-own": "1",
4938
+ "data-dme-dock-slot": "1",
4939
+ style: { display: "flex", alignItems: "center", justifyContent: "flex-start", gap: "6px", paddingTop: "2px", paddingBottom: "2px", paddingLeft: String(livePad.left) + "px", paddingRight: String(livePad.right) + "px", font: "11px system-ui, sans-serif", color: "inherit" }
4940
+ },
4941
+ React.createElement("button", {
4942
+ type: "button",
4943
+ onClick: () => state.handlers.onToggle(),
4944
+ style: { font: "inherit", padding: "1px 8px", borderRadius: "9px", border: "1px solid " + TOKEN.border, background: "transparent", color: "inherit", cursor: "pointer" }
4945
+ }, t("pending") + " \xD7" + String(state.count) + " L" + String(livePad.left) + diag),
4946
+ React.createElement("button", {
4947
+ type: "button",
4948
+ onClick: () => state.handlers.onSend(),
4949
+ style: { font: "inherit", padding: "1px 8px", borderRadius: "9px", border: "1px solid " + TOKEN.border, background: "transparent", color: "inherit", cursor: "pointer" }
4950
+ }, t("send"))
4951
+ );
4952
+ };
4953
+ }
4954
+ var dividerObserved;
4955
+ var surfaceObserved;
4956
+ var surfaceInputWatched = false;
4957
+ function observeSurface(doc, surface) {
4958
+ try {
4959
+ if (surface === void 0 || surface === null || surfaceObserved === surface) return;
4960
+ surfaceObserved = surface;
4961
+ const targets = [surface, surface?.parentElement].filter((node) => node !== null && node !== void 0);
4962
+ const Observer = globalThis.ResizeObserver;
4963
+ if (Observer !== void 0) {
4964
+ const watcher = new Observer(() => {
4965
+ scheduleDock();
4966
+ });
4967
+ for (const target of targets) {
4968
+ try {
4969
+ watcher.observe(target);
4970
+ } catch {
4971
+ }
4972
+ }
4973
+ }
4974
+ const scope = globalThis;
4975
+ if (typeof scope.addEventListener === "function" && !surfaceInputWatched) {
4976
+ surfaceInputWatched = true;
4977
+ scope.addEventListener("input", () => {
4978
+ scheduleDock();
4979
+ scope.setTimeout?.(() => {
4980
+ scheduleDock();
4981
+ }, 120);
4982
+ scope.setTimeout?.(() => {
4983
+ scheduleDock();
4984
+ }, 400);
4985
+ });
4986
+ scope.addEventListener("paste", () => {
4987
+ scope.setTimeout?.(() => {
4988
+ scheduleDock();
4989
+ }, 60);
4990
+ });
4991
+ }
4992
+ } catch {
4993
+ }
4994
+ }
4995
+ function observeDivider(doc) {
4996
+ try {
4997
+ const handle = doc?.querySelector?.('[class*="widthHandle"]');
4998
+ if (handle === null || handle === void 0 || dividerObserved === handle) return;
4999
+ dividerObserved = handle;
5000
+ const Observer = globalThis.ResizeObserver;
5001
+ if (Observer !== void 0) {
5002
+ try {
5003
+ new Observer(() => {
5004
+ scheduleDock();
5005
+ }).observe(handle);
5006
+ } catch {
5007
+ }
5008
+ }
5009
+ const scope = globalThis;
5010
+ scope.addEventListener?.("pointerup", () => {
5011
+ scheduleDock();
5012
+ });
5013
+ } catch {
5014
+ }
5015
+ }
5016
+ function domReport() {
5017
+ const doc = globalThis.document;
5018
+ if (doc === void 0) return "no document";
5019
+ const lines = [];
5020
+ const rect = (el) => {
5021
+ const r = el?.getBoundingClientRect?.();
5022
+ return r === void 0 || r === null ? "absent" : [Math.round(r.left), Math.round(r.top), Math.round(r.width), Math.round(r.height)].join(",");
5023
+ };
5024
+ const probe = (name, selector) => {
5025
+ const el = doc.querySelector(selector);
5026
+ lines.push(name + " " + (el === null || el === void 0 ? "absent" : "l,t,w,h=" + rect(el)));
5027
+ };
5028
+ probe("[data-composer-card]", "[data-composer-card]");
5029
+ probe("[data-composer-seat]", "[data-composer-seat]");
5030
+ probe("textarea/contenteditable", 'textarea, [contenteditable="true"]');
5031
+ probe("[data-annotation-chip]", "[data-annotation-chip]");
5032
+ probe("[data-conversation-scroll]", "[data-conversation-scroll]");
5033
+ probe("widthHandle", '[class*="widthHandle"]');
5034
+ const dock = doc.querySelector("[data-dme-dock]");
5035
+ lines.push("dock " + (dock === null ? "absent" : "l,t,w,h=" + rect(dock) + " connected=" + String(dock.isConnected)));
5036
+ const chips = doc.querySelectorAll("[data-dme-chip]");
5037
+ lines.push("chips " + String(chips.length) + " " + Array.from(chips).map((chip) => rect(chip)).join(" | "));
5038
+ lines.push("pendingBlock " + String(pendingBlock === "" ? "empty" : pendingBlock.split(String.fromCharCode(10)).length + " lines"));
5039
+ lines.push("chipAttempt " + chipAttempt);
5040
+ lines.push("dockedCount " + String(dockReact?.count ?? 0) + " placedText " + String(placedText.length));
5041
+ lines.push("viewport " + String(globalThis.innerWidth) + "x" + String(globalThis.innerHeight));
5042
+ const report = lines.join(String.fromCharCode(10));
5043
+ try {
5044
+ globalThis.console?.log?.(report);
5045
+ } catch {
5046
+ }
5047
+ return report;
5048
+ }
5049
+ function installEnterCapture() {
5050
+ if (pendingBlock === "") return;
5051
+ const doc = globalThis.document;
5052
+ const composer = findComposer(doc);
5053
+ if (composer === void 0 || composer === null) return;
5054
+ if (enterWatch === composer) return;
5055
+ enterWatch = composer;
5056
+ const listen = composer.addEventListener;
5057
+ if (typeof listen !== "function") return;
5058
+ listen.call(composer, "keydown", (event) => {
5059
+ const key = event;
5060
+ if (key?.key !== "Enter" || key.shiftKey === true || key.isComposing === true) return;
5061
+ if (pendingBlock === "") return;
5062
+ const shell = draftShell();
5063
+ const draft = String(shell?.state?.getSnapshot?.()?.draft ?? "");
5064
+ const block = draft.trim() === "" ? withoutEmptyQuestion(pendingBlock) : pendingBlock;
5065
+ replaceBlock(block);
5066
+ const count = (block.match(/^Diagram note \[/gm) ?? []).length;
5067
+ const label = "\u56FE\u6CE8 \xD7" + String(count === 0 ? 1 : count);
5068
+ attachBelowBubble(label, draft);
5069
+ void attachSentChip;
5070
+ notifySent();
5071
+ pendingBlock = "";
5072
+ }, true);
5073
+ }
5074
+ function notifySent() {
5075
+ if (dockReact !== void 0) {
5076
+ const before = dockReact.count;
5077
+ dockReact = { count: 0, open: false, items: [], handlers: dockReact.handlers };
5078
+ if (before > 0) publishDockReceipt("\u56FE\u6CE8 \xD7" + String(before) + " \u5DF2\u53D1\u9001");
5079
+ try {
5080
+ scheduleDock();
5081
+ } catch {
5082
+ }
5083
+ }
5084
+ for (const listener of sentListeners.slice()) {
5085
+ try {
5086
+ listener();
5087
+ } catch {
5088
+ }
5089
+ }
5090
+ }
5091
+ function placeBlock(text2) {
5092
+ const shell = draftShell();
5093
+ const snapshot = shell?.state?.getSnapshot?.();
5094
+ const current = typeof snapshot?.draft === "string" ? String(snapshot.draft) : "";
5095
+ return replaceBlock(current.trim() === "" ? withoutEmptyQuestion(text2) : text2);
5096
+ }
5097
+ var sentListeners = [];
5098
+ var watchState = "idle";
5099
+ var lastSeenDraft = "";
5100
+ function onMessageSent(listener) {
5101
+ sentListeners.push(listener);
5102
+ watchDraft();
5103
+ return () => {
5104
+ sentListeners = sentListeners.filter((item) => item !== listener);
5105
+ };
5106
+ }
5107
+ function watchDraft() {
5108
+ if (watchState !== "idle") return;
5109
+ const shell = draftShell();
5110
+ const subscribe = shell?.state?.subscribe;
5111
+ if (typeof subscribe !== "function") {
5112
+ return;
5113
+ }
5114
+ watchState = "watching";
5115
+ try {
5116
+ lastSeenDraft = String(shell?.state?.getSnapshot?.()?.draft ?? "");
5117
+ subscribe(() => {
5118
+ const draft = String(shell?.state?.getSnapshot?.()?.draft ?? "");
5119
+ const before = lastSeenDraft;
5120
+ lastSeenDraft = draft;
5121
+ if (before.trim() === "" || draft.trim() !== "") return;
5122
+ if (placedText === "") return;
5123
+ placedText = "";
5124
+ for (const listener of sentListeners.slice()) {
5125
+ try {
5126
+ listener();
5127
+ } catch {
5128
+ }
5129
+ }
5130
+ });
5131
+ } catch {
5132
+ watchState = "unavailable";
5133
+ }
5134
+ }
5135
+ function submitDraft() {
5136
+ const shell = draftShell();
5137
+ if (shell === void 0 || typeof shell.submit !== "function") return false;
5138
+ try {
5139
+ shell.submit("queue");
5140
+ return true;
5141
+ } catch {
5142
+ return false;
5143
+ }
5144
+ }
3706
5145
  function viewFor(React, overrides = {}) {
3707
5146
  return (props) => {
5147
+ if (props.toolName === DRAWING_TOOL) return drawingCard(React, props, overrides);
3708
5148
  const diagram = viewModel({ phase: props.phase, toolName: props.toolName, block: props.block });
3709
5149
  const { canvas, colours } = paintWith(diagram, overrides, { mode: themeMode() });
3710
5150
  const written = toSvg(canvas, colours, diagram.kind === "none" ? diagram.caption : diagram.title + ": " + diagram.caption);
@@ -3744,41 +5184,113 @@ window.__ModuleLoader__.load({
3744
5184
  const [scheme, setScheme] = useState("default");
3745
5185
  const [fit, setFit] = useState(true);
3746
5186
  const [folded, setFolded] = useState([]);
5187
+ const [annotate, setAnnotate] = useState(false);
5188
+ const [picked, setPicked] = useState(null);
5189
+ const [anchor2, setAnchor] = useState(void 0);
5190
+ const [note, setNote] = useState("");
5191
+ const [status, setStatus] = useState("");
5192
+ const [pending, setPending] = useState([]);
5193
+ const [open, setOpen] = useState(false);
5194
+ React.useEffect?.(() => {
5195
+ try {
5196
+ return onMessageSent(() => {
5197
+ setPending([]);
5198
+ setStatus("");
5199
+ });
5200
+ } catch {
5201
+ return void 0;
5202
+ }
5203
+ }, []);
3747
5204
  const drawn = drawSample(React, overrides, source, fit ? 0 : zoom, scheme, folded);
5205
+ const document = globalThis.document;
5206
+ const caption = source.split(String.fromCharCode(10)).map((line) => line.trim()).find((line) => line !== "") ?? "";
5207
+ const sendAll = (list, submit) => {
5208
+ if (list.length === 0) return;
5209
+ const text2 = annotationBlock(list.map((item) => ({ ...item, caption })));
5210
+ void (async () => {
5211
+ if (placeBlock(text2)) {
5212
+ setStatus("\u5DF2\u653E\u5165\u8F93\u5165\u6846\u5E76\u63D0\u4EA4\uFF08" + String(list.length) + " \u6761\u56FE\u6CE8\uFF09");
5213
+ setPending([]);
5214
+ if (submit) submitDraft();
5215
+ return;
5216
+ }
5217
+ const said = prependBlock(document, list, caption);
5218
+ setStatus(said);
5219
+ if (!said.startsWith("\u5DF2")) return;
5220
+ setPending([]);
5221
+ if (submit) submitComposer(document);
5222
+ })();
5223
+ };
5224
+ const addDraft = () => {
5225
+ if (picked === null) return false;
5226
+ const merged = [...pending, { nodeId: picked.id, note }];
5227
+ setPending(merged);
5228
+ setNote("");
5229
+ setPicked(null);
5230
+ setStatus("\u5DF2\u653E\u5165\u8F93\u5165\u6846\uFF0C\u76F4\u63A5\u56DE\u8F66\u5373\u53EF");
5231
+ return true;
5232
+ };
5233
+ const addAndSend = () => {
5234
+ if (picked === null) return;
5235
+ const merged = [...pending, { nodeId: picked.id, note }];
5236
+ setNote("");
5237
+ setPicked(null);
5238
+ sendAll(merged, true);
5239
+ };
3748
5240
  const textarea = h("textarea", {
5241
+ "data-dme-own": "1",
3749
5242
  value: source,
3750
5243
  spellcheck: false,
3751
5244
  rows: Math.min(12, Math.max(4, String(source).split("\n").length)),
3752
- style: { width: "100%", font: "12px ui-monospace, SFMono-Regular, Menlo, monospace", padding: "6px", resize: "vertical" },
5245
+ style: { width: "100%", boxSizing: "border-box", font: "12px ui-monospace, SFMono-Regular, Menlo, monospace", padding: "6px", resize: "vertical", borderRadius: "6px", border: "1px solid " + TOKEN.border, background: "transparent", color: TOKEN.text },
3753
5246
  onInput: (event) => setSource(String(event?.target?.value ?? ""))
3754
5247
  });
5248
+ const controlStyle = { fontSize: "11px", lineHeight: "18px", padding: "1px 7px", borderRadius: "6px", border: "1px solid " + TOKEN.border, background: "transparent", color: TOKEN.text, cursor: "pointer" };
5249
+ const control = (label, onPress, title) => h("button", { type: "button", title, onClick: onPress, style: controlStyle }, label);
3755
5250
  const controls = h(
3756
5251
  "div",
3757
- { style: { display: "flex", gap: "6px", alignItems: "center", padding: "4px 0", flexWrap: "wrap" } },
3758
- h("button", { type: "button", onClick: () => {
3759
- setFit(false);
3760
- setZoom(Math.max(0.5, Math.round((Number(zoom) - 0.25) * 100) / 100));
3761
- } }, "\u2212"),
3762
- h("span", { style: { fontSize: "12px", opacity: 0.7 } }, fit ? "fit" : String(Math.round(Number(zoom) * 100)) + "%"),
3763
- h("button", { type: "button", onClick: () => {
3764
- setFit(false);
3765
- setZoom(Math.min(3, Math.round((Number(zoom) + 0.25) * 100) / 100));
3766
- } }, "+"),
3767
- h("button", { type: "button", onClick: () => {
3768
- setFit(false);
3769
- setZoom(1);
3770
- } }, "reset"),
3771
- h("button", { type: "button", title: "Scale to the pane width", onClick: () => setFit(!fit) }, fit ? "fit: on" : "fit: off"),
3772
- folded.length === 0 ? null : h("button", { type: "button", title: "Unfold every group", onClick: () => setFolded([]) }, "unfold " + String(folded.length)),
5252
+ { style: { display: "flex", flexDirection: "column", gap: "3px", padding: "2px 0" } },
3773
5253
  h(
3774
- "select",
3775
- {
3776
- value: scheme,
3777
- title: "Colour scheme",
3778
- style: { marginLeft: "auto", fontSize: "12px" },
3779
- onChange: (event) => setScheme(String(event?.target?.value ?? "default"))
3780
- },
3781
- ...schemeNames().map((name) => h("option", { value: name, selected: name === scheme }, name))
5254
+ "div",
5255
+ { style: { display: "flex", gap: "4px", alignItems: "center", flexWrap: "wrap" } },
5256
+ control("\u2212", () => {
5257
+ setFit(false);
5258
+ setZoom(Math.max(0.5, Math.round((Number(zoom) - 0.25) * 100) / 100));
5259
+ }, "\u7F29\u5C0F"),
5260
+ h("span", { style: { fontSize: "11px", color: TOKEN.dim, minWidth: "34px", textAlign: "center" } }, fit ? "fit" : String(Math.round(Number(zoom) * 100)) + "%"),
5261
+ control("+", () => {
5262
+ setFit(false);
5263
+ setZoom(Math.min(3, Math.round((Number(zoom) + 0.25) * 100) / 100));
5264
+ }, "\u653E\u5927"),
5265
+ control("100%", () => {
5266
+ setFit(false);
5267
+ setZoom(1);
5268
+ }, "\u5B9E\u9645\u5927\u5C0F"),
5269
+ control(fit ? t("fitOn") : t("fitOff"), () => setFit(!fit), t("fitOff")),
5270
+ folded.length === 0 ? null : control(t("unfold") + " " + String(folded.length), () => setFolded([]), "\u5C55\u5F00\u6240\u6709\u5206\u7EC4"),
5271
+ h(
5272
+ "select",
5273
+ {
5274
+ value: scheme,
5275
+ title: t("scheme"),
5276
+ style: { marginLeft: "auto", fontSize: "11px", padding: "1px 4px", borderRadius: "6px", border: "1px solid " + TOKEN.border, background: "transparent", color: TOKEN.text },
5277
+ onChange: (event) => setScheme(String(event?.target?.value ?? "default"))
5278
+ },
5279
+ ...schemeNames().map((name) => h("option", { value: name, selected: name === scheme }, name))
5280
+ )
5281
+ ),
5282
+ h(
5283
+ "div",
5284
+ { style: { display: "flex", gap: "6px", alignItems: "center" } },
5285
+ control(annotate ? t("noteOn") : t("note"), () => {
5286
+ setAnnotate(!annotate);
5287
+ setStatus("");
5288
+ if (annotate) {
5289
+ setPicked(null);
5290
+ setNote("");
5291
+ }
5292
+ }, t("noteHint")),
5293
+ h("span", { style: { fontSize: "11px", color: TOKEN.dim } }, annotate ? picked === null ? t("noteHint") : t("node") + " " + picked.id : t("noteHint"))
3782
5294
  )
3783
5295
  );
3784
5296
  return h(
@@ -3786,21 +5298,76 @@ window.__ModuleLoader__.load({
3786
5298
  { style: { display: "flex", flexDirection: "column", gap: "4px", height: "100%", boxSizing: "border-box", padding: "8px" } },
3787
5299
  textarea,
3788
5300
  controls,
3789
- // The drawing takes the rest of the pane and scrolls inside it, so an expanded tab uses its room.
5301
+ // The drawing takes the rest of the pane and scrolls inside it; the annotation surface floats above it,
5302
+ // so the picture keeps its size while the reader writes about it.
3790
5303
  h(
3791
5304
  "div",
3792
5305
  {
3793
- style: { flex: "1 1 auto", minHeight: "0", overflow: "auto" },
3794
- // A boundary carries its id in the markup, so one listener on the container is enough: no per-rect
3795
- // handler, and the handling survives a re-render that replaced the whole SVG.
3796
- onClick: (event) => {
3797
- const hit = event?.target?.closest?.("[data-group-id]");
3798
- const id = hit?.getAttribute?.("data-group-id");
3799
- if (typeof id !== "string" || id === "") return;
3800
- setFolded(folded.includes(id) ? folded.filter((entry) => entry !== id) : [...folded, id]);
3801
- }
5306
+ style: { position: "relative", flex: "1 1 auto", minHeight: "0", display: "flex", flexDirection: "column", gap: "2px" }
3802
5307
  },
3803
- drawn
5308
+ h(
5309
+ "div",
5310
+ {
5311
+ style: { flex: "1 1 auto", minHeight: "0", overflow: "auto" },
5312
+ // A boundary carries its id in the markup, so one listener on the container is enough: no per-rect
5313
+ // handler, and the handling survives a re-render that replaced the whole SVG.
5314
+ onClick: (event) => {
5315
+ if (annotate) {
5316
+ const node = event?.target?.closest?.("[data-node-id]");
5317
+ const marked = node?.getAttribute?.("data-node-id");
5318
+ if (typeof marked === "string" && marked !== "") {
5319
+ const pointer = event;
5320
+ const frame = pointer.currentTarget?.getBoundingClientRect?.();
5321
+ if (frame !== void 0 && typeof pointer.clientX === "number" && typeof pointer.clientY === "number") {
5322
+ setAnchor({
5323
+ left: Math.max(4, Math.min(pointer.clientX - frame.left + 12, frame.width - 270)),
5324
+ top: Math.max(4, Math.min(pointer.clientY - frame.top + 12, Math.max(4, frame.height - 160)))
5325
+ });
5326
+ } else {
5327
+ setAnchor({ left: 10, top: 10 });
5328
+ }
5329
+ setPicked({ id: marked });
5330
+ setStatus("");
5331
+ return;
5332
+ }
5333
+ if (note.trim() === "") {
5334
+ setPicked(null);
5335
+ setAnchor(void 0);
5336
+ }
5337
+ return;
5338
+ }
5339
+ const hit = event?.target?.closest?.("[data-group-id]");
5340
+ const id = hit?.getAttribute?.("data-group-id");
5341
+ if (typeof id !== "string" || id === "") return;
5342
+ setFolded(folded.includes(id) ? folded.filter((entry) => entry !== id) : [...folded, id]);
5343
+ }
5344
+ },
5345
+ drawn
5346
+ ),
5347
+ annotate ? annotationPanel(
5348
+ h,
5349
+ { picked, note, pending, status, anchor: anchor2, open },
5350
+ {
5351
+ onNote: setNote,
5352
+ onAdd: () => {
5353
+ addDraft();
5354
+ },
5355
+ onAddAndSend: addAndSend,
5356
+ onSend: () => sendAll(pending, true),
5357
+ onClear: () => {
5358
+ setPending([]);
5359
+ setStatus("");
5360
+ },
5361
+ onCancel: () => {
5362
+ setPicked(null);
5363
+ setNote("");
5364
+ setStatus("");
5365
+ },
5366
+ onToggle: () => setOpen(!open),
5367
+ onRemove: (index) => setPending(pending.filter((_, at) => at !== index))
5368
+ },
5369
+ { document }
5370
+ ) : null
3804
5371
  )
3805
5372
  );
3806
5373
  };
@@ -3864,10 +5431,13 @@ window.__ModuleLoader__.load({
3864
5431
  inject: ["slots"],
3865
5432
  mount: (ctx, options = {}) => mountWhiteboard(React, ctx, options),
3866
5433
  apply(ctx) {
5434
+ services = ctx;
5435
+ void startTranscriptDecoration;
3867
5436
  for (const name of TOOL_NAMES) {
3868
5437
  ctx.slots.inject("tool.call.toolview", () => ctx.slots.register({ name: "tool.call.toolview", key: name }, viewFor(React)));
3869
5438
  }
3870
5439
  ctx.slots.inject("sidebar.right.pane.tab", () => mountWhiteboard(React, ctx));
5440
+ void dockSlotView;
3871
5441
  }
3872
5442
  };
3873
5443
  }