dsh-sql 0.5.9 → 0.5.11

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/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # 更新记录
2
2
 
3
+ ## 0.5.11 (2026-11-04)
4
+
5
+ - 同步共享界面:嵌入设置时继承宿主底色,输入框跟随主题,空状态保持可读宽度;新版 DSH 可显示插件设置图标。
6
+ - Align embedded surfaces, themed inputs, readable empty states and optional native settings icons.
7
+
8
+
9
+ ## 0.5.10 (2026-11-03)
10
+
11
+ - 连接与模式查询失败保留原文并追加下一步;sql_list 补端口;空态给指引。
12
+ - Connection and schema failures keep the original error and add next steps; sql_list shows ports; empty states guide the next action.
13
+
3
14
  ## 0.5.9 (2026-10-30)
4
15
 
5
16
  - 重整中英文首页:用途、三步流程图、安装入口与操作示例;详细配置与边界集中到完整说明。
package/docs/USAGE.en.md CHANGED
@@ -101,6 +101,23 @@ pnpm install
101
101
  pnpm test # build + full test suite, including a real SQLite integration suite
102
102
  ```
103
103
 
104
+ ## Troubleshooting
105
+
106
+ Run `sql_health` first: it pings every connection and summarizes read-only and approval settings, and each failing check carries the next step.
107
+
108
+ | Symptom | Usual cause | What to do |
109
+ | :-- | :-- | :-- |
110
+ | `ECONNREFUSED` / `ETIMEDOUT` | Server down, wrong host/port, or firewall | Verify the server and port, then check `host`/`port` in the connection |
111
+ | `Access denied for user` / `password authentication failed` | Wrong user or password | Check `user`/`password`; prefer the `DSH_SQL_PASSWORD_<CONNECTION>` env var |
112
+ | `Unknown database` / `database "…" does not exist` | Typo, or the database was never created | Check the `database` field |
113
+ | `SQLITE_CANTOPEN` / `unable to open database file` | Missing path, or no read/write permission | Check the file path, directory permissions, and the account running DSH |
114
+ | `no such table` / `relation "…" does not exist` | Wrong table name, case, or schema | Call `sql_schema` without `table` to list the real names |
115
+ | Write reports "0 rows affected" | `WHERE` matched nothing, or the script was DDL/multi-statement | Re-check the predicate and data with `sql_query` |
116
+ | `sql_exec` says confirmation cannot be asked | Session approval policy is `never` | Switch to an ask-capable policy, or explicitly set `writeApproval: false` and restart (no more prompts) |
117
+ | `sql_schema` returns no columns | Table missing, or the account cannot read it | List all tables first, then check case and permissions |
118
+
119
+ If health is green but a query is still rejected, check the read-only rule: writes (INSERT/UPDATE/DDL) belong in `sql_exec`.
120
+
104
121
  ## License
105
122
 
106
123
  MIT
package/docs/USAGE.md CHANGED
@@ -103,6 +103,23 @@ pnpm install
103
103
  pnpm test # 构建 + 完整测试套件(含真实 SQLite 集成)
104
104
  ```
105
105
 
106
+ ## 故障排查
107
+
108
+ 先运行 `sql_health`:它逐连接探活并汇总只读模式与审批状态,失败项后面会直接给出下一步。
109
+
110
+ | 现象 | 常见原因 | 处理 |
111
+ | :-- | :-- | :-- |
112
+ | `ECONNREFUSED` / `ETIMEDOUT` | 服务没启动、host/port 不对或被防火墙拦住 | 确认服务与端口,核对连接里的 `host`/`port` |
113
+ | `Access denied for user` / `password authentication failed` | 账号或密码不对 | 核对 `user`/`password`;密码建议用环境变量 `DSH_SQL_PASSWORD_<连接名大写>` |
114
+ | `Unknown database` / `database "…" does not exist` | 库名写错或尚未创建 | 核对 `database` 字段 |
115
+ | `SQLITE_CANTOPEN` / `unable to open database file` | 路径不存在,或运行账号没有读写权限 | 检查文件路径、目录可写性与进程账号 |
116
+ | `no such table` / `relation "…" does not exist` | 表名、大小写或 Schema 不对 | 先不带 `table` 运行 `sql_schema` 看真实表名 |
117
+ | 写操作返回「0 行受影响」 | `WHERE` 没命中,或执行的是 DDL/多语句脚本 | 用 `sql_query` 复核条件与数据 |
118
+ | `sql_exec` 报「需要确认但无法询问」 | 会话审批策略是 `never` | 切到可询问模式,或明确设置 `writeApproval: false` 后重启(之后不再询问) |
119
+ | `sql_schema` 返回「没有取到列」 | 表不存在,或当前账号没有读取权限 | 先列全部表,再核对大小写与权限 |
120
+
121
+ 自检正常但查询仍被拒绝时,先确认是不是只读限制:写语句(INSERT/UPDATE/DDL)要走 `sql_exec`。
122
+
106
123
  ## License
107
124
 
108
125
  MIT
package/lib/tools.d.ts CHANGED
@@ -26,6 +26,16 @@ export interface SqlToolDefinition {
26
26
  execute(args: unknown, exec: unknown): Promise<unknown>;
27
27
  timeoutMs?: number;
28
28
  }
29
+ /**
30
+ * 把驱动/连接的原始错误映射成一行可执行的「下一步」。
31
+ *
32
+ * 之前 sql_list / sql_health / sql_query 直接把驱动原文(ECONNREFUSED、
33
+ * ER_ACCESS_DENIED_ERROR、SQLITE_CANTOPEN…)交给用户,知道怎么修的人能看懂,
34
+ * 不知道的人只能反复重试。这里只补一行提示,原始错误文本一律保留。
35
+ */
36
+ export declare function connectionErrorHint(message: string): string | undefined;
37
+ /** 给错误补一行「下一步」;无法识别时原样返回,避免把断言类错误改写成连接问题。 */
38
+ export declare function annotateError(error: unknown): Error;
29
39
  /** 词法校验需要区分的三种引擎。 */
30
40
  type SqlEngine = 'sqlite' | 'mysql' | 'postgres';
