@theokit/sdk 2.8.0 → 2.9.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/dist/eval.js CHANGED
@@ -1,12 +1,12 @@
1
1
  import { randomUUID, randomBytes, createHash } from 'crypto';
2
- import { readFile, unlink, mkdir, open, rename, statfs, stat, rm, readdir, appendFile, access } from 'fs/promises';
2
+ import { mkdir, writeFile, readFile, unlink, open, rename, statfs, stat, rm, readdir, appendFile, access } from 'fs/promises';
3
3
  import { join, dirname, resolve, sep, relative, isAbsolute } from 'path';
4
4
  import { z, toJSONSchema } from 'zod';
5
5
  import { readFileSync, mkdirSync, appendFileSync, readdirSync, existsSync, realpathSync, lstatSync, readlinkSync } from 'fs';
6
6
  import { AsyncLocalStorage } from 'async_hooks';
7
7
  import { createRequire } from 'module';
8
8
  import { homedir } from 'os';
9
- import { spawn } from 'child_process';
9
+ import { execFile, spawn } from 'child_process';
10
10
  import { fileURLToPath } from 'url';
11
11
 
12
12
  var __defProp = Object.defineProperty;
@@ -16190,6 +16190,118 @@ async function llmJudgeScore(options) {
16190
16190
  return parseScore(judgement.text, rubric);
16191
16191
  }
16192
16192
 
16193
+ // src/sandbox/types.ts
16194
+ var SandboxSecurityError = class extends Error {
16195
+ code = "sandbox_security";
16196
+ constructor(message) {
16197
+ super(message);
16198
+ this.name = "SandboxSecurityError";
16199
+ }
16200
+ };
16201
+ var SHELL_METACHARACTERS = /[;&|`$(){}]/;
16202
+ var SandboxBackend = class {
16203
+ config;
16204
+ constructor(config = {}) {
16205
+ this.config = {
16206
+ workDir: config.workDir ?? "/tmp",
16207
+ timeoutMs: config.timeoutMs ?? 3e4,
16208
+ maxOutputBytes: config.maxOutputBytes ?? 5 * 1024 * 1024
16209
+ };
16210
+ }
16211
+ async readFile(path) {
16212
+ const result = await this.execute(`cat ${this.shellEscape(path)}`);
16213
+ if (result.exitCode !== 0) {
16214
+ throw new Error(`readFile failed: ${result.stderr}`);
16215
+ }
16216
+ return result.stdout;
16217
+ }
16218
+ async writeFile(path, content) {
16219
+ await this.uploadFile(path, content);
16220
+ }
16221
+ async glob(pattern, cwd) {
16222
+ const dir = cwd ?? this.config.workDir ?? ".";
16223
+ const result = await this.execute(
16224
+ `find ${this.shellEscape(dir)} -name ${this.shellEscape(pattern)} -type f 2>/dev/null`
16225
+ );
16226
+ if (result.exitCode !== 0) return [];
16227
+ return result.stdout.trim().split("\n").filter(Boolean);
16228
+ }
16229
+ async grep(pattern, path) {
16230
+ const target = path ?? ".";
16231
+ const result = await this.execute(
16232
+ `grep -rn ${this.shellEscape(pattern)} ${this.shellEscape(target)} 2>/dev/null`
16233
+ );
16234
+ if (result.exitCode !== 0) return [];
16235
+ return result.stdout.trim().split("\n").filter(Boolean);
16236
+ }
16237
+ async listDir(path) {
16238
+ const result = await this.execute(`ls -1 ${this.shellEscape(path)}`);
16239
+ if (result.exitCode !== 0) return [];
16240
+ return result.stdout.trim().split("\n").filter(Boolean);
16241
+ }
16242
+ validateCommand(command) {
16243
+ if (SHELL_METACHARACTERS.test(command)) {
16244
+ throw new SandboxSecurityError(
16245
+ `Command contains shell metacharacters: ${command.slice(0, 80)}`
16246
+ );
16247
+ }
16248
+ }
16249
+ truncateOutput(output) {
16250
+ const max = this.config.maxOutputBytes ?? 5 * 1024 * 1024;
16251
+ if (Buffer.byteLength(output) > max) {
16252
+ return `${output.slice(0, max)}
16253
+ ...(truncated)`;
16254
+ }
16255
+ return output;
16256
+ }
16257
+ shellEscape(arg) {
16258
+ return shellEscapePosix(arg);
16259
+ }
16260
+ };
16261
+
16262
+ // src/sandbox/local-sandbox.ts
16263
+ var LocalSandbox = class extends SandboxBackend {
16264
+ constructor(config = {}) {
16265
+ super(config);
16266
+ }
16267
+ async execute(command, opts) {
16268
+ const timeout = opts?.timeoutMs ?? this.config.timeoutMs ?? 3e4;
16269
+ const max = this.config.maxOutputBytes ?? 5 * 1024 * 1024;
16270
+ return new Promise((resolve3) => {
16271
+ const child = execFile(
16272
+ "/bin/sh",
16273
+ ["-c", command],
16274
+ {
16275
+ cwd: this.config.workDir,
16276
+ timeout,
16277
+ maxBuffer: max,
16278
+ encoding: "utf-8"
16279
+ },
16280
+ (error, stdout, stderr) => {
16281
+ resolve3(this.buildResult(error, stdout ?? "", stderr ?? ""));
16282
+ }
16283
+ );
16284
+ child.on("error", () => {
16285
+ resolve3({ stdout: "", stderr: "spawn error", exitCode: 1, timedOut: false });
16286
+ });
16287
+ });
16288
+ }
16289
+ buildResult(error, stdout, stderr) {
16290
+ const timedOut = error !== null && "killed" in error && error.killed;
16291
+ return {
16292
+ stdout: this.truncateOutput(stdout),
16293
+ stderr: this.truncateOutput(stderr),
16294
+ exitCode: timedOut ? 124 : error ? 1 : 0,
16295
+ timedOut
16296
+ };
16297
+ }
16298
+ async uploadFile(path, content) {
16299
+ const fullPath = path.startsWith("/") ? path : `${this.config.workDir}/${path}`;
16300
+ await mkdir(dirname(fullPath), { recursive: true });
16301
+ await writeFile(fullPath, content, "utf-8");
16302
+ }
16303
+ };
16304
+
16193
16305
  // src/scorers.ts
16194
16306
  var JSON_SHAPE_MAX_BYTES = 1e6;
16195
16307
  function makeStringScorer(name, caseSensitive, compare) {
@@ -16293,7 +16405,7 @@ var Scorers = {
16293
16405
  * that rejects shell metacharacters in `execute` is unsupported for this scorer.
16294
16406
  */
16295
16407
  verifyGate(opts) {
16296
- const { sandbox, repoDir, failToPass, passToPass, command } = opts;
16408
+ const { sandbox = new LocalSandbox(), repoDir, failToPass, passToPass, command } = opts;
16297
16409
  return {
16298
16410
  name: "verify-gate",
16299
16411
  score: async () => {