dsh-dock 0.1.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +12 -15
- package/README.md +170 -37
- package/client.js +2136 -97
- package/features/balance/host.js +494 -0
- package/features/balance/view.js +303 -0
- package/features/heartbeat/view.js +34 -0
- package/features/modelconfig/host.js +403 -0
- package/features/modelconfig/view.js +446 -0
- package/features/theme/view.js +35 -0
- package/features/tokenlog/host.js +678 -0
- package/features/tokenlog/view.jsx +568 -0
- package/features/visionproxy/host.js +301 -0
- package/index.js +50 -36
- package/package.json +19 -5
- package/src/client.jsx +549 -0
- package/src/host-core.js +54 -0
- package/src/shared.js +108 -0
package/src/shared.js
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
// dsh-dock · 客户端共享工具(外壳与功能模块共用;提取功能模块独立成包时随包复制)
|
|
2
|
+
import react from "react";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 功能视图错误边界:外部功能包注册进来的视图渲染抛错时降级为错误提示,
|
|
6
|
+
* 不拖垮整个功能坞面板(内置视图不包——它们与外壳同包发布、同生命周期)。
|
|
7
|
+
*/
|
|
8
|
+
export class FeatureBoundary extends react.Component {
|
|
9
|
+
constructor(props) {
|
|
10
|
+
super(props);
|
|
11
|
+
this.state = { error: null };
|
|
12
|
+
}
|
|
13
|
+
static getDerivedStateFromError(error) {
|
|
14
|
+
return { error: error };
|
|
15
|
+
}
|
|
16
|
+
render() {
|
|
17
|
+
if (this.state.error) {
|
|
18
|
+
const msg = this.state.error && this.state.error.message ? this.state.error.message : String(this.state.error);
|
|
19
|
+
return react.createElement("div", { className: "dockm-note dockm-err" },
|
|
20
|
+
"功能视图渲染出错:" + msg + "(该功能来自外部包,不影响面板其他功能)");
|
|
21
|
+
}
|
|
22
|
+
return this.props.children;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// ---- 功能开关状态(外壳面板与会话区 chips 共用;浏览器内存态,随页面生命周期) ----
|
|
27
|
+
const featureState = new Map();
|
|
28
|
+
const stateListeners = new Set();
|
|
29
|
+
function notifyState() {
|
|
30
|
+
for (const fn of stateListeners) fn();
|
|
31
|
+
}
|
|
32
|
+
/** 外壳 apply 时初始化内置功能的默认开关。 */
|
|
33
|
+
export function initFeatureState(defs) {
|
|
34
|
+
for (const f of defs) {
|
|
35
|
+
if (!featureState.has(f.id)) featureState.set(f.id, { enabled: !f.planned && f.defaultEnabled !== false, error: null });
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/** 取功能开关(外部功能默认启用;未登记的 id 惰性建项)。 */
|
|
39
|
+
export function stateOf(id) {
|
|
40
|
+
let st = featureState.get(id);
|
|
41
|
+
if (!st) { st = { enabled: true, error: null }; featureState.set(id, st); }
|
|
42
|
+
return st;
|
|
43
|
+
}
|
|
44
|
+
export function toggleFeature(id) {
|
|
45
|
+
const st = stateOf(id);
|
|
46
|
+
st.enabled = !st.enabled;
|
|
47
|
+
notifyState();
|
|
48
|
+
}
|
|
49
|
+
export function subscribeFeatureState(fn) {
|
|
50
|
+
stateListeners.add(fn);
|
|
51
|
+
return () => { stateListeners.delete(fn); };
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// ---- 会话页 chips 显示开关(每功能;localStorage 持久化,缺省显示) ----
|
|
55
|
+
// 与功能启用正交:功能启用决定面板页与宿主功能,本开关只控制会话输入区的随身小控件。
|
|
56
|
+
const CHIP_STORE_KEY = "dsh-dock/chips/v1";
|
|
57
|
+
const chipVisible = { map: {} };
|
|
58
|
+
try {
|
|
59
|
+
if (typeof localStorage !== "undefined") {
|
|
60
|
+
const raw = localStorage.getItem(CHIP_STORE_KEY);
|
|
61
|
+
const obj = raw ? JSON.parse(raw) : null;
|
|
62
|
+
if (obj && typeof obj === "object") chipVisible.map = obj;
|
|
63
|
+
}
|
|
64
|
+
} catch { /* localStorage 不可用时用默认值 */ }
|
|
65
|
+
function persistChipVisible() {
|
|
66
|
+
try {
|
|
67
|
+
if (typeof localStorage !== "undefined") localStorage.setItem(CHIP_STORE_KEY, JSON.stringify(chipVisible.map));
|
|
68
|
+
} catch { /* 持久化失败静默 */ }
|
|
69
|
+
}
|
|
70
|
+
/** 功能的会话页 chip 是否显示(未记录过的功能默认显示)。 */
|
|
71
|
+
export function chipShown(id) {
|
|
72
|
+
return chipVisible.map[id] !== false;
|
|
73
|
+
}
|
|
74
|
+
/** 设置功能的会话页 chip 显示开关(立即生效并持久化)。 */
|
|
75
|
+
export function setChipShown(id, value) {
|
|
76
|
+
chipVisible.map[id] = value !== false;
|
|
77
|
+
persistChipVisible();
|
|
78
|
+
notifyState();
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// ---- 面板导航总线:功能坞外任何位置(会话区 chips 等)可请求打开面板并跳到某功能 ----
|
|
82
|
+
// openPanel("balance", { provider }) → 打开功能坞并定位到模型余额页,高亮指定 Provider
|
|
83
|
+
// openPanel("tokenlog", { sessionId }) → 打开功能坞并定位到用量记录页,按会话筛选
|
|
84
|
+
export const panelNav = { open: false, active: "home", params: null };
|
|
85
|
+
const navListeners = new Set();
|
|
86
|
+
function notifyNav() {
|
|
87
|
+
for (const fn of navListeners) fn();
|
|
88
|
+
}
|
|
89
|
+
export function openPanel(active, params) {
|
|
90
|
+
panelNav.open = true;
|
|
91
|
+
panelNav.active = typeof active === "string" && active ? active : "home";
|
|
92
|
+
panelNav.params = params && typeof params === "object" ? params : null;
|
|
93
|
+
notifyNav();
|
|
94
|
+
}
|
|
95
|
+
export function setPanelOpen(value) {
|
|
96
|
+
panelNav.open = !!value;
|
|
97
|
+
if (!value) panelNav.params = null;
|
|
98
|
+
notifyNav();
|
|
99
|
+
}
|
|
100
|
+
/** 面板内切换功能页(不携带参数)。 */
|
|
101
|
+
export function navigatePanel(active) {
|
|
102
|
+
panelNav.active = typeof active === "string" && active ? active : "home";
|
|
103
|
+
notifyNav();
|
|
104
|
+
}
|
|
105
|
+
export function subscribePanel(fn) {
|
|
106
|
+
navListeners.add(fn);
|
|
107
|
+
return () => { navListeners.delete(fn); };
|
|
108
|
+
}
|