31
41
  /**
package/lib/tools.js CHANGED
@@ -38,6 +38,42 @@ function executionSignal(exec) {
38
38
  const signal = exec.signal;
39
39
  return signal instanceof AbortSignal ? signal : undefined;
40
40
  }
41
+ /**
42
+ * 把驱动/连接的原始错误映射成一行可执行的「下一步」。
43
+ *
44
+ * 之前 sql_list / sql_health / sql_query 直接把驱动原文(ECONNREFUSED、
45
+ * ER_ACCESS_DENIED_ERROR、SQLITE_CANTOPEN…)交给用户,知道怎么修的人能看懂,
46
+ * 不知道的人只能反复重试。这里只补一行提示,原始错误文本一律保留。
47
+ */
48
+ export function connectionErrorHint(message) {
49
+ if (/ECONNREFUSED/i.test(message))
50
+ return '目标地址拒绝连接:请确认数据库服务已启动、host 与 port 正确,并检查防火墙是否放行。';
51
+ if (/ENOTFOUND|EAI_AGAIN|getaddrinfo/i.test(message))
52
+ return '主机名解析失败:请检查连接配置里的 host 拼写,以及本机 DNS/网络是否可用。';
53
+ if (/ETIMEDOUT|timed out|timeout exceeded|connection timeout/i.test(message))
54
+ return '连接或查询超时:请确认网络可达与服务器负载,必要时调大 queryTimeoutMs / execTimeoutMs 后重试。';
55
+ if (/password authentication failed|Access denied for user|authentication failed/i.test(message))
56
+ return '认证失败:请核对 user 与 password;也可改用环境变量 DSH_SQL_PASSWORD_<连接名大写> 提供密码,避免明文写进配置。';
57
+ if (/Unknown database|ER_BAD_DB_ERROR|database .* does not exist|\b3D000\b/i.test(message))
58
+ return '数据库不存在:请核对连接配置里的 database,或先在服务器上创建该库。';
59
+ if (/no such table|SQLITE_ERROR: no such table|relation .* does not exist|\b42P01\b/i.test(message))
60
+ return '表不存在:先用 sql_schema(不带 table)查看该连接的表清单,注意大小写与实际 schema。';
61
+ if (/SQLITE_CANTOPEN|unable to open database file|EACCES|EPERM|readonly database/i.test(message))
62
+ return 'SQLite 文件无法打开或没有权限:请检查文件路径是否存在、所在目录可写、进程账号有读写权限。';
63
+ if (/ECONNRESET|EPIPE|Connection terminated|server closed the connection/i.test(message))
64
+ return '连接被对端关闭:可能是服务器重启或中间代理断开,请重试一次;持续出现时检查连接池与代理设置。';
65
+ if (/no pg_hba\.conf entry|unsupported startup parameter|\b28000\b/i.test(message))
66
+ return '服务器拒绝本次连接:请核对 pg_hba.conf 与账号来源限制,确认该主机与该用户被允许登录。';
67
+ return undefined;
68
+ }
69
+ /** 给错误补一行「下一步」;无法识别时原样返回,避免把断言类错误改写成连接问题。 */
70
+ export function annotateError(error) {
71
+ const message = error instanceof Error ? error.message : String(error);
72
+ const hint = connectionErrorHint(message);
73
+ if (hint === undefined || message.includes('下一步:'))
74
+ return error instanceof Error ? error : new Error(message);
75
+ return new Error(message + '\n下一步:' + hint);
76
+ }
41
77
  /** 只读语句关键字白名单。 */
42
78
  const READ_KEYWORDS = /^(select|pragma|explain|show|describe|desc|with)\b/i;
