@zhin.js/plugin-code-runner 1.1.4 → 1.1.6

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.md CHANGED
@@ -5,24 +5,30 @@ Zhin.js plugin for code-runner functionality.
5
5
  ## Installation
6
6
 
7
7
  ```bash
8
- pnpm add @zhin.js/plugin-code-runner
8
+ pnpm exec zhin install @zhin.js/plugin-code-runner
9
9
  ```
10
10
 
11
11
  ## Usage
12
12
 
13
- Add the plugin to your `zhin.config.yml`:
13
+ Run the installation command from your application directory. It installs the package and mounts the `code-runner` instance in `package.json#zhin.plugins`. The corresponding `zhin.config.yml` node is:
14
14
 
15
15
  ```yaml
16
16
  plugins:
17
- - @zhin.js/plugin-code-runner
17
+ code-runner: {}
18
18
  ```
19
19
 
20
- Or via CLI:
20
+ ## Configuration
21
21
 
22
- ```bash
23
- zhin install @zhin.js/plugin-code-runner
24
- ```
22
+ This plugin currently has no configuration fields. Its [`schema.json`](./schema.json) accepts an empty object; do not place package names in a `plugins` array.
25
23
 
26
- ## Configuration
24
+ ## Commands
25
+
26
+ - `run javascript console.log("hello")`: execute with the default 30-second timeout.
27
+ - `run python --timeout 5 print(1)` / `run python -t 5 print(1)`: choose 1–30 seconds.
28
+ - `run --help`: show supported languages, code constraints and timeout defaults.
27
29
 
28
- Configure in `zhin.config.yml` under the plugin's key. Refer to the plugin source for available options.
30
+ The Endpoint determines any command prefix, and an explicit `commandNamespace` adds a plugin
31
+ namespace. `commands/run/[language]/index.ts` binds the language, while code and timeout are
32
+ centrally declared in the same definition. Code keeps quotes and newlines; its limit is
33
+ 10,000 characters. Use `--` before code containing option-like words. Unsupported languages,
34
+ missing code and invalid timeout values are rejected before the remote request.
@@ -1,16 +1,17 @@
1
1
  // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
2
  import { defineCommand } from 'zhin.js/command';
