dsh-sql 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 stardustlc
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.en.md CHANGED
@@ -10,12 +10,25 @@ DSH (DeepSeek Harness) engineer-grade database plugin: four tools covering conne
10
10
 
11
11
  [![Awesome DSH Plugin](https://awesome-dsh-plugin.com/badge.svg)](https://awesome-dsh-plugin.com)
12
12
 
13
+ ## Compatibility
14
+
15
+ Verified against `@deepseek-ai/dsh@0.1.1-rc.2` on 2026-08-26. Built for the cordis patch-bundle plugin model (`cordis.patch.yml` + `dsh.bundle.patch`). No runtime imports of `@deepseek-ai/*` internals.
16
+
13
17
  ## Installation
14
18
 
15
19
  ```bash
16
20
  dsh plugin --profile web add dsh-sql
17
21
  ```
18
22
 
23
+ ## Uninstall
24
+
25
+ ```bash
26
+ dsh plugin --profile web remove dsh-sql
27
+ ```
28
+
29
+ Then restart the web service. To clean up fully, also remove the plugin entry from your profile `cordis.patch.yml` if you overrode it.
30
+
31
+
19
32
  ## Configuration
20
33
 
21
34
  ```yaml
@@ -87,4 +100,4 @@ pnpm test # build + 35 tests, including a real SQLite integration suite
87
100
 
88
101
  ## License
89
102
 
90
- MIT
103
+ MIT
package/README.md CHANGED
@@ -10,12 +10,25 @@ DSH(DeepSeek Harness)工程师级数据库插件:四个工具覆盖连接
10
10
 
11
11
  [![Awesome DSH Plugin](https://awesome-dsh-plugin.com/badge.svg)](https://awesome-dsh-plugin.com)
12
12
 
13
+ ## 兼容性
14
+
15
+ 在 `@deepseek-ai/dsh@0.1.1-rc.2` 上验证(2026-08-26)。遵循 cordis 组合包补丁模型(`cordis.patch.yml` + `dsh.bundle.patch`),运行时不 import 任何 `@deepseek-ai/*` 内部模块。
16
+
13
17
  ## 安装
14
18
 
15
19
  ```bash
16
20
  dsh plugin --profile web add dsh-sql
17
21
  ```
18
22
 
23
+ ## 卸载
24
+
25
+ ```bash
26
+ dsh plugin --profile web remove dsh-sql
27
+ ```
28
+
29
+ 卸载后重启 Web 服务。如需彻底清理,可再手动删除自己 profile `cordis.patch.yml` 中覆盖的插件行。
30
+
31
+
19
32
  ## 配置
20
33
 
21
34
  ```yaml
@@ -87,4 +100,4 @@ pnpm test # 构建 + 35 个测试(含真实 SQLite 集成)
87
100
 
88
101
  ## License
89
102
 
90
- MIT
103
+ MIT
package/cordis.patch.yml CHANGED
@@ -12,8 +12,8 @@
12
12
  # engine: sqlite
13
13
  # file: E:\data\app.db
14
14
  # maxRows: 1000 # sql_query 返回行数上限(1-10000,默认 1000)
15
- queryTimeoutMs: 60000 # 单次查询超时(5 秒 - 10 分钟)
16
- execTimeoutMs: 120000 # 单次写操作超时(5 秒 - 10 分钟)
15
+ # queryTimeoutMs: 60000 # 单次查询超时(5 秒 - 10 分钟)
16
+ # execTimeoutMs: 120000 # 单次写操作超时(5 秒 - 10 分钟)
17
17
  # readOnly: false # true 时 sql_exec 被禁用
18
18
  # writeApproval: true # 写操作先弹审批(默认 true)
19
19
  #
package/lib/index.d.ts CHANGED
@@ -10,6 +10,7 @@
10
10
  import { type SqlConfig } from './config.js';
11
11
  import { type SqlToolDefinition } from './tools.js';
12
12
  /** cordis 服务注入:apply 里要用 ctx.tools,必须显式声明。 */
13
+ export declare const name = "sql";
13
14
  export declare const inject: string[];
14
15
  /** 审批服务最小面(对齐 dsh-email)。 */
15
16
  export interface SqlApproval {
package/lib/index.js CHANGED
@@ -10,6 +10,7 @@
10
10
  import { resolveConfig } from './config.js';
11
11
  import { buildSqlTools } from './tools.js';
12
12
  /** cordis 服务注入:apply 里要用 ctx.tools,必须显式声明。 */
13
+ export const name = 'sql';
13
14
  export const inject = ['tools'];
14
15
  /**
15
16
  * 插件入口:解析配置、构建四工具、给 sql_exec 注入审批门。
package/lib/tools.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * 四个面向模型的数据库工具:sql_list / sql_query / sql_exec / sql_schema。
2
+ * 六个面向模型的数据库工具:sql_list / sql_query / sql_exec / sql_schema / sql_stats / sql_health。
3
3
  *
4
4
  * @module dsh-sql/tools
5
5
  */
@@ -29,6 +29,8 @@ export interface SqlToolDefinition {
29
29
  }
30
30
  /** 校验只读查询:词法去噪后白名单开头 + 写关键字扫描 + 单语句。 */
31
31
  export declare function assertReadQuery(sql: string): string;
32
+ /** 查询结果转 CSV 文本(RFC 4180 风格转义)。 */
33
+ export declare function toCsv(columns: string[], rows: unknown[][]): string;
32
34
  /** 审批执行上下文的最小面。 */
33
35
  export interface SqlExecGateContext {
34
36
  agent?: unknown;
package/lib/tools.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * 四个面向模型的数据库工具:sql_list / sql_query / sql_exec / sql_schema。
2
+ * 六个面向模型的数据库工具:sql_list / sql_query / sql_exec / sql_schema / sql_stats / sql_health。
3
3
  *
4
4
  * @module dsh-sql/tools
5
5
  */
@@ -166,6 +166,8 @@ const querySchema = {
166
166
  rowCount: { type: 'integer' },
167
167
  truncated: { type: 'boolean' },
168
168
  maxRows: { type: 'integer' },
169
+ format: { type: 'string' },
170
+ formatted: { type: 'string' },
169
171
  },
170
172
  additionalProperties: true,
171
173
  };
@@ -208,6 +210,75 @@ const schemaToolSchema = {
208
210
  },
209
211
  additionalProperties: true,
210
212
  };
213
+ // ---------- 输出格式与统计辅助 ----------
214
+ /** 按引擎给标识符加引号,防止表名破坏 SQL。 */
215
+ function quoteIdent(engine, name) {
216
+ if (engine === 'mysql')
217
+ return '`' + name.replace(/`/g, '``') + '`';
218
+ return '"' + name.replace(/"/g, '""') + '"';
219
+ }
220
+ /** 查询结果转 CSV 文本(RFC 4180 风格转义)。 */
221
+ export function toCsv(columns, rows) {
222
+ const escape = (cell) => {
223
+ if (cell === null || cell === undefined)
224
+ return '';
225
+ const text = Array.isArray(cell) || typeof cell === 'object' ? JSON.stringify(cell) : String(cell);
226
+ return /[",\n\r]/.test(text) ? '"' + text.replace(/"/g, '""') + '"' : text;
227
+ };
228
+ const lines = [columns.map(escape).join(',')];
229
+ for (const row of rows)
230
+ lines.push(row.map(escape).join(','));
231
+ return lines.join('\n');
232
+ }
233
+ /** 人类可读的字节数。 */
234
+ function formatBytes(bytes) {
235
+ if (bytes < 1024)
236
+ return bytes + ' B';
237
+ if (bytes < 1024 * 1024)
238
+ return (bytes / 1024).toFixed(1) + ' KB';
239
+ if (bytes < 1024 * 1024 * 1024)
240
+ return (bytes / 1024 / 1024).toFixed(1) + ' MB';
241
+ return (bytes / 1024 / 1024 / 1024).toFixed(2) + ' GB';
242
+ }
243
+ /** 库体积:SQLite 用页数×页大小;MySQL/PostgreSQL 走系统函数;失败抛错由调用方兜底。 */
244
+ async function databaseSize(adapter, engine) {
245
+ if (engine === 'sqlite') {
246
+ const pageCount = await adapter.query('PRAGMA page_count', 1);
247
+ const pageSize = await adapter.query('PRAGMA page_size', 1);
248
+ return Number(pageCount.rows[0]?.[0] ?? 0) * Number(pageSize.rows[0]?.[0] ?? 0);
249
+ }
250
+ if (engine === 'mysql') {
251
+ const result = await adapter.query('SELECT SUM(DATA_LENGTH + INDEX_LENGTH) FROM information_schema.tables WHERE TABLE_SCHEMA = DATABASE()', 1);
252
+ return Number(result.rows[0]?.[0] ?? -1);
253
+ }
254
+ const result = await adapter.query('SELECT pg_database_size(current_database())', 1);
255
+ return Number(result.rows[0]?.[0] ?? -1);
256
+ }
257
+ const statsSchema = {
258
+ type: 'object',
259
+ properties: {
260
+ connection: { type: 'string' },
261
+ engine: { type: 'string' },
262
+ tableCount: { type: 'integer' },
263
+ tables: { type: 'array', items: { type: 'object', additionalProperties: true } },
264
+ sizeBytes: { type: 'integer' },
265
+ },
266
+ additionalProperties: true,
267
+ };
268
+ const healthSchema = {
269
+ type: 'object',
270
+ properties: {
271
+ ok: { type: 'boolean' },
272
+ plugin: { type: 'string' },
273
+ connections: { type: 'array', items: { type: 'object', additionalProperties: true } },
274
+ readOnly: { type: 'boolean' },
275
+ writeApproval: { type: 'boolean' },
276
+ maxRows: { type: 'integer' },
277
+ queryTimeoutMs: { type: 'integer' },
278
+ execTimeoutMs: { type: 'integer' },
279
+ },
280
+ additionalProperties: true,
281
+ };
211
282
  /** 构建四个工具定义;adapters 惰性创建并按连接名缓存。 */
212
283
  export function buildSqlTools(config) {
213
284
  const cfg = config;
@@ -225,6 +296,30 @@ export function buildSqlTools(config) {
225
296
  }
226
297
  return { adapter, name: connection.name };
227
298
  };
299
+ const pingAllConnections = async () => {
300
+ const rows = [];
301
+ for (const connection of cfg.connections) {
302
+ const entry = { name: connection.name, engine: connection.engine };
303
+ if (connection.engine === 'sqlite')
304
+ entry.file = connection.file ?? ':memory:';
305
+ else {
306
+ entry.host = connection.host ?? '';
307
+ entry.database = connection.database ?? '';
308
+ }
309
+ try {
310
+ const { adapter } = getAdapter(connection.name);
311
+ await adapter.ping();
312
+ entry.ok = true;
313
+ entry.error = '';
314
+ }
315
+ catch (error) {
316
+ entry.ok = false;
317
+ entry.error = error instanceof Error ? error.message : String(error);
318
+ }
319
+ rows.push(entry);
320
+ }
321
+ return rows;
322
+ };
228
323
  const sqlList = {
229
324
  name: 'sql_list',
230
325
  description: '列出配置的数据库连接并逐一做连通性测试(SELECT 1)。返回连接名、引擎、目标与健康状态。',
@@ -244,28 +339,7 @@ export function buildSqlTools(config) {
244
339
  },
245
340
  },
246
341
  async execute() {
247
- const rows = [];
248
- for (const connection of cfg.connections) {
249
- const entry = { name: connection.name, engine: connection.engine };
250
- if (connection.engine === 'sqlite')
251
- entry.file = connection.file ?? ':memory:';
252
- else {
253
- entry.host = connection.host ?? '';
254
- entry.database = connection.database ?? '';
255
- }
256
- try {
257
- const { adapter } = getAdapter(connection.name);
258
- await adapter.ping();
259
- entry.ok = true;
260
- entry.error = '';
261
- }
262
- catch (error) {
263
- entry.ok = false;
264
- entry.error = error instanceof Error ? error.message : String(error);
265
- }
266
- rows.push(entry);
267
- }
268
- return { connections: rows };
342
+ return { connections: await pingAllConnections() };
269
343
  },
270
344
  timeoutMs: 30000,
271
345
  };
@@ -275,11 +349,16 @@ export function buildSqlTools(config) {
275
349
  parameters: compileParameters({
276
350
  sql: { type: 'string', required: true, description: '只读 SQL 语句(必填,单条)。' },
277
351
  connection: { type: 'string', description: '连接名(可选,缺省第一个连接)。' },
352
+ format: { type: 'string', description: '输出格式:table(默认表格)/ csv / json。csv 与 json 会额外返回 formatted 文本,便于落盘或转存。' },
278
353
  }),
279
354
  output: {
280
355
  schema: querySchema,
281
356
  render: (_args, value) => {
282
357
  const rec = asRecord(value);
358
+ if (typeof rec.formatted === 'string' && rec.formatted !== '') {
359
+ const preview = rec.formatted.length > 4000 ? rec.formatted.slice(0, 4000) + '\n…(预览已截断)' : rec.formatted;
360
+ return [{ type: 'text', text: '查询返回 ' + rec.rowCount + ' 行(' + String(rec.format) + ' 格式):\n' + preview }];
361
+ }
283
362
  const rows = Array.isArray(rec.rows) ? rec.rows : [];
284
363
  const lines = ['查询返回 ' + rec.rowCount + ' 行' + (rec.truncated === true ? '(截断到 ' + rec.maxRows + ' 行)' : '') + ',列:' + (Array.isArray(rec.columns) ? rec.columns.join(', ') : '')];
285
364
  for (const row of rows.slice(0, 20)) {
@@ -297,7 +376,8 @@ export function buildSqlTools(config) {
297
376
  const result = await adapter.query(sql, cfg.maxRows + 1);
298
377
  const total = result.rows.length;
299
378
  const rows = result.rows.slice(0, cfg.maxRows);
300
- return {
379
+ const format = optionalString(args, 'format')?.toLowerCase() ?? 'table';
380
+ const base = {
301
381
  connection: name,
302
382
  columns: result.columns,
303
383
  rows,
@@ -305,6 +385,13 @@ export function buildSqlTools(config) {
305
385
  truncated: total > cfg.maxRows,
306
386
  maxRows: cfg.maxRows,
307
387
  };
388
+ if (format === 'csv')
389
+ return { ...base, format, formatted: toCsv(result.columns, rows) };
390
+ if (format === 'json') {
391
+ const objects = rows.map((row) => Object.fromEntries(result.columns.map((column, i) => [column, row[i]])));
392
+ return { ...base, format, formatted: JSON.stringify(objects, null, 2) };
393
+ }
394
+ return base;
308
395
  },
309
396
  timeoutMs: cfg.queryTimeoutMs,
310
397
  };
@@ -373,5 +460,105 @@ export function buildSqlTools(config) {
373
460
  },
374
461
  timeoutMs: 30000,
375
462
  };
376
- return { tools: [sqlList, sqlQuery, sqlExec, sqlSchema], adapters };
463
+ const sqlStats = {
464
+ name: 'sql_stats',
465
+ description: '数据库概览统计:表数量、每张表的行数、库体积(SQLite 按页计算,MySQL/PostgreSQL 走系统表)。connection 为连接名(缺省第一个连接)。适合在写查询前先了解数据规模。',
466
+ parameters: compileParameters({
467
+ connection: { type: 'string', description: '连接名(可选,缺省第一个连接)。' },
468
+ }),
469
+ output: {
470
+ schema: statsSchema,
471
+ render: (_args, value) => {
472
+ const rec = asRecord(value);
473
+ const tables = Array.isArray(rec.tables) ? rec.tables : [];
474
+ const lines = ['连接 ' + rec.connection + '(' + rec.engine + '):共 ' + tables.length + ' 张表' + (typeof rec.sizeBytes === 'number' && rec.sizeBytes >= 0 ? ',库体积 ' + formatBytes(rec.sizeBytes) : '') + '。'];
475
+ for (const item of tables.slice(0, 30)) {
476
+ const t = asRecord(item);
477
+ lines.push('- ' + t.name + ':' + (typeof t.rowCount === 'number' ? t.rowCount + ' 行' : '行数未知' + (t.error ? '(' + t.error + ')' : '')));
478
+ }
479
+ if (tables.length > 30)
480
+ lines.push('…仅展示前 30 张表');
481
+ return [{ type: 'text', text: lines.join('\n') }];
482
+ },
483
+ },
484
+ async execute(rawArgs) {
485
+ const args = asRecord(rawArgs);
486
+ const { adapter, name } = getAdapter(optionalString(args, 'connection'));
487
+ const engine = adapter.engine;
488
+ let sizeBytes = -1;
489
+ try {
490
+ sizeBytes = await databaseSize(adapter, engine);
491
+ }
492
+ catch {
493
+ sizeBytes = -1;
494
+ }
495
+ const tables = [];
496
+ if (engine === 'mysql' || engine === 'postgres') {
497
+ try {
498
+ const sql = engine === 'mysql'
499
+ ? 'SELECT TABLE_NAME, TABLE_ROWS FROM information_schema.tables WHERE TABLE_SCHEMA = DATABASE()'
500
+ : 'SELECT relname, n_live_tup FROM pg_stat_user_tables ORDER BY relname';
501
+ const result = await adapter.query(sql);
502
+ for (const row of result.rows) {
503
+ tables.push({ name: String(row[0]), rowCount: typeof row[1] === 'number' ? row[1] : Number(row[1] ?? 0) });
504
+ }
505
+ }
506
+ catch (error) {
507
+ tables.push({ name: '', error: error instanceof Error ? error.message : String(error) });
508
+ }
509
+ }
510
+ else {
511
+ const names = await adapter.listTables();
512
+ for (const table of names) {
513
+ try {
514
+ const result = await adapter.query('SELECT COUNT(*) FROM ' + quoteIdent(engine, table), 1);
515
+ tables.push({ name: table, rowCount: Number(result.rows[0]?.[0] ?? 0) });
516
+ }
517
+ catch (error) {
518
+ tables.push({ name: table, error: error instanceof Error ? error.message : String(error) });
519
+ }
520
+ }
521
+ }
522
+ return { connection: name, engine, tableCount: tables.filter((t) => t.name !== '').length, tables, sizeBytes };
523
+ },
524
+ timeoutMs: cfg.queryTimeoutMs,
525
+ };
526
+ const sqlHealth = {
527
+ name: 'sql_health',
528
+ description: 'dsh-sql 自检:逐个连接做连通性测试,并汇总安全配置(只读模式、写审批门、行数上限、超时)。遇到问题时先运行本工具定位。',
529
+ parameters: compileParameters({}),
530
+ output: {
531
+ schema: healthSchema,
532
+ render: (_args, value) => {
533
+ const rec = asRecord(value);
534
+ const connections = Array.isArray(rec.connections) ? rec.connections : [];
535
+ const bad = connections.filter((c) => asRecord(c).ok !== true);
536
+ const lines = ['dsh-sql 自检' + (bad.length === 0 ? ':全部连接正常。' : ':' + bad.length + ' 个连接异常。')];
537
+ for (const item of connections) {
538
+ const c = asRecord(item);
539
+ lines.push('- ' + c.name + '(' + c.engine + ')' + (c.ok === true ? ' ✅' : ' ❌ ' + String(c.error ?? '')));
540
+ }
541
+ lines.push('- 只读模式:' + (rec.readOnly === true ? '开(sql_exec 已禁用)' : '关'));
542
+ lines.push('- 写审批门:' + (rec.writeApproval === true ? '开' : '关'));
543
+ lines.push('- 行数上限:' + String(rec.maxRows) + ';查询超时 ' + String(rec.queryTimeoutMs) + 'ms;写超时 ' + String(rec.execTimeoutMs) + 'ms');
544
+ return [{ type: 'text', text: lines.join('\n') }];
545
+ },
546
+ },
547
+ async execute() {
548
+ const connections = await pingAllConnections();
549
+ const bad = connections.filter((c) => c.ok !== true);
550
+ return {
551
+ ok: bad.length === 0,
552
+ plugin: 'dsh-sql',
553
+ connections,
554
+ readOnly: cfg.readOnly,
555
+ writeApproval: cfg.writeApproval,
556
+ maxRows: cfg.maxRows,
557
+ queryTimeoutMs: cfg.queryTimeoutMs,
558
+ execTimeoutMs: cfg.execTimeoutMs,
559
+ };
560
+ },
561
+ timeoutMs: 30000,
562
+ };
563
+ return { tools: [sqlList, sqlQuery, sqlExec, sqlSchema, sqlStats, sqlHealth], adapters };
377
564
  }
package/package.json CHANGED
@@ -1,68 +1,67 @@
1
- {
2
- "name": "dsh-sql",
3
- "version": "0.3.0",
4
- "description": "DSH 工程师级数据库插件:sql_list/query/exec/schema 四工具,SQLite/MySQL/PostgreSQL 三引擎、多连接、只读模式与写操作审批门、词法级只读保护、流式行数钳制与可配置查询/写超时。",
5
- "type": "module",
6
- "main": "lib/index.js",
7
- "types": "lib/index.d.ts",
8
- "exports": {
9
- ".": {
10
- "types": "./lib/index.d.ts",
11
- "default": "./lib/index.js"
12
- },
13
- "./cordis.patch.yml": "./cordis.patch.yml",
14
- "./package.json": "./package.json"
15
- },
16
- "files": [
17
- "lib",
18
- "cordis.patch.yml",
19
- "README.md",
20
- "README.en.md"
21
- ],
22
- "scripts": {
23
- "build": "tsc -p tsconfig.json",
24
- "prepare": "tsc -p tsconfig.json",
25
- "typecheck": "tsc -p tsconfig.json --noEmit",
26
- "test": "pnpm run build && node --test \"test/*.test.mjs\"",
27
- "prepublishOnly": "pnpm run build"
28
- },
29
- "dsh": {
30
- "bundle": {
31
- "patch": "./cordis.patch.yml"
32
- }
33
- },
34
- "keywords": [
35
- "dsh",
36
- "deepseek-harness",
37
- "plugin",
38
- "sql",
39
- "sqlite",
40
- "mysql",
41
- "postgresql",
42
- "database",
43
- "dsh-plugin"
44
- ],
45
- "license": "MIT",
46
- "engines": {
47
- "node": ">=22.13"
48
- },
49
- "dependencies": {
50
- "mysql2": "^3.11.0",
51
- "pg": "^8.13.0"
52
- },
53
- "devDependencies": {
54
- "@types/node": "^24.0.0",
55
- "@types/pg": "^8.21.0",
56
- "typescript": "^5.6.0"
57
- },
58
- "repository": {
59
- "type": "git",
60
- "url": "git+https://github.com/STARDUSTLC666/dsh-sql.git"
61
- },
62
- "bugs": {
63
- "url": "https://github.com/STARDUSTLC666/dsh-sql/issues"
64
- },
65
- "homepage": "https://github.com/STARDUSTLC666/dsh-sql#readme",
66
- "author": "stardustlc",
67
- "packageManager": "pnpm@11.7.0"
68
- }
1
+ {
2
+ "name": "dsh-sql",
3
+ "version": "0.4.0",
4
+ "description": "DSH 工程师级数据库插件:sql_list/query/exec/schema 四工具,SQLite/MySQL/PostgreSQL 三引擎、多连接、只读模式与写操作审批门、词法级只读保护、流式行数钳制与可配置查询/写超时。",
5
+ "type": "module",
6
+ "main": "lib/index.js",
7
+ "types": "lib/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./lib/index.d.ts",
11
+ "default": "./lib/index.js"
12
+ },
13
+ "./cordis.patch.yml": "./cordis.patch.yml",
14
+ "./package.json": "./package.json"
15
+ },
16
+ "files": [
17
+ "lib",
18
+ "cordis.patch.yml",
19
+ "README.md",
20
+ "README.en.md"
21
+ ],
22
+ "scripts": {
23
+ "build": "tsc -p tsconfig.json",
24
+ "typecheck": "tsc -p tsconfig.json --noEmit",
25
+ "test": "pnpm run build && node --test \"test/*.test.mjs\"",
26
+ "prepublishOnly": "pnpm run build"
27
+ },
28
+ "dsh": {
29
+ "bundle": {
30
+ "patch": "./cordis.patch.yml"
31
+ }
32
+ },
33
+ "keywords": [
34
+ "dsh",
35
+ "deepseek-harness",
36
+ "plugin",
37
+ "sql",
38
+ "sqlite",
39
+ "mysql",
40
+ "postgresql",
41
+ "database",
42
+ "dsh-plugin"
43
+ ],
44
+ "license": "MIT",
45
+ "engines": {
46
+ "node": ">=22.13"
47
+ },
48
+ "dependencies": {
49
+ "mysql2": "^3.11.0",
50
+ "pg": "^8.13.0"
51
+ },
52
+ "devDependencies": {
53
+ "@types/node": "^24.0.0",
54
+ "@types/pg": "^8.21.0",
55
+ "typescript": "^5.6.0"
56
+ },
57
+ "repository": {
58
+ "type": "git",
59
+ "url": "git+https://github.com/STARDUSTLC666/dsh-sql.git"
60
+ },
61
+ "bugs": {
62
+ "url": "https://github.com/STARDUSTLC666/dsh-sql/issues"
63
+ },
64
+ "homepage": "https://github.com/STARDUSTLC666/dsh-sql#readme",
65
+ "author": "stardustlc",
66
+ "packageManager": "pnpm@11.7.0"
67
+ }