@michengai/dsh-btw 0.1.15 → 0.1.17
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/CHANGELOG.md +12 -0
- package/CHANGELOG.zh-CN.md +12 -0
- package/README.md +3 -1
- package/README.zh-CN.md +3 -1
- package/lib/client.js +121 -36
- package/lib/index.js +6 -0
- package/lib/types/client/answer-markdown.d.ts +9 -0
- package/lib/types/client/host-markdown.d.ts +16 -0
- package/lib/types/client/styles.d.ts +1 -1
- package/lib/types/locales.d.ts +3 -0
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +4 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## Unreleased
|
|
4
|
+
|
|
5
|
+
## [0.1.17] - 2026-10-07
|
|
6
|
+
|
|
7
|
+
- Side-question answers use the host Markdown renderer, so `$...$`, `$$...$$`, and TeX delimiters render as formulas, matching the main conversation. Hosts without that renderer still show the original text. Copy keeps the raw Markdown, and answers do not load remote images.
|
|
8
|
+
- A code block’s own copy button says “Copy code” instead of reusing the whole-answer label.
|
|
9
|
+
|
|
10
|
+
## [0.1.16] - 2026-10-06
|
|
11
|
+
|
|
12
|
+
- The installed-plugin list shows “BTW” and a localized description instead of the package name. Titles and descriptions come from `meta.title` and `meta.description` in `locale/zh.json` and `locale/en.json`.
|
|
13
|
+
- Installing from GitHub now includes the compiled runtime, so no manual build is required.
|
|
14
|
+
|
|
3
15
|
## [0.1.15] - 2026-09-30
|
|
4
16
|
|
|
5
17
|
- Support DSH `0.2.0-rc.2` and keep the previous seven hosts working. Supported hosts are `0.1.2-rc.1`, `0.1.5-rc.1`, `0.1.5-rc.2`, `0.1.5-rc.3`, `0.1.7-rc.1`, `0.1.7-rc.2`, `0.2.0-rc.1`, and `0.2.0-rc.2`.
|
package/CHANGELOG.zh-CN.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# 更新日志
|
|
2
2
|
|
|
3
|
+
## 未发布
|
|
4
|
+
|
|
5
|
+
## [0.1.17] - 2026-10-07
|
|
6
|
+
|
|
7
|
+
- 旁问答案使用宿主 Markdown 渲染,`$...$`、`$$...$$` 和 TeX 分隔符与主会话一样显示为公式。宿主没有该渲染器时仍显示原文本。复制仍保留原始 Markdown,答案不加载远程图片。
|
|
8
|
+
- 代码块自己的复制按钮改为「复制代码」,不再和整段回答的复制按钮共用文案。
|
|
9
|
+
|
|
10
|
+
## [0.1.16] - 2026-10-06
|
|
11
|
+
|
|
12
|
+
- 已安装插件列表显示「BTW」和中文简介,不再只用包名。显示名来自 `locale/zh.json` 和 `locale/en.json` 的 `meta.title`、`meta.description`。
|
|
13
|
+
- 从 GitHub 安装时已包含运行文件,不必再手动构建。
|
|
14
|
+
|
|
3
15
|
## [0.1.15] - 2026-09-30
|
|
4
16
|
|
|
5
17
|
- 支持 DSH `0.2.0-rc.2`,同时保留此前七个宿主版本。支持的宿主版本为 `0.1.2-rc.1`、`0.1.5-rc.1`、`0.1.5-rc.2`、`0.1.5-rc.3`、`0.1.7-rc.1`、`0.1.7-rc.2`、`0.2.0-rc.1` 和 `0.2.0-rc.2`。
|
package/README.md
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
|
|
23
23
|
- **Context-aware questions**: explain concepts, recap conclusions, or ask a quick question about the current conversation.
|
|
24
24
|
- **Answers only**: no reading new files, browsing the web, running commands, or editing code.
|
|
25
|
-
- **Independent answer bubbles**: render Markdown, copy answers, collapse, expand, and close individual bubbles. Multiple answers can stay visible.
|
|
25
|
+
- **Independent answer bubbles**: render Markdown and formulas, copy answers, collapse, expand, and close individual bubbles. Multiple answers can stay visible.
|
|
26
26
|
- **Keep the main task going**: side questions are answered separately and do not add answers to the main conversation.
|
|
27
27
|
- **Cancel anytime**: close a bubble while it is answering to cancel that question.
|
|
28
28
|
- **Themes and languages**: follow DSH light and dark themes and switch between Chinese and English UI.
|
|
@@ -164,6 +164,8 @@ Development and builds target `0.2.0-rc.2`. `npm run test:compat` builds with th
|
|
|
164
164
|
|
|
165
165
|
Previous manual end-to-end acceptance with Edge and a live DeepSeek model passed on `0.1.5-rc.1`: side questions, attachment rejection, copying, collapse/expand, cancellation, and continued parent-session operation. This is not part of `npm run test:compat`. The selection toolbar, draft insertion, sidebar coexistence, and real-model side answers were subsequently checked on `0.1.5-rc.2`; the full end-to-end suite remains pending on that version and the older three versions.
|
|
166
166
|
|
|
167
|
+
GitHub and npm both include a ready-to-run `lib`; after changing source, run `npm run build` before committing.
|
|
168
|
+
|
|
167
169
|
To install from source, run `dsh plugin --profile web add . --ignore-scripts` from the project directory, then reload DSH.
|
|
168
170
|
|
|
169
171
|
## License
|
package/README.zh-CN.md
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
|
|
23
23
|
- **上下文旁问**:根据当前会话内容解释概念、回顾结论或回答临时问题。
|
|
24
24
|
- **只回答,不执行**:不会读取新文件、联网、运行命令或修改代码。
|
|
25
|
-
- **独立答案气泡**:支持 Markdown
|
|
25
|
+
- **独立答案气泡**:支持 Markdown、公式、复制、折叠、展开和关闭,可同时查看多条旁问。
|
|
26
26
|
- **不打断主任务**:旁问单独作答,答案不会写入主会话。
|
|
27
27
|
- **随时取消**:关闭正在回答的气泡即可取消该旁问。
|
|
28
28
|
- **主题与国际化**:跟随 DSH 浅色、深色主题,界面支持中文和英文切换。
|
|
@@ -163,6 +163,8 @@ npm run check
|
|
|
163
163
|
|
|
164
164
|
此前在 `0.1.5-rc.1` 上完成真实 Edge 与 DeepSeek 模型的手工端到端验收,旁问、附件拒绝、复制、折叠/展开、取消和父会话继续均通过。这不属于 `npm run test:compat`;随后在 `0.1.5-rc.2` 验证了划词横条、添加引用、侧边栏共存及真实模型旁问回答;该版本与旧三版的完整端到端用例仍未全部验收。
|
|
165
165
|
|
|
166
|
+
GitHub 与 npm 都包含可直接运行的 `lib`;改了源码后,提交前运行 `npm run build`。
|
|
167
|
+
|
|
166
168
|
从源码安装时,在项目目录执行 `dsh plugin --profile web add . --ignore-scripts`,然后重新加载 DSH。
|
|
167
169
|
|
|
168
170
|
## 许可证
|
package/lib/client.js
CHANGED
|
@@ -367,7 +367,7 @@ __export(index_exports, {
|
|
|
367
367
|
inject: () => inject
|
|
368
368
|
});
|
|
369
369
|
module.exports = __toCommonJS(index_exports);
|
|
370
|
-
var
|
|
370
|
+
var import_react7 = __toESM(require("react"), 1);
|
|
371
371
|
|
|
372
372
|
// node_modules/lucide-react/dist/esm/createLucideIcon.js
|
|
373
373
|
var import_react2 = require("react");
|
|
@@ -494,8 +494,11 @@ var zh = {
|
|
|
494
494
|
"error.reference": `\u8BF7\u9009\u62E9 1\u2013${MAX_REFERENCE_LENGTH} \u4E2A\u5B57\u7B26\u7684\u6B63\u6587\uFF08\u542B\u7A7A\u767D\uFF0C\u90E8\u5206\u7B26\u53F7\u8BA1\u4E3A\u591A\u4E2A\u5B57\u7B26\uFF09\u3002`,
|
|
495
495
|
"bubble.label": "\u65C1\u95EE\u56DE\u7B54",
|
|
496
496
|
"bubble.image": "\u56FE\u7247",
|
|
497
|
+
"bubble.footnotes": "\u811A\u6CE8",
|
|
497
498
|
"action.copy": "\u590D\u5236\u56DE\u7B54",
|
|
498
499
|
"action.copied": "\u5DF2\u590D\u5236",
|
|
500
|
+
"action.copyCode": "\u590D\u5236\u4EE3\u7801",
|
|
501
|
+
"action.copiedCode": "\u5DF2\u590D\u5236\u4EE3\u7801",
|
|
499
502
|
"action.expand": "\u5C55\u5F00\u56DE\u7B54",
|
|
500
503
|
"action.collapse": "\u6298\u53E0\u56DE\u7B54",
|
|
501
504
|
"action.close": "\u5173\u95ED\u65C1\u95EE",
|
|
@@ -543,8 +546,11 @@ var en = {
|
|
|
543
546
|
"error.reference": `Select 1\u2013${MAX_REFERENCE_LENGTH.toLocaleString("en-US")} characters of message text, including whitespace (some symbols count as multiple characters).`,
|
|
544
547
|
"bubble.label": "Side question answer",
|
|
545
548
|
"bubble.image": "Image",
|
|
549
|
+
"bubble.footnotes": "Footnotes",
|
|
546
550
|
"action.copy": "Copy answer",
|
|
547
551
|
"action.copied": "Copied",
|
|
552
|
+
"action.copyCode": "Copy code",
|
|
553
|
+
"action.copiedCode": "Copied code",
|
|
548
554
|
"action.expand": "Expand answer",
|
|
549
555
|
"action.collapse": "Collapse answer",
|
|
550
556
|
"action.close": "Close side question",
|
|
@@ -680,6 +686,9 @@ var BubbleStore = class {
|
|
|
680
686
|
};
|
|
681
687
|
|
|
682
688
|
// src/client/BubbleView.tsx
|
|
689
|
+
var import_react5 = __toESM(require("react"), 1);
|
|
690
|
+
|
|
691
|
+
// src/client/answer-markdown.tsx
|
|
683
692
|
var import_react4 = __toESM(require("react"), 1);
|
|
684
693
|
|
|
685
694
|
// node_modules/devlop/lib/default.js
|
|
@@ -13367,12 +13376,91 @@ function remarkGfm(options) {
|
|
|
13367
13376
|
toMarkdownExtensions.push(gfmToMarkdown(settings));
|
|
13368
13377
|
}
|
|
13369
13378
|
|
|
13379
|
+
// src/client/host-markdown.ts
|
|
13380
|
+
var cached;
|
|
13381
|
+
function isHostMarkdown(value) {
|
|
13382
|
+
if (typeof value === "function") return true;
|
|
13383
|
+
return typeof value === "object" && value !== null && "$$typeof" in value;
|
|
13384
|
+
}
|
|
13385
|
+
function loadHostMarkdownText() {
|
|
13386
|
+
if (cached !== void 0) return cached;
|
|
13387
|
+
try {
|
|
13388
|
+
const loaded = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
13389
|
+
cached = isHostMarkdown(loaded?.MarkdownText) ? loaded.MarkdownText : null;
|
|
13390
|
+
} catch {
|
|
13391
|
+
cached = null;
|
|
13392
|
+
}
|
|
13393
|
+
return cached;
|
|
13394
|
+
}
|
|
13395
|
+
|
|
13396
|
+
// src/client/answer-markdown.tsx
|
|
13397
|
+
var IMAGE = /^!\[([^\]\n]*)\](?:\([^)\n]*\)|\[[^\]\n]*\])/;
|
|
13398
|
+
function neutralizeMarkdownImages(source, emptyAlt = "") {
|
|
13399
|
+
let out = "";
|
|
13400
|
+
let index2 = 0;
|
|
13401
|
+
while (index2 < source.length) {
|
|
13402
|
+
const fence = source.startsWith("```", index2) ? "```" : source.startsWith("~~~", index2) ? "~~~" : "";
|
|
13403
|
+
if (fence) {
|
|
13404
|
+
const end = source.indexOf(fence, index2 + fence.length);
|
|
13405
|
+
if (end === -1) return out + source.slice(index2);
|
|
13406
|
+
out += source.slice(index2, end + fence.length);
|
|
13407
|
+
index2 = end + fence.length;
|
|
13408
|
+
continue;
|
|
13409
|
+
}
|
|
13410
|
+
if (source[index2] === "`") {
|
|
13411
|
+
let width = 0;
|
|
13412
|
+
while (source[index2 + width] === "`") width += 1;
|
|
13413
|
+
const fence2 = "`".repeat(width);
|
|
13414
|
+
const end = source.indexOf(fence2, index2 + width);
|
|
13415
|
+
if (end === -1) return out + source.slice(index2);
|
|
13416
|
+
out += source.slice(index2, end + width);
|
|
13417
|
+
index2 = end + width;
|
|
13418
|
+
continue;
|
|
13419
|
+
}
|
|
13420
|
+
const image3 = IMAGE.exec(source.slice(index2));
|
|
13421
|
+
if (image3) {
|
|
13422
|
+
out += image3[1] || emptyAlt;
|
|
13423
|
+
index2 += image3[0].length;
|
|
13424
|
+
continue;
|
|
13425
|
+
}
|
|
13426
|
+
out += source[index2];
|
|
13427
|
+
index2 += 1;
|
|
13428
|
+
}
|
|
13429
|
+
return out;
|
|
13430
|
+
}
|
|
13431
|
+
function FallbackMarkdown({ text: text7 }) {
|
|
13432
|
+
return /* @__PURE__ */ import_react4.default.createElement(Markdown, { remarkPlugins: [remarkGfm], skipHtml: true, components: {
|
|
13433
|
+
a: (props) => /* @__PURE__ */ import_react4.default.createElement("a", { href: props.href, target: "_blank", rel: "noreferrer noopener" }, props.children),
|
|
13434
|
+
img: () => null
|
|
13435
|
+
} }, text7);
|
|
13436
|
+
}
|
|
13437
|
+
var AnswerBoundary = class extends import_react4.default.Component {
|
|
13438
|
+
state = { failed: false };
|
|
13439
|
+
static getDerivedStateFromError() {
|
|
13440
|
+
return { failed: true };
|
|
13441
|
+
}
|
|
13442
|
+
render() {
|
|
13443
|
+
return this.state.failed ? this.props.fallback : this.props.children;
|
|
13444
|
+
}
|
|
13445
|
+
};
|
|
13446
|
+
function AnswerMarkdown({ text: text7, labels, imageLabel }) {
|
|
13447
|
+
const safe = neutralizeMarkdownImages(text7, imageLabel);
|
|
13448
|
+
const fallback = /* @__PURE__ */ import_react4.default.createElement(FallbackMarkdown, { text: safe });
|
|
13449
|
+
const Host = loadHostMarkdownText();
|
|
13450
|
+
if (!Host) return fallback;
|
|
13451
|
+
return /* @__PURE__ */ import_react4.default.createElement(AnswerBoundary, { key: safe, fallback }, /* @__PURE__ */ import_react4.default.createElement(Host, { text: safe, streaming: false, labels, variant: "compact" }));
|
|
13452
|
+
}
|
|
13453
|
+
|
|
13370
13454
|
// src/client/BubbleView.tsx
|
|
13371
13455
|
function BubbleView({ item, close, t }) {
|
|
13372
|
-
const [collapsed, setCollapsed] = (0,
|
|
13373
|
-
const [copied, setCopied] = (0,
|
|
13374
|
-
const [copyError, setCopyError] = (0,
|
|
13456
|
+
const [collapsed, setCollapsed] = (0, import_react5.useState)(false);
|
|
13457
|
+
const [copied, setCopied] = (0, import_react5.useState)(false);
|
|
13458
|
+
const [copyError, setCopyError] = (0, import_react5.useState)(false);
|
|
13375
13459
|
const busy = item.phase === "answering" || item.phase === "closing";
|
|
13460
|
+
const labels = (0, import_react5.useMemo)(() => ({
|
|
13461
|
+
code: { copyLabel: t("action.copyCode"), copiedLabel: t("action.copiedCode") },
|
|
13462
|
+
footnotes: t("bubble.footnotes")
|
|
13463
|
+
}), [t]);
|
|
13376
13464
|
const copy = async () => {
|
|
13377
13465
|
try {
|
|
13378
13466
|
await navigator.clipboard.writeText(item.answer);
|
|
@@ -13382,18 +13470,15 @@ function BubbleView({ item, close, t }) {
|
|
|
13382
13470
|
setCopyError(true);
|
|
13383
13471
|
}
|
|
13384
13472
|
};
|
|
13385
|
-
return /* @__PURE__ */
|
|
13473
|
+
return /* @__PURE__ */ import_react5.default.createElement("article", { className: "btw-bubble", "data-phase": item.phase, "aria-label": t("bubble.label") }, /* @__PURE__ */ import_react5.default.createElement("header", { className: "btw-header" }, /* @__PURE__ */ import_react5.default.createElement("span", { className: "btw-symbol" }, /* @__PURE__ */ import_react5.default.createElement(MessageCircle, { size: 16 })), /* @__PURE__ */ import_react5.default.createElement("span", { className: "btw-question" }, item.question), /* @__PURE__ */ import_react5.default.createElement("div", { className: "btw-actions" }, item.answer && /* @__PURE__ */ import_react5.default.createElement("button", { type: "button", title: t(copied ? "action.copied" : "action.copy"), "aria-label": t("action.copy"), onClick: () => {
|
|
13386
13474
|
void copy();
|
|
13387
|
-
} }, copied ? /* @__PURE__ */
|
|
13388
|
-
a: (props) => /* @__PURE__ */ import_react4.default.createElement("a", { href: props.href, target: "_blank", rel: "noreferrer noopener" }, props.children),
|
|
13389
|
-
img: (props) => /* @__PURE__ */ import_react4.default.createElement("span", null, props.alt || t("bubble.image"))
|
|
13390
|
-
} }, item.answer)), item.error && /* @__PURE__ */ import_react4.default.createElement("p", { className: "btw-error", role: "alert" }, item.closeFailed ? t("error.close", { detail: item.error }) : item.error), copyError && /* @__PURE__ */ import_react4.default.createElement("p", { className: "btw-error", role: "alert" }, t("error.copy")));
|
|
13475
|
+
} }, copied ? /* @__PURE__ */ import_react5.default.createElement(Check, { size: 16 }) : /* @__PURE__ */ import_react5.default.createElement(Copy, { size: 16 })), /* @__PURE__ */ import_react5.default.createElement("button", { type: "button", title: t(collapsed ? "action.expand" : "action.collapse"), "aria-label": t(collapsed ? "action.expand" : "action.collapse"), "aria-expanded": !collapsed, onClick: () => setCollapsed(!collapsed) }, collapsed ? /* @__PURE__ */ import_react5.default.createElement(ChevronUp, { size: 16 }) : /* @__PURE__ */ import_react5.default.createElement(ChevronDown, { size: 16 })), /* @__PURE__ */ import_react5.default.createElement("button", { type: "button", title: t(item.closeFailed ? "action.retryClose" : "action.close"), "aria-label": t("action.close"), disabled: item.phase === "closing", onClick: close }, /* @__PURE__ */ import_react5.default.createElement(X, { size: 16 })))), !collapsed && item.reference && /* @__PURE__ */ import_react5.default.createElement("details", { className: "btw-reference" }, /* @__PURE__ */ import_react5.default.createElement("summary", null, t("selection.reference")), /* @__PURE__ */ import_react5.default.createElement("blockquote", null, item.reference)), busy && /* @__PURE__ */ import_react5.default.createElement("div", { className: "btw-status", role: "status" }, /* @__PURE__ */ import_react5.default.createElement(LoaderCircle, { size: 14, className: "btw-spinner" }), t(item.phase === "closing" ? "status.closing" : "status.answering")), !collapsed && item.answer && /* @__PURE__ */ import_react5.default.createElement("div", { className: "btw-answer" }, /* @__PURE__ */ import_react5.default.createElement(AnswerMarkdown, { text: item.answer, labels, imageLabel: t("bubble.image") })), item.error && /* @__PURE__ */ import_react5.default.createElement("p", { className: "btw-error", role: "alert" }, item.closeFailed ? t("error.close", { detail: item.error }) : item.error), copyError && /* @__PURE__ */ import_react5.default.createElement("p", { className: "btw-error", role: "alert" }, t("error.copy")));
|
|
13391
13476
|
}
|
|
13392
13477
|
function BubbleDock({ store, sessionId, t }) {
|
|
13393
|
-
const snapshot = (0,
|
|
13478
|
+
const snapshot = (0, import_react5.useSyncExternalStore)(store.subscribe, store.getSnapshot, store.getSnapshot);
|
|
13394
13479
|
const items = snapshot.filter((item) => item.sessionId === sessionId);
|
|
13395
13480
|
if (!items.length) return null;
|
|
13396
|
-
return /* @__PURE__ */
|
|
13481
|
+
return /* @__PURE__ */ import_react5.default.createElement("div", { className: "btw-dock" }, items.map((item) => /* @__PURE__ */ import_react5.default.createElement(BubbleView, { key: item.id, item, t, close: () => {
|
|
13397
13482
|
void store.close(item.id);
|
|
13398
13483
|
} })));
|
|
13399
13484
|
}
|
|
@@ -13414,7 +13499,7 @@ function addQuoteToComposer(input, reference, t) {
|
|
|
13414
13499
|
}
|
|
13415
13500
|
|
|
13416
13501
|
// src/client/SelectionAsk.tsx
|
|
13417
|
-
var
|
|
13502
|
+
var import_react6 = __toESM(require("react"), 1);
|
|
13418
13503
|
|
|
13419
13504
|
// src/client/selection.ts
|
|
13420
13505
|
function captureSelection(scope, target) {
|
|
@@ -13434,21 +13519,21 @@ function captureSelection(scope, target) {
|
|
|
13434
13519
|
|
|
13435
13520
|
// src/client/SelectionAsk.tsx
|
|
13436
13521
|
function SelectionAsk({ store, sessionId, t, addToConversation }) {
|
|
13437
|
-
const anchor = (0,
|
|
13438
|
-
const dialog = (0,
|
|
13439
|
-
const previousFocus = (0,
|
|
13440
|
-
const mounted = (0,
|
|
13441
|
-
const submitting = (0,
|
|
13442
|
-
const [draft, setDraft] = (0,
|
|
13443
|
-
const [question, setQuestion] = (0,
|
|
13444
|
-
const [error, setError] = (0,
|
|
13445
|
-
const [busy, setBusy] = (0,
|
|
13522
|
+
const anchor = (0, import_react6.useRef)(null);
|
|
13523
|
+
const dialog = (0, import_react6.useRef)(null);
|
|
13524
|
+
const previousFocus = (0, import_react6.useRef)(null);
|
|
13525
|
+
const mounted = (0, import_react6.useRef)(false);
|
|
13526
|
+
const submitting = (0, import_react6.useRef)(false);
|
|
13527
|
+
const [draft, setDraft] = (0, import_react6.useState)();
|
|
13528
|
+
const [question, setQuestion] = (0, import_react6.useState)("");
|
|
13529
|
+
const [error, setError] = (0, import_react6.useState)("");
|
|
13530
|
+
const [busy, setBusy] = (0, import_react6.useState)(false);
|
|
13446
13531
|
const dismiss = () => {
|
|
13447
13532
|
if (submitting.current) return;
|
|
13448
13533
|
setDraft(void 0);
|
|
13449
13534
|
previousFocus.current?.focus({ preventScroll: true });
|
|
13450
13535
|
};
|
|
13451
|
-
(0,
|
|
13536
|
+
(0, import_react6.useEffect)(() => {
|
|
13452
13537
|
mounted.current = true;
|
|
13453
13538
|
const scope = anchor.current?.closest("[data-conversation-scroll]");
|
|
13454
13539
|
if (!scope) return () => {
|
|
@@ -13474,7 +13559,7 @@ function SelectionAsk({ store, sessionId, t, addToConversation }) {
|
|
|
13474
13559
|
scope.removeEventListener("keyup", open);
|
|
13475
13560
|
};
|
|
13476
13561
|
}, [sessionId]);
|
|
13477
|
-
(0,
|
|
13562
|
+
(0, import_react6.useLayoutEffect)(() => {
|
|
13478
13563
|
const element3 = dialog.current;
|
|
13479
13564
|
if (!draft || !element3) return;
|
|
13480
13565
|
if (!draft.form) {
|
|
@@ -13497,7 +13582,7 @@ function SelectionAsk({ store, sessionId, t, addToConversation }) {
|
|
|
13497
13582
|
if (draft.form) element3.querySelector("textarea")?.focus();
|
|
13498
13583
|
else if (draft.keyboard) element3.querySelector("button")?.focus({ preventScroll: true });
|
|
13499
13584
|
}, [draft]);
|
|
13500
|
-
(0,
|
|
13585
|
+
(0, import_react6.useLayoutEffect)(() => {
|
|
13501
13586
|
const element3 = dialog.current;
|
|
13502
13587
|
return () => {
|
|
13503
13588
|
if (!element3) return;
|
|
@@ -13505,7 +13590,7 @@ function SelectionAsk({ store, sessionId, t, addToConversation }) {
|
|
|
13505
13590
|
if (element3 instanceof HTMLDialogElement && element3.open) element3.close();
|
|
13506
13591
|
};
|
|
13507
13592
|
}, [draft?.form]);
|
|
13508
|
-
(0,
|
|
13593
|
+
(0, import_react6.useEffect)(() => {
|
|
13509
13594
|
if (!draft) return;
|
|
13510
13595
|
const scope = anchor.current?.closest("[data-conversation-scroll]");
|
|
13511
13596
|
const hide = () => setDraft(void 0);
|
|
@@ -13578,7 +13663,7 @@ function SelectionAsk({ store, sessionId, t, addToConversation }) {
|
|
|
13578
13663
|
}
|
|
13579
13664
|
};
|
|
13580
13665
|
const Surface = draft?.form ? "dialog" : "div";
|
|
13581
|
-
return /* @__PURE__ */
|
|
13666
|
+
return /* @__PURE__ */ import_react6.default.createElement(import_react6.default.Fragment, null, /* @__PURE__ */ import_react6.default.createElement("span", { ref: anchor, hidden: true }), draft && /* @__PURE__ */ import_react6.default.createElement(
|
|
13582
13667
|
Surface,
|
|
13583
13668
|
{
|
|
13584
13669
|
ref: (element3) => {
|
|
@@ -13595,10 +13680,10 @@ function SelectionAsk({ store, sessionId, t, addToConversation }) {
|
|
|
13595
13680
|
if (event.target === event.currentTarget && (event.clientX < rect.left || event.clientX > rect.right || event.clientY < rect.top || event.clientY > rect.bottom)) dismiss();
|
|
13596
13681
|
}
|
|
13597
13682
|
},
|
|
13598
|
-
draft.form ? /* @__PURE__ */
|
|
13683
|
+
draft.form ? /* @__PURE__ */ import_react6.default.createElement("form", { onSubmit: (event) => {
|
|
13599
13684
|
event.preventDefault();
|
|
13600
13685
|
void send(question);
|
|
13601
|
-
} }, /* @__PURE__ */
|
|
13686
|
+
} }, /* @__PURE__ */ import_react6.default.createElement("h3", null, t("selection.ask")), /* @__PURE__ */ import_react6.default.createElement("details", { className: "btw-reference" }, /* @__PURE__ */ import_react6.default.createElement("summary", null, t("selection.reference"), " \xB7 ", draft.reference.length, /* @__PURE__ */ import_react6.default.createElement("span", { className: "btw-reference-preview" }, draft.reference.slice(0, 120), draft.reference.length > 120 ? "\u2026" : "")), /* @__PURE__ */ import_react6.default.createElement("blockquote", null, draft.reference)), /* @__PURE__ */ import_react6.default.createElement("label", null, /* @__PURE__ */ import_react6.default.createElement("span", null, t("selection.question")), /* @__PURE__ */ import_react6.default.createElement(
|
|
13602
13687
|
"textarea",
|
|
13603
13688
|
{
|
|
13604
13689
|
value: question,
|
|
@@ -13612,11 +13697,11 @@ function SelectionAsk({ store, sessionId, t, addToConversation }) {
|
|
|
13612
13697
|
}
|
|
13613
13698
|
}
|
|
13614
13699
|
}
|
|
13615
|
-
)), /* @__PURE__ */
|
|
13700
|
+
)), /* @__PURE__ */ import_react6.default.createElement("p", { className: "btw-selection-hint" }, t("selection.context")), /* @__PURE__ */ import_react6.default.createElement("div", { className: "btw-selection-actions" }, /* @__PURE__ */ import_react6.default.createElement("button", { type: "button", disabled: busy, onClick: dismiss }, t("selection.cancel")), /* @__PURE__ */ import_react6.default.createElement("button", { type: "button", disabled: busy || draft.reference.length > MAX_REFERENCE_LENGTH, onClick: () => {
|
|
13616
13701
|
void send(t("selection.explain"));
|
|
13617
|
-
} }, t("selection.explain")), /* @__PURE__ */
|
|
13618
|
-
draft.form && draft.reference.length > MAX_REFERENCE_LENGTH && /* @__PURE__ */
|
|
13619
|
-
error && /* @__PURE__ */
|
|
13702
|
+
} }, t("selection.explain")), /* @__PURE__ */ import_react6.default.createElement("button", { type: "submit", disabled: busy || !question.trim() || draft.reference.length > MAX_REFERENCE_LENGTH }, t("selection.send")))) : /* @__PURE__ */ import_react6.default.createElement("div", { role: "toolbar", "aria-label": t("selection.ask"), onMouseDown: (event) => event.preventDefault() }, /* @__PURE__ */ import_react6.default.createElement("button", { type: "button", onClick: add }, t("selection.add")), /* @__PURE__ */ import_react6.default.createElement("button", { type: "button", onClick: () => setDraft({ ...draft, form: true }) }, t("selection.btw"))),
|
|
13703
|
+
draft.form && draft.reference.length > MAX_REFERENCE_LENGTH && /* @__PURE__ */ import_react6.default.createElement("p", { className: "btw-error", role: "alert" }, t("error.reference")),
|
|
13704
|
+
error && /* @__PURE__ */ import_react6.default.createElement("p", { className: "btw-error", role: "alert" }, error)
|
|
13620
13705
|
));
|
|
13621
13706
|
}
|
|
13622
13707
|
|
|
@@ -13650,7 +13735,7 @@ var CSS = `
|
|
|
13650
13735
|
.btw-answer{padding:0 14px 14px;max-height:300px;overflow:auto;overflow-wrap:anywhere;font-size:13px;line-height:1.7}
|
|
13651
13736
|
.btw-answer>*:first-child{margin-top:0}.btw-answer>*:last-child{margin-bottom:0}
|
|
13652
13737
|
.btw-answer p{margin:8px 0}.btw-answer h1,.btw-answer h2,.btw-answer h3{font-size:15px;line-height:1.5;margin:12px 0 6px;font-weight:600}
|
|
13653
|
-
.btw-answer pre{max-width:100%;overflow:auto;background:var(--dsw-alias-markdown-code-block);padding:10px;border-radius:8px;white-space:pre;font-size:12px}
|
|
13738
|
+
.btw-answer pre{max-width:100%;overflow:auto;background:var(--dsw-alias-markdown-code-block);padding:10px;border-radius:8px;white-space:pre;font-size:12px}.btw-answer .katex-display{max-width:100%;overflow:auto}
|
|
13654
13739
|
.btw-answer code{font-family:Consolas,monospace;font-size:12px}.btw-answer :not(pre)>code{background:var(--dsw-alias-markdown-code-block);border-radius:4px;padding:1px 3px}.btw-answer a{color:var(--dsw-alias-label-primary);text-decoration:underline;text-underline-offset:2px;overflow-wrap:anywhere}
|
|
13655
13740
|
.btw-answer table{display:block;max-width:100%;overflow:auto;border-collapse:collapse}.btw-answer th,.btw-answer td{border:1px solid var(--dsw-alias-border-l2);padding:5px 9px}
|
|
13656
13741
|
.btw-answer ul,.btw-answer ol{padding-left:22px}.btw-answer blockquote{margin:8px 0;padding-left:10px;border-left:2px solid var(--dsw-alias-border-l4);color:var(--dsw-alias-label-secondary)}
|
|
@@ -13662,7 +13747,7 @@ var CSS = `
|
|
|
13662
13747
|
// src/client/index.tsx
|
|
13663
13748
|
var inject = ["slots", "remote", "remote.commands", "locale", "conversation", "sessions"];
|
|
13664
13749
|
function BtwCommandIcon({ size = 16, className }) {
|
|
13665
|
-
return /* @__PURE__ */
|
|
13750
|
+
return /* @__PURE__ */ import_react7.default.createElement(MessageCircle, { size, className });
|
|
13666
13751
|
}
|
|
13667
13752
|
function sessionIdOf(session) {
|
|
13668
13753
|
if (typeof session === "string") return session;
|
|
@@ -13781,11 +13866,11 @@ function apply(ctx) {
|
|
|
13781
13866
|
});
|
|
13782
13867
|
ctx.effect(() => () => store.dispose());
|
|
13783
13868
|
function Dock(props) {
|
|
13784
|
-
return /* @__PURE__ */
|
|
13869
|
+
return /* @__PURE__ */ import_react7.default.createElement(import_react7.default.Fragment, null, /* @__PURE__ */ import_react7.default.createElement(SelectionAsk, { key: props.session.sessionId, store, sessionId: props.session.sessionId, t: props.t, addToConversation: (reference) => {
|
|
13785
13870
|
const session = ctx.get("sessions").scope(props.session.sessionId);
|
|
13786
13871
|
if (!session) throw new Error(props.t("error.backend"));
|
|
13787
13872
|
addQuoteToComposer(ctx.conversation.input.for(session), reference, props.t);
|
|
13788
|
-
} }), /* @__PURE__ */
|
|
13873
|
+
} }), /* @__PURE__ */ import_react7.default.createElement(BubbleDock, { store, sessionId: props.session.sessionId, t: props.t }));
|
|
13789
13874
|
}
|
|
13790
13875
|
slots.inject("conversation.input.dock", () => slots.register({ name: "conversation.input.dock", id: "michengai-btw", order: -50, locale: NS }, Dock));
|
|
13791
13876
|
slots.inject("conversation.chat.commandview", () => {
|
package/lib/index.js
CHANGED
|
@@ -18,8 +18,11 @@ var zh = {
|
|
|
18
18
|
"error.reference": `\u8BF7\u9009\u62E9 1\u2013${MAX_REFERENCE_LENGTH} \u4E2A\u5B57\u7B26\u7684\u6B63\u6587\uFF08\u542B\u7A7A\u767D\uFF0C\u90E8\u5206\u7B26\u53F7\u8BA1\u4E3A\u591A\u4E2A\u5B57\u7B26\uFF09\u3002`,
|
|
19
19
|
"bubble.label": "\u65C1\u95EE\u56DE\u7B54",
|
|
20
20
|
"bubble.image": "\u56FE\u7247",
|
|
21
|
+
"bubble.footnotes": "\u811A\u6CE8",
|
|
21
22
|
"action.copy": "\u590D\u5236\u56DE\u7B54",
|
|
22
23
|
"action.copied": "\u5DF2\u590D\u5236",
|
|
24
|
+
"action.copyCode": "\u590D\u5236\u4EE3\u7801",
|
|
25
|
+
"action.copiedCode": "\u5DF2\u590D\u5236\u4EE3\u7801",
|
|
23
26
|
"action.expand": "\u5C55\u5F00\u56DE\u7B54",
|
|
24
27
|
"action.collapse": "\u6298\u53E0\u56DE\u7B54",
|
|
25
28
|
"action.close": "\u5173\u95ED\u65C1\u95EE",
|
|
@@ -67,8 +70,11 @@ var en = {
|
|
|
67
70
|
"error.reference": `Select 1\u2013${MAX_REFERENCE_LENGTH.toLocaleString("en-US")} characters of message text, including whitespace (some symbols count as multiple characters).`,
|
|
68
71
|
"bubble.label": "Side question answer",
|
|
69
72
|
"bubble.image": "Image",
|
|
73
|
+
"bubble.footnotes": "Footnotes",
|
|
70
74
|
"action.copy": "Copy answer",
|
|
71
75
|
"action.copied": "Copied",
|
|
76
|
+
"action.copyCode": "Copy code",
|
|
77
|
+
"action.copiedCode": "Copied code",
|
|
72
78
|
"action.expand": "Expand answer",
|
|
73
79
|
"action.collapse": "Collapse answer",
|
|
74
80
|
"action.close": "Close side question",
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { type HostMarkdownLabels } from './host-markdown';
|
|
3
|
+
/** 旁问不加载远程图片。代码块和行内代码里的写法保持原样。 */
|
|
4
|
+
export declare function neutralizeMarkdownImages(source: string, emptyAlt?: string): string;
|
|
5
|
+
export declare function AnswerMarkdown({ text, labels, imageLabel }: {
|
|
6
|
+
text: string;
|
|
7
|
+
labels: HostMarkdownLabels;
|
|
8
|
+
imageLabel: string;
|
|
9
|
+
}): React.JSX.Element;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ComponentType } from 'react';
|
|
2
|
+
export interface HostMarkdownLabels {
|
|
3
|
+
code: {
|
|
4
|
+
copyLabel: string;
|
|
5
|
+
copiedLabel: string;
|
|
6
|
+
};
|
|
7
|
+
footnotes: string;
|
|
8
|
+
}
|
|
9
|
+
export type HostMarkdownText = ComponentType<{
|
|
10
|
+
text: string;
|
|
11
|
+
streaming?: boolean;
|
|
12
|
+
labels: HostMarkdownLabels;
|
|
13
|
+
variant?: 'body' | 'compact';
|
|
14
|
+
}>;
|
|
15
|
+
/** 宿主基座模块。旧宿主没有它时返回 null,调用方改用自带 Markdown。 */
|
|
16
|
+
export declare function loadHostMarkdownText(): HostMarkdownText | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const CSS = "\n.btw-reference-preview{display:block;margin-top:6px;max-height:3.2em;overflow:hidden;overflow-wrap:anywhere;line-height:1.6;color:var(--dsw-alias-label-primary)}\n.btw-selection-dialog,.btw-selection-menu{position:fixed;box-sizing:border-box;background:var(--dsw-alias-bg-base);color:var(--dsw-alias-label-primary);border:1px solid var(--dsw-alias-border-l2);border-radius:12px;padding:16px;font:inherit;font-size:13px;max-height:calc(100dvh - 32px);overflow:auto;box-shadow:0 12px 36px #0003}\n.btw-selection-dialog{width:min(520px,calc(100vw - 32px));margin:auto}.btw-selection-menu{margin:0;width:max-content;max-width:calc(100vw - 16px);padding:0;inset:auto;border-radius:10px;overflow:hidden;border-color:var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2);font-family:inherit;font-size:12px;font-weight:500;line-height:16px;box-shadow:0 2px 6px #0001}\n.btw-selection-menu::backdrop{background:transparent}.btw-selection-dialog::backdrop{background:#0004}\n.btw-selection-dialog h3{margin:0 0 12px;font-size:16px}.btw-selection-dialog label{display:flex;flex-direction:column;gap:8px;margin-top:12px}\n.btw-selection-dialog textarea{box-sizing:border-box;width:100%;min-height:96px;resize:vertical;font:inherit;padding:10px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;background:var(--dsw-alias-bg-base);color:inherit}\n.btw-selection-dialog button,.btw-selection-menu button{font:inherit;color:inherit;background:var(--dsw-alias-interactive-bg-hover);border:0;border-radius:6px;padding:8px 12px;cursor:pointer;min-height:36px}\n.btw-selection-menu [role=\"toolbar\"]{display:flex;align-items:center}.btw-selection-menu button+button{border-left:1px solid var(--dsw-alias-border-l1)}\n.btw-selection-menu button{display:inline-flex;align-items:center;height:28px;min-height:28px;padding:0 8px;border-radius:0;text-align:left;white-space:nowrap;background:transparent}.btw-selection-menu button:hover{background:var(--dsw-alias-interactive-bg-hover)}\n.btw-selection-dialog button:disabled{opacity:.5;cursor:default}.btw-selection-dialog :focus-visible,.btw-selection-menu :focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,var(--dsw-alias-label-primary));outline-offset:2px}\n.btw-selection-menu :focus-visible{outline-width:1px;outline-offset:-2px}\n.btw-selection-actions{display:flex;justify-content:flex-end;flex-wrap:wrap;gap:8px}.btw-selection-hint{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.6;margin:10px 4px}\n.btw-reference{padding:0 14px 10px;font-size:12px}.btw-reference summary{cursor:pointer;color:var(--dsw-alias-label-secondary)}.btw-reference blockquote{margin:8px 0 0;padding:8px;border-left:2px solid var(--dsw-alias-border-l2);white-space:pre-wrap;overflow-wrap:anywhere;max-height:150px;overflow:auto}.btw-selection-dialog .btw-reference{padding:0}\n.btw-dock{display:flex;flex:none;flex-direction:column;gap:8px;width:calc(100% - var(--dsh-composer-side-clearance,0px) - var(--dsh-composer-side-clearance,0px));max-width:var(--dsh-composer-card-max-width,100%);margin:0 auto;max-height:440px;overflow:auto;padding:4px 0 10px;box-sizing:border-box;letter-spacing:0}\n.btw-bubble{background:var(--dsw-alias-bg-base);color:var(--dsw-alias-label-primary);border:1px solid var(--dsw-alias-border-l2);border-radius:12px;min-width:0;flex-shrink:0;font-size:13px;line-height:1.6;font-family:var(--dsw-font-family,inherit);letter-spacing:0}\n.btw-header{display:flex;align-items:center;gap:8px;padding:8px 10px 8px 14px;min-width:0;min-height:44px}\n.btw-symbol{display:flex;align-items:center;color:var(--dsw-alias-label-secondary);height:28px;flex-shrink:0}\n.btw-question{flex:1;min-width:0;overflow-wrap:anywhere;font-size:13px;font-weight:500;line-height:22px;max-height:66px;overflow:auto}\n.btw-actions{display:flex;gap:4px;flex-shrink:0}\n.btw-actions button{display:grid;place-items:center;width:28px;height:28px;padding:0;border:0;border-radius:50%;background:transparent;color:var(--dsw-alias-label-secondary);cursor:pointer;flex:none;transition:background-color 120ms ease}\n.btw-actions button:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}\n.btw-actions button:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,var(--dsw-alias-label-primary));outline-offset:-2px}\n.btw-actions button:disabled{cursor:wait;opacity:.5}\n.btw-status{display:flex;align-items:center;gap:8px;padding:0 14px 12px;color:var(--dsw-alias-label-secondary);font-size:13px}\n.btw-spinner{animation:btw-spin 1.2s linear infinite}@keyframes btw-spin{to{transform:rotate(360deg)}}\n.btw-answer{padding:0 14px 14px;max-height:300px;overflow:auto;overflow-wrap:anywhere;font-size:13px;line-height:1.7}\n.btw-answer>*:first-child{margin-top:0}.btw-answer>*:last-child{margin-bottom:0}\n.btw-answer p{margin:8px 0}.btw-answer h1,.btw-answer h2,.btw-answer h3{font-size:15px;line-height:1.5;margin:12px 0 6px;font-weight:600}\n.btw-answer pre{max-width:100%;overflow:auto;background:var(--dsw-alias-markdown-code-block);padding:10px;border-radius:8px;white-space:pre;font-size:12px}\n.btw-answer code{font-family:Consolas,monospace;font-size:12px}.btw-answer :not(pre)>code{background:var(--dsw-alias-markdown-code-block);border-radius:4px;padding:1px 3px}.btw-answer a{color:var(--dsw-alias-label-primary);text-decoration:underline;text-underline-offset:2px;overflow-wrap:anywhere}\n.btw-answer table{display:block;max-width:100%;overflow:auto;border-collapse:collapse}.btw-answer th,.btw-answer td{border:1px solid var(--dsw-alias-border-l2);padding:5px 9px}\n.btw-answer ul,.btw-answer ol{padding-left:22px}.btw-answer blockquote{margin:8px 0;padding-left:10px;border-left:2px solid var(--dsw-alias-border-l4);color:var(--dsw-alias-label-secondary)}\n.btw-error{margin:0;padding:0 14px 12px;font-size:13px;color:var(--dsw-alias-state-error-primary);overflow-wrap:anywhere}\n@media(max-width:480px){.btw-dock{max-height:330px}.btw-header{padding:6px 8px 6px 12px;gap:6px}.btw-answer{padding:0 12px 12px;max-height:230px}.btw-status,.btw-error{padding-left:12px}.btw-actions{gap:0}.btw-actions button{width:36px;height:36px}}\n@media(prefers-reduced-motion:reduce){.btw-spinner{animation:none}.btw-actions button{transition:none}}\n";
|
|
1
|
+
export declare const CSS = "\n.btw-reference-preview{display:block;margin-top:6px;max-height:3.2em;overflow:hidden;overflow-wrap:anywhere;line-height:1.6;color:var(--dsw-alias-label-primary)}\n.btw-selection-dialog,.btw-selection-menu{position:fixed;box-sizing:border-box;background:var(--dsw-alias-bg-base);color:var(--dsw-alias-label-primary);border:1px solid var(--dsw-alias-border-l2);border-radius:12px;padding:16px;font:inherit;font-size:13px;max-height:calc(100dvh - 32px);overflow:auto;box-shadow:0 12px 36px #0003}\n.btw-selection-dialog{width:min(520px,calc(100vw - 32px));margin:auto}.btw-selection-menu{margin:0;width:max-content;max-width:calc(100vw - 16px);padding:0;inset:auto;border-radius:10px;overflow:hidden;border-color:var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2);font-family:inherit;font-size:12px;font-weight:500;line-height:16px;box-shadow:0 2px 6px #0001}\n.btw-selection-menu::backdrop{background:transparent}.btw-selection-dialog::backdrop{background:#0004}\n.btw-selection-dialog h3{margin:0 0 12px;font-size:16px}.btw-selection-dialog label{display:flex;flex-direction:column;gap:8px;margin-top:12px}\n.btw-selection-dialog textarea{box-sizing:border-box;width:100%;min-height:96px;resize:vertical;font:inherit;padding:10px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;background:var(--dsw-alias-bg-base);color:inherit}\n.btw-selection-dialog button,.btw-selection-menu button{font:inherit;color:inherit;background:var(--dsw-alias-interactive-bg-hover);border:0;border-radius:6px;padding:8px 12px;cursor:pointer;min-height:36px}\n.btw-selection-menu [role=\"toolbar\"]{display:flex;align-items:center}.btw-selection-menu button+button{border-left:1px solid var(--dsw-alias-border-l1)}\n.btw-selection-menu button{display:inline-flex;align-items:center;height:28px;min-height:28px;padding:0 8px;border-radius:0;text-align:left;white-space:nowrap;background:transparent}.btw-selection-menu button:hover{background:var(--dsw-alias-interactive-bg-hover)}\n.btw-selection-dialog button:disabled{opacity:.5;cursor:default}.btw-selection-dialog :focus-visible,.btw-selection-menu :focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,var(--dsw-alias-label-primary));outline-offset:2px}\n.btw-selection-menu :focus-visible{outline-width:1px;outline-offset:-2px}\n.btw-selection-actions{display:flex;justify-content:flex-end;flex-wrap:wrap;gap:8px}.btw-selection-hint{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.6;margin:10px 4px}\n.btw-reference{padding:0 14px 10px;font-size:12px}.btw-reference summary{cursor:pointer;color:var(--dsw-alias-label-secondary)}.btw-reference blockquote{margin:8px 0 0;padding:8px;border-left:2px solid var(--dsw-alias-border-l2);white-space:pre-wrap;overflow-wrap:anywhere;max-height:150px;overflow:auto}.btw-selection-dialog .btw-reference{padding:0}\n.btw-dock{display:flex;flex:none;flex-direction:column;gap:8px;width:calc(100% - var(--dsh-composer-side-clearance,0px) - var(--dsh-composer-side-clearance,0px));max-width:var(--dsh-composer-card-max-width,100%);margin:0 auto;max-height:440px;overflow:auto;padding:4px 0 10px;box-sizing:border-box;letter-spacing:0}\n.btw-bubble{background:var(--dsw-alias-bg-base);color:var(--dsw-alias-label-primary);border:1px solid var(--dsw-alias-border-l2);border-radius:12px;min-width:0;flex-shrink:0;font-size:13px;line-height:1.6;font-family:var(--dsw-font-family,inherit);letter-spacing:0}\n.btw-header{display:flex;align-items:center;gap:8px;padding:8px 10px 8px 14px;min-width:0;min-height:44px}\n.btw-symbol{display:flex;align-items:center;color:var(--dsw-alias-label-secondary);height:28px;flex-shrink:0}\n.btw-question{flex:1;min-width:0;overflow-wrap:anywhere;font-size:13px;font-weight:500;line-height:22px;max-height:66px;overflow:auto}\n.btw-actions{display:flex;gap:4px;flex-shrink:0}\n.btw-actions button{display:grid;place-items:center;width:28px;height:28px;padding:0;border:0;border-radius:50%;background:transparent;color:var(--dsw-alias-label-secondary);cursor:pointer;flex:none;transition:background-color 120ms ease}\n.btw-actions button:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}\n.btw-actions button:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,var(--dsw-alias-label-primary));outline-offset:-2px}\n.btw-actions button:disabled{cursor:wait;opacity:.5}\n.btw-status{display:flex;align-items:center;gap:8px;padding:0 14px 12px;color:var(--dsw-alias-label-secondary);font-size:13px}\n.btw-spinner{animation:btw-spin 1.2s linear infinite}@keyframes btw-spin{to{transform:rotate(360deg)}}\n.btw-answer{padding:0 14px 14px;max-height:300px;overflow:auto;overflow-wrap:anywhere;font-size:13px;line-height:1.7}\n.btw-answer>*:first-child{margin-top:0}.btw-answer>*:last-child{margin-bottom:0}\n.btw-answer p{margin:8px 0}.btw-answer h1,.btw-answer h2,.btw-answer h3{font-size:15px;line-height:1.5;margin:12px 0 6px;font-weight:600}\n.btw-answer pre{max-width:100%;overflow:auto;background:var(--dsw-alias-markdown-code-block);padding:10px;border-radius:8px;white-space:pre;font-size:12px}.btw-answer .katex-display{max-width:100%;overflow:auto}\n.btw-answer code{font-family:Consolas,monospace;font-size:12px}.btw-answer :not(pre)>code{background:var(--dsw-alias-markdown-code-block);border-radius:4px;padding:1px 3px}.btw-answer a{color:var(--dsw-alias-label-primary);text-decoration:underline;text-underline-offset:2px;overflow-wrap:anywhere}\n.btw-answer table{display:block;max-width:100%;overflow:auto;border-collapse:collapse}.btw-answer th,.btw-answer td{border:1px solid var(--dsw-alias-border-l2);padding:5px 9px}\n.btw-answer ul,.btw-answer ol{padding-left:22px}.btw-answer blockquote{margin:8px 0;padding-left:10px;border-left:2px solid var(--dsw-alias-border-l4);color:var(--dsw-alias-label-secondary)}\n.btw-error{margin:0;padding:0 14px 12px;font-size:13px;color:var(--dsw-alias-state-error-primary);overflow-wrap:anywhere}\n@media(max-width:480px){.btw-dock{max-height:330px}.btw-header{padding:6px 8px 6px 12px;gap:6px}.btw-answer{padding:0 12px 12px;max-height:230px}.btw-status,.btw-error{padding-left:12px}.btw-actions{gap:0}.btw-actions button{width:36px;height:36px}}\n@media(prefers-reduced-motion:reduce){.btw-spinner{animation:none}.btw-actions button{transition:none}}\n";
|
package/lib/types/locales.d.ts
CHANGED
|
@@ -15,8 +15,11 @@ export declare const zh: {
|
|
|
15
15
|
'error.reference': string;
|
|
16
16
|
'bubble.label': string;
|
|
17
17
|
'bubble.image': string;
|
|
18
|
+
'bubble.footnotes': string;
|
|
18
19
|
'action.copy': string;
|
|
19
20
|
'action.copied': string;
|
|
21
|
+
'action.copyCode': string;
|
|
22
|
+
'action.copiedCode': string;
|
|
20
23
|
'action.expand': string;
|
|
21
24
|
'action.collapse': string;
|
|
22
25
|
'action.close': string;
|
package/locale/en.json
ADDED
package/locale/zh.json
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@michengai/dsh-btw",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.17",
|
|
4
4
|
"description": "DSH 一次性只读旁问插件:基于当前上下文回答,独立气泡,不执行工具 · One-shot read-only side-ask plugin: answers from current context in an independent bubble, no tool execution",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -23,9 +23,11 @@
|
|
|
23
23
|
"default": "./lib/index.js"
|
|
24
24
|
},
|
|
25
25
|
"./client": "./lib/client.js",
|
|
26
|
-
"./package.json": "./package.json"
|
|
26
|
+
"./package.json": "./package.json",
|
|
27
|
+
"./locale/*.json": "./locale/*.json"
|
|
27
28
|
},
|
|
28
29
|
"files": [
|
|
30
|
+
"locale",
|
|
29
31
|
"lib",
|
|
30
32
|
"cordis.patch.yml",
|
|
31
33
|
"README.md",
|