43
79
  /**
@@ -309,7 +345,7 @@ const listSchema = {
309
345
  type: 'array',
310
346
  items: {
311
347
  type: 'object',
312
- properties: { name: { type: 'string' }, engine: { type: 'string' }, host: { type: 'string' }, database: { type: 'string' }, file: { type: 'string' }, ok: { type: 'boolean' }, error: { type: 'string' } },
348
+ properties: { name: { type: 'string' }, engine: { type: 'string' }, host: { type: 'string' }, port: { type: 'integer' }, database: { type: 'string' }, file: { type: 'string' }, ok: { type: 'boolean' }, error: { type: 'string' } },
313
349
  additionalProperties: true,
314
350
  },
315
351
  },
@@ -423,6 +459,16 @@ export function buildSqlTools(config, policyOf = () => 'unknown') {
423
459
  }
424
460
  return { adapter, name: connection.name };
425
461
  };
462
+ /** 适配器调用统一兜底:被取消时原样抛出,其余错误补「下一步」。 */
463
+ const guard = async (signal, work) => {
464
+ try {
465
+ return await work();
466
+ }
467
+ catch (error) {
468
+ signal?.throwIfAborted();
469
+ throw annotateError(error);
470
+ }
471
+ };
426
472
  const pingAllConnections = async (signal) => {
427
473
  const rows = [];
428
474
  for (const connection of cfg.connections) {
@@ -431,6 +477,8 @@ export function buildSqlTools(config, policyOf = () => 'unknown') {
431
477
  entry.file = connection.file ?? ':memory:';
432
478
  else {
433
479
  entry.host = connection.host ?? '';
480
+ // 端口要一并返回,否则渲染只能显示 host:undefined/database。
481
+ entry.port = connection.port;
434
482
  entry.database = connection.database ?? '';
435
483
  }
436
484
  try {
@@ -442,7 +490,7 @@ export function buildSqlTools(config, policyOf = () => 'unknown') {
442
490
  catch (error) {
443
491
  signal?.throwIfAborted();
444
492
  entry.ok = false;
445
- entry.error = error instanceof Error ? error.message : String(error);
493
+ entry.error = annotateError(error).message;
446
494
  }
447
495
  rows.push(entry);
448
496
  }
@@ -458,10 +506,16 @@ export function buildSqlTools(config, policyOf = () => 'unknown') {
458
506
  const rec = asRecord(value);
459
507
  const connections = Array.isArray(rec.connections) ? rec.connections : [];
460
508
  const lines = ['共 ' + connections.length + ' 个数据库连接:'];
509
+ const bad = [];
461
510
  for (const item of connections) {
462
511
  const c = asRecord(item);
463
- const target = c.file !== undefined && c.file !== '' ? c.file : c.host + '/' + c.database;
512
+ const target = c.file !== undefined && c.file !== '' ? c.file : c.host + ':' + c.port + '/' + c.database;
464
513
  lines.push('- ' + c.name + '(' + c.engine + ' @ ' + target + ')' + (c.ok === true ? ' ✅' : ' ❌ ' + String(c.error ?? '')));
514
+ if (c.ok !== true)
515
+ bad.push(String(c.name));
516
+ }
517
+ if (bad.length > 0) {
518
+ lines.push('', '下一步:先修好 ' + bad.join('、') + '(核对 host/port、服务是否启动、账号密码或 SQLite 文件路径),再运行 sql_list 复查。');
465
519
  }
466
520
  return [{ type: 'text', text: lines.join('\n') }];
467
521
  },
@@ -504,7 +558,7 @@ export function buildSqlTools(config, policyOf = () => 'unknown') {
504
558
  // 先按目标连接的引擎做词法校验,再打开数据库:被拒绝的 SQL 不该去建连接或建库文件。
505
559
  const sql = assertReadQuery(rawSql, findConnection(connectionName).engine);
506
560
  const { adapter, name } = getAdapter(connectionName);
507
- const result = await adapter.query(sql, cfg.maxRows + 1, executionSignal(exec));
561
+ const result = await guard(executionSignal(exec), () => adapter.query(sql, cfg.maxRows + 1, executionSignal(exec)));
508
562
  const total = result.rows.length;
509
563
  const rows = result.rows.slice(0, cfg.maxRows);
510
564
  const format = optionalString(args, 'format')?.toLowerCase() ?? 'table';
@@ -540,7 +594,9 @@ export function buildSqlTools(config, policyOf = () => 'unknown') {
540
594
  schema: execSchema,
541
595
  render: (_args, value) => {
542
596
  const rec = asRecord(value);
543
- return [{ type: 'text', text: '执行完成(' + rec.connection + '):影响 ' + rec.changes + ' 行。' }];
597
+ const changes = typeof rec.changes === 'number' ? rec.changes : 0;
598
+ const tail = changes === 0 ? '\n注意:0 行受影响,通常是 WHERE 条件没有命中数据,或用的是 DDL/多语句脚本;可用 sql_query 复核。' : '';
599
+ return [{ type: 'text', text: '执行完成(' + rec.connection + '):影响 ' + changes + ' 行。' + tail }];
544
600
  },
545
601
  },
546
602
  async execute(rawArgs, exec) {
@@ -549,7 +605,7 @@ export function buildSqlTools(config, policyOf = () => 'unknown') {
549
605
  const args = asRecord(rawArgs);
550
606
  const sql = requiredString(args, 'sql', 'SQL 语句');
551
607
  const { adapter, name } = getAdapter(optionalString(args, 'connection'));
552
- const changes = await adapter.exec(sql, executionSignal(exec));
608
+ const changes = await guard(executionSignal(exec), () => adapter.exec(sql, executionSignal(exec)));
553
609
  return { connection: name, changes, readOnly: false };
554
610
  },
555
611
  timeoutMs: cfg.execTimeoutMs,
@@ -566,7 +622,11 @@ export function buildSqlTools(config, policyOf = () => 'unknown') {
566
622
  render: (_args, value) => {
567
623
  const rec = asRecord(value);
568
624
  const columns = Array.isArray(rec.columns) ? rec.columns : [];
569
- if (columns.length > 0) {
625
+ // 指定了 table 却没有列:不能落到「共 0 张表」,那会把「表不存在」说成「库是空的」。
626
+ if (typeof rec.table === 'string' && rec.table !== '') {
627
+ if (columns.length === 0) {
628
+ return [{ type: 'text', text: '没有取到表 ' + rec.table + ' 的列:该表可能不存在、大小写/Schema 不匹配,或当前账号没有读取权限。\n下一步:先调用 sql_schema(不带 table)查看连接 ' + rec.connection + ' 的表清单,再用清单里的原名重试。' }];
629
+ }
570
630
  const lines = ['表 ' + rec.table + ' 的列:'];
571
631
  for (const item of columns) {
572
632
  const c = asRecord(item);
@@ -575,6 +635,8 @@ export function buildSqlTools(config, policyOf = () => 'unknown') {
575
635
  return [{ type: 'text', text: lines.join('\n') }];
576
636
  }
577
637
  const tables = Array.isArray(rec.tables) ? rec.tables : [];
638
+ if (tables.length === 0)
639
+ return [{ type: 'text', text: '连接 ' + rec.connection + ' 里没有用户表(库可能是空的,或该账号只能看到部分 Schema)。' }];
578
640
  return [{ type: 'text', text: '共 ' + tables.length + ' 张表:' + tables.join(', ') }];
579
641
  },
580
642
  },
@@ -584,10 +646,10 @@ export function buildSqlTools(config, policyOf = () => 'unknown') {
584
646
  const table = optionalString(args, 'table');
585
647
  const signal = executionSignal(exec);
586
648
  if (table !== undefined) {
587
- const columns = await adapter.describeTable(table, signal);
649
+ const columns = await guard(signal, () => adapter.describeTable(table, signal));
588
650
  return { connection: name, table, columns, tables: [] };
589
651
  }
590
- const tables = await adapter.listTables(signal);
652
+ const tables = await guard(signal, () => adapter.listTables(signal));
591
653
  return { connection: name, tables, columns: [] };
592
654
  },
593
655
  timeoutMs: 30000,
@@ -606,7 +668,11 @@ export function buildSqlTools(config, policyOf = () => 'unknown') {
606
668
  const lines = ['连接 ' + rec.connection + '(' + rec.engine + '):共 ' + tables.length + ' 张表' + (typeof rec.sizeBytes === 'number' && rec.sizeBytes >= 0 ? ',库体积 ' + formatBytes(rec.sizeBytes) : '') + '。'];
607
669
  for (const item of tables.slice(0, 30)) {
608
670
  const t = asRecord(item);
609
- lines.push('- ' + t.name + ':' + (typeof t.rowCount === 'number' ? t.rowCount + ' 行' : '行数未知' + (t.error ? '(' + t.error + ')' : '')));
671
+ const label = typeof t.name === 'string' && t.name !== '' ? t.name : '(表清单读取失败)';
672
+ lines.push('- ' + label + ':' + (typeof t.rowCount === 'number' ? t.rowCount + ' 行' : '行数未知' + (t.error ? '(' + t.error + ')' : '')));
673
+ }
674
+ if (tables.length > 0 && tables.every((item) => typeof asRecord(item).rowCount !== 'number') && tables.every((item) => asRecord(item).error !== undefined)) {
675
+ lines.push('', '下一步:统计信息读不到时,先用 sql_schema 确认表清单可用、账号有读取系统表/information_schema 的权限,再用 sql_query 手动 COUNT(*)。');
610
676
  }
611
677
  if (tables.length > 30)
612
678
  lines.push('…仅展示前 30 张表');
@@ -643,7 +709,7 @@ export function buildSqlTools(config, policyOf = () => 'unknown') {
643
709
  }
644
710
  }
645
711
  else {
646
- const names = await adapter.listTables(signal);
712
+ const names = await guard(signal, () => adapter.listTables(signal));
647
713
  for (const table of names) {
648
714
  try {
649
715
  const result = await adapter.query('SELECT COUNT(*) FROM ' + quoteIdent(engine, table), 1, signal);
@@ -677,6 +743,15 @@ export function buildSqlTools(config, policyOf = () => 'unknown') {
677
743
  lines.push('- 只读模式:' + (rec.readOnly === true ? '开(sql_exec 已禁用)' : '关'));
678
744
  lines.push('- 写审批门:' + String(rec.writeApprovalDetail ?? (rec.writeApproval === true ? '开' : '关')));
679
745
  lines.push('- 行数上限:' + String(rec.maxRows) + ';查询超时 ' + String(rec.queryTimeoutMs) + 'ms;写超时 ' + String(rec.execTimeoutMs) + 'ms');
746
+ // 自检的价值在于失败时告诉用户下一步做什么,而不只是把 ❌ 摆出来。
747
+ if (bad.length > 0) {
748
+ lines.push('- 下一步:逐个修好上面的 ❌ 连接(核对 host/port、数据库服务是否启动、账号密码或 SQLite 文件路径与权限),再运行 sql_health 复查。');
749
+ }
750
+ if (rec.writeApprovalReady === false) {
751
+ lines.push('- 下一步:写审批门当前无法确认。把会话审批策略切到可询问(ask),或由用户明确设置 writeApproval=false 后重启(之后 sql_exec 不再询问,慎用)。');
752
+ }
753
+ if (rec.readOnly === true)
754
+ lines.push('- 说明:readOnly=true 时 sql_exec 被禁用属于配置预期,不是故障。');
680
755
  return [{ type: 'text', text: lines.join('\n') }];
681
756
  },
682
757
  },
@@ -55,7 +55,7 @@ function createWorkbenchUI(React) {
55
55
  }
56
56
  function Page({ title, subtitle, actions, children, workbench = false, className, rootRef, ...props }) {
57
57
  return h('section', { ...props, ref: rootRef, className: cx('dshw', 'w-page', className), 'data-main': workbench ? 'true' : 'false' },
58
- h('style', null, styles),
58
+ h(Styles, { key: 'styles' }),
59
59
  h('header', { className: 'w-page-header' }, h('div', { className: 'w-heading' }, h('h1', null, title), subtitle ? h('p', { className: 'w-subtitle' }, subtitle) : null), actions ? h('div', { className: 'w-header-actions' }, actions) : null),
60
60
  h('div', { className: 'w-body' }, children));
61
61
  }
@@ -78,10 +78,10 @@ function createWorkbenchUI(React) {
78
78
  }
79
79
  function Status({ children, tone = 'info', className }) {
80
80
  if (!children) return null;
81
- return h('div', { className: cx('w-status', 'w-status-' + tone, className), role: tone === 'error' ? 'alert' : 'status', 'aria-live': tone === 'error' ? 'assertive' : 'polite' }, h(Icon, { name: tone === 'success' ? 'check' : 'info', size: 18 }), h('div', null, children));
81
+ return h('div', { className: cx('dshw', 'w-status', 'w-status-' + tone, className), role: tone === 'error' ? 'alert' : 'status', 'aria-live': tone === 'error' ? 'assertive' : 'polite' }, h(Icon, { name: tone === 'success' ? 'check' : 'info', size: 18 }), h('div', null, children));
82
82
  }
83
83
  function Empty({ title, children, action, icon = 'file' }) {
84
- return h('div', { className: 'w-empty' }, h(Icon, { name: icon, size: 32 }), h('h2', null, title), children ? h('div', { className: 'w-muted' }, children) : null, action ? h('div', { className: 'w-toolbar' }, action) : null);
84
+ return h('div', { className: 'dshw w-empty' }, h(Styles, { key: 'styles' }), h(Icon, { name: icon, size: 32 }), h('h2', null, title), children ? h('div', { className: 'w-muted' }, children) : null, action ? h('div', { className: 'w-toolbar' }, action) : null);
85
85
  }
86
86
  function Split({ list, detail, selected, onBack, backLabel, className, listWidth = 360 }) {
87
87
  const ref = useRef(null);
@@ -125,7 +125,8 @@ function createWorkbenchUI(React) {
125
125
  else if (event.shiftKey && document.activeElement === first) { event.preventDefault(); last.focus(); }
126
126
  else if (!event.shiftKey && document.activeElement === last) { event.preventDefault(); first.focus(); }
127
127
  }
128
- return h('div', { className: 'w-overlay', onClick: event => { if (!busy && event.target === event.currentTarget) onClose(); } },
128
+ return h('div', { className: 'dshw w-overlay', onClick: event => { if (!busy && event.target === event.currentTarget) onClose(); } },
129
+ h(Styles, { key: 'styles' }),
129
130
  h('section', { ref: panel, className: cx('w-dialog', className), role: 'dialog', 'aria-modal': true, 'aria-labelledby': id, tabIndex: -1, onKeyDown: keydown },
130
131
  h('header', { className: 'w-dialog-header' }, h('h2', { id }, title), h(IconButton, { icon: 'close', label: closeLabel, disabled: busy, onClick: onClose })), h('div', { className: 'w-dialog-body' }, children)));
131
132
  }
@@ -136,10 +137,10 @@ function createWorkbenchUI(React) {
136
137
  ctx.slots.inject('sidebar.panellist', () => ctx.slots.register({ name: 'sidebar.panellist', id, order, label }, function WorkbenchIcon({ size }) { return h(Icon, { name: icon, size }); }));
137
138
  }
138
139
  const styles = `
139
- .dshw{--w-bg:var(--dsw-alias-bg-layer-1,#fff);--w-soft:var(--dsw-alias-bg-layer-2,#f7f8fa);--w-text:var(--dsw-alias-label-primary,#18202c);--w-muted:var(--dsw-alias-label-secondary,#667085);--w-border:var(--dsw-alias-border-l3,#e7e9ef);--w-accent:var(--dsh-plugin-workbench-accent,#4f6bdb);--w-selected:color-mix(in srgb,var(--w-accent) 10%,var(--w-bg));--w-primary:var(--w-text);--w-on-primary:var(--w-bg);container-type:inline-size;container-name:dsh-workbench;color:var(--w-text);background:var(--w-bg);font:14px/1.65 var(--dsh-font-family-content,system-ui,-apple-system,"Segoe UI","Microsoft YaHei",sans-serif);min-width:0;max-width:100%;box-sizing:border-box;text-align:start;color-scheme:inherit}
140
- .dshw *,.dshw *:before,.dshw *:after{box-sizing:border-box}.dshw h1,.dshw h2,.dshw h3,.dshw h4,.dshw p{margin:0}.dshw h1{font-size:30px;line-height:1.25;letter-spacing:-.025em;font-weight:650}.dshw h2{font-size:24px;line-height:1.35;font-weight:650;letter-spacing:-.015em;overflow-wrap:anywhere}.dshw h3,.dshw h4{font-size:16px;line-height:1.4;font-weight:600}.dshw a{color:var(--w-accent);text-underline-offset:3px;overflow-wrap:anywhere}.dshw button,.dshw input,.dshw select,.dshw textarea{font:inherit;color:inherit;max-width:100%}.dshw input:not([type=checkbox]):not([type=radio]):not([type=file]),.dshw select,.dshw textarea{background:var(--w-bg);border:1px solid var(--w-border);border-radius:8px;padding:8px 11px;min-width:0;line-height:1.5}.dshw input:not([type=checkbox]):not([type=radio]):not([type=file]),.dshw select{min-height:38px}.dshw textarea{resize:vertical}.dshw input[type=checkbox],.dshw input[type=radio]{width:16px;height:16px;flex-shrink:0;accent-color:var(--w-accent)}.dshw :focus-visible{outline:2px solid var(--w-accent);outline-offset:3px}.dshw button:disabled,.dshw input:disabled,.dshw select:disabled,.dshw textarea:disabled{opacity:.5;cursor:not-allowed}.dshw label{font-size:13px}.dshw fieldset{min-width:0;border:1px solid var(--w-border);border-radius:8px}.dshw summary{cursor:pointer;font-weight:550;list-style:none;display:flex;align-items:center;gap:8px}.dshw summary::-webkit-details-marker{display:none}.dshw summary:after{content:'';display:block;margin-inline-start:auto;width:7px;height:7px;border-inline-end:1.75px solid currentColor;border-bottom:1.75px solid currentColor;transform:rotate(45deg);flex-shrink:0}.dshw details[open]>summary:after{transform:rotate(225deg)}.dshw details>summary+*{margin-top:12px}.dshw pre{white-space:pre-wrap;overflow-wrap:anywhere;font:12px/1.7 ui-monospace,SFMono-Regular,Consolas,monospace;max-width:100%;background:var(--w-soft);border-radius:6px;padding:14px}.dshw img,.dshw video,.dshw iframe{max-width:100%}
141
- .w-page{display:flex;flex-direction:column;position:relative;padding:0;min-height:540px;gap:0}.w-page[data-main=true]{height:100%;min-height:0;padding:calc(24px + var(--dsh-frame-top-clearance,0px)) 28px 0 max(28px,var(--dsh-frame-leading-clearance,0px));overflow:auto}.w-page-header{display:flex;justify-content:space-between;gap:24px;align-items:flex-start;padding-bottom:22px;flex-shrink:0}.w-heading{min-width:0}.w-subtitle{margin-top:8px!important;font-size:14px;color:var(--w-muted);line-height:1.6}.w-header-actions,.w-toolbar,.w-actions{display:flex;align-items:center;flex-wrap:wrap;gap:8px;min-width:0}.w-header-actions{justify-content:flex-end}.w-body,.w-tabs-layout{display:flex;flex-direction:column;flex:1;min-height:0;min-width:0}.w-body{overflow:auto}.w-tab-panel{flex:1;min-width:0;min-height:0;display:flex;flex-direction:column;overflow:auto}.w-tabs{display:flex;align-items:stretch;gap:20px;border-bottom:1px solid var(--w-border);flex-shrink:0;overflow-x:auto;scrollbar-width:thin}.dshw .w-tabs>button{border:0;border-bottom:2px solid transparent;background:transparent;padding:11px 8px 13px;white-space:nowrap;font-size:14px;font-weight:550;cursor:pointer;color:var(--w-muted);display:flex;align-items:center;gap:7px}.dshw .w-tabs>button[aria-selected=true]{border-bottom-color:var(--w-accent);color:var(--w-accent)}.w-count,.w-tag{font-size:12px;line-height:1.5;display:inline-flex;align-items:center;flex-shrink:0;background:var(--w-soft);border-radius:5px;padding:1px 6px;color:var(--w-muted)}.w-tabs [aria-selected=true] .w-count,.w-selected .w-tag{color:var(--w-accent);background:var(--w-selected)}
142
- .dshw .w-button{display:inline-flex;justify-content:center;align-items:center;gap:7px;background:var(--w-bg);border:1px solid var(--w-border);border-radius:8px;padding:8px 12px;min-height:36px;line-height:1.4;font-size:14px;font-weight:500;cursor:pointer;text-decoration:none;white-space:normal}.dshw .w-button:not(:disabled):hover{background:var(--w-soft)}.dshw .w-primary{background:var(--w-primary);border-color:var(--w-primary);color:var(--w-on-primary)}.dshw .w-primary:not(:disabled):hover{background:var(--w-primary);opacity:.9}.dshw .w-ghost{background:transparent;border-color:transparent}.dshw .w-danger{color:var(--dsw-alias-state-error-primary,#b43c3c)}.dshw .w-icon-button{width:36px;min-width:36px;padding:8px}.dshw .w-button svg{flex-shrink:0}.w-muted{color:var(--w-muted);font-size:12px;line-height:1.6}.w-section{padding:24px 0;border-bottom:1px solid var(--w-border);min-width:0}.w-section>h3{margin-bottom:12px}.w-section>p+p{margin-top:8px}.w-fields{display:grid;gap:16px;min-width:0}.w-field{display:grid;gap:6px;min-width:0}.w-field>input,.w-field>select,.w-field>textarea{width:100%}.w-status{display:flex;align-items:flex-start;gap:8px;padding:11px 13px;margin:12px 0;border:1px solid var(--w-border);border-radius:8px;background:var(--w-soft);font-size:13px;overflow-wrap:anywhere;flex-shrink:0}.w-status>svg{flex-shrink:0;margin-top:2px}.w-status-error{color:var(--dsw-alias-state-error-primary,#ad3636)}.w-status-success{color:var(--dsw-alias-state-success-primary,#24794a)}.w-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;gap:14px;max-width:580px;padding:48px 24px;margin:auto;min-height:280px;overflow-wrap:anywhere}.w-empty>svg{color:var(--w-muted)}.w-empty h2{font-size:20px}.w-empty .w-muted{font-size:14px}.w-empty .w-toolbar{justify-content:center}
140
+ .dshw{--w-bg:var(--dsw-alias-bg-layer-1,#fff);--w-soft:var(--dsw-alias-bg-layer-2,#f7f8fa);--w-text:var(--dsw-alias-label-primary,#18202c);--w-muted:var(--dsw-alias-label-secondary,#667085);--w-border:var(--dsw-alias-border-l3,#e7e9ef);--w-accent:var(--dsh-plugin-workbench-accent,#4f6bdb);--w-selected:color-mix(in srgb,var(--w-accent) 10%,var(--w-bg));--w-primary:var(--w-text);--w-on-primary:var(--w-bg);container-type:inline-size;container-name:dsh-workbench;color:var(--w-text);font:14px/1.65 var(--dsh-font-family-content,system-ui,-apple-system,"Segoe UI","Microsoft YaHei",sans-serif);min-width:0;max-width:100%;box-sizing:border-box;text-align:start;color-scheme:inherit}
141
+ .dshw *,.dshw *:before,.dshw *:after{box-sizing:border-box}.dshw h1,.dshw h2,.dshw h3,.dshw h4,.dshw p{margin:0}.dshw h1{font-size:30px;line-height:1.25;letter-spacing:-.025em;font-weight:650}.dshw h2{font-size:24px;line-height:1.35;font-weight:650;letter-spacing:-.015em;overflow-wrap:anywhere}.dshw h3,.dshw h4{font-size:16px;line-height:1.4;font-weight:600}.dshw a{color:var(--w-accent);text-underline-offset:3px;overflow-wrap:anywhere}.dshw button,.dshw input,.dshw select,.dshw textarea{font:inherit;color:inherit;max-width:100%}.dshw input:not([type=checkbox]):not([type=radio]):not([type=file]),.dshw select,.dshw textarea{background:var(--dsw-specific-input-major,var(--w-bg));border:1px solid var(--w-border);border-radius:8px;padding:8px 11px;min-width:0;line-height:1.5}.dshw input:not([type=checkbox]):not([type=radio]):not([type=file]),.dshw select{min-height:38px}.dshw textarea{resize:vertical}.dshw input[type=checkbox],.dshw input[type=radio]{width:16px;height:16px;flex-shrink:0;accent-color:var(--w-accent)}.dshw :focus-visible{outline:2px solid var(--w-accent);outline-offset:3px}.dshw button:disabled,.dshw input:disabled,.dshw select:disabled,.dshw textarea:disabled{opacity:.5;cursor:not-allowed}.dshw label{font-size:13px}.dshw fieldset{min-width:0;border:1px solid var(--w-border);border-radius:8px}.dshw summary{cursor:pointer;font-weight:550;list-style:none;display:flex;align-items:center;gap:8px}.dshw summary::-webkit-details-marker{display:none}.dshw summary:after{content:'';display:block;margin-inline-start:auto;width:7px;height:7px;border-inline-end:1.75px solid currentColor;border-bottom:1.75px solid currentColor;transform:rotate(45deg);flex-shrink:0}.dshw details[open]>summary:after{transform:rotate(225deg)}.dshw details>summary+*{margin-top:12px}.dshw pre{white-space:pre-wrap;overflow-wrap:anywhere;font:12px/1.7 ui-monospace,SFMono-Regular,Consolas,monospace;max-width:100%;background:var(--w-soft);border-radius:6px;padding:14px}.dshw img,.dshw video,.dshw iframe{max-width:100%}
142
+ .w-page{display:flex;flex-direction:column;position:relative;padding:0;min-height:540px;gap:0}.w-page[data-main=true]{height:100%;min-height:0;padding:calc(24px + var(--dsh-frame-top-clearance,0px)) 28px 0 max(28px,var(--dsh-frame-leading-clearance,0px));overflow:auto}.dshw[data-main=true]{background:var(--w-bg)}.dshw.w-page,.dshw .w-body,.dshw .w-tab-panel{overflow-x:clip}.w-page-header{display:flex;justify-content:space-between;gap:24px;align-items:flex-start;padding-bottom:22px;flex-shrink:0}.w-heading{min-width:0}.w-subtitle{margin-top:8px!important;font-size:14px;color:var(--w-muted);line-height:1.6}.w-header-actions,.w-toolbar,.w-actions{display:flex;align-items:center;flex-wrap:wrap;gap:8px;min-width:0}.w-header-actions{justify-content:flex-end}.w-body,.w-tabs-layout{display:flex;flex-direction:column;flex:1;min-height:0;min-width:0}.w-body{overflow:auto}.w-tab-panel{flex:1;min-width:0;min-height:0;display:flex;flex-direction:column;overflow:auto}.w-tabs{display:flex;align-items:stretch;gap:20px;border-bottom:1px solid var(--w-border);flex-shrink:0;overflow-x:auto;scrollbar-width:thin}.dshw .w-tabs>button{border:0;border-bottom:2px solid transparent;background:transparent;padding:11px 8px 13px;white-space:nowrap;font-size:14px;font-weight:550;cursor:pointer;color:var(--w-muted);display:flex;align-items:center;gap:7px}.dshw .w-tabs>button[aria-selected=true]{border-bottom-color:var(--w-accent);color:var(--w-accent)}.w-count,.w-tag{font-size:12px;line-height:1.5;display:inline-flex;align-items:center;flex-shrink:0;background:var(--w-soft);border-radius:5px;padding:1px 6px;color:var(--w-muted)}.w-tabs [aria-selected=true] .w-count,.w-selected .w-tag{color:var(--w-accent);background:var(--w-selected)}
143
+ .dshw .w-button{display:inline-flex;justify-content:center;align-items:center;gap:7px;background:var(--w-bg);border:1px solid var(--w-border);border-radius:8px;padding:8px 12px;min-height:36px;line-height:1.4;font-size:14px;font-weight:500;cursor:pointer;text-decoration:none;white-space:normal}.dshw .w-button:not(:disabled):hover{background:var(--w-soft)}.dshw .w-primary{background:var(--w-primary);border-color:var(--w-primary);color:var(--w-on-primary)}.dshw .w-primary:not(:disabled):hover{background:var(--w-primary);opacity:.9}.dshw .w-ghost{background:transparent;border-color:transparent}.dshw .w-danger{color:var(--dsw-alias-state-error-primary,#b43c3c)}.dshw .w-icon-button{width:36px;min-width:36px;padding:8px}.dshw .w-button svg{flex-shrink:0}.w-muted{color:var(--w-muted);font-size:12px;line-height:1.6}.w-section{padding:24px 0;border-bottom:1px solid var(--w-border);min-width:0}.w-section>h3{margin-bottom:12px}.w-section>p+p{margin-top:8px}.w-fields{display:grid;gap:16px;min-width:0}.w-field{display:grid;gap:6px;min-width:0}.w-field>input,.w-field>select,.w-field>textarea{width:100%}.w-status{display:flex;align-items:flex-start;gap:8px;padding:11px 13px;margin:12px 0;border:1px solid var(--w-border);border-radius:8px;background:var(--w-soft);font-size:13px;overflow-wrap:anywhere;flex-shrink:0}.w-status>svg{flex-shrink:0;margin-top:2px}.w-status-error{color:var(--dsw-alias-state-error-primary,#ad3636)}.w-status-success{color:var(--dsw-alias-state-success-primary,#24794a)}.w-status-warn{color:var(--dsw-alias-state-warning-primary,#8a5a00)}.w-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;gap:14px;width:100%;max-width:580px;padding:48px 24px;margin:auto;min-height:280px;overflow-wrap:anywhere}.w-empty>svg{color:var(--w-muted)}.w-empty h2{font-size:20px}.w-empty .w-muted{font-size:14px}.w-empty .w-toolbar{justify-content:center}
143
144
  .w-split{display:grid;grid-template-columns:minmax(240px,var(--w-list-width)) minmax(0,1fr);min-height:460px;flex:1;min-width:0}.w-master{min-width:0;border-inline-end:1px solid var(--w-border);overflow:auto;padding-bottom:24px}.w-detail{min-width:0;padding:26px 28px;overflow:auto;overflow-wrap:anywhere;display:flex;flex-direction:column}.w-master-toolbar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:20px 16px}.w-search{display:flex;align-items:center;gap:8px;border:1px solid var(--w-border);border-radius:8px;padding:0 10px;min-width:0;flex:1;background:var(--w-bg)}.w-search>svg{color:var(--w-muted);flex-shrink:0}.dshw .w-search>input{border:0!important;background:transparent!important;padding:8px 0!important;width:100%;outline-offset:0}.w-row{display:flex;gap:0;min-width:0;position:relative;border-bottom:1px solid var(--w-border);border-inline-start:3px solid transparent}.w-row-select{display:flex;align-items:flex-start;padding:21px 0 0 14px}.dshw .w-row-button{display:flex;flex-direction:column;align-items:stretch;gap:7px;text-align:start;width:100%;padding:18px 18px 18px 16px;border:0;background:transparent;color:inherit;min-width:0;cursor:pointer;line-height:1.5}.dshw .w-row-button:hover{background:var(--w-soft)}.w-row-head{display:flex;align-items:flex-start;gap:10px;justify-content:space-between;min-width:0}.w-row-head>strong{font-size:14px;line-height:1.5;font-weight:600;overflow-wrap:anywhere}.w-row-meta,.w-row-description{color:var(--w-muted);font-size:12px;line-height:1.6;overflow-wrap:anywhere}.w-row-description{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.w-selected{background:var(--w-selected);border-inline-start-color:var(--w-accent)}.w-back{display:none!important}.w-detail-title{margin-bottom:12px!important}.w-detail-meta{color:var(--w-muted);font-size:13px;display:flex;align-items:center;gap:8px;flex-wrap:wrap}.w-detail-footer{padding:24px 0;display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-top:auto;border-top:1px solid var(--w-border)}.w-detail-footer .w-muted{flex:1;min-width:160px}.w-definition{display:grid;grid-template-columns:minmax(80px,120px) minmax(0,1fr);gap:8px 16px;font-size:14px;margin:20px 0}.w-definition dt{color:var(--w-muted)}.w-definition dd{margin:0;min-width:0;overflow-wrap:anywhere}
144
145
  .w-switch-label{display:inline-flex;align-items:center;gap:8px;font-size:13px;position:relative;cursor:pointer}.w-switch-label>input{position:absolute;opacity:0;inset-inline-end:0;width:36px!important;height:22px!important;margin:0;cursor:pointer}.w-switch-track{width:36px;height:22px;border-radius:12px;display:block;background:var(--w-border);border:1px solid var(--w-border);pointer-events:none;padding:2px;transition:background .15s}.w-switch-track:before{content:'';display:block;width:16px;height:16px;border-radius:50%;background:#fff;box-shadow:0 1px 2px #0002;transition:transform .15s}.w-switch-label>input:checked+.w-switch-track{background:var(--w-accent);border-color:var(--w-accent)}.w-switch-label>input:checked+.w-switch-track:before{transform:translateX(14px)}.w-switch-label>input:focus-visible+.w-switch-track{outline:2px solid var(--w-accent);outline-offset:3px}.w-switch-label:has(>input:disabled){opacity:.5;cursor:not-allowed}
145
146
  .w-overlay{position:fixed;inset:0;background:#0005;display:flex;justify-content:flex-end;z-index:1000;padding:12px;overflow:auto}.w-dialog{width:min(620px,100%);max-height:100%;display:flex;flex-direction:column;min-height:0;background:var(--w-bg);color:var(--w-text);border:1px solid var(--w-border);border-radius:12px;box-shadow:0 18px 70px #0003}.w-dialog-header{display:flex;justify-content:space-between;align-items:center;gap:16px;padding:20px 24px;border-bottom:1px solid var(--w-border);flex-shrink:0}.w-dialog-header>h2{font-size:20px}.w-dialog-body{overflow:auto;padding:20px 24px;min-height:0}.w-editor-grid{display:grid;grid-template-columns:210px minmax(0,1fr) 300px;min-height:500px;flex:1}.w-editor-list{padding:20px 12px;border-inline-end:1px solid var(--w-border);min-width:0}.w-editor-canvas{background:var(--w-soft);padding:20px;min-width:0;display:flex;flex-direction:column;gap:14px}.w-editor-inspector{padding:24px;border-inline-start:1px solid var(--w-border);min-width:0;overflow:auto}.w-editor-inspector h3{margin-bottom:18px}.w-preview-empty{display:flex;flex-direction:column;justify-content:center;align-items:center;text-align:center;gap:12px;aspect-ratio:16/9;min-height:180px;background:var(--w-soft);border:1px solid var(--w-border);border-radius:8px;padding:24px;color:var(--w-muted)}.w-content-pad{padding:24px 0}.w-stack{display:flex;flex-direction:column;gap:16px;min-width:0}.w-scroll-x{overflow:auto;max-width:100%}
@@ -148,7 +149,8 @@ function createWorkbenchUI(React) {
148
149
  @media(max-width:700px){.w-page[data-main=true]{padding:calc(16px + var(--dsh-frame-top-clearance,0px)) 16px 0 max(16px,var(--dsh-frame-leading-clearance,0px))}.w-overlay{padding:8px}.w-dialog{width:100%}}
149
150
  @media(prefers-reduced-motion:reduce){.dshw *,.dshw *:before{scroll-behavior:auto!important;transition:none!important;animation:none!important}}
150
151
  `;
151
- return { Icon, Button, IconButton, Page, Tabs, Status, Empty, Split, Row, Search, Switch, Dialog, register, styles };
152
+ function Styles() { return h('style', null, styles); }
153
+ return { Icon, Button, IconButton, Page, Tabs, Status, Empty, Split, Row, Search, Switch, Dialog, Styles, register, styles };
152
154
  }
153
155
 
154
156
  /* One update control per plugin. Only transport, idle guards and installation
@@ -228,6 +230,13 @@ function __stardustUpdatesWrap(definition, participant) {
228
230
  const React = require('react');
229
231
  return { ...original, apply(ctx, ...args) {
230
232
  const result = original.apply?.call(this, ctx, ...args);
233
+ // The optional alpha.3 slot stays dormant in older hosts; its scoped
234
+ // injection unregisters naturally when the plugin is unloaded.
235
+ if (participant.iconData && participant.sectionIds?.length && typeof ctx.inject === 'function') ctx.inject(['slots'], host => {
236
+ for (const id of new Set(participant.sectionIds)) host.slots.inject('settings.section.icon', () => host.slots.register({ name: 'settings.section.icon', id }, function PluginSettingsIcon({ size = 20 }) {
237
+ return React.createElement('img', { src: participant.iconData, alt: '', 'aria-hidden': true, width: size, height: size, style: { objectFit: 'contain', display: 'block', flexShrink: 0 } });
238
+ }));
239
+ });
231
240
  if (typeof ctx.inject === 'function') ctx.inject(['slots', 'locale', 'remote', 'remote.pluginManager'], host => __stardustUpdatesJoin(host, React, require, participant));
232
241
  return result;
233
242
  } };
@@ -333,6 +342,16 @@ function __stardustUpdatesClient(ctx, React, require, shared) {
333
342
  'owner-required': t('只有 profile 拥有者能管理更新。', 'Only the profile owner can manage updates.'),
334
343
  })[code] || t('操作未完成,请刷新后重试。DSH 不会因此自动重启。', 'The operation could not be completed. Refresh and retry. DSH will not restart automatically.');
335
344
  }
345
+ // releaseOf() keeps the failing engine/peer range check as a stable code; say which
346
+ // environment has to change instead of only reporting that the release is incompatible.
347
+ function requirement(release) {
348
+ return ({
349
+ 'dsh-version': t('需要换成与该版本匹配的 DSH 本体', 'it needs a different DSH version'),
350
+ 'node-version': t('需要换成与该版本匹配的 Node.js', 'it needs a different Node.js version'),
351
+ deprecated: t('作者已把这个版本标记为弃用', 'the author marked this release as deprecated'),
352
+ 'not-bundle': t('这个版本不是可加载的 DSH 插件包', 'this release is not a loadable DSH plugin bundle'),
353
+ })[release?.reason] || t('发布元数据的兼容范围与当前环境不符', 'its published compatibility range does not match this environment');
354
+ }
336
355
  function jobLabel(job) {
337
356
  return ({ verifying: t('正在核对版本', 'Verifying release'), installing: t('正在安装', 'Installing'), cancelling: t('正在请求取消', 'Requesting cancellation'), complete: t('已更新', 'Updated'), 'restart-required': t('已安装,等待你手动重启', 'Installed; manual restart needed'), restored: t('更新未成功,已恢复原版本', 'Update failed; previous version restored'), 'restore-failed': t('恢复未成功,请检查官方插件管理', 'Recovery failed; check native plugin management'), unknown: t('结果未确认,请检查官方插件管理', 'Result unconfirmed; check native plugin management'), cancelled: t('已取消', 'Cancelled'), failed: t('更新未成功', 'Update failed') })[job.state] || job.state;
338
357
  }
@@ -371,7 +390,7 @@ function __stardustUpdatesClient(ctx, React, require, shared) {
371
390
  const title = language() === 'en' ? original.labelEn : original.label;
372
391
  const ownPage = pageState(true), unconfirmed = ['unknown', 'restore-failed'].includes(snapshot.job?.state), pageBusy = ownPage.busy || (snapshot.pages.clients || []).some(client => client.id !== id && client.busy), installLocked = working || activeJob() || unconfirmed || snapshot.updaterRestart || snapshot.preferenceError || !snapshot.activity.known || snapshot.activity.busy || snapshot.pages.dirty || ownPage.dirty || pageBusy || !snapshot.pages.known;
373
392
  const checkingThis = checking || snapshot.checkingNames?.includes(target);
374
- const status = row.sourceKind !== 'registry' ? t('本地 / 外部来源,保留原安装方式', 'Local / external source; keep original install method') : row.loadError ? t('加载异常,请先检查官方插件管理', 'Loading error; check native plugin management') : row.error ? t('检查失败,可以重试', 'Check failed; retry available') : row.release && !row.release.compatible ? t('新版本暂不兼容当前环境', 'Latest release is incompatible with this environment') : row.available ? (prefs.ignoredVersion === row.release.version ? t('已忽略提醒,仍可手动更新', 'Reminder ignored; manual update available') : t('有新版本', 'Update available')) : row.checkedAt ? t('当前已是最新稳定版', 'Latest stable version') : t('尚未检查', 'Not checked yet');
393
+ const status = row.sourceKind !== 'registry' ? t('本地 / 外部来源,保留原安装方式', 'Local / external source; keep original install method') : row.loadError ? t('加载异常,请先检查官方插件管理', 'Loading error; check native plugin management') : row.error ? t('检查失败,可以重试', 'Check failed; retry available') : row.release && !row.release.compatible ? t('新版本暂不兼容当前环境:', 'Latest release is incompatible with this environment: ') + requirement(row.release) : row.available ? (prefs.ignoredVersion === row.release.version ? t('已忽略提醒,仍可手动更新', 'Reminder ignored; manual update available') : t('有新版本', 'Update available')) : row.checkedAt ? t('当前已是最新稳定版', 'Latest stable version') : t('尚未检查', 'Not checked yet');
375
394
  return h(FooterFrame, { name, label: title, subtitle: original.name + ' · ' + original.version, actions: h(W.Button, { icon: 'refresh', disabled: checkingThis || row.sourceKind !== 'registry', onClick: check }, checkingThis ? t('正在检查…', 'Checking…') : target === '@stardustlc/dsh-suite' ? t('检查整包更新', 'Check Suite updates') : t('检查更新', 'Check for updates')) },
376
395
  original.bundledBy && h(W.Status, null, t('此插件随 Suite 安装。以下设置与安装作用于 Suite 整包,以保持组件版本一致。单独安装的插件可以独立更新。', 'This plugin was installed through Suite. These controls update Suite as a package so its components stay consistent. Independently installed plugins update individually.')),
377
396
  h('section', { className: 'w-section' }, (original.bundledBy || row.available) && h('p', { className: 'updates-version' }, target + ' · ' + row.version, row.release?.version && row.release.version !== row.version ? ' → ' + row.release.version : ''), h('p', { className: 'w-muted updates-note' }, status), !row.enabled && h('p', { className: 'w-muted' }, t('当前已停用,更新后仍保持停用。', 'Currently disabled; it will remain disabled after updating.')), row.checkedAt && h('p', { className: 'w-muted updates-note' }, t('上次检查:', 'Last checked: ') + new Date(row.checkedAt).toLocaleString(language() === 'en' ? 'en-US' : 'zh-CN')),
@@ -437,7 +456,7 @@ function __stardustUpdatesClient(ctx, React, require, shared) {
437
456
  }
438
457
 
439
458
  /* STARDUSTLC_UPDATE_CLIENT_BODY_START */
440
- window.__ModuleLoader__.load(__stardustUpdatesWrap({id:"dsh-sql",factory:require=>({apply(){}})},{"name":"dsh-sql","version":"0.1.0","hasWorkbench":false,"packageVersion":"0.5.9","label":"数据库","labelEn":"SQL","suiteComponent":true}));
459
+ window.__ModuleLoader__.load(__stardustUpdatesWrap({id:"dsh-sql",factory:require=>({apply(){}})},{"name":"dsh-sql","version":"0.1.0","hasWorkbench":false,"packageVersion":"0.5.11","label":"数据库","labelEn":"SQL","suiteComponent":true,"sectionIds":[],"iconData":"data:image/webp;base64,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"}));
441
460
 
442
461
  /* STARDUSTLC_UPDATE_CLIENT_BODY_END */
443
462
  })();
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "dsh-sql",
3
- "version": "0.5.9",
4
- "description": "先看表结构,再用查询回答问题。 需要自己的数据库连接与权限 欢迎提交 issues 和 PR。",
3
+ "version": "0.5.11",
4
+ "description": "DSH 数据库工具:SQLite / MySQL / PostgreSQL 查询、结构与统计、只读保护和写操作确认。欢迎提交 issues 和 PR。",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
7
7
  "types": "lib/index.d.ts",
@@ -26,8 +26,8 @@
26
26
  "scripts": {
27
27
  "build": "tsc -p tsconfig.json && node scripts/build-updates.mjs",
28
28
  "typecheck": "tsc -p tsconfig.json --noEmit",
29
- "test": "pnpm run build && node --test \"test/*.test.mjs\"",
30
- "prepublishOnly": "pnpm run build"
29
+ "test": "npm run build && node --test \"test/*.test.mjs\"",
30
+ "prepublishOnly": "npm run build"
31
31
  },
32
32
  "dsh": {
33
33
  "bundle": {
@@ -61,7 +61,7 @@
61
61
  "dependencies": {
62
62
  "mysql2": "^3.11.0",
63
63
  "pg": "^8.23.0",
64
- "@stardustlc/dsh-updates": "0.1.3"
64
+ "@stardustlc/dsh-updates": "0.1.4"
65
65
  },
66
66
  "devDependencies": {
67
67
  "@types/node": "^24.0.0",