@anionex/dsh-vision-toolkit 0.1.6 → 0.1.7
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.i18n.yaml +2 -2
- package/README.md +6 -10
- package/README.zh.md +6 -10
- package/lib/client.js +85 -16
- package/lib/client.js.map +1 -1
- package/lib/types/client/index.d.ts +13 -5
- package/lib/types/client/index.d.ts.map +1 -1
- package/lib/types/web.d.ts +1 -0
- package/lib/types/web.d.ts.map +1 -1
- package/lib/web.js +61 -8
- package/lib/web.js.map +1 -1
- package/package.json +1 -1
- package/src/client/index.tsx +95 -20
- package/src/web.ts +74 -9
package/README.i18n.yaml
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
|
3
3
|
# after editing either side, bring the other along and re-record with:
|
|
4
4
|
# pnpm run verify-translation-pairing --write dsh-vision-dark-theme/README.md
|
|
5
|
-
README.md:
|
|
6
|
-
README.zh.md:
|
|
5
|
+
README.md: ab7ac8d402f6da738a0d70cad3170c3dc0d970cb
|
|
6
|
+
README.zh.md: 6d6da22d56babde78acffa0b7865b941476f0134
|
package/README.md
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
# DSH Vision Toolkit
|
|
4
4
|
|
|
5
5
|
[](https://x.com/anion_ex)
|
|
6
|
-
[](https://github.com/Anionex/dsh-vision-toolkit/releases/tag/v0.1.7)
|
|
7
|
+
[](tests)
|
|
8
8
|
[](LICENSE)
|
|
9
9
|
[](package.json)
|
|
10
10
|
[](runtime/requirements.lock)
|
|
@@ -191,7 +191,7 @@ dsh plugin --profile web remove @dsh-external/dsh-vision-toolkit
|
|
|
191
191
|
dsh plugin --profile web add @anionex/dsh-vision-toolkit
|
|
192
192
|
```
|
|
193
193
|
|
|
194
|
-
After restarting, Settings → Vision should report plugin version **0.1.
|
|
194
|
+
After restarting, Settings → Vision should report plugin version **0.1.7**.
|
|
195
195
|
|
|
196
196
|
For a registry installation, update the dependency through the profile package manager:
|
|
197
197
|
|
|
@@ -257,13 +257,9 @@ The bundle defaults to the managed runtime. A profile patch can override the pro
|
|
|
257
257
|
|
|
258
258
|
### Credentials
|
|
259
259
|
|
|
260
|
-
|
|
260
|
+
The Web Settings page accepts the actual value in its write-only **API key** field. Leave that field blank to retain an existing key; saving a non-empty value writes it under the advanced **Credential name** reference, which defaults to `VISION_API_KEY`. Headless deployments can pre-provision the same reference in `$DSH_HOME/.credentials.yaml`.
|
|
261
261
|
|
|
262
|
-
|
|
263
|
-
dsh credentials set VISION_API_KEY
|
|
264
|
-
```
|
|
265
|
-
|
|
266
|
-
The reference is stored in Settings; the value is not. Remote operations resolve it once per call and inject it only into that subprocess environment. The plugin excludes user `.env` files, checkout `.env` files, `PYTHONPATH`, `PYTHONHOME`, `VIRTUAL_ENV`, and user site-packages so ambient Python or upstream configuration cannot override the selected DSH provider. Logs, errors, tool results, Artifact metadata, and Settings responses never contain the secret.
|
|
262
|
+
Settings store only the reference, never the value. The browser does not receive a stored value, and a successful save clears the field instead of echoing it. Remote operations resolve the reference once per call and inject the value only into that subprocess environment. The plugin excludes user `.env` files, checkout `.env` files, `PYTHONPATH`, `PYTHONHOME`, `VIRTUAL_ENV`, and user site-packages so ambient Python or upstream configuration cannot override the selected DSH provider. Logs, errors, tool results, Artifact metadata, and Settings responses never contain the secret.
|
|
267
263
|
|
|
268
264
|
### Managed and external runtimes
|
|
269
265
|
|
|
@@ -346,7 +342,7 @@ The committed evidence records an initial `6.04%` difference across six non-zero
|
|
|
346
342
|
| Symptom | Resolution |
|
|
347
343
|
|---|---|
|
|
348
344
|
| `Model "..." does not support image input. (attachment-error)` | The image used DSH's native model-attachment channel, so a text-only model rejected the turn before the Skill or Vision Toolkit could run. Use DSH Paste Input's attachment button, paste, or drop flow so the file is copied into the session workspace and represented by a path, then invoke `/vision-tools`. Restart the Web profile and reload the page after installing or upgrading either browser plugin. |
|
|
349
|
-
| Credential reported missing |
|
|
345
|
+
| Credential reported missing | Paste the key into Web Settings **API key**, keep the advanced **Credential name** aligned with `provider.credential`, save, then rerun health. Headless deployments can provision the same reference in `$DSH_HOME/.credentials.yaml`. Local-only tools do not need it. |
|
|
350
346
|
| Runtime preparation fails | Read the Settings runtime error, verify Python 3.11+, package-cache/network access, disk permissions, and the exact external pin. Save only after correcting the candidate; the active generation remains intact. |
|
|
351
347
|
| Chrome is not found | Install Chrome, Chromium, or Edge or configure an environment where one is discoverable. Only `vision_html_screenshot` is unavailable. |
|
|
352
348
|
| macOS displays a keychain dialog | Confirm the current built adapter is installed and no stale external `html_shot`/headless Chrome process is running. Current launches use a mock keychain and disposable profile; cancel the dialog rather than resetting the login keychain. |
|
package/README.zh.md
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
# DSH Vision Toolkit
|
|
4
4
|
|
|
5
5
|
[](https://x.com/anion_ex)
|
|
6
|
-
[](https://github.com/Anionex/dsh-vision-toolkit/releases/tag/v0.1.7)
|
|
7
|
+
[](tests)
|
|
8
8
|
[](LICENSE)
|
|
9
9
|
[](package.json)
|
|
10
10
|
[](runtime/requirements.lock)
|
|
@@ -191,7 +191,7 @@ dsh plugin --profile web remove @dsh-external/dsh-vision-toolkit
|
|
|
191
191
|
dsh plugin --profile web add @anionex/dsh-vision-toolkit
|
|
192
192
|
```
|
|
193
193
|
|
|
194
|
-
重启后,Settings → 视觉工具 应显示插件版本 **0.1.
|
|
194
|
+
重启后,Settings → 视觉工具 应显示插件版本 **0.1.7**。
|
|
195
195
|
|
|
196
196
|
通过注册表安装时,使用 Profile 的包管理命令更新依赖:
|
|
197
197
|
|
|
@@ -257,13 +257,9 @@ Bundle 默认使用 managed 运行时。Profile patch 可以覆盖提供方与
|
|
|
257
257
|
|
|
258
258
|
### Credential
|
|
259
259
|
|
|
260
|
-
|
|
260
|
+
Web 设置页的只写 **API 密钥** 输入框直接接收真实密钥。留空表示保留现有密钥;填写后保存,会把密钥写入高级设置中的 **凭据名称**,默认名称是 `VISION_API_KEY`。Headless 部署可以在 `$DSH_HOME/.credentials.yaml` 中预置同名引用。
|
|
261
261
|
|
|
262
|
-
|
|
263
|
-
dsh credentials set VISION_API_KEY
|
|
264
|
-
```
|
|
265
|
-
|
|
266
|
-
Settings 只保存引用,不保存值。每次远程操作都会重新解析引用,并只把值注入对应子进程环境。插件排除用户 `.env`、checkout `.env`、`PYTHONPATH`、`PYTHONHOME`、`VIRTUAL_ENV` 和用户 site-packages,避免环境中的 Python 或上游配置覆盖选定的 DSH 提供方。日志、错误、工具结果、产物元数据和 Settings 响应都不包含密钥。
|
|
262
|
+
Settings 只保存引用,不保存值。浏览器不会读取已保存的密钥,保存成功后输入框也会立即清空而不是回显。每次远程操作都会重新解析引用,并只把值注入对应子进程环境。插件排除用户 `.env`、checkout `.env`、`PYTHONPATH`、`PYTHONHOME`、`VIRTUAL_ENV` 和用户 site-packages,避免环境中的 Python 或上游配置覆盖选定的 DSH 提供方。日志、错误、工具结果、产物元数据和 Settings 响应都不包含密钥。
|
|
267
263
|
|
|
268
264
|
### Managed 与 external 运行时
|
|
269
265
|
|
|
@@ -346,7 +342,7 @@ npm run example:ui-restoration:write
|
|
|
346
342
|
| 症状 | 解决方法 |
|
|
347
343
|
|---|---|
|
|
348
344
|
| `Model "..." does not support image input. (attachment-error)` | 图片走了 DSH 的模型原生附件通道,纯文本模型会在 Skill 或 Vision Toolkit 运行前拒绝该轮。请使用 DSH Paste Input 的附件按钮、粘贴或拖放流程,让文件先复制到会话工作区并以路径形式进入消息,再调用 `/vision-tools`。安装或升级任一浏览器插件后,需要重启 Web Profile 并刷新页面。 |
|
|
349
|
-
| Credential 显示缺失 |
|
|
345
|
+
| Credential 显示缺失 | 在 Web 设置页的 **API 密钥** 中粘贴密钥,确认高级设置中的 **凭据名称** 与 `provider.credential` 一致,保存后重新运行健康检查。Headless 部署可以在 `$DSH_HOME/.credentials.yaml` 中预置同名引用。本地工具不需要它。 |
|
|
350
346
|
| 运行时准备失败 | 查看 Settings 中的运行时错误,检查 Python 3.11+、软件包缓存/网络、磁盘权限和精确 external 固定版本。修正候选后再保存;当前 generation 不受影响。 |
|
|
351
347
|
| 找不到 Chrome | 安装 Chrome、Chromium 或 Edge,或让其中一个可被运行环境发现。只有 `vision_html_screenshot` 不可用。 |
|
|
352
348
|
| macOS 弹出钥匙串对话框 | 确认安装的是当前构建产物,且没有遗留的外部 `html_shot`/headless Chrome 进程。当前启动使用 mock keychain 和一次性 profile;取消对话框,不要重置登录钥匙串。 |
|
package/lib/client.js
CHANGED
|
@@ -24,9 +24,17 @@ const en = {
|
|
|
24
24
|
settingsIntro: 'Configure the pinned visual engineering runtime, its external vision endpoint, and local safety limits.',
|
|
25
25
|
externalNotice: 'Remote tools send the selected image bytes to the configured external vision API. Local crop, trace, pixel diff, palette, foreground extraction, and HTML rendering do not upload images.',
|
|
26
26
|
provider: 'Vision service',
|
|
27
|
-
providerHint: 'Choose the API protocol, then provide the service address, model, and
|
|
27
|
+
providerHint: 'Choose the API protocol, then provide the service address, model, and API key used by online vision features.',
|
|
28
28
|
baseUrl: 'Base URL',
|
|
29
|
-
|
|
29
|
+
apiKey: 'API key',
|
|
30
|
+
apiKeyPlaceholderMissing: 'Paste the API key',
|
|
31
|
+
apiKeyPlaceholderConfigured: 'Saved; leave blank to keep it',
|
|
32
|
+
apiKeyHint: 'The key is stored in DSH Credentials and is never shown again after saving.',
|
|
33
|
+
apiKeyLocked: 'The current key comes from a read-only source and cannot be replaced here.',
|
|
34
|
+
apiKeyBlank: 'The API key cannot contain only spaces.',
|
|
35
|
+
apiKeyInvalid: 'Paste only the key, without a variable name, quotes, spaces, or line breaks.',
|
|
36
|
+
credential: 'Credential name',
|
|
37
|
+
credentialHint: 'Advanced: the API key is stored under this name. Keep VISION_API_KEY unless another plugin configuration requires a different reference.',
|
|
30
38
|
model: 'Model',
|
|
31
39
|
protocol: 'API protocol',
|
|
32
40
|
anthropicThinking: 'Anthropic thinking',
|
|
@@ -48,7 +56,7 @@ const en = {
|
|
|
48
56
|
saving: 'Validating runtime…',
|
|
49
57
|
reload: 'Reload',
|
|
50
58
|
saved: 'Settings validated and applied.',
|
|
51
|
-
readOnly: '
|
|
59
|
+
readOnly: 'Service settings are read-only. A writable API key can still be saved.',
|
|
52
60
|
configured: 'Configured',
|
|
53
61
|
missing: 'Missing',
|
|
54
62
|
source: 'Source',
|
|
@@ -62,7 +70,7 @@ const en = {
|
|
|
62
70
|
connectionHint: 'Connection testing explicitly sends the configured credential to GET /models. It uploads no image and creates no completion.',
|
|
63
71
|
saveBeforeTesting: 'Save service changes before testing the connection.',
|
|
64
72
|
advanced: 'Advanced settings',
|
|
65
|
-
advancedHint: '
|
|
73
|
+
advancedHint: 'Credential name, provider compatibility, output language, resource limits, runtime source, Python, and additional readable directories.',
|
|
66
74
|
pluginVersion: 'Plugin',
|
|
67
75
|
upstreamVersion: 'Upstream',
|
|
68
76
|
activeGeneration: 'Runtime generation',
|
|
@@ -153,9 +161,17 @@ const zh = {
|
|
|
153
161
|
settingsIntro: '在这里设置视觉模型服务、工具运行环境,以及图片和文件的本地访问范围。',
|
|
154
162
|
externalNotice: '使用图像理解、目标定位、界面检测或文字识别等在线功能时,所选图片会发送到下方配置的视觉服务。图片裁剪、轮廓描摹、像素对比、主色提取、前景提取和网页截图均在本机完成,不会上传图片。',
|
|
155
163
|
provider: '在线视觉服务',
|
|
156
|
-
providerHint: '选择接口协议后,填写在线视觉功能使用的 API
|
|
164
|
+
providerHint: '选择接口协议后,填写在线视觉功能使用的 API 地址、模型名称和 API 密钥。',
|
|
157
165
|
baseUrl: 'API 地址',
|
|
158
|
-
|
|
166
|
+
apiKey: 'API 密钥',
|
|
167
|
+
apiKeyPlaceholderMissing: '粘贴 API 密钥',
|
|
168
|
+
apiKeyPlaceholderConfigured: '已保存;留空表示不修改',
|
|
169
|
+
apiKeyHint: '密钥会保存到 DSH 凭据存储,保存后不会在页面中回显。',
|
|
170
|
+
apiKeyLocked: '当前密钥来自只读配置,无法在此替换。',
|
|
171
|
+
apiKeyBlank: 'API 密钥不能只包含空格。',
|
|
172
|
+
apiKeyInvalid: '请只粘贴密钥本身,不要包含变量名、引号、空格或换行。',
|
|
173
|
+
credential: '凭据名称',
|
|
174
|
+
credentialHint: '高级用法:API 密钥会按此名称保存。除非其他插件配置要求不同名称,否则保持 VISION_API_KEY。',
|
|
159
175
|
model: '模型名称',
|
|
160
176
|
protocol: 'API 协议',
|
|
161
177
|
anthropicThinking: 'Anthropic thinking',
|
|
@@ -177,7 +193,7 @@ const zh = {
|
|
|
177
193
|
saving: '正在检查并应用…',
|
|
178
194
|
reload: '重新加载',
|
|
179
195
|
saved: '设置已保存并生效。',
|
|
180
|
-
readOnly: '
|
|
196
|
+
readOnly: '服务设置来自只读配置;如果 API 密钥可写,仍可在此保存密钥。',
|
|
181
197
|
configured: '已就绪',
|
|
182
198
|
missing: '未配置',
|
|
183
199
|
source: '配置来源',
|
|
@@ -191,7 +207,7 @@ const zh = {
|
|
|
191
207
|
connectionHint: '“检查本地环境”只检查本机依赖和目录;“测试服务连接”会携带已配置的 API 密钥请求 /models,但不会上传图片或调用模型。',
|
|
192
208
|
saveBeforeTesting: '修改服务配置后,请先保存,再测试连接。',
|
|
193
209
|
advanced: '高级设置',
|
|
194
|
-
advancedHint: '
|
|
210
|
+
advancedHint: '凭据名称、服务兼容参数、结果语言、资源限制、运行环境来源、Python 和额外可读目录。一般无需修改。',
|
|
195
211
|
pluginVersion: '插件版本',
|
|
196
212
|
upstreamVersion: '工具包版本',
|
|
197
213
|
activeGeneration: '本次运行已应用',
|
|
@@ -541,18 +557,48 @@ class VisionSettingsController {
|
|
|
541
557
|
return;
|
|
542
558
|
void this.load();
|
|
543
559
|
}
|
|
544
|
-
async save(value, expectedRevision) {
|
|
560
|
+
async save(value, expectedRevision, credentialValue, writeSettings) {
|
|
545
561
|
this.set({ ...this.state, action: 'save', error: undefined, message: undefined });
|
|
562
|
+
let snapshot = this.state.snapshot;
|
|
546
563
|
try {
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
564
|
+
if (writeSettings) {
|
|
565
|
+
snapshot = await apiRequest({
|
|
566
|
+
method: 'POST',
|
|
567
|
+
headers: { 'Content-Type': 'application/json' },
|
|
568
|
+
body: JSON.stringify({ action: 'save', expectedRevision, value }),
|
|
569
|
+
});
|
|
570
|
+
}
|
|
571
|
+
if (snapshot === undefined)
|
|
572
|
+
throw new Error('Vision Toolkit Settings are unavailable');
|
|
573
|
+
if (credentialValue !== undefined) {
|
|
574
|
+
try {
|
|
575
|
+
snapshot = await apiRequest({
|
|
576
|
+
method: 'POST',
|
|
577
|
+
headers: { 'Content-Type': 'application/json' },
|
|
578
|
+
body: JSON.stringify({
|
|
579
|
+
action: 'credential',
|
|
580
|
+
expectedRevision: snapshot.settings.revision,
|
|
581
|
+
ref: snapshot.credential.ref,
|
|
582
|
+
value: credentialValue,
|
|
583
|
+
}),
|
|
584
|
+
});
|
|
585
|
+
}
|
|
586
|
+
catch (error) {
|
|
587
|
+
this.set({
|
|
588
|
+
status: 'ready',
|
|
589
|
+
snapshot,
|
|
590
|
+
health: this.state.health,
|
|
591
|
+
error: error instanceof Error ? error.message : String(error),
|
|
592
|
+
});
|
|
593
|
+
return false;
|
|
594
|
+
}
|
|
595
|
+
}
|
|
552
596
|
this.set({ status: 'ready', snapshot, health: this.state.health, message: 'saved' });
|
|
597
|
+
return true;
|
|
553
598
|
}
|
|
554
599
|
catch (error) {
|
|
555
600
|
this.set({ ...this.state, action: undefined, error: error instanceof Error ? error.message : String(error) });
|
|
601
|
+
return false;
|
|
556
602
|
}
|
|
557
603
|
}
|
|
558
604
|
async runHealth(testConnection) {
|
|
@@ -596,6 +642,18 @@ function positiveInteger(raw, label, t) {
|
|
|
596
642
|
throw new Error(t('positiveInteger', { field: label }));
|
|
597
643
|
return value;
|
|
598
644
|
}
|
|
645
|
+
function apiKeyFailure(value, t) {
|
|
646
|
+
if (value.length === 0)
|
|
647
|
+
return undefined;
|
|
648
|
+
const trimmed = value.trim();
|
|
649
|
+
if (trimmed.length === 0)
|
|
650
|
+
return t('apiKeyBlank');
|
|
651
|
+
const quoted = trimmed.length > 1 && ['"', '\'', '`'].includes(trimmed[0] ?? '') && trimmed.endsWith(trimmed[0] ?? '');
|
|
652
|
+
const environmentLine = /^[A-Z][A-Z0-9_]*=[^=]/u.test(trimmed);
|
|
653
|
+
if (quoted || environmentLine || !/^[\x21-\x7E]+$/u.test(trimmed))
|
|
654
|
+
return t('apiKeyInvalid');
|
|
655
|
+
return undefined;
|
|
656
|
+
}
|
|
599
657
|
function valueOf(draft, t) {
|
|
600
658
|
return {
|
|
601
659
|
provider: {
|
|
@@ -709,6 +767,7 @@ function LoadedSettings({ controller, t }) {
|
|
|
709
767
|
const state = (0, react_1.useSyncExternalStore)(controller.subscribe, controller.snapshot, controller.snapshot);
|
|
710
768
|
const snapshot = state.snapshot;
|
|
711
769
|
const [draft, setDraft] = (0, react_1.useState)(undefined);
|
|
770
|
+
const [apiKey, setApiKey] = (0, react_1.useState)('');
|
|
712
771
|
const [draftError, setDraftError] = (0, react_1.useState)(undefined);
|
|
713
772
|
(0, react_1.useEffect)(() => { if (state.status === 'idle')
|
|
714
773
|
void controller.load(); }, [controller, state.status]);
|
|
@@ -725,16 +784,26 @@ function LoadedSettings({ controller, t }) {
|
|
|
725
784
|
const update = (key, value) => setDraft(current => current === undefined ? current : { ...current, [key]: value });
|
|
726
785
|
const save = () => {
|
|
727
786
|
try {
|
|
787
|
+
const keyFailure = apiKeyFailure(apiKey, t);
|
|
788
|
+
if (keyFailure !== undefined) {
|
|
789
|
+
setDraftError(keyFailure);
|
|
790
|
+
return;
|
|
791
|
+
}
|
|
792
|
+
const credentialValue = apiKey.length === 0 ? undefined : apiKey.trim();
|
|
728
793
|
setDraftError(undefined);
|
|
729
|
-
void controller.save(valueOf(draft, t), snapshot.settings.revision)
|
|
794
|
+
void controller.save(valueOf(draft, t), snapshot.settings.revision, credentialValue, snapshot.writable).then(saved => { if (saved)
|
|
795
|
+
setApiKey(''); });
|
|
730
796
|
}
|
|
731
797
|
catch (error) {
|
|
732
798
|
setDraftError(error instanceof Error ? error.message : String(error));
|
|
733
799
|
}
|
|
734
800
|
};
|
|
735
801
|
const busy = state.action !== undefined;
|
|
802
|
+
const credentialMatchesSnapshot = draft.credential.trim() === snapshot.credential.ref;
|
|
803
|
+
const keyLocked = credentialMatchesSnapshot && !snapshot.credential.writable;
|
|
804
|
+
const canSave = snapshot.writable || (apiKey.length > 0 && !keyLocked);
|
|
736
805
|
const runtimeErrorTitle = snapshot.runtime.ready ? t('runtimeCandidateRejected') : t('runtimeUnavailable');
|
|
737
|
-
return ((0, jsx_runtime_1.jsxs)("div", { className: "dvt-settings", children: [(0, jsx_runtime_1.jsx)("div", { className: "dvt-alert notice", children: t('externalNotice') }), !snapshot.writable ? (0, jsx_runtime_1.jsx)("div", { className: "dvt-alert warning", children: t('readOnly') }) : null, draftError === undefined ? null : (0, jsx_runtime_1.jsx)("div", { className: "dvt-alert error", children: draftError }), state.error === undefined ? null : (0, jsx_runtime_1.jsx)("div", { className: "dvt-alert error", children: state.error }), state.message === 'saved' ? (0, jsx_runtime_1.jsx)("div", { className: "dvt-alert success", children: t('saved') }) : null, snapshot.runtime.lastError === undefined ? null : (0, jsx_runtime_1.jsxs)("div", { className: "dvt-alert error", children: [(0, jsx_runtime_1.jsx)("strong", { children: runtimeErrorTitle }), (0, jsx_runtime_1.jsx)("span", { children: snapshot.runtime.lastError })] }), (0, jsx_runtime_1.jsxs)("section", { className: "dvt-panel dvt-essential", children: [(0, jsx_runtime_1.jsxs)("div", { className: "dvt-panel-title", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("h3", { children: t('provider') }), (0, jsx_runtime_1.jsx)("p", { children: t('providerHint') })] }), (0, jsx_runtime_1.jsx)("span", { className: `dvt-badge ${snapshot.credential.configured ? 'ok' : 'error'}`, children: snapshot.credential.configured ? t('configured') : t('missing') })] }), (0, jsx_runtime_1.jsxs)("div", { className: "dvt-form-grid", children: [(0, jsx_runtime_1.jsx)(Field, { label: t('protocol'), children: (0, jsx_runtime_1.jsxs)("select", { value: draft.protocol, onChange: (event) => { update('protocol', event.target.value); }, children: [(0, jsx_runtime_1.jsx)("option", { value: "openai", children: "OpenAI Chat Completions" }), (0, jsx_runtime_1.jsx)("option", { value: "anthropic", children: "Anthropic Messages" })] }) }), (0, jsx_runtime_1.jsx)(Field, { label: t('baseUrl'), children: (0, jsx_runtime_1.jsx)(dsh_client_ui_primitives_1.Input, { value: draft.baseUrl, onChange: (event) => { update('baseUrl', event.target.value); } }) }), (0, jsx_runtime_1.jsx)(Field, { label: t('model'), children: (0, jsx_runtime_1.jsx)(dsh_client_ui_primitives_1.Input, { value: draft.model, onChange: (event) => { update('model', event.target.value); } }) }), (0, jsx_runtime_1.jsx)(Field, { label: t('credential'), hint: snapshot.credential.source === undefined ? undefined : t('sourceHint', { source: t('source'), value: credentialSource(snapshot.credential.source, t) }), children: (0, jsx_runtime_1.jsx)(dsh_client_ui_primitives_1.Input, { value: draft.credential, onChange: (event) => { update('credential', event.target.value); } }) })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "dvt-save-row", children: [(0, jsx_runtime_1.jsx)(dsh_client_ui_primitives_1.Button, { variant: "primary", disabled: !snapshot.writable || busy, onClick: save, children: state.action === 'save' ? t('saving') : t('save') }), (0, jsx_runtime_1.jsx)(dsh_client_ui_primitives_1.Button, { variant: "outline", disabled: busy, onClick: () => { void controller.load(); }, children: t('reload') })] }), (0, jsx_runtime_1.jsxs)("section", { className: "dvt-panel", children: [(0, jsx_runtime_1.jsxs)("div", { className: "dvt-panel-title", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("h3", { children: t('health') }), (0, jsx_runtime_1.jsx)("p", { children: t('connectionHint') })] }), (0, jsx_runtime_1.jsxs)("div", { className: "dvt-actions", children: [(0, jsx_runtime_1.jsx)(dsh_client_ui_primitives_1.Button, { size: "sm", variant: "outline", disabled: busy || !snapshot.runtime.ready, onClick: () => { void controller.runHealth(false); }, children: state.action === 'health' ? t('testing') : t('runHealth') }), (0, jsx_runtime_1.jsx)(dsh_client_ui_primitives_1.Button, { size: "sm", variant: "primary", disabled: busy || !snapshot.runtime.ready, onClick: () => { void controller.runHealth(true); }, children: state.action === 'connection' ? t('testing') : t('testConnection') })] })] }), (0, jsx_runtime_1.jsx)("p", { className: "dvt-muted", children: t('saveBeforeTesting') }), state.health === undefined ? (0, jsx_runtime_1.jsx)("p", { className: "dvt-muted", children: t('notTested') }) : (0, jsx_runtime_1.jsx)("div", { className: "dvt-health-grid", children: Object.entries(state.health.checks).map(([name, check]) => (0, jsx_runtime_1.jsxs)("div", { "data-status": check.status, children: [(0, jsx_runtime_1.jsx)("span", { children: t(HEALTH_NAME_KEYS[name] ?? 'health') }), (0, jsx_runtime_1.jsx)("strong", { children: t(HEALTH_STATUS_KEYS[check.status]) }), (0, jsx_runtime_1.jsx)("p", { children: healthDetail(name, check.detail, t) })] }, name)) })] }), (0, jsx_runtime_1.jsxs)("details", { className: "dvt-advanced", children: [(0, jsx_runtime_1.jsxs)("summary", { children: [(0, jsx_runtime_1.jsxs)("span", { children: [(0, jsx_runtime_1.jsx)("strong", { children: t('advanced') }), (0, jsx_runtime_1.jsx)("small", { children: t('advancedHint') })] }), (0, jsx_runtime_1.jsx)("span", { className: "dvt-details-chevron", "aria-hidden": "true", children: "\u2304" })] }), (0, jsx_runtime_1.jsxs)("div", { className: "dvt-advanced-body", children: [(0, jsx_runtime_1.jsxs)("section", { className: "dvt-panel", children: [(0, jsx_runtime_1.jsx)("div", { className: "dvt-panel-title", children: (0, jsx_runtime_1.jsx)("h3", { children: t('provider') }) }), (0, jsx_runtime_1.jsxs)("div", { className: "dvt-form-grid", children: [draft.protocol === 'anthropic' ? (0, jsx_runtime_1.jsx)(Field, { label: t('anthropicThinking'), hint: t('anthropicThinkingHint'), children: (0, jsx_runtime_1.jsxs)("select", { "aria-label": t('anthropicThinking'), value: draft.anthropicThinking, onChange: (event) => { update('anthropicThinking', event.target.value); }, children: [(0, jsx_runtime_1.jsx)("option", { value: "omit", children: "omit (widest compatibility)" }), (0, jsx_runtime_1.jsx)("option", { value: "disabled", children: "disabled (model support required)" }), (0, jsx_runtime_1.jsx)("option", { value: "adaptive", children: "adaptive (model support required)" })] }) }) : null, (0, jsx_runtime_1.jsx)(Field, { label: t('userAgent'), children: (0, jsx_runtime_1.jsx)(dsh_client_ui_primitives_1.Input, { value: draft.userAgent, onChange: (event) => { update('userAgent', event.target.value); } }) })] })] }), (0, jsx_runtime_1.jsxs)("section", { className: "dvt-panel", children: [(0, jsx_runtime_1.jsx)("div", { className: "dvt-panel-title", children: (0, jsx_runtime_1.jsx)("h3", { children: t('limits') }) }), (0, jsx_runtime_1.jsxs)("div", { className: "dvt-form-grid", children: [(0, jsx_runtime_1.jsx)(Field, { label: t('language'), children: (0, jsx_runtime_1.jsxs)("select", { value: draft.language, onChange: (event) => { update('language', event.target.value); }, children: [(0, jsx_runtime_1.jsx)("option", { value: "zh", children: "\u4E2D\u6587" }), (0, jsx_runtime_1.jsx)("option", { value: "en", children: "English" })] }) }), (0, jsx_runtime_1.jsx)(Field, { label: t('timeout'), children: (0, jsx_runtime_1.jsx)(dsh_client_ui_primitives_1.Input, { inputMode: "numeric", value: draft.timeoutMs, onChange: (event) => { update('timeoutMs', event.target.value); } }) }), (0, jsx_runtime_1.jsx)(Field, { label: t('maxBytes'), children: (0, jsx_runtime_1.jsx)(dsh_client_ui_primitives_1.Input, { inputMode: "numeric", value: draft.maxImageBytes, onChange: (event) => { update('maxImageBytes', event.target.value); } }) }), (0, jsx_runtime_1.jsx)(Field, { label: t('maxPixels'), children: (0, jsx_runtime_1.jsx)(dsh_client_ui_primitives_1.Input, { inputMode: "numeric", value: draft.maxImagePixels, onChange: (event) => { update('maxImagePixels', event.target.value); } }) }), (0, jsx_runtime_1.jsx)(Field, { label: t('concurrency'), children: (0, jsx_runtime_1.jsx)(dsh_client_ui_primitives_1.Input, { inputMode: "numeric", value: draft.concurrency, onChange: (event) => { update('concurrency', event.target.value); } }) })] })] }), (0, jsx_runtime_1.jsxs)("section", { className: "dvt-panel", children: [(0, jsx_runtime_1.jsxs)("div", { className: "dvt-panel-title", children: [(0, jsx_runtime_1.jsx)("h3", { children: t('runtime') }), (0, jsx_runtime_1.jsx)("span", { className: `dvt-badge ${snapshot.runtime.ready ? 'ok' : 'error'}`, children: snapshot.runtime.ready ? snapshot.runtime.upstream?.source === 'managed' ? t('runtimeManaged') : snapshot.runtime.upstream?.source === 'external' ? t('runtimeExternal') : t('runtimeReady') : t('runtimeUnavailable') })] }), (0, jsx_runtime_1.jsxs)("div", { className: "dvt-form-grid", children: [(0, jsx_runtime_1.jsx)(Field, { label: t('runtimeMode'), children: (0, jsx_runtime_1.jsxs)("select", { value: draft.runtimeMode, onChange: (event) => { update('runtimeMode', event.target.value); }, children: [(0, jsx_runtime_1.jsx)("option", { value: "managed", children: t('runtimeManaged') }), (0, jsx_runtime_1.jsx)("option", { value: "external", children: t('runtimeExternal') })] }) }), draft.runtimeMode === 'external' ? (0, jsx_runtime_1.jsx)(Field, { label: t('toolkitPath'), children: (0, jsx_runtime_1.jsx)(dsh_client_ui_primitives_1.Input, { value: draft.toolkitPath, onChange: (event) => { update('toolkitPath', event.target.value); } }) }) : null, (0, jsx_runtime_1.jsx)(Field, { label: t('python'), children: (0, jsx_runtime_1.jsx)(dsh_client_ui_primitives_1.Input, { placeholder: "python3", value: draft.python, onChange: (event) => { update('python', event.target.value); } }) }), (0, jsx_runtime_1.jsx)(Field, { label: t('allowedDirs'), hint: t('allowedDirsHint'), children: (0, jsx_runtime_1.jsx)("textarea", { rows: 3, value: draft.allowedDirs, onChange: (event) => { update('allowedDirs', event.target.value); } }) })] }), snapshot.runtime.upstream === undefined ? null : (0, jsx_runtime_1.jsxs)("div", { className: "dvt-runtime-facts", children: [(0, jsx_runtime_1.jsx)("code", { children: snapshot.runtime.upstream.path }), (0, jsx_runtime_1.jsxs)("code", { children: [snapshot.runtime.upstream.python, " \u00B7 ", snapshot.runtime.upstream.pythonVersion] }), (0, jsx_runtime_1.jsx)("code", { children: snapshot.runtime.upstream.runtimeHome })] })] })] })] }), (0, jsx_runtime_1.jsxs)("footer", { className: "dvt-settings-footer", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("span", { className: "dvt-kicker", children: t('pluginKind') }), (0, jsx_runtime_1.jsx)("h2", { children: t('settingsTitle') }), (0, jsx_runtime_1.jsx)("p", { children: t('settingsIntro') })] }), (0, jsx_runtime_1.jsxs)("div", { className: "dvt-release", children: [(0, jsx_runtime_1.jsxs)("span", { children: [t('pluginVersion'), " ", (0, jsx_runtime_1.jsx)("strong", { children: snapshot.release.pluginVersion })] }), (0, jsx_runtime_1.jsxs)("span", { children: [t('upstreamVersion'), " ", (0, jsx_runtime_1.jsx)("strong", { children: snapshot.release.upstreamVersion })] }), (0, jsx_runtime_1.jsxs)("span", { children: [t('activeGeneration'), " ", (0, jsx_runtime_1.jsx)("strong", { children: t('activeGenerationValue', { generation: snapshot.runtime.generation }) })] })] })] })] }));
|
|
806
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: "dvt-settings", children: [(0, jsx_runtime_1.jsx)("div", { className: "dvt-alert notice", children: t('externalNotice') }), !snapshot.writable ? (0, jsx_runtime_1.jsx)("div", { className: "dvt-alert warning", children: t('readOnly') }) : null, draftError === undefined ? null : (0, jsx_runtime_1.jsx)("div", { className: "dvt-alert error", children: draftError }), state.error === undefined ? null : (0, jsx_runtime_1.jsx)("div", { className: "dvt-alert error", children: state.error }), state.message === 'saved' ? (0, jsx_runtime_1.jsx)("div", { className: "dvt-alert success", children: t('saved') }) : null, snapshot.runtime.lastError === undefined ? null : (0, jsx_runtime_1.jsxs)("div", { className: "dvt-alert error", children: [(0, jsx_runtime_1.jsx)("strong", { children: runtimeErrorTitle }), (0, jsx_runtime_1.jsx)("span", { children: snapshot.runtime.lastError })] }), (0, jsx_runtime_1.jsxs)("section", { className: "dvt-panel dvt-essential", children: [(0, jsx_runtime_1.jsxs)("div", { className: "dvt-panel-title", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("h3", { children: t('provider') }), (0, jsx_runtime_1.jsx)("p", { children: t('providerHint') })] }), (0, jsx_runtime_1.jsx)("span", { className: `dvt-badge ${snapshot.credential.configured ? 'ok' : 'error'}`, children: snapshot.credential.configured ? t('configured') : t('missing') })] }), (0, jsx_runtime_1.jsxs)("div", { className: "dvt-form-grid", children: [(0, jsx_runtime_1.jsx)(Field, { label: t('protocol'), children: (0, jsx_runtime_1.jsxs)("select", { disabled: !snapshot.writable || busy, value: draft.protocol, onChange: (event) => { update('protocol', event.target.value); }, children: [(0, jsx_runtime_1.jsx)("option", { value: "openai", children: "OpenAI Chat Completions" }), (0, jsx_runtime_1.jsx)("option", { value: "anthropic", children: "Anthropic Messages" })] }) }), (0, jsx_runtime_1.jsx)(Field, { label: t('baseUrl'), children: (0, jsx_runtime_1.jsx)(dsh_client_ui_primitives_1.Input, { disabled: !snapshot.writable || busy, value: draft.baseUrl, onChange: (event) => { update('baseUrl', event.target.value); } }) }), (0, jsx_runtime_1.jsx)(Field, { label: t('model'), children: (0, jsx_runtime_1.jsx)(dsh_client_ui_primitives_1.Input, { disabled: !snapshot.writable || busy, value: draft.model, onChange: (event) => { update('model', event.target.value); } }) }), (0, jsx_runtime_1.jsx)(Field, { label: t('apiKey'), hint: keyLocked ? t('apiKeyLocked') : snapshot.credential.source === undefined ? t('apiKeyHint') : `${t('apiKeyHint')} ${t('sourceHint', { source: t('source'), value: credentialSource(snapshot.credential.source, t) })}`, children: (0, jsx_runtime_1.jsx)(dsh_client_ui_primitives_1.Input, { "aria-label": t('apiKey'), type: "password", autoComplete: "new-password", disabled: busy || keyLocked, placeholder: snapshot.credential.configured ? t('apiKeyPlaceholderConfigured') : t('apiKeyPlaceholderMissing'), value: apiKey, onChange: (event) => { setApiKey(event.target.value); setDraftError(undefined); } }) })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "dvt-save-row", children: [(0, jsx_runtime_1.jsx)(dsh_client_ui_primitives_1.Button, { variant: "primary", disabled: !canSave || busy, onClick: save, children: state.action === 'save' ? t('saving') : t('save') }), (0, jsx_runtime_1.jsx)(dsh_client_ui_primitives_1.Button, { variant: "outline", disabled: busy, onClick: () => { void controller.load(); }, children: t('reload') })] }), (0, jsx_runtime_1.jsxs)("section", { className: "dvt-panel", children: [(0, jsx_runtime_1.jsxs)("div", { className: "dvt-panel-title", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("h3", { children: t('health') }), (0, jsx_runtime_1.jsx)("p", { children: t('connectionHint') })] }), (0, jsx_runtime_1.jsxs)("div", { className: "dvt-actions", children: [(0, jsx_runtime_1.jsx)(dsh_client_ui_primitives_1.Button, { size: "sm", variant: "outline", disabled: busy || !snapshot.runtime.ready, onClick: () => { void controller.runHealth(false); }, children: state.action === 'health' ? t('testing') : t('runHealth') }), (0, jsx_runtime_1.jsx)(dsh_client_ui_primitives_1.Button, { size: "sm", variant: "primary", disabled: busy || !snapshot.runtime.ready, onClick: () => { void controller.runHealth(true); }, children: state.action === 'connection' ? t('testing') : t('testConnection') })] })] }), (0, jsx_runtime_1.jsx)("p", { className: "dvt-muted", children: t('saveBeforeTesting') }), state.health === undefined ? (0, jsx_runtime_1.jsx)("p", { className: "dvt-muted", children: t('notTested') }) : (0, jsx_runtime_1.jsx)("div", { className: "dvt-health-grid", children: Object.entries(state.health.checks).map(([name, check]) => (0, jsx_runtime_1.jsxs)("div", { "data-status": check.status, children: [(0, jsx_runtime_1.jsx)("span", { children: t(HEALTH_NAME_KEYS[name] ?? 'health') }), (0, jsx_runtime_1.jsx)("strong", { children: t(HEALTH_STATUS_KEYS[check.status]) }), (0, jsx_runtime_1.jsx)("p", { children: healthDetail(name, check.detail, t) })] }, name)) })] }), (0, jsx_runtime_1.jsxs)("details", { className: "dvt-advanced", children: [(0, jsx_runtime_1.jsxs)("summary", { children: [(0, jsx_runtime_1.jsxs)("span", { children: [(0, jsx_runtime_1.jsx)("strong", { children: t('advanced') }), (0, jsx_runtime_1.jsx)("small", { children: t('advancedHint') })] }), (0, jsx_runtime_1.jsx)("span", { className: "dvt-details-chevron", "aria-hidden": "true", children: "\u2304" })] }), (0, jsx_runtime_1.jsxs)("div", { className: "dvt-advanced-body", children: [(0, jsx_runtime_1.jsxs)("section", { className: "dvt-panel", children: [(0, jsx_runtime_1.jsx)("div", { className: "dvt-panel-title", children: (0, jsx_runtime_1.jsx)("h3", { children: t('provider') }) }), (0, jsx_runtime_1.jsxs)("div", { className: "dvt-form-grid", children: [(0, jsx_runtime_1.jsx)(Field, { label: t('credential'), hint: t('credentialHint'), children: (0, jsx_runtime_1.jsx)(dsh_client_ui_primitives_1.Input, { "aria-label": t('credential'), disabled: !snapshot.writable || busy, value: draft.credential, onChange: (event) => { update('credential', event.target.value); } }) }), draft.protocol === 'anthropic' ? (0, jsx_runtime_1.jsx)(Field, { label: t('anthropicThinking'), hint: t('anthropicThinkingHint'), children: (0, jsx_runtime_1.jsxs)("select", { "aria-label": t('anthropicThinking'), value: draft.anthropicThinking, onChange: (event) => { update('anthropicThinking', event.target.value); }, children: [(0, jsx_runtime_1.jsx)("option", { value: "omit", children: "omit (widest compatibility)" }), (0, jsx_runtime_1.jsx)("option", { value: "disabled", children: "disabled (model support required)" }), (0, jsx_runtime_1.jsx)("option", { value: "adaptive", children: "adaptive (model support required)" })] }) }) : null, (0, jsx_runtime_1.jsx)(Field, { label: t('userAgent'), children: (0, jsx_runtime_1.jsx)(dsh_client_ui_primitives_1.Input, { value: draft.userAgent, onChange: (event) => { update('userAgent', event.target.value); } }) })] })] }), (0, jsx_runtime_1.jsxs)("section", { className: "dvt-panel", children: [(0, jsx_runtime_1.jsx)("div", { className: "dvt-panel-title", children: (0, jsx_runtime_1.jsx)("h3", { children: t('limits') }) }), (0, jsx_runtime_1.jsxs)("div", { className: "dvt-form-grid", children: [(0, jsx_runtime_1.jsx)(Field, { label: t('language'), children: (0, jsx_runtime_1.jsxs)("select", { value: draft.language, onChange: (event) => { update('language', event.target.value); }, children: [(0, jsx_runtime_1.jsx)("option", { value: "zh", children: "\u4E2D\u6587" }), (0, jsx_runtime_1.jsx)("option", { value: "en", children: "English" })] }) }), (0, jsx_runtime_1.jsx)(Field, { label: t('timeout'), children: (0, jsx_runtime_1.jsx)(dsh_client_ui_primitives_1.Input, { inputMode: "numeric", value: draft.timeoutMs, onChange: (event) => { update('timeoutMs', event.target.value); } }) }), (0, jsx_runtime_1.jsx)(Field, { label: t('maxBytes'), children: (0, jsx_runtime_1.jsx)(dsh_client_ui_primitives_1.Input, { inputMode: "numeric", value: draft.maxImageBytes, onChange: (event) => { update('maxImageBytes', event.target.value); } }) }), (0, jsx_runtime_1.jsx)(Field, { label: t('maxPixels'), children: (0, jsx_runtime_1.jsx)(dsh_client_ui_primitives_1.Input, { inputMode: "numeric", value: draft.maxImagePixels, onChange: (event) => { update('maxImagePixels', event.target.value); } }) }), (0, jsx_runtime_1.jsx)(Field, { label: t('concurrency'), children: (0, jsx_runtime_1.jsx)(dsh_client_ui_primitives_1.Input, { inputMode: "numeric", value: draft.concurrency, onChange: (event) => { update('concurrency', event.target.value); } }) })] })] }), (0, jsx_runtime_1.jsxs)("section", { className: "dvt-panel", children: [(0, jsx_runtime_1.jsxs)("div", { className: "dvt-panel-title", children: [(0, jsx_runtime_1.jsx)("h3", { children: t('runtime') }), (0, jsx_runtime_1.jsx)("span", { className: `dvt-badge ${snapshot.runtime.ready ? 'ok' : 'error'}`, children: snapshot.runtime.ready ? snapshot.runtime.upstream?.source === 'managed' ? t('runtimeManaged') : snapshot.runtime.upstream?.source === 'external' ? t('runtimeExternal') : t('runtimeReady') : t('runtimeUnavailable') })] }), (0, jsx_runtime_1.jsxs)("div", { className: "dvt-form-grid", children: [(0, jsx_runtime_1.jsx)(Field, { label: t('runtimeMode'), children: (0, jsx_runtime_1.jsxs)("select", { value: draft.runtimeMode, onChange: (event) => { update('runtimeMode', event.target.value); }, children: [(0, jsx_runtime_1.jsx)("option", { value: "managed", children: t('runtimeManaged') }), (0, jsx_runtime_1.jsx)("option", { value: "external", children: t('runtimeExternal') })] }) }), draft.runtimeMode === 'external' ? (0, jsx_runtime_1.jsx)(Field, { label: t('toolkitPath'), children: (0, jsx_runtime_1.jsx)(dsh_client_ui_primitives_1.Input, { value: draft.toolkitPath, onChange: (event) => { update('toolkitPath', event.target.value); } }) }) : null, (0, jsx_runtime_1.jsx)(Field, { label: t('python'), children: (0, jsx_runtime_1.jsx)(dsh_client_ui_primitives_1.Input, { placeholder: "python3", value: draft.python, onChange: (event) => { update('python', event.target.value); } }) }), (0, jsx_runtime_1.jsx)(Field, { label: t('allowedDirs'), hint: t('allowedDirsHint'), children: (0, jsx_runtime_1.jsx)("textarea", { rows: 3, value: draft.allowedDirs, onChange: (event) => { update('allowedDirs', event.target.value); } }) })] }), snapshot.runtime.upstream === undefined ? null : (0, jsx_runtime_1.jsxs)("div", { className: "dvt-runtime-facts", children: [(0, jsx_runtime_1.jsx)("code", { children: snapshot.runtime.upstream.path }), (0, jsx_runtime_1.jsxs)("code", { children: [snapshot.runtime.upstream.python, " \u00B7 ", snapshot.runtime.upstream.pythonVersion] }), (0, jsx_runtime_1.jsx)("code", { children: snapshot.runtime.upstream.runtimeHome })] })] })] })] }), (0, jsx_runtime_1.jsxs)("footer", { className: "dvt-settings-footer", children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("span", { className: "dvt-kicker", children: t('pluginKind') }), (0, jsx_runtime_1.jsx)("h2", { children: t('settingsTitle') }), (0, jsx_runtime_1.jsx)("p", { children: t('settingsIntro') })] }), (0, jsx_runtime_1.jsxs)("div", { className: "dvt-release", children: [(0, jsx_runtime_1.jsxs)("span", { children: [t('pluginVersion'), " ", (0, jsx_runtime_1.jsx)("strong", { children: snapshot.release.pluginVersion })] }), (0, jsx_runtime_1.jsxs)("span", { children: [t('upstreamVersion'), " ", (0, jsx_runtime_1.jsx)("strong", { children: snapshot.release.upstreamVersion })] }), (0, jsx_runtime_1.jsxs)("span", { children: [t('activeGeneration'), " ", (0, jsx_runtime_1.jsx)("strong", { children: t('activeGenerationValue', { generation: snapshot.runtime.generation }) })] })] })] })] }));
|
|
738
807
|
}
|
|
739
808
|
const CSS = `
|
|
740
809
|
.dvt-tool{margin:4px 0;border:1px solid var(--dsw-alias-border-l1);border-radius:12px;background:var(--dsw-alias-bg-layer-1);overflow:hidden;box-shadow:var(--dsw-shadow-lv1)}
|