3
- import { formatResult, runCode } from "../../../lib/run-code.js";
3
+ import { formatResult, MAX_CODE_LENGTH, runCode, supportedLanguages } from "../../../lib/run-code.js";
4
4
  export default defineCommand({
5
- description: '在沙箱中运行代码片段(/code-runner run <语言> <代码>)',
6
- params: { language: { type: 'string' } },
7
- async execute({ params, args }) {
8
- const language = String(params.language ?? '');
9
- // code 原来是第二动态段,约定式命令只支持单动态文件参数,改从 args 取
10
- const code = args.join(' ').trim();
11
- if (!code)
12
- return '请提供要运行的代码,例如:/code-runner run javascript alert(1+1)';
13
- const result = await runCode(language, code);
14
- return formatResult(result);
5
+ description: '在远程沙箱中运行代码片段',
6
+ params: {
7
+ language: {
8
+ type: 'string', description: `执行语言:${supportedLanguages.join(', ')}(不区分大小写)`,
9
+ validate: (value) => typeof value === 'string' && supportedLanguages.includes(value.toLowerCase().trim()),
10
+ },
11
+ code: { type: 'text', min: 1, max: MAX_CODE_LENGTH, description: '要运行的代码' },
12
+ },
13
+ options: { timeout: { type: 'integer', alias: 't', default: 30, min: 1, max: 30, description: '请求超时(秒)' } },
14
+ async execute({ params, options }) {
15
+ return formatResult(await runCode(params.language, params.code, options.timeout));
15
16
  },
16
17
  });
@@ -1,15 +1,17 @@
1
- import { defineCommand } from 'zhin.js/command';
2
- import { formatResult, runCode } from '../../../src/run-code.js';
1
+ import { defineCommand, type CommandParameterValue } from 'zhin.js/command';
2
+ import { formatResult, MAX_CODE_LENGTH, runCode, supportedLanguages } from '../../../src/run-code.js';
3
3
 
4
4
  export default defineCommand({
5
- description: '在沙箱中运行代码片段(/code-runner run <语言> <代码>)',
6
- params: { language: { type: 'string' } },
7
- async execute({ params, args }) {
8
- const language = String(params.language ?? '');
9
- // code 原来是第二动态段,约定式命令只支持单动态文件参数,改从 args 取
10
- const code = args.join(' ').trim();
11
- if (!code) return '请提供要运行的代码,例如:/code-runner run javascript alert(1+1)';
12
- const result = await runCode(language, code);
13
- return formatResult(result);
5
+ description: '在远程沙箱中运行代码片段',
6
+ params: {
7
+ language: {
8
+ type: 'string', description: `执行语言:${supportedLanguages.join(', ')}(不区分大小写)`,
9
+ validate: (value: CommandParameterValue) => typeof value === 'string' && supportedLanguages.includes(value.toLowerCase().trim()),
10
+ },
11
+ code: { type: 'text', min: 1, max: MAX_CODE_LENGTH, description: '要运行的代码' },
12
+ },
13
+ options: { timeout: { type: 'integer', alias: 't', default: 30, min: 1, max: 30, description: '请求超时(秒)' } },
14
+ async execute({ params, options }) {
15
+ return formatResult(await runCode(params.language, params.code, options.timeout));
14
16
  },
15
17
  });
package/lib/run-code.d.ts CHANGED
@@ -1,9 +1,11 @@
1
+ export declare const MAX_CODE_LENGTH = 10000;
2
+ export declare const supportedLanguages: readonly string[];
1
3
  interface RunResult {
2
4
  stdout: string;
3
5
  stderr: string;
4
6
  error: string;
5
7
  }
6
- export declare function runCode(language: string, code: string): Promise<RunResult>;
8
+ export declare function runCode(language: string, code: string, timeoutSeconds?: number): Promise<RunResult>;
7
9
  export declare function formatResult(result: RunResult): string;
8
10
  export {};
9
11
  //# sourceMappingURL=run-code.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"run-code.d.ts","sourceRoot":"","sources":["../src/run-code.ts"],"names":[],"mappings":"AAiBA,UAAU,SAAS;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED,wBAAsB,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAmDhF;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAMtD"}
1
+ {"version":3,"file":"run-code.d.ts","sourceRoot":"","sources":["../src/run-code.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,eAAe,QAAQ,CAAC;AAerC,eAAO,MAAM,kBAAkB,mBAAkD,CAAC;AAIlF,UAAU,SAAS;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED,wBAAsB,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,cAAc,SAAK,GAAG,OAAO,CAAC,SAAS,CAAC,CAmDrG;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAMtD"}
package/lib/run-code.js CHANGED
@@ -1,4 +1,4 @@
1
- const MAX_CODE_LENGTH = 10000;
1
+ export const MAX_CODE_LENGTH = 10000;
2
2
  const SUPPORTED_LANGUAGES = {
3
3
  python: 'main.py',
4
4
  javascript: 'main.js',
@@ -11,8 +11,9 @@ const SUPPORTED_LANGUAGES = {
11
11
  ruby: 'main.rb',
12
12
  php: 'main.php',
13
13
  };
14
+ export const supportedLanguages = Object.freeze(Object.keys(SUPPORTED_LANGUAGES));
14
15
  const GLOT_API_BASE = 'https://glot.io/api/run';
15
- export async function runCode(language, code) {
16
+ export async function runCode(language, code, timeoutSeconds = 30) {
16
17
  const lang = language.toLowerCase().trim();
17
18
  if (!SUPPORTED_LANGUAGES[lang]) {
18
19
  return {
@@ -37,7 +38,7 @@ export async function runCode(language, code) {
37
38
  body: JSON.stringify({
38
39
  files: [{ name: fileName, content: code }],
39
40
  }),
40
- signal: AbortSignal.timeout(30_000),
41
+ signal: AbortSignal.timeout(timeoutSeconds * 1000),
41
42
  });
42
43
  if (!response.ok) {
43
44
  return {
@@ -55,7 +56,7 @@ export async function runCode(language, code) {
55
56
  }
56
57
  catch (e) {
57
58
  const err = e;
58
- const msg = err.name === 'TimeoutError' ? '请求超时(30s)' : err.message || '未知错误';
59
+ const msg = err.name === 'TimeoutError' ? `请求超时(${timeoutSeconds}s)` : err.message || '未知错误';
59
60
  return { stdout: '', stderr: '', error: msg };
60
61
  }
61
62
  }
@@ -1 +1 @@
1
- {"version":3,"file":"run-code.js","sourceRoot":"","sources":["../src/run-code.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"run-code.js","sourceRoot":"","sources":["../src/run-code.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhin.js/plugin-code-runner",
3
- "version": "1.1.4",
3
+ "version": "1.1.6",
4
4
  "description": "Sandboxed code execution plugin for Zhin.js (Plugin Runtime)",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",
@@ -8,7 +8,6 @@
8
8
  "exports": {
9
9
  ".": {
10
10
  "types": "./lib/index.d.ts",
11
- "development": "./src/index.ts",
12
11
  "import": "./lib/index.js"
13
12
  },
14
13
  "./package.json": "./package.json"
@@ -42,12 +41,12 @@
42
41
  "typescript": "^6.0.3",
43
42
  "vitest": "^4.1.10",
44
43
  "zod": "^4.4.3",
45
- "zhin.js": "1.1.6"
44
+ "zhin.js": "1.1.9"
46
45
  },
47
46
  "peerDependencies": {
48
47
  "zod": "^4.0.0",
49
- "zhin.js": "^1.1.6",
50
- "@zhin.js/command": "^1.1.5"
48
+ "@zhin.js/command": "^1.1.7",
49
+ "zhin.js": "^1.1.9"
51
50
  },
52
51
  "peerDependenciesMeta": {
53
52
  "@zhin.js/command": {
@@ -67,7 +66,7 @@
67
66
  "registry": "https://registry.npmjs.org"
68
67
  },
69
68
  "engines": {
70
- "node": "^20.19.0 || >=22.12.0"
69
+ "node": ">=22.19.0"
71
70
  },
72
71
  "zhin": {
73
72
  "protocol": 1,
@@ -92,8 +91,8 @@
92
91
  "plugins": []
93
92
  },
94
93
  "dependencies": {
95
- "@zhin.js/tool": "1.1.4",
96
- "@zhin.js/skill": "1.1.4"
94
+ "@zhin.js/tool": "1.1.6",
95
+ "@zhin.js/skill": "1.1.6"
97
96
  },
98
97
  "scripts": {
99
98
  "build": "tsc",
package/src/run-code.ts CHANGED
@@ -1,4 +1,4 @@
1
- const MAX_CODE_LENGTH = 10000;
1
+ export const MAX_CODE_LENGTH = 10000;
2
2
 
3
3
  const SUPPORTED_LANGUAGES: Record<string, string> = {
4
4
  python: 'main.py',
@@ -13,6 +13,8 @@ const SUPPORTED_LANGUAGES: Record<string, string> = {
13
13
  php: 'main.php',
14
14
  };
15
15
 
16
+ export const supportedLanguages = Object.freeze(Object.keys(SUPPORTED_LANGUAGES));
17
+
16
18
  const GLOT_API_BASE = 'https://glot.io/api/run';
17
19
 
18
20
  interface RunResult {
@@ -21,7 +23,7 @@ interface RunResult {
21
23
  error: string;
22
24
  }
23
25
 
24
- export async function runCode(language: string, code: string): Promise<RunResult> {
26
+ export async function runCode(language: string, code: string, timeoutSeconds = 30): Promise<RunResult> {
25
27
  const lang = language.toLowerCase().trim();
26
28
 
27
29
  if (!SUPPORTED_LANGUAGES[lang]) {
@@ -50,7 +52,7 @@ export async function runCode(language: string, code: string): Promise<RunResult
50
52
  body: JSON.stringify({
51
53
  files: [{ name: fileName, content: code }],
52
54
  }),
53
- signal: AbortSignal.timeout(30_000),
55
+ signal: AbortSignal.timeout(timeoutSeconds * 1000),
54
56
  });
55
57
 
56
58
  if (!response.ok) {
@@ -69,7 +71,7 @@ export async function runCode(language: string, code: string): Promise<RunResult
69
71
  };
70
72
  } catch (e: unknown) {
71
73
  const err = e as Error;
72
- const msg = err.name === 'TimeoutError' ? '请求超时(30s)' : err.message || '未知错误';
74
+ const msg = err.name === 'TimeoutError' ? `请求超时(${timeoutSeconds}s)` : err.message || '未知错误';
73
75
  return { stdout: '', stderr: '', error: msg };
74
76
  }
75
77
  }