dsh-session-conductor 0.0.0-stage → 1.0.9
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 +165 -2
- package/cordis.patch.yml +48 -0
- package/lib/apply.js +1361 -0
- package/lib/client-parts/apply.js +43 -0
- package/lib/client-parts/components/compaction.js +124 -0
- package/lib/client-parts/components/conductor-settings.js +62 -0
- package/lib/client-parts/components/group.js +115 -0
- package/lib/client-parts/components/panel.js +1265 -0
- package/lib/client-parts/components/processing.js +98 -0
- package/lib/client-parts/components/session-icon.js +20 -0
- package/lib/client-parts/components/settings.js +415 -0
- package/lib/client-parts/foundation/bootstrap.js +48 -0
- package/lib/client-parts/foundation/i18n.js +74 -0
- package/lib/client-parts/foundation/list-cache.js +28 -0
- package/lib/client-parts/foundation/styles.js +236 -0
- package/lib/client.js +2534 -0
- package/lib/core/config.js +159 -0
- package/lib/core/domain.js +157 -0
- package/lib/core/lazy.js +20 -0
- package/lib/core/state.js +106 -0
- package/lib/core.js +82 -0
- package/lib/eio-repair.js +204 -0
- package/lib/features/context-usage/index.js +219 -0
- package/lib/features/continue/eligibility.js +49 -0
- package/lib/features/continue/scan.js +134 -0
- package/lib/features/continue/session.js +235 -0
- package/lib/features/inject/preset.js +20 -0
- package/lib/features/member-model/index.js +14 -0
- package/lib/features/member-model/locate.js +157 -0
- package/lib/features/member-model/override.js +76 -0
- package/lib/features/member-model/setup.js +55 -0
- package/lib/features/member-model/switch.js +186 -0
- package/lib/features/rename/analysis.js +303 -0
- package/lib/features/rename/title.js +158 -0
- package/lib/features/rename/value.js +77 -0
- package/lib/features/search.js +119 -0
- package/lib/features/session-ops-routes.js +218 -0
- package/lib/features/session-ops.js +414 -0
- package/lib/group.js +303 -0
- package/lib/guards.js +28 -0
- package/lib/http.js +24 -0
- package/lib/i18n/en.json +204 -0
- package/lib/i18n/zh.json +204 -0
- package/lib/index.js +78 -0
- package/lib/repair.js +398 -0
- package/lib/seq-gap-repair.js +224 -0
- package/lib/session-codec.js +37 -0
- package/lib/session-log.js +46 -0
- package/lib/sessions/detach.js +113 -0
- package/lib/sessions/events.js +73 -0
- package/lib/sessions/interruption.js +73 -0
- package/lib/sessions/list-cache.js +175 -0
- package/lib/sessions/list.js +187 -0
- package/lib/sessions/route.js +60 -0
- package/lib/sessions/turn.js +21 -0
- package/lib/shared/constants.js +20 -0
- package/lib/shared/log.js +17 -0
- package/lib/shared/settings.js +14 -0
- package/lib/shared/test-hooks.js +93 -0
- package/lib/shared/util.js +6 -0
- package/lib/template-inject.js +289 -0
- package/lib/value.js +430 -0
- package/lib/zstd-frames.js +177 -0
- package/package.json +65 -3
- package/skills/dsh-session-conductor-functions.md +197 -0
- package/skills/dsh-session-conductor.md +151 -0
- package/skills/dsh-session-official-doc.md +245 -0
- package/skills/task-completion-report.md +56 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
function apply(ctx) {
|
|
2
|
+
// 插槽排序(slots 顺序权重,小在前):设置左侧栏「会话管理」页 vs 侧边栏底部入口
|
|
3
|
+
const SETTINGS_SECTION_ORDER = 40;
|
|
4
|
+
const SIDEBAR_ACTION_ORDER = 90;
|
|
5
|
+
ctx.effect(() => ctx.locale.register(NS, { zh, en }), "session-conductor: dictionaries");
|
|
6
|
+
const slots = ctx.get("slots");
|
|
7
|
+
if (slots !== undefined) {
|
|
8
|
+
slots.inject("settings.section", () => slots.register(
|
|
9
|
+
{ name: "settings.section", id: "session-conductor", order: SETTINGS_SECTION_ORDER, label: () => trSettings("settings.nav") },
|
|
10
|
+
() => h(ConductorSettingsPage, null),
|
|
11
|
+
));
|
|
12
|
+
}
|
|
13
|
+
ctx.slots.inject("sidebar.footer.action", () => ctx.slots.register({
|
|
14
|
+
name: "sidebar.footer.action",
|
|
15
|
+
id: "session-conductor",
|
|
16
|
+
order: SIDEBAR_ACTION_ORDER,
|
|
17
|
+
locale: NS,
|
|
18
|
+
inject: () => ({
|
|
19
|
+
onOpenSession: (sessionId) => {
|
|
20
|
+
try {
|
|
21
|
+
ctx.get("sessions")?.open?.(sessionId);
|
|
22
|
+
} catch {
|
|
23
|
+
// 打开失败不阻塞面板
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
}),
|
|
27
|
+
}, SessionManagerPanel));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
exports.apply = apply;
|
|
31
|
+
exports.inject = inject;
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* dsh-session-conductor — 「会话分组」精简卡(裁剪后版本)
|
|
36
|
+
*
|
|
37
|
+
* 分组管理(创建/重命名/删除/移动会话)已移除,回归 DSH 官方 workspace 机制。
|
|
38
|
+
* 本卡只保留:
|
|
39
|
+
* · 分组列表(GET /api/session-conductor/group/list,只读展示)
|
|
40
|
+
* · 每行「在分组下新建会话」(POST /api/session-conductor/group/new-session {workspaceId})
|
|
41
|
+
* · 「新建会话(上次会话工作区)」(new-session 不带 workspaceId = 最近活跃会话 cwd 归属分组)
|
|
42
|
+
*/
|
|
43
|
+
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
window.__ModuleLoader__.load({
|
|
2
|
+
id: "dsh-session-conductor-compaction-model",
|
|
3
|
+
factory: (require) => {
|
|
4
|
+
var module = { exports: {} };
|
|
5
|
+
var exports = module.exports;
|
|
6
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
7
|
+
let react = require("react");
|
|
8
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
9
|
+
|
|
10
|
+
const NS = "sessionConductorCompaction";
|
|
11
|
+
const zh = {};
|
|
12
|
+
const en = {};
|
|
13
|
+
__scFillI18nDict("sessionConductorCompaction", zh, en);
|
|
14
|
+
|
|
15
|
+
/** 自定义模式下 provider / model 输入框宽度(px)。 */
|
|
16
|
+
const PROVIDER_INPUT_WIDTH = 110;
|
|
17
|
+
const MODEL_INPUT_WIDTH = 160;
|
|
18
|
+
|
|
19
|
+
const css = `
|
|
20
|
+
.cm_card { border:1px solid var(--dsw-alias-border-l1,rgba(128,128,128,.2)); border-radius:10px; padding:12px; margin-top:8px; background:var(--dsw-alias-bg-base,#141518); }
|
|
21
|
+
.cm_hint { color:var(--dsw-alias-label-tertiary,#888); font-size:12px; margin:2px 0 10px; line-height:1.5; }
|
|
22
|
+
.cm_row { display:flex; gap:8px; align-items:center; margin-bottom:8px; flex-wrap:wrap; }
|
|
23
|
+
.cm_input { height:28px; border-radius:6px; border:1px solid var(--dsw-alias-border-l2,rgba(128,128,128,.3)); background:var(--dsw-alias-bg-base,#141518); color:var(--dsw-alias-label-primary,#eee); padding:0 10px; font-size:12.5px; }
|
|
24
|
+
.cm_btn { height:28px; border-radius:6px; border:1px solid var(--dsw-alias-border-l2,rgba(128,128,128,.3)); background:var(--dsw-alias-interactive-bg-hover,rgba(128,128,128,.15)); color:var(--dsw-alias-label-primary,#eee); cursor:pointer; padding:0 14px; font-size:12.5px; }
|
|
25
|
+
.cm_btn:hover { background:rgba(128,128,128,.25); }
|
|
26
|
+
.cm_msg { font-size:12px; margin-top:6px; }
|
|
27
|
+
`;
|
|
28
|
+
const styleId = "sm-compaction-css";
|
|
29
|
+
if (typeof document !== "undefined" && !document.getElementById(styleId)) {
|
|
30
|
+
const s = document.createElement("style");
|
|
31
|
+
s.id = styleId;
|
|
32
|
+
s.textContent = css;
|
|
33
|
+
document.head.appendChild(s);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function CompactionModelCard({ t }) {
|
|
37
|
+
const [mode, setMode] = react.useState("follow"); // follow | custom
|
|
38
|
+
const [provider, setProvider] = react.useState("llm-pi-ai");
|
|
39
|
+
const [model, setModel] = react.useState("agnes-2.5-flash");
|
|
40
|
+
const [msg, setMsg] = react.useState(null);
|
|
41
|
+
const [busy, setBusy] = react.useState(false);
|
|
42
|
+
|
|
43
|
+
react.useEffect(() => {
|
|
44
|
+
(async () => {
|
|
45
|
+
try {
|
|
46
|
+
const r = await window.__scFetch("/api/session-conductor/compaction-model", { headers: { accept: "application/json" } });
|
|
47
|
+
const payload = await r.json();
|
|
48
|
+
if (payload?.ok && payload.compactionModel) {
|
|
49
|
+
setMode("custom");
|
|
50
|
+
setProvider(payload.compactionModel.provider || "");
|
|
51
|
+
setModel(payload.compactionModel.model || "");
|
|
52
|
+
} else if (payload?.ok) setMode("follow");
|
|
53
|
+
} catch { /* 初始加载失败忽略 */ }
|
|
54
|
+
})();
|
|
55
|
+
}, []);
|
|
56
|
+
|
|
57
|
+
const save = async () => {
|
|
58
|
+
setBusy(true); setMsg(null);
|
|
59
|
+
try {
|
|
60
|
+
const body = mode === "follow"
|
|
61
|
+
? { follow: true }
|
|
62
|
+
: { provider, model };
|
|
63
|
+
const r = await window.__scFetch("/api/session-conductor/compaction-model", {
|
|
64
|
+
method: "POST",
|
|
65
|
+
headers: { "Content-Type": "application/json" },
|
|
66
|
+
body: JSON.stringify(body),
|
|
67
|
+
});
|
|
68
|
+
const payload = await r.json();
|
|
69
|
+
setMsg(payload?.ok ? t("saved") : (payload?.error?.message || t("error")));
|
|
70
|
+
} catch { setMsg(t("error")); }
|
|
71
|
+
setBusy(false);
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
return react_jsx_runtime.jsxs("div", { className: "cm_card", children: [
|
|
75
|
+
react_jsx_runtime.jsx("div", { className: "cm_hint", children: t("desc") }),
|
|
76
|
+
react_jsx_runtime.jsxs("div", { className: "cm_row", children: [
|
|
77
|
+
react_jsx_runtime.jsx("label", { children: react_jsx_runtime.jsx("input", { type: "radio", name: "cm-mode", checked: mode === "follow", onChange: () => setMode("follow") }) }),
|
|
78
|
+
react_jsx_runtime.jsx("span", { children: t("follow") }),
|
|
79
|
+
react_jsx_runtime.jsx("label", { children: react_jsx_runtime.jsx("input", { type: "radio", name: "cm-mode", checked: mode === "custom", onChange: () => setMode("custom") }) }),
|
|
80
|
+
react_jsx_runtime.jsx("span", { children: t("custom") }),
|
|
81
|
+
]}),
|
|
82
|
+
mode === "custom" && react_jsx_runtime.jsxs("div", { className: "cm_row", children: [
|
|
83
|
+
react_jsx_runtime.jsx("span", { children: t("provider") }),
|
|
84
|
+
react_jsx_runtime.jsx("input", { className: "cm_input", value: provider, onChange: (e) => setProvider(e.target.value), style: { width: PROVIDER_INPUT_WIDTH } }),
|
|
85
|
+
react_jsx_runtime.jsx("span", { children: t("model") }),
|
|
86
|
+
react_jsx_runtime.jsx("input", { className: "cm_input", value: model, onChange: (e) => setModel(e.target.value), style: { width: MODEL_INPUT_WIDTH } }),
|
|
87
|
+
]}),
|
|
88
|
+
mode === "follow" && react_jsx_runtime.jsx("div", { className: "cm_hint", children: t("followNote") }),
|
|
89
|
+
react_jsx_runtime.jsxs("div", { className: "cm_row", children: [
|
|
90
|
+
react_jsx_runtime.jsx("button", { className: "cm_btn", disabled: busy, onClick: save, children: t("save") }),
|
|
91
|
+
msg && react_jsx_runtime.jsx("span", { className: "cm_msg", children: msg }),
|
|
92
|
+
]}),
|
|
93
|
+
]});
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function apply(ctx) {
|
|
97
|
+
ctx.effect(() => ctx.locale.register(NS, { zh, en }), "dsh-session-conductor-compaction-model: dictionaries");
|
|
98
|
+
ctx.slots.inject("settings.plugin.item", () => ctx.slots.register({
|
|
99
|
+
name: "settings.plugin.item",
|
|
100
|
+
key: "session-conductor-compaction",
|
|
101
|
+
locale: NS,
|
|
102
|
+
}, function WrappedCard(props) {
|
|
103
|
+
const t = ctx.locale.bind(NS);
|
|
104
|
+
return react_jsx_runtime.jsxs("div", { children: [
|
|
105
|
+
react_jsx_runtime.jsx("div", { children: t("title") }),
|
|
106
|
+
react_jsx_runtime.jsx(CompactionModelCard, { t }),
|
|
107
|
+
] });
|
|
108
|
+
}));
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const inject = ["slots", "locale"];
|
|
112
|
+
exports.apply = apply;
|
|
113
|
+
exports.inject = inject;
|
|
114
|
+
return module.exports;
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
/**
|
|
118
|
+
* dsh-session-conductor — 「会话管理」设置侧边栏页( 新增)
|
|
119
|
+
*
|
|
120
|
+
* 注册 settings.section 侧边栏导航(设置左栏出现「会话管理」条目),
|
|
121
|
+
* 点开是完整聚合页——会话管理说明 + 模板注入。
|
|
122
|
+
* UI 组件 scs_* = 页面级。
|
|
123
|
+
*/
|
|
124
|
+
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
window.__ModuleLoader__.load({
|
|
2
|
+
id: "dsh-session-conductor-settings",
|
|
3
|
+
factory: (require) => {
|
|
4
|
+
var module = { exports: {} };
|
|
5
|
+
var exports = module.exports;
|
|
6
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
7
|
+
|
|
8
|
+
let react = require("react");
|
|
9
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
10
|
+
|
|
11
|
+
const NS = "sessionConductorSettings";
|
|
12
|
+
const zh = {};
|
|
13
|
+
const en = {};
|
|
14
|
+
__scFillI18nDict("sessionConductorSettings", zh, en);
|
|
15
|
+
|
|
16
|
+
const css = `
|
|
17
|
+
.scs_page { display:flex; flex-direction:column; gap:16px; }
|
|
18
|
+
.scs_hero { display:flex; flex-direction:column; gap:6px; }
|
|
19
|
+
.scs_title { font-size:20px; font-weight:650; color:var(--dsw-alias-label-primary); }
|
|
20
|
+
.scs_desc { font-size:13px; line-height:1.6; color:var(--dsw-alias-label-tertiary); max-width:72ch; }
|
|
21
|
+
.scs_hint { font-size:11px; line-height:16px; color:var(--dsw-alias-label-tertiary); }
|
|
22
|
+
.scs_card { display:flex; flex-direction:column; gap:12px; padding:16px; border:.5px solid var(--dsw-alias-border-l4); border-radius:16px; background:var(--dsw-alias-bg-layer-3); }
|
|
23
|
+
.scs_cardtitle { font-size:15px; font-weight:600; color:var(--dsw-alias-label-primary); }
|
|
24
|
+
.scs_note { font-size:12px; line-height:1.7; color:var(--dsw-alias-label-secondary); padding:10px 12px; border:1px dashed var(--dsw-alias-border-l2); border-radius:10px; }
|
|
25
|
+
`;
|
|
26
|
+
const styleId = "scs-css";
|
|
27
|
+
if (typeof document !== "undefined" && !document.getElementById(styleId)) {
|
|
28
|
+
const s = document.createElement("style");
|
|
29
|
+
s.id = styleId;
|
|
30
|
+
s.textContent = css;
|
|
31
|
+
document.head.appendChild(s);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
// ── 设置侧边栏页(settings.section,仿 skill-scoreboard)───────────────
|
|
37
|
+
function ScsPage({ t }) {
|
|
38
|
+
return react_jsx_runtime.jsxs("div", { className: "scs_page", children: [
|
|
39
|
+
react_jsx_runtime.jsxs("div", { className: "scs_hero", children: [
|
|
40
|
+
react_jsx_runtime.jsx("div", { className: "scs_title", children: t("title") }),
|
|
41
|
+
react_jsx_runtime.jsx("div", { className: "scs_desc", children: t("desc") }),
|
|
42
|
+
react_jsx_runtime.jsx("div", { className: "scs_hint", children: t("scopeHint") }),
|
|
43
|
+
] }),
|
|
44
|
+
react_jsx_runtime.jsxs("div", { className: "scs_note", children: [
|
|
45
|
+
react_jsx_runtime.jsx("b", { children: t("noteTitle") + ":" }),
|
|
46
|
+
t("noteBody"),
|
|
47
|
+
] }),
|
|
48
|
+
] });
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function apply(ctx) {
|
|
52
|
+
// 设置页只在主入口 dsh-session-conductor 注册。这里再挂 settings.section
|
|
53
|
+
// 会用 jsx-runtime 把页面打成空白。
|
|
54
|
+
ctx.effect(() => ctx.locale.register(NS, { zh, en }), "session-conductor-settings: dictionaries");
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const inject = ["slots", "locale"];
|
|
58
|
+
exports.apply = apply;
|
|
59
|
+
exports.inject = inject;
|
|
60
|
+
return module.exports;
|
|
61
|
+
},
|
|
62
|
+
});
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
window.__ModuleLoader__.load({
|
|
2
|
+
id: "dsh-session-conductor-group",
|
|
3
|
+
factory: (require) => {
|
|
4
|
+
var module = { exports: {} };
|
|
5
|
+
var exports = module.exports;
|
|
6
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
7
|
+
|
|
8
|
+
let react = require("react");
|
|
9
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
10
|
+
|
|
11
|
+
const NS = "sessionGroup";
|
|
12
|
+
const zh = {};
|
|
13
|
+
const en = {};
|
|
14
|
+
__scFillI18nDict("sessionGroup", zh, en);
|
|
15
|
+
|
|
16
|
+
const css = `
|
|
17
|
+
.sg2_card { display:flex; flex-direction:column; gap:10px; }
|
|
18
|
+
.sg2_row { display:flex; align-items:center; gap:8px; flex-wrap:wrap; }
|
|
19
|
+
.sg2_btn { cursor:pointer; border:1px solid var(--dsw-alias-border-l1, rgba(128,128,128,.35)); background:var(--dsw-specific-tip, transparent); color:var(--dsw-alias-label-secondary, inherit); border-radius:8px; height:28px; padding:0 12px; font-size:12px; line-height:26px; display:inline-flex; align-items:center; gap:4px; white-space:nowrap; }
|
|
20
|
+
.sg2_btn:hover { background:var(--dsw-alias-interactive-bg-hover, rgba(128,128,128,.15)); }
|
|
21
|
+
.sg2_btn:disabled { opacity:.45; cursor:default; }
|
|
22
|
+
.sg2_hint { color:var(--dsw-alias-label-tertiary, #888); font-size:11px; line-height:16px; }
|
|
23
|
+
.sg2_listTitle { font-size:12px; color:var(--dsw-alias-label-secondary, inherit); margin-top:4px; }
|
|
24
|
+
.sg2_item { display:flex; align-items:center; gap:8px; padding:6px 8px; border-radius:8px; font-size:12px; border:1px solid var(--dsw-alias-border-l1, rgba(128,128,128,.2)); }
|
|
25
|
+
.sg2_item .sg2_name { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
|
|
26
|
+
.sg2_item .sg2_meta { color:var(--dsw-alias-label-tertiary, #888); font-size:11px; flex:none; }
|
|
27
|
+
.sg2_msg { font-size:12px; line-height:18px; }
|
|
28
|
+
.sg2_msg.err { color:var(--dsw-state-error-primary, #d9534f); }
|
|
29
|
+
.sg2_msg.ok { color:var(--dsw-state-success-primary, #4caf50); }
|
|
30
|
+
`;
|
|
31
|
+
const styleId = "dsh-session-group-css";
|
|
32
|
+
if (typeof document !== "undefined" && !document.getElementById(styleId)) {
|
|
33
|
+
const s = document.createElement("style");
|
|
34
|
+
s.id = styleId;
|
|
35
|
+
s.textContent = css;
|
|
36
|
+
document.head.appendChild(s);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function SessionGroupCard({ t }) {
|
|
40
|
+
const [workspaces, setWorkspaces] = react.useState(null);
|
|
41
|
+
const [busy, setBusy] = react.useState(false);
|
|
42
|
+
const [msg, setMsg] = react.useState(null);
|
|
43
|
+
const load = () => {
|
|
44
|
+
window.__scFetch("/api/session-conductor/group/list").then((r) => r.json()).then((b) => {
|
|
45
|
+
if (b.ok) setWorkspaces(b.workspaces ?? []);
|
|
46
|
+
}).catch(() => setWorkspaces([]));
|
|
47
|
+
};
|
|
48
|
+
react.useEffect(() => { load(); }, []);
|
|
49
|
+
const createIn = async (workspaceId) => {
|
|
50
|
+
if (busy) return;
|
|
51
|
+
setBusy(true); setMsg(null);
|
|
52
|
+
try {
|
|
53
|
+
const r = await window.__scFetch("/api/session-conductor/group/new-session", {
|
|
54
|
+
method: "POST",
|
|
55
|
+
headers: { "Content-Type": "application/json" },
|
|
56
|
+
body: JSON.stringify(workspaceId ? { workspaceId } : {}),
|
|
57
|
+
});
|
|
58
|
+
const b = await r.json();
|
|
59
|
+
if (!b.ok) throw new Error(b.error || ("HTTP " + r.status));
|
|
60
|
+
setMsg({ kind: "ok", text: t("ok") });
|
|
61
|
+
load();
|
|
62
|
+
} catch (e) {
|
|
63
|
+
setMsg({ kind: "err", text: t("fail", { message: (e && e.message) || String(e) }) });
|
|
64
|
+
} finally { setBusy(false); }
|
|
65
|
+
};
|
|
66
|
+
return react_jsx_runtime.jsxs("div", { className: "sg2_card", children: [
|
|
67
|
+
react_jsx_runtime.jsx("div", { className: "sg2_hint", children: t("desc") }),
|
|
68
|
+
react_jsx_runtime.jsxs("div", { className: "sg2_row", children: [
|
|
69
|
+
react_jsx_runtime.jsx("button", { className: "sg2_btn", disabled: busy, onClick: () => createIn(""), children: busy ? t("busy") : t("newDefault") }),
|
|
70
|
+
react_jsx_runtime.jsx("button", { className: "sg2_btn", disabled: busy, onClick: load, children: t("refresh") }),
|
|
71
|
+
] }),
|
|
72
|
+
react_jsx_runtime.jsx("div", { className: "sg2_listTitle", children: t("listTitle") }),
|
|
73
|
+
!workspaces
|
|
74
|
+
? react_jsx_runtime.jsx("div", { className: "sg2_hint", children: t("listEmpty") })
|
|
75
|
+
: workspaces.map((w) => react_jsx_runtime.jsxs("div", { className: "sg2_item", key: w.workspaceId, children: [
|
|
76
|
+
react_jsx_runtime.jsx("span", { className: "sg2_name", children: w.title || w.path }),
|
|
77
|
+
react_jsx_runtime.jsx("span", { className: "sg2_meta", children: __SC_TR__("sessionCount", { n: w.sessionIds?.length ?? 0 }) }),
|
|
78
|
+
react_jsx_runtime.jsx("button", { className: "sg2_btn", disabled: busy, onClick: () => createIn(w.workspaceId), children: busy ? t("busy") : t("newIn") }),
|
|
79
|
+
] })),
|
|
80
|
+
msg && react_jsx_runtime.jsx("div", { className: "sg2_msg " + (msg.kind === "err" ? "err" : "ok"), children: msg.text }),
|
|
81
|
+
] });
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function apply(ctx) {
|
|
85
|
+
ctx.effect(() => ctx.locale.register(NS, { zh, en }), "dsh-session-group: dictionaries");
|
|
86
|
+
ctx.slots.inject("settings.plugin.item", () => ctx.slots.register({
|
|
87
|
+
name: "settings.plugin.item",
|
|
88
|
+
key: "session-conductor-group",
|
|
89
|
+
locale: NS,
|
|
90
|
+
}, function WrappedCard(props) {
|
|
91
|
+
const t = ctx.locale.bind(NS);
|
|
92
|
+
return react_jsx_runtime.jsxs("div", { children: [
|
|
93
|
+
react_jsx_runtime.jsx("div", { children: t("title") }),
|
|
94
|
+
react_jsx_runtime.jsx(SessionGroupCard, { t }),
|
|
95
|
+
] });
|
|
96
|
+
}));
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const inject = ["slots", "locale"];
|
|
100
|
+
exports.apply = apply;
|
|
101
|
+
exports.inject = inject;
|
|
102
|
+
return module.exports;
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* dsh-session-conductor — 「第一条正在处理」队列条目(client 附加模块, 改写)
|
|
108
|
+
*
|
|
109
|
+
* DSH 原生排队逻辑:第一条消息(claimed)立即执行、从 host inbox 移除,因此
|
|
110
|
+
* 原生排队 dock 只显示「后续排队消息」,执行中的第一条不可见。
|
|
111
|
+
* 本模块在原生 dock 区域**上方**渲染一条与原生 QueueDock 同风格的条目:
|
|
112
|
+
* 「⚙️ {第一条消息摘要}」——第一条也显示在排队列表里,回合结束(执行完)自动消失。
|
|
113
|
+
* 排队消息列表仍由原生 dock 负责(不重复渲染)。不改 DSH 原生源码。
|
|
114
|
+
*/
|
|
115
|
+
|