dsh-plugin-t-expert 0.3.26 → 0.3.39
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/lib/client.js +267 -23
- package/lib/index.js +12 -1
- package/lib/remote-schemas.js +3 -0
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -19874,11 +19874,14 @@ var enabledStateSchema = external_exports.object({
|
|
|
19874
19874
|
});
|
|
19875
19875
|
var uiPrefsSchema = external_exports.object({
|
|
19876
19876
|
showTaskBadge: external_exports.boolean(),
|
|
19877
|
-
showScheduleButton: external_exports.boolean()
|
|
19877
|
+
showScheduleButton: external_exports.boolean(),
|
|
19878
|
+
// 窗口右上角「活跃指示」是否显示。宿主**总是**返回布尔(缺省按 true 算),所以这里必填。
|
|
19879
|
+
showActivePulse: external_exports.boolean()
|
|
19878
19880
|
});
|
|
19879
19881
|
var uiPrefsPatchSchema = external_exports.object({
|
|
19880
19882
|
showTaskBadge: external_exports.boolean().optional(),
|
|
19881
|
-
showScheduleButton: external_exports.boolean().optional()
|
|
19883
|
+
showScheduleButton: external_exports.boolean().optional(),
|
|
19884
|
+
showActivePulse: external_exports.boolean().optional()
|
|
19882
19885
|
});
|
|
19883
19886
|
var promptSchema = external_exports.object({ prompt: external_exports.string() });
|
|
19884
19887
|
var squadMemberSchema = external_exports.object({
|
|
@@ -20015,8 +20018,9 @@ var scheduleWorkspaceSchema = external_exports.object({
|
|
|
20015
20018
|
|
|
20016
20019
|
// src/client.jsx
|
|
20017
20020
|
var NS = "t-team";
|
|
20018
|
-
var CLIENT_BUILD_VERSION = "0.3.
|
|
20019
|
-
var uiPrefs = { showTaskBadge: true, showScheduleButton: true };
|
|
20021
|
+
var CLIENT_BUILD_VERSION = "0.3.39";
|
|
20022
|
+
var uiPrefs = { showTaskBadge: true, showScheduleButton: true, showActivePulse: true };
|
|
20023
|
+
var UI_PREF_KEYS = Object.keys(uiPrefs);
|
|
20020
20024
|
var uiPrefsListeners = /* @__PURE__ */ new Set();
|
|
20021
20025
|
function setUiPrefs(next) {
|
|
20022
20026
|
let changed = false;
|
|
@@ -20052,6 +20056,9 @@ function useShowTaskBadge() {
|
|
|
20052
20056
|
function useShowScheduleButton() {
|
|
20053
20057
|
return useUiPref("showScheduleButton", true);
|
|
20054
20058
|
}
|
|
20059
|
+
function useShowActivePulse() {
|
|
20060
|
+
return useUiPref("showActivePulse", true);
|
|
20061
|
+
}
|
|
20055
20062
|
var PLUGIN_ID = "dsh-plugin-t-expert";
|
|
20056
20063
|
var DIVISION_FALLBACK = "specialized";
|
|
20057
20064
|
var NEW_DIVISION = "__new";
|
|
@@ -20060,6 +20067,15 @@ var zh = {
|
|
|
20060
20067
|
"settings.showTaskBadge": "\u663E\u793A\u4EFB\u52A1\u5FBD\u7AE0",
|
|
20061
20068
|
"settings.showTaskBadgeHint": "\u5173\u95ED\u540E\u4E0D\u518D\u81EA\u52A8\u51FA\u73B0\u53F3\u4E0A\u89D2\u7684\u4EFB\u52A1\u5FBD\u7AE0\uFF08\u8F93\u5165\u533A\u6D6E\u5C42\u91CC\u7684\u300C\u4EFB\u52A1\u300D\u9875\u4ECD\u7136\u53EF\u7528\uFF09",
|
|
20062
20069
|
"settings.showTaskBadgeUnreadable": "\u8BFB\u53D6\u8BE5\u8BBE\u7F6E\u5931\u8D25",
|
|
20070
|
+
"settings.uiPrefsWriteFailed": "\u4FDD\u5B58\u8BE5\u8BBE\u7F6E\u5931\u8D25",
|
|
20071
|
+
"settings.showActivePulse": "\u663E\u793A\u6D3B\u8DC3\u6307\u793A",
|
|
20072
|
+
"settings.showActivePulseHint": "\u4F1A\u8BDD\u6807\u9898\u680F\u91CC\u90A3\u679A\u5FC3\u7535\u56FE\u56FE\u6807\uFF1A\u6709\u4F1A\u8BDD\u6B63\u5728\u8DD1\u3001\u6216\u6709\u4E8B\u7B49\u4F60\u67E5\u770B\u65F6\u663E\u793A\u5F69\u8272\uFF0C\u5168\u90E8\u7A7A\u95F2\u4E14\u65E0\u5F85\u770B\u65F6\u663E\u793A\u7070\u8272\u3002\u70B9\u5B83\u53EF\u4EE5\u5217\u51FA\u9700\u8981\u6CE8\u610F\u7684\u4F1A\u8BDD\uFF0C\u70B9\u5176\u4E2D\u4E00\u6761\u5C31\u76F4\u63A5\u63A5\u4E0A\u90A3\u4E2A\u4F1A\u8BDD",
|
|
20073
|
+
"pulse.on": "\u6709\u4F1A\u8BDD\u6B63\u5728\u6D3B\u52A8\uFF0C\u6216\u6709\u4E8B\u7B49\u4F60\u67E5\u770B",
|
|
20074
|
+
"pulse.off": "\u5168\u90E8\u7A7A\u95F2\uFF0C\u4E14\u6CA1\u6709\u5F85\u4F60\u67E5\u770B\u7684",
|
|
20075
|
+
"pulse.title": "\u9700\u8981\u6CE8\u610F\u7684\u4F1A\u8BDD",
|
|
20076
|
+
"pulse.empty": "\u73B0\u5728\u6CA1\u6709\u9700\u8981\u6CE8\u610F\u7684\u4F1A\u8BDD",
|
|
20077
|
+
"pulse.running": "\u8FD0\u884C\u4E2D",
|
|
20078
|
+
"pulse.pending": "\u5F85\u67E5\u770B",
|
|
20063
20079
|
"settings.loading": "\u6B63\u5728\u8BFB\u53D6\u540D\u518C\u2026",
|
|
20064
20080
|
"settings.retry": "\u91CD\u8BD5",
|
|
20065
20081
|
"settings.search": "\u641C\u7D22\u4E13\u5BB6\u540D\u6216\u7B80\u4ECB",
|
|
@@ -20330,7 +20346,16 @@ var en = {
|
|
|
20330
20346
|
"settings.title": "T Expert",
|
|
20331
20347
|
"settings.showTaskBadge": "Show task badge",
|
|
20332
20348
|
"settings.showTaskBadgeHint": "When off, the top-right task badge no longer appears (the Tasks tab in the input floater still works)",
|
|
20349
|
+
"settings.showActivePulse": "Show activity indicator",
|
|
20350
|
+
"settings.showActivePulseHint": "The ECG icon in the session header: coloured when a session is running or something awaits your review, grey when everything is idle. Click it to list the sessions that need attention and jump straight into one",
|
|
20351
|
+
"pulse.on": "A session is running, or something awaits your review",
|
|
20352
|
+
"pulse.off": "Everything is idle and nothing awaits you",
|
|
20353
|
+
"pulse.title": "Sessions needing attention",
|
|
20354
|
+
"pulse.empty": "Nothing needs your attention right now",
|
|
20355
|
+
"pulse.running": "Running",
|
|
20356
|
+
"pulse.pending": "Unread",
|
|
20333
20357
|
"settings.showTaskBadgeUnreadable": "Failed to read this setting",
|
|
20358
|
+
"settings.uiPrefsWriteFailed": "Failed to save this setting",
|
|
20334
20359
|
"settings.loading": "Loading roster\u2026",
|
|
20335
20360
|
"settings.retry": "Retry",
|
|
20336
20361
|
"settings.search": "Search expert name or description",
|
|
@@ -20664,6 +20689,28 @@ var CSS = `
|
|
|
20664
20689
|
.t-team-badge{font-size:11px;border-radius:999px;padding:1px 8px;background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-secondary)}
|
|
20665
20690
|
.t-team-badge[data-tone="warn"]{color:var(--dsw-alias-state-warn-primary)}
|
|
20666
20691
|
.t-team-badge[data-tone="error"]{color:var(--dsw-alias-state-error-primary)}
|
|
20692
|
+
/* \u6D3B\u8DC3\u6307\u793A\uFF1A\u4F1A\u8BDD\u6807\u9898\u680F\u91CC\u7684\u4E00\u679A\u5FC3\u7535\u56FE\u56FE\u6807 \u2014\u2014 \u7D27\u8D34 agent preset \u80F6\u56CA\u5DE6\u4FA7\uFF08order \u6BD4\u5B83\u5C0F\uFF09\u3002
|
|
20693
|
+
\u5F69\u8272 = \u6709\u6D3B\u52A8\u6216\u6709\u5F85\u770B\uFF0C\u7070 = \u5168\u7A7A\u95F2\u3002pointer-events:none\uFF1A\u5B83\u53EA\u662F\u6307\u793A\uFF0C\u4E0D\u8BE5\u6321\u4F4F\u70B9\u51FB\u3002 */
|
|
20694
|
+
.t-team-pulse{display:inline-flex;align-items:center;justify-content:center;flex:none;width:24px;height:24px;margin-right:2px;padding:0;border:0;font:inherit;border-radius:7px;cursor:pointer;color:var(--dsw-alias-state-success-primary);background:color-mix(in srgb,var(--dsw-alias-state-success-primary) 14%,transparent)}
|
|
20695
|
+
.t-team-pulse[data-on="false"]{color:var(--dsw-alias-label-caption);background:color-mix(in srgb,var(--dsw-alias-label-caption) 12%,transparent)}
|
|
20696
|
+
.t-team-pulse:hover{background:color-mix(in srgb,var(--dsw-alias-label-primary) 12%,transparent)}
|
|
20697
|
+
/* \u70B9\u5FBD\u7AE0\u5F39\u51FA\u7684\u300C\u9700\u8981\u6CE8\u610F\u7684\u4F1A\u8BDD\u300D\u6E05\u5355\uFF1A\u8D34\u5FBD\u7AE0\u53F3\u7F18\u3001\u56FE\u6807\u4E0B\u65B9\u3002 */
|
|
20698
|
+
.t-team-pulse-pop{position:fixed;z-index:70;width:300px;max-height:min(420px,60vh);overflow:auto;box-sizing:border-box;display:flex;flex-direction:column;gap:2px;padding:8px;border-radius:12px;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-specific-menu,var(--dsw-alias-bg-layer-3));box-shadow:var(--dsw-shadow-lv3);color:var(--dsw-alias-label-primary)}
|
|
20699
|
+
.t-team-pulse-pop-head{font-size:12px;font-weight:600;color:var(--dsw-alias-label-secondary);padding:4px 6px 6px}
|
|
20700
|
+
.t-team-pulse-pop-empty{font-size:12px;color:var(--dsw-alias-label-caption);padding:8px 6px}
|
|
20701
|
+
.t-team-pulse-pop-row{display:flex;align-items:center;gap:8px;width:100%;box-sizing:border-box;border:0;background:transparent;color:inherit;font:inherit;font-size:13px;text-align:left;padding:7px 8px;border-radius:8px;cursor:pointer}
|
|
20702
|
+
.t-team-pulse-pop-row:hover{background:var(--dsw-alias-interactive-bg-hover)}
|
|
20703
|
+
.t-team-pulse-pop-dot{flex:none;width:6px;height:6px;border-radius:50%;background:var(--dsw-alias-state-success-primary)}
|
|
20704
|
+
.t-team-pulse-pop-dot[data-state="pending"]{background:var(--dsw-alias-state-warn-primary)}
|
|
20705
|
+
.t-team-pulse-pop-title{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
20706
|
+
.t-team-pulse-pop-tag{flex:none;font-size:11px;color:var(--dsw-alias-label-caption)}
|
|
20707
|
+
/* \u6D3B\u52A8\u6001\u52A8\u6548\uFF1A\u4E00\u6BB5\u9AD8\u4EAE\u6CBF\u5FC3\u7535\u56FE\u8DEF\u5F84\u6EDA\u52A8\uFF08\u8D70\u7EB8\uFF0F\u76D1\u62A4\u4EEA\u626B\u8FC7\u90A3\u4E00\u4E0B\uFF09\uFF0C\u53EA\u5BF9\u6709\u6D3B\u52A8\u6216\u6709\u5F85\u770B\u65F6\u751F\u6548\uFF1B
|
|
20708
|
+
pathLength=100 \u8BA9\u8FD9\u91CC\u7684 100 \u5C31\u662F"\u6574\u6761\u8DEF\u5F84"\uFF0C\u4E0D\u5FC5\u77E5\u9053\u771F\u5B9E\u957F\u5EA6\u3002\u7A7A\u95F2\uFF08\u7070\uFF09\u65F6\u662F\u9759\u6B62\u5B9E\u7EBF\u3002
|
|
20709
|
+
\u53C2\u6570\uFF08\u7528\u6237 2026-09-15 \u8C03\u8FC7\u4E24\u8F6E\uFF09\uFF1A\u9AD8\u4EAE\u7EA6\u5360\u4E00\u534A\u8DEF\u5F84\u30011.2s \u8DD1\u5B8C\u4E00\u5708 \u2014\u2014 \u60F3\u518D\u8C03\u5C31\u6539\u8FD9\u4E24\u4E2A\u6570\u3002
|
|
20710
|
+
\u6CE8\u610F\u522B\u628A\u9AD8\u4EAE\u8C03\u5230\u63A5\u8FD1 100\uFF1A\u6697\u6BB5\u592A\u77ED\u5C31\u770B\u4E0D\u51FA"\u5728\u6EDA\u52A8"\u4E86\u3002 */
|
|
20711
|
+
@keyframes t-team-pulse-scan{from{stroke-dashoffset:100}to{stroke-dashoffset:0}}
|
|
20712
|
+
.t-team-pulse[data-on="true"] path{stroke-dasharray:48 52;animation:t-team-pulse-scan 1.2s linear infinite}
|
|
20713
|
+
@media (prefers-reduced-motion:reduce){.t-team-pulse[data-on="true"] path{animation:none;stroke-dasharray:none}}
|
|
20667
20714
|
.t-team-team-meta{font-size:12px;color:var(--dsw-alias-label-caption);display:flex;gap:10px;flex-wrap:wrap}
|
|
20668
20715
|
.t-team-note{font-size:12px;color:var(--dsw-alias-label-caption)}
|
|
20669
20716
|
.t-team-ok{font-size:12px;color:var(--dsw-alias-state-success-primary)}
|
|
@@ -21872,6 +21919,163 @@ function ScheduleGlyph({ size = 16 }) {
|
|
|
21872
21919
|
/* @__PURE__ */ import_react.default.createElement("path", { d: "M6.1 9.7l1.3 1.3 2.5-2.7" })
|
|
21873
21920
|
);
|
|
21874
21921
|
}
|
|
21922
|
+
var attentionCache = { key: "", list: [] };
|
|
21923
|
+
function useAttentionSessions(ctx) {
|
|
21924
|
+
const subscribe = import_react.default.useCallback((onChange) => {
|
|
21925
|
+
const list = ctx?.sessions?.list;
|
|
21926
|
+
if (typeof list?.subscribe !== "function") return () => {
|
|
21927
|
+
};
|
|
21928
|
+
return list.subscribe(onChange);
|
|
21929
|
+
}, [ctx]);
|
|
21930
|
+
const read = import_react.default.useCallback(() => {
|
|
21931
|
+
const byId = ctx?.sessions?.list?.getSnapshot?.()?.byId ?? {};
|
|
21932
|
+
const runningSubagents = /* @__PURE__ */ new Map();
|
|
21933
|
+
for (const id of Object.keys(byId)) {
|
|
21934
|
+
const child = byId[id];
|
|
21935
|
+
if (child?.origin !== "subagent" || child.running !== true) continue;
|
|
21936
|
+
const seen = /* @__PURE__ */ new Set();
|
|
21937
|
+
let parent = child.parentId;
|
|
21938
|
+
while (typeof parent === "string" && parent !== "" && !seen.has(parent)) {
|
|
21939
|
+
seen.add(parent);
|
|
21940
|
+
runningSubagents.set(parent, (runningSubagents.get(parent) ?? 0) + 1);
|
|
21941
|
+
parent = byId[parent]?.parentId;
|
|
21942
|
+
}
|
|
21943
|
+
}
|
|
21944
|
+
const rows = [];
|
|
21945
|
+
for (const id of Object.keys(byId)) {
|
|
21946
|
+
const session = byId[id];
|
|
21947
|
+
if (session === void 0 || session === null) continue;
|
|
21948
|
+
if (session.origin === "subagent" || session.blank === true) continue;
|
|
21949
|
+
const running = session.running === true || (runningSubagents.get(id) ?? 0) > 0;
|
|
21950
|
+
const pending = session.completed === true;
|
|
21951
|
+
if (!running && !pending) continue;
|
|
21952
|
+
rows.push({
|
|
21953
|
+
id,
|
|
21954
|
+
title: session.displayTitle || session.title || id,
|
|
21955
|
+
running,
|
|
21956
|
+
pending,
|
|
21957
|
+
at: typeof session.updatedAt === "number" ? session.updatedAt : 0
|
|
21958
|
+
});
|
|
21959
|
+
}
|
|
21960
|
+
rows.sort((a, b) => a.running === b.running ? b.at - a.at : a.running ? -1 : 1);
|
|
21961
|
+
const key = rows.map((row) => `${row.id}:${row.running ? 1 : 0}${row.pending ? 1 : 0}:${row.title}`).join("|");
|
|
21962
|
+
if (key !== attentionCache.key) {
|
|
21963
|
+
attentionCache.key = key;
|
|
21964
|
+
attentionCache.list = rows;
|
|
21965
|
+
}
|
|
21966
|
+
return attentionCache.list;
|
|
21967
|
+
}, [ctx]);
|
|
21968
|
+
return import_react.default.useSyncExternalStore(subscribe, read, () => attentionCache.list);
|
|
21969
|
+
}
|
|
21970
|
+
var expandGroupFailureReported = false;
|
|
21971
|
+
function reportExpandFailure(cause) {
|
|
21972
|
+
if (expandGroupFailureReported) return;
|
|
21973
|
+
expandGroupFailureReported = true;
|
|
21974
|
+
console.warn("[t-team] \u5C55\u5F00\u5DE5\u4F5C\u533A\u5206\u7EC4\u5931\u8D25\uFF08\u53EA\u63D0\u793A\u4E00\u6B21\uFF0C\u4E0D\u5F71\u54CD\u8DF3\u8F6C\uFF09\uFF1A", cause);
|
|
21975
|
+
}
|
|
21976
|
+
function owningWorkspaceKey(items, sessionId) {
|
|
21977
|
+
return items.find((item) => Array.isArray(item?.sessionIds) && item.sessionIds.includes(sessionId))?.workspaceId ?? "";
|
|
21978
|
+
}
|
|
21979
|
+
function expandOwningWorkspaceGroup(ctx, sessionId) {
|
|
21980
|
+
try {
|
|
21981
|
+
if (typeof sessionId !== "string" || sessionId === "") return;
|
|
21982
|
+
const items = ctx?.get?.("workspaces")?.list?.getSnapshot?.()?.items;
|
|
21983
|
+
if (!Array.isArray(items) || items.length === 0) return;
|
|
21984
|
+
const entries = ctx?.slots?.entries?.("sidebar.workspaces");
|
|
21985
|
+
if (!Array.isArray(entries) || entries.length === 0) return;
|
|
21986
|
+
const entry = entries.find((row) => row?.store?.spec?.actions?.setGroupExpanded !== void 0);
|
|
21987
|
+
if (entry === void 0) {
|
|
21988
|
+
reportExpandFailure("\u4FA7\u680F\u69FD\u91CC\u627E\u4E0D\u5230\u5E26 setGroupExpanded \u7684 store \u58F0\u660E\uFF08\u4E0A\u6E38\u63A5\u53E3\u53EF\u80FD\u6539\u4E86\uFF09");
|
|
21989
|
+
return;
|
|
21990
|
+
}
|
|
21991
|
+
const store = ctx?.slots?.hostFace?.()?.storeOf?.(entry);
|
|
21992
|
+
if (store?.actions?.setGroupExpanded === void 0) {
|
|
21993
|
+
reportExpandFailure("\u62FF\u5230\u7684\u4FA7\u680F store \u5B9E\u4F8B\u6CA1\u6709 setGroupExpanded\uFF08\u4E0A\u6E38\u63A5\u53E3\u53EF\u80FD\u6539\u4E86\uFF09");
|
|
21994
|
+
return;
|
|
21995
|
+
}
|
|
21996
|
+
const key = owningWorkspaceKey(items, sessionId);
|
|
21997
|
+
if (store.getSnapshot?.()?.groupExpansion?.[key] === true) return;
|
|
21998
|
+
store.actions.setGroupExpanded(key, true);
|
|
21999
|
+
} catch (error62) {
|
|
22000
|
+
reportExpandFailure(error62);
|
|
22001
|
+
}
|
|
22002
|
+
}
|
|
22003
|
+
function AttentionPanel({ t, sessions, anchor: anchor2, onClose, onOpen }) {
|
|
22004
|
+
import_react.default.useEffect(() => {
|
|
22005
|
+
const onKey = (event) => {
|
|
22006
|
+
if (event.key === "Escape") onClose();
|
|
22007
|
+
};
|
|
22008
|
+
const onDown = (event) => {
|
|
22009
|
+
const target = event.target;
|
|
22010
|
+
if (target instanceof Element && target.closest(".t-team-pulse-pop, .t-team-pulse") !== null) return;
|
|
22011
|
+
onClose();
|
|
22012
|
+
};
|
|
22013
|
+
window.addEventListener("keydown", onKey);
|
|
22014
|
+
window.addEventListener("mousedown", onDown, true);
|
|
22015
|
+
return () => {
|
|
22016
|
+
window.removeEventListener("keydown", onKey);
|
|
22017
|
+
window.removeEventListener("mousedown", onDown, true);
|
|
22018
|
+
};
|
|
22019
|
+
}, [onClose]);
|
|
22020
|
+
return /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-pulse-pop", style: { right: anchor2.right, top: anchor2.top }, role: "dialog", "aria-label": t("pulse.title") }, /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-pulse-pop-head" }, t("pulse.title")), sessions.length === 0 && /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-pulse-pop-empty" }, t("pulse.empty")), sessions.map((row) => /* @__PURE__ */ import_react.default.createElement("button", { key: row.id, type: "button", className: "t-team-pulse-pop-row", onClick: () => onOpen(row.id), title: row.title }, /* @__PURE__ */ import_react.default.createElement("span", { className: "t-team-pulse-pop-dot", "data-state": row.running ? "running" : "pending", "aria-hidden": "true" }), /* @__PURE__ */ import_react.default.createElement("span", { className: "t-team-pulse-pop-title" }, row.title), /* @__PURE__ */ import_react.default.createElement("span", { className: "t-team-pulse-pop-tag" }, t(row.running ? "pulse.running" : "pulse.pending")))));
|
|
22021
|
+
}
|
|
22022
|
+
function ActivePulse({ ctx, t }) {
|
|
22023
|
+
const show = useShowActivePulse();
|
|
22024
|
+
const sessions = useAttentionSessions(ctx);
|
|
22025
|
+
const [anchor2, setAnchor] = import_react.default.useState(null);
|
|
22026
|
+
const attention = sessions.length > 0;
|
|
22027
|
+
if (!show) return null;
|
|
22028
|
+
const label = t(attention ? "pulse.on" : "pulse.off");
|
|
22029
|
+
const toggle = (event) => {
|
|
22030
|
+
if (anchor2 !== null) {
|
|
22031
|
+
setAnchor(null);
|
|
22032
|
+
return;
|
|
22033
|
+
}
|
|
22034
|
+
const rect = event.currentTarget.getBoundingClientRect();
|
|
22035
|
+
setAnchor({ right: Math.max(8, window.innerWidth - rect.right - 24), top: Math.round(rect.bottom) + 6 });
|
|
22036
|
+
};
|
|
22037
|
+
return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement(
|
|
22038
|
+
"button",
|
|
22039
|
+
{
|
|
22040
|
+
type: "button",
|
|
22041
|
+
className: "t-team-pulse",
|
|
22042
|
+
"data-on": attention,
|
|
22043
|
+
onClick: toggle,
|
|
22044
|
+
"aria-label": label,
|
|
22045
|
+
"aria-expanded": anchor2 !== null,
|
|
22046
|
+
title: label
|
|
22047
|
+
},
|
|
22048
|
+
/* @__PURE__ */ import_react.default.createElement(
|
|
22049
|
+
"svg",
|
|
22050
|
+
{
|
|
22051
|
+
width: "16",
|
|
22052
|
+
height: "16",
|
|
22053
|
+
viewBox: "0 0 16 16",
|
|
22054
|
+
fill: "none",
|
|
22055
|
+
stroke: "currentColor",
|
|
22056
|
+
strokeWidth: "1.5",
|
|
22057
|
+
strokeLinecap: "round",
|
|
22058
|
+
strokeLinejoin: "round",
|
|
22059
|
+
"aria-hidden": "true",
|
|
22060
|
+
focusable: "false"
|
|
22061
|
+
},
|
|
22062
|
+
/* @__PURE__ */ import_react.default.createElement("path", { pathLength: "100", d: "M1 8h3.2l1.4-4.2 2.6 8.4 1.5-5.2 1 1H15" })
|
|
22063
|
+
)
|
|
22064
|
+
), anchor2 !== null && /* @__PURE__ */ import_react.default.createElement(
|
|
22065
|
+
AttentionPanel,
|
|
22066
|
+
{
|
|
22067
|
+
t,
|
|
22068
|
+
sessions,
|
|
22069
|
+
anchor: anchor2,
|
|
22070
|
+
onClose: () => setAnchor(null),
|
|
22071
|
+
onOpen: (id) => {
|
|
22072
|
+
expandOwningWorkspaceGroup(ctx, id);
|
|
22073
|
+
ctx?.sessions?.open?.(id);
|
|
22074
|
+
setAnchor(null);
|
|
22075
|
+
}
|
|
22076
|
+
}
|
|
22077
|
+
));
|
|
22078
|
+
}
|
|
21875
22079
|
function SettingsPanel({ t, ctx, remote, getActive, refreshCatalog, initialTab, squadsPreview, teamsPreview, draftPreview }) {
|
|
21876
22080
|
const [snapshot, setSnapshot] = import_react.default.useState(() => snapshotOf(remote) ?? null);
|
|
21877
22081
|
const [query, setQuery] = import_react.default.useState("");
|
|
@@ -22080,26 +22284,27 @@ function SettingsPanel({ t, ctx, remote, getActive, refreshCatalog, initialTab,
|
|
|
22080
22284
|
setBusy(false);
|
|
22081
22285
|
}
|
|
22082
22286
|
}
|
|
22083
|
-
if (snapshot === null) {
|
|
22084
|
-
return /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-settings" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-title" }, t("settings.title")), /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-meta" }, t("settings.loading")), error62 !== "" && /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-error" }, t("settings.loadFailed", { detail: error62 })), /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-row" }, /* @__PURE__ */ import_react.default.createElement("button", { className: "t-team-chip", type: "button", onClick: () => void reload(true) }, t("settings.retry")))));
|
|
22085
|
-
}
|
|
22086
22287
|
const [showTaskBadge, setShowTaskBadgeState] = import_react.default.useState(true);
|
|
22087
22288
|
const [showScheduleButton, setShowScheduleButtonState] = import_react.default.useState(true);
|
|
22289
|
+
const [showActivePulse, setShowActivePulseState] = import_react.default.useState(true);
|
|
22088
22290
|
const [uiPrefsError, setUiPrefsError] = import_react.default.useState("");
|
|
22291
|
+
const [uiPrefsWriteError, setUiPrefsWriteError] = import_react.default.useState("");
|
|
22292
|
+
const uiPrefQueue = import_react.default.useRef(Promise.resolve());
|
|
22089
22293
|
import_react.default.useEffect(() => {
|
|
22090
22294
|
let alive = true;
|
|
22091
22295
|
void (async () => {
|
|
22092
22296
|
try {
|
|
22093
22297
|
const data = unwrap(await remote.getUiPrefs(), "getUiPrefs");
|
|
22094
22298
|
if (!alive) return;
|
|
22095
|
-
if (typeof data?.showTaskBadge !== "boolean" || typeof data?.showScheduleButton !== "boolean") {
|
|
22299
|
+
if (typeof data?.showTaskBadge !== "boolean" || typeof data?.showScheduleButton !== "boolean" || typeof data?.showActivePulse !== "boolean") {
|
|
22096
22300
|
setUiPrefsError(t("settings.showTaskBadgeUnreadable"));
|
|
22097
22301
|
return;
|
|
22098
22302
|
}
|
|
22099
22303
|
setUiPrefsError("");
|
|
22100
22304
|
setShowTaskBadgeState(data.showTaskBadge);
|
|
22101
22305
|
setShowScheduleButtonState(data.showScheduleButton);
|
|
22102
|
-
|
|
22306
|
+
setShowActivePulseState(data.showActivePulse);
|
|
22307
|
+
setUiPrefs({ showTaskBadge: data.showTaskBadge, showScheduleButton: data.showScheduleButton, showActivePulse: data.showActivePulse });
|
|
22103
22308
|
} catch (cause) {
|
|
22104
22309
|
console.error("[t-team] \u754C\u9762\u504F\u597D\u8BFB\u53D6\u5931\u8D25\uFF0C\u6682\u6309\u9ED8\u8BA4\uFF08\u663E\u793A\u5FBD\u7AE0\uFF09\u5904\u7406\uFF1A", cause);
|
|
22105
22310
|
if (alive) setUiPrefsError(cause instanceof Error ? cause.message : String(cause));
|
|
@@ -22109,19 +22314,30 @@ function SettingsPanel({ t, ctx, remote, getActive, refreshCatalog, initialTab,
|
|
|
22109
22314
|
alive = false;
|
|
22110
22315
|
};
|
|
22111
22316
|
}, [remote]);
|
|
22317
|
+
if (snapshot === null) {
|
|
22318
|
+
return /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-settings" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-title" }, t("settings.title")), /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-meta" }, t("settings.loading")), error62 !== "" && /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-error" }, t("settings.loadFailed", { detail: error62 })), /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-row" }, /* @__PURE__ */ import_react.default.createElement("button", { className: "t-team-chip", type: "button", onClick: () => void reload(true) }, t("settings.retry")))));
|
|
22319
|
+
}
|
|
22112
22320
|
async function writeUiPref(patch, rollback) {
|
|
22113
22321
|
setUiPrefs(patch);
|
|
22114
|
-
|
|
22115
|
-
|
|
22116
|
-
|
|
22117
|
-
|
|
22118
|
-
|
|
22119
|
-
|
|
22120
|
-
|
|
22121
|
-
|
|
22122
|
-
|
|
22123
|
-
|
|
22124
|
-
|
|
22322
|
+
const run = uiPrefQueue.current.then(async () => {
|
|
22323
|
+
try {
|
|
22324
|
+
const next = unwrap(await remote.setUiPrefs(patch), "setUiPrefs");
|
|
22325
|
+
setUiPrefs(next);
|
|
22326
|
+
setShowTaskBadgeState(next.showTaskBadge);
|
|
22327
|
+
setShowScheduleButtonState(next.showScheduleButton);
|
|
22328
|
+
setShowActivePulseState(next.showActivePulse);
|
|
22329
|
+
setUiPrefsWriteError("");
|
|
22330
|
+
} catch (cause) {
|
|
22331
|
+
setUiPrefs(rollback);
|
|
22332
|
+
setShowTaskBadgeState(rollback.showTaskBadge ?? showTaskBadge);
|
|
22333
|
+
setShowScheduleButtonState(rollback.showScheduleButton ?? showScheduleButton);
|
|
22334
|
+
setShowActivePulseState(rollback.showActivePulse ?? showActivePulse);
|
|
22335
|
+
setUiPrefsWriteError(cause instanceof Error ? cause.message : String(cause));
|
|
22336
|
+
}
|
|
22337
|
+
});
|
|
22338
|
+
uiPrefQueue.current = run.catch(() => {
|
|
22339
|
+
});
|
|
22340
|
+
await run;
|
|
22125
22341
|
}
|
|
22126
22342
|
async function setShowTaskBadge(next) {
|
|
22127
22343
|
setShowTaskBadgeState(next);
|
|
@@ -22131,6 +22347,10 @@ function SettingsPanel({ t, ctx, remote, getActive, refreshCatalog, initialTab,
|
|
|
22131
22347
|
setShowScheduleButtonState(next);
|
|
22132
22348
|
await writeUiPref({ showScheduleButton: next }, { showScheduleButton: !next });
|
|
22133
22349
|
}
|
|
22350
|
+
async function setShowActivePulse(next) {
|
|
22351
|
+
setShowActivePulseState(next);
|
|
22352
|
+
await writeUiPref({ showActivePulse: next }, { showActivePulse: !next });
|
|
22353
|
+
}
|
|
22134
22354
|
const enabledCount = snapshot.enabled.length;
|
|
22135
22355
|
return /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-settings" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-head" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-title" }, t("settings.title")), /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-meta" }, t("settings.enabledCount", { enabled: enabledCount, total: experts.length }), " \xB7 v", CLIENT_BUILD_VERSION)), /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-setting-row" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-setting-head" }, /* @__PURE__ */ import_react.default.createElement("span", { className: "t-team-setting-name" }, t("settings.showTaskBadge")), /* @__PURE__ */ import_react.default.createElement(
|
|
22136
22356
|
"button",
|
|
@@ -22143,7 +22363,7 @@ function SettingsPanel({ t, ctx, remote, getActive, refreshCatalog, initialTab,
|
|
|
22143
22363
|
onClick: () => void setShowTaskBadge(!showTaskBadge)
|
|
22144
22364
|
},
|
|
22145
22365
|
/* @__PURE__ */ import_react.default.createElement("span", { className: "t-team-switch-knob" })
|
|
22146
|
-
)), /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-setting-hint" }, t("settings.showTaskBadgeHint")), uiPrefsError !== "" && /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-error" }, t("settings.showTaskBadgeUnreadable"), "\uFF1A", uiPrefsError)), /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-setting-row" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-setting-head" }, /* @__PURE__ */ import_react.default.createElement("span", { className: "t-team-setting-name" }, t("settings.showScheduleButton")), /* @__PURE__ */ import_react.default.createElement(
|
|
22366
|
+
)), /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-setting-hint" }, t("settings.showTaskBadgeHint")), uiPrefsError !== "" && /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-error" }, t("settings.showTaskBadgeUnreadable"), "\uFF1A", uiPrefsError), uiPrefsWriteError !== "" && /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-error" }, t("settings.uiPrefsWriteFailed"), "\uFF1A", uiPrefsWriteError)), /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-setting-row" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-setting-head" }, /* @__PURE__ */ import_react.default.createElement("span", { className: "t-team-setting-name" }, t("settings.showScheduleButton")), /* @__PURE__ */ import_react.default.createElement(
|
|
22147
22367
|
"button",
|
|
22148
22368
|
{
|
|
22149
22369
|
className: "t-team-switch",
|
|
@@ -22154,7 +22374,18 @@ function SettingsPanel({ t, ctx, remote, getActive, refreshCatalog, initialTab,
|
|
|
22154
22374
|
onClick: () => void setShowScheduleButton(!showScheduleButton)
|
|
22155
22375
|
},
|
|
22156
22376
|
/* @__PURE__ */ import_react.default.createElement("span", { className: "t-team-switch-knob" })
|
|
22157
|
-
)), /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-setting-hint" }, t("settings.showScheduleButtonHint"))), /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-
|
|
22377
|
+
)), /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-setting-hint" }, t("settings.showScheduleButtonHint"))), /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-setting-row" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-setting-head" }, /* @__PURE__ */ import_react.default.createElement("span", { className: "t-team-setting-name" }, t("settings.showActivePulse")), /* @__PURE__ */ import_react.default.createElement(
|
|
22378
|
+
"button",
|
|
22379
|
+
{
|
|
22380
|
+
className: "t-team-switch",
|
|
22381
|
+
type: "button",
|
|
22382
|
+
role: "switch",
|
|
22383
|
+
"aria-checked": showActivePulse,
|
|
22384
|
+
"data-on": showActivePulse,
|
|
22385
|
+
onClick: () => void setShowActivePulse(!showActivePulse)
|
|
22386
|
+
},
|
|
22387
|
+
/* @__PURE__ */ import_react.default.createElement("span", { className: "t-team-switch-knob" })
|
|
22388
|
+
)), /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-setting-hint" }, t("settings.showActivePulseHint"))), /* @__PURE__ */ import_react.default.createElement("div", { className: "t-team-tabs", role: "tablist" }, [["experts", "tab.experts"], ["categories", "tab.categories"], ["roster", "tab.roster"], ["teams", "tab.teams"]].map(([key, label]) => /* @__PURE__ */ import_react.default.createElement(
|
|
22158
22389
|
"button",
|
|
22159
22390
|
{
|
|
22160
22391
|
className: "t-team-tab",
|
|
@@ -23403,7 +23634,9 @@ async function apply(ctx) {
|
|
|
23403
23634
|
void (async () => {
|
|
23404
23635
|
try {
|
|
23405
23636
|
const data = unwrap(await remote.getUiPrefs(), "getUiPrefs");
|
|
23406
|
-
|
|
23637
|
+
const patch = {};
|
|
23638
|
+
for (const key of UI_PREF_KEYS) if (typeof data?.[key] === "boolean") patch[key] = data[key];
|
|
23639
|
+
setUiPrefs(patch);
|
|
23407
23640
|
} catch (cause) {
|
|
23408
23641
|
console.warn("[t-team] \u754C\u9762\u504F\u597D\u8BFB\u53D6\u5931\u8D25\uFF0C\u6682\u6309\u9ED8\u8BA4\uFF08\u663E\u793A\u5FBD\u7AE0\uFF09\u5904\u7406\uFF1A", cause);
|
|
23409
23642
|
}
|
|
@@ -23472,6 +23705,17 @@ async function apply(ctx) {
|
|
|
23472
23705
|
t: ctx.locale.bind(NS),
|
|
23473
23706
|
ctx: props?.ctx ?? ctx
|
|
23474
23707
|
})));
|
|
23708
|
+
ctx.slots.inject("conversation.session.header.utilities", () => ctx.slots.register({
|
|
23709
|
+
name: "conversation.session.header.utilities",
|
|
23710
|
+
id: `${NS}-pulse`,
|
|
23711
|
+
order: 1,
|
|
23712
|
+
label: () => ctx.locale.bind(NS)("pulse.on"),
|
|
23713
|
+
locale: NS
|
|
23714
|
+
}, (props) => import_react.default.createElement(ActivePulse, {
|
|
23715
|
+
...props,
|
|
23716
|
+
t: ctx.locale.bind(NS),
|
|
23717
|
+
ctx: props?.ctx ?? ctx
|
|
23718
|
+
})));
|
|
23475
23719
|
ctx.slots.inject("shell.overlay", () => ctx.slots.register({
|
|
23476
23720
|
name: "shell.overlay",
|
|
23477
23721
|
id: `${NS}-jobs`,
|
package/lib/index.js
CHANGED
|
@@ -167,6 +167,14 @@ const settingsSchema = schema.object({
|
|
|
167
167
|
* (见 apply 里的 applyScheduleArmed)。任务与执行记录完整保留,重新打开即恢复调度。
|
|
168
168
|
*/
|
|
169
169
|
showScheduleButton: schema.boolean().default(true),
|
|
170
|
+
/**
|
|
171
|
+
* 是否显示窗口右上角的「活跃指示」(心电图图标,界面偏好)。
|
|
172
|
+
*
|
|
173
|
+
* 彩色 = 有会话正在活动(自己在跑、或子代理在跑)**或**有待查看的完成提醒;
|
|
174
|
+
* 灰色 = 全部空闲且没有待看。与任务徽章的差别:它是**全局**的(挂 shell.overlay),
|
|
175
|
+
* 不受"当前打开哪个会话"影响。
|
|
176
|
+
*/
|
|
177
|
+
showActivePulse: schema.boolean().default(true),
|
|
170
178
|
});
|
|
171
179
|
|
|
172
180
|
/**
|
|
@@ -394,7 +402,7 @@ export function apply(ctx, config) {
|
|
|
394
402
|
return;
|
|
395
403
|
}
|
|
396
404
|
scope = settingsService.register(SETTINGS_NAMESPACE, settingsSchema, {
|
|
397
|
-
base: { enabled: [], showTaskBadge: true, showScheduleButton: true },
|
|
405
|
+
base: { enabled: [], showTaskBadge: true, showScheduleButton: true, showActivePulse: true },
|
|
398
406
|
applies: "live",
|
|
399
407
|
validate: (value) => {
|
|
400
408
|
const list = value?.enabled;
|
|
@@ -902,6 +910,7 @@ export function apply(ctx, config) {
|
|
|
902
910
|
return {
|
|
903
911
|
showTaskBadge: current?.showTaskBadge !== false,
|
|
904
912
|
showScheduleButton: current?.showScheduleButton !== false,
|
|
913
|
+
showActivePulse: current?.showActivePulse !== false,
|
|
905
914
|
};
|
|
906
915
|
}
|
|
907
916
|
|
|
@@ -911,6 +920,7 @@ export function apply(ctx, config) {
|
|
|
911
920
|
return {
|
|
912
921
|
...(typeof source.showTaskBadge === "boolean" ? { showTaskBadge: source.showTaskBadge } : {}),
|
|
913
922
|
...(typeof source.showScheduleButton === "boolean" ? { showScheduleButton: source.showScheduleButton } : {}),
|
|
923
|
+
...(typeof source.showActivePulse === "boolean" ? { showActivePulse: source.showActivePulse } : {}),
|
|
914
924
|
};
|
|
915
925
|
}
|
|
916
926
|
|
|
@@ -927,6 +937,7 @@ export function apply(ctx, config) {
|
|
|
927
937
|
[
|
|
928
938
|
{ op: "set", path: ["showTaskBadge"], value: next.showTaskBadge },
|
|
929
939
|
{ op: "set", path: ["showScheduleButton"], value: next.showScheduleButton },
|
|
940
|
+
{ op: "set", path: ["showActivePulse"], value: next.showActivePulse },
|
|
930
941
|
],
|
|
931
942
|
revision(),
|
|
932
943
|
);
|
package/lib/remote-schemas.js
CHANGED
|
@@ -82,12 +82,15 @@ export const enabledStateSchema = z.object({
|
|
|
82
82
|
export const uiPrefsSchema = z.object({
|
|
83
83
|
showTaskBadge: z.boolean(),
|
|
84
84
|
showScheduleButton: z.boolean(),
|
|
85
|
+
// 窗口右上角「活跃指示」是否显示。宿主**总是**返回布尔(缺省按 true 算),所以这里必填。
|
|
86
|
+
showActivePulse: z.boolean(),
|
|
85
87
|
});
|
|
86
88
|
|
|
87
89
|
/** `setUiPrefs` 的入参:想改哪个传哪个(未传的键保持原值)。 */
|
|
88
90
|
export const uiPrefsPatchSchema = z.object({
|
|
89
91
|
showTaskBadge: z.boolean().optional(),
|
|
90
92
|
showScheduleButton: z.boolean().optional(),
|
|
93
|
+
showActivePulse: z.boolean().optional(),
|
|
91
94
|
});
|
|
92
95
|
|
|
93
96
|
export const promptSchema = z.object({ prompt: z.string() });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-plugin-t-expert",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.39",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "T Expert — a 323-expert, 22-division roster with full Chinese translations, as a standalone DeepSeek Harness plugin, with a built-in multi-agent team engine (T Team).",
|
|
6
6
|
"license": "MIT",
|