@ch4acko3/dsh-turn-fold 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -6
- package/README.zh-CN.md +28 -3
- package/inline-source.cjs +381 -54
- package/locales/en.json +9 -3
- package/locales/zh.json +9 -3
- package/package.json +12 -3
- package/patch.cjs +2 -2
package/README.md
CHANGED
|
@@ -5,6 +5,8 @@ English | [简体中文](README.zh-CN.md)
|
|
|
5
5
|
A [dsh-harmony](https://github.com/memorax-ai/dsh-harmony) provider that adds
|
|
6
6
|
Codex-Desktop-style turn folding to the DSH WebUI conversation.
|
|
7
7
|
|
|
8
|
+
https://github.com/user-attachments/assets/3c9dfdcf-a454-4750-9edf-76771ed5a9a6
|
|
9
|
+
|
|
8
10
|
During a turn, the summary bar remains visible while native thinking, notes,
|
|
9
11
|
commands, and tool calls keep streaming. Consecutive reasoning and tool activity
|
|
10
12
|
share one compact group from the second item onward. When a turn settles, known
|
|
@@ -29,7 +31,7 @@ short open/close transition that unmounts the activity after it closes.
|
|
|
29
31
|
|
|
30
32
|
## How it works
|
|
31
33
|
|
|
32
|
-
|
|
34
|
+
Three pinned Source Patches run in memory against the compiled browser bundle of
|
|
33
35
|
`@deepseek-ai/dsh-client-ui-conversation` (`lib/client.js`); installed DSH files
|
|
34
36
|
are never modified.
|
|
35
37
|
|
|
@@ -37,12 +39,13 @@ are never modified.
|
|
|
37
39
|
| --- | --- | --- |
|
|
38
40
|
| `inject-turn-fold-runtime` | `FunctionDeclaration[name.name="ChatView"], VariableStatement:has(VariableDeclaration[name.name="ChatView"])` | Injects the fold renderer + disclosure UI into either native or decorated `ChatView` |
|
|
39
41
|
| `rewrite-node-render-loop` | `CallExpression[expression.name.name="map"][expression.expression.name="order"]` | Replaces the `order.map(...)` node loop with the per-turn renderer |
|
|
42
|
+
| `install-turn-fold-services` | `VariableStatement:has(VariableDeclaration[name.name="t"][initializer.expression.name.name="bind"])` | Registers the bundled English and Chinese dictionaries through DSH's native locale service and binds the native settings scope |
|
|
40
43
|
|
|
41
44
|
## Install
|
|
42
45
|
|
|
43
46
|
```sh
|
|
44
47
|
dsh plugin --profile web add github:CH4ACKO3/dsh-turn-fold
|
|
45
|
-
dsh harmony status --profile web #
|
|
48
|
+
dsh harmony status --profile web # all three patches must be `bound`
|
|
46
49
|
```
|
|
47
50
|
|
|
48
51
|
## Test
|
|
@@ -51,9 +54,31 @@ dsh harmony status --profile web # both patches must be `bound`
|
|
|
51
54
|
node test/run.cjs
|
|
52
55
|
```
|
|
53
56
|
|
|
54
|
-
`npm install` installs
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
57
|
+
`npm install` installs the dependencies required by the test harness. The test
|
|
58
|
+
suite applies all three patches in memory, parses the final browser bundle, and
|
|
59
|
+
covers completed, split-activity, post-closing, partial-history, failed,
|
|
60
|
+
interrupted, open, accessibility, localization, settings, and state-retention
|
|
58
61
|
behavior. A missing target or selector mismatch fails the test; it is never
|
|
59
62
|
reported as a skipped pass.
|
|
63
|
+
|
|
64
|
+
## CI and release
|
|
65
|
+
|
|
66
|
+
GitHub Actions runs the test suite and a package dry run for every pull request
|
|
67
|
+
and every push to `main`. Version tags publish to npm through Trusted Publishing
|
|
68
|
+
(OIDC), without a long-lived npm token.
|
|
69
|
+
|
|
70
|
+
Configure the npm trusted publisher once:
|
|
71
|
+
|
|
72
|
+
```sh
|
|
73
|
+
npx npm@^11.15.0 trust github @ch4acko3/dsh-turn-fold \
|
|
74
|
+
--repo ch4acko3/dsh-turn-fold \
|
|
75
|
+
--file release.yml \
|
|
76
|
+
--allow-publish
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Then create and push a version tag whose value matches `package.json`:
|
|
80
|
+
|
|
81
|
+
```sh
|
|
82
|
+
npm version patch
|
|
83
|
+
git push --follow-tags
|
|
84
|
+
```
|
package/README.zh-CN.md
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
一个基于 [dsh-harmony](https://github.com/memorax-ai/dsh-harmony) 的 Provider,为 DSH WebUI 对话添加 Codex Desktop 风格的回合折叠。
|
|
6
6
|
|
|
7
|
+
https://github.com/user-attachments/assets/3c9dfdcf-a454-4750-9edf-76771ed5a9a6
|
|
8
|
+
|
|
7
9
|
回合进行期间,摘要栏保持可见,原生思考、说明、命令和工具调用继续流式输出。从第二项开始,连续的推理和工具活动会合并为一个紧凑分组。回合结束后,包括上下文注入在内的已知 Agent 活动会收进最终答复前方的折叠栏。摘要指标可以配置,默认显示耗时、工具调用次数以及输入/输出 token;只有当已加载的回合包含足够数据、无需猜测即可计算时才会展示对应指标。
|
|
8
10
|
|
|
9
11
|
最终答复通过 `turn-tail.closing.finalNode` 定位,不依赖 `finish_reason` 或 DOM 位置。正常完成、已停止和已中断的回合都会折叠,后两者显示不同的状态标签。当 DSH 将结束分支标记为不可用、结束答复之后仍有节点,或者用户的键盘焦点或文本选择位于活动内容中时,回合会保持展开。失败、达到最大 token、缺少结束节点以及仍在进行的回合也会保持展开,避免隐藏错误或未完成的工作。
|
|
@@ -12,18 +14,19 @@
|
|
|
12
14
|
|
|
13
15
|
## 工作原理
|
|
14
16
|
|
|
15
|
-
|
|
17
|
+
三个固定目标的 Source Patch 会在内存中修改 `@deepseek-ai/dsh-client-ui-conversation` 的编译后浏览器包(`lib/client.js`),不会修改已安装的 DSH 文件。
|
|
16
18
|
|
|
17
19
|
| Patch | 选择器(预期命中 1 次) | 作用 |
|
|
18
20
|
| --- | --- | --- |
|
|
19
21
|
| `inject-turn-fold-runtime` | `FunctionDeclaration[name.name="ChatView"], VariableStatement:has(VariableDeclaration[name.name="ChatView"])` | 向原生或已装饰的 `ChatView` 注入折叠渲染器和折叠 UI |
|
|
20
22
|
| `rewrite-node-render-loop` | `CallExpression[expression.name.name="map"][expression.expression.name="order"]` | 将 `order.map(...)` 节点循环替换为按回合渲染器 |
|
|
23
|
+
| `install-turn-fold-services` | `VariableStatement:has(VariableDeclaration[name.name="t"][initializer.expression.name.name="bind"])` | 通过 DSH 原生语言服务注册内置的中英文词典,并绑定原生设置作用域 |
|
|
21
24
|
|
|
22
25
|
## 安装
|
|
23
26
|
|
|
24
27
|
```sh
|
|
25
28
|
dsh plugin --profile web add github:CH4ACKO3/dsh-turn-fold
|
|
26
|
-
dsh harmony status --profile web #
|
|
29
|
+
dsh harmony status --profile web # 三个 Patch 都必须为 `bound`
|
|
27
30
|
```
|
|
28
31
|
|
|
29
32
|
## 测试
|
|
@@ -32,4 +35,26 @@ dsh harmony status --profile web # 两个 Patch 都必须为 `bound`
|
|
|
32
35
|
node test/run.cjs
|
|
33
36
|
```
|
|
34
37
|
|
|
35
|
-
`npm install`
|
|
38
|
+
`npm install` 会安装测试工具所需的依赖。测试套件会在内存中应用三个 Patch、解析最终浏览器包,并覆盖已完成回合、分段活动、结束后活动、部分历史、失败、中断、进行中、无障碍、本地化、设置和状态保留等行为。目标缺失或选择器不匹配会使测试失败,不会被报告为跳过后通过。
|
|
39
|
+
|
|
40
|
+
## CI 与发布
|
|
41
|
+
|
|
42
|
+
GitHub Actions 会在每个 Pull Request 和每次推送到 `main` 时运行测试套件及
|
|
43
|
+
包内容预检。版本标签通过 Trusted Publishing(OIDC)发布到 npm,无需保存
|
|
44
|
+
长期 npm Token。
|
|
45
|
+
|
|
46
|
+
首次使用时配置一次 npm 可信发布者:
|
|
47
|
+
|
|
48
|
+
```sh
|
|
49
|
+
npx npm@^11.15.0 trust github @ch4acko3/dsh-turn-fold \
|
|
50
|
+
--repo ch4acko3/dsh-turn-fold \
|
|
51
|
+
--file release.yml \
|
|
52
|
+
--allow-publish
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
之后创建与 `package.json` 版本一致的标签并推送:
|
|
56
|
+
|
|
57
|
+
```sh
|
|
58
|
+
npm version patch
|
|
59
|
+
git push --follow-tags
|
|
60
|
+
```
|
package/inline-source.cjs
CHANGED
|
@@ -17,7 +17,7 @@ var __ch4acko3DshTurnFoldSettingsScope = null;
|
|
|
17
17
|
var __ch4acko3DshTurnFoldSummaryFields = __ch4acko3DshTurnFoldDefaultFields.slice();
|
|
18
18
|
var __ch4acko3DshTurnFoldSettingsListeners = new Set();
|
|
19
19
|
var __ch4acko3DshTurnFoldCss = [
|
|
20
|
-
".__ch4acko3-dsh-turn-fold{min-width:0;margin:1px 0 2px;animation:__ch4acko3-dsh-turn-fold-enter .18s cubic-bezier(.33,1,.68,1)}",
|
|
20
|
+
".__ch4acko3-dsh-turn-fold{width:100%;min-width:0;max-width:100%;box-sizing:border-box;margin:1px 0 2px;animation:__ch4acko3-dsh-turn-fold-enter .18s cubic-bezier(.33,1,.68,1)}",
|
|
21
21
|
".__ch4acko3-dsh-turn-fold__header{display:block;width:100%;min-height:28px;box-sizing:border-box;margin:0;padding:3px 4px;color:var(--dsw-alias-label-secondary);text-align:left;font:var(--dsw-font-xs-13)}",
|
|
22
22
|
"button.__ch4acko3-dsh-turn-fold__header{appearance:none;-webkit-tap-highlight-color:transparent;border:0;border-radius:0;background:transparent;cursor:pointer}",
|
|
23
23
|
"button.__ch4acko3-dsh-turn-fold__header:focus-visible{outline:2px solid var(--dsw-static-deepseek-500);outline-offset:1px}",
|
|
@@ -29,43 +29,76 @@ var __ch4acko3DshTurnFoldCss = [
|
|
|
29
29
|
".__ch4acko3-dsh-turn-fold__rule{width:100%;height:1px;background:var(--dsw-alias-border-l3)}",
|
|
30
30
|
".__ch4acko3-dsh-turn-fold__chevron{display:inline-block;margin-left:5px;color:var(--dsw-alias-label-caption);vertical-align:-2px;transform:rotate(-90deg);transition:transform .16s cubic-bezier(.33,1,.68,1)}",
|
|
31
31
|
".__ch4acko3-dsh-turn-fold--open .__ch4acko3-dsh-turn-fold__chevron{transform:rotate(0deg)}",
|
|
32
|
-
".__ch4acko3-dsh-turn-fold__clip{display:grid;grid-template-rows:0fr;opacity:0;transition:grid-template-rows .18s cubic-bezier(.33,1,.68,1),opacity .14s ease}",
|
|
32
|
+
".__ch4acko3-dsh-turn-fold__clip{display:grid;grid-template-columns:minmax(0,1fr);grid-template-rows:0fr;min-width:0;max-width:100%;opacity:0;transition:grid-template-rows .18s cubic-bezier(.33,1,.68,1),opacity .14s ease}",
|
|
33
33
|
".__ch4acko3-dsh-turn-fold--open .__ch4acko3-dsh-turn-fold__clip{grid-template-rows:1fr;opacity:1}",
|
|
34
|
-
".__ch4acko3-dsh-turn-fold__bodyWrap{min-height:0;overflow:hidden}",
|
|
35
|
-
".__ch4acko3-dsh-turn-
|
|
34
|
+
".__ch4acko3-dsh-turn-fold__bodyWrap{min-width:0;max-width:100%;min-height:0;overflow:hidden}",
|
|
35
|
+
".__ch4acko3-dsh-turn-fold__bodyWrap--overflow-visible{overflow:visible}",
|
|
36
|
+
".__ch4acko3-dsh-turn-fold__body{display:flex;min-width:0;max-width:100%;flex-direction:column;gap:16px;margin-top:12px}",
|
|
37
|
+
".__ch4acko3-dsh-turn-fold__body>*{min-width:0;max-width:100%}",
|
|
36
38
|
".__ch4acko3-dsh-turn-fold__closing{display:contents}",
|
|
37
39
|
".__ch4acko3-dsh-turn-fold__closing [data-variant=think]{display:none}",
|
|
38
40
|
".__ch4acko3-dsh-turn-fold__activityText{display:contents}",
|
|
39
41
|
".__ch4acko3-dsh-turn-fold__activityText [data-variant=think]{display:none}",
|
|
40
|
-
".__ch4acko3-dsh-turn-fold-activity{min-width:0}",
|
|
42
|
+
".__ch4acko3-dsh-turn-fold-activity{width:100%;min-width:0;max-width:100%}",
|
|
41
43
|
".__ch4acko3-dsh-turn-fold-activity__row{position:relative;overflow:hidden}",
|
|
42
44
|
".__ch4acko3-dsh-turn-fold-activity[data-state=running] .__ch4acko3-dsh-turn-fold-activity__row:after{content:\"\";position:absolute;inset-block:0;left:-300px;width:300px;pointer-events:none;background:linear-gradient(90deg,transparent 0%,color-mix(in srgb,var(--dsw-alias-bg-base) 60%,transparent) 55%,transparent 100%);animation:2.6s ease-out infinite __ch4acko3-dsh-turn-fold-activity-sweep}",
|
|
43
45
|
".__ch4acko3-dsh-turn-fold-activity__leading{flex-shrink:0}",
|
|
44
46
|
".__ch4acko3-dsh-turn-fold-activity__title{font-weight:400}",
|
|
45
47
|
".__ch4acko3-dsh-turn-fold-activity__chevron{color:var(--dsw-alias-label-secondary)}",
|
|
46
|
-
".__ch4acko3-dsh-turn-fold-activity__separator{width:
|
|
48
|
+
".__ch4acko3-dsh-turn-fold-activity__separator{display:inline-block;width:1px;height:10px;margin:0 7px;flex:none;background:var(--dsw-alias-border-l2);vertical-align:-1px}",
|
|
47
49
|
".__ch4acko3-dsh-turn-fold-activity__failure{min-width:0;color:var(--dsw-alias-state-error-primary);font-size:14px;line-height:24px}",
|
|
48
|
-
".__ch4acko3-dsh-turn-fold-activity__clip{display:grid;grid-template-rows:0fr;opacity:0;transition:grid-template-rows .18s cubic-bezier(.16,1,.3,1),opacity .12s ease-out}",
|
|
50
|
+
".__ch4acko3-dsh-turn-fold-activity__clip{display:grid;grid-template-columns:minmax(0,1fr);grid-template-rows:0fr;min-width:0;max-width:100%;opacity:0;transition:grid-template-rows .18s cubic-bezier(.16,1,.3,1),opacity .12s ease-out}",
|
|
49
51
|
".__ch4acko3-dsh-turn-fold-activity--open .__ch4acko3-dsh-turn-fold-activity__clip{grid-template-rows:1fr;opacity:1}",
|
|
50
|
-
".__ch4acko3-dsh-turn-fold-activity__bodyWrap{min-height:0;overflow:hidden}",
|
|
51
|
-
".__ch4acko3-dsh-turn-fold-
|
|
52
|
-
".__ch4acko3-dsh-turn-fold-
|
|
53
|
-
".__ch4acko3-dsh-turn-fold-
|
|
54
|
-
".__ch4acko3-dsh-turn-fold-
|
|
55
|
-
".__ch4acko3-dsh-turn-fold-
|
|
52
|
+
".__ch4acko3-dsh-turn-fold-activity__bodyWrap{min-width:0;max-width:100%;min-height:0;overflow:hidden}",
|
|
53
|
+
".__ch4acko3-dsh-turn-fold-activity__bodyWrap--overflow-visible{overflow:visible}",
|
|
54
|
+
".__ch4acko3-dsh-turn-fold-activity__body{display:flex;min-width:0;max-width:100%;flex-direction:column;gap:8px;margin:4px 0 4px 22px}",
|
|
55
|
+
".__ch4acko3-dsh-turn-fold-activity__body>*{min-width:0;max-width:100%}",
|
|
56
|
+
".__ch4acko3-dsh-turn-fold-settings{list-style:none;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;transition:border-color .16s,background .16s}",
|
|
57
|
+
".__ch4acko3-dsh-turn-fold-settings:hover{border-color:var(--dsw-alias-label-dimmed)}",
|
|
58
|
+
".__ch4acko3-dsh-turn-fold-settings--open{background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-label-dimmed)}",
|
|
59
|
+
".__ch4acko3-dsh-turn-fold-settings__header{position:relative;display:flex;align-items:center;gap:12px;padding:14px 16px}",
|
|
60
|
+
".__ch4acko3-dsh-turn-fold-settings__headerButton{appearance:none;position:absolute;inset:0;z-index:0;width:100%;border:0;border-radius:12px;background:transparent;color:inherit;font:inherit;cursor:pointer}",
|
|
61
|
+
".__ch4acko3-dsh-turn-fold-settings__headerButton:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}",
|
|
62
|
+
".__ch4acko3-dsh-turn-fold-settings__headText{position:relative;z-index:1;display:flex;flex:1;min-width:0;flex-direction:column;gap:4px;pointer-events:none}",
|
|
63
|
+
".__ch4acko3-dsh-turn-fold-settings__titleRow{display:flex;align-items:baseline;gap:8px;min-width:0;flex-wrap:wrap}",
|
|
56
64
|
".__ch4acko3-dsh-turn-fold-settings__title{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4}",
|
|
65
|
+
".__ch4acko3-dsh-turn-fold-settings__pluginName{max-width:100%;overflow:hidden;color:var(--dsw-alias-label-caption);font-size:12px;font-weight:400;line-height:18px;text-decoration:none;text-overflow:ellipsis;white-space:nowrap;opacity:.38;pointer-events:auto;transition:color .16s,opacity .16s}",
|
|
66
|
+
".__ch4acko3-dsh-turn-fold-settings__pluginName:hover{color:var(--dsw-alias-label-secondary);opacity:.72}",
|
|
67
|
+
".__ch4acko3-dsh-turn-fold-settings__pluginName[data-ready=true],.__ch4acko3-dsh-turn-fold-settings__pluginName:focus-visible{color:var(--dsw-alias-state-business-primary);opacity:1}",
|
|
68
|
+
".__ch4acko3-dsh-turn-fold-settings__pluginName:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:2px;border-radius:2px}",
|
|
57
69
|
".__ch4acko3-dsh-turn-fold-settings__description{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5}",
|
|
58
|
-
".__ch4acko3-dsh-turn-fold-settings__chevron{
|
|
59
|
-
".__ch4acko3-dsh-turn-fold-settings--open .__ch4acko3-dsh-turn-fold-settings__chevron{transform:rotate(
|
|
60
|
-
".__ch4acko3-dsh-turn-fold-settings__body{display:
|
|
61
|
-
".__ch4acko3-dsh-turn-fold-
|
|
62
|
-
".__ch4acko3-dsh-turn-fold-
|
|
63
|
-
".__ch4acko3-dsh-turn-fold-
|
|
70
|
+
".__ch4acko3-dsh-turn-fold-settings__chevron{position:relative;z-index:1;color:var(--dsw-alias-label-tertiary);flex:none;pointer-events:none;transition:transform .16s}",
|
|
71
|
+
".__ch4acko3-dsh-turn-fold-settings--open .__ch4acko3-dsh-turn-fold-settings__chevron{transform:rotate(180deg)}",
|
|
72
|
+
".__ch4acko3-dsh-turn-fold-settings__body{display:flex;flex-direction:column;gap:10px;margin:0 16px;padding:12px 0 14px;border-top:1px solid var(--dsw-alias-border-l2)}",
|
|
73
|
+
".__ch4acko3-dsh-turn-fold-settings__metricEditor{display:flex;flex-direction:column;gap:10px}",
|
|
74
|
+
".__ch4acko3-dsh-turn-fold-settings__zone{display:flex;flex-direction:column;gap:6px}",
|
|
75
|
+
".__ch4acko3-dsh-turn-fold-settings__zoneLabel{color:var(--dsw-alias-label-primary);font-size:12px;font-weight:500;line-height:18px}",
|
|
76
|
+
".__ch4acko3-dsh-turn-fold-settings__slot{display:flex;align-items:center;align-content:center;flex-wrap:wrap;gap:7px;min-height:44px;box-sizing:border-box;padding:7px;border:1px dashed var(--dsw-alias-border-l2);border-radius:10px;background:var(--dsw-alias-bg-layer-3);transition:border-color .16s,background .16s}",
|
|
77
|
+
".__ch4acko3-dsh-turn-fold-settings__slot[data-empty=true]{justify-content:center}",
|
|
78
|
+
".__ch4acko3-dsh-turn-fold-settings__slot[data-drop-active=true]{border-color:var(--dsw-alias-brand-primary);background:var(--dsw-alias-bg-base)}",
|
|
79
|
+
".__ch4acko3-dsh-turn-fold-settings__palette{display:flex;align-items:center;align-content:center;flex-wrap:wrap;gap:7px;min-height:44px;box-sizing:border-box;padding:7px;border:1px dashed var(--dsw-alias-border-l2);border-radius:10px;background:var(--dsw-alias-bg-layer-3)}",
|
|
80
|
+
".__ch4acko3-dsh-turn-fold-settings__palette[data-empty=true]{justify-content:center}",
|
|
81
|
+
".__ch4acko3-dsh-turn-fold-settings__palette[data-drop-active=true]{border-color:var(--dsw-alias-brand-primary);background:var(--dsw-alias-bg-base)}",
|
|
82
|
+
".__ch4acko3-dsh-turn-fold-settings__tag{appearance:none;max-width:100%;overflow:hidden;border:1px solid var(--dsw-alias-border-l2);border-radius:999px;background:transparent;padding:4px 10px;color:var(--dsw-alias-label-secondary);font:inherit;font-size:12px;line-height:18px;text-overflow:ellipsis;white-space:nowrap;cursor:grab;user-select:none;touch-action:none;transition:border-color .16s,color .16s,background .16s,opacity .16s}",
|
|
83
|
+
".__ch4acko3-dsh-turn-fold-settings__tag[data-selected=true]{background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-primary)}",
|
|
84
|
+
".__ch4acko3-dsh-turn-fold-settings__tag:hover:not(:disabled){border-color:var(--dsw-alias-label-dimmed);color:var(--dsw-alias-label-primary)}",
|
|
85
|
+
".__ch4acko3-dsh-turn-fold-settings__tag:active:not(:disabled){cursor:grabbing}",
|
|
86
|
+
".__ch4acko3-dsh-turn-fold-settings__tag:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px}",
|
|
87
|
+
".__ch4acko3-dsh-turn-fold-settings__tag:disabled{cursor:default;opacity:.45}",
|
|
88
|
+
".__ch4acko3-dsh-turn-fold-settings__dropSlot{display:flex;align-items:center;justify-content:center;width:7px;height:28px;flex:none;pointer-events:none}",
|
|
89
|
+
".__ch4acko3-dsh-turn-fold-settings__dropSlot:before{content:\"\";width:2px;height:22px;border-radius:2px;background:#3b82f6;box-shadow:0 0 4px #3b82f6,0 0 9px color-mix(in srgb,#3b82f6 65%,transparent)}",
|
|
90
|
+
".__ch4acko3-dsh-turn-fold-settings__dragPreview{position:fixed;z-index:1400;pointer-events:none;filter:drop-shadow(0 8px 14px rgba(0,0,0,.16))}",
|
|
91
|
+
".__ch4acko3-dsh-turn-fold-settings__dragPreview .__ch4acko3-dsh-turn-fold-settings__tag{display:block;box-sizing:border-box;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary)}",
|
|
92
|
+
".__ch4acko3-dsh-turn-fold-settings__empty{margin:0;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px;pointer-events:none}",
|
|
93
|
+
".__ch4acko3-dsh-turn-fold-settings__hint{margin:0;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}",
|
|
94
|
+
".__ch4acko3-dsh-turn-fold-settings__readOnly{margin:0;color:var(--dsw-alias-label-tertiary);font-size:12px}",
|
|
64
95
|
"@keyframes __ch4acko3-dsh-turn-fold-enter{from{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}",
|
|
65
96
|
"@keyframes __ch4acko3-dsh-turn-fold-metric-roll{from{opacity:.15;transform:translateY(65%)}to{opacity:1;transform:translateY(0)}}",
|
|
66
97
|
"@keyframes __ch4acko3-dsh-turn-fold-activity-sweep{0%{left:-300px}90%,to{left:100%}}",
|
|
67
|
-
"@
|
|
68
|
-
"@media(
|
|
98
|
+
"@keyframes __ch4acko3-dsh-turn-fold-settings-drop-in{from{opacity:0;transform:scaleY(.45)}to{opacity:1;transform:scaleY(1)}}",
|
|
99
|
+
"@media(max-width:520px){.__ch4acko3-dsh-turn-fold__label{line-height:18px}}",
|
|
100
|
+
"@media(prefers-reduced-motion:no-preference){.__ch4acko3-dsh-turn-fold-settings__dropSlot{animation:__ch4acko3-dsh-turn-fold-settings-drop-in .13s cubic-bezier(.16,1,.3,1)}}",
|
|
101
|
+
"@media(prefers-reduced-motion:reduce){.__ch4acko3-dsh-turn-fold,.__ch4acko3-dsh-turn-fold__metricValue,.__ch4acko3-dsh-turn-fold-activity[data-state=running] .__ch4acko3-dsh-turn-fold-activity__row:after{animation:none}.__ch4acko3-dsh-turn-fold__chevron,.__ch4acko3-dsh-turn-fold__clip,.__ch4acko3-dsh-turn-fold-activity__clip,.__ch4acko3-dsh-turn-fold-settings,.__ch4acko3-dsh-turn-fold-settings__pluginName,.__ch4acko3-dsh-turn-fold-settings__chevron,.__ch4acko3-dsh-turn-fold-settings__slot,.__ch4acko3-dsh-turn-fold-settings__tag{transition:none}}"
|
|
69
102
|
].join("");
|
|
70
103
|
if (typeof document !== "undefined") {
|
|
71
104
|
var __ch4acko3DshTurnFoldStyle = document.getElementById("ch4acko3-dsh-turn-fold-style");
|
|
@@ -208,10 +241,10 @@ function __ch4acko3DshTurnFoldToolFacts(toolKeys, nodeStore) {
|
|
|
208
241
|
function __ch4acko3DshTurnFoldActivityGroup(props) {
|
|
209
242
|
var foldKey = props.foldKey;
|
|
210
243
|
var toolCount = 0;
|
|
211
|
-
var
|
|
244
|
+
var reasoningCount = 0;
|
|
212
245
|
for (var itemIndex = 0; itemIndex < props.items.length; itemIndex++) {
|
|
213
246
|
if (props.items[itemIndex].kind === "tool") toolCount++;
|
|
214
|
-
else
|
|
247
|
+
else reasoningCount++;
|
|
215
248
|
}
|
|
216
249
|
var initialOpen = __ch4acko3DshTurnFoldOpenKeys.has(foldKey);
|
|
217
250
|
var openState = react.useState(initialOpen);
|
|
@@ -220,6 +253,9 @@ function __ch4acko3DshTurnFoldActivityGroup(props) {
|
|
|
220
253
|
var renderedState = react.useState(initialOpen);
|
|
221
254
|
var bodyRendered = renderedState[0];
|
|
222
255
|
var setBodyRendered = renderedState[1];
|
|
256
|
+
var overflowState = react.useState(initialOpen);
|
|
257
|
+
var overflowVisible = overflowState[0];
|
|
258
|
+
var setOverflowVisible = overflowState[1];
|
|
223
259
|
var frameRef = react.useRef(null);
|
|
224
260
|
var timerRef = react.useRef(null);
|
|
225
261
|
react.useEffect(function () {
|
|
@@ -228,9 +264,13 @@ function __ch4acko3DshTurnFoldActivityGroup(props) {
|
|
|
228
264
|
if (timerRef.current !== null) clearTimeout(timerRef.current);
|
|
229
265
|
};
|
|
230
266
|
}, []);
|
|
231
|
-
var
|
|
232
|
-
|
|
233
|
-
|
|
267
|
+
var reasoningTitle = reasoningCount === 0 ? null : __ch4acko3DshTurnFoldText("activityGroup.reasoning." + (reasoningCount === 1 ? "one" : "many"), { count: reasoningCount });
|
|
268
|
+
var toolTitle = toolCount === 0 ? null : __ch4acko3DshTurnFoldText("activityGroup.tools." + (toolCount === 1 ? "one" : "many"), { count: toolCount });
|
|
269
|
+
var title = reasoningTitle === null ? toolTitle : toolTitle === null ? reasoningTitle : react_jsx_runtime.jsxs(react_jsx_runtime.Fragment, { children: [
|
|
270
|
+
reasoningTitle,
|
|
271
|
+
react_jsx_runtime.jsx("span", { className: "__ch4acko3-dsh-turn-fold-activity__separator", "aria-hidden": true }),
|
|
272
|
+
toolTitle
|
|
273
|
+
] });
|
|
234
274
|
var failure = props.failed === 0 ? null : __ch4acko3DshTurnFoldText("activityGroup.failures." + (props.failed === 1 ? "one" : "many"), { count: props.failed });
|
|
235
275
|
var state = props.running ? "running" : props.failed > 0 ? "error" : "ok";
|
|
236
276
|
function toggle() {
|
|
@@ -240,6 +280,7 @@ function __ch4acko3DshTurnFoldActivityGroup(props) {
|
|
|
240
280
|
timerRef.current = null;
|
|
241
281
|
if (open) {
|
|
242
282
|
__ch4acko3DshTurnFoldOpenKeys.delete(foldKey);
|
|
283
|
+
setOverflowVisible(false);
|
|
243
284
|
setOpen(false);
|
|
244
285
|
var delay = __ch4acko3DshTurnFoldMotionMs();
|
|
245
286
|
if (delay === 0) setBodyRendered(false);
|
|
@@ -251,13 +292,19 @@ function __ch4acko3DshTurnFoldActivityGroup(props) {
|
|
|
251
292
|
}
|
|
252
293
|
__ch4acko3DshTurnFoldOpenKeys.add(foldKey);
|
|
253
294
|
setBodyRendered(true);
|
|
254
|
-
|
|
295
|
+
var delay = __ch4acko3DshTurnFoldMotionMs();
|
|
296
|
+
if (delay === 0 || typeof requestAnimationFrame !== "function") {
|
|
255
297
|
setOpen(true);
|
|
298
|
+
setOverflowVisible(true);
|
|
256
299
|
return;
|
|
257
300
|
}
|
|
258
301
|
frameRef.current = requestAnimationFrame(function () {
|
|
259
302
|
frameRef.current = null;
|
|
260
303
|
setOpen(true);
|
|
304
|
+
timerRef.current = setTimeout(function () {
|
|
305
|
+
timerRef.current = null;
|
|
306
|
+
setOverflowVisible(true);
|
|
307
|
+
}, delay);
|
|
261
308
|
});
|
|
262
309
|
}
|
|
263
310
|
return react_jsx_runtime.jsxs("div", {
|
|
@@ -289,7 +336,7 @@ function __ch4acko3DshTurnFoldActivityGroup(props) {
|
|
|
289
336
|
"aria-hidden": !open,
|
|
290
337
|
inert: !open,
|
|
291
338
|
children: bodyRendered ? react_jsx_runtime.jsx("div", {
|
|
292
|
-
className: "__ch4acko3-dsh-turn-fold-activity__bodyWrap",
|
|
339
|
+
className: "__ch4acko3-dsh-turn-fold-activity__bodyWrap" + (overflowVisible ? " __ch4acko3-dsh-turn-fold-activity__bodyWrap--overflow-visible" : ""),
|
|
293
340
|
children: react_jsx_runtime.jsx("div", {
|
|
294
341
|
className: "__ch4acko3-dsh-turn-fold-activity__body",
|
|
295
342
|
children: props.items.map(function (item) {
|
|
@@ -303,6 +350,38 @@ function __ch4acko3DshTurnFoldActivityGroup(props) {
|
|
|
303
350
|
]
|
|
304
351
|
});
|
|
305
352
|
}
|
|
353
|
+
function __ch4acko3DshTurnFoldInsertionIndex(bounds, clientX, clientY) {
|
|
354
|
+
if (bounds.length === 0) return 0;
|
|
355
|
+
clientY = Math.max(bounds[0].top, Math.min(clientY, bounds[bounds.length - 1].bottom));
|
|
356
|
+
var rows = [];
|
|
357
|
+
for (var boundIndex = 0; boundIndex < bounds.length; boundIndex++) {
|
|
358
|
+
var bound = bounds[boundIndex];
|
|
359
|
+
var row = rows[rows.length - 1];
|
|
360
|
+
if (!row || Math.abs(bound.top - row.top) > 4) {
|
|
361
|
+
row = { start: boundIndex, end: boundIndex + 1, top: bound.top, bottom: bound.bottom };
|
|
362
|
+
rows.push(row);
|
|
363
|
+
} else {
|
|
364
|
+
row.end = boundIndex + 1;
|
|
365
|
+
row.bottom = Math.max(row.bottom, bound.bottom);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
for (var rowIndex = 0; rowIndex < rows.length; rowIndex++) {
|
|
369
|
+
var candidate = rows[rowIndex];
|
|
370
|
+
if (clientY < candidate.top) return candidate.start;
|
|
371
|
+
if (clientY <= candidate.bottom) {
|
|
372
|
+
for (var itemIndex = candidate.start; itemIndex < candidate.end; itemIndex++) {
|
|
373
|
+
var item = bounds[itemIndex];
|
|
374
|
+
if (clientX < item.left + item.width / 2) return itemIndex;
|
|
375
|
+
}
|
|
376
|
+
return candidate.end;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
return bounds.length;
|
|
380
|
+
}
|
|
381
|
+
function __ch4acko3DshTurnFoldDropDestination(dividerY, clientY) {
|
|
382
|
+
return clientY <= dividerY ? "selected" : "available";
|
|
383
|
+
}
|
|
384
|
+
var __ch4acko3DshTurnFoldOwnerLinkDelay = 300;
|
|
306
385
|
function __ch4acko3DshTurnFoldSettingsCard() {
|
|
307
386
|
var openState = react.useState(false);
|
|
308
387
|
var open = openState[0];
|
|
@@ -313,17 +392,74 @@ function __ch4acko3DshTurnFoldSettingsCard() {
|
|
|
313
392
|
var failedState = react.useState(false);
|
|
314
393
|
var failed = failedState[0];
|
|
315
394
|
var setFailed = failedState[1];
|
|
395
|
+
var dragViewState = react.useState(null);
|
|
396
|
+
var dragView = dragViewState[0];
|
|
397
|
+
var setDragView = dragViewState[1];
|
|
398
|
+
var drag = react.useRef(null);
|
|
399
|
+
var selectedSlotRef = react.useRef(null);
|
|
400
|
+
var paletteRef = react.useRef(null);
|
|
401
|
+
var selectedTagRefs = react.useRef(new Map());
|
|
402
|
+
var moveDragRef = react.useRef(null);
|
|
403
|
+
var finishDragRef = react.useRef(null);
|
|
404
|
+
var suppressClick = react.useRef(false);
|
|
405
|
+
var ownerHoverStartedAt = react.useRef(null);
|
|
406
|
+
var ownerReadyTimer = react.useRef(null);
|
|
407
|
+
var ownerLinkReadyState = react.useState(false);
|
|
408
|
+
var ownerLinkReady = ownerLinkReadyState[0];
|
|
409
|
+
var setOwnerLinkReady = ownerLinkReadyState[1];
|
|
410
|
+
react.useEffect(function () {
|
|
411
|
+
if (typeof window === "undefined") return;
|
|
412
|
+
function move(event) { if (moveDragRef.current) moveDragRef.current(event); }
|
|
413
|
+
function finish(event) { if (finishDragRef.current) finishDragRef.current(event); }
|
|
414
|
+
window.addEventListener("pointermove", move);
|
|
415
|
+
window.addEventListener("pointerup", finish, true);
|
|
416
|
+
window.addEventListener("pointercancel", finish, true);
|
|
417
|
+
return function () {
|
|
418
|
+
window.removeEventListener("pointermove", move);
|
|
419
|
+
window.removeEventListener("pointerup", finish, true);
|
|
420
|
+
window.removeEventListener("pointercancel", finish, true);
|
|
421
|
+
};
|
|
422
|
+
}, []);
|
|
423
|
+
react.useEffect(function () {
|
|
424
|
+
return function () {
|
|
425
|
+
if (ownerReadyTimer.current !== null) clearTimeout(ownerReadyTimer.current);
|
|
426
|
+
};
|
|
427
|
+
}, []);
|
|
316
428
|
var scope = __ch4acko3DshTurnFoldSettingsScope;
|
|
317
429
|
if (scope === null) return null;
|
|
318
430
|
var snapshot = react.useSyncExternalStore(function (listener) { return scope.subscribe(listener); }, function () { return scope.getSnapshot(); }, function () { return scope.getSnapshot(); });
|
|
319
431
|
if (snapshot.status !== "ready" || snapshot.value === void 0) return null;
|
|
320
432
|
var fields = snapshot.value.summaryFields;
|
|
433
|
+
var availableFields = __ch4acko3DshTurnFoldKnownFields.filter(function (field) { return fields.indexOf(field) < 0; });
|
|
321
434
|
var title = __ch4acko3DshTurnFoldText("settings.title");
|
|
322
|
-
function
|
|
435
|
+
function toggleOpen() {
|
|
436
|
+
setOpen(function (current) { return !current; });
|
|
437
|
+
}
|
|
438
|
+
function beginOwnerHover() {
|
|
439
|
+
if (ownerReadyTimer.current !== null) clearTimeout(ownerReadyTimer.current);
|
|
440
|
+
ownerHoverStartedAt.current = Date.now();
|
|
441
|
+
setOwnerLinkReady(false);
|
|
442
|
+
ownerReadyTimer.current = setTimeout(function () {
|
|
443
|
+
ownerReadyTimer.current = null;
|
|
444
|
+
setOwnerLinkReady(true);
|
|
445
|
+
}, __ch4acko3DshTurnFoldOwnerLinkDelay);
|
|
446
|
+
}
|
|
447
|
+
function endOwnerHover() {
|
|
448
|
+
if (ownerReadyTimer.current !== null) clearTimeout(ownerReadyTimer.current);
|
|
449
|
+
ownerReadyTimer.current = null;
|
|
450
|
+
ownerHoverStartedAt.current = null;
|
|
451
|
+
setOwnerLinkReady(false);
|
|
452
|
+
}
|
|
453
|
+
function activateOwnerLink(event) {
|
|
454
|
+
if (event.detail === 0) return;
|
|
455
|
+
var startedAt = ownerHoverStartedAt.current;
|
|
456
|
+
if (ownerLinkReady || typeof startedAt === "number" && Date.now() - startedAt >= __ch4acko3DshTurnFoldOwnerLinkDelay) return;
|
|
457
|
+
event.preventDefault();
|
|
458
|
+
toggleOpen();
|
|
459
|
+
}
|
|
460
|
+
function saveFields(next) {
|
|
323
461
|
if (!snapshot.writable || pending) return;
|
|
324
|
-
|
|
325
|
-
return candidate === field ? checked : fields.indexOf(candidate) >= 0;
|
|
326
|
-
});
|
|
462
|
+
if (next.length === fields.length && next.every(function (field, index) { return field === fields[index]; })) return;
|
|
327
463
|
setPending(true);
|
|
328
464
|
setFailed(false);
|
|
329
465
|
scope.set("summaryFields", next).then(function () {
|
|
@@ -333,25 +469,169 @@ function __ch4acko3DshTurnFoldSettingsCard() {
|
|
|
333
469
|
setFailed(true);
|
|
334
470
|
});
|
|
335
471
|
}
|
|
472
|
+
function addField(field) {
|
|
473
|
+
if (__ch4acko3DshTurnFoldKnownFields.indexOf(field) < 0 || fields.indexOf(field) >= 0) return;
|
|
474
|
+
saveFields(fields.concat(field));
|
|
475
|
+
}
|
|
476
|
+
function removeField(field) {
|
|
477
|
+
saveFields(fields.filter(function (candidate) { return candidate !== field; }));
|
|
478
|
+
}
|
|
479
|
+
function placeFieldAt(field, index) {
|
|
480
|
+
if (__ch4acko3DshTurnFoldKnownFields.indexOf(field) < 0) return;
|
|
481
|
+
var next = fields.filter(function (candidate) { return candidate !== field; });
|
|
482
|
+
next.splice(Math.max(0, Math.min(index, next.length)), 0, field);
|
|
483
|
+
saveFields(next);
|
|
484
|
+
}
|
|
485
|
+
function projectDrag(clientX, clientY, field) {
|
|
486
|
+
var selectedSlot = selectedSlotRef.current;
|
|
487
|
+
var palette = paletteRef.current;
|
|
488
|
+
if (!selectedSlot || !palette) return { destination: null, index: 0 };
|
|
489
|
+
var selectedBounds = selectedSlot.getBoundingClientRect();
|
|
490
|
+
var paletteBounds = palette.getBoundingClientRect();
|
|
491
|
+
var destination = __ch4acko3DshTurnFoldDropDestination((selectedBounds.bottom + paletteBounds.top) / 2, clientY);
|
|
492
|
+
if (destination === "selected") {
|
|
493
|
+
var remaining = fields.filter(function (candidate) { return candidate !== field; });
|
|
494
|
+
var bounds = remaining.map(function (candidate) {
|
|
495
|
+
var element = selectedTagRefs.current.get(candidate);
|
|
496
|
+
return element ? element.getBoundingClientRect() : null;
|
|
497
|
+
}).filter(function (value) { return value !== null; });
|
|
498
|
+
return { destination: "selected", index: __ch4acko3DshTurnFoldInsertionIndex(bounds, clientX, clientY) };
|
|
499
|
+
}
|
|
500
|
+
if (destination === "available") return { destination: "available", index: 0 };
|
|
501
|
+
return { destination: null, index: 0 };
|
|
502
|
+
}
|
|
503
|
+
function beginPointerDrag(event, field) {
|
|
504
|
+
if (event.button !== 0 || !snapshot.writable || pending) return;
|
|
505
|
+
var bounds = event.currentTarget.getBoundingClientRect();
|
|
506
|
+
drag.current = {
|
|
507
|
+
field: field,
|
|
508
|
+
pointerId: event.pointerId,
|
|
509
|
+
originX: event.clientX,
|
|
510
|
+
originY: event.clientY,
|
|
511
|
+
lastX: event.clientX,
|
|
512
|
+
lastY: event.clientY,
|
|
513
|
+
moved: false,
|
|
514
|
+
selected: fields.indexOf(field) >= 0,
|
|
515
|
+
width: bounds.width,
|
|
516
|
+
offsetX: event.clientX - bounds.left,
|
|
517
|
+
offsetY: event.clientY - bounds.top
|
|
518
|
+
};
|
|
519
|
+
}
|
|
520
|
+
function movePointerDrag(event) {
|
|
521
|
+
var active = drag.current;
|
|
522
|
+
if (!active || active.pointerId !== event.pointerId || pending) return;
|
|
523
|
+
active.lastX = event.clientX;
|
|
524
|
+
active.lastY = event.clientY;
|
|
525
|
+
if (!active.moved && Math.hypot(event.clientX - active.originX, event.clientY - active.originY) < 8) return;
|
|
526
|
+
active.moved = true;
|
|
527
|
+
event.preventDefault();
|
|
528
|
+
var projection = projectDrag(event.clientX, event.clientY, active.field);
|
|
529
|
+
setDragView({
|
|
530
|
+
field: active.field,
|
|
531
|
+
selected: active.selected,
|
|
532
|
+
x: event.clientX,
|
|
533
|
+
y: event.clientY,
|
|
534
|
+
width: active.width,
|
|
535
|
+
offsetX: active.offsetX,
|
|
536
|
+
offsetY: active.offsetY,
|
|
537
|
+
destination: projection.destination,
|
|
538
|
+
index: projection.index
|
|
539
|
+
});
|
|
540
|
+
}
|
|
541
|
+
function finishPointerDrag(event) {
|
|
542
|
+
var active = drag.current;
|
|
543
|
+
if (!active || active.pointerId !== event.pointerId) return;
|
|
544
|
+
drag.current = null;
|
|
545
|
+
if (!active.moved) return;
|
|
546
|
+
event.preventDefault();
|
|
547
|
+
var projection = projectDrag(event.clientX, event.clientY, active.field);
|
|
548
|
+
setDragView(null);
|
|
549
|
+
if (projection.destination === "selected") placeFieldAt(active.field, projection.index);
|
|
550
|
+
else if (projection.destination === "available" && active.selected) removeField(active.field);
|
|
551
|
+
suppressClick.current = true;
|
|
552
|
+
if (typeof window === "undefined") suppressClick.current = false;
|
|
553
|
+
else window.setTimeout(function () { suppressClick.current = false; }, 0);
|
|
554
|
+
}
|
|
555
|
+
moveDragRef.current = movePointerDrag;
|
|
556
|
+
finishDragRef.current = finishPointerDrag;
|
|
557
|
+
function renderTag(field, selected) {
|
|
558
|
+
var label = __ch4acko3DshTurnFoldText("settings." + field);
|
|
559
|
+
return react_jsx_runtime.jsx("button", {
|
|
560
|
+
ref: selected ? function (element) {
|
|
561
|
+
if (element === null) selectedTagRefs.current.delete(field);
|
|
562
|
+
else selectedTagRefs.current.set(field, element);
|
|
563
|
+
} : void 0,
|
|
564
|
+
type: "button",
|
|
565
|
+
className: "__ch4acko3-dsh-turn-fold-settings__tag",
|
|
566
|
+
"data-field": field,
|
|
567
|
+
"data-selected": selected ? "true" : "false",
|
|
568
|
+
disabled: !snapshot.writable || pending,
|
|
569
|
+
"aria-label": __ch4acko3DshTurnFoldText(selected ? "settings.removeMetric" : "settings.addMetric", { label: label }),
|
|
570
|
+
onClick: function () {
|
|
571
|
+
if (suppressClick.current) return;
|
|
572
|
+
if (selected) removeField(field);
|
|
573
|
+
else addField(field);
|
|
574
|
+
},
|
|
575
|
+
onPointerDown: function (event) { beginPointerDrag(event, field); },
|
|
576
|
+
onKeyDown: selected ? function (event) {
|
|
577
|
+
if (!event.altKey || event.key !== "ArrowLeft" && event.key !== "ArrowRight") return;
|
|
578
|
+
event.preventDefault();
|
|
579
|
+
var index = fields.indexOf(field);
|
|
580
|
+
var target = event.key === "ArrowLeft" ? Math.max(0, index - 1) : Math.min(fields.length - 1, index + 1);
|
|
581
|
+
if (target !== index) placeFieldAt(field, event.key === "ArrowLeft" ? target : target + 1);
|
|
582
|
+
} : void 0,
|
|
583
|
+
children: label
|
|
584
|
+
}, field);
|
|
585
|
+
}
|
|
586
|
+
var movingField = dragView === null ? null : dragView.field;
|
|
587
|
+
var visibleSelected = fields.filter(function (field) { return field !== movingField; });
|
|
588
|
+
var selectedChildren = [];
|
|
589
|
+
for (var selectedIndex = 0; selectedIndex <= visibleSelected.length; selectedIndex++) {
|
|
590
|
+
if (dragView !== null && dragView.destination === "selected" && dragView.index === selectedIndex) {
|
|
591
|
+
selectedChildren.push(react_jsx_runtime.jsx("span", { className: "__ch4acko3-dsh-turn-fold-settings__dropSlot", "aria-hidden": true }, "drop-" + selectedIndex));
|
|
592
|
+
}
|
|
593
|
+
if (selectedIndex < visibleSelected.length) selectedChildren.push(renderTag(visibleSelected[selectedIndex], true));
|
|
594
|
+
}
|
|
595
|
+
if (selectedChildren.length === 0) selectedChildren.push(react_jsx_runtime.jsx("p", { className: "__ch4acko3-dsh-turn-fold-settings__empty", children: __ch4acko3DshTurnFoldText("settings.emptySelection") }, "empty"));
|
|
596
|
+
var visibleAvailable = availableFields.filter(function (field) { return field !== movingField; });
|
|
336
597
|
return react_jsx_runtime.jsxs("li", {
|
|
337
598
|
className: "__ch4acko3-dsh-turn-fold-settings" + (open ? " __ch4acko3-dsh-turn-fold-settings--open" : ""),
|
|
338
599
|
"data-ch4acko3-dsh-turn-fold-settings": "",
|
|
339
600
|
children: [
|
|
340
|
-
react_jsx_runtime.jsxs("
|
|
341
|
-
type: "button",
|
|
601
|
+
react_jsx_runtime.jsxs("div", {
|
|
342
602
|
className: "__ch4acko3-dsh-turn-fold-settings__header",
|
|
343
|
-
"aria-expanded": open,
|
|
344
|
-
"aria-label": __ch4acko3DshTurnFoldText(open ? "settings.collapse" : "settings.expand", { title: title }),
|
|
345
|
-
onClick: function () { setOpen(!open); },
|
|
346
603
|
children: [
|
|
604
|
+
react_jsx_runtime.jsx("button", {
|
|
605
|
+
type: "button",
|
|
606
|
+
className: "__ch4acko3-dsh-turn-fold-settings__headerButton",
|
|
607
|
+
"aria-expanded": open,
|
|
608
|
+
"aria-label": __ch4acko3DshTurnFoldText(open ? "settings.collapse" : "settings.expand", { title: title }),
|
|
609
|
+
onClick: toggleOpen
|
|
610
|
+
}),
|
|
347
611
|
react_jsx_runtime.jsxs("span", {
|
|
348
612
|
className: "__ch4acko3-dsh-turn-fold-settings__headText",
|
|
349
613
|
children: [
|
|
350
|
-
react_jsx_runtime.
|
|
614
|
+
react_jsx_runtime.jsxs("span", {
|
|
615
|
+
className: "__ch4acko3-dsh-turn-fold-settings__titleRow",
|
|
616
|
+
children: [
|
|
617
|
+
react_jsx_runtime.jsx("span", { className: "__ch4acko3-dsh-turn-fold-settings__title", children: title }),
|
|
618
|
+
react_jsx_runtime.jsx("a", {
|
|
619
|
+
className: "__ch4acko3-dsh-turn-fold-settings__pluginName",
|
|
620
|
+
href: "https://github.com/CH4ACKO3/dsh-turn-fold",
|
|
621
|
+
target: "_blank",
|
|
622
|
+
rel: "noreferrer",
|
|
623
|
+
"data-ready": ownerLinkReady ? "true" : "false",
|
|
624
|
+
onPointerEnter: beginOwnerHover,
|
|
625
|
+
onPointerLeave: endOwnerHover,
|
|
626
|
+
onClick: activateOwnerLink,
|
|
627
|
+
children: "@ch4acko3/dsh-turn-fold"
|
|
628
|
+
})
|
|
629
|
+
]
|
|
630
|
+
}),
|
|
351
631
|
react_jsx_runtime.jsx("span", { className: "__ch4acko3-dsh-turn-fold-settings__description", children: __ch4acko3DshTurnFoldText("settings.description") })
|
|
352
632
|
]
|
|
353
633
|
}),
|
|
354
|
-
react_jsx_runtime.jsx(
|
|
634
|
+
react_jsx_runtime.jsx(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutline14, { className: "__ch4acko3-dsh-turn-fold-settings__chevron" })
|
|
355
635
|
]
|
|
356
636
|
}),
|
|
357
637
|
open ? react_jsx_runtime.jsxs("div", {
|
|
@@ -359,19 +639,56 @@ function __ch4acko3DshTurnFoldSettingsCard() {
|
|
|
359
639
|
children: [
|
|
360
640
|
!snapshot.writable ? react_jsx_runtime.jsx("p", { className: "__ch4acko3-dsh-turn-fold-settings__readOnly", role: "status", children: __ch4acko3DshTurnFoldText("settings.readOnly") }) : null,
|
|
361
641
|
failed ? react_jsx_runtime.jsx("p", { className: "__ch4acko3-dsh-turn-fold-settings__readOnly", role: "alert", children: __ch4acko3DshTurnFoldText("settings.writeFailed") }) : null,
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
642
|
+
react_jsx_runtime.jsxs("div", {
|
|
643
|
+
className: "__ch4acko3-dsh-turn-fold-settings__metricEditor",
|
|
644
|
+
children: [
|
|
645
|
+
react_jsx_runtime.jsxs("div", {
|
|
646
|
+
className: "__ch4acko3-dsh-turn-fold-settings__zone",
|
|
647
|
+
children: [
|
|
648
|
+
react_jsx_runtime.jsx("span", { className: "__ch4acko3-dsh-turn-fold-settings__zoneLabel", children: __ch4acko3DshTurnFoldText("settings.selectedMetrics") }),
|
|
649
|
+
react_jsx_runtime.jsx("div", {
|
|
650
|
+
ref: selectedSlotRef,
|
|
651
|
+
className: "__ch4acko3-dsh-turn-fold-settings__slot",
|
|
652
|
+
role: "group",
|
|
653
|
+
"aria-label": __ch4acko3DshTurnFoldText("settings.selectedMetrics"),
|
|
654
|
+
"data-empty": visibleSelected.length === 0 && !(dragView !== null && dragView.destination === "selected") ? "true" : "false",
|
|
655
|
+
"data-drop-active": dragView !== null && dragView.destination === "selected" ? "true" : "false",
|
|
656
|
+
children: selectedChildren
|
|
657
|
+
})
|
|
658
|
+
]
|
|
659
|
+
}),
|
|
660
|
+
react_jsx_runtime.jsxs("div", {
|
|
661
|
+
className: "__ch4acko3-dsh-turn-fold-settings__zone",
|
|
662
|
+
children: [
|
|
663
|
+
react_jsx_runtime.jsx("span", { className: "__ch4acko3-dsh-turn-fold-settings__zoneLabel", children: __ch4acko3DshTurnFoldText("settings.availableMetrics") }),
|
|
664
|
+
react_jsx_runtime.jsx("div", {
|
|
665
|
+
ref: paletteRef,
|
|
666
|
+
className: "__ch4acko3-dsh-turn-fold-settings__palette",
|
|
667
|
+
role: "group",
|
|
668
|
+
"aria-label": __ch4acko3DshTurnFoldText("settings.availableMetrics"),
|
|
669
|
+
"data-empty": visibleAvailable.length === 0 ? "true" : "false",
|
|
670
|
+
"data-drop-active": dragView !== null && dragView.destination === "available" ? "true" : "false",
|
|
671
|
+
children: visibleAvailable.length === 0
|
|
672
|
+
? react_jsx_runtime.jsx("p", { className: "__ch4acko3-dsh-turn-fold-settings__empty", children: __ch4acko3DshTurnFoldText("settings.allSelected") })
|
|
673
|
+
: visibleAvailable.map(function (field) { return renderTag(field, false); })
|
|
674
|
+
})
|
|
675
|
+
]
|
|
676
|
+
})
|
|
677
|
+
]
|
|
678
|
+
}),
|
|
679
|
+
react_jsx_runtime.jsx("p", { className: "__ch4acko3-dsh-turn-fold-settings__hint", children: __ch4acko3DshTurnFoldText("settings.dragHint") }),
|
|
680
|
+
dragView === null ? null : react_jsx_runtime.jsx("div", {
|
|
681
|
+
className: "__ch4acko3-dsh-turn-fold-settings__dragPreview",
|
|
682
|
+
style: {
|
|
683
|
+
left: dragView.x - dragView.offsetX + "px",
|
|
684
|
+
top: dragView.y - dragView.offsetY + "px",
|
|
685
|
+
width: dragView.width + "px"
|
|
686
|
+
},
|
|
687
|
+
children: react_jsx_runtime.jsx("span", {
|
|
688
|
+
className: "__ch4acko3-dsh-turn-fold-settings__tag",
|
|
689
|
+
"data-selected": dragView.selected ? "true" : "false",
|
|
690
|
+
children: __ch4acko3DshTurnFoldText("settings." + dragView.field)
|
|
691
|
+
})
|
|
375
692
|
})
|
|
376
693
|
]
|
|
377
694
|
}) : null
|
|
@@ -601,6 +918,9 @@ function __ch4acko3DshTurnFoldDisclosure(props) {
|
|
|
601
918
|
var renderedState = react.useState(initialOpen);
|
|
602
919
|
var bodyRendered = renderedState[0];
|
|
603
920
|
var setBodyRendered = renderedState[1];
|
|
921
|
+
var overflowState = react.useState(initialOpen);
|
|
922
|
+
var overflowVisible = overflowState[0];
|
|
923
|
+
var setOverflowVisible = overflowState[1];
|
|
604
924
|
var frameRef = react.useRef(null);
|
|
605
925
|
var timerRef = react.useRef(null);
|
|
606
926
|
var bodyIdState = react.useState(function () { return "ch4acko3-dsh-turn-fold-body-" + (++__ch4acko3DshTurnFoldBodyId); });
|
|
@@ -622,6 +942,7 @@ function __ch4acko3DshTurnFoldDisclosure(props) {
|
|
|
622
942
|
timerRef.current = null;
|
|
623
943
|
if (expanded) {
|
|
624
944
|
__ch4acko3DshTurnFoldOpenKeys.delete(foldKey);
|
|
945
|
+
setOverflowVisible(false);
|
|
625
946
|
setExpanded(false);
|
|
626
947
|
var delay = __ch4acko3DshTurnFoldMotionMs();
|
|
627
948
|
if (delay === 0) setBodyRendered(false);
|
|
@@ -633,13 +954,19 @@ function __ch4acko3DshTurnFoldDisclosure(props) {
|
|
|
633
954
|
}
|
|
634
955
|
__ch4acko3DshTurnFoldOpenKeys.add(foldKey);
|
|
635
956
|
setBodyRendered(true);
|
|
636
|
-
|
|
957
|
+
var delay = __ch4acko3DshTurnFoldMotionMs();
|
|
958
|
+
if (delay === 0 || typeof requestAnimationFrame !== "function") {
|
|
637
959
|
setExpanded(true);
|
|
960
|
+
setOverflowVisible(true);
|
|
638
961
|
return;
|
|
639
962
|
}
|
|
640
963
|
frameRef.current = requestAnimationFrame(function () {
|
|
641
964
|
frameRef.current = null;
|
|
642
965
|
setExpanded(true);
|
|
966
|
+
timerRef.current = setTimeout(function () {
|
|
967
|
+
timerRef.current = null;
|
|
968
|
+
setOverflowVisible(true);
|
|
969
|
+
}, delay);
|
|
643
970
|
});
|
|
644
971
|
}
|
|
645
972
|
return react_jsx_runtime.jsxs("div", {
|
|
@@ -666,7 +993,7 @@ function __ch4acko3DshTurnFoldDisclosure(props) {
|
|
|
666
993
|
"aria-hidden": !expanded,
|
|
667
994
|
inert: !expanded,
|
|
668
995
|
children: bodyRendered ? react_jsx_runtime.jsx("div", {
|
|
669
|
-
className: "__ch4acko3-dsh-turn-fold__bodyWrap",
|
|
996
|
+
className: "__ch4acko3-dsh-turn-fold__bodyWrap" + (overflowVisible ? " __ch4acko3-dsh-turn-fold__bodyWrap--overflow-visible" : ""),
|
|
670
997
|
children: react_jsx_runtime.jsxs("div", {
|
|
671
998
|
className: "__ch4acko3-dsh-turn-fold__body",
|
|
672
999
|
children: [
|
package/locales/en.json
CHANGED
|
@@ -15,11 +15,10 @@
|
|
|
15
15
|
"summary.tokensPerSecond": "{count} tokens/s",
|
|
16
16
|
"summary.stoppedSuffix": " - Stopped",
|
|
17
17
|
"summary.interruptedSuffix": " - Interrupted",
|
|
18
|
-
"activityGroup.
|
|
18
|
+
"activityGroup.reasoning.one": "{count} reasoning step",
|
|
19
|
+
"activityGroup.reasoning.many": "{count} reasoning steps",
|
|
19
20
|
"activityGroup.tools.one": "{count} tool call",
|
|
20
21
|
"activityGroup.tools.many": "{count} tool calls",
|
|
21
|
-
"activityGroup.thinkAndTools.one": "Think · {count} tool call",
|
|
22
|
-
"activityGroup.thinkAndTools.many": "Think · {count} tool calls",
|
|
23
22
|
"activityGroup.failures.one": "{count} failed",
|
|
24
23
|
"activityGroup.failures.many": "{count} failed",
|
|
25
24
|
"action.expand": "Expand agent activity: {summary}",
|
|
@@ -30,6 +29,13 @@
|
|
|
30
29
|
"settings.collapse": "Collapse settings: {title}",
|
|
31
30
|
"settings.readOnly": "This settings source is read-only.",
|
|
32
31
|
"settings.writeFailed": "Could not save this setting.",
|
|
32
|
+
"settings.selectedMetrics": "Displayed metrics",
|
|
33
|
+
"settings.availableMetrics": "Available metrics",
|
|
34
|
+
"settings.emptySelection": "No metrics will be shown",
|
|
35
|
+
"settings.allSelected": "All metrics are displayed",
|
|
36
|
+
"settings.dragHint": "Drag to add, remove, or reorder. Click a tag to move it between lists.",
|
|
37
|
+
"settings.addMetric": "Add {label}",
|
|
38
|
+
"settings.removeMetric": "Remove {label}",
|
|
33
39
|
"settings.duration": "Elapsed time",
|
|
34
40
|
"settings.toolCalls": "Tool calls",
|
|
35
41
|
"settings.modelCalls": "Model calls",
|
package/locales/zh.json
CHANGED
|
@@ -15,11 +15,10 @@
|
|
|
15
15
|
"summary.tokensPerSecond": "{count} tokens/秒",
|
|
16
16
|
"summary.stoppedSuffix": " - 已停止",
|
|
17
17
|
"summary.interruptedSuffix": " - 已中断",
|
|
18
|
-
"activityGroup.
|
|
18
|
+
"activityGroup.reasoning.one": "{count} 段思考",
|
|
19
|
+
"activityGroup.reasoning.many": "{count} 段思考",
|
|
19
20
|
"activityGroup.tools.one": "{count} 次工具调用",
|
|
20
21
|
"activityGroup.tools.many": "{count} 次工具调用",
|
|
21
|
-
"activityGroup.thinkAndTools.one": "Think · {count} 次工具调用",
|
|
22
|
-
"activityGroup.thinkAndTools.many": "Think · {count} 次工具调用",
|
|
23
22
|
"activityGroup.failures.one": "{count} 个失败",
|
|
24
23
|
"activityGroup.failures.many": "{count} 个失败",
|
|
25
24
|
"action.expand": "展开执行过程:{summary}",
|
|
@@ -30,6 +29,13 @@
|
|
|
30
29
|
"settings.collapse": "收起设置:{title}",
|
|
31
30
|
"settings.readOnly": "当前设置来源为只读。",
|
|
32
31
|
"settings.writeFailed": "无法保存此设置。",
|
|
32
|
+
"settings.selectedMetrics": "已显示指标",
|
|
33
|
+
"settings.availableMetrics": "可用指标",
|
|
34
|
+
"settings.emptySelection": "摘要栏将不显示任何指标",
|
|
35
|
+
"settings.allSelected": "所有指标均已显示",
|
|
36
|
+
"settings.dragHint": "拖动标签以添加、移除或排序;也可以点击标签在两组间移动。",
|
|
37
|
+
"settings.addMetric": "添加{label}",
|
|
38
|
+
"settings.removeMetric": "移除{label}",
|
|
33
39
|
"settings.duration": "工作耗时",
|
|
34
40
|
"settings.toolCalls": "工具调用次数",
|
|
35
41
|
"settings.modelCalls": "模型调用次数",
|
package/package.json
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ch4acko3/dsh-turn-fold",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Codex-style turn folding for the DSH WebUI conversation, implemented as a dsh-harmony provider.",
|
|
5
5
|
"main": "./index.cjs",
|
|
6
|
+
"engines": {
|
|
7
|
+
"node": "^22.22.3 || >=24.11.1"
|
|
8
|
+
},
|
|
6
9
|
"files": [
|
|
7
10
|
"README.md",
|
|
8
11
|
"README.zh-CN.md",
|
|
@@ -20,7 +23,7 @@
|
|
|
20
23
|
},
|
|
21
24
|
"repository": {
|
|
22
25
|
"type": "git",
|
|
23
|
-
"url": "
|
|
26
|
+
"url": "https://github.com/CH4ACKO3/dsh-turn-fold"
|
|
24
27
|
},
|
|
25
28
|
"dsh": {
|
|
26
29
|
"bundle": {
|
|
@@ -47,12 +50,18 @@
|
|
|
47
50
|
"check": "node test/run.cjs"
|
|
48
51
|
},
|
|
49
52
|
"dependencies": {
|
|
50
|
-
"@deepseek-ai/dsh-settings": "0.1.0-rc.8",
|
|
51
53
|
"@deepseek-ai/schemastery": "^3.18.1"
|
|
52
54
|
},
|
|
55
|
+
"peerDependencies": {
|
|
56
|
+
"@deepseek-ai/dsh-client-ui-conversation": "^0.1.0-rc.8",
|
|
57
|
+
"@deepseek-ai/dsh-settings": "^0.1.0-rc.8",
|
|
58
|
+
"dsh-harmony": "^0.7.0"
|
|
59
|
+
},
|
|
53
60
|
"devDependencies": {
|
|
54
61
|
"@deepseek-ai/dsh-client-ui-conversation": "0.1.0-rc.8",
|
|
62
|
+
"@deepseek-ai/dsh-settings": "0.1.0-rc.8",
|
|
55
63
|
"@phenomnomnominal/tsquery": "^6.2.0",
|
|
64
|
+
"dsh-harmony": "^0.7.0",
|
|
56
65
|
"react": "18.3.1",
|
|
57
66
|
"react-test-renderer": "18.3.1",
|
|
58
67
|
"typescript": "^6.0.3"
|
package/patch.cjs
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
// 3. install-turn-fold-services — registers the plugin's native DSH locale
|
|
14
14
|
// namespace and binds its native settings scope during conversation boot.
|
|
15
15
|
//
|
|
16
|
-
//
|
|
16
|
+
// All three selectors are pinned with an exact `expect: 1` and a target version so
|
|
17
17
|
// a compiled-shape drift fails loudly in `dsh harmony status`.
|
|
18
18
|
|
|
19
19
|
const INLINE = require('./inline-source.cjs')
|
|
@@ -21,7 +21,7 @@ const INLINE = require('./inline-source.cjs')
|
|
|
21
21
|
const TARGET = {
|
|
22
22
|
package: '@deepseek-ai/dsh-client-ui-conversation',
|
|
23
23
|
version: '0.1.0-rc.8',
|
|
24
|
-
|
|
24
|
+
file: 'lib/client.js',
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
module.exports = [
|