dsh-sql 0.4.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +2 -2
- package/README.md +2 -2
- package/lib/index.d.ts +19 -14
- package/lib/index.js +19 -41
- package/lib/tools.d.ts +0 -1
- package/lib/tools.js +0 -3
- package/package.json +1 -1
package/README.en.md
CHANGED
|
@@ -12,7 +12,7 @@ DSH (DeepSeek Harness) engineer-grade database plugin: four tools covering conne
|
|
|
12
12
|
|
|
13
13
|
## Compatibility
|
|
14
14
|
|
|
15
|
-
Verified against `@deepseek-ai/dsh@0.1.
|
|
15
|
+
Verified against source-run `@deepseek-ai/dsh@0.1.2-alpha.4` on 2026-09-02. Built for the cordis patch-bundle plugin model (`cordis.patch.yml` + `dsh.bundle.patch`). No runtime imports of `@deepseek-ai/*` internals.
|
|
16
16
|
|
|
17
17
|
## Installation
|
|
18
18
|
|
|
@@ -100,4 +100,4 @@ pnpm test # build + 35 tests, including a real SQLite integration suite
|
|
|
100
100
|
|
|
101
101
|
## License
|
|
102
102
|
|
|
103
|
-
MIT
|
|
103
|
+
MIT
|
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@ DSH(DeepSeek Harness)工程师级数据库插件:四个工具覆盖连接
|
|
|
12
12
|
|
|
13
13
|
## 兼容性
|
|
14
14
|
|
|
15
|
-
在 `@deepseek-ai/dsh@0.1.
|
|
15
|
+
在 `@deepseek-ai/dsh@0.1.2-alpha.4` 源码模式下验证(2026-09-02)。遵循 cordis 组合包补丁模型(`cordis.patch.yml` + `dsh.bundle.patch`),运行时不 import 任何 `@deepseek-ai/*` 内部模块。
|
|
16
16
|
|
|
17
17
|
## 安装
|
|
18
18
|
|
|
@@ -100,4 +100,4 @@ pnpm test # 构建 + 35 个测试(含真实 SQLite 集成)
|
|
|
100
100
|
|
|
101
101
|
## License
|
|
102
102
|
|
|
103
|
-
MIT
|
|
103
|
+
MIT
|
package/lib/index.d.ts
CHANGED
|
@@ -12,25 +12,30 @@ import { type SqlToolDefinition } from './tools.js';
|
|
|
12
12
|
/** cordis 服务注入:apply 里要用 ctx.tools,必须显式声明。 */
|
|
13
13
|
export declare const name = "sql";
|
|
14
14
|
export declare const inject: string[];
|
|
15
|
-
/**
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
15
|
+
/** Harness `tools/pre-execute` 的决策结果。 */
|
|
16
|
+
type SqlPreToolDecision = {
|
|
17
|
+
kind: 'allow';
|
|
18
|
+
} | {
|
|
19
|
+
kind: 'deny';
|
|
20
|
+
reason: string;
|
|
21
|
+
} | {
|
|
22
|
+
kind: 'ask';
|
|
23
|
+
reason?: string;
|
|
24
|
+
};
|
|
25
|
+
/** 审批策略需要读取的 alpha.4 工具执行字段。 */
|
|
26
|
+
interface SqlToolExecution {
|
|
27
|
+
readonly name: string;
|
|
28
|
+
readonly arguments: unknown;
|
|
24
29
|
}
|
|
30
|
+
/** Harness `tools/pre-execute` waterfall 监听器。 */
|
|
31
|
+
type SqlPreExecuteListener = (exec: SqlToolExecution, next: () => Promise<SqlPreToolDecision>) => Promise<SqlPreToolDecision>;
|
|
25
32
|
/** 插件所需的最小 ctx 面。 */
|
|
26
33
|
export interface SqlPluginContext {
|
|
27
34
|
tools: {
|
|
28
|
-
register(definition: SqlToolDefinition
|
|
29
|
-
prepend?: boolean;
|
|
30
|
-
}): () => void;
|
|
35
|
+
register(definition: SqlToolDefinition): () => void;
|
|
31
36
|
};
|
|
32
|
-
|
|
33
|
-
on
|
|
37
|
+
on(event: 'tools/pre-execute', listener: SqlPreExecuteListener): () => void;
|
|
38
|
+
on(event: 'dispose', listener: () => void): () => void;
|
|
34
39
|
}
|
|
35
40
|
/**
|
|
36
41
|
* 插件入口:解析配置、构建四工具、给 sql_exec 注入审批门。
|
package/lib/index.js
CHANGED
|
@@ -25,50 +25,28 @@ export function apply(ctx, config) {
|
|
|
25
25
|
cfg = resolveConfig(null);
|
|
26
26
|
}
|
|
27
27
|
const { tools, adapters } = buildSqlTools(cfg);
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
reason: 'sql_exec 需要确认,但当前环境没有审批通道(如 headless)。如确定安全,可在配置中设置 writeApproval: false 后直接执行。',
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
const execRecord = (typeof exec === 'object' && exec !== null ? exec : {});
|
|
41
|
-
const args = (typeof execRecord.args === 'object' && execRecord.args !== null ? execRecord.args : {});
|
|
42
|
-
const sql = typeof args.sql === 'string' ? args.sql : '';
|
|
43
|
-
const outcome = await approval.request({
|
|
44
|
-
agent: execRecord.agent,
|
|
45
|
-
toolName: execRecord.name,
|
|
46
|
-
callId: execRecord.callId,
|
|
47
|
-
reason: '执行数据库写操作:' + sql.slice(0, 200) + (sql.length > 200 ? '…' : ''),
|
|
48
|
-
signal: execRecord.signal,
|
|
49
|
-
});
|
|
50
|
-
if (outcome === 'allowed-once')
|
|
51
|
-
return originalGate ? originalGate(exec, next) : next();
|
|
52
|
-
if (outcome === 'cancelled')
|
|
53
|
-
return { kind: 'deny', reason: '写操作确认被取消,SQL 未执行。' };
|
|
54
|
-
if (outcome === 'unavailable')
|
|
55
|
-
return { kind: 'deny', reason: '写操作确认不可用(没有可用的审批界面),SQL 未执行。' };
|
|
56
|
-
return {
|
|
57
|
-
kind: 'deny',
|
|
58
|
-
reason: '写操作未获批准:要么你拒绝了,要么当前会话处于 Full Access(审批策略 never,不会弹框)。若在 Full Access:切到 Read Only / Write 再执行,或关闭 writeApproval(自行承担风险)。',
|
|
59
|
-
};
|
|
28
|
+
if (cfg.writeApproval) {
|
|
29
|
+
ctx.on('tools/pre-execute', async (exec, next) => {
|
|
30
|
+
if (exec.name !== 'sql_exec')
|
|
31
|
+
return next();
|
|
32
|
+
const args = (typeof exec.arguments === 'object' && exec.arguments !== null ? exec.arguments : {});
|
|
33
|
+
const sql = typeof args.sql === 'string' ? args.sql : '';
|
|
34
|
+
return {
|
|
35
|
+
kind: 'ask',
|
|
36
|
+
reason: 'sql_exec 写操作需要确认:' + sql.slice(0, 200) + (sql.length > 200 ? '…' : ''),
|
|
60
37
|
};
|
|
61
|
-
}
|
|
62
|
-
disposers.push(ctx.tools.register(definition, { prepend: true }));
|
|
63
|
-
}
|
|
64
|
-
if (typeof ctx.on === 'function') {
|
|
65
|
-
ctx.on('dispose', () => {
|
|
66
|
-
for (const dispose of disposers)
|
|
67
|
-
dispose();
|
|
68
|
-
for (const adapter of adapters.values())
|
|
69
|
-
void adapter.close();
|
|
70
38
|
});
|
|
71
39
|
}
|
|
40
|
+
const disposers = [];
|
|
41
|
+
for (const definition of tools) {
|
|
42
|
+
disposers.push(ctx.tools.register(definition));
|
|
43
|
+
}
|
|
44
|
+
ctx.on('dispose', () => {
|
|
45
|
+
for (const dispose of disposers)
|
|
46
|
+
dispose();
|
|
47
|
+
for (const adapter of adapters.values())
|
|
48
|
+
void adapter.close();
|
|
49
|
+
});
|
|
72
50
|
}
|
|
73
51
|
export * from './adapters.js';
|
|
74
52
|
export * from './config.js';
|
package/lib/tools.d.ts
CHANGED
|
@@ -24,7 +24,6 @@ export interface SqlToolDefinition {
|
|
|
24
24
|
render(args: unknown, value: unknown): ContentBlock[];
|
|
25
25
|
};
|
|
26
26
|
execute(args: unknown, exec: unknown): Promise<unknown>;
|
|
27
|
-
gate?(exec: unknown, next: () => Promise<unknown>): Promise<unknown>;
|
|
28
27
|
timeoutMs?: number;
|
|
29
28
|
}
|
|
30
29
|
/** 校验只读查询:词法去噪后白名单开头 + 写关键字扫描 + 单语句。 */
|
package/lib/tools.js
CHANGED
|
@@ -418,9 +418,6 @@ export function buildSqlTools(config) {
|
|
|
418
418
|
const changes = await adapter.exec(sql);
|
|
419
419
|
return { connection: name, changes, readOnly: false };
|
|
420
420
|
},
|
|
421
|
-
gate(exec, next) {
|
|
422
|
-
return next(); // 审批门由 index.ts 注入(需要宿主 ctx)
|
|
423
|
-
},
|
|
424
421
|
timeoutMs: cfg.execTimeoutMs,
|
|
425
422
|
};
|
|
426
423
|
const sqlSchema = {
|
package/package.json
CHANGED