dsh-conversation-overview 1.2.0 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -24
- package/client.js +133 -7
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,24 +8,12 @@ DeepSeek Harness(DSH)插件:在对话/轨迹旁增加「概览」标签页
|
|
|
8
8
|
|
|
9
9
|
## 功能特性
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
- 团队会话显示各成员阶段(创建中/运行中/空闲/失败/阻塞),可展开团队详情;
|
|
18
|
-
- 点击步骤行复制其完整目标文本(命令/文件路径/查询等),悬停查看全文;
|
|
19
|
-
- 双击 todo 行把「重新执行指定步骤」的提示词填入聊天输入框(不自动发送),提示词模板可自定义(支持 `{index}`、`{content}` 占位符)。
|
|
20
|
-
- **产物**:产出/交付文件列表、按轮次分组的变更审阅入口、Finder/系统定位;右键菜单支持「打开方式」选择应用与系统定位。
|
|
21
|
-
- **引用**:上下文注入、OpenViking 记忆(`viking://`)、技能目录、文件与会话引用;
|
|
22
|
-
- 类型多选下拉筛选(选中类型以 chips 显示)、「过滤常见」隐藏每轮都出现的注入、排序(最新/类型/次数,可点击取消);
|
|
23
|
-
- `viking://` 记忆在右侧边栏新标签页内预览(frontmatter 结构化 + Markdown 渲染 + 预览/源码切换,经 OpenViking HTTP API);
|
|
24
|
-
- 运行时上下文注入可点击打开快照预览标签页;文件路径点击定位。
|
|
25
|
-
- **范围选择器**:最新一轮 / 第 N 轮 / 全部轮次;轮次统计胶囊(用时、工具调用、命令、修改文件、失败数),可整体开关,时间支持「时间点 / 本轮计时」两种显示。
|
|
26
|
-
- **时间轴**:点击用时胶囊打开时间轴,按任意时间点回看当时的进展/产物/引用;支持「回到最新」、在时间轴保持打开时切换轮次。
|
|
27
|
-
- **快速导航联动**:可强制显示内置轮次导航轨(含窄容器下),轨道刻度带轮次号提示,点击刻度联动概览切换到对应轮次。
|
|
28
|
-
- **设置页**:DSH 设置中的独立分区 + 插件行内配置,全部选项即时生效;内置「问题反馈」入口直达 GitHub Issues;显示当前版本并自动检查 GitHub 最新 Release,有新版时出现「新版本」徽标,点击直达 Releases。
|
|
11
|
+
- **进展**:目标与任务计划进度;本轮关键步骤(可展开全部、等待确认高亮、里程碑可置顶);团队成员状态;双击待办生成重跑提示词。
|
|
12
|
+
- **产物**:生成/交付文件列表、按轮次的变更审阅入口、系统定位与「打开方式」。
|
|
13
|
+
- **引用**:上下文注入、OpenViking 记忆(侧边栏内预览)、技能、文件与会话引用;类型筛选、隐藏常见项、多种排序。
|
|
14
|
+
- **统计与时间轴**:轮次统计胶囊(用时/调用/命令/改动文件/失败,失败可点击查看详情);打开时间轴拖到任意时间点,回看当时的进展、产物与引用。
|
|
15
|
+
- **轮次导航**:范围选择器(最新 / 第 N 轮 / 全部),与内置轮次导航轨双向联动。
|
|
16
|
+
- **设置**:DSH 设置独立分区 + 插件行内配置,选项即时生效;问题反馈入口与新版本徽标。
|
|
29
17
|
|
|
30
18
|
## 安装
|
|
31
19
|
|
|
@@ -39,10 +27,32 @@ dsh-conversation-overview
|
|
|
39
27
|
|
|
40
28
|
方式二:GUI「插件管理」中选择安装 bundle,输入上面的 npm 包名(或 `dsh-conversation-overview@latest`)。
|
|
41
29
|
|
|
30
|
+
方式三:已全局安装 DSH(终端可用 `dsh` 命令)时,用 CLI 安装进指定 profile(`web` 为 profile 名,按需替换;该命令等价于在 profile 目录执行 pnpm):
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
dsh plugin --profile web add dsh-conversation-overview
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
CLI 安装后重启 `dsh` 生效(方式一/二安装后刷新浏览器页面即可)。
|
|
37
|
+
|
|
42
38
|
安装后在「设置 → 会话概览」或插件行内配置中调整选项;对话页刷新即可看到「概览」标签页与右侧边栏入口。
|
|
43
39
|
|
|
44
40
|
> 注意:若此前安装过开发版 `@local/dsh-conversation-overview`,请先移除它再安装本包——两者使用相同的插件行 id(`conversation-overview`)与插槽 key,不应同时启用。
|
|
45
41
|
|
|
42
|
+
**插件更新**:
|
|
43
|
+
|
|
44
|
+
- CLI(已全局安装 DSH):
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
dsh plugin --profile web update dsh-conversation-overview
|
|
48
|
+
# 或指定最新版重装:dsh plugin --profile web add dsh-conversation-overview@latest
|
|
49
|
+
# 卸载:dsh plugin --profile web remove dsh-conversation-overview
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
更新后重启 `dsh` 生效。
|
|
53
|
+
|
|
54
|
+
- GUI / 会话内:在 DSH 会话中让 Agent 依次执行插件管理器的 `remove_bundle`(target: `dsh-conversation-overview`)→ `install_bundle`(target: `dsh-conversation-overview@latest`),或在 GUI「插件管理」中移除后重新安装最新版。更新后刷新浏览器页面;若新版本增加了配置字段或宿主端代码有改动,需重启一次 DSH。
|
|
55
|
+
|
|
46
56
|
## 配置项
|
|
47
57
|
|
|
48
58
|
| 字段 | 默认 | 说明 |
|
|
@@ -64,12 +74,6 @@ dsh-conversation-overview
|
|
|
64
74
|
| `vikingAccount` | `""` | OpenViking 账户(预览记忆必填) |
|
|
65
75
|
| `vikingUser` | `""` | OpenViking 用户(预览记忆必填) |
|
|
66
76
|
|
|
67
|
-
## 版本更新
|
|
68
|
-
|
|
69
|
-
**升级已安装的插件**:在 DSH「插件管理」中先移除 `dsh-conversation-overview`,再安装最新版(或在会话中让 Agent 依次执行 `remove_bundle` → `install_bundle dsh-conversation-overview@latest`),完成后刷新浏览器页面;若新版本增加了配置字段或宿主端代码有改动,需重启一次 DSH。
|
|
70
|
-
|
|
71
|
-
**维护者发布**:将开发目录的改动同步到本目录并做发布转换(包名 id、OpenViking 账户/用户默认值置空)→ 跑离线测试套件与 `npm pack --dry-run` 核对文件清单 → `npm version patch|minor|major`(自动生成 git 提交与标签)→ `npm publish --registry https://registry.npmjs.org/`(本机默认 registry 是镜像,必须显式指定官方源)→ `git push origin main --tags`。
|
|
72
|
-
|
|
73
77
|
## 开发与测试
|
|
74
78
|
|
|
75
79
|
包内无构建步骤:`index.js`(Host 侧,schemastery Config + 资源定位)与 `client.js`(浏览器侧,`window.__ModuleLoader__` 工厂格式)均为源文件直发。
|
package/client.js
CHANGED
|
@@ -313,6 +313,10 @@ window.__ModuleLoader__.load({
|
|
|
313
313
|
"stats.files.title": "修改文件数",
|
|
314
314
|
"stats.errors": "失败 {n}",
|
|
315
315
|
"stats.errors.title": "失败的工具调用次数",
|
|
316
|
+
"stats.errors.popTitle": "点击查看失败详情",
|
|
317
|
+
"stats.errors.list": "失败详情({n})",
|
|
318
|
+
"stats.errors.truncated": "仅列出步骤窗口内的失败",
|
|
319
|
+
"stats.errors.close": "关闭",
|
|
316
320
|
"reference.types": "类型",
|
|
317
321
|
"reference.types.title": "按类型筛选",
|
|
318
322
|
"reference.types.all": "全部类型",
|
|
@@ -490,6 +494,10 @@ window.__ModuleLoader__.load({
|
|
|
490
494
|
"stats.files.title": "Files changed",
|
|
491
495
|
"stats.errors": "{n} failed",
|
|
492
496
|
"stats.errors.title": "Failed tool calls",
|
|
497
|
+
"stats.errors.popTitle": "Click for failure details",
|
|
498
|
+
"stats.errors.list": "Failure details ({n})",
|
|
499
|
+
"stats.errors.truncated": "Only failures within the step window are listed",
|
|
500
|
+
"stats.errors.close": "Close",
|
|
493
501
|
"reference.types": "Types",
|
|
494
502
|
"reference.types.title": "Filter by type",
|
|
495
503
|
"reference.types.all": "All types",
|
|
@@ -1933,11 +1941,14 @@ window.__ModuleLoader__.load({
|
|
|
1933
1941
|
touch(folder);
|
|
1934
1942
|
}
|
|
1935
1943
|
|
|
1936
|
-
function markStepDone(folder, callId, time, failed) {
|
|
1944
|
+
function markStepDone(folder, callId, time, failed, errText) {
|
|
1937
1945
|
const step = folder.stepByCall.get(callId);
|
|
1938
1946
|
if (step === undefined) return;
|
|
1939
1947
|
step.done = true;
|
|
1940
|
-
if (failed === true)
|
|
1948
|
+
if (failed === true) {
|
|
1949
|
+
step.error = true;
|
|
1950
|
+
if (typeof errText === "string" && errText.trim() !== "") step.err = errText.trim().slice(0, 400);
|
|
1951
|
+
}
|
|
1941
1952
|
if (typeof time === "number") step.endTime = time;
|
|
1942
1953
|
touch(folder);
|
|
1943
1954
|
}
|
|
@@ -2053,7 +2064,7 @@ window.__ModuleLoader__.load({
|
|
|
2053
2064
|
if (approvalStep !== undefined && outcome !== "" && typeof approvalStep.detail === "string" && !approvalStep.detail.includes(outcome)) {
|
|
2054
2065
|
approvalStep.detail = approvalStep.detail === "" ? outcome : `${approvalStep.detail} · ${outcome}`;
|
|
2055
2066
|
}
|
|
2056
|
-
markStepDone(folder, `approval-${data.id}`, event.time, /denied|reject/i.test(outcome));
|
|
2067
|
+
markStepDone(folder, `approval-${data.id}`, event.time, /denied|reject/i.test(outcome), outcome);
|
|
2057
2068
|
return;
|
|
2058
2069
|
}
|
|
2059
2070
|
case "workspace/changes": {
|
|
@@ -2176,7 +2187,7 @@ window.__ModuleLoader__.load({
|
|
|
2176
2187
|
const source = message.source;
|
|
2177
2188
|
const callId = isRecord(source) && typeof source.callId === "string" ? source.callId : undefined;
|
|
2178
2189
|
if (callId === undefined) return;
|
|
2179
|
-
markStepDone(folder, callId, event.time, message.isError === true);
|
|
2190
|
+
markStepDone(folder, callId, event.time, message.isError === true, message.isError === true ? textOf(message.content) : undefined);
|
|
2180
2191
|
if (message.isError === true) {
|
|
2181
2192
|
folder.stats.errors += 1;
|
|
2182
2193
|
const errorBucket = folder.byTurn.get(folder.currentTurn);
|
|
@@ -4627,7 +4638,34 @@ function FileTypeIcon(props) {
|
|
|
4627
4638
|
}
|
|
4628
4639
|
|
|
4629
4640
|
/** Left-hand stat pills on the scope row: duration, tool calls, commands, files, failures. */
|
|
4630
|
-
function StatsBar({ stats, t, canTimeline, timelineOpen, scrubbing, onToggleTimeline, prevJump, onPrevTurn }) {
|
|
4641
|
+
function StatsBar({ stats, t, canTimeline, timelineOpen, scrubbing, onToggleTimeline, prevJump, onPrevTurn, failedSteps }) {
|
|
4642
|
+
/* failure details popover: hooks must run before any early return */
|
|
4643
|
+
const failed = Array.isArray(failedSteps) ? failedSteps.filter((step) => isRecord(step)) : [];
|
|
4644
|
+
/* fixed-position popover: the toolbar wrappers clip absolutely positioned
|
|
4645
|
+
children (overflow hidden/auto), so anchor to the viewport instead */
|
|
4646
|
+
const [errPop, setErrPop] = React.useState(null);
|
|
4647
|
+
const errOpen = isRecord(errPop);
|
|
4648
|
+
const errRef = React.useRef(null);
|
|
4649
|
+
React.useEffect(() => {
|
|
4650
|
+
if (!errOpen) return undefined;
|
|
4651
|
+
const close = () => setErrPop(null);
|
|
4652
|
+
const onDown = (event) => {
|
|
4653
|
+
if (errRef.current && !errRef.current.contains(event.target)) close();
|
|
4654
|
+
};
|
|
4655
|
+
const onKey = (event) => {
|
|
4656
|
+
if (event.key === "Escape") close();
|
|
4657
|
+
};
|
|
4658
|
+
document.addEventListener("mousedown", onDown);
|
|
4659
|
+
document.addEventListener("keydown", onKey);
|
|
4660
|
+
window.addEventListener("scroll", close, true);
|
|
4661
|
+
window.addEventListener("resize", close);
|
|
4662
|
+
return () => {
|
|
4663
|
+
document.removeEventListener("mousedown", onDown);
|
|
4664
|
+
document.removeEventListener("keydown", onKey);
|
|
4665
|
+
window.removeEventListener("scroll", close, true);
|
|
4666
|
+
window.removeEventListener("resize", close);
|
|
4667
|
+
};
|
|
4668
|
+
}, [errOpen]);
|
|
4631
4669
|
if (!isRecord(stats)) return null;
|
|
4632
4670
|
const duration = typeof stats.durationMs === "number" ? stats.durationMs : 0;
|
|
4633
4671
|
const toolCalls = typeof stats.toolCalls === "number" ? stats.toolCalls : 0;
|
|
@@ -4671,7 +4709,71 @@ function FileTypeIcon(props) {
|
|
|
4671
4709
|
pill("tools", t("stats.tools", { n: toolCalls }), t("stats.tools.title")),
|
|
4672
4710
|
commands > 0 ? pill("commands", t("stats.commands", { n: commands }), t("stats.commands.title")) : null,
|
|
4673
4711
|
files > 0 ? pill("files", t("stats.files", { n: files }), t("stats.files.title")) : null,
|
|
4674
|
-
errors > 0
|
|
4712
|
+
errors > 0
|
|
4713
|
+
? h(
|
|
4714
|
+
"span",
|
|
4715
|
+
{ className: "dsov-statWrap", key: "errors", ref: errRef },
|
|
4716
|
+
h(
|
|
4717
|
+
"button",
|
|
4718
|
+
{
|
|
4719
|
+
type: "button",
|
|
4720
|
+
className: "dsov-stat dsov-statBtn",
|
|
4721
|
+
"data-tone": "err",
|
|
4722
|
+
"data-active": errOpen ? "true" : undefined,
|
|
4723
|
+
disabled: failed.length === 0,
|
|
4724
|
+
title: failed.length > 0 ? t("stats.errors.popTitle") : t("stats.errors.title"),
|
|
4725
|
+
onClick:
|
|
4726
|
+
failed.length > 0
|
|
4727
|
+
? (event) => {
|
|
4728
|
+
if (errOpen) {
|
|
4729
|
+
setErrPop(null);
|
|
4730
|
+
return;
|
|
4731
|
+
}
|
|
4732
|
+
const rect = event.currentTarget.getBoundingClientRect();
|
|
4733
|
+
setErrPop({
|
|
4734
|
+
top: Math.min(rect.bottom + 5, Math.max(8, window.innerHeight - 292)),
|
|
4735
|
+
right: Math.max(8, window.innerWidth - rect.right),
|
|
4736
|
+
});
|
|
4737
|
+
}
|
|
4738
|
+
: undefined,
|
|
4739
|
+
},
|
|
4740
|
+
t("stats.errors", { n: errors })
|
|
4741
|
+
),
|
|
4742
|
+
errOpen && failed.length > 0
|
|
4743
|
+
? h(
|
|
4744
|
+
"div",
|
|
4745
|
+
{ className: "dsov-errPop", style: { top: `${errPop.top}px`, right: `${errPop.right}px` } },
|
|
4746
|
+
h(
|
|
4747
|
+
"div",
|
|
4748
|
+
{ className: "dsov-errPopHead" },
|
|
4749
|
+
h("span", null, t("stats.errors.list", { n: failed.length }), errors > failed.length ? h("span", { className: "dsov-errPopHint" }, t("stats.errors.truncated")) : null),
|
|
4750
|
+
h("button", { type: "button", className: "dsov-errPopClose", title: t("stats.errors.close"), onClick: () => setErrPop(null) }, "\u00d7")
|
|
4751
|
+
),
|
|
4752
|
+
...failed
|
|
4753
|
+
.slice()
|
|
4754
|
+
.reverse()
|
|
4755
|
+
.map((step, index) =>
|
|
4756
|
+
h(
|
|
4757
|
+
"div",
|
|
4758
|
+
{ className: "dsov-errPopRow", key: typeof step.callId === "string" && step.callId !== "" ? step.callId : `err-${index}`, title: typeof step.full === "string" && step.full !== "" ? step.full : step.detail },
|
|
4759
|
+
h(
|
|
4760
|
+
"div",
|
|
4761
|
+
{ className: "dsov-errPopTop" },
|
|
4762
|
+
h(
|
|
4763
|
+
"span",
|
|
4764
|
+
{ className: "dsov-errPopName" },
|
|
4765
|
+
step.name === "compact-checkpoint" ? t("step.compact") : step.name === "approval" ? t("step.approval") : typeof step.name === "string" ? step.name : ""
|
|
4766
|
+
),
|
|
4767
|
+
h("span", { className: "dsov-errPopTime" }, typeof step.timeText === "string" ? step.timeText : "")
|
|
4768
|
+
),
|
|
4769
|
+
step.detail ? h("div", { className: "dsov-errPopDetail" }, step.detail) : null,
|
|
4770
|
+
step.err ? h("div", { className: "dsov-errPopMsg" }, step.err) : null
|
|
4771
|
+
)
|
|
4772
|
+
)
|
|
4773
|
+
)
|
|
4774
|
+
: null
|
|
4775
|
+
)
|
|
4776
|
+
: null
|
|
4675
4777
|
);
|
|
4676
4778
|
}
|
|
4677
4779
|
|
|
@@ -4734,6 +4836,15 @@ function FileTypeIcon(props) {
|
|
|
4734
4836
|
};
|
|
4735
4837
|
}, [asOf, summary]);
|
|
4736
4838
|
const canTimeline = typeof summary.turnStart === "number" && typeof summary.turnEnd === "number" && summary.turnEnd > summary.turnStart;
|
|
4839
|
+
/* the errors pill drills into these: failed steps of the scope, honoring the scrub point */
|
|
4840
|
+
const failedSteps = React.useMemo(() => {
|
|
4841
|
+
const list = Array.isArray(summary.stepsAll) ? summary.stepsAll : [];
|
|
4842
|
+
const cut = asOf === null ? Number.POSITIVE_INFINITY : asOf;
|
|
4843
|
+
return list
|
|
4844
|
+
.filter((step) => isRecord(step) && step.error === true && (step.endTime || step.time || 0) <= cut)
|
|
4845
|
+
.slice(-50)
|
|
4846
|
+
.map((step) => ({ ...step, timeText: formatTime(step.time, cfg.timeMode, summary.turnStart) }));
|
|
4847
|
+
}, [summary, asOf, cfg]);
|
|
4737
4848
|
/* at the 0s point nothing has happened yet in this turn: offer a jump to
|
|
4738
4849
|
the previous turn, rendered inside the (otherwise empty) stats bar */
|
|
4739
4850
|
const turnNums = Array.isArray(summary.turns) ? summary.turns.filter((value) => Number.isFinite(value)) : [];
|
|
@@ -4752,6 +4863,7 @@ function FileTypeIcon(props) {
|
|
|
4752
4863
|
canTimeline,
|
|
4753
4864
|
timelineOpen,
|
|
4754
4865
|
scrubbing: asOf !== null,
|
|
4866
|
+
failedSteps,
|
|
4755
4867
|
prevJump: asOf !== null && asOf <= summary.turnStart ? prevTurn : null,
|
|
4756
4868
|
onPrevTurn: () => {
|
|
4757
4869
|
setSelection(`turn:${prevTurn}`);
|
|
@@ -5550,7 +5662,7 @@ function FileTypeIcon(props) {
|
|
|
5550
5662
|
.dsov-headAction{flex:none;display:inline-flex;align-items:center;gap:5px;height:26px;padding:0 9px;border-radius:8px;border:.5px solid var(--dsw-alias-border-l2);background:transparent;color:var(--dsw-alias-label-secondary);font:inherit;font-size:12px;cursor:pointer;white-space:nowrap}
|
|
5551
5663
|
.dsov-headAction:hover{color:var(--dsw-alias-brand-primary);border-color:color-mix(in srgb,var(--dsw-alias-brand-primary) 45%,transparent);background:color-mix(in srgb,var(--dsw-alias-brand-primary) 8%,transparent)}
|
|
5552
5664
|
.dsov-empty{font-size:12.5px;line-height:1.6;color:var(--dsw-alias-label-secondary);padding:4px 2px}
|
|
5553
|
-
.dsov-secBody{max-height:320px;overflow-y:auto;overflow-x:hidden;
|
|
5665
|
+
.dsov-secBody{max-height:320px;overflow-y:auto;overflow-x:hidden;margin:0 -12px 0 -8px;padding:0 12px 0 8px}
|
|
5554
5666
|
.dsov-section[data-full=true] .dsov-secBody{max-height:none;overflow:visible;margin:0;padding:0}
|
|
5555
5667
|
.dsov-loading{font-size:12px;color:var(--dsw-alias-label-secondary)}
|
|
5556
5668
|
.dsov-goal{display:flex;align-items:flex-start;gap:8px;font-size:13px;color:var(--dsw-alias-label-primary);padding:2px}
|
|
@@ -5728,6 +5840,20 @@ html[data-dsov-quicknav="off"] nav:has(button[data-index][aria-label]),html[data
|
|
|
5728
5840
|
.dsov-fileMenuSep{height:1px;margin:4px 6px;background:var(--dsw-alias-border-l1)}
|
|
5729
5841
|
.dsov-fileMenuHint{padding:5px 8px;font-size:11.5px;color:var(--dsw-alias-label-secondary)}
|
|
5730
5842
|
.dsov-fileMenuErr{padding:5px 8px;font-size:11px;color:var(--dsw-alias-state-error-primary,#ff453a)}
|
|
5843
|
+
.dsov-statWrap{position:relative;display:inline-flex}
|
|
5844
|
+
.dsov-statBtn[disabled]{cursor:default}
|
|
5845
|
+
.dsov-errPop{position:fixed;z-index:80;width:min(360px,78vw);max-height:280px;overflow-y:auto;padding:4px;border-radius:8px;background:var(--dsw-alias-bg-layer-2);border:.5px solid var(--dsw-alias-border-l1);box-shadow:0 8px 22px rgba(0,0,0,.20)}
|
|
5846
|
+
.dsov-errPopHead{display:flex;justify-content:space-between;align-items:center;gap:8px;padding:2px 4px 4px;font-size:11px;color:var(--dsw-alias-label-secondary)}
|
|
5847
|
+
.dsov-errPopHint{margin-left:6px;font-size:10px;color:var(--dsw-alias-label-tertiary)}
|
|
5848
|
+
.dsov-errPopClose{border:0;background:none;cursor:pointer;color:var(--dsw-alias-label-secondary);font-size:13px;line-height:1;padding:2px 5px;border-radius:4px}
|
|
5849
|
+
.dsov-errPopClose:hover{background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-primary)}
|
|
5850
|
+
.dsov-errPopRow{padding:4px 6px;border-radius:6px;font-size:11px;line-height:1.5}
|
|
5851
|
+
.dsov-errPopRow:hover{background:var(--dsw-alias-bg-layer-3)}
|
|
5852
|
+
.dsov-errPopTop{display:flex;justify-content:space-between;align-items:baseline;gap:8px}
|
|
5853
|
+
.dsov-errPopName{font-weight:600;color:var(--dsw-alias-label-primary)}
|
|
5854
|
+
.dsov-errPopTime{color:var(--dsw-alias-label-tertiary);font-size:10px;white-space:nowrap}
|
|
5855
|
+
.dsov-errPopDetail{color:var(--dsw-alias-label-secondary);word-break:break-all;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
|
|
5856
|
+
.dsov-errPopMsg{margin-top:2px;color:var(--dsw-alias-state-error-primary,#ff453a);white-space:pre-wrap;word-break:break-all;font-size:10.5px;max-height:76px;overflow-y:auto}
|
|
5731
5857
|
.dsov-renderErr{margin:8px 12px 0;padding:6px 8px;border-radius:6px;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-state-error-primary,#ff453a);font-size:11px;line-height:1.5;white-space:pre-wrap;word-break:break-all;text-align:left;max-height:140px;overflow:auto}
|
|
5732
5858
|
.dsov-turnSelect{flex:none;max-width:150px;height:24px;padding:0 22px 0 9px;border:.5px solid var(--dsw-alias-border-l2);border-radius:12px;background:transparent;color:var(--dsw-alias-label-secondary);font:inherit;font-size:11px;cursor:pointer;appearance:none;-webkit-appearance:none;background-image:linear-gradient(45deg,transparent 50%,currentColor 50%),linear-gradient(135deg,currentColor 50%,transparent 50%);background-position:calc(100% - 12px) 10px,calc(100% - 8px) 10px;background-size:4px 4px,4px 4px;background-repeat:no-repeat}
|
|
5733
5859
|
.dsov-turnSelect:hover{color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-border-l3,var(--dsw-alias-border-l2))}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-conversation-overview",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "DeepSeek Harness (DSH) plugin: an Overview tab beside Chat/Trajectory plus a right-sidebar page summarizing session progress (goal, todos, key steps), artifacts, and references, with per-turn scoping, OpenViking memory preview, and quick-nav linkage.",
|
|
6
6
|
"keywords": [
|