@aipanel/dsh-plugin 1.2.0-beta.3

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.
Files changed (2) hide show
  1. package/dist/index.js +115 -0
  2. package/package.json +25 -0
package/dist/index.js ADDED
@@ -0,0 +1,115 @@
1
+ // dsh-plugin/src/index.ts
2
+ import path from "node:path";
3
+ import { randomUUID } from "node:crypto";
4
+ var name = "aipanel";
5
+ var inject = ["tools", "subprocess"];
6
+ var JS_EXTENSIONS = /* @__PURE__ */ new Set([
7
+ ".js",
8
+ ".jsx",
9
+ ".ts",
10
+ ".tsx",
11
+ ".mjs",
12
+ ".cjs",
13
+ ".mts",
14
+ ".cts",
15
+ ".vue"
16
+ ]);
17
+ var MUTATING_TOOLS = /* @__PURE__ */ new Set(["write", "edit", "apply_patch"]);
18
+ var STDOUT_MAX_BYTES = 2e5;
19
+ var STDOUT_SPILL_MAX_BYTES = 2e6;
20
+ var STDERR_MAX_BYTES = 1e5;
21
+ var GRACE_MS = 3e4;
22
+ function apply(ctx, config = {}) {
23
+ const cwd = config.cwd ?? process.cwd();
24
+ const autoDiagnose = config.autoDiagnose ?? true;
25
+ const tools = ctx.tools;
26
+ const subprocess = ctx.subprocess;
27
+ async function collectOutput(argv, signal) {
28
+ try {
29
+ const exe = await subprocess.resolveExecutable("npx", void 0, signal);
30
+ const proc = subprocess.spawn({
31
+ argv: [exe, ...argv],
32
+ cwd,
33
+ stdio: {
34
+ stdin: "ignore",
35
+ stdout: { maxBytes: STDOUT_MAX_BYTES, spill: { maxBytes: STDOUT_SPILL_MAX_BYTES } },
36
+ stderr: { maxBytes: STDERR_MAX_BYTES }
37
+ },
38
+ graceMs: GRACE_MS,
39
+ signal
40
+ });
41
+ await proc.done;
42
+ return { text: proc.collected.stdout?.readFrom(0)?.text ?? "" };
43
+ } catch (e) {
44
+ return { text: "", error: String(e) };
45
+ }
46
+ }
47
+ async function runDiagnostics(filePath, signal) {
48
+ const parts = [];
49
+ const tsc = await collectOutput(["tsc", "--noEmit", "--pretty", "false"], signal);
50
+ if (tsc.error) parts.push("## tsc\n\n(diagnostics skipped: " + tsc.error + ")");
51
+ else if (tsc.text.trim()) parts.push("## tsc\n\n" + tsc.text.trim());
52
+ const eslint = await collectOutput(["eslint", filePath, "--format", "compact"], signal);
53
+ if (eslint.text.trim()) parts.push("## eslint\n\n" + eslint.text.trim());
54
+ return parts.join("\n\n");
55
+ }
56
+ const diagnosticsTool = {
57
+ name: "run_diagnostics",
58
+ description: "Run ESLint and TypeScript type checks on filePath and report problems. Use after editing code to verify no lint/type errors before proceeding.",
59
+ parameters: {
60
+ type: "object",
61
+ additionalProperties: false,
62
+ properties: {
63
+ filePath: {
64
+ type: "string",
65
+ description: "Absolute or cwd-relative file path to diagnose"
66
+ }
67
+ },
68
+ required: ["filePath"]
69
+ },
70
+ output: {
71
+ schema: { type: "string" },
72
+ render: (_args, value) => [{ type: "text", text: value }]
73
+ },
74
+ async execute(args, exec) {
75
+ const filePath = args?.filePath;
76
+ const target = typeof filePath === "string" ? path.resolve(cwd, filePath) : cwd;
77
+ return runDiagnostics(target, exec.signal).catch((e) => "diagnostics failed: " + String(e));
78
+ }
79
+ };
80
+ tools.register(diagnosticsTool);
81
+ ctx.on(
82
+ "tools/post-execute",
83
+ async (exec, result, next) => {
84
+ const decision = await next();
85
+ if (!autoDiagnose) return decision;
86
+ if (!MUTATING_TOOLS.has(exec.name)) return decision;
87
+ if (result.isError) return decision;
88
+ if (decision.kind !== "accept") return decision;
89
+ const filePath = exec.arguments?.filePath;
90
+ if (typeof filePath !== "string" || !filePath) return decision;
91
+ if (!JS_EXTENSIONS.has(path.extname(filePath))) return decision;
92
+ const diag = await runDiagnostics(path.resolve(cwd, filePath), exec.signal).catch(
93
+ () => "diagnostics unavailable"
94
+ );
95
+ const message = {
96
+ role: "user",
97
+ id: randomUUID(),
98
+ content: [
99
+ {
100
+ type: "text",
101
+ text: `Auto diagnostics after ${exec.name} (${filePath}):
102
+ ${diag}`
103
+ }
104
+ ],
105
+ source: { kind: "plugin", plugin: name }
106
+ };
107
+ return { kind: "accept", additionalContexts: [message] };
108
+ }
109
+ );
110
+ }
111
+ export {
112
+ apply,
113
+ inject,
114
+ name
115
+ };
package/package.json ADDED
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "@aipanel/dsh-plugin",
3
+ "version": "1.2.0-beta.3",
4
+ "type": "module",
5
+ "description": "AIPanel for DeepSeek Harness (dsh):注入审查工具 run_diagnostics、编辑后自动诊断。",
6
+ "main": "./dist/index.js",
7
+ "files": [
8
+ "dist"
9
+ ],
10
+ "publishConfig": {
11
+ "access": "public",
12
+ "registry": "https://registry.npmjs.org/"
13
+ },
14
+ "devDependencies": {
15
+ "@deepseek-ai/cordis": "^4.0.1",
16
+ "@deepseek-ai/dsh-llm": "^0.1.1-rc.2",
17
+ "@deepseek-ai/dsh-subprocess": "^0.1.1-rc.2",
18
+ "@deepseek-ai/dsh-tools": "^0.1.1-rc.2",
19
+ "esbuild": "^0.25.0"
20
+ },
21
+ "scripts": {
22
+ "build": "esbuild src/index.ts --bundle --outfile=dist/index.js --platform=node --format=esm --target=node18 --external:@deepseek-ai/* --external:node:*",
23
+ "typecheck": "tsc -p tsconfig.json"
24
+ }
25
+ }