dsh-dbhub-live 5.2.0-dev.3 → 5.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +116 -116
- package/README.en.md +22 -22
- package/README.md +23 -23
- package/doc/ARCHITECTURE.md +108 -108
- package/doc/CLIENT.md +124 -124
- package/doc/DESENSITIZE.md +56 -56
- package/doc/DEVELOPMENT.md +139 -139
- package/doc/IMPACT-MATRIX.md +36 -36
- package/doc/RELEASE.md +93 -93
- package/lib/meta.mjs +267 -267
- package/lib/policy.mjs +92 -92
- package/lib/update.mjs +244 -244
- package/package.json +1 -1
- package/scripts/desensitize-check.mjs +331 -331
- package/scripts/docs-check.mjs +214 -214
- package/scripts/release-preflight.mjs +180 -180
- package/test/meta.test.mjs +234 -234
- package/test/policy.test.mjs +132 -132
- package/test/update.test.mjs +270 -270
package/AGENTS.md
CHANGED
|
@@ -1,116 +1,116 @@
|
|
|
1
|
-
# AGENTS.md — dsh-dbhub-live
|
|
2
|
-
|
|
3
|
-
> 本仓库的 AI/维护者入口:**这里只记结论**(规则、常量、命令、门禁)。原因与踩坑过程见 [doc/ARCHITECTURE.md](doc/ARCHITECTURE.md),操作步骤见 [doc/DEVELOPMENT.md](doc/DEVELOPMENT.md)(调试)/ [doc/CLIENT.md](doc/CLIENT.md)(客户端半)/ [doc/RELEASE.md](doc/RELEASE.md)(发布)/ [doc/DESENSITIZE.md](doc/DESENSITIZE.md)(脱敏),改动前要核查的联动清单见 [doc/IMPACT-MATRIX.md](doc/IMPACT-MATRIX.md)。业务需求 [doc/REQUIREMENTS.md](doc/REQUIREMENTS.md),用户文档 [README.md](README.md)。
|
|
4
|
-
|
|
5
|
-
## 定位
|
|
6
|
-
|
|
7
|
-
DSH host 插件(Node ESM)+ Web client 插件:把 dbhub(Bytebase 的数据库 MCP 服务器)接入 DSH。两个性质:**零知识**(DSN/密码只在宿主侧,模型只见 source 句柄与元数据)+ **一次性进程**(每次调用 spawn 一条 dbhub,跑完即杀)。附配置页(设置 → DBHub 数据库工具 / 侧边栏 / 插件页「配置」):连接管理、连接测试、SSH 层独立测试、环境级只读、SSH 隧道、版本与更新检查;5.2 起三套布局(弹窗 / 宽屏 / 小屏)。
|
|
8
|
-
|
|
9
|
-
## 仓库结构
|
|
10
|
-
|
|
11
|
-
```
|
|
12
|
-
lib/ host + 客户端实现(模块地图见 ARCHITECTURE)| test/ 单测 | scripts/ 门禁脚本
|
|
13
|
-
release-test/ 版本矩阵实测 | doc/ 文档 | .github/ CI | cordis.patch.yml bundle patch | .env 本地脱敏黑名单
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
模块一览、各文件职责在 [doc/ARCHITECTURE.md](doc/ARCHITECTURE.md#模块地图)。
|
|
17
|
-
|
|
18
|
-
## 红线(结论)
|
|
19
|
-
|
|
20
|
-
### 零知识
|
|
21
|
-
- 工具参数**不得有 `dsn`**;`dbhub_configure` 收到 `args.dsn` 直接拒绝(`result.noDsnViaModel`)。
|
|
22
|
-
- 模型可见文本(结果/列表/标签/错误/stderr/诊断)一律过 `connLabel` 或 `scrubSecrets`;清洗要折叠任意 URL 连接串的整个 userinfo → [原因](doc/ARCHITECTURE.md#零知识边界)。
|
|
23
|
-
- 密码与完整 DSN 只经界面:`askUser`(configure)/ `configOp`(配置页)。门禁 `test/zero-knowledge.test.mjs`。
|
|
24
|
-
|
|
25
|
-
### 一次性进程
|
|
26
|
-
- `resolveSource` 解 DSN → `runAdhoc` 起一条 `dbhub --transport stdio`,跑完 terminate。**无常驻服务**(无指纹 / mtime / 空闲回收 / respawn / 孤儿清理 / 配置重启)→ [原因](doc/ARCHITECTURE.md#一次性进程的理由)。
|
|
27
|
-
- 工具恒 4 个:configure / list_sources / execute_sql / search_objects;不为工作区×环境注册工具。
|
|
28
|
-
- `apply()` 只注册工具 + `startBackgroundBoot` bookkeeping;dbhub 解析发生在每次调用(`runtime.json` 缓存);无数据源照常启动。
|
|
29
|
-
|
|
30
|
-
### 执行路径
|
|
31
|
-
- `ro === true || ssh != null` → 临时 `--config`;其余走 `--dsn`。
|
|
32
|
-
- TOML 里秘密只写 `${DSH_DBHUB_SEC_*}` 占位符,真值走子进程 env;**引用集合 == env 键集合**(`test/toml.test.mjs`)。
|
|
33
|
-
- `[[tools]]` 是白名单:只读必须写**两条** → [原因](doc/ARCHITECTURE.md#一次性toml的由来)。
|
|
34
|
-
- 版本门槛:1.4.0 起实测;`< 1.0.0` 拒绝(`result.dbhubTooOld`);不生成未实测写法。
|
|
35
|
-
- 临时文件在 `$DSH_HOME/storages/dsh-dbhub-live/tmp/`:`finally` 尽力删 + boot 时 `sweepTempToml()`。
|
|
36
|
-
|
|
37
|
-
### 环境选项(只读 / SSH)
|
|
38
|
-
- store:`credentials.json` 顶层 `{ [wsPath]: { environments: { [env]: { dsn, source, updatedAt, readOnly?, ssh? } } } }`;`ssh = {host,port,user,auth,keyPath?,passphrase?,password?,proxyJump?}`。
|
|
39
|
-
- `setWorkspaceEnv(..., opts?)`:opts 缺省**保留** readOnly/ssh;`{readOnly:false}` / `{ssh:null}` 才是删除。`setWorkspaceEnvOptions` 只改选项不碰 DSN。
|
|
40
|
-
- 模型传 `readOnly:true` 允许、`false` 拒绝(`result.readOnlyUserOnly`,拦截在 `runConfigure`)。
|
|
41
|
-
- `handleConfigOp`:`add` / `set` / `rename` / `remove` / `test` / `options`;`options` 可带 `newEnv`(改名+改选项原子);行不存在时提升为持久化行(`source:'promoted'`)。实现在 `applyOptionsOp`。
|
|
42
|
-
- 秘密字段「留空 = 保持原值」;`auth==='key'` 且无已存路径时落 `DEFAULT_SSH_KEY_PATH = '~/.ssh/id_ed25519'`;载荷统一走 `connDraftOf` / `withConnDraft`。
|
|
43
|
-
- 描述符 `{dsn, ro, ssh}`:`probeConnection` 验有效连接,`probeSshTunnel` 只验 SSH 层(`SSH_LAYER_RE` → 断;否则 `DB_LAYER_RE` / 指名转发目标 → 通;都没有 → unknown)。
|
|
44
|
-
- 预算 `PROBE_TIMEOUT_MS = 25s` / `PROBE_TIMEOUT_SSH_MS = 45s` < 客户端看门狗 30s/60s;宿主兜底 = 预算 + 500ms → [原因](doc/ARCHITECTURE.md#环境选项与执行预算)。
|
|
45
|
-
- UI 落点:现代面行内 `.dbh-rochip`(点击发 `{op:'options', readOnly}`),legacy 面 `.dbh-ro`;SSH 只进 tooltip。见 [doc/CLIENT.md](doc/CLIENT.md)。
|
|
46
|
-
|
|
47
|
-
### source 身份
|
|
48
|
-
- 每条 source 只属于一个工作区,同名不同区是不同目标;`sourceIdOf(row)` 是唯一构造点(`<标题slug>_<路径哈希>[_<envSlug>]`)。
|
|
49
|
-
- `envSlug`:`default` 裸值 / 纯 ASCII 原 slug / 非 ASCII `env-<shortHash>` → [原因](doc/ARCHITECTURE.md#envslug事故)。
|
|
50
|
-
- `resolveSource`:精确 → 当前会话工作区 → `{ambiguous}` 澄清,**不按列表顺序猜**。
|
|
51
|
-
- `dbhub_configure` 不回退 `workspaces[0]`(`result.unknownWorkspace` / `result.needWorkspace`);跨区复用走 `copyFrom`。
|
|
52
|
-
|
|
53
|
-
### 状态通道
|
|
54
|
-
- 一个发布核心 `createHostCore`,两条通道:0.1.x settings 命名空间(仅 `settings.register` 存在时)/ `connection.fetch` 的 `/api/dsh-dbhub-live/{state,enabled,options,op}`。
|
|
55
|
-
- 客户端 `inject` **只能 `["slots"]`**;host face 用 `ctx.get('settingsScope')` 探测 → [为什么](doc/ARCHITECTURE.md#状态通道与inject根因)。
|
|
56
|
-
- 注入回调内服务必须 `ctx.get(...)` 就地取;legacy 回调 `wrap()` 防护。
|
|
57
|
-
- view:`{enabled, phase, toolCount, lastError, mode}` + `{updateIntervalDays, showSidebarEntry, announceAccessPolicy, capabilities, workspaces, testResult}` + `{pluginVersion, dshVersion, dshModern, runtime, update}`;legacy 额外 `configOp`。**DSN 只从浏览器流向 Host。**
|
|
58
|
-
|
|
59
|
-
### 部署开关与连接管理
|
|
60
|
-
- `lib/options.mjs` 唯一持有开关;Config 值经 `options.configValuesOf` → `applyPatch(..., {persist:true})`;`entryIdOf(ctx)` 运行时解析行 id;不绕过 `applyPatch`。
|
|
61
|
-
- 页面只见元数据(`collectSources` → `latestSummaries`);增删改改名走 `configOp`;`renameFrom` 让「改名 + 改连接」原子。
|
|
62
|
-
- 写前先问(`requestWrite` / `envCollision` / `normalizeEnvForCompare` → `dbh-warncard`)→ [原因](doc/ARCHITECTURE.md#覆盖门为什么先问)。
|
|
63
|
-
- 即时回推:`handleConfigOp` 返回补丁并 `publishFast`;`reportTest` 只 `publishMirror`;扫描单飞 + 补丁重放;`rename` 补丁幂等 → [原因](doc/ARCHITECTURE.md#即时回推与扫描单飞)。
|
|
64
|
-
- test op 三档快路径 `resolveTestDsn`(store → 卡片缓存 → walk);失败不写 store/lastError/phase;`kind:'ssh'` 只验 SSH 层。
|
|
65
|
-
- 诊断取尾部 600(`diagnosticTail`),前缀 `【SSH 层】/【数据库层】/【插件层】`;页面只认自己派发的 nonce → [原因](doc/ARCHITECTURE.md#诊断为什么取尾部)。
|
|
66
|
-
|
|
67
|
-
### 版本与更新
|
|
68
|
-
- `dshModern` = DSH >= 0.2.1(含预发布);解析不到 → desktop true / web false → [原因](doc/ARCHITECTURE.md#版本门与更新检查)。
|
|
69
|
-
- `{op:'updateCheck'}` 在 `runOp` 中先于 `handleConfigOp` 拦截;不改行、不写 store。门禁 `test/meta.test.mjs` / `test/update.test.mjs`。
|
|
70
|
-
|
|
71
|
-
### 自动发现(mise)
|
|
72
|
-
- 每次探测必须有总超时(`MISE_ENV_TIMEOUT_MS`;`graceMs` 不是超时);结果按 `AUTO_DSN_TTL_MS` 缓存;工作区之间并发。
|
|
73
|
-
- **预算计时器不 `unref()`** → [原因](doc/ARCHITECTURE.md#自动发现的代价与unref教训)。
|
|
74
|
-
- `resolveWorkspaceRef` 必须用与扫描同一个 `listWorkspaces(ctx)`。
|
|
75
|
-
|
|
76
|
-
### 其他不可退化
|
|
77
|
-
- 依赖只进不出:`config ← state ← mcp`;`config ← runtime|toml|capability ← adhoc`;`mcp ← tools ← index`;`adhoc|collect ← tools`;`state|options ← policy ← index`;`meta`/`update` 是叶子。禁循环 import。
|
|
78
|
-
- schema 弹性:`await import('@deepseek-ai/schemastery')` 失败 → 内建最小 schema;不改回静态顶层 import。
|
|
79
|
-
- `policy.mjs` 唯一 system prompt 段(order 8900):已配置连接走 `dbhub_*`、禁 CLI/脚本/驱动/其它 MCP/其它数据库插件绕过、只读被拒不换途径;不支持的库让给用户其它插件、判不准先问。`announceAccessPolicy=false` 时 `text` 为空。门禁 `test/policy.test.mjs`。
|
|
80
|
-
- 启用/禁用:`state.setEnabled` → `credentials.json`;禁用时工具首行返回「插件已禁用」。
|
|
81
|
-
- 存储:`$DSH_HOME/storages/dsh-dbhub-live/`(credentials / prefs / runtime / dbhub-runtime / tmp);`writeJsonFile` tmp+rename,失败只 `warnOnce`;load 时清洗 + 一次性回写迁移,**未知字段保留**;进程环境变量不参与连接解析。
|
|
82
|
-
|
|
83
|
-
### 客户端半(细节见 [doc/CLIENT.md](doc/CLIENT.md))
|
|
84
|
-
- 手写 lazy-CJS bundle,无构建;`id` = Loader entry 名;三入口都要在:`settings.section`(始终)/ 侧边栏(`enabled && showSidebarEntry`)/ `plugins.row.config`(始终)。
|
|
85
|
-
- `apply()` 可重入:locale 注册失败降级 `localTranslator`。
|
|
86
|
-
- 样式只允许 `--dsw-alias-*` token + 中性半透明兜底;组件不接触 ctx。
|
|
87
|
-
- 行内只显示 `w.conn`;操作只用图标;`source` 可复制 chip;库名不截断 → [原因](doc/ARCHITECTURE.md#布局取舍)。
|
|
88
|
-
- 空闲不轮询(残留 interval 会让 `check:ui` 挂住不退出)。
|
|
89
|
-
|
|
90
|
-
## 质量门
|
|
91
|
-
|
|
92
|
-
```bash
|
|
93
|
-
npm run check # 语法:全部 lib + client.js
|
|
94
|
-
npm run check:secrets # 脱敏门禁(槽位 + 兜底 + 本地 denylist)
|
|
95
|
-
npm run check:ui # 客户端离屏渲染 + 点击交互
|
|
96
|
-
npm run check:docs # 文档链接/锚点、影响矩阵路径、包内文档一致性
|
|
97
|
-
|
|
98
|
-
# 单测必须逐文件跑(沙箱内 node --test 的 runner 子进程 EPERM)
|
|
99
|
-
Get-ChildItem test/*.test.mjs | ForEach-Object { node $_.FullName }
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
- CI:`.github/workflows/quality.yml` job **`gate`**(ubuntu-latest + Node 22),push `main`/`dev`、所有 PR、`workflow_dispatch`;`main` 分支保护把它设为必需检查。另有 `release-matrix.yml` 定时跑 `support:check`。
|
|
103
|
-
- **CI 是真实执行**,Linux 会暴露 Windows 掩盖的缺陷 → [原因](doc/ARCHITECTURE.md#自动发现的代价与unref教训)。
|
|
104
|
-
- 发布前在隔离实例完整冷启动一遍:见 [doc/DEVELOPMENT.md](doc/DEVELOPMENT.md) 第 3 步(含 200/401 与 bundle 校验)。
|
|
105
|
-
|
|
106
|
-
## 变更影响矩阵
|
|
107
|
-
|
|
108
|
-
改动前先去 [doc/IMPACT-MATRIX.md](doc/IMPACT-MATRIX.md) **按类型核查一遍联动项**(该表按需加载,本文件不内联)。矩阵本身也是受管文档:出现新的联动关系要同次加行,`npm run check:docs` 会校验它的路径与链接。
|
|
109
|
-
|
|
110
|
-
## 约定
|
|
111
|
-
|
|
112
|
-
- 产品文案中文、代码注释英文;零知识不可绕过;扫描必须经 `askUser` 授权。
|
|
113
|
-
- 仓库内一切内容视为公开分发:不得出现真实主机/账号/密码/库名/项目名,也**不得出现本机绝对路径**;示例主机用回环或 RFC 5737、示例密码用 `CHANGE_ME`;新出口同次登记槽位表;发现新真实值只写本地 `.env`(详见 [doc/DESENSITIZE.md](doc/DESENSITIZE.md))。
|
|
114
|
-
- `state.*` 之外不要直接改持久化。
|
|
115
|
-
- 发布:默认只往 `dev` 提交/推送;动 `main`、打 tag、发 npm 前先向用户确认(「可以了,发布」= dev 测试版)。流程见 [doc/RELEASE.md](doc/RELEASE.md)。
|
|
116
|
-
- 增加行为时同次更新本文件 + `doc/REQUIREMENTS.md` + README(双语,`README.md` 为唯一真源,`README.en.md` 由 AI 同次派生)。
|
|
1
|
+
# AGENTS.md — dsh-dbhub-live
|
|
2
|
+
|
|
3
|
+
> 本仓库的 AI/维护者入口:**这里只记结论**(规则、常量、命令、门禁)。原因与踩坑过程见 [doc/ARCHITECTURE.md](doc/ARCHITECTURE.md),操作步骤见 [doc/DEVELOPMENT.md](doc/DEVELOPMENT.md)(调试)/ [doc/CLIENT.md](doc/CLIENT.md)(客户端半)/ [doc/RELEASE.md](doc/RELEASE.md)(发布)/ [doc/DESENSITIZE.md](doc/DESENSITIZE.md)(脱敏),改动前要核查的联动清单见 [doc/IMPACT-MATRIX.md](doc/IMPACT-MATRIX.md)。业务需求 [doc/REQUIREMENTS.md](doc/REQUIREMENTS.md),用户文档 [README.md](README.md)。
|
|
4
|
+
|
|
5
|
+
## 定位
|
|
6
|
+
|
|
7
|
+
DSH host 插件(Node ESM)+ Web client 插件:把 dbhub(Bytebase 的数据库 MCP 服务器)接入 DSH。两个性质:**零知识**(DSN/密码只在宿主侧,模型只见 source 句柄与元数据)+ **一次性进程**(每次调用 spawn 一条 dbhub,跑完即杀)。附配置页(设置 → DBHub 数据库工具 / 侧边栏 / 插件页「配置」):连接管理、连接测试、SSH 层独立测试、环境级只读、SSH 隧道、版本与更新检查;5.2 起三套布局(弹窗 / 宽屏 / 小屏)。
|
|
8
|
+
|
|
9
|
+
## 仓库结构
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
lib/ host + 客户端实现(模块地图见 ARCHITECTURE)| test/ 单测 | scripts/ 门禁脚本
|
|
13
|
+
release-test/ 版本矩阵实测 | doc/ 文档 | .github/ CI | cordis.patch.yml bundle patch | .env 本地脱敏黑名单
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
模块一览、各文件职责在 [doc/ARCHITECTURE.md](doc/ARCHITECTURE.md#模块地图)。
|
|
17
|
+
|
|
18
|
+
## 红线(结论)
|
|
19
|
+
|
|
20
|
+
### 零知识
|
|
21
|
+
- 工具参数**不得有 `dsn`**;`dbhub_configure` 收到 `args.dsn` 直接拒绝(`result.noDsnViaModel`)。
|
|
22
|
+
- 模型可见文本(结果/列表/标签/错误/stderr/诊断)一律过 `connLabel` 或 `scrubSecrets`;清洗要折叠任意 URL 连接串的整个 userinfo → [原因](doc/ARCHITECTURE.md#零知识边界)。
|
|
23
|
+
- 密码与完整 DSN 只经界面:`askUser`(configure)/ `configOp`(配置页)。门禁 `test/zero-knowledge.test.mjs`。
|
|
24
|
+
|
|
25
|
+
### 一次性进程
|
|
26
|
+
- `resolveSource` 解 DSN → `runAdhoc` 起一条 `dbhub --transport stdio`,跑完 terminate。**无常驻服务**(无指纹 / mtime / 空闲回收 / respawn / 孤儿清理 / 配置重启)→ [原因](doc/ARCHITECTURE.md#一次性进程的理由)。
|
|
27
|
+
- 工具恒 4 个:configure / list_sources / execute_sql / search_objects;不为工作区×环境注册工具。
|
|
28
|
+
- `apply()` 只注册工具 + `startBackgroundBoot` bookkeeping;dbhub 解析发生在每次调用(`runtime.json` 缓存);无数据源照常启动。
|
|
29
|
+
|
|
30
|
+
### 执行路径
|
|
31
|
+
- `ro === true || ssh != null` → 临时 `--config`;其余走 `--dsn`。
|
|
32
|
+
- TOML 里秘密只写 `${DSH_DBHUB_SEC_*}` 占位符,真值走子进程 env;**引用集合 == env 键集合**(`test/toml.test.mjs`)。
|
|
33
|
+
- `[[tools]]` 是白名单:只读必须写**两条** → [原因](doc/ARCHITECTURE.md#一次性toml的由来)。
|
|
34
|
+
- 版本门槛:1.4.0 起实测;`< 1.0.0` 拒绝(`result.dbhubTooOld`);不生成未实测写法。
|
|
35
|
+
- 临时文件在 `$DSH_HOME/storages/dsh-dbhub-live/tmp/`:`finally` 尽力删 + boot 时 `sweepTempToml()`。
|
|
36
|
+
|
|
37
|
+
### 环境选项(只读 / SSH)
|
|
38
|
+
- store:`credentials.json` 顶层 `{ [wsPath]: { environments: { [env]: { dsn, source, updatedAt, readOnly?, ssh? } } } }`;`ssh = {host,port,user,auth,keyPath?,passphrase?,password?,proxyJump?}`。
|
|
39
|
+
- `setWorkspaceEnv(..., opts?)`:opts 缺省**保留** readOnly/ssh;`{readOnly:false}` / `{ssh:null}` 才是删除。`setWorkspaceEnvOptions` 只改选项不碰 DSN。
|
|
40
|
+
- 模型传 `readOnly:true` 允许、`false` 拒绝(`result.readOnlyUserOnly`,拦截在 `runConfigure`)。
|
|
41
|
+
- `handleConfigOp`:`add` / `set` / `rename` / `remove` / `test` / `options`;`options` 可带 `newEnv`(改名+改选项原子);行不存在时提升为持久化行(`source:'promoted'`)。实现在 `applyOptionsOp`。
|
|
42
|
+
- 秘密字段「留空 = 保持原值」;`auth==='key'` 且无已存路径时落 `DEFAULT_SSH_KEY_PATH = '~/.ssh/id_ed25519'`;载荷统一走 `connDraftOf` / `withConnDraft`。
|
|
43
|
+
- 描述符 `{dsn, ro, ssh}`:`probeConnection` 验有效连接,`probeSshTunnel` 只验 SSH 层(`SSH_LAYER_RE` → 断;否则 `DB_LAYER_RE` / 指名转发目标 → 通;都没有 → unknown)。
|
|
44
|
+
- 预算 `PROBE_TIMEOUT_MS = 25s` / `PROBE_TIMEOUT_SSH_MS = 45s` < 客户端看门狗 30s/60s;宿主兜底 = 预算 + 500ms → [原因](doc/ARCHITECTURE.md#环境选项与执行预算)。
|
|
45
|
+
- UI 落点:现代面行内 `.dbh-rochip`(点击发 `{op:'options', readOnly}`),legacy 面 `.dbh-ro`;SSH 只进 tooltip。见 [doc/CLIENT.md](doc/CLIENT.md)。
|
|
46
|
+
|
|
47
|
+
### source 身份
|
|
48
|
+
- 每条 source 只属于一个工作区,同名不同区是不同目标;`sourceIdOf(row)` 是唯一构造点(`<标题slug>_<路径哈希>[_<envSlug>]`)。
|
|
49
|
+
- `envSlug`:`default` 裸值 / 纯 ASCII 原 slug / 非 ASCII `env-<shortHash>` → [原因](doc/ARCHITECTURE.md#envslug事故)。
|
|
50
|
+
- `resolveSource`:精确 → 当前会话工作区 → `{ambiguous}` 澄清,**不按列表顺序猜**。
|
|
51
|
+
- `dbhub_configure` 不回退 `workspaces[0]`(`result.unknownWorkspace` / `result.needWorkspace`);跨区复用走 `copyFrom`。
|
|
52
|
+
|
|
53
|
+
### 状态通道
|
|
54
|
+
- 一个发布核心 `createHostCore`,两条通道:0.1.x settings 命名空间(仅 `settings.register` 存在时)/ `connection.fetch` 的 `/api/dsh-dbhub-live/{state,enabled,options,op}`。
|
|
55
|
+
- 客户端 `inject` **只能 `["slots"]`**;host face 用 `ctx.get('settingsScope')` 探测 → [为什么](doc/ARCHITECTURE.md#状态通道与inject根因)。
|
|
56
|
+
- 注入回调内服务必须 `ctx.get(...)` 就地取;legacy 回调 `wrap()` 防护。
|
|
57
|
+
- view:`{enabled, phase, toolCount, lastError, mode}` + `{updateIntervalDays, showSidebarEntry, announceAccessPolicy, capabilities, workspaces, testResult}` + `{pluginVersion, dshVersion, dshModern, runtime, update}`;legacy 额外 `configOp`。**DSN 只从浏览器流向 Host。**
|
|
58
|
+
|
|
59
|
+
### 部署开关与连接管理
|
|
60
|
+
- `lib/options.mjs` 唯一持有开关;Config 值经 `options.configValuesOf` → `applyPatch(..., {persist:true})`;`entryIdOf(ctx)` 运行时解析行 id;不绕过 `applyPatch`。
|
|
61
|
+
- 页面只见元数据(`collectSources` → `latestSummaries`);增删改改名走 `configOp`;`renameFrom` 让「改名 + 改连接」原子。
|
|
62
|
+
- 写前先问(`requestWrite` / `envCollision` / `normalizeEnvForCompare` → `dbh-warncard`)→ [原因](doc/ARCHITECTURE.md#覆盖门为什么先问)。
|
|
63
|
+
- 即时回推:`handleConfigOp` 返回补丁并 `publishFast`;`reportTest` 只 `publishMirror`;扫描单飞 + 补丁重放;`rename` 补丁幂等 → [原因](doc/ARCHITECTURE.md#即时回推与扫描单飞)。
|
|
64
|
+
- test op 三档快路径 `resolveTestDsn`(store → 卡片缓存 → walk);失败不写 store/lastError/phase;`kind:'ssh'` 只验 SSH 层。
|
|
65
|
+
- 诊断取尾部 600(`diagnosticTail`),前缀 `【SSH 层】/【数据库层】/【插件层】`;页面只认自己派发的 nonce → [原因](doc/ARCHITECTURE.md#诊断为什么取尾部)。
|
|
66
|
+
|
|
67
|
+
### 版本与更新
|
|
68
|
+
- `dshModern` = DSH >= 0.2.1(含预发布);解析不到 → desktop true / web false → [原因](doc/ARCHITECTURE.md#版本门与更新检查)。
|
|
69
|
+
- `{op:'updateCheck'}` 在 `runOp` 中先于 `handleConfigOp` 拦截;不改行、不写 store。门禁 `test/meta.test.mjs` / `test/update.test.mjs`。
|
|
70
|
+
|
|
71
|
+
### 自动发现(mise)
|
|
72
|
+
- 每次探测必须有总超时(`MISE_ENV_TIMEOUT_MS`;`graceMs` 不是超时);结果按 `AUTO_DSN_TTL_MS` 缓存;工作区之间并发。
|
|
73
|
+
- **预算计时器不 `unref()`** → [原因](doc/ARCHITECTURE.md#自动发现的代价与unref教训)。
|
|
74
|
+
- `resolveWorkspaceRef` 必须用与扫描同一个 `listWorkspaces(ctx)`。
|
|
75
|
+
|
|
76
|
+
### 其他不可退化
|
|
77
|
+
- 依赖只进不出:`config ← state ← mcp`;`config ← runtime|toml|capability ← adhoc`;`mcp ← tools ← index`;`adhoc|collect ← tools`;`state|options ← policy ← index`;`meta`/`update` 是叶子。禁循环 import。
|
|
78
|
+
- schema 弹性:`await import('@deepseek-ai/schemastery')` 失败 → 内建最小 schema;不改回静态顶层 import。
|
|
79
|
+
- `policy.mjs` 唯一 system prompt 段(order 8900):已配置连接走 `dbhub_*`、禁 CLI/脚本/驱动/其它 MCP/其它数据库插件绕过、只读被拒不换途径;不支持的库让给用户其它插件、判不准先问。`announceAccessPolicy=false` 时 `text` 为空。门禁 `test/policy.test.mjs`。
|
|
80
|
+
- 启用/禁用:`state.setEnabled` → `credentials.json`;禁用时工具首行返回「插件已禁用」。
|
|
81
|
+
- 存储:`$DSH_HOME/storages/dsh-dbhub-live/`(credentials / prefs / runtime / dbhub-runtime / tmp);`writeJsonFile` tmp+rename,失败只 `warnOnce`;load 时清洗 + 一次性回写迁移,**未知字段保留**;进程环境变量不参与连接解析。
|
|
82
|
+
|
|
83
|
+
### 客户端半(细节见 [doc/CLIENT.md](doc/CLIENT.md))
|
|
84
|
+
- 手写 lazy-CJS bundle,无构建;`id` = Loader entry 名;三入口都要在:`settings.section`(始终)/ 侧边栏(`enabled && showSidebarEntry`)/ `plugins.row.config`(始终)。
|
|
85
|
+
- `apply()` 可重入:locale 注册失败降级 `localTranslator`。
|
|
86
|
+
- 样式只允许 `--dsw-alias-*` token + 中性半透明兜底;组件不接触 ctx。
|
|
87
|
+
- 行内只显示 `w.conn`;操作只用图标;`source` 可复制 chip;库名不截断 → [原因](doc/ARCHITECTURE.md#布局取舍)。
|
|
88
|
+
- 空闲不轮询(残留 interval 会让 `check:ui` 挂住不退出)。
|
|
89
|
+
|
|
90
|
+
## 质量门
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
npm run check # 语法:全部 lib + client.js
|
|
94
|
+
npm run check:secrets # 脱敏门禁(槽位 + 兜底 + 本地 denylist)
|
|
95
|
+
npm run check:ui # 客户端离屏渲染 + 点击交互
|
|
96
|
+
npm run check:docs # 文档链接/锚点、影响矩阵路径、包内文档一致性
|
|
97
|
+
|
|
98
|
+
# 单测必须逐文件跑(沙箱内 node --test 的 runner 子进程 EPERM)
|
|
99
|
+
Get-ChildItem test/*.test.mjs | ForEach-Object { node $_.FullName }
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
- CI:`.github/workflows/quality.yml` job **`gate`**(ubuntu-latest + Node 22),push `main`/`dev`、所有 PR、`workflow_dispatch`;`main` 分支保护把它设为必需检查。另有 `release-matrix.yml` 定时跑 `support:check`。
|
|
103
|
+
- **CI 是真实执行**,Linux 会暴露 Windows 掩盖的缺陷 → [原因](doc/ARCHITECTURE.md#自动发现的代价与unref教训)。
|
|
104
|
+
- 发布前在隔离实例完整冷启动一遍:见 [doc/DEVELOPMENT.md](doc/DEVELOPMENT.md) 第 3 步(含 200/401 与 bundle 校验)。
|
|
105
|
+
|
|
106
|
+
## 变更影响矩阵
|
|
107
|
+
|
|
108
|
+
改动前先去 [doc/IMPACT-MATRIX.md](doc/IMPACT-MATRIX.md) **按类型核查一遍联动项**(该表按需加载,本文件不内联)。矩阵本身也是受管文档:出现新的联动关系要同次加行,`npm run check:docs` 会校验它的路径与链接。
|
|
109
|
+
|
|
110
|
+
## 约定
|
|
111
|
+
|
|
112
|
+
- 产品文案中文、代码注释英文;零知识不可绕过;扫描必须经 `askUser` 授权。
|
|
113
|
+
- 仓库内一切内容视为公开分发:不得出现真实主机/账号/密码/库名/项目名,也**不得出现本机绝对路径**;示例主机用回环或 RFC 5737、示例密码用 `CHANGE_ME`;新出口同次登记槽位表;发现新真实值只写本地 `.env`(详见 [doc/DESENSITIZE.md](doc/DESENSITIZE.md))。
|
|
114
|
+
- `state.*` 之外不要直接改持久化。
|
|
115
|
+
- 发布:默认只往 `dev` 提交/推送;动 `main`、打 tag、发 npm 前先向用户确认(「可以了,发布」= dev 测试版)。流程见 [doc/RELEASE.md](doc/RELEASE.md)。
|
|
116
|
+
- 增加行为时同次更新本文件 + `doc/REQUIREMENTS.md` + README(双语,`README.md` 为唯一真源,`README.en.md` 由 AI 同次派生)。
|
package/README.en.md
CHANGED
|
@@ -33,26 +33,26 @@ Install it and you can simply tell the AI "show me the last 10 rows of the order
|
|
|
33
33
|
|
|
34
34
|
Supports **MySQL · PostgreSQL · MariaDB · SQLite · SQL Server**.
|
|
35
35
|
|
|
36
|
-
<!-- release-test:versions:begin -->
|
|
37
|
-
## Supported version range
|
|
38
|
-
|
|
39
|
-
**From DSH 0.1.5 (lines 0.1.5 / 0.1.6 / 0.1.7 / 0.2.0 / 0.2.1, prereleases included)** — 6 declared versions verified (last verified 2026-10-24).
|
|
40
|
-
|
|
41
|
-
<details>
|
|
42
|
-
<summary>Per-version verification details (expand)</summary>
|
|
43
|
-
|
|
44
|
-
| DSH version | UI | Boot | Hard checks | Result | Last verified |
|
|
45
|
-
| --- | --- | --- | --- | --- | --- |
|
|
46
|
-
| `0.1.5-rc.3` | legacy |
|
|
47
|
-
| `0.1.6-alpha.2` | legacy |
|
|
48
|
-
| `0.1.7-rc.2` | legacy |
|
|
49
|
-
| `0.2.0-rc.2` | legacy |
|
|
50
|
-
| `0.2.1-alpha.1` | modern |
|
|
51
|
-
| `0.2.1-rc.2` | modern |
|
|
52
|
-
|
|
53
|
-
</details>
|
|
54
|
-
|
|
55
|
-
Full evidence, review rules and known drift live in [doc/SUPPORT-MATRIX.md](doc/SUPPORT-MATRIX.md).
|
|
36
|
+
<!-- release-test:versions:begin -->
|
|
37
|
+
## Supported version range
|
|
38
|
+
|
|
39
|
+
**From DSH 0.1.5 (lines 0.1.5 / 0.1.6 / 0.1.7 / 0.2.0 / 0.2.1, prereleases included)** — 6 declared versions verified (last verified 2026-10-24).
|
|
40
|
+
|
|
41
|
+
<details>
|
|
42
|
+
<summary>Per-version verification details (expand)</summary>
|
|
43
|
+
|
|
44
|
+
| DSH version | UI | Boot | Hard checks | Result | Last verified |
|
|
45
|
+
| --- | --- | --- | --- | --- | --- |
|
|
46
|
+
| `0.1.5-rc.3` | legacy | 39.8s | 19 | ⚠️ pass with notes · manual | 2026-10-24 · 91642fa2 |
|
|
47
|
+
| `0.1.6-alpha.2` | legacy | 13.1s | 19 | ⚠️ pass with notes · manual | 2026-10-24 · 91642fa2 |
|
|
48
|
+
| `0.1.7-rc.2` | legacy | 14.8s | 20 | ⚠️ pass with notes · manual | 2026-10-24 · 91642fa2 |
|
|
49
|
+
| `0.2.0-rc.2` | legacy | 14.8s | 20 | ⚠️ pass with notes · manual | 2026-10-24 · 91642fa2 |
|
|
50
|
+
| `0.2.1-alpha.1` | modern | 15.2s | 20 | ⚠️ pass with notes · manual | 2026-10-24 · 91642fa2 |
|
|
51
|
+
| `0.2.1-rc.2` | modern | 16.9s | 20 | ⚠️ pass with notes · manual | 2026-10-24 · 91642fa2 |
|
|
52
|
+
|
|
53
|
+
</details>
|
|
54
|
+
|
|
55
|
+
Full evidence, review rules and known drift live in [doc/SUPPORT-MATRIX.md](doc/SUPPORT-MATRIX.md).
|
|
56
56
|
<!-- release-test:versions:end -->
|
|
57
57
|
|
|
58
58
|
## Installation
|
|
@@ -87,7 +87,7 @@ Then **restart `dsh web`**.
|
|
|
87
87
|
|
|
88
88
|
**Desktop**: uninstall the plugin on the **left menu → Plugins** page and reinstall the latest version (desktop updates go through the visual Plugins page). **Connections and credentials survive the reinstall** — they live in `~/.dsh/storages/dsh-dbhub-live`, independent of the module directory.
|
|
89
89
|
|
|
90
|
-
**No need to remember version numbers**: the configure page header shows the plugin name and the current version; when a newer version exists a quiet "**↑ Upgrade to <latest>**" text link appears and **clicking it
|
|
90
|
+
**No need to remember version numbers**: the configure page header shows the plugin name and the current version; when a newer version exists a quiet "**↑ Upgrade to <latest>**" text link appears and **clicking it opens a panel where you copy** `dsh-dbhub-live@<latest>`; the "Check for updates" button next to it checks on demand. Opening the page also triggers one automatic check (throttled, so it does not hit the network on every open). Checks use the **npm registry first, with GitHub Releases as the fallback**; release notes live in [GitHub Releases](https://github.com/mr-mihu/dsh-dbhub-live/releases).
|
|
91
91
|
|
|
92
92
|
> The version/update hint is part of the new UI and needs plugin 5.2.0+ and DSH 0.2.1+; on 0.1.x it is not shown (see "Configure Page").
|
|
93
93
|
|
|
@@ -163,7 +163,7 @@ The same component offers **three layouts**, picked automatically from the host
|
|
|
163
163
|
|
|
164
164
|
**Header: version and upgrade entry**: the title is the plugin name with the current version (small, muted) right next to it; when a newer version exists a quiet "**↑ Upgrade to <latest>**" text link appears on the right, and **clicking it expands** the update notes — the `dsh-dbhub-live@<latest>` spec (click to copy), the update command / steps for this deployment, and a link to the release notes; the "↻" button checks on demand. Opening the page also triggers an automatic check (throttled). Checks use the npm registry first, with GitHub Releases as the fallback. **An update is neutral news, never styled as an error.**
|
|
165
165
|
|
|
166
|
-
- **Status line**: it shows only "running / disabled · N connections". Implementation facts — tool count, one-shot execution mode, dbhub version — live in the collapsed "ⓘ Details
|
|
166
|
+
- **Status line**: it shows only "running / disabled · N connections". Implementation facts — tool count, one-shot execution mode, dbhub version — live in the collapsed "ⓘ Details" block below the status line.
|
|
167
167
|
- **Connection list**: organised by workspace. When every workspace has a single environment the rows render as flat cards; as soon as one workspace owns several environments they fold into per-workspace groups (click a group head to expand; the most recently used one is open by default). Each connection takes one line: environment name · type / host / port / **database** · **read-only switch** · the `source` handle (click it to copy) · test / edit / delete. In a narrow window the host and port are truncated first, while **the database name always stays visible**.
|
|
168
168
|
- **Settings (DSH-native style, deliberately quiet)**: on the wide page the four controls collapse into **one compact settings line** — `Plugin settings · Enable plugin [enabled] · Sidebar entry [shown] · Access policy [on] · Auto-update [7] days [save] · ⓘ details`; the modal and the phone use compact stacked rows. Fonts and switches are kept small so the **connection list** stays the main content. The controls are DSH's own switches (theme/skin aware, with state words); every explanatory paragraph lives in "ⓘ Details & diagnostics".
|
|
169
169
|
- **Read-only switch (outside the edit form in all three layouts)**: right next to the datasource on every connection row there is a small "RO" toggle — one click flips it (open lock + "Writable" = writable; closed lock + "RO" = read-only) without opening the edit form; the modal and the phone layout have it too. The tick-box in the edit form stays as well; both are the same state. **The connection string itself no longer carries a lock icon** — it used to read like "this row needs a password" and clashed with the read-only lock.
|
package/README.md
CHANGED
|
@@ -33,26 +33,26 @@
|
|
|
33
33
|
|
|
34
34
|
支持 **MySQL · PostgreSQL · MariaDB · SQLite · SQL Server**。
|
|
35
35
|
|
|
36
|
-
<!-- release-test:versions:begin -->
|
|
37
|
-
## 支持的版本范围
|
|
38
|
-
|
|
39
|
-
**DSH 0.1.5 起(0.1.5 / 0.1.6 / 0.1.7 / 0.2.0 / 0.2.1 共 5 条版本线,含预发布)** — 6 个声明版本已实测通过(最近验证 2026-10-24)。
|
|
40
|
-
|
|
41
|
-
<details>
|
|
42
|
-
<summary>逐版本实测明细(点开查看)</summary>
|
|
43
|
-
|
|
44
|
-
| DSH 版本 | 界面 | 启动 | 硬检查 | 结论 | 最近验证 |
|
|
45
|
-
| --- | --- | --- | --- | --- | --- |
|
|
46
|
-
| `0.1.5-rc.3` | 旧版 |
|
|
47
|
-
| `0.1.6-alpha.2` | 旧版 |
|
|
48
|
-
| `0.1.7-rc.2` | 旧版 |
|
|
49
|
-
| `0.2.0-rc.2` | 旧版 |
|
|
50
|
-
| `0.2.1-alpha.1` | 新版 |
|
|
51
|
-
| `0.2.1-rc.2` | 新版 |
|
|
52
|
-
|
|
53
|
-
</details>
|
|
54
|
-
|
|
55
|
-
完整证据、判定规则与已知偏差见 [doc/SUPPORT-MATRIX.md](doc/SUPPORT-MATRIX.md)。
|
|
36
|
+
<!-- release-test:versions:begin -->
|
|
37
|
+
## 支持的版本范围
|
|
38
|
+
|
|
39
|
+
**DSH 0.1.5 起(0.1.5 / 0.1.6 / 0.1.7 / 0.2.0 / 0.2.1 共 5 条版本线,含预发布)** — 6 个声明版本已实测通过(最近验证 2026-10-24)。
|
|
40
|
+
|
|
41
|
+
<details>
|
|
42
|
+
<summary>逐版本实测明细(点开查看)</summary>
|
|
43
|
+
|
|
44
|
+
| DSH 版本 | 界面 | 启动 | 硬检查 | 结论 | 最近验证 |
|
|
45
|
+
| --- | --- | --- | --- | --- | --- |
|
|
46
|
+
| `0.1.5-rc.3` | 旧版 | 39.8s | 19 | ⚠️ 通过(有告警) · 手工装配 | 2026-10-24 · 91642fa2 |
|
|
47
|
+
| `0.1.6-alpha.2` | 旧版 | 13.1s | 19 | ⚠️ 通过(有告警) · 手工装配 | 2026-10-24 · 91642fa2 |
|
|
48
|
+
| `0.1.7-rc.2` | 旧版 | 14.8s | 20 | ⚠️ 通过(有告警) · 手工装配 | 2026-10-24 · 91642fa2 |
|
|
49
|
+
| `0.2.0-rc.2` | 旧版 | 14.8s | 20 | ⚠️ 通过(有告警) · 手工装配 | 2026-10-24 · 91642fa2 |
|
|
50
|
+
| `0.2.1-alpha.1` | 新版 | 15.2s | 20 | ⚠️ 通过(有告警) · 手工装配 | 2026-10-24 · 91642fa2 |
|
|
51
|
+
| `0.2.1-rc.2` | 新版 | 16.9s | 20 | ⚠️ 通过(有告警) · 手工装配 | 2026-10-24 · 91642fa2 |
|
|
52
|
+
|
|
53
|
+
</details>
|
|
54
|
+
|
|
55
|
+
完整证据、判定规则与已知偏差见 [doc/SUPPORT-MATRIX.md](doc/SUPPORT-MATRIX.md)。
|
|
56
56
|
<!-- release-test:versions:end -->
|
|
57
57
|
|
|
58
58
|
## 安装
|
|
@@ -87,7 +87,7 @@ dsh plugin --profile web up dsh-dbhub-live@<最新版本号>
|
|
|
87
87
|
|
|
88
88
|
**桌面端**:在 **左侧菜单 → 插件** 页里卸载该插件,再重新安装最新版本(桌面端更新走可视化插件页)。**连接与凭据不会被重装清掉**——它们都在 `~/.dsh/storages/dsh-dbhub-live`,与模块目录无关。
|
|
89
89
|
|
|
90
|
-
**不用自己记版本号**:配置页页头显示插件名与当前版本,检测到更新时会出现一行低调的「**↑ 可升级到 <latest
|
|
90
|
+
**不用自己记版本号**:配置页页头显示插件名与当前版本,检测到更新时会出现一行低调的「**↑ 可升级到 <latest>**」文字链接,**点开后在面板里点一下即可复制** `dsh-dbhub-live@<latest>`;旁边的「检查更新」按钮可以随时手动检查。打开页面时也会自动检查一次(有节流,不会每次打开都打网络)。检查以 **npm registry 为主、GitHub Releases 为兜底**,发布说明见 [GitHub Releases](https://github.com/mr-mihu/dsh-dbhub-live/releases)。
|
|
91
91
|
|
|
92
92
|
> 版本与升级提示属于新界面,需要插件 5.2.0+ 且 DSH 0.2.1+;0.1.x 上不显示(见「配置页」)。
|
|
93
93
|
|
|
@@ -163,9 +163,9 @@ AI:…(返回查询结果)
|
|
|
163
163
|
|
|
164
164
|
**页头:版本与升级入口**:标题是插件名,紧跟当前版本(灰色小字);有更新时右侧出现一行低调的「**↑ 可升级到 <latest>**」文字链接,**点开才展开**更新说明——里面是 `dsh-dbhub-live@<latest>`(点击复制)、按部署方式给的更新命令 / 步骤,以及更新说明链接;「↻」按钮随时手动检查一次。打开页面时也会自动检查(有节流)。检查以 npm registry 为主、GitHub Releases 为兜底。**更新是中性提示,不会用报错红。**
|
|
165
165
|
|
|
166
|
-
- **状态行**:只显示「运行中 /
|
|
166
|
+
- **状态行**:只显示「运行中 / 已禁用 · N 个连接」。工具数量、一次性执行模式、dbhub 版本这类实现细节收进状态行下方的「ⓘ 说明」折叠区,默认不展开。
|
|
167
167
|
- **连接列表**:按工作区组织。所有工作区都只有一个环境时用平铺卡片;任一工作区有多个环境时按工作区分组折叠(点组头展开,默认展开最近使用的那个)。每个连接只占一行:环境名 · 类型 / 主机 / 端口 / **库名** · **只读开关** · `source` 句柄(点它即复制) · 测试 / 修改 / 删除。窄窗口下先截断主机端口,**库名始终可见**。
|
|
168
|
-
- **设置区(DSH 主体样式,刻意弱化)**:宽屏把四项收成**一行紧凑设置条**——`插件设置 · 启用插件[启用] · 侧边栏入口[显示] · 访问策略[开启] · 自动更新[7]天[保存] · ⓘ说明`;弹窗与手机是紧凑设置行。字号与开关都收小,让**连接列表**成为页面主体。控件用 DSH 自己的开关(跟随主题 / 皮肤,带汉字状态词);解释性长文字都在「ⓘ
|
|
168
|
+
- **设置区(DSH 主体样式,刻意弱化)**:宽屏把四项收成**一行紧凑设置条**——`插件设置 · 启用插件[启用] · 侧边栏入口[显示] · 访问策略[开启] · 自动更新[7]天[保存] · ⓘ说明`;弹窗与手机是紧凑设置行。字号与开关都收小,让**连接列表**成为页面主体。控件用 DSH 自己的开关(跟随主题 / 皮肤,带汉字状态词);解释性长文字都在「ⓘ 说明」里。
|
|
169
169
|
- **只读开关(三种布局都在外面)**:每条连接行的数据源旁边就是该环境的「只读」小开关,点一下即改(开锁图标 + 「可写」= 可写;闭锁图标 + 「只读」= 已只读),不必打开编辑表单;弹窗 / 手机同样可用。编辑表单里的勾选也保留,两处是同一个状态。**连接串本身不再带锁形图标**——过去容易被误读成"需要密码",也和只读锁冲突。
|
|
170
170
|
- **增删改**:行内 ✏ 改连接串或环境名;「+ 添加连接」支持中文环境名。**同名环境保存前会先问「是否覆盖」**,取消则一个字都不写。
|
|
171
171
|
- **连接测试**:按该环境**真正会被使用的有效连接**(含只读 / 隧道)执行 `SELECT 1`,测试中显示已耗时。结果是一次性反馈,不持久化、不改变连接状态。
|