dsh-focus-overlay 0.12.1 → 0.12.3
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.en.md +1 -1
- package/README.md +1 -1
- package/lib/client.js +217 -192
- package/package.json +3 -2
package/README.en.md
CHANGED
|
@@ -55,7 +55,7 @@ Click the line to expand that turn's full work detail (per-category one-line sum
|
|
|
55
55
|
| Feature | Description |
|
|
56
56
|
| --- | --- |
|
|
57
57
|
| Full-screen overlay | Registered into `shell.overlay` (additive, `replaceRisk: none`) — covers header / composer / sidebar; the thin top bar keeps only the session title and an exit button |
|
|
58
|
-
| Official rendering primitives | Assistant text through official `MarkdownText` (GFM + code highlighting + TeX + code copy buttons + footnotes); user messages through `
|
|
58
|
+
| Official rendering primitives | Assistant text through official `MarkdownText` (GFM + code highlighting + TeX + code copy buttons + footnotes); user messages through the official `projectUserText` projection; buttons, modals and icons are all official primitives |
|
|
59
59
|
| Image resolution | Assistant `image` blocks resolve through `uiConversation.imageUrl` (the dsh 0.1.2+ session-authorized image cache), falling back to the legacy resolver on older dsh |
|
|
60
60
|
| Tool-call folding | Follows the official "transcript view" preference (normal / compact); compact mode folds each turn's work part into a "N tool calls · M messages · K subagents" disclosure line ("Thought for a while" when nothing is countable), clickable to expand the full detail; steering messages always stay top-level, never buried; the last turn stays unfolded while streaming |
|
|
61
61
|
| Categorized summaries | The expanded detail counts tools by family: commands / edits / searches / reads / directory listings / subagents / todos / goals / workflows / skills / questions / plans / background jobs / context injections |
|
package/README.md
CHANGED
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
| 功能 | 说明 |
|
|
54
54
|
| --- | --- |
|
|
55
55
|
| 全屏专注遮罩 | 经 `shell.overlay` 注册(纯增量、`replaceRisk: none`),覆盖标题区 / 输入区 / 侧栏;顶部只留会话标题与「退出专注」按钮 |
|
|
56
|
-
| 官方渲染原语 | AI 文本走官方 `MarkdownText`(GFM + 代码高亮 + TeX + 代码复制按钮 +
|
|
56
|
+
| 官方渲染原语 | AI 文本走官方 `MarkdownText`(GFM + 代码高亮 + TeX + 代码复制按钮 + 脚注),用户消息走官方 `projectUserText` 投影;按钮、模态、图标均为官方原语 |
|
|
57
57
|
| 图片解析 | assistant 的 `image` 块经 `uiConversation.imageUrl`(dsh 0.1.2+ 的会话授权图片缓存)解析,旧版 dsh 自动回退到 legacy 解析器 |
|
|
58
58
|
| 工具调用折叠 | 遵循官方「对话显示」偏好(normal / compact);compact 模式把每轮的工作部分折叠成「N 次工具调用 · M 条消息 · K 个 subagent」披露行(无内容时显示「已思考」),点击可展开完整明细;steering 消息始终独立成行不被折叠;流式中的最后一轮保持展开直到结束 |
|
|
59
59
|
| 分类摘要明细 | 展开后按工具类别计数:命令 / 编辑 / 搜索 / 读取 / 列目录 / 子代理 / 待办 / 目标 / 工作流 / 技能 / 提问 / 计划 / 后台任务 / 上下文注入 |
|
package/lib/client.js
CHANGED
|
@@ -849,6 +849,196 @@ window.__ModuleLoader__.load({
|
|
|
849
849
|
return s;
|
|
850
850
|
}
|
|
851
851
|
//#endregion
|
|
852
|
+
//#region src/client/locales.ts
|
|
853
|
+
/** i18n dictionaries for the `focus` namespace. */
|
|
854
|
+
const zh = {
|
|
855
|
+
"toggle": "专注",
|
|
856
|
+
"toggle.title": "进入专注模式",
|
|
857
|
+
"exit": "退出专注 (Esc)",
|
|
858
|
+
"backToLatest": "回到最新",
|
|
859
|
+
"nav.label": "回合导航",
|
|
860
|
+
"nav.jump": "跳转到第 {n} 回合",
|
|
861
|
+
"nav.turn": "第 {n} 回合",
|
|
862
|
+
"settings.label": "专注模式",
|
|
863
|
+
"settings.description": "全屏阅读遮罩的偏好设置",
|
|
864
|
+
"settings.expand": "展开",
|
|
865
|
+
"settings.collapse": "收起",
|
|
866
|
+
"settings.navbar": "显示右侧轮次导航条",
|
|
867
|
+
"settings.navbar.hint": "在右侧显示导航圆点,每个用户消息(一轮)对应一个,悬停预览、点击跳转",
|
|
868
|
+
"settings.scrollPreserve": "进入专注模式时,同步当前阅读位置",
|
|
869
|
+
"settings.scrollPreserve.hint": "进入时定位到你正在阅读的消息;关闭则定位到你最近一次提问",
|
|
870
|
+
"settings.autoFocus": "AI完成回复后,自动进入专注模式",
|
|
871
|
+
"settings.autoFocus.hint": "AI 正常完成回复后自动进入并定位到你的提问",
|
|
872
|
+
"settings.hotkey": "按 F 键进入专注模式",
|
|
873
|
+
"settings.hotkey.hint": "在任意界面按下 F 立即进入专注模式;在输入框内打字不会触发",
|
|
874
|
+
"settings.borrow": "使用官方输入框",
|
|
875
|
+
"settings.borrow.hint": "专注模式直接借用主界面的官方输入框(支持 / 指令、@ 引用文件与会话);关闭时使用插件内置输入框。官方输入框不可用时自动回退。",
|
|
876
|
+
"settings.entries": "您已进入专注模式 {n} 次",
|
|
877
|
+
"settings.entries.cheer": "🎉 您已进入专注模式 {n} 次 ✨",
|
|
878
|
+
"settings.entries.star": "为这个项目点一个 GitHub Star ⭐",
|
|
879
|
+
"settings.entries.repo": "前往 GitHub 项目页面",
|
|
880
|
+
"process.toolCalls": "{n} 次工具调用",
|
|
881
|
+
"process.messages": "{n} 条消息",
|
|
882
|
+
"process.subagents": "{n} 个 subagent",
|
|
883
|
+
"process.thought": "已思考",
|
|
884
|
+
"process.separator": " · ",
|
|
885
|
+
"process.toolRow": "已完成",
|
|
886
|
+
"empty": "暂无打开的会话",
|
|
887
|
+
"loading": "正在读取会话…",
|
|
888
|
+
"running": "正在工作",
|
|
889
|
+
"reply.ready": "新回复已生成",
|
|
890
|
+
"reply.view": "查看",
|
|
891
|
+
"reply.waiting": "AI 正在等待你的回复",
|
|
892
|
+
"answer.open": "去回答",
|
|
893
|
+
"answer.title": "等待你的回答",
|
|
894
|
+
"answer.approvalTitle": "请求审批",
|
|
895
|
+
"answer.planTitle": "计划待审",
|
|
896
|
+
"answer.submit": "提交回答",
|
|
897
|
+
"answer.close": "收起",
|
|
898
|
+
"answer.custom": "其他答案(可选)",
|
|
899
|
+
"answer.recommended": "推荐",
|
|
900
|
+
"answer.incomplete": "请先回答所有问题",
|
|
901
|
+
"answer.rejected": "提交被拒绝",
|
|
902
|
+
"answer.allow": "允许",
|
|
903
|
+
"answer.reject": "拒绝",
|
|
904
|
+
"composer.placeholder": "输入回复…",
|
|
905
|
+
"composer.send": "发送",
|
|
906
|
+
"markdown.code.copy": "复制代码",
|
|
907
|
+
"markdown.code.copied": "已复制",
|
|
908
|
+
"markdown.footnotes": "脚注",
|
|
909
|
+
"composer.expand": "展开输入框",
|
|
910
|
+
"composer.queued": "已排队 {n}",
|
|
911
|
+
"composer.occurrences": "草稿中包含引用 / 命令,在此编辑可能使其失效,建议退出专注模式编辑",
|
|
912
|
+
"sum.context": "载入了 {n} 项上下文",
|
|
913
|
+
"sum.commands": "运行了 {n} 个命令",
|
|
914
|
+
"sum.edits": "编辑了 {n} 个文件",
|
|
915
|
+
"sum.searches": "搜索了 {n} 个正则",
|
|
916
|
+
"sum.files": "读取了 {n} 个文件",
|
|
917
|
+
"sum.dirs": "列出了 {n} 个目录",
|
|
918
|
+
"sum.subagents": "fork 了 {n} 个子代理",
|
|
919
|
+
"sum.todos": "更新了待办",
|
|
920
|
+
"sum.goals": "更新了目标",
|
|
921
|
+
"sum.workflows": "运行了 {n} 个工作流",
|
|
922
|
+
"sum.skills": "载入了 {n} 个技能",
|
|
923
|
+
"sum.questions": "问了 {n} 个问题",
|
|
924
|
+
"sum.plans": "计划了 {n} 次",
|
|
925
|
+
"sum.jobs": "后台任务 {n} 个",
|
|
926
|
+
"sum.others": "调用了 {n} 个工具",
|
|
927
|
+
"onboarding.title": "欢迎使用专注模式",
|
|
928
|
+
"onboarding.intro": "dsh-focus-overlay 为 DeepSeek Harness Web 提供全屏专注阅读。",
|
|
929
|
+
"onboarding.features.title": "功能",
|
|
930
|
+
"onboarding.feature.fullscreen": "全屏阅读 —— 隐藏标题栏、输入区与侧栏,纵向空间尽给对话",
|
|
931
|
+
"onboarding.feature.fold": "折叠工具调用 —— 把 AI 的命令、编辑、搜索等步骤折叠成一行摘要",
|
|
932
|
+
"onboarding.feature.navbar": "右侧导航条 —— 按用户消息快速跳转,悬停预览",
|
|
933
|
+
"onboarding.feature.autoFocus": "自动专注与提醒 —— 回复完成自动进入专注,AI 提问 / 等待时提醒",
|
|
934
|
+
"onboarding.feature.hotkey": "快捷键 F —— 任意界面按 F 一键进入专注,可在设置中关闭",
|
|
935
|
+
"onboarding.configure.title": "快速配置",
|
|
936
|
+
"onboarding.laterNote": "这些设置随时可在「设置 → 插件 → 插件配置」中更改。",
|
|
937
|
+
"onboarding.openSettings": "打开设置",
|
|
938
|
+
"onboarding.done": "完成"
|
|
939
|
+
};
|
|
940
|
+
const en = {
|
|
941
|
+
"toggle": "Focus",
|
|
942
|
+
"toggle.title": "Enter focus mode",
|
|
943
|
+
"exit": "Exit focus (Esc)",
|
|
944
|
+
"backToLatest": "Back to latest",
|
|
945
|
+
"nav.label": "Turn navigation",
|
|
946
|
+
"nav.jump": "Jump to turn {n}",
|
|
947
|
+
"nav.turn": "Turn {n}",
|
|
948
|
+
"settings.label": "Focus Mode",
|
|
949
|
+
"settings.description": "Preferences for the full-screen reading overlay",
|
|
950
|
+
"settings.expand": "Expand",
|
|
951
|
+
"settings.collapse": "Collapse",
|
|
952
|
+
"settings.navbar": "Show right-side turn navbar",
|
|
953
|
+
"settings.navbar.hint": "Show one navigation dot per user message (turn) — hover to preview, click to jump",
|
|
954
|
+
"settings.scrollPreserve": "Sync the current reading position when entering focus mode",
|
|
955
|
+
"settings.scrollPreserve.hint": "Open at the message you're reading; off opens at your most recent question",
|
|
956
|
+
"settings.autoFocus": "Auto-enter focus mode when the AI finishes a reply",
|
|
957
|
+
"settings.autoFocus.hint": "Auto-open at your question after a normal reply",
|
|
958
|
+
"settings.hotkey": "Press F to enter focus mode",
|
|
959
|
+
"settings.hotkey.hint": "Press F anywhere to enter focus mode instantly; typing in an input never triggers it",
|
|
960
|
+
"settings.borrow": "Use the official composer",
|
|
961
|
+
"settings.borrow.hint": "Focus mode borrows the main view's official composer (slash commands, @ file/session references included); turn off to use the built-in input bar. Falls back automatically when the official composer is unavailable.",
|
|
962
|
+
"settings.entries": "You have entered focus mode {n} times",
|
|
963
|
+
"settings.entries.cheer": "🎉 You have entered focus mode {n} times ✨",
|
|
964
|
+
"settings.entries.star": "Give this project a GitHub Star ⭐",
|
|
965
|
+
"settings.entries.repo": "Open the GitHub project page",
|
|
966
|
+
"process.toolCalls": "{n} tool calls",
|
|
967
|
+
"process.messages": "{n} messages",
|
|
968
|
+
"process.subagents": "{n} subagents",
|
|
969
|
+
"process.thought": "Thought for a while",
|
|
970
|
+
"process.separator": " · ",
|
|
971
|
+
"process.toolRow": "completed",
|
|
972
|
+
"empty": "No open session",
|
|
973
|
+
"loading": "Reading session…",
|
|
974
|
+
"running": "Working",
|
|
975
|
+
"reply.ready": "New reply ready",
|
|
976
|
+
"reply.view": "View",
|
|
977
|
+
"reply.waiting": "AI is waiting for your reply",
|
|
978
|
+
"answer.open": "Answer",
|
|
979
|
+
"answer.title": "Waiting for your answer",
|
|
980
|
+
"answer.approvalTitle": "Approval requested",
|
|
981
|
+
"answer.planTitle": "Plan review",
|
|
982
|
+
"answer.submit": "Submit answer",
|
|
983
|
+
"answer.close": "Collapse",
|
|
984
|
+
"answer.custom": "Other (optional)",
|
|
985
|
+
"answer.recommended": "Recommended",
|
|
986
|
+
"answer.incomplete": "Answer every question first",
|
|
987
|
+
"answer.rejected": "Submission rejected",
|
|
988
|
+
"answer.allow": "Allow",
|
|
989
|
+
"answer.reject": "Deny",
|
|
990
|
+
"composer.placeholder": "Type a reply…",
|
|
991
|
+
"composer.send": "Send",
|
|
992
|
+
"markdown.code.copy": "Copy code",
|
|
993
|
+
"markdown.code.copied": "Copied",
|
|
994
|
+
"markdown.footnotes": "Footnotes",
|
|
995
|
+
"composer.expand": "Expand input",
|
|
996
|
+
"composer.queued": "Queued {n}",
|
|
997
|
+
"composer.occurrences": "Draft contains references / commands — editing here may break them; edit outside focus mode",
|
|
998
|
+
"sum.context": "loaded {n} context items",
|
|
999
|
+
"sum.commands": "ran {n} commands",
|
|
1000
|
+
"sum.edits": "edited {n} files",
|
|
1001
|
+
"sum.searches": "ran {n} searches",
|
|
1002
|
+
"sum.files": "read {n} files",
|
|
1003
|
+
"sum.dirs": "listed {n} directories",
|
|
1004
|
+
"sum.subagents": "forked {n} subagents",
|
|
1005
|
+
"sum.todos": "updated todos",
|
|
1006
|
+
"sum.goals": "updated goals",
|
|
1007
|
+
"sum.workflows": "ran {n} workflows",
|
|
1008
|
+
"sum.skills": "loaded {n} skills",
|
|
1009
|
+
"sum.questions": "asked {n} questions",
|
|
1010
|
+
"sum.plans": "planned {n} times",
|
|
1011
|
+
"sum.jobs": "{n} background jobs",
|
|
1012
|
+
"sum.others": "called {n} tools",
|
|
1013
|
+
"onboarding.title": "Welcome to Focus Mode",
|
|
1014
|
+
"onboarding.intro": "dsh-focus-overlay adds full-screen reading to the DeepSeek Harness web GUI.",
|
|
1015
|
+
"onboarding.features.title": "Features",
|
|
1016
|
+
"onboarding.feature.fullscreen": "Full-screen reading — hides the header, composer and sidebars",
|
|
1017
|
+
"onboarding.feature.fold": "Folded tool calls — collapses commands, edits and searches into one summary line",
|
|
1018
|
+
"onboarding.feature.navbar": "Right-side navbar — jump between user messages with hover previews",
|
|
1019
|
+
"onboarding.feature.autoFocus": "Auto-focus & reminders — auto-enter after a reply, notify while the AI waits",
|
|
1020
|
+
"onboarding.feature.hotkey": "Hotkey F — press F anywhere to enter focus mode (toggleable in settings)",
|
|
1021
|
+
"onboarding.configure.title": "Quick setup",
|
|
1022
|
+
"onboarding.laterNote": "You can change these anytime in Settings → Plugins → Plugin configuration.",
|
|
1023
|
+
"onboarding.openSettings": "Open settings",
|
|
1024
|
+
"onboarding.done": "Done"
|
|
1025
|
+
};
|
|
1026
|
+
/** Labels the official MarkdownText requires for its code-block copy buttons
|
|
1027
|
+
* and footnotes section — mirrors the official `markdownLabels(t)` shape.
|
|
1028
|
+
* Lives here (not FocusView) so both the transcript items and the answer
|
|
1029
|
+
* card share it without an import cycle (FocusView imports Composer).
|
|
1030
|
+
* Without it the renderer throws `Cannot read properties of undefined
|
|
1031
|
+
* (reading 'code')` on the first fenced code block. */
|
|
1032
|
+
function markdownLabels(t) {
|
|
1033
|
+
return {
|
|
1034
|
+
code: {
|
|
1035
|
+
copyLabel: t("markdown.code.copy"),
|
|
1036
|
+
copiedLabel: t("markdown.code.copied")
|
|
1037
|
+
},
|
|
1038
|
+
footnotes: t("markdown.footnotes")
|
|
1039
|
+
};
|
|
1040
|
+
}
|
|
1041
|
+
//#endregion
|
|
852
1042
|
//#region src/client/Composer.tsx
|
|
853
1043
|
/**
|
|
854
1044
|
* The focus-mode bottom dock: the compact composer region that replaces the
|
|
@@ -945,6 +1135,8 @@ window.__ModuleLoader__.load({
|
|
|
945
1135
|
const { t, width, wait, onClose } = props;
|
|
946
1136
|
const isQuestion = !(wait.kind === "approval");
|
|
947
1137
|
const questions = isQuestion && Array.isArray(wait.questions) ? wait.questions : [];
|
|
1138
|
+
const isPlanReview = questions.some((q) => q && q.intent && q.intent.kind === "plan-review");
|
|
1139
|
+
const mdLabels = (0, react.useMemo)(() => markdownLabels(t), [t]);
|
|
948
1140
|
const [drafts, setDrafts] = (0, react.useState)({});
|
|
949
1141
|
const [busy, setBusy] = (0, react.useState)(false);
|
|
950
1142
|
const [error, setError] = (0, react.useState)(null);
|
|
@@ -1020,7 +1212,7 @@ window.__ModuleLoader__.load({
|
|
|
1020
1212
|
children: t("reply.waiting")
|
|
1021
1213
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
|
|
1022
1214
|
className: "fm-card-title",
|
|
1023
|
-
children: t("answer.title")
|
|
1215
|
+
children: isPlanReview ? t("answer.planTitle") : t("answer.title")
|
|
1024
1216
|
})]
|
|
1025
1217
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1026
1218
|
type: "button",
|
|
@@ -1064,7 +1256,10 @@ window.__ModuleLoader__.load({
|
|
|
1064
1256
|
}),
|
|
1065
1257
|
q.detail ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1066
1258
|
className: "fm-card-detail",
|
|
1067
|
-
children:
|
|
1259
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.MarkdownText, {
|
|
1260
|
+
text: q.detail,
|
|
1261
|
+
labels: mdLabels
|
|
1262
|
+
})
|
|
1068
1263
|
}) : null,
|
|
1069
1264
|
q.options && q.options.length ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1070
1265
|
className: "fm-card-opts",
|
|
@@ -1580,7 +1775,10 @@ window.__ModuleLoader__.load({
|
|
|
1580
1775
|
.fm-card-body{overscroll-behavior:contain;flex:1 1 auto;min-height:0;display:flex;flex-direction:column;overflow-y:auto;padding-bottom:8px;font-size:var(--dsh-content-font-size,14px);line-height:calc(22px + var(--dsh-content-font-delta,0px))}
|
|
1581
1776
|
.fm-card-q{display:flex;flex-direction:column}
|
|
1582
1777
|
.fm-card-q-text{margin:0 2px 8px;padding:0 22px;white-space:pre-wrap;word-break:break-word;font-size:calc(var(--dsh-content-font-size,14px) + 2px);font-weight:500;line-height:calc(22px + var(--dsh-content-font-delta,0px))}
|
|
1583
|
-
.fm-card-detail{color:var(--dsw-alias-label-secondary,#888);margin:0 2px 8px;padding:0 22px;font
|
|
1778
|
+
.fm-card-detail{color:var(--dsw-alias-label-secondary,#888);margin:0 2px 8px;padding:0 22px;font:var(--dsw-font-markdown-base,400 var(--dsh-content-font-size,14px)/calc(24px + var(--dsh-content-font-delta,0px)) var(--dsw-font-family,sans-serif))}
|
|
1779
|
+
.fm-card-detail>*:first-child{margin-top:0}
|
|
1780
|
+
.fm-card-detail>*:last-child{margin-bottom:0}
|
|
1781
|
+
.fm-card-detail pre{overflow-x:auto}
|
|
1584
1782
|
.fm-card-opts{display:flex;flex-direction:column;gap:1px;margin:8px 0 0;padding:4px 12px}
|
|
1585
1783
|
.fm-opt{width:100%;min-height:40px;color:inherit;text-align:left;cursor:pointer;background:0 0;border:1px solid #0000;border-radius:12px;flex-shrink:0;display:flex;align-items:flex-start;gap:8px;padding:8px 12px 8px 8px;transition:background-color .12s,border-color .12s;font:inherit}
|
|
1586
1784
|
.fm-opt:hover:not(:disabled),.fm-opt-on{background:var(--dsw-alias-interactive-bg-hover,rgba(0,0,0,.06))}
|
|
@@ -2066,6 +2264,19 @@ body[data-fm-focus] #root :has(> [data-slot="conversation"]){margin-bottom:0!imp
|
|
|
2066
2264
|
(0, react.useEffect)(() => focusStore.subscribe(() => setV(focusStore.getDonePing())), []);
|
|
2067
2265
|
return v;
|
|
2068
2266
|
}
|
|
2267
|
+
/** Body of a sent user message / steering row.
|
|
2268
|
+
*
|
|
2269
|
+
* dsh 0.1.3-alpha.2 removed the `MessageText` component from the primitives
|
|
2270
|
+
* module in favour of the `projectUserText` display projection (which has
|
|
2271
|
+
* existed since 0.1.2 and is still exported by 0.1.5). Importing the removed
|
|
2272
|
+
* name made it `undefined`, so the overlay threw React #130 the moment it
|
|
2273
|
+
* rendered a session containing a user message — the "toggle does nothing"
|
|
2274
|
+
* symptom. `projectUserText` returns inline plain runs plus `@session` /
|
|
2275
|
+
* `/skill` chips; `.fm-user` still supplies the bubble chrome and
|
|
2276
|
+
* `white-space: pre-wrap`, so the text keeps its shape. */
|
|
2277
|
+
function UserText({ text }) {
|
|
2278
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: (0, _deepseek_ai_dsh_client_ui_primitives.projectUserText)(text, []) });
|
|
2279
|
+
}
|
|
2069
2280
|
let bodyEl = null;
|
|
2070
2281
|
const anchors = {};
|
|
2071
2282
|
function useSessionSnapshot(sessions, sessionId) {
|
|
@@ -2191,19 +2402,6 @@ body[data-fm-focus] #root :has(> [data-slot="conversation"]){margin-bottom:0!imp
|
|
|
2191
2402
|
alt: ""
|
|
2192
2403
|
});
|
|
2193
2404
|
}
|
|
2194
|
-
/** Labels the official MarkdownText requires for its code-block copy buttons
|
|
2195
|
-
* and footnotes section — mirrors the official `markdownLabels(t)` shape.
|
|
2196
|
-
* Without it the renderer throws `Cannot read properties of undefined
|
|
2197
|
-
* (reading 'code')` on the first fenced code block. */
|
|
2198
|
-
function markdownLabels(t) {
|
|
2199
|
-
return {
|
|
2200
|
-
code: {
|
|
2201
|
-
copyLabel: t("markdown.code.copy"),
|
|
2202
|
-
copiedLabel: t("markdown.code.copied")
|
|
2203
|
-
},
|
|
2204
|
-
footnotes: t("markdown.footnotes")
|
|
2205
|
-
};
|
|
2206
|
-
}
|
|
2207
2405
|
function AssistantItem(props) {
|
|
2208
2406
|
const { blocks, loadImage, fileMentions, labels } = props;
|
|
2209
2407
|
const text = (blocks || []).filter((b) => b && b.kind === "text").map((b) => b.text).join("");
|
|
@@ -2790,7 +2988,7 @@ body[data-fm-focus] #root :has(> [data-slot="conversation"]){margin-bottom:0!imp
|
|
|
2790
2988
|
},
|
|
2791
2989
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2792
2990
|
className: "fm-user",
|
|
2793
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
2991
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(UserText, { text: it.text })
|
|
2794
2992
|
})
|
|
2795
2993
|
}, key);
|
|
2796
2994
|
if (it.kind === "steering") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
@@ -2801,7 +2999,7 @@ body[data-fm-focus] #root :has(> [data-slot="conversation"]){margin-bottom:0!imp
|
|
|
2801
2999
|
},
|
|
2802
3000
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2803
3001
|
className: "fm-user fm-steering",
|
|
2804
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
3002
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(UserText, { text: it.text })
|
|
2805
3003
|
})
|
|
2806
3004
|
}, key);
|
|
2807
3005
|
if (it.kind === "assistant") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AssistantItem, {
|
|
@@ -3292,179 +3490,6 @@ body[data-fm-focus] #root :has(> [data-slot="conversation"]){margin-bottom:0!imp
|
|
|
3292
3490
|
});
|
|
3293
3491
|
}
|
|
3294
3492
|
//#endregion
|
|
3295
|
-
//#region src/client/locales.ts
|
|
3296
|
-
/** i18n dictionaries for the `focus` namespace. */
|
|
3297
|
-
const zh = {
|
|
3298
|
-
"toggle": "专注",
|
|
3299
|
-
"toggle.title": "进入专注模式",
|
|
3300
|
-
"exit": "退出专注 (Esc)",
|
|
3301
|
-
"backToLatest": "回到最新",
|
|
3302
|
-
"nav.label": "回合导航",
|
|
3303
|
-
"nav.jump": "跳转到第 {n} 回合",
|
|
3304
|
-
"nav.turn": "第 {n} 回合",
|
|
3305
|
-
"settings.label": "专注模式",
|
|
3306
|
-
"settings.description": "全屏阅读遮罩的偏好设置",
|
|
3307
|
-
"settings.expand": "展开",
|
|
3308
|
-
"settings.collapse": "收起",
|
|
3309
|
-
"settings.navbar": "显示右侧轮次导航条",
|
|
3310
|
-
"settings.navbar.hint": "在右侧显示导航圆点,每个用户消息(一轮)对应一个,悬停预览、点击跳转",
|
|
3311
|
-
"settings.scrollPreserve": "进入专注模式时,同步当前阅读位置",
|
|
3312
|
-
"settings.scrollPreserve.hint": "进入时定位到你正在阅读的消息;关闭则定位到你最近一次提问",
|
|
3313
|
-
"settings.autoFocus": "AI完成回复后,自动进入专注模式",
|
|
3314
|
-
"settings.autoFocus.hint": "AI 正常完成回复后自动进入并定位到你的提问",
|
|
3315
|
-
"settings.hotkey": "按 F 键进入专注模式",
|
|
3316
|
-
"settings.hotkey.hint": "在任意界面按下 F 立即进入专注模式;在输入框内打字不会触发",
|
|
3317
|
-
"settings.borrow": "使用官方输入框",
|
|
3318
|
-
"settings.borrow.hint": "专注模式直接借用主界面的官方输入框(支持 / 指令、@ 引用文件与会话);关闭时使用插件内置输入框。官方输入框不可用时自动回退。",
|
|
3319
|
-
"settings.entries": "您已进入专注模式 {n} 次",
|
|
3320
|
-
"settings.entries.cheer": "🎉 您已进入专注模式 {n} 次 ✨",
|
|
3321
|
-
"settings.entries.star": "为这个项目点一个 GitHub Star ⭐",
|
|
3322
|
-
"settings.entries.repo": "前往 GitHub 项目页面",
|
|
3323
|
-
"process.toolCalls": "{n} 次工具调用",
|
|
3324
|
-
"process.messages": "{n} 条消息",
|
|
3325
|
-
"process.subagents": "{n} 个 subagent",
|
|
3326
|
-
"process.thought": "已思考",
|
|
3327
|
-
"process.separator": " · ",
|
|
3328
|
-
"process.toolRow": "已完成",
|
|
3329
|
-
"empty": "暂无打开的会话",
|
|
3330
|
-
"loading": "正在读取会话…",
|
|
3331
|
-
"running": "正在工作",
|
|
3332
|
-
"reply.ready": "新回复已生成",
|
|
3333
|
-
"reply.view": "查看",
|
|
3334
|
-
"reply.waiting": "AI 正在等待你的回复",
|
|
3335
|
-
"answer.open": "去回答",
|
|
3336
|
-
"answer.title": "等待你的回答",
|
|
3337
|
-
"answer.approvalTitle": "请求审批",
|
|
3338
|
-
"answer.submit": "提交回答",
|
|
3339
|
-
"answer.close": "收起",
|
|
3340
|
-
"answer.custom": "其他答案(可选)",
|
|
3341
|
-
"answer.recommended": "推荐",
|
|
3342
|
-
"answer.incomplete": "请先回答所有问题",
|
|
3343
|
-
"answer.rejected": "提交被拒绝",
|
|
3344
|
-
"answer.allow": "允许",
|
|
3345
|
-
"answer.reject": "拒绝",
|
|
3346
|
-
"composer.placeholder": "输入回复…",
|
|
3347
|
-
"composer.send": "发送",
|
|
3348
|
-
"markdown.code.copy": "复制代码",
|
|
3349
|
-
"markdown.code.copied": "已复制",
|
|
3350
|
-
"markdown.footnotes": "脚注",
|
|
3351
|
-
"composer.expand": "展开输入框",
|
|
3352
|
-
"composer.queued": "已排队 {n}",
|
|
3353
|
-
"composer.occurrences": "草稿中包含引用 / 命令,在此编辑可能使其失效,建议退出专注模式编辑",
|
|
3354
|
-
"sum.context": "载入了 {n} 项上下文",
|
|
3355
|
-
"sum.commands": "运行了 {n} 个命令",
|
|
3356
|
-
"sum.edits": "编辑了 {n} 个文件",
|
|
3357
|
-
"sum.searches": "搜索了 {n} 个正则",
|
|
3358
|
-
"sum.files": "读取了 {n} 个文件",
|
|
3359
|
-
"sum.dirs": "列出了 {n} 个目录",
|
|
3360
|
-
"sum.subagents": "fork 了 {n} 个子代理",
|
|
3361
|
-
"sum.todos": "更新了待办",
|
|
3362
|
-
"sum.goals": "更新了目标",
|
|
3363
|
-
"sum.workflows": "运行了 {n} 个工作流",
|
|
3364
|
-
"sum.skills": "载入了 {n} 个技能",
|
|
3365
|
-
"sum.questions": "问了 {n} 个问题",
|
|
3366
|
-
"sum.plans": "计划了 {n} 次",
|
|
3367
|
-
"sum.jobs": "后台任务 {n} 个",
|
|
3368
|
-
"sum.others": "调用了 {n} 个工具",
|
|
3369
|
-
"onboarding.title": "欢迎使用专注模式",
|
|
3370
|
-
"onboarding.intro": "dsh-focus-overlay 为 DeepSeek Harness Web 提供全屏专注阅读。",
|
|
3371
|
-
"onboarding.features.title": "功能",
|
|
3372
|
-
"onboarding.feature.fullscreen": "全屏阅读 —— 隐藏标题栏、输入区与侧栏,纵向空间尽给对话",
|
|
3373
|
-
"onboarding.feature.fold": "折叠工具调用 —— 把 AI 的命令、编辑、搜索等步骤折叠成一行摘要",
|
|
3374
|
-
"onboarding.feature.navbar": "右侧导航条 —— 按用户消息快速跳转,悬停预览",
|
|
3375
|
-
"onboarding.feature.autoFocus": "自动专注与提醒 —— 回复完成自动进入专注,AI 提问 / 等待时提醒",
|
|
3376
|
-
"onboarding.feature.hotkey": "快捷键 F —— 任意界面按 F 一键进入专注,可在设置中关闭",
|
|
3377
|
-
"onboarding.configure.title": "快速配置",
|
|
3378
|
-
"onboarding.laterNote": "这些设置随时可在「设置 → 插件 → 插件配置」中更改。",
|
|
3379
|
-
"onboarding.openSettings": "打开设置",
|
|
3380
|
-
"onboarding.done": "完成"
|
|
3381
|
-
};
|
|
3382
|
-
const en = {
|
|
3383
|
-
"toggle": "Focus",
|
|
3384
|
-
"toggle.title": "Enter focus mode",
|
|
3385
|
-
"exit": "Exit focus (Esc)",
|
|
3386
|
-
"backToLatest": "Back to latest",
|
|
3387
|
-
"nav.label": "Turn navigation",
|
|
3388
|
-
"nav.jump": "Jump to turn {n}",
|
|
3389
|
-
"nav.turn": "Turn {n}",
|
|
3390
|
-
"settings.label": "Focus Mode",
|
|
3391
|
-
"settings.description": "Preferences for the full-screen reading overlay",
|
|
3392
|
-
"settings.expand": "Expand",
|
|
3393
|
-
"settings.collapse": "Collapse",
|
|
3394
|
-
"settings.navbar": "Show right-side turn navbar",
|
|
3395
|
-
"settings.navbar.hint": "Show one navigation dot per user message (turn) — hover to preview, click to jump",
|
|
3396
|
-
"settings.scrollPreserve": "Sync the current reading position when entering focus mode",
|
|
3397
|
-
"settings.scrollPreserve.hint": "Open at the message you're reading; off opens at your most recent question",
|
|
3398
|
-
"settings.autoFocus": "Auto-enter focus mode when the AI finishes a reply",
|
|
3399
|
-
"settings.autoFocus.hint": "Auto-open at your question after a normal reply",
|
|
3400
|
-
"settings.hotkey": "Press F to enter focus mode",
|
|
3401
|
-
"settings.hotkey.hint": "Press F anywhere to enter focus mode instantly; typing in an input never triggers it",
|
|
3402
|
-
"settings.borrow": "Use the official composer",
|
|
3403
|
-
"settings.borrow.hint": "Focus mode borrows the main view's official composer (slash commands, @ file/session references included); turn off to use the built-in input bar. Falls back automatically when the official composer is unavailable.",
|
|
3404
|
-
"settings.entries": "You have entered focus mode {n} times",
|
|
3405
|
-
"settings.entries.cheer": "🎉 You have entered focus mode {n} times ✨",
|
|
3406
|
-
"settings.entries.star": "Give this project a GitHub Star ⭐",
|
|
3407
|
-
"settings.entries.repo": "Open the GitHub project page",
|
|
3408
|
-
"process.toolCalls": "{n} tool calls",
|
|
3409
|
-
"process.messages": "{n} messages",
|
|
3410
|
-
"process.subagents": "{n} subagents",
|
|
3411
|
-
"process.thought": "Thought for a while",
|
|
3412
|
-
"process.separator": " · ",
|
|
3413
|
-
"process.toolRow": "completed",
|
|
3414
|
-
"empty": "No open session",
|
|
3415
|
-
"loading": "Reading session…",
|
|
3416
|
-
"running": "Working",
|
|
3417
|
-
"reply.ready": "New reply ready",
|
|
3418
|
-
"reply.view": "View",
|
|
3419
|
-
"reply.waiting": "AI is waiting for your reply",
|
|
3420
|
-
"answer.open": "Answer",
|
|
3421
|
-
"answer.title": "Waiting for your answer",
|
|
3422
|
-
"answer.approvalTitle": "Approval requested",
|
|
3423
|
-
"answer.submit": "Submit answer",
|
|
3424
|
-
"answer.close": "Collapse",
|
|
3425
|
-
"answer.custom": "Other (optional)",
|
|
3426
|
-
"answer.recommended": "Recommended",
|
|
3427
|
-
"answer.incomplete": "Answer every question first",
|
|
3428
|
-
"answer.rejected": "Submission rejected",
|
|
3429
|
-
"answer.allow": "Allow",
|
|
3430
|
-
"answer.reject": "Deny",
|
|
3431
|
-
"composer.placeholder": "Type a reply…",
|
|
3432
|
-
"composer.send": "Send",
|
|
3433
|
-
"markdown.code.copy": "Copy code",
|
|
3434
|
-
"markdown.code.copied": "Copied",
|
|
3435
|
-
"markdown.footnotes": "Footnotes",
|
|
3436
|
-
"composer.expand": "Expand input",
|
|
3437
|
-
"composer.queued": "Queued {n}",
|
|
3438
|
-
"composer.occurrences": "Draft contains references / commands — editing here may break them; edit outside focus mode",
|
|
3439
|
-
"sum.context": "loaded {n} context items",
|
|
3440
|
-
"sum.commands": "ran {n} commands",
|
|
3441
|
-
"sum.edits": "edited {n} files",
|
|
3442
|
-
"sum.searches": "ran {n} searches",
|
|
3443
|
-
"sum.files": "read {n} files",
|
|
3444
|
-
"sum.dirs": "listed {n} directories",
|
|
3445
|
-
"sum.subagents": "forked {n} subagents",
|
|
3446
|
-
"sum.todos": "updated todos",
|
|
3447
|
-
"sum.goals": "updated goals",
|
|
3448
|
-
"sum.workflows": "ran {n} workflows",
|
|
3449
|
-
"sum.skills": "loaded {n} skills",
|
|
3450
|
-
"sum.questions": "asked {n} questions",
|
|
3451
|
-
"sum.plans": "planned {n} times",
|
|
3452
|
-
"sum.jobs": "{n} background jobs",
|
|
3453
|
-
"sum.others": "called {n} tools",
|
|
3454
|
-
"onboarding.title": "Welcome to Focus Mode",
|
|
3455
|
-
"onboarding.intro": "dsh-focus-overlay adds full-screen reading to the DeepSeek Harness web GUI.",
|
|
3456
|
-
"onboarding.features.title": "Features",
|
|
3457
|
-
"onboarding.feature.fullscreen": "Full-screen reading — hides the header, composer and sidebars",
|
|
3458
|
-
"onboarding.feature.fold": "Folded tool calls — collapses commands, edits and searches into one summary line",
|
|
3459
|
-
"onboarding.feature.navbar": "Right-side navbar — jump between user messages with hover previews",
|
|
3460
|
-
"onboarding.feature.autoFocus": "Auto-focus & reminders — auto-enter after a reply, notify while the AI waits",
|
|
3461
|
-
"onboarding.feature.hotkey": "Hotkey F — press F anywhere to enter focus mode (toggleable in settings)",
|
|
3462
|
-
"onboarding.configure.title": "Quick setup",
|
|
3463
|
-
"onboarding.laterNote": "You can change these anytime in Settings → Plugins → Plugin configuration.",
|
|
3464
|
-
"onboarding.openSettings": "Open settings",
|
|
3465
|
-
"onboarding.done": "Done"
|
|
3466
|
-
};
|
|
3467
|
-
//#endregion
|
|
3468
3493
|
//#region src/client/index.ts
|
|
3469
3494
|
/**
|
|
3470
3495
|
* Focus Mode, browser half: a full-screen reading overlay in `shell.overlay`
|
|
@@ -3472,7 +3497,7 @@ body[data-fm-focus] #root :has(> [data-slot="conversation"]){margin-bottom:0!imp
|
|
|
3472
3497
|
* action row, and a collapsible plugin card in the Plugins settings tab
|
|
3473
3498
|
* (`settings.plugin.item`). Rendering reuses the official client UI primitives
|
|
3474
3499
|
* module (`@deepseek-ai/dsh-client-ui-primitives` runtime id) — Markdown /
|
|
3475
|
-
*
|
|
3500
|
+
* projectUserText / Tooltip / Button — plus the conversation service's composer
|
|
3476
3501
|
* registry and the uiSession pending-interaction service (dsh 0.1.2).
|
|
3477
3502
|
*/
|
|
3478
3503
|
const NS = "focus";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-focus-overlay",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.3",
|
|
4
4
|
"description": "Focus Mode for the dsh web GUI: a full-screen reading overlay that hides chrome and folds the AI tool-call flow into summaries, reusing the official Markdown / image primitives.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.mjs",
|
|
@@ -30,7 +30,8 @@
|
|
|
30
30
|
"dshReleases": {
|
|
31
31
|
"0.1.2-alpha.5": "compatible",
|
|
32
32
|
"0.1.2-rc.1": "compatible",
|
|
33
|
-
"0.1.3-alpha.1": "compatible"
|
|
33
|
+
"0.1.3-alpha.1": "compatible",
|
|
34
|
+
"0.1.5-rc.1": "compatible"
|
|
34
35
|
}
|
|
35
36
|
}
|
|
36
37
|
},
|