@theokit/sdk 2.8.0 → 2.10.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;
@@ -3288,6 +3288,18 @@ async function writeVersionedJson(path, data2, currentVersion) {
3288
3288
  await atomicWriteJson(path, file);
3289
3289
  }
3290
3290
 
3291
+ // src/internal/plugins/enabled-names.ts
3292
+ function isPluginArray(plugins) {
3293
+ return Array.isArray(plugins);
3294
+ }
3295
+ function asPluginsSettings(plugins) {
3296
+ if (plugins === void 0) return void 0;
3297
+ return isPluginArray(plugins) ? void 0 : plugins;
3298
+ }
3299
+ function enabledPluginNames(plugins) {
3300
+ return asPluginsSettings(plugins)?.enabled ?? [];
3301
+ }
3302
+
3291
3303
  // src/internal/runtime/registry/agent-registry-store.ts
3292
3304
  var SCHEMA_VERSION = 1;
3293
3305
  var LEGACY_SCHEMA_VERSION_STRING = "1.0";
@@ -3301,7 +3313,9 @@ function stripSecretsFromOptions(options) {
3301
3313
  cloud: serializeCloud(options.cloud),
3302
3314
  memory: serializeMemory(options.memory),
3303
3315
  skills: serializeEnabledList(options.skills),
3304
- plugins: serializeEnabledList(options.plugins),
3316
+ // Code-`Plugin` objects are closures and cannot be persisted (like custom
3317
+ // tools); only the named-enable settings form is serialized.
3318
+ plugins: serializeEnabledList(asPluginsSettings(options.plugins)),
3305
3319
  context: serializeContext(options.context),
3306
3320
  providers: serializeProviders(options.providers),
3307
3321
  agents: serializeAgents(options.agents)
@@ -3609,8 +3623,9 @@ function serializeSkills(skills) {
3609
3623
  return { enabled: [...skills.enabled] };
3610
3624
  }
3611
3625
  function serializePlugins(plugins) {
3612
- if (plugins?.enabled === void 0 || plugins.enabled.length === 0) return void 0;
3613
- return { enabled: [...plugins.enabled] };
3626
+ const enabled = enabledPluginNames(plugins);
3627
+ if (enabled.length === 0) return void 0;
3628
+ return { enabled: [...enabled] };
3614
3629
  }
3615
3630
  function serializeMcp(mcpServers) {
3616
3631
  if (mcpServers === void 0) return void 0;
@@ -3793,11 +3808,8 @@ function defaultLocalTools(request) {
3793
3808
  tools.push(`mcp_${sanitizeMcpName(name)}_call`);
3794
3809
  }
3795
3810
  }
3796
- const plugins = request.agentOptions.plugins;
3797
- if (plugins?.enabled !== void 0) {
3798
- for (const _pluginName of plugins.enabled) {
3799
- tools.push("mcp_search_provider_web_search");
3800
- }
3811
+ for (const _pluginName of enabledPluginNames(request.agentOptions.plugins)) {
3812
+ tools.push("mcp_search_provider_web_search");
3801
3813
  }
3802
3814
  return tools;
3803
3815
  }
@@ -7040,7 +7052,7 @@ function resolveRoute(route, modelProvider, plugins) {
7040
7052
  if (modelName !== void 0) base.model = modelName;
7041
7053
  return base;
7042
7054
  }
7043
- if (plugins?.enabled !== void 0 && plugins.enabled.length > 0) {
7055
+ if (enabledPluginNames(plugins).length > 0) {
7044
7056
  return {
7045
7057
  capability: route.capability,
7046
7058
  provider: route.provider,
@@ -8043,7 +8055,7 @@ function bootstrapSubmanagers(args) {
8043
8055
  args.settingSourcesIncludeProject
8044
8056
  );
8045
8057
  }
8046
- const providerCount = (args.options.providers?.routes?.length ?? 0) + (args.options.plugins?.enabled?.length ?? 0);
8058
+ const providerCount = (args.options.providers?.routes?.length ?? 0) + enabledPluginNames(args.options.plugins).length;
8047
8059
  if (providerCount > 0 || args.options.providers !== void 0) {
8048
8060
  out.providers = new ProvidersManagerImpl(
8049
8061
  args.options.model,
@@ -8063,7 +8075,9 @@ function bootstrapSubmanagers(args) {
8063
8075
  if (args.options.plugins !== void 0 || args.settingSourcesIncludePlugins) {
8064
8076
  out.pluginsManager = new PluginsManager(
8065
8077
  args.workspaceCwd,
8066
- args.options.plugins?.enabled,
8078
+ // The array (code-`Plugin`) form has no named-enable list; `undefined`
8079
+ // here preserves "no filter / load all file-discovered plugins".
8080
+ asPluginsSettings(args.options.plugins)?.enabled,
8067
8081
  args.settingSourcesIncludePlugins,
8068
8082
  false,
8069
8083
  void 0
@@ -15355,7 +15369,7 @@ var Agent = class _Agent {
15355
15369
  const runtime = options.cloud !== void 0 ? "cloud" : "local";
15356
15370
  const span = telemetry.startSpan(SPAN_NAMES.AGENT_CREATE, {
15357
15371
  runtime,
15358
- pluginCount: options.plugins?.enabled?.length ?? 0
15372
+ pluginCount: enabledPluginNames(options.plugins).length
15359
15373
  });
15360
15374
  try {
15361
15375
  const agent = await runCreateUnderSpan(options, span);
@@ -16190,6 +16204,118 @@ async function llmJudgeScore(options) {
16190
16204
  return parseScore(judgement.text, rubric);
16191
16205
  }
16192
16206
 
16207
+ // src/sandbox/types.ts
16208
+ var SandboxSecurityError = class extends Error {
16209
+ code = "sandbox_security";
16210
+ constructor(message) {
16211
+ super(message);
16212
+ this.name = "SandboxSecurityError";
16213
+ }
16214
+ };
16215
+ var SHELL_METACHARACTERS = /[;&|`$(){}]/;
16216
+ var SandboxBackend = class {
16217
+ config;
16218
+ constructor(config = {}) {
16219
+ this.config = {
16220
+ workDir: config.workDir ?? "/tmp",
16221
+ timeoutMs: config.timeoutMs ?? 3e4,
16222
+ maxOutputBytes: config.maxOutputBytes ?? 5 * 1024 * 1024
16223
+ };
16224
+ }
16225
+ async readFile(path) {
16226
+ const result = await this.execute(`cat ${this.shellEscape(path)}`);
16227
+ if (result.exitCode !== 0) {
16228
+ throw new Error(`readFile failed: ${result.stderr}`);
16229
+ }
16230
+ return result.stdout;
16231
+ }
16232
+ async writeFile(path, content) {
16233
+ await this.uploadFile(path, content);
16234
+ }
16235
+ async glob(pattern, cwd) {
16236
+ const dir = cwd ?? this.config.workDir ?? ".";
16237
+ const result = await this.execute(
16238
+ `find ${this.shellEscape(dir)} -name ${this.shellEscape(pattern)} -type f 2>/dev/null`
16239
+ );
16240
+ if (result.exitCode !== 0) return [];
16241
+ return result.stdout.trim().split("\n").filter(Boolean);
16242
+ }
16243
+ async grep(pattern, path) {
16244
+ const target = path ?? ".";
16245
+ const result = await this.execute(
16246
+ `grep -rn ${this.shellEscape(pattern)} ${this.shellEscape(target)} 2>/dev/null`
16247
+ );
16248
+ if (result.exitCode !== 0) return [];
16249
+ return result.stdout.trim().split("\n").filter(Boolean);
16250
+ }
16251
+ async listDir(path) {
16252
+ const result = await this.execute(`ls -1 ${this.shellEscape(path)}`);
16253
+ if (result.exitCode !== 0) return [];
16254
+ return result.stdout.trim().split("\n").filter(Boolean);
16255
+ }
16256
+ validateCommand(command) {
16257
+ if (SHELL_METACHARACTERS.test(command)) {
16258
+ throw new SandboxSecurityError(
16259
+ `Command contains shell metacharacters: ${command.slice(0, 80)}`
16260
+ );
16261
+ }
16262
+ }
16263
+ truncateOutput(output) {
16264
+ const max = this.config.maxOutputBytes ?? 5 * 1024 * 1024;
16265
+ if (Buffer.byteLength(output) > max) {
16266
+ return `${output.slice(0, max)}
16267
+ ...(truncated)`;
16268
+ }
16269
+ return output;
16270
+ }
16271
+ shellEscape(arg) {
16272
+ return shellEscapePosix(arg);
16273
+ }
16274
+ };
16275
+
16276
+ // src/sandbox/local-sandbox.ts
16277
+ var LocalSandbox = class extends SandboxBackend {
16278
+ constructor(config = {}) {
16279
+ super(config);
16280
+ }
16281
+ async execute(command, opts) {
16282
+ const timeout = opts?.timeoutMs ?? this.config.timeoutMs ?? 3e4;
16283
+ const max = this.config.maxOutputBytes ?? 5 * 1024 * 1024;
16284
+ return new Promise((resolve3) => {
16285
+ const child = execFile(
16286
+ "/bin/sh",
16287
+ ["-c", command],
16288
+ {
16289
+ cwd: this.config.workDir,
16290
+ timeout,
16291
+ maxBuffer: max,
16292
+ encoding: "utf-8"
16293
+ },
16294
+ (error, stdout, stderr) => {
16295
+ resolve3(this.buildResult(error, stdout ?? "", stderr ?? ""));
16296
+ }
16297
+ );
16298
+ child.on("error", () => {
16299
+ resolve3({ stdout: "", stderr: "spawn error", exitCode: 1, timedOut: false });
16300
+ });
16301
+ });
16302
+ }
16303
+ buildResult(error, stdout, stderr) {
16304
+ const timedOut = error !== null && "killed" in error && error.killed;
16305
+ return {
16306
+ stdout: this.truncateOutput(stdout),
16307
+ stderr: this.truncateOutput(stderr),
16308
+ exitCode: timedOut ? 124 : error ? 1 : 0,
16309
+ timedOut
16310
+ };
16311
+ }
16312
+ async uploadFile(path, content) {
16313
+ const fullPath = path.startsWith("/") ? path : `${this.config.workDir}/${path}`;
16314
+ await mkdir(dirname(fullPath), { recursive: true });
16315
+ await writeFile(fullPath, content, "utf-8");
16316
+ }
16317
+ };
16318
+
16193
16319
  // src/scorers.ts
16194
16320
  var JSON_SHAPE_MAX_BYTES = 1e6;
16195
16321
  function makeStringScorer(name, caseSensitive, compare) {
@@ -16293,7 +16419,7 @@ var Scorers = {
16293
16419
  * that rejects shell metacharacters in `execute` is unsupported for this scorer.
16294
16420
  */
16295
16421
  verifyGate(opts) {
16296
- const { sandbox, repoDir, failToPass, passToPass, command } = opts;
16422
+ const { sandbox = new LocalSandbox(), repoDir, failToPass, passToPass, command } = opts;
16297
16423
  return {
16298
16424
  name: "verify-gate",
16299
16425
  score: async () => {