@deepseek-ai/dsh-client-ui-settings-plugin-inventory 0.0.1-rc.3
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 +28 -0
- package/README.i18n.yaml +6 -0
- package/README.md +20 -0
- package/README.zh.md +20 -0
- package/lib/client.js +302 -0
- package/lib/index.js +6 -0
- package/lib/invariant.js +13 -0
- package/lib/types/client/PluginInventorySettingsTab.d.ts +13 -0
- package/lib/types/client/index.d.ts +18 -0
- package/lib/types/client/locales.d.ts +46 -0
- package/lib/types/index.d.ts +4 -0
- package/lib/types/invariant.d.ts +9 -0
- package/package.json +80 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026, DeepSeek
|
|
4
|
+
|
|
5
|
+
Redistribution and use in source and binary forms, with or without
|
|
6
|
+
modification, are permitted provided that the following conditions are met:
|
|
7
|
+
|
|
8
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
9
|
+
list of conditions and the following disclaimer.
|
|
10
|
+
|
|
11
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
12
|
+
this list of conditions and the following disclaimer in the documentation
|
|
13
|
+
and/or other materials provided with the distribution.
|
|
14
|
+
|
|
15
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
16
|
+
contributors may be used to endorse or promote products derived from
|
|
17
|
+
this software without specific prior written permission.
|
|
18
|
+
|
|
19
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
20
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
21
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
22
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
23
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
24
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
25
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
26
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
27
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
28
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
package/README.i18n.yaml
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
|
|
2
|
+
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
|
3
|
+
# after editing either side, bring the other along and re-record with:
|
|
4
|
+
# pnpm run verify-translation-pairing --write packages/client/ui-settings-plugin-inventory/README.md
|
|
5
|
+
README.md: d3410d1387b4a51a0ecaeee4ec9f80913157d453
|
|
6
|
+
README.zh.md: e262a29dfa5c9c4d1505b442aeb1881015a1de8c
|
package/README.md
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# @deepseek-ai/dsh-client-ui-settings-plugin-inventory
|
|
2
|
+
|
|
3
|
+
English | [中文](README.zh.md)
|
|
4
|
+
|
|
5
|
+
Read-only **Plugin list** tab for Web Settings. The browser plugin registers one localized `settings.plugins.tab` contribution with id `all`; the Plugins section owns the navigation entry and tab chrome. It performs no Remote read during plugin activation. Selecting the tab for the first time mounts it and lazily calls `ctx.remote.pluginInventory.list()` through [`api-remotes`](../../api/remotes/README.md).
|
|
6
|
+
|
|
7
|
+
The tab renders a searchable two-column catalog of compact disclosure cards. Each collapsed card uses the short module name as its title and a small effective-enablement tag; enabled entries also show a colored root-fiber status dot. Expanding one card reveals its Loader-tree entry id without a redundant field label, followed by the effective configuration and, for enabled entries, Cordis status. Disabled entries omit the redundant unmounted runtime state. The entry id remains the React key, disclosure identity, detail value, and an additional search target; it is never classified by string shape. Loading, empty, no-match, and generic failure states stay local to the mounted component, and a failed read can be retried without exposing transport details. The registration uses `ctx.slots.inject()`, so it follows late tab declaration, redeclaration, locale changes, and teardown without importing the section owner.
|
|
8
|
+
|
|
9
|
+
## Model Experience
|
|
10
|
+
|
|
11
|
+
None, as this package only visualizes a Host-owned deployment snapshot in browser Settings and registers nothing model-facing.
|
|
12
|
+
|
|
13
|
+
#### KV Cache effect
|
|
14
|
+
|
|
15
|
+
None; this package neither assembles nor sends a provider request.
|
|
16
|
+
|
|
17
|
+
## Known Limitations and Deferred Work
|
|
18
|
+
|
|
19
|
+
- **One snapshot per Settings mount or retry** — the tab does not subscribe to Loader changes or automatically refetch after reconnect; switching tabs preserves the current snapshot, while reopening Settings obtains a new one.
|
|
20
|
+
- **Read-only Loader view** — local search does not add provenance, current-browser activation diagnosis, grouping by source, or plugin mutation controls.
|
package/README.zh.md
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# @deepseek-ai/dsh-client-ui-settings-plugin-inventory
|
|
2
|
+
|
|
3
|
+
[English](README.md) | 中文
|
|
4
|
+
|
|
5
|
+
Web 设置中的只读**插件列表**标签页。浏览器插件注册一个 id 为 `all` 的本地化 `settings.plugins.tab` 贡献;“插件”分区拥有导航入口与标签栏。插件激活期间不会读取 Remote;首次选择该标签页时才挂载组件,并通过 [`api-remotes`](../../api/remotes/README.md) 懒调用 `ctx.remote.pluginInventory.list()`。
|
|
6
|
+
|
|
7
|
+
该标签页以可搜索的双列紧凑折叠卡片展示清单。每张收起的卡片使用模块短名称作为标题,以小标签表示有效启停状态;已启用的条目还会以彩色圆点表示根 fiber 状态。展开卡片后会直接展示 Loader 树条目 id,不附加重复的字段标题,并列出有效配置状态;已启用的条目还会列出 Cordis 状态,已停用的条目则省略重复的“未挂载”运行状态。条目 id 仍作为 React key、展开标识、详情值与额外的搜索目标;代码不按字符串形状对它分类。加载、空结果、无匹配结果与通用失败状态只属于已挂载组件;读取失败后可以重试,且不会暴露传输细节。注册使用 `ctx.slots.inject()`,因此能跟随标签 slot 的延迟声明、重新声明、本地化变化与 teardown,而无需 import 分区拥有方。
|
|
8
|
+
|
|
9
|
+
## 模型体验
|
|
10
|
+
|
|
11
|
+
无,因为本包只在浏览器设置中展示 Host 拥有的部署快照,不注册任何模型接口。
|
|
12
|
+
|
|
13
|
+
#### KV Cache 影响
|
|
14
|
+
|
|
15
|
+
无;本包既不组装也不发送提供方请求。
|
|
16
|
+
|
|
17
|
+
## 已知限制与暂缓事项
|
|
18
|
+
|
|
19
|
+
- **每次 Settings 挂载或重试只读取一份快照** —— 标签页不订阅 Loader 变化,也不会在重连后自动重新读取;切换标签页会保留当前快照,重新打开 Settings 则会取得新快照。
|
|
20
|
+
- **只读 Loader 视图** —— 本地搜索不会额外引入来源、按来源分组、当前浏览器激活诊断或插件修改控件。
|
package/lib/client.js
ADDED
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
window.__ModuleLoader__.load({
|
|
2
|
+
id: "@deepseek-ai/dsh-client-ui-settings-plugin-inventory",
|
|
3
|
+
factory: (require) => {
|
|
4
|
+
var module = { exports: {} };
|
|
5
|
+
var exports = module.exports;
|
|
6
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
7
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
8
|
+
let react = require("react");
|
|
9
|
+
let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
10
|
+
//#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-settings-plugin-inventory/src/client/PluginInventorySettingsTab.module.css.mjs
|
|
11
|
+
const css = ".qSYn7G_section{width:100%;max-width:760px;color:var(--dsw-alias-label-primary);flex-direction:column;gap:14px;display:flex}.qSYn7G_catalogHeading h3,.qSYn7G_status,.qSYn7G_failure p{margin:0}.qSYn7G_status,.qSYn7G_failure{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:20px}.qSYn7G_failure{color:var(--dsw-alias-state-error-primary);align-items:center;gap:10px;display:flex}.qSYn7G_failure button{border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary);font:inherit;cursor:pointer;background:0 0;border-radius:6px;padding:4px 10px}.qSYn7G_catalog{flex-direction:column;gap:12px;display:flex}.qSYn7G_search{width:100%;color:var(--dsw-alias-label-tertiary);align-items:center;display:flex;position:relative}.qSYn7G_search>svg{pointer-events:none;position:absolute;left:12px}.qSYn7G_search input{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);width:100%;height:36px;color:var(--dsw-alias-label-primary);font:inherit;border-radius:8px;outline:none;padding:0 34px 0 36px;font-size:13px}.qSYn7G_search input::placeholder{color:var(--dsw-alias-label-tertiary)}.qSYn7G_search input:focus-visible{border-color:var(--dsw-alias-state-business-primary);box-shadow:0 0 0 2px color-mix(in srgb, var(--dsw-alias-state-business-primary) 18%, transparent)}.qSYn7G_catalogHeading{align-items:baseline;gap:7px;padding:0 2px;display:flex}.qSYn7G_catalogHeading h3{font-size:13px;font-weight:600;line-height:20px}.qSYn7G_catalogHeading span{color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums;font-size:12px;line-height:18px}.qSYn7G_cards{grid-template-columns:repeat(2,minmax(0,1fr));align-items:start;gap:10px;margin:0;padding:0;list-style:none;display:grid}.qSYn7G_card{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:10px;min-width:0;overflow:hidden}.qSYn7G_card[data-open=true]{border-color:var(--dsw-alias-border-l1);box-shadow:var(--dsw-shadow-lv1)}.qSYn7G_cardContent{box-sizing:border-box;width:100%;min-height:52px;color:inherit;font:inherit;text-align:left;cursor:pointer;background:0 0;border:0;justify-content:space-between;align-items:center;gap:12px;padding:12px 14px;display:flex}.qSYn7G_cardContent:hover,.qSYn7G_card[data-open=true]>.qSYn7G_cardContent{background:var(--dsw-alias-interactive-bg-hover)}.qSYn7G_cardContent:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:-2px}.qSYn7G_cardTitle{text-overflow:ellipsis;white-space:nowrap;min-width:0;font-size:14px;font-weight:600;line-height:20px;overflow:hidden}.qSYn7G_cardTrailing{color:var(--dsw-alias-label-tertiary);flex:none;align-items:center;gap:7px;display:inline-flex}.qSYn7G_statusDot{background:var(--dsw-alias-label-tertiary);border-radius:999px;flex:none;width:7px;height:7px;display:inline-block}.qSYn7G_statusDot[data-phase=active]{background:var(--dsw-alias-state-success-primary)}.qSYn7G_statusDot[data-phase=failed]{background:var(--dsw-alias-state-error-primary)}.qSYn7G_statusDot[data-phase=loading]{background:var(--dsw-alias-state-business-primary)}.qSYn7G_configTag{background:var(--dsw-alias-bg-layer-1);min-height:20px;color:var(--dsw-alias-label-secondary);white-space:nowrap;border-radius:5px;align-items:center;padding:1px 6px;font-size:11px;line-height:16px;display:inline-flex}.qSYn7G_configTag[data-enabled=true]{background:color-mix(in srgb, var(--dsw-alias-state-success-primary) 10%, transparent);color:var(--dsw-alias-state-success-primary)}.qSYn7G_chevron{color:var(--dsw-alias-label-tertiary);flex:none}.qSYn7G_card[data-open=true] .qSYn7G_chevron{transform:rotate(180deg)}.qSYn7G_cardDetails{border-top:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-module-platform);padding:10px 14px 12px}.qSYn7G_entryValue{overflow-wrap:anywhere;color:var(--dsw-alias-label-primary);font-family:var(--ds-font-family-code);font-size:12px;line-height:18px;display:block}.qSYn7G_details{grid-template-columns:76px minmax(0,1fr);gap:6px 10px;margin:8px 0 0;display:grid}.qSYn7G_details div{display:contents}.qSYn7G_details dt{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:17px}.qSYn7G_details dd{overflow-wrap:anywhere;min-width:0;color:var(--dsw-alias-label-secondary);margin:0;font-size:12px;line-height:17px}.qSYn7G_visuallyHidden{clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;width:1px;height:1px;position:absolute;overflow:hidden}@media (prefers-reduced-motion:no-preference){.qSYn7G_chevron{transition:transform .14s var(--ds-ease-in-out)}}@media (width<=680px){.qSYn7G_cards{grid-template-columns:minmax(0,1fr)}}";
|
|
12
|
+
const tagId = "@deepseek-ai/dsh-client-ui-settings-plugin-inventory/PluginInventorySettingsTab.module.css";
|
|
13
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
|
|
14
|
+
const tag = document.createElement("style");
|
|
15
|
+
tag.dataset.plugin = "@deepseek-ai/dsh-client-ui-settings-plugin-inventory";
|
|
16
|
+
tag.dataset.pluginCss = tagId;
|
|
17
|
+
tag.textContent = css;
|
|
18
|
+
document.head.appendChild(tag);
|
|
19
|
+
}
|
|
20
|
+
var PluginInventorySettingsTab_module_css_default = {
|
|
21
|
+
"section": "qSYn7G_section",
|
|
22
|
+
"cardDetails": "qSYn7G_cardDetails",
|
|
23
|
+
"status": "qSYn7G_status",
|
|
24
|
+
"cards": "qSYn7G_cards",
|
|
25
|
+
"configTag": "qSYn7G_configTag",
|
|
26
|
+
"cardTrailing": "qSYn7G_cardTrailing",
|
|
27
|
+
"cardContent": "qSYn7G_cardContent",
|
|
28
|
+
"details": "qSYn7G_details",
|
|
29
|
+
"catalogHeading": "qSYn7G_catalogHeading",
|
|
30
|
+
"entryValue": "qSYn7G_entryValue",
|
|
31
|
+
"visuallyHidden": "qSYn7G_visuallyHidden",
|
|
32
|
+
"statusDot": "qSYn7G_statusDot",
|
|
33
|
+
"card": "qSYn7G_card",
|
|
34
|
+
"chevron": "qSYn7G_chevron",
|
|
35
|
+
"failure": "qSYn7G_failure",
|
|
36
|
+
"catalog": "qSYn7G_catalog",
|
|
37
|
+
"cardTitle": "qSYn7G_cardTitle",
|
|
38
|
+
"search": "qSYn7G_search"
|
|
39
|
+
};
|
|
40
|
+
//#endregion
|
|
41
|
+
//#region lib/types/client/PluginInventorySettingsTab.js
|
|
42
|
+
const PHASE_KEYS = {
|
|
43
|
+
pending: "pending",
|
|
44
|
+
loading: "loadingPhase",
|
|
45
|
+
active: "active",
|
|
46
|
+
failed: "failed",
|
|
47
|
+
unloading: "unloading"
|
|
48
|
+
};
|
|
49
|
+
/** Localized accessible label for one root Fiber phase. */
|
|
50
|
+
function phaseLabel(phase, t) {
|
|
51
|
+
return phase === null ? t("unobserved") : t(PHASE_KEYS[phase]);
|
|
52
|
+
}
|
|
53
|
+
/** Compact a module specifier without guessing whether its Loader id was generated. */
|
|
54
|
+
function moduleShortName(moduleName) {
|
|
55
|
+
return (moduleName.startsWith("@") ? moduleName.slice(moduleName.indexOf("/") + 1) : moduleName).replace(/^cordis:/, "").replace(/^cordis-plugin-/, "").replace(/^dsh-(?:host-|client-)?/, "");
|
|
56
|
+
}
|
|
57
|
+
/** Whether an inventory row matches the local catalog query. */
|
|
58
|
+
function matches(entry, normalizedQuery) {
|
|
59
|
+
if (normalizedQuery.length === 0) return true;
|
|
60
|
+
return [entry.moduleName, entry.entryId].some((value) => value.toLocaleLowerCase().includes(normalizedQuery));
|
|
61
|
+
}
|
|
62
|
+
/** Render the read-only current Loader inventory. */
|
|
63
|
+
function PluginInventorySettingsTab({ list, t }) {
|
|
64
|
+
const catalogId = (0, react.useId)();
|
|
65
|
+
const [request, setRequest] = (0, react.useState)(0);
|
|
66
|
+
const [query, setQuery] = (0, react.useState)("");
|
|
67
|
+
const [expanded, setExpanded] = (0, react.useState)(null);
|
|
68
|
+
const [state, setState] = (0, react.useState)({ status: "loading" });
|
|
69
|
+
(0, react.useEffect)(() => {
|
|
70
|
+
let current = true;
|
|
71
|
+
Promise.resolve().then(() => list()).then((snapshot) => {
|
|
72
|
+
if (current) setState({
|
|
73
|
+
status: "ready",
|
|
74
|
+
snapshot
|
|
75
|
+
});
|
|
76
|
+
}, () => {
|
|
77
|
+
if (current) setState({ status: "error" });
|
|
78
|
+
});
|
|
79
|
+
return () => {
|
|
80
|
+
current = false;
|
|
81
|
+
};
|
|
82
|
+
}, [list, request]);
|
|
83
|
+
const normalizedQuery = query.trim().toLocaleLowerCase();
|
|
84
|
+
const filteredEntries = (0, react.useMemo)(() => state.status === "ready" ? state.snapshot.entries.filter((entry) => matches(entry, normalizedQuery)) : [], [normalizedQuery, state]);
|
|
85
|
+
(0, react.useEffect)(() => {
|
|
86
|
+
if (expanded !== null && !filteredEntries.some((entry) => entry.entryId === expanded)) setExpanded(null);
|
|
87
|
+
}, [expanded, filteredEntries]);
|
|
88
|
+
const retry = () => {
|
|
89
|
+
setState({ status: "loading" });
|
|
90
|
+
setRequest((value) => value + 1);
|
|
91
|
+
};
|
|
92
|
+
return (0, react_jsx_runtime.jsxs)("div", {
|
|
93
|
+
className: PluginInventorySettingsTab_module_css_default.section,
|
|
94
|
+
"aria-busy": state.status === "loading",
|
|
95
|
+
children: [
|
|
96
|
+
state.status === "loading" ? (0, react_jsx_runtime.jsx)("p", {
|
|
97
|
+
className: PluginInventorySettingsTab_module_css_default.status,
|
|
98
|
+
children: t("loading")
|
|
99
|
+
}) : null,
|
|
100
|
+
state.status === "error" ? (0, react_jsx_runtime.jsxs)("div", {
|
|
101
|
+
className: PluginInventorySettingsTab_module_css_default.failure,
|
|
102
|
+
children: [(0, react_jsx_runtime.jsx)("p", {
|
|
103
|
+
role: "alert",
|
|
104
|
+
children: t("error")
|
|
105
|
+
}), (0, react_jsx_runtime.jsx)("button", {
|
|
106
|
+
type: "button",
|
|
107
|
+
onClick: retry,
|
|
108
|
+
children: t("retry")
|
|
109
|
+
})]
|
|
110
|
+
}) : null,
|
|
111
|
+
state.status === "ready" ? (0, react_jsx_runtime.jsxs)("div", {
|
|
112
|
+
className: PluginInventorySettingsTab_module_css_default.catalog,
|
|
113
|
+
children: [
|
|
114
|
+
(0, react_jsx_runtime.jsxs)("label", {
|
|
115
|
+
className: PluginInventorySettingsTab_module_css_default.search,
|
|
116
|
+
children: [
|
|
117
|
+
(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSearchOutline16, { "aria-hidden": "true" }),
|
|
118
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
119
|
+
className: PluginInventorySettingsTab_module_css_default.visuallyHidden,
|
|
120
|
+
children: t("search")
|
|
121
|
+
}),
|
|
122
|
+
(0, react_jsx_runtime.jsx)("input", {
|
|
123
|
+
type: "search",
|
|
124
|
+
value: query,
|
|
125
|
+
placeholder: t("search"),
|
|
126
|
+
"aria-label": t("search"),
|
|
127
|
+
onChange: (event) => {
|
|
128
|
+
setQuery(event.currentTarget.value);
|
|
129
|
+
}
|
|
130
|
+
})
|
|
131
|
+
]
|
|
132
|
+
}),
|
|
133
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
134
|
+
className: PluginInventorySettingsTab_module_css_default.catalogHeading,
|
|
135
|
+
children: [(0, react_jsx_runtime.jsx)("h3", { children: t("catalog") }), (0, react_jsx_runtime.jsx)("span", {
|
|
136
|
+
"data-plugin-count": filteredEntries.length,
|
|
137
|
+
children: filteredEntries.length
|
|
138
|
+
})]
|
|
139
|
+
}),
|
|
140
|
+
state.snapshot.entries.length === 0 ? (0, react_jsx_runtime.jsx)("p", {
|
|
141
|
+
className: PluginInventorySettingsTab_module_css_default.status,
|
|
142
|
+
children: t("empty")
|
|
143
|
+
}) : null,
|
|
144
|
+
state.snapshot.entries.length > 0 && filteredEntries.length === 0 ? (0, react_jsx_runtime.jsx)("p", {
|
|
145
|
+
className: PluginInventorySettingsTab_module_css_default.status,
|
|
146
|
+
children: t("emptySearch")
|
|
147
|
+
}) : null,
|
|
148
|
+
filteredEntries.length > 0 ? (0, react_jsx_runtime.jsx)("ul", {
|
|
149
|
+
className: PluginInventorySettingsTab_module_css_default.cards,
|
|
150
|
+
children: filteredEntries.map((entry) => {
|
|
151
|
+
const status = phaseLabel(entry.fiberPhase, t);
|
|
152
|
+
const title = moduleShortName(entry.moduleName);
|
|
153
|
+
const configuration = t(entry.enabled ? "enabledTag" : "disabledTag");
|
|
154
|
+
const open = expanded === entry.entryId;
|
|
155
|
+
const detailId = `${catalogId}-details-${encodeURIComponent(entry.entryId)}`;
|
|
156
|
+
return (0, react_jsx_runtime.jsxs)("li", {
|
|
157
|
+
className: PluginInventorySettingsTab_module_css_default.card,
|
|
158
|
+
"data-plugin-entry": entry.entryId,
|
|
159
|
+
"data-open": open ? "true" : void 0,
|
|
160
|
+
children: [(0, react_jsx_runtime.jsxs)("button", {
|
|
161
|
+
className: PluginInventorySettingsTab_module_css_default.cardContent,
|
|
162
|
+
type: "button",
|
|
163
|
+
"aria-expanded": open,
|
|
164
|
+
"aria-controls": detailId,
|
|
165
|
+
"aria-label": entry.enabled ? `${title}, ${status}, ${configuration}` : `${title}, ${configuration}`,
|
|
166
|
+
onClick: () => {
|
|
167
|
+
setExpanded((current) => current === entry.entryId ? null : entry.entryId);
|
|
168
|
+
},
|
|
169
|
+
children: [(0, react_jsx_runtime.jsx)("strong", {
|
|
170
|
+
className: PluginInventorySettingsTab_module_css_default.cardTitle,
|
|
171
|
+
title: entry.moduleName,
|
|
172
|
+
children: title
|
|
173
|
+
}), (0, react_jsx_runtime.jsxs)("span", {
|
|
174
|
+
className: PluginInventorySettingsTab_module_css_default.cardTrailing,
|
|
175
|
+
children: [
|
|
176
|
+
entry.enabled ? (0, react_jsx_runtime.jsx)("span", {
|
|
177
|
+
className: PluginInventorySettingsTab_module_css_default.statusDot,
|
|
178
|
+
"data-phase": entry.fiberPhase ?? "unobserved",
|
|
179
|
+
role: "img",
|
|
180
|
+
"aria-label": status,
|
|
181
|
+
title: status
|
|
182
|
+
}) : null,
|
|
183
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
184
|
+
className: PluginInventorySettingsTab_module_css_default.configTag,
|
|
185
|
+
"data-enabled": entry.enabled ? "true" : "false",
|
|
186
|
+
children: configuration
|
|
187
|
+
}),
|
|
188
|
+
(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutline14, {
|
|
189
|
+
className: PluginInventorySettingsTab_module_css_default.chevron,
|
|
190
|
+
size: 12,
|
|
191
|
+
"aria-hidden": "true"
|
|
192
|
+
})
|
|
193
|
+
]
|
|
194
|
+
})]
|
|
195
|
+
}), open ? (0, react_jsx_runtime.jsxs)("div", {
|
|
196
|
+
className: PluginInventorySettingsTab_module_css_default.cardDetails,
|
|
197
|
+
id: detailId,
|
|
198
|
+
children: [(0, react_jsx_runtime.jsx)("code", {
|
|
199
|
+
className: PluginInventorySettingsTab_module_css_default.entryValue,
|
|
200
|
+
"data-loader-entry": true,
|
|
201
|
+
children: entry.entryId
|
|
202
|
+
}), (0, react_jsx_runtime.jsxs)("dl", {
|
|
203
|
+
className: PluginInventorySettingsTab_module_css_default.details,
|
|
204
|
+
children: [(0, react_jsx_runtime.jsxs)("div", { children: [(0, react_jsx_runtime.jsx)("dt", { children: t("configuration") }), (0, react_jsx_runtime.jsx)("dd", { children: configuration })] }), entry.enabled ? (0, react_jsx_runtime.jsxs)("div", { children: [(0, react_jsx_runtime.jsx)("dt", { children: t("cordis") }), (0, react_jsx_runtime.jsx)("dd", { children: status })] }) : null]
|
|
205
|
+
})]
|
|
206
|
+
}) : null]
|
|
207
|
+
}, entry.entryId);
|
|
208
|
+
})
|
|
209
|
+
}) : null
|
|
210
|
+
]
|
|
211
|
+
}) : null
|
|
212
|
+
]
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
//#endregion
|
|
216
|
+
//#region lib/types/client/locales.js
|
|
217
|
+
/** Copy dictionaries for the plugin inventory Settings section. */
|
|
218
|
+
/** Simplified Chinese dictionary and key source of truth. */
|
|
219
|
+
const zh = {
|
|
220
|
+
tab: "插件列表",
|
|
221
|
+
loading: "正在读取插件…",
|
|
222
|
+
error: "暂时无法读取插件。",
|
|
223
|
+
retry: "重试",
|
|
224
|
+
search: "搜索插件",
|
|
225
|
+
catalog: "插件列表",
|
|
226
|
+
empty: "暂无插件。",
|
|
227
|
+
emptySearch: "没有匹配的插件。",
|
|
228
|
+
enabledTag: "已启用",
|
|
229
|
+
disabledTag: "已停用",
|
|
230
|
+
configuration: "配置状态",
|
|
231
|
+
cordis: "Cordis 状态",
|
|
232
|
+
unobserved: "未挂载",
|
|
233
|
+
pending: "等待依赖",
|
|
234
|
+
loadingPhase: "加载中",
|
|
235
|
+
active: "已挂载",
|
|
236
|
+
failed: "挂载失败",
|
|
237
|
+
unloading: "卸载中"
|
|
238
|
+
};
|
|
239
|
+
/** English dictionary checked against the Chinese key set. */
|
|
240
|
+
const en = {
|
|
241
|
+
tab: "Plugin list",
|
|
242
|
+
loading: "Reading plugins…",
|
|
243
|
+
error: "Plugins are temporarily unavailable.",
|
|
244
|
+
retry: "Retry",
|
|
245
|
+
search: "Search plugins",
|
|
246
|
+
catalog: "Plugin list",
|
|
247
|
+
empty: "No plugins are available.",
|
|
248
|
+
emptySearch: "No matching plugins.",
|
|
249
|
+
enabledTag: "Enabled",
|
|
250
|
+
disabledTag: "Disabled",
|
|
251
|
+
configuration: "Configuration",
|
|
252
|
+
cordis: "Cordis status",
|
|
253
|
+
unobserved: "Not mounted",
|
|
254
|
+
pending: "Waiting for dependencies",
|
|
255
|
+
loadingPhase: "Loading",
|
|
256
|
+
active: "Mounted",
|
|
257
|
+
failed: "Mount failed",
|
|
258
|
+
unloading: "Unloading"
|
|
259
|
+
};
|
|
260
|
+
//#endregion
|
|
261
|
+
//#region lib/types/client/index.js
|
|
262
|
+
/** Read-only Host plugin inventory registered into Web Settings. */
|
|
263
|
+
/** Dictionary namespace owned by this plugin. */
|
|
264
|
+
const NS = "settings.pluginInventory";
|
|
265
|
+
/** Services required by the Settings registration and generated Remote face. */
|
|
266
|
+
const inject = [
|
|
267
|
+
"slots",
|
|
268
|
+
"locale",
|
|
269
|
+
"remote",
|
|
270
|
+
"remote.pluginInventory"
|
|
271
|
+
];
|
|
272
|
+
/** Contribute the lazy inventory tab to the Plugins settings section. */
|
|
273
|
+
function apply(ctx) {
|
|
274
|
+
ctx.effect(() => ctx.locale.register(NS, {
|
|
275
|
+
zh,
|
|
276
|
+
en
|
|
277
|
+
}), "ui-settings-plugin-inventory: dictionaries");
|
|
278
|
+
const t = ctx.locale.bind(NS);
|
|
279
|
+
const list = async () => {
|
|
280
|
+
const result = await ctx.remote.pluginInventory.list();
|
|
281
|
+
if (!result.ok) throw new Error(`pluginInventory.list failed: ${result.error.code}: ${result.error.message}`);
|
|
282
|
+
return result.value;
|
|
283
|
+
};
|
|
284
|
+
const injected = () => ({ list });
|
|
285
|
+
ctx.slots.inject("settings.plugins.tab", () => ctx.slots.register({
|
|
286
|
+
name: "settings.plugins.tab",
|
|
287
|
+
id: "all",
|
|
288
|
+
order: 10,
|
|
289
|
+
label: () => t("tab"),
|
|
290
|
+
locale: NS,
|
|
291
|
+
inject: injected
|
|
292
|
+
}, PluginInventorySettingsTab));
|
|
293
|
+
}
|
|
294
|
+
//#endregion
|
|
295
|
+
exports.NS = NS;
|
|
296
|
+
exports.apply = apply;
|
|
297
|
+
exports.inject = inject;
|
|
298
|
+
return module.exports;
|
|
299
|
+
}
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
//# sourceMappingURL=client.js.map
|
package/lib/index.js
ADDED
package/lib/invariant.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
//#region lib/types/invariant.js
|
|
2
|
+
/** Package-owned invariant companion. @module @deepseek-ai/dsh-client-ui-settings-plugin-inventory/invariant */
|
|
3
|
+
const PACKAGE_NAME = "@deepseek-ai/dsh-client-ui-settings-plugin-inventory";
|
|
4
|
+
/** Cordis companion plugin name. */
|
|
5
|
+
const name = "client-ui-settings-plugin-inventory-invariant";
|
|
6
|
+
/** Service required before the companion can reserve package ownership. */
|
|
7
|
+
const inject = ["invariants"];
|
|
8
|
+
/** No runtime invariant: this package owns a read-only Settings contribution. */
|
|
9
|
+
const install = () => {};
|
|
10
|
+
/** Register this package's invariant companion. */
|
|
11
|
+
const apply = (ctx) => Promise.resolve(ctx.invariants.register(PACKAGE_NAME, install));
|
|
12
|
+
//#endregion
|
|
13
|
+
export { apply, inject, name };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import type { PluginInventorySnapshot } from '@deepseek-ai/dsh-api-remotes/client';
|
|
3
|
+
import type { InjectFace, PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
|
|
4
|
+
/** Registration-side Remote face used by the section. */
|
|
5
|
+
export interface PluginInventorySettingsTabInjected {
|
|
6
|
+
/** Read a current Host inventory snapshot. */
|
|
7
|
+
list: () => Promise<PluginInventorySnapshot>;
|
|
8
|
+
}
|
|
9
|
+
/** Full component props assembled by the Settings slot renderer. */
|
|
10
|
+
export type PluginInventorySettingsTabProps = PropsRuntime<'settings.plugins.tab'> & PropsLocale<'settings.pluginInventory'> & InjectFace<PluginInventorySettingsTabInjected>;
|
|
11
|
+
/** Render the read-only current Loader inventory. */
|
|
12
|
+
export declare function PluginInventorySettingsTab({ list, t }: PluginInventorySettingsTabProps): ReactNode;
|
|
13
|
+
//# sourceMappingURL=PluginInventorySettingsTab.d.ts.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** Read-only Host plugin inventory registered into Web Settings. */
|
|
2
|
+
import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client';
|
|
3
|
+
import { type PluginInventoryLocaleKey } from './locales.ts';
|
|
4
|
+
export type { PluginInventorySettingsTabInjected, PluginInventorySettingsTabProps } from './PluginInventorySettingsTab.tsx';
|
|
5
|
+
export type { PluginInventoryLocaleKey } from './locales.ts';
|
|
6
|
+
declare module '@deepseek-ai/dsh-client-ui-slots' {
|
|
7
|
+
interface LocaleNamespaceMap {
|
|
8
|
+
/** Read-only Host plugin inventory copy. */
|
|
9
|
+
'settings.pluginInventory': PluginInventoryLocaleKey;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
/** Dictionary namespace owned by this plugin. */
|
|
13
|
+
export declare const NS = "settings.pluginInventory";
|
|
14
|
+
/** Services required by the Settings registration and generated Remote face. */
|
|
15
|
+
export declare const inject: string[];
|
|
16
|
+
/** Contribute the lazy inventory tab to the Plugins settings section. */
|
|
17
|
+
export declare function apply(ctx: ClientContext): void;
|
|
18
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/** Copy dictionaries for the plugin inventory Settings section. */
|
|
2
|
+
/** Simplified Chinese dictionary and key source of truth. */
|
|
3
|
+
export declare const zh: {
|
|
4
|
+
tab: string;
|
|
5
|
+
loading: string;
|
|
6
|
+
error: string;
|
|
7
|
+
retry: string;
|
|
8
|
+
search: string;
|
|
9
|
+
catalog: string;
|
|
10
|
+
empty: string;
|
|
11
|
+
emptySearch: string;
|
|
12
|
+
enabledTag: string;
|
|
13
|
+
disabledTag: string;
|
|
14
|
+
configuration: string;
|
|
15
|
+
cordis: string;
|
|
16
|
+
unobserved: string;
|
|
17
|
+
pending: string;
|
|
18
|
+
loadingPhase: string;
|
|
19
|
+
active: string;
|
|
20
|
+
failed: string;
|
|
21
|
+
unloading: string;
|
|
22
|
+
};
|
|
23
|
+
/** Plugin inventory locale key union. */
|
|
24
|
+
export type PluginInventoryLocaleKey = keyof typeof zh;
|
|
25
|
+
/** English dictionary checked against the Chinese key set. */
|
|
26
|
+
export declare const en: {
|
|
27
|
+
tab: string;
|
|
28
|
+
loading: string;
|
|
29
|
+
error: string;
|
|
30
|
+
retry: string;
|
|
31
|
+
search: string;
|
|
32
|
+
catalog: string;
|
|
33
|
+
empty: string;
|
|
34
|
+
emptySearch: string;
|
|
35
|
+
enabledTag: string;
|
|
36
|
+
disabledTag: string;
|
|
37
|
+
configuration: string;
|
|
38
|
+
cordis: string;
|
|
39
|
+
unobserved: string;
|
|
40
|
+
pending: string;
|
|
41
|
+
loadingPhase: string;
|
|
42
|
+
active: string;
|
|
43
|
+
failed: string;
|
|
44
|
+
unloading: string;
|
|
45
|
+
};
|
|
46
|
+
//# sourceMappingURL=locales.d.ts.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Package-owned invariant companion. @module @deepseek-ai/dsh-client-ui-settings-plugin-inventory/invariant */
|
|
2
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
3
|
+
/** Cordis companion plugin name. */
|
|
4
|
+
export declare const name = "client-ui-settings-plugin-inventory-invariant";
|
|
5
|
+
/** Service required before the companion can reserve package ownership. */
|
|
6
|
+
export declare const inject: string[];
|
|
7
|
+
/** Register this package's invariant companion. */
|
|
8
|
+
export declare const apply: (ctx: Context) => Promise<() => void>;
|
|
9
|
+
//# sourceMappingURL=invariant.d.ts.map
|
package/package.json
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@deepseek-ai/dsh-client-ui-settings-plugin-inventory",
|
|
3
|
+
"description": "Read-only Cordis Loader inventory tab in Web Plugins settings",
|
|
4
|
+
"version": "0.0.1-rc.3",
|
|
5
|
+
"publishConfig": {
|
|
6
|
+
"access": "restricted"
|
|
7
|
+
},
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/deepseek-ai/deepseek-harness.git",
|
|
11
|
+
"directory": "packages/client/ui-settings-plugin-inventory"
|
|
12
|
+
},
|
|
13
|
+
"type": "module",
|
|
14
|
+
"main": "lib/index.js",
|
|
15
|
+
"types": "lib/types/index.d.ts",
|
|
16
|
+
"exports": {
|
|
17
|
+
".": {
|
|
18
|
+
"types": "./lib/types/index.d.ts",
|
|
19
|
+
"default": "./lib/index.js"
|
|
20
|
+
},
|
|
21
|
+
"./invariant": {
|
|
22
|
+
"types": "./lib/types/invariant.d.ts",
|
|
23
|
+
"default": "./lib/invariant.js"
|
|
24
|
+
},
|
|
25
|
+
"./client": {
|
|
26
|
+
"types": "./lib/types/client/index.d.ts",
|
|
27
|
+
"default": "./lib/client.js"
|
|
28
|
+
},
|
|
29
|
+
"./src/*": "./src/*",
|
|
30
|
+
"./package.json": "./package.json"
|
|
31
|
+
},
|
|
32
|
+
"dsh": {
|
|
33
|
+
"client": {
|
|
34
|
+
"inject": [
|
|
35
|
+
"@deepseek-ai/dsh-api-remotes",
|
|
36
|
+
"@deepseek-ai/dsh-client-runtime",
|
|
37
|
+
"@deepseek-ai/dsh-client-ui-settings",
|
|
38
|
+
"@deepseek-ai/dsh-client-locale"
|
|
39
|
+
],
|
|
40
|
+
"platform": "web"
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
"license": "BSD-3-Clause",
|
|
44
|
+
"peerDependencies": {
|
|
45
|
+
"react": "^18.2.0",
|
|
46
|
+
"@deepseek-ai/dsh-api-remotes": "^0.0.1-rc.3",
|
|
47
|
+
"@deepseek-ai/dsh-client-runtime": "^0.0.1-rc.3",
|
|
48
|
+
"@deepseek-ai/dsh-client-locale": "^0.0.1-rc.3",
|
|
49
|
+
"@deepseek-ai/dsh-client-ui-primitives": "^0.0.1-rc.3",
|
|
50
|
+
"@deepseek-ai/cordis": "^4.0.1-rc.1",
|
|
51
|
+
"@deepseek-ai/dsh-client-ui-settings": "^0.0.1-rc.3",
|
|
52
|
+
"@deepseek-ai/dsh-invariants": "^0.0.1-rc.3",
|
|
53
|
+
"@deepseek-ai/dsh-client-ui-slots": "^0.0.1-rc.3"
|
|
54
|
+
},
|
|
55
|
+
"devDependencies": {
|
|
56
|
+
"@testing-library/react": "^16.1.0",
|
|
57
|
+
"@types/react": "~18.3.1",
|
|
58
|
+
"react": "^18.2.0",
|
|
59
|
+
"react-dom": "^18.2.0",
|
|
60
|
+
"@deepseek-ai/dsh-client-locale": "^0.0.1-rc.3",
|
|
61
|
+
"@deepseek-ai/dsh-client-runtime": "^0.0.1-rc.3",
|
|
62
|
+
"@deepseek-ai/dsh-client-test-runtime": "^0.0.1-rc.3",
|
|
63
|
+
"@deepseek-ai/dsh-client-ui-primitives": "^0.0.1-rc.3",
|
|
64
|
+
"@deepseek-ai/dsh-client-ui-settings": "^0.0.1-rc.3",
|
|
65
|
+
"@deepseek-ai/dsh-api-remotes": "^0.0.1-rc.3",
|
|
66
|
+
"@deepseek-ai/dsh-invariants": "^0.0.1-rc.3",
|
|
67
|
+
"@deepseek-ai/dsh-client-ui-slots": "^0.0.1-rc.3",
|
|
68
|
+
"@deepseek-ai/cordis": "^4.0.1-rc.1"
|
|
69
|
+
},
|
|
70
|
+
"files": [
|
|
71
|
+
"lib/index.js",
|
|
72
|
+
"lib/invariant.js",
|
|
73
|
+
"lib/client.js",
|
|
74
|
+
"lib/types/**/*.d.ts"
|
|
75
|
+
],
|
|
76
|
+
"scripts": {
|
|
77
|
+
"bundle": "tsdown",
|
|
78
|
+
"watch": "tsdown --watch"
|
|
79
|
+
}
|
|
80
|
+
}
|