@ch4acko3/dsh-turn-fold 0.3.1 → 0.4.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 +5 -2
- package/README.zh-CN.md +3 -1
- package/index.cjs +2 -3
- package/inline-source.cjs +389 -55
- package/locales/en.json +11 -3
- package/locales/zh.json +11 -3
- package/package.json +2 -2
- package/patch.cjs +3 -0
- package/settings.cjs +40 -4
package/README.md
CHANGED
|
@@ -2,14 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
English | [简体中文](README.zh-CN.md)
|
|
4
4
|
|
|
5
|
+
[](https://memorax-ai.github.io/dsh-harmony/)
|
|
6
|
+
|
|
5
7
|
A [dsh-harmony](https://github.com/memorax-ai/dsh-harmony) provider that adds
|
|
6
8
|
Codex-Desktop-style turn folding to the DSH WebUI conversation.
|
|
7
9
|
|
|
8
10
|
https://github.com/user-attachments/assets/3c9dfdcf-a454-4750-9edf-76771ed5a9a6
|
|
9
11
|
|
|
10
12
|
During a turn, the summary bar remains visible while native thinking, notes,
|
|
11
|
-
commands, and tool calls keep streaming. Consecutive reasoning
|
|
12
|
-
share one compact group from the second item
|
|
13
|
+
commands, and tool calls keep streaming. Consecutive reasoning, context
|
|
14
|
+
injections, and tool activity share one compact group from the second item
|
|
15
|
+
onward. When a turn settles, known
|
|
13
16
|
Agent activity, including context injection, moves into one disclosure
|
|
14
17
|
immediately before the final answer. Its configurable metrics default to wall
|
|
15
18
|
time, tool-call count, and input/output tokens, and appear only when the loaded
|
package/README.zh-CN.md
CHANGED
|
@@ -2,11 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
[English](README.md) | 简体中文
|
|
4
4
|
|
|
5
|
+
[](https://memorax-ai.github.io/dsh-harmony/)
|
|
6
|
+
|
|
5
7
|
一个基于 [dsh-harmony](https://github.com/memorax-ai/dsh-harmony) 的 Provider,为 DSH WebUI 对话添加 Codex Desktop 风格的回合折叠。
|
|
6
8
|
|
|
7
9
|
https://github.com/user-attachments/assets/3c9dfdcf-a454-4750-9edf-76771ed5a9a6
|
|
8
10
|
|
|
9
|
-
|
|
11
|
+
回合进行期间,摘要栏保持可见,原生思考、说明、命令和工具调用继续流式输出。从第二项开始,连续的推理、上下文注入和工具活动会合并为一个紧凑分组。回合结束后,包括上下文注入在内的已知 Agent 活动会收进最终答复前方的折叠栏。摘要指标可以配置,默认显示耗时、工具调用次数以及输入/输出 token;只有当已加载的回合包含足够数据、无需猜测即可计算时才会展示对应指标。
|
|
10
12
|
|
|
11
13
|
最终答复通过 `turn-tail.closing.finalNode` 定位,不依赖 `finish_reason` 或 DOM 位置。正常完成、已停止和已中断的回合都会折叠,后两者显示不同的状态标签。当 DSH 将结束分支标记为不可用、结束答复之后仍有节点,或者用户的键盘焦点或文本选择位于活动内容中时,回合会保持展开。失败、达到最大 token、缺少结束节点以及仍在进行的回合也会保持展开,避免隐藏错误或未完成的工作。
|
|
12
14
|
|
package/index.cjs
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
// Host entry for the @ch4acko3/dsh-turn-fold Harmony provider.
|
|
4
|
-
const {
|
|
5
|
-
const { Config, SETTINGS_NAMESPACE } = require('./settings.cjs')
|
|
4
|
+
const { Config, SETTINGS_NAMESPACE, createSettingsSchema } = require('./settings.cjs')
|
|
6
5
|
|
|
7
6
|
exports.Config = Config
|
|
8
7
|
exports.inject = ['harmony']
|
|
9
8
|
exports.apply = (ctx, config) => {
|
|
10
9
|
ctx.inject(['settings'], (settingsCtx) => {
|
|
11
|
-
settingsCtx.settings.register(
|
|
10
|
+
settingsCtx.settings.register(SETTINGS_NAMESPACE, createSettingsSchema(), { base: config })
|
|
12
11
|
})
|
|
13
12
|
}
|
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,12 @@ 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;
|
|
245
|
+
var contextCount = 0;
|
|
212
246
|
for (var itemIndex = 0; itemIndex < props.items.length; itemIndex++) {
|
|
213
247
|
if (props.items[itemIndex].kind === "tool") toolCount++;
|
|
214
|
-
else
|
|
248
|
+
else if (props.items[itemIndex].kind === "reasoning") reasoningCount++;
|
|
249
|
+
else if (props.items[itemIndex].kind === "context") contextCount++;
|
|
215
250
|
}
|
|
216
251
|
var initialOpen = __ch4acko3DshTurnFoldOpenKeys.has(foldKey);
|
|
217
252
|
var openState = react.useState(initialOpen);
|
|
@@ -220,6 +255,9 @@ function __ch4acko3DshTurnFoldActivityGroup(props) {
|
|
|
220
255
|
var renderedState = react.useState(initialOpen);
|
|
221
256
|
var bodyRendered = renderedState[0];
|
|
222
257
|
var setBodyRendered = renderedState[1];
|
|
258
|
+
var overflowState = react.useState(initialOpen);
|
|
259
|
+
var overflowVisible = overflowState[0];
|
|
260
|
+
var setOverflowVisible = overflowState[1];
|
|
223
261
|
var frameRef = react.useRef(null);
|
|
224
262
|
var timerRef = react.useRef(null);
|
|
225
263
|
react.useEffect(function () {
|
|
@@ -228,9 +266,16 @@ function __ch4acko3DshTurnFoldActivityGroup(props) {
|
|
|
228
266
|
if (timerRef.current !== null) clearTimeout(timerRef.current);
|
|
229
267
|
};
|
|
230
268
|
}, []);
|
|
231
|
-
var
|
|
232
|
-
|
|
233
|
-
|
|
269
|
+
var reasoningTitle = reasoningCount === 0 ? null : __ch4acko3DshTurnFoldText("activityGroup.reasoning." + (reasoningCount === 1 ? "one" : "many"), { count: reasoningCount });
|
|
270
|
+
var contextTitle = contextCount === 0 ? null : __ch4acko3DshTurnFoldText("activityGroup.context." + (contextCount === 1 ? "one" : "many"), { count: contextCount });
|
|
271
|
+
var toolTitle = toolCount === 0 ? null : __ch4acko3DshTurnFoldText("activityGroup.tools." + (toolCount === 1 ? "one" : "many"), { count: toolCount });
|
|
272
|
+
var titleParts = [reasoningTitle, contextTitle, toolTitle].filter(function (part) { return part !== null; });
|
|
273
|
+
var titleChildren = [];
|
|
274
|
+
for (var titleIndex = 0; titleIndex < titleParts.length; titleIndex++) {
|
|
275
|
+
if (titleIndex > 0) titleChildren.push(react_jsx_runtime.jsx("span", { className: "__ch4acko3-dsh-turn-fold-activity__separator", "aria-hidden": true }, "separator-" + String(titleIndex)));
|
|
276
|
+
titleChildren.push(titleParts[titleIndex]);
|
|
277
|
+
}
|
|
278
|
+
var title = titleParts.length === 1 ? titleParts[0] : react_jsx_runtime.jsx(react_jsx_runtime.Fragment, { children: titleChildren });
|
|
234
279
|
var failure = props.failed === 0 ? null : __ch4acko3DshTurnFoldText("activityGroup.failures." + (props.failed === 1 ? "one" : "many"), { count: props.failed });
|
|
235
280
|
var state = props.running ? "running" : props.failed > 0 ? "error" : "ok";
|
|
236
281
|
function toggle() {
|
|
@@ -240,6 +285,7 @@ function __ch4acko3DshTurnFoldActivityGroup(props) {
|
|
|
240
285
|
timerRef.current = null;
|
|
241
286
|
if (open) {
|
|
242
287
|
__ch4acko3DshTurnFoldOpenKeys.delete(foldKey);
|
|
288
|
+
setOverflowVisible(false);
|
|
243
289
|
setOpen(false);
|
|
244
290
|
var delay = __ch4acko3DshTurnFoldMotionMs();
|
|
245
291
|
if (delay === 0) setBodyRendered(false);
|
|
@@ -251,13 +297,19 @@ function __ch4acko3DshTurnFoldActivityGroup(props) {
|
|
|
251
297
|
}
|
|
252
298
|
__ch4acko3DshTurnFoldOpenKeys.add(foldKey);
|
|
253
299
|
setBodyRendered(true);
|
|
254
|
-
|
|
300
|
+
var delay = __ch4acko3DshTurnFoldMotionMs();
|
|
301
|
+
if (delay === 0 || typeof requestAnimationFrame !== "function") {
|
|
255
302
|
setOpen(true);
|
|
303
|
+
setOverflowVisible(true);
|
|
256
304
|
return;
|
|
257
305
|
}
|
|
258
306
|
frameRef.current = requestAnimationFrame(function () {
|
|
259
307
|
frameRef.current = null;
|
|
260
308
|
setOpen(true);
|
|
309
|
+
timerRef.current = setTimeout(function () {
|
|
310
|
+
timerRef.current = null;
|
|
311
|
+
setOverflowVisible(true);
|
|
312
|
+
}, delay);
|
|
261
313
|
});
|
|
262
314
|
}
|
|
263
315
|
return react_jsx_runtime.jsxs("div", {
|
|
@@ -289,7 +341,7 @@ function __ch4acko3DshTurnFoldActivityGroup(props) {
|
|
|
289
341
|
"aria-hidden": !open,
|
|
290
342
|
inert: !open,
|
|
291
343
|
children: bodyRendered ? react_jsx_runtime.jsx("div", {
|
|
292
|
-
className: "__ch4acko3-dsh-turn-fold-activity__bodyWrap",
|
|
344
|
+
className: "__ch4acko3-dsh-turn-fold-activity__bodyWrap" + (overflowVisible ? " __ch4acko3-dsh-turn-fold-activity__bodyWrap--overflow-visible" : ""),
|
|
293
345
|
children: react_jsx_runtime.jsx("div", {
|
|
294
346
|
className: "__ch4acko3-dsh-turn-fold-activity__body",
|
|
295
347
|
children: props.items.map(function (item) {
|
|
@@ -303,6 +355,38 @@ function __ch4acko3DshTurnFoldActivityGroup(props) {
|
|
|
303
355
|
]
|
|
304
356
|
});
|
|
305
357
|
}
|
|
358
|
+
function __ch4acko3DshTurnFoldInsertionIndex(bounds, clientX, clientY) {
|
|
359
|
+
if (bounds.length === 0) return 0;
|
|
360
|
+
clientY = Math.max(bounds[0].top, Math.min(clientY, bounds[bounds.length - 1].bottom));
|
|
361
|
+
var rows = [];
|
|
362
|
+
for (var boundIndex = 0; boundIndex < bounds.length; boundIndex++) {
|
|
363
|
+
var bound = bounds[boundIndex];
|
|
364
|
+
var row = rows[rows.length - 1];
|
|
365
|
+
if (!row || Math.abs(bound.top - row.top) > 4) {
|
|
366
|
+
row = { start: boundIndex, end: boundIndex + 1, top: bound.top, bottom: bound.bottom };
|
|
367
|
+
rows.push(row);
|
|
368
|
+
} else {
|
|
369
|
+
row.end = boundIndex + 1;
|
|
370
|
+
row.bottom = Math.max(row.bottom, bound.bottom);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
for (var rowIndex = 0; rowIndex < rows.length; rowIndex++) {
|
|
374
|
+
var candidate = rows[rowIndex];
|
|
375
|
+
if (clientY < candidate.top) return candidate.start;
|
|
376
|
+
if (clientY <= candidate.bottom) {
|
|
377
|
+
for (var itemIndex = candidate.start; itemIndex < candidate.end; itemIndex++) {
|
|
378
|
+
var item = bounds[itemIndex];
|
|
379
|
+
if (clientX < item.left + item.width / 2) return itemIndex;
|
|
380
|
+
}
|
|
381
|
+
return candidate.end;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
return bounds.length;
|
|
385
|
+
}
|
|
386
|
+
function __ch4acko3DshTurnFoldDropDestination(dividerY, clientY) {
|
|
387
|
+
return clientY <= dividerY ? "selected" : "available";
|
|
388
|
+
}
|
|
389
|
+
var __ch4acko3DshTurnFoldOwnerLinkDelay = 300;
|
|
306
390
|
function __ch4acko3DshTurnFoldSettingsCard() {
|
|
307
391
|
var openState = react.useState(false);
|
|
308
392
|
var open = openState[0];
|
|
@@ -313,17 +397,74 @@ function __ch4acko3DshTurnFoldSettingsCard() {
|
|
|
313
397
|
var failedState = react.useState(false);
|
|
314
398
|
var failed = failedState[0];
|
|
315
399
|
var setFailed = failedState[1];
|
|
400
|
+
var dragViewState = react.useState(null);
|
|
401
|
+
var dragView = dragViewState[0];
|
|
402
|
+
var setDragView = dragViewState[1];
|
|
403
|
+
var drag = react.useRef(null);
|
|
404
|
+
var selectedSlotRef = react.useRef(null);
|
|
405
|
+
var paletteRef = react.useRef(null);
|
|
406
|
+
var selectedTagRefs = react.useRef(new Map());
|
|
407
|
+
var moveDragRef = react.useRef(null);
|
|
408
|
+
var finishDragRef = react.useRef(null);
|
|
409
|
+
var suppressClick = react.useRef(false);
|
|
410
|
+
var ownerHoverStartedAt = react.useRef(null);
|
|
411
|
+
var ownerReadyTimer = react.useRef(null);
|
|
412
|
+
var ownerLinkReadyState = react.useState(false);
|
|
413
|
+
var ownerLinkReady = ownerLinkReadyState[0];
|
|
414
|
+
var setOwnerLinkReady = ownerLinkReadyState[1];
|
|
415
|
+
react.useEffect(function () {
|
|
416
|
+
if (typeof window === "undefined") return;
|
|
417
|
+
function move(event) { if (moveDragRef.current) moveDragRef.current(event); }
|
|
418
|
+
function finish(event) { if (finishDragRef.current) finishDragRef.current(event); }
|
|
419
|
+
window.addEventListener("pointermove", move);
|
|
420
|
+
window.addEventListener("pointerup", finish, true);
|
|
421
|
+
window.addEventListener("pointercancel", finish, true);
|
|
422
|
+
return function () {
|
|
423
|
+
window.removeEventListener("pointermove", move);
|
|
424
|
+
window.removeEventListener("pointerup", finish, true);
|
|
425
|
+
window.removeEventListener("pointercancel", finish, true);
|
|
426
|
+
};
|
|
427
|
+
}, []);
|
|
428
|
+
react.useEffect(function () {
|
|
429
|
+
return function () {
|
|
430
|
+
if (ownerReadyTimer.current !== null) clearTimeout(ownerReadyTimer.current);
|
|
431
|
+
};
|
|
432
|
+
}, []);
|
|
316
433
|
var scope = __ch4acko3DshTurnFoldSettingsScope;
|
|
317
434
|
if (scope === null) return null;
|
|
318
435
|
var snapshot = react.useSyncExternalStore(function (listener) { return scope.subscribe(listener); }, function () { return scope.getSnapshot(); }, function () { return scope.getSnapshot(); });
|
|
319
436
|
if (snapshot.status !== "ready" || snapshot.value === void 0) return null;
|
|
320
437
|
var fields = snapshot.value.summaryFields;
|
|
438
|
+
var availableFields = __ch4acko3DshTurnFoldKnownFields.filter(function (field) { return fields.indexOf(field) < 0; });
|
|
321
439
|
var title = __ch4acko3DshTurnFoldText("settings.title");
|
|
322
|
-
function
|
|
440
|
+
function toggleOpen() {
|
|
441
|
+
setOpen(function (current) { return !current; });
|
|
442
|
+
}
|
|
443
|
+
function beginOwnerHover() {
|
|
444
|
+
if (ownerReadyTimer.current !== null) clearTimeout(ownerReadyTimer.current);
|
|
445
|
+
ownerHoverStartedAt.current = Date.now();
|
|
446
|
+
setOwnerLinkReady(false);
|
|
447
|
+
ownerReadyTimer.current = setTimeout(function () {
|
|
448
|
+
ownerReadyTimer.current = null;
|
|
449
|
+
setOwnerLinkReady(true);
|
|
450
|
+
}, __ch4acko3DshTurnFoldOwnerLinkDelay);
|
|
451
|
+
}
|
|
452
|
+
function endOwnerHover() {
|
|
453
|
+
if (ownerReadyTimer.current !== null) clearTimeout(ownerReadyTimer.current);
|
|
454
|
+
ownerReadyTimer.current = null;
|
|
455
|
+
ownerHoverStartedAt.current = null;
|
|
456
|
+
setOwnerLinkReady(false);
|
|
457
|
+
}
|
|
458
|
+
function activateOwnerLink(event) {
|
|
459
|
+
if (event.detail === 0) return;
|
|
460
|
+
var startedAt = ownerHoverStartedAt.current;
|
|
461
|
+
if (ownerLinkReady || typeof startedAt === "number" && Date.now() - startedAt >= __ch4acko3DshTurnFoldOwnerLinkDelay) return;
|
|
462
|
+
event.preventDefault();
|
|
463
|
+
toggleOpen();
|
|
464
|
+
}
|
|
465
|
+
function saveFields(next) {
|
|
323
466
|
if (!snapshot.writable || pending) return;
|
|
324
|
-
|
|
325
|
-
return candidate === field ? checked : fields.indexOf(candidate) >= 0;
|
|
326
|
-
});
|
|
467
|
+
if (next.length === fields.length && next.every(function (field, index) { return field === fields[index]; })) return;
|
|
327
468
|
setPending(true);
|
|
328
469
|
setFailed(false);
|
|
329
470
|
scope.set("summaryFields", next).then(function () {
|
|
@@ -333,25 +474,169 @@ function __ch4acko3DshTurnFoldSettingsCard() {
|
|
|
333
474
|
setFailed(true);
|
|
334
475
|
});
|
|
335
476
|
}
|
|
477
|
+
function addField(field) {
|
|
478
|
+
if (__ch4acko3DshTurnFoldKnownFields.indexOf(field) < 0 || fields.indexOf(field) >= 0) return;
|
|
479
|
+
saveFields(fields.concat(field));
|
|
480
|
+
}
|
|
481
|
+
function removeField(field) {
|
|
482
|
+
saveFields(fields.filter(function (candidate) { return candidate !== field; }));
|
|
483
|
+
}
|
|
484
|
+
function placeFieldAt(field, index) {
|
|
485
|
+
if (__ch4acko3DshTurnFoldKnownFields.indexOf(field) < 0) return;
|
|
486
|
+
var next = fields.filter(function (candidate) { return candidate !== field; });
|
|
487
|
+
next.splice(Math.max(0, Math.min(index, next.length)), 0, field);
|
|
488
|
+
saveFields(next);
|
|
489
|
+
}
|
|
490
|
+
function projectDrag(clientX, clientY, field) {
|
|
491
|
+
var selectedSlot = selectedSlotRef.current;
|
|
492
|
+
var palette = paletteRef.current;
|
|
493
|
+
if (!selectedSlot || !palette) return { destination: null, index: 0 };
|
|
494
|
+
var selectedBounds = selectedSlot.getBoundingClientRect();
|
|
495
|
+
var paletteBounds = palette.getBoundingClientRect();
|
|
496
|
+
var destination = __ch4acko3DshTurnFoldDropDestination((selectedBounds.bottom + paletteBounds.top) / 2, clientY);
|
|
497
|
+
if (destination === "selected") {
|
|
498
|
+
var remaining = fields.filter(function (candidate) { return candidate !== field; });
|
|
499
|
+
var bounds = remaining.map(function (candidate) {
|
|
500
|
+
var element = selectedTagRefs.current.get(candidate);
|
|
501
|
+
return element ? element.getBoundingClientRect() : null;
|
|
502
|
+
}).filter(function (value) { return value !== null; });
|
|
503
|
+
return { destination: "selected", index: __ch4acko3DshTurnFoldInsertionIndex(bounds, clientX, clientY) };
|
|
504
|
+
}
|
|
505
|
+
if (destination === "available") return { destination: "available", index: 0 };
|
|
506
|
+
return { destination: null, index: 0 };
|
|
507
|
+
}
|
|
508
|
+
function beginPointerDrag(event, field) {
|
|
509
|
+
if (event.button !== 0 || !snapshot.writable || pending) return;
|
|
510
|
+
var bounds = event.currentTarget.getBoundingClientRect();
|
|
511
|
+
drag.current = {
|
|
512
|
+
field: field,
|
|
513
|
+
pointerId: event.pointerId,
|
|
514
|
+
originX: event.clientX,
|
|
515
|
+
originY: event.clientY,
|
|
516
|
+
lastX: event.clientX,
|
|
517
|
+
lastY: event.clientY,
|
|
518
|
+
moved: false,
|
|
519
|
+
selected: fields.indexOf(field) >= 0,
|
|
520
|
+
width: bounds.width,
|
|
521
|
+
offsetX: event.clientX - bounds.left,
|
|
522
|
+
offsetY: event.clientY - bounds.top
|
|
523
|
+
};
|
|
524
|
+
}
|
|
525
|
+
function movePointerDrag(event) {
|
|
526
|
+
var active = drag.current;
|
|
527
|
+
if (!active || active.pointerId !== event.pointerId || pending) return;
|
|
528
|
+
active.lastX = event.clientX;
|
|
529
|
+
active.lastY = event.clientY;
|
|
530
|
+
if (!active.moved && Math.hypot(event.clientX - active.originX, event.clientY - active.originY) < 8) return;
|
|
531
|
+
active.moved = true;
|
|
532
|
+
event.preventDefault();
|
|
533
|
+
var projection = projectDrag(event.clientX, event.clientY, active.field);
|
|
534
|
+
setDragView({
|
|
535
|
+
field: active.field,
|
|
536
|
+
selected: active.selected,
|
|
537
|
+
x: event.clientX,
|
|
538
|
+
y: event.clientY,
|
|
539
|
+
width: active.width,
|
|
540
|
+
offsetX: active.offsetX,
|
|
541
|
+
offsetY: active.offsetY,
|
|
542
|
+
destination: projection.destination,
|
|
543
|
+
index: projection.index
|
|
544
|
+
});
|
|
545
|
+
}
|
|
546
|
+
function finishPointerDrag(event) {
|
|
547
|
+
var active = drag.current;
|
|
548
|
+
if (!active || active.pointerId !== event.pointerId) return;
|
|
549
|
+
drag.current = null;
|
|
550
|
+
if (!active.moved) return;
|
|
551
|
+
event.preventDefault();
|
|
552
|
+
var projection = projectDrag(event.clientX, event.clientY, active.field);
|
|
553
|
+
setDragView(null);
|
|
554
|
+
if (projection.destination === "selected") placeFieldAt(active.field, projection.index);
|
|
555
|
+
else if (projection.destination === "available" && active.selected) removeField(active.field);
|
|
556
|
+
suppressClick.current = true;
|
|
557
|
+
if (typeof window === "undefined") suppressClick.current = false;
|
|
558
|
+
else window.setTimeout(function () { suppressClick.current = false; }, 0);
|
|
559
|
+
}
|
|
560
|
+
moveDragRef.current = movePointerDrag;
|
|
561
|
+
finishDragRef.current = finishPointerDrag;
|
|
562
|
+
function renderTag(field, selected) {
|
|
563
|
+
var label = __ch4acko3DshTurnFoldText("settings." + field);
|
|
564
|
+
return react_jsx_runtime.jsx("button", {
|
|
565
|
+
ref: selected ? function (element) {
|
|
566
|
+
if (element === null) selectedTagRefs.current.delete(field);
|
|
567
|
+
else selectedTagRefs.current.set(field, element);
|
|
568
|
+
} : void 0,
|
|
569
|
+
type: "button",
|
|
570
|
+
className: "__ch4acko3-dsh-turn-fold-settings__tag",
|
|
571
|
+
"data-field": field,
|
|
572
|
+
"data-selected": selected ? "true" : "false",
|
|
573
|
+
disabled: !snapshot.writable || pending,
|
|
574
|
+
"aria-label": __ch4acko3DshTurnFoldText(selected ? "settings.removeMetric" : "settings.addMetric", { label: label }),
|
|
575
|
+
onClick: function () {
|
|
576
|
+
if (suppressClick.current) return;
|
|
577
|
+
if (selected) removeField(field);
|
|
578
|
+
else addField(field);
|
|
579
|
+
},
|
|
580
|
+
onPointerDown: function (event) { beginPointerDrag(event, field); },
|
|
581
|
+
onKeyDown: selected ? function (event) {
|
|
582
|
+
if (!event.altKey || event.key !== "ArrowLeft" && event.key !== "ArrowRight") return;
|
|
583
|
+
event.preventDefault();
|
|
584
|
+
var index = fields.indexOf(field);
|
|
585
|
+
var target = event.key === "ArrowLeft" ? Math.max(0, index - 1) : Math.min(fields.length - 1, index + 1);
|
|
586
|
+
if (target !== index) placeFieldAt(field, event.key === "ArrowLeft" ? target : target + 1);
|
|
587
|
+
} : void 0,
|
|
588
|
+
children: label
|
|
589
|
+
}, field);
|
|
590
|
+
}
|
|
591
|
+
var movingField = dragView === null ? null : dragView.field;
|
|
592
|
+
var visibleSelected = fields.filter(function (field) { return field !== movingField; });
|
|
593
|
+
var selectedChildren = [];
|
|
594
|
+
for (var selectedIndex = 0; selectedIndex <= visibleSelected.length; selectedIndex++) {
|
|
595
|
+
if (dragView !== null && dragView.destination === "selected" && dragView.index === selectedIndex) {
|
|
596
|
+
selectedChildren.push(react_jsx_runtime.jsx("span", { className: "__ch4acko3-dsh-turn-fold-settings__dropSlot", "aria-hidden": true }, "drop-" + selectedIndex));
|
|
597
|
+
}
|
|
598
|
+
if (selectedIndex < visibleSelected.length) selectedChildren.push(renderTag(visibleSelected[selectedIndex], true));
|
|
599
|
+
}
|
|
600
|
+
if (selectedChildren.length === 0) selectedChildren.push(react_jsx_runtime.jsx("p", { className: "__ch4acko3-dsh-turn-fold-settings__empty", children: __ch4acko3DshTurnFoldText("settings.emptySelection") }, "empty"));
|
|
601
|
+
var visibleAvailable = availableFields.filter(function (field) { return field !== movingField; });
|
|
336
602
|
return react_jsx_runtime.jsxs("li", {
|
|
337
603
|
className: "__ch4acko3-dsh-turn-fold-settings" + (open ? " __ch4acko3-dsh-turn-fold-settings--open" : ""),
|
|
338
604
|
"data-ch4acko3-dsh-turn-fold-settings": "",
|
|
339
605
|
children: [
|
|
340
|
-
react_jsx_runtime.jsxs("
|
|
341
|
-
type: "button",
|
|
606
|
+
react_jsx_runtime.jsxs("div", {
|
|
342
607
|
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
608
|
children: [
|
|
609
|
+
react_jsx_runtime.jsx("button", {
|
|
610
|
+
type: "button",
|
|
611
|
+
className: "__ch4acko3-dsh-turn-fold-settings__headerButton",
|
|
612
|
+
"aria-expanded": open,
|
|
613
|
+
"aria-label": __ch4acko3DshTurnFoldText(open ? "settings.collapse" : "settings.expand", { title: title }),
|
|
614
|
+
onClick: toggleOpen
|
|
615
|
+
}),
|
|
347
616
|
react_jsx_runtime.jsxs("span", {
|
|
348
617
|
className: "__ch4acko3-dsh-turn-fold-settings__headText",
|
|
349
618
|
children: [
|
|
350
|
-
react_jsx_runtime.
|
|
619
|
+
react_jsx_runtime.jsxs("span", {
|
|
620
|
+
className: "__ch4acko3-dsh-turn-fold-settings__titleRow",
|
|
621
|
+
children: [
|
|
622
|
+
react_jsx_runtime.jsx("span", { className: "__ch4acko3-dsh-turn-fold-settings__title", children: title }),
|
|
623
|
+
react_jsx_runtime.jsx("a", {
|
|
624
|
+
className: "__ch4acko3-dsh-turn-fold-settings__pluginName",
|
|
625
|
+
href: "https://github.com/CH4ACKO3/dsh-turn-fold",
|
|
626
|
+
target: "_blank",
|
|
627
|
+
rel: "noreferrer",
|
|
628
|
+
"data-ready": ownerLinkReady ? "true" : "false",
|
|
629
|
+
onPointerEnter: beginOwnerHover,
|
|
630
|
+
onPointerLeave: endOwnerHover,
|
|
631
|
+
onClick: activateOwnerLink,
|
|
632
|
+
children: "@ch4acko3/dsh-turn-fold"
|
|
633
|
+
})
|
|
634
|
+
]
|
|
635
|
+
}),
|
|
351
636
|
react_jsx_runtime.jsx("span", { className: "__ch4acko3-dsh-turn-fold-settings__description", children: __ch4acko3DshTurnFoldText("settings.description") })
|
|
352
637
|
]
|
|
353
638
|
}),
|
|
354
|
-
react_jsx_runtime.jsx(
|
|
639
|
+
react_jsx_runtime.jsx(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutline14, { className: "__ch4acko3-dsh-turn-fold-settings__chevron" })
|
|
355
640
|
]
|
|
356
641
|
}),
|
|
357
642
|
open ? react_jsx_runtime.jsxs("div", {
|
|
@@ -359,19 +644,56 @@ function __ch4acko3DshTurnFoldSettingsCard() {
|
|
|
359
644
|
children: [
|
|
360
645
|
!snapshot.writable ? react_jsx_runtime.jsx("p", { className: "__ch4acko3-dsh-turn-fold-settings__readOnly", role: "status", children: __ch4acko3DshTurnFoldText("settings.readOnly") }) : null,
|
|
361
646
|
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
|
-
|
|
647
|
+
react_jsx_runtime.jsxs("div", {
|
|
648
|
+
className: "__ch4acko3-dsh-turn-fold-settings__metricEditor",
|
|
649
|
+
children: [
|
|
650
|
+
react_jsx_runtime.jsxs("div", {
|
|
651
|
+
className: "__ch4acko3-dsh-turn-fold-settings__zone",
|
|
652
|
+
children: [
|
|
653
|
+
react_jsx_runtime.jsx("span", { className: "__ch4acko3-dsh-turn-fold-settings__zoneLabel", children: __ch4acko3DshTurnFoldText("settings.selectedMetrics") }),
|
|
654
|
+
react_jsx_runtime.jsx("div", {
|
|
655
|
+
ref: selectedSlotRef,
|
|
656
|
+
className: "__ch4acko3-dsh-turn-fold-settings__slot",
|
|
657
|
+
role: "group",
|
|
658
|
+
"aria-label": __ch4acko3DshTurnFoldText("settings.selectedMetrics"),
|
|
659
|
+
"data-empty": visibleSelected.length === 0 && !(dragView !== null && dragView.destination === "selected") ? "true" : "false",
|
|
660
|
+
"data-drop-active": dragView !== null && dragView.destination === "selected" ? "true" : "false",
|
|
661
|
+
children: selectedChildren
|
|
662
|
+
})
|
|
663
|
+
]
|
|
664
|
+
}),
|
|
665
|
+
react_jsx_runtime.jsxs("div", {
|
|
666
|
+
className: "__ch4acko3-dsh-turn-fold-settings__zone",
|
|
667
|
+
children: [
|
|
668
|
+
react_jsx_runtime.jsx("span", { className: "__ch4acko3-dsh-turn-fold-settings__zoneLabel", children: __ch4acko3DshTurnFoldText("settings.availableMetrics") }),
|
|
669
|
+
react_jsx_runtime.jsx("div", {
|
|
670
|
+
ref: paletteRef,
|
|
671
|
+
className: "__ch4acko3-dsh-turn-fold-settings__palette",
|
|
672
|
+
role: "group",
|
|
673
|
+
"aria-label": __ch4acko3DshTurnFoldText("settings.availableMetrics"),
|
|
674
|
+
"data-empty": visibleAvailable.length === 0 ? "true" : "false",
|
|
675
|
+
"data-drop-active": dragView !== null && dragView.destination === "available" ? "true" : "false",
|
|
676
|
+
children: visibleAvailable.length === 0
|
|
677
|
+
? react_jsx_runtime.jsx("p", { className: "__ch4acko3-dsh-turn-fold-settings__empty", children: __ch4acko3DshTurnFoldText("settings.allSelected") })
|
|
678
|
+
: visibleAvailable.map(function (field) { return renderTag(field, false); })
|
|
679
|
+
})
|
|
680
|
+
]
|
|
681
|
+
})
|
|
682
|
+
]
|
|
683
|
+
}),
|
|
684
|
+
react_jsx_runtime.jsx("p", { className: "__ch4acko3-dsh-turn-fold-settings__hint", children: __ch4acko3DshTurnFoldText("settings.dragHint") }),
|
|
685
|
+
dragView === null ? null : react_jsx_runtime.jsx("div", {
|
|
686
|
+
className: "__ch4acko3-dsh-turn-fold-settings__dragPreview",
|
|
687
|
+
style: {
|
|
688
|
+
left: dragView.x - dragView.offsetX + "px",
|
|
689
|
+
top: dragView.y - dragView.offsetY + "px",
|
|
690
|
+
width: dragView.width + "px"
|
|
691
|
+
},
|
|
692
|
+
children: react_jsx_runtime.jsx("span", {
|
|
693
|
+
className: "__ch4acko3-dsh-turn-fold-settings__tag",
|
|
694
|
+
"data-selected": dragView.selected ? "true" : "false",
|
|
695
|
+
children: __ch4acko3DshTurnFoldText("settings." + dragView.field)
|
|
696
|
+
})
|
|
375
697
|
})
|
|
376
698
|
]
|
|
377
699
|
}) : null
|
|
@@ -512,7 +834,7 @@ function __ch4acko3DshTurnFoldHasToolCallBlock(node) {
|
|
|
512
834
|
return Array.isArray(blocks) && blocks.some(function (block) { return block !== void 0 && block.kind === "tool-call"; });
|
|
513
835
|
}
|
|
514
836
|
function __ch4acko3DshTurnFoldIsActivityNode(node) {
|
|
515
|
-
if (node.kind === "tool-call") return true;
|
|
837
|
+
if (node.kind === "tool-call" || node.kind === "context") return true;
|
|
516
838
|
if (node.kind !== "assistant-step" || __ch4acko3DshTurnFoldReasoningTexts(node).length === 0) return false;
|
|
517
839
|
return __ch4acko3DshTurnFoldHasToolCallBlock(node) || !__ch4acko3DshTurnFoldHasVisibleNonReasoning(node);
|
|
518
840
|
}
|
|
@@ -560,6 +882,8 @@ function __ch4acko3DshTurnFoldRenderEntries(entries, nodeStore, renderNode, sess
|
|
|
560
882
|
if (activityEntry.node.kind === "tool-call") {
|
|
561
883
|
toolKeys.push(activityEntry.key);
|
|
562
884
|
items.push({ kind: "tool", key: activityEntry.key });
|
|
885
|
+
} else if (activityEntry.node.kind === "context") {
|
|
886
|
+
items.push({ kind: "context", key: activityEntry.key });
|
|
563
887
|
} else {
|
|
564
888
|
var texts = __ch4acko3DshTurnFoldReasoningTexts(activityEntry.node);
|
|
565
889
|
for (var textIndex = 0; textIndex < texts.length; textIndex++) items.push({ kind: "reasoning", key: String(activityEntry.key) + ":" + String(textIndex), text: texts[textIndex] });
|
|
@@ -601,6 +925,9 @@ function __ch4acko3DshTurnFoldDisclosure(props) {
|
|
|
601
925
|
var renderedState = react.useState(initialOpen);
|
|
602
926
|
var bodyRendered = renderedState[0];
|
|
603
927
|
var setBodyRendered = renderedState[1];
|
|
928
|
+
var overflowState = react.useState(initialOpen);
|
|
929
|
+
var overflowVisible = overflowState[0];
|
|
930
|
+
var setOverflowVisible = overflowState[1];
|
|
604
931
|
var frameRef = react.useRef(null);
|
|
605
932
|
var timerRef = react.useRef(null);
|
|
606
933
|
var bodyIdState = react.useState(function () { return "ch4acko3-dsh-turn-fold-body-" + (++__ch4acko3DshTurnFoldBodyId); });
|
|
@@ -622,6 +949,7 @@ function __ch4acko3DshTurnFoldDisclosure(props) {
|
|
|
622
949
|
timerRef.current = null;
|
|
623
950
|
if (expanded) {
|
|
624
951
|
__ch4acko3DshTurnFoldOpenKeys.delete(foldKey);
|
|
952
|
+
setOverflowVisible(false);
|
|
625
953
|
setExpanded(false);
|
|
626
954
|
var delay = __ch4acko3DshTurnFoldMotionMs();
|
|
627
955
|
if (delay === 0) setBodyRendered(false);
|
|
@@ -633,13 +961,19 @@ function __ch4acko3DshTurnFoldDisclosure(props) {
|
|
|
633
961
|
}
|
|
634
962
|
__ch4acko3DshTurnFoldOpenKeys.add(foldKey);
|
|
635
963
|
setBodyRendered(true);
|
|
636
|
-
|
|
964
|
+
var delay = __ch4acko3DshTurnFoldMotionMs();
|
|
965
|
+
if (delay === 0 || typeof requestAnimationFrame !== "function") {
|
|
637
966
|
setExpanded(true);
|
|
967
|
+
setOverflowVisible(true);
|
|
638
968
|
return;
|
|
639
969
|
}
|
|
640
970
|
frameRef.current = requestAnimationFrame(function () {
|
|
641
971
|
frameRef.current = null;
|
|
642
972
|
setExpanded(true);
|
|
973
|
+
timerRef.current = setTimeout(function () {
|
|
974
|
+
timerRef.current = null;
|
|
975
|
+
setOverflowVisible(true);
|
|
976
|
+
}, delay);
|
|
643
977
|
});
|
|
644
978
|
}
|
|
645
979
|
return react_jsx_runtime.jsxs("div", {
|
|
@@ -666,7 +1000,7 @@ function __ch4acko3DshTurnFoldDisclosure(props) {
|
|
|
666
1000
|
"aria-hidden": !expanded,
|
|
667
1001
|
inert: !expanded,
|
|
668
1002
|
children: bodyRendered ? react_jsx_runtime.jsx("div", {
|
|
669
|
-
className: "__ch4acko3-dsh-turn-fold__bodyWrap",
|
|
1003
|
+
className: "__ch4acko3-dsh-turn-fold__bodyWrap" + (overflowVisible ? " __ch4acko3-dsh-turn-fold__bodyWrap--overflow-visible" : ""),
|
|
670
1004
|
children: react_jsx_runtime.jsxs("div", {
|
|
671
1005
|
className: "__ch4acko3-dsh-turn-fold__body",
|
|
672
1006
|
children: [
|
package/locales/en.json
CHANGED
|
@@ -15,11 +15,12 @@
|
|
|
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",
|
|
20
|
+
"activityGroup.context.one": "{count} context injection",
|
|
21
|
+
"activityGroup.context.many": "{count} context injections",
|
|
19
22
|
"activityGroup.tools.one": "{count} tool call",
|
|
20
23
|
"activityGroup.tools.many": "{count} tool calls",
|
|
21
|
-
"activityGroup.thinkAndTools.one": "Think · {count} tool call",
|
|
22
|
-
"activityGroup.thinkAndTools.many": "Think · {count} tool calls",
|
|
23
24
|
"activityGroup.failures.one": "{count} failed",
|
|
24
25
|
"activityGroup.failures.many": "{count} failed",
|
|
25
26
|
"action.expand": "Expand agent activity: {summary}",
|
|
@@ -30,6 +31,13 @@
|
|
|
30
31
|
"settings.collapse": "Collapse settings: {title}",
|
|
31
32
|
"settings.readOnly": "This settings source is read-only.",
|
|
32
33
|
"settings.writeFailed": "Could not save this setting.",
|
|
34
|
+
"settings.selectedMetrics": "Displayed metrics",
|
|
35
|
+
"settings.availableMetrics": "Available metrics",
|
|
36
|
+
"settings.emptySelection": "No metrics will be shown",
|
|
37
|
+
"settings.allSelected": "All metrics are displayed",
|
|
38
|
+
"settings.dragHint": "Drag to add, remove, or reorder. Click a tag to move it between lists.",
|
|
39
|
+
"settings.addMetric": "Add {label}",
|
|
40
|
+
"settings.removeMetric": "Remove {label}",
|
|
33
41
|
"settings.duration": "Elapsed time",
|
|
34
42
|
"settings.toolCalls": "Tool calls",
|
|
35
43
|
"settings.modelCalls": "Model calls",
|
package/locales/zh.json
CHANGED
|
@@ -15,11 +15,12 @@
|
|
|
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} 段思考",
|
|
20
|
+
"activityGroup.context.one": "{count} 次上下文注入",
|
|
21
|
+
"activityGroup.context.many": "{count} 次上下文注入",
|
|
19
22
|
"activityGroup.tools.one": "{count} 次工具调用",
|
|
20
23
|
"activityGroup.tools.many": "{count} 次工具调用",
|
|
21
|
-
"activityGroup.thinkAndTools.one": "Think · {count} 次工具调用",
|
|
22
|
-
"activityGroup.thinkAndTools.many": "Think · {count} 次工具调用",
|
|
23
24
|
"activityGroup.failures.one": "{count} 个失败",
|
|
24
25
|
"activityGroup.failures.many": "{count} 个失败",
|
|
25
26
|
"action.expand": "展开执行过程:{summary}",
|
|
@@ -30,6 +31,13 @@
|
|
|
30
31
|
"settings.collapse": "收起设置:{title}",
|
|
31
32
|
"settings.readOnly": "当前设置来源为只读。",
|
|
32
33
|
"settings.writeFailed": "无法保存此设置。",
|
|
34
|
+
"settings.selectedMetrics": "已显示指标",
|
|
35
|
+
"settings.availableMetrics": "可用指标",
|
|
36
|
+
"settings.emptySelection": "摘要栏将不显示任何指标",
|
|
37
|
+
"settings.allSelected": "所有指标均已显示",
|
|
38
|
+
"settings.dragHint": "拖动标签以添加、移除或排序;也可以点击标签在两组间移动。",
|
|
39
|
+
"settings.addMetric": "添加{label}",
|
|
40
|
+
"settings.removeMetric": "移除{label}",
|
|
33
41
|
"settings.duration": "工作耗时",
|
|
34
42
|
"settings.toolCalls": "工具调用次数",
|
|
35
43
|
"settings.modelCalls": "模型调用次数",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ch4acko3/dsh-turn-fold",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "Codex-style turn folding for the DSH WebUI conversation, implemented as a dsh-harmony provider.",
|
|
5
5
|
"main": "./index.cjs",
|
|
6
6
|
"engines": {
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"@deepseek-ai/dsh-client-ui-conversation": "0.1.0-rc.8",
|
|
62
62
|
"@deepseek-ai/dsh-settings": "0.1.0-rc.8",
|
|
63
63
|
"@phenomnomnominal/tsquery": "^6.2.0",
|
|
64
|
-
"dsh-harmony": "^0.7.
|
|
64
|
+
"dsh-harmony": "^0.7.2",
|
|
65
65
|
"react": "18.3.1",
|
|
66
66
|
"react-test-renderer": "18.3.1",
|
|
67
67
|
"typescript": "^6.0.3"
|
package/patch.cjs
CHANGED
|
@@ -27,6 +27,7 @@ const TARGET = {
|
|
|
27
27
|
module.exports = [
|
|
28
28
|
{
|
|
29
29
|
id: 'inject-turn-fold-runtime',
|
|
30
|
+
description: 'Provides the Turn Fold rendering, disclosure, metrics, settings, and locale runtime used by ChatView.',
|
|
30
31
|
target: TARGET,
|
|
31
32
|
select: 'FunctionDeclaration[name.name="ChatView"], VariableStatement:has(VariableDeclaration[name.name="ChatView"])',
|
|
32
33
|
expect: 1,
|
|
@@ -36,6 +37,7 @@ module.exports = [
|
|
|
36
37
|
},
|
|
37
38
|
{
|
|
38
39
|
id: 'rewrite-node-render-loop',
|
|
40
|
+
description: 'Routes ChatView node rendering through Turn Fold while preserving the native node renderer.',
|
|
39
41
|
target: TARGET,
|
|
40
42
|
select: 'CallExpression[expression.name.name="map"][expression.expression.name="order"]',
|
|
41
43
|
expect: 1,
|
|
@@ -52,6 +54,7 @@ module.exports = [
|
|
|
52
54
|
},
|
|
53
55
|
{
|
|
54
56
|
id: 'install-turn-fold-services',
|
|
57
|
+
description: 'Registers Turn Fold locales and connects its settings when the conversation UI starts.',
|
|
55
58
|
target: TARGET,
|
|
56
59
|
select: 'VariableStatement:has(VariableDeclaration[name.name="t"][initializer.expression.name.name="bind"])',
|
|
57
60
|
expect: 1,
|
package/settings.cjs
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const z = require('@deepseek-ai/schemastery')
|
|
4
|
-
|
|
5
3
|
const SETTINGS_NAMESPACE = 'dsh-turn-fold'
|
|
6
4
|
|
|
7
5
|
const SUMMARY_FIELDS = [
|
|
@@ -24,12 +22,50 @@ const DEFAULT_SUMMARY_FIELDS = [
|
|
|
24
22
|
'outputTokens',
|
|
25
23
|
]
|
|
26
24
|
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
function decodeConfig(value) {
|
|
26
|
+
const source = value == null ? {} : value
|
|
27
|
+
if (typeof source !== 'object' || Array.isArray(source)) throw new TypeError('expected config to be an object')
|
|
28
|
+
const summaryFields = source.summaryFields === undefined ? DEFAULT_SUMMARY_FIELDS : source.summaryFields
|
|
29
|
+
if (!Array.isArray(summaryFields)) throw new TypeError('summaryFields must be an array')
|
|
30
|
+
for (const field of summaryFields) {
|
|
31
|
+
if (!SUMMARY_FIELDS.includes(field)) throw new TypeError(`unknown summary field: ${String(field)}`)
|
|
32
|
+
}
|
|
33
|
+
return { ...source, summaryFields: summaryFields.slice() }
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function Config(value) {
|
|
37
|
+
return decodeConfig(value)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
Object.defineProperty(Config, '~standard', {
|
|
41
|
+
value: {
|
|
42
|
+
version: 1,
|
|
43
|
+
vendor: '@ch4acko3/dsh-turn-fold',
|
|
44
|
+
validate(value) {
|
|
45
|
+
try {
|
|
46
|
+
return { value: decodeConfig(value) }
|
|
47
|
+
} catch (error) {
|
|
48
|
+
return { issues: [{ message: error instanceof Error ? error.message : String(error) }] }
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
},
|
|
29
52
|
})
|
|
30
53
|
|
|
54
|
+
let settingsSchema
|
|
55
|
+
function createSettingsSchema() {
|
|
56
|
+
if (settingsSchema !== undefined) return settingsSchema
|
|
57
|
+
// The Host loads CommonJS providers alongside the ESM settings graph. Defer
|
|
58
|
+
// Schemastery until that service is ready to avoid a Node 24 CJS/ESM race.
|
|
59
|
+
const z = require('@deepseek-ai/schemastery')
|
|
60
|
+
settingsSchema = z.object({
|
|
61
|
+
summaryFields: z.array(z.union(SUMMARY_FIELDS)).default(DEFAULT_SUMMARY_FIELDS),
|
|
62
|
+
})
|
|
63
|
+
return settingsSchema
|
|
64
|
+
}
|
|
65
|
+
|
|
31
66
|
module.exports = {
|
|
32
67
|
Config,
|
|
68
|
+
createSettingsSchema,
|
|
33
69
|
DEFAULT_SUMMARY_FIELDS,
|
|
34
70
|
SETTINGS_NAMESPACE,
|
|
35
71
|
SUMMARY_FIELDS,
|