dsh-context 0.21.1 → 0.22.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.
- package/README.md +8 -0
- package/lib/client.js +197 -27
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -86,6 +86,14 @@ Six collapsible category sections (system prompt, tool schemas, user messages, i
|
|
|
86
86
|
- **Linked with the history chart** — hover any bar in the History card and the browser previews that step instantly; leave the chart and it returns to your own pick. Keep a category open while scrubbing to compare one category across steps.
|
|
87
87
|
- **Honest about coverage** — steps before a compaction are reconstructed from the removed-message archive, and the card says so when a step's makeup is only approximate. Elements older than the loaded chat window page older history in automatically when you expand them, and live injections (AGENTS.md, session-start context, …) are always listed — never a token sum without its items.
|
|
88
88
|
|
|
89
|
+
### 🖼 Multimodal — image attachments in full view (DeepSeek Harness 0.1.1+)
|
|
90
|
+
|
|
91
|
+
Fully adapted to DeepSeek Harness 0.1.1's multimodal pipeline and the vision capability of **DeepSeek-V4-Flash-Vision-Exp**. A user message carrying images expands into a card layout — prose in the text card (with the usual raw/Markdown toggle), each image attachment as a thumbnail card with its name, normalized dimensions (plus the pre-normalization size when 0.1.1's image pipeline downscaled it) and stored size, and anything unrecognized as raw content:
|
|
92
|
+
|
|
93
|
+

|
|
94
|
+
|
|
95
|
+
Images load through the harness's own session-authorized loader — the same one the chat history uses — and degrade to metadata-only cards when it is unavailable. Image blocks in assistant messages and tool results (e.g. `read_image` output) now render too, instead of being silently dropped.
|
|
96
|
+
|
|
89
97
|
## Like it?
|
|
90
98
|
|
|
91
99
|
If `dsh-context` helped you understand what your agent is carrying around, a ⭐ on [GitHub](https://github.com/bowenliang123/dsh-context) is much appreciated — and issues/PRs are welcome!
|
package/lib/client.js
CHANGED
|
@@ -116,7 +116,22 @@ var DICT_ZH = {
|
|
|
116
116
|
"rich.raw": "\u539F\u6587",
|
|
117
117
|
"rich.md": "Markdown",
|
|
118
118
|
"rich.toMd": "\u6309 Markdown \u6E32\u67D3\u67E5\u770B",
|
|
119
|
-
"rich.toRaw": "\u67E5\u770B\u539F\u59CB\u6587\u672C"
|
|
119
|
+
"rich.toRaw": "\u67E5\u770B\u539F\u59CB\u6587\u672C",
|
|
120
|
+
// Assistant-message block titles inside the detail card: the reasoning
|
|
121
|
+
// trace and the response each carry a small label (Reasoning / Response,
|
|
122
|
+
// mirroring the harness's own block + locale vocabulary).
|
|
123
|
+
"block.thinking": "\u601D\u8003",
|
|
124
|
+
"block.answer": "\u56DE\u7B54",
|
|
125
|
+
// Attachment cards in a message detail: image refs render as thumbnail
|
|
126
|
+
// cards (name + normalized dims + stored size), anything unrecognized
|
|
127
|
+
// falls into the generic raw-JSON card.
|
|
128
|
+
"attach.images": "\u56FE\u7247\u9644\u4EF6",
|
|
129
|
+
"attach.other": "\u5176\u4ED6\u5185\u5BB9",
|
|
130
|
+
"attach.image": "\u56FE\u7247",
|
|
131
|
+
"attach.open": "\u67E5\u770B\u539F\u56FE",
|
|
132
|
+
"attach.loading": "\u2026",
|
|
133
|
+
"attach.loadFailed": "\u52A0\u8F7D\u5931\u8D25 \xB7 \u70B9\u51FB\u91CD\u8BD5",
|
|
134
|
+
"attach.orig": "\u539F\u56FE {d}"
|
|
120
135
|
};
|
|
121
136
|
var DICT_EN = {
|
|
122
137
|
"tab": "Context",
|
|
@@ -227,7 +242,22 @@ var DICT_EN = {
|
|
|
227
242
|
"rich.raw": "Raw",
|
|
228
243
|
"rich.md": "Markdown",
|
|
229
244
|
"rich.toMd": "View as Markdown",
|
|
230
|
-
"rich.toRaw": "View Raw Text"
|
|
245
|
+
"rich.toRaw": "View Raw Text",
|
|
246
|
+
// Assistant-message block titles inside the detail card: the reasoning
|
|
247
|
+
// trace and the response each carry a small label (Reasoning / Response,
|
|
248
|
+
// mirroring the harness's own block + locale vocabulary).
|
|
249
|
+
"block.thinking": "Reasoning",
|
|
250
|
+
"block.answer": "Response",
|
|
251
|
+
// Attachment cards in a message detail: image refs render as thumbnail
|
|
252
|
+
// cards (name + normalized dims + stored size), anything unrecognized
|
|
253
|
+
// falls into the generic raw-JSON card.
|
|
254
|
+
"attach.images": "Images",
|
|
255
|
+
"attach.other": "Other content",
|
|
256
|
+
"attach.image": "Image",
|
|
257
|
+
"attach.open": "Open full image",
|
|
258
|
+
"attach.loading": "\u2026",
|
|
259
|
+
"attach.loadFailed": "Load failed \xB7 click to retry",
|
|
260
|
+
"attach.orig": "original {d}"
|
|
231
261
|
};
|
|
232
262
|
|
|
233
263
|
// src/client/modalStore.ts
|
|
@@ -467,6 +497,96 @@ function makeNodeList(kit) {
|
|
|
467
497
|
};
|
|
468
498
|
}
|
|
469
499
|
|
|
500
|
+
// src/client/format.ts
|
|
501
|
+
function fmt(n) {
|
|
502
|
+
if (n === void 0 || n === null || isNaN(n)) return "\u2014";
|
|
503
|
+
if (n >= 1e6) return (n / 1e6).toFixed(1) + "M";
|
|
504
|
+
if (n >= 1e3) return (n / 1e3).toFixed(1) + "k";
|
|
505
|
+
return String(Math.round(n));
|
|
506
|
+
}
|
|
507
|
+
function fmtBytes(n) {
|
|
508
|
+
if (n === void 0 || n === null || isNaN(n) || n < 0) return "\u2014";
|
|
509
|
+
if (n >= 1e6) return (n / 1e6).toFixed(1) + " MB";
|
|
510
|
+
if (n >= 1e3) return (n / 1e3).toFixed(1) + " kB";
|
|
511
|
+
return String(Math.round(n)) + " B";
|
|
512
|
+
}
|
|
513
|
+
function fmtTime(t) {
|
|
514
|
+
const d = new Date(t);
|
|
515
|
+
if (isNaN(d.getTime())) return "\u2014";
|
|
516
|
+
return d.toLocaleTimeString("en-GB", { hour12: false });
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
// src/client/components/images.tsx
|
|
520
|
+
function imageRefOf(block) {
|
|
521
|
+
if (block === null || typeof block !== "object") return null;
|
|
522
|
+
const b = block;
|
|
523
|
+
if (b.type !== "image" && b.kind !== "image") return null;
|
|
524
|
+
const a = b.attachment;
|
|
525
|
+
if (a === null || typeof a !== "object") return null;
|
|
526
|
+
const r = a;
|
|
527
|
+
if (typeof r.attachmentId !== "string" || r.attachmentId === "") return null;
|
|
528
|
+
const num = (v) => typeof v === "number" && Number.isFinite(v) && v > 0 ? v : void 0;
|
|
529
|
+
const orig = r.originalDimensions !== null && typeof r.originalDimensions === "object" ? r.originalDimensions : void 0;
|
|
530
|
+
const origDims = orig !== void 0 && num(orig.width) !== void 0 && num(orig.height) !== void 0 ? { width: num(orig.width), height: num(orig.height) } : void 0;
|
|
531
|
+
return {
|
|
532
|
+
attachmentId: r.attachmentId,
|
|
533
|
+
...typeof r.name === "string" && r.name !== "" ? { name: r.name } : {},
|
|
534
|
+
...num(r.bytes) !== void 0 ? { bytes: num(r.bytes) } : {},
|
|
535
|
+
...num(r.width) !== void 0 ? { width: num(r.width) } : {},
|
|
536
|
+
...num(r.height) !== void 0 ? { height: num(r.height) } : {},
|
|
537
|
+
...origDims !== void 0 ? { originalDimensions: origDims } : {}
|
|
538
|
+
};
|
|
539
|
+
}
|
|
540
|
+
function makeImageCard(kit) {
|
|
541
|
+
const { t } = kit;
|
|
542
|
+
return function ImageCard(props) {
|
|
543
|
+
const { attachment, load } = props;
|
|
544
|
+
const [src, setSrc] = React.useState(null);
|
|
545
|
+
const [error, setError] = React.useState(false);
|
|
546
|
+
const [attempt, setAttempt] = React.useState(0);
|
|
547
|
+
React.useEffect(() => {
|
|
548
|
+
if (load === void 0) return;
|
|
549
|
+
let live = true;
|
|
550
|
+
setError(false);
|
|
551
|
+
setSrc(null);
|
|
552
|
+
void load(attachment).then((url) => {
|
|
553
|
+
if (live) setSrc(url);
|
|
554
|
+
}).catch(() => {
|
|
555
|
+
if (live) setError(true);
|
|
556
|
+
});
|
|
557
|
+
return () => {
|
|
558
|
+
live = false;
|
|
559
|
+
};
|
|
560
|
+
}, [attachment, load, attempt]);
|
|
561
|
+
const name = attachment.name ?? t("attach.image");
|
|
562
|
+
const dims = attachment.width !== void 0 && attachment.height !== void 0 ? attachment.width + "\xD7" + attachment.height : null;
|
|
563
|
+
const orig = attachment.originalDimensions;
|
|
564
|
+
const facts = [];
|
|
565
|
+
if (dims !== null) facts.push(dims);
|
|
566
|
+
if (orig !== void 0) facts.push(t("attach.orig", { d: orig.width + "\xD7" + orig.height }));
|
|
567
|
+
if (attachment.bytes !== void 0) facts.push(fmtBytes(attachment.bytes));
|
|
568
|
+
const open = () => {
|
|
569
|
+
if (src === null) return;
|
|
570
|
+
try {
|
|
571
|
+
window.open(src, "_blank", "noopener");
|
|
572
|
+
} catch {
|
|
573
|
+
}
|
|
574
|
+
};
|
|
575
|
+
return /* @__PURE__ */ React.createElement("div", { className: "lc-att-item" }, /* @__PURE__ */ React.createElement(
|
|
576
|
+
"button",
|
|
577
|
+
{
|
|
578
|
+
type: "button",
|
|
579
|
+
className: "lc-att-thumb",
|
|
580
|
+
title: error ? t("attach.loadFailed") : t("attach.open"),
|
|
581
|
+
onClick: error ? () => {
|
|
582
|
+
setAttempt((a) => a + 1);
|
|
583
|
+
} : open
|
|
584
|
+
},
|
|
585
|
+
src !== null ? /* @__PURE__ */ React.createElement("img", { src, alt: name }) : /* @__PURE__ */ React.createElement("span", { className: error ? "lc-att-err" : "lc-att-ph" }, error ? "\u26A0" : load === void 0 ? "\u{1F5BC}" : t("attach.loading"))
|
|
586
|
+
), /* @__PURE__ */ React.createElement("div", { className: "lc-att-meta" }, /* @__PURE__ */ React.createElement("span", { className: "lc-att-name", title: name }, name), facts.length > 0 ? /* @__PURE__ */ React.createElement("span", { className: "lc-att-dims" }, facts.join(" \xB7 ")) : null));
|
|
587
|
+
};
|
|
588
|
+
}
|
|
589
|
+
|
|
470
590
|
// src/client/components/richText.tsx
|
|
471
591
|
var import_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
472
592
|
function makeRichText(kit) {
|
|
@@ -601,7 +721,7 @@ function ToolSchema(props) {
|
|
|
601
721
|
), jsonOpen ? /* @__PURE__ */ React.createElement("pre", { className: "lc-br-pre lc-br-dim" }, schemaJson) : null) : null);
|
|
602
722
|
}
|
|
603
723
|
function RawBlocks(props) {
|
|
604
|
-
const { rich } = props;
|
|
724
|
+
const { rich, img } = props;
|
|
605
725
|
return /* @__PURE__ */ React.createElement(React.Fragment, null, props.blocks.map((b, i) => {
|
|
606
726
|
const blk = b;
|
|
607
727
|
if (blk !== null && typeof blk === "object" && (blk.type === "text" || blk.type === "reasoning") && typeof blk.text === "string") {
|
|
@@ -610,14 +730,16 @@ function RawBlocks(props) {
|
|
|
610
730
|
}
|
|
611
731
|
return /* @__PURE__ */ React.createElement(rich.RichText, { key: i, text: blk.text, mode: props.mode });
|
|
612
732
|
}
|
|
733
|
+
const image = imageRefOf(b);
|
|
734
|
+
if (image !== null) return /* @__PURE__ */ React.createElement(img.Card, { key: i, attachment: image, load: img.load });
|
|
613
735
|
if (blk !== null && typeof blk === "object" && blk.type === "tool-result" && Array.isArray(blk.content)) {
|
|
614
|
-
return /* @__PURE__ */ React.createElement(RawBlocks, { key: i, blocks: blk.content, mode: props.mode, rich });
|
|
736
|
+
return /* @__PURE__ */ React.createElement(RawBlocks, { key: i, blocks: blk.content, mode: props.mode, rich, img });
|
|
615
737
|
}
|
|
616
738
|
return /* @__PURE__ */ React.createElement("pre", { key: i, className: "lc-br-pre lc-br-dim" }, JSON.stringify(b, null, 2));
|
|
617
739
|
}));
|
|
618
740
|
}
|
|
619
741
|
function NodeContent(props) {
|
|
620
|
-
const { node, conv, rich } = props;
|
|
742
|
+
const { node, conv, rich, img } = props;
|
|
621
743
|
const richable = node.cat === "user" || node.cat === "assistant" || node.cat === "inject";
|
|
622
744
|
const wrap = (render) => richable ? /* @__PURE__ */ React.createElement(rich.RichCard, { render }) : /* @__PURE__ */ React.createElement("div", { className: "lc-br-content" }, render("raw"));
|
|
623
745
|
if (conv === void 0) {
|
|
@@ -631,25 +753,52 @@ function NodeContent(props) {
|
|
|
631
753
|
return wrap((mode) => /* @__PURE__ */ React.createElement(React.Fragment, null, blocks.map((b, i) => {
|
|
632
754
|
const blk = b;
|
|
633
755
|
if (blk.kind === "text" && typeof blk.text === "string") {
|
|
634
|
-
return /* @__PURE__ */ React.createElement(
|
|
756
|
+
return /* @__PURE__ */ React.createElement("div", { key: i, className: "lc-br-blk" }, /* @__PURE__ */ React.createElement("div", { className: "lc-br-blk-label" }, props.labels.answer), /* @__PURE__ */ React.createElement(rich.RichText, { text: blk.text, mode }));
|
|
635
757
|
}
|
|
636
758
|
if (blk.kind === "reasoning" && typeof blk.text === "string") {
|
|
637
|
-
return /* @__PURE__ */ React.createElement("
|
|
759
|
+
return /* @__PURE__ */ React.createElement("div", { key: i, className: "lc-br-blk" }, /* @__PURE__ */ React.createElement("div", { className: "lc-br-blk-label" }, props.labels.thinking), /* @__PURE__ */ React.createElement("pre", { className: "lc-br-pre lc-br-dim" }, blk.text));
|
|
638
760
|
}
|
|
639
761
|
if (blk.kind === "tool-call") {
|
|
640
762
|
return /* @__PURE__ */ React.createElement("div", { key: i, className: "lc-br-call" }, /* @__PURE__ */ React.createElement("span", { className: "lc-br-tag" }, "\u2192 " + String(blk.name ?? "?")), typeof blk.argsRaw === "string" && blk.argsRaw !== "" ? /* @__PURE__ */ React.createElement("pre", { className: "lc-br-pre lc-br-dim" }, blk.argsRaw) : null);
|
|
641
763
|
}
|
|
764
|
+
const image = imageRefOf(b);
|
|
765
|
+
if (image !== null) return /* @__PURE__ */ React.createElement(img.Card, { key: i, attachment: image, load: img.load });
|
|
642
766
|
return null;
|
|
643
767
|
})));
|
|
644
768
|
}
|
|
645
769
|
if (conv.kind === "tool-result") {
|
|
646
|
-
return /* @__PURE__ */ React.createElement("div", { className: "lc-br-content" }, conv.call != null ? /* @__PURE__ */ React.createElement("div", { className: "lc-br-call" }, /* @__PURE__ */ React.createElement("span", { className: "lc-br-tag" }, "\u2190 " + conv.call.name), conv.call.argsRaw !== "" ? /* @__PURE__ */ React.createElement("pre", { className: "lc-br-pre lc-br-dim" }, conv.call.argsRaw) : null) : null, Array.isArray(conv.content) ? /* @__PURE__ */ React.createElement(RawBlocks, { blocks: conv.content, mode: "raw", rich }) : null);
|
|
770
|
+
return /* @__PURE__ */ React.createElement("div", { className: "lc-br-content" }, conv.call != null ? /* @__PURE__ */ React.createElement("div", { className: "lc-br-call" }, /* @__PURE__ */ React.createElement("span", { className: "lc-br-tag" }, "\u2190 " + conv.call.name), conv.call.argsRaw !== "" ? /* @__PURE__ */ React.createElement("pre", { className: "lc-br-pre lc-br-dim" }, conv.call.argsRaw) : null) : null, Array.isArray(conv.content) ? /* @__PURE__ */ React.createElement(RawBlocks, { blocks: conv.content, mode: "raw", rich, img }) : null);
|
|
647
771
|
}
|
|
648
772
|
if (conv.kind === "compaction") {
|
|
649
773
|
return wrap((mode) => /* @__PURE__ */ React.createElement(React.Fragment, null, typeof conv.summary === "string" && conv.summary !== "" ? /* @__PURE__ */ React.createElement(rich.RichText, { text: conv.summary, mode }) : null));
|
|
650
774
|
}
|
|
651
775
|
if (Array.isArray(conv.content)) {
|
|
652
|
-
|
|
776
|
+
const blocks = conv.content;
|
|
777
|
+
if (node.cat !== "user") {
|
|
778
|
+
return wrap((mode) => /* @__PURE__ */ React.createElement(RawBlocks, { blocks, mode, rich, img }));
|
|
779
|
+
}
|
|
780
|
+
const texts = [];
|
|
781
|
+
const images = [];
|
|
782
|
+
const others = [];
|
|
783
|
+
for (const b of blocks) {
|
|
784
|
+
const blk = b;
|
|
785
|
+
if (blk !== null && typeof blk === "object" && blk.type === "text" && typeof blk.text === "string") {
|
|
786
|
+
texts.push(blk.text);
|
|
787
|
+
continue;
|
|
788
|
+
}
|
|
789
|
+
const image = imageRefOf(b);
|
|
790
|
+
if (image !== null) {
|
|
791
|
+
images.push(image);
|
|
792
|
+
continue;
|
|
793
|
+
}
|
|
794
|
+
others.push(b);
|
|
795
|
+
}
|
|
796
|
+
return /* @__PURE__ */ React.createElement("div", { className: "lc-br-content" }, texts.length > 0 ? (
|
|
797
|
+
// Un-padded RichCard: the outer lc-br-content already owns the
|
|
798
|
+
// body indent, so the text card aligns with the attachment cards
|
|
799
|
+
// instead of sitting one indent deeper.
|
|
800
|
+
/* @__PURE__ */ React.createElement(rich.RichCard, { className: "lc-br-rich-inline", render: (mode) => /* @__PURE__ */ React.createElement(React.Fragment, null, texts.map((text, i) => /* @__PURE__ */ React.createElement(rich.RichText, { key: i, text, mode }))) })
|
|
801
|
+
) : null, images.length > 0 ? /* @__PURE__ */ React.createElement("div", { className: "lc-ts-card" }, /* @__PURE__ */ React.createElement("div", { className: "lc-ts-card-head" }, /* @__PURE__ */ React.createElement("b", null, props.labels.images), /* @__PURE__ */ React.createElement("span", { className: "lc-ts-card-count" }, images.length)), /* @__PURE__ */ React.createElement("div", { className: "lc-att-grid" }, images.map((a, i) => /* @__PURE__ */ React.createElement(img.Card, { key: a.attachmentId + ":" + i, attachment: a, load: img.load })))) : null, others.length > 0 ? /* @__PURE__ */ React.createElement("div", { className: "lc-ts-card" }, /* @__PURE__ */ React.createElement("div", { className: "lc-ts-card-head" }, /* @__PURE__ */ React.createElement("b", null, props.labels.other), /* @__PURE__ */ React.createElement("span", { className: "lc-ts-card-count" }, others.length)), others.map((b, i) => /* @__PURE__ */ React.createElement("pre", { key: i, className: "lc-br-pre lc-br-dim" }, JSON.stringify(b, null, 2)))) : null);
|
|
653
802
|
}
|
|
654
803
|
return /* @__PURE__ */ React.createElement("div", { className: "lc-br-content" }, /* @__PURE__ */ React.createElement("div", { className: "lc-br-note" }, props.hint));
|
|
655
804
|
}
|
|
@@ -672,6 +821,7 @@ function makeContextBrowser(kit, StackedBar) {
|
|
|
672
821
|
const { t, fmt: fmt3, fmtTime: fmtTime2, catLabel } = kit;
|
|
673
822
|
const nodeText = makeNodeText(kit);
|
|
674
823
|
const rich = makeRichText(kit);
|
|
824
|
+
const ImageCard = makeImageCard(kit);
|
|
675
825
|
const catColor = {};
|
|
676
826
|
for (const c of CATS) catColor[c.key] = c.color;
|
|
677
827
|
const MAX_AUTO_PAGES = 20;
|
|
@@ -816,6 +966,13 @@ function makeContextBrowser(kit, StackedBar) {
|
|
|
816
966
|
node: n,
|
|
817
967
|
conv: bySeq.get(n.seq),
|
|
818
968
|
rich,
|
|
969
|
+
img: { Card: ImageCard, load: props.loadImage },
|
|
970
|
+
labels: {
|
|
971
|
+
thinking: t("block.thinking"),
|
|
972
|
+
answer: t("block.answer"),
|
|
973
|
+
images: t("attach.images"),
|
|
974
|
+
other: t("attach.other")
|
|
975
|
+
},
|
|
819
976
|
hint: bySeq.get(n.seq) === void 0 && awaiting ? t("browser.loading") : t("browser.noContent")
|
|
820
977
|
}
|
|
821
978
|
)
|
|
@@ -1422,6 +1579,11 @@ var STYLES = [
|
|
|
1422
1579
|
".lc-br-pre { margin: 0; padding: 8px 10px; background: var(--dsw-alias-bg-layer-2); border: 1px solid var(--dsw-alias-border-l1); border-radius: 6px; color: var(--dsw-alias-label-primary); font-size: 12px; line-height: 1.55; white-space: pre-wrap; word-break: break-word; max-height: 320px; overflow-y: auto; scrollbar-width: thin; }",
|
|
1423
1580
|
".lc-br-dim { color: var(--dsw-alias-label-secondary); }",
|
|
1424
1581
|
".lc-br-call { display: flex; flex-direction: column; gap: 4px; align-items: flex-start; }",
|
|
1582
|
+
// Assistant-message block title: a slim label line above each block
|
|
1583
|
+
// (thinking / answer) so a mixed reply stays scannable — same weight and
|
|
1584
|
+
// tone as the tool-schema card heads, without an extra bordered card.
|
|
1585
|
+
".lc-br-blk { display: flex; flex-direction: column; gap: 4px; }",
|
|
1586
|
+
".lc-br-blk-label { font-size: 11px; font-weight: 600; color: var(--dsw-alias-label-secondary); }",
|
|
1425
1587
|
// ---- Tool schema body (browser card, tools category). The description
|
|
1426
1588
|
// and parameter table share one "card with a small title" chrome — a
|
|
1427
1589
|
// labeled bordered block so a reader can scan three stacked sections
|
|
@@ -1481,26 +1643,27 @@ var STYLES = [
|
|
|
1481
1643
|
".lc-br-md div p, .lc-ts-desc-md div p { margin: 6px 0; }",
|
|
1482
1644
|
".lc-br-md div pre, .lc-ts-desc-md div pre { margin: 6px 0; }",
|
|
1483
1645
|
".lc-br-md div :not(pre) > code, .lc-ts-desc-md div :not(pre) > code { font-size: 1em !important; line-height: 1.3; padding: 1px 5px; box-decoration-break: clone; }",
|
|
1484
|
-
".lc-br-md div table code, .lc-ts-desc-md div table code { font-size: inherit; }"
|
|
1646
|
+
".lc-br-md div table code, .lc-ts-desc-md div table code { font-size: inherit; }",
|
|
1647
|
+
// Un-padded RichCard variant: used when the text card is one section
|
|
1648
|
+
// among several (attachment cards) inside an already-indented body.
|
|
1649
|
+
".lc-br-rich-inline { display: flex; flex-direction: column; gap: 6px; }",
|
|
1650
|
+
// ---- Attachment cards (image refs in a message detail). The card chrome
|
|
1651
|
+
// reuses the tool-schema sections' `lc-ts-card`/`lc-ts-card-head`; only the
|
|
1652
|
+
// image grid and tile are new. Each image is a 64px cover tile (the chat
|
|
1653
|
+
// history's tile size) beside a name + dims + size column. ----
|
|
1654
|
+
".lc-ts-card .lc-br-pre { margin: 8px 10px; }",
|
|
1655
|
+
".lc-att-grid { display: flex; flex-wrap: wrap; gap: 10px; padding: 8px 10px; }",
|
|
1656
|
+
".lc-att-item { display: flex; gap: 8px; align-items: center; min-width: 0; }",
|
|
1657
|
+
".lc-att-thumb { width: 64px; height: 64px; flex: none; padding: 0; display: flex; align-items: center; justify-content: center; border: 1px solid var(--dsw-alias-border-l1); border-radius: 6px; overflow: hidden; background: var(--dsw-alias-bg-layer-1); cursor: pointer; font: inherit; }",
|
|
1658
|
+
".lc-att-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }",
|
|
1659
|
+
".lc-att-ph, .lc-att-err { font-size: 10px; color: var(--dsw-alias-label-secondary); text-align: center; padding: 2px; }",
|
|
1660
|
+
".lc-att-meta { display: flex; flex-direction: column; gap: 2px; min-width: 0; }",
|
|
1661
|
+
".lc-att-name { font-size: 12px; color: var(--dsw-alias-label-primary); max-width: 200px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }",
|
|
1662
|
+
".lc-att-dims { font-size: 11px; color: var(--dsw-alias-label-secondary); }"
|
|
1485
1663
|
].join("\n");
|
|
1486
1664
|
|
|
1487
1665
|
// src/client/components/events.tsx
|
|
1488
1666
|
var import_dsh_client_ui_primitives2 = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
1489
|
-
|
|
1490
|
-
// src/client/format.ts
|
|
1491
|
-
function fmt(n) {
|
|
1492
|
-
if (n === void 0 || n === null || isNaN(n)) return "\u2014";
|
|
1493
|
-
if (n >= 1e6) return (n / 1e6).toFixed(1) + "M";
|
|
1494
|
-
if (n >= 1e3) return (n / 1e3).toFixed(1) + "k";
|
|
1495
|
-
return String(Math.round(n));
|
|
1496
|
-
}
|
|
1497
|
-
function fmtTime(t) {
|
|
1498
|
-
const d = new Date(t);
|
|
1499
|
-
if (isNaN(d.getTime())) return "\u2014";
|
|
1500
|
-
return d.toLocaleTimeString("en-GB", { hour12: false });
|
|
1501
|
-
}
|
|
1502
|
-
|
|
1503
|
-
// src/client/components/events.tsx
|
|
1504
1667
|
var EVENT_ICONS = { compaction: "\u2702", prune: "\u2702", inject: "\uFF0B", model: "\u21C4" };
|
|
1505
1668
|
function makeEventText(t) {
|
|
1506
1669
|
function eventLabel(ev) {
|
|
@@ -1563,7 +1726,7 @@ function makeEventList(kit) {
|
|
|
1563
1726
|
|
|
1564
1727
|
// src/client/meta.ts
|
|
1565
1728
|
var PLUGIN_NAME = "dsh-context";
|
|
1566
|
-
var PLUGIN_VERSION = true ? "0.
|
|
1729
|
+
var PLUGIN_VERSION = true ? "0.22.0" : "0.0.0-dev";
|
|
1567
1730
|
var PLUGIN_REPO = true ? "https://github.com/bowenliang123/dsh-context" : "https://github.com/bowenliang123/dsh-context";
|
|
1568
1731
|
var PLUGIN_REPO_SHORT = PLUGIN_REPO.replace(/^https?:\/\/github\.com\//, "");
|
|
1569
1732
|
|
|
@@ -1930,6 +2093,12 @@ function makeContextView(ctx, kit) {
|
|
|
1930
2093
|
const clearToolFocus = React.useCallback(() => {
|
|
1931
2094
|
setToolFocus(null);
|
|
1932
2095
|
}, []);
|
|
2096
|
+
const loadImage = React.useMemo(() => {
|
|
2097
|
+
if (typeof sessionId !== "string" || sessionId === "") return void 0;
|
|
2098
|
+
const conversation = ctx.get("conversation");
|
|
2099
|
+
if (conversation === void 0 || typeof conversation.resolveImage !== "function") return void 0;
|
|
2100
|
+
return (attachment) => conversation.resolveImage(sessionId, attachment);
|
|
2101
|
+
}, [sessionId]);
|
|
1933
2102
|
const rootRef = React.useRef(null);
|
|
1934
2103
|
const scrollerRef = React.useRef(null);
|
|
1935
2104
|
const restoredRef = React.useRef(null);
|
|
@@ -2041,7 +2210,8 @@ function makeContextView(ctx, kit) {
|
|
|
2041
2210
|
hoverKey: hoverCat,
|
|
2042
2211
|
onHoverKey: setHoverCat,
|
|
2043
2212
|
toolFocus,
|
|
2044
|
-
onToolFocusHandled: clearToolFocus
|
|
2213
|
+
onToolFocusHandled: clearToolFocus,
|
|
2214
|
+
loadImage
|
|
2045
2215
|
}
|
|
2046
2216
|
))), /* @__PURE__ */ React.createElement("div", { className: "lc-cols" }, /* @__PURE__ */ React.createElement("div", { className: "lc-card lc-col" }, /* @__PURE__ */ React.createElement("div", { className: "lc-card-title" }, /* @__PURE__ */ React.createElement("span", { className: "lc-card-title-text" }, t("events.title")), /* @__PURE__ */ React.createElement("div", { className: "lc-kinds" }, EVENT_KINDS.map((k) => /* @__PURE__ */ React.createElement(
|
|
2047
2217
|
"button",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-context",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.22.0",
|
|
4
4
|
"description": "A DeepSeek Harness plugin for context insight and management, with context dashboard and context command, for understanding how the context is made of, and how it evolves.",
|
|
5
5
|
"author": "bowenliang123",
|
|
6
6
|
"repository": {
|