@elisym/sdk 0.21.1 → 0.23.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/skills.js CHANGED
@@ -56,6 +56,14 @@ function runScript(cmd, args, opts) {
56
56
  }
57
57
  });
58
58
  }
59
+ var SECRET_ENV_VARS = ["ANTHROPIC_API_KEY", "OPENAI_API_KEY"];
60
+ function scopedToolEnv() {
61
+ const env = { ...process.env };
62
+ for (const key of SECRET_ENV_VARS) {
63
+ delete env[key];
64
+ }
65
+ return env;
66
+ }
59
67
  var ScriptSkill = class {
60
68
  name;
61
69
  description;
@@ -177,13 +185,21 @@ var ScriptSkill = class {
177
185
  if (value === void 0) {
178
186
  continue;
179
187
  }
188
+ const stringValue = String(value);
189
+ if (stringValue.startsWith("-")) {
190
+ return `Error: tool "${toolDef.name}" argument "${param.name}" must not begin with "-".`;
191
+ }
180
192
  if (param.required && index === 0) {
181
- args.push(String(value));
193
+ args.push(stringValue);
182
194
  } else {
183
- args.push(`--${param.name}`, String(value));
195
+ args.push(`--${param.name}`, stringValue);
184
196
  }
185
197
  }
186
- const result = await runScript(cmd, args, { cwd: this.skillDir, signal });
198
+ const result = await runScript(cmd, args, {
199
+ cwd: this.skillDir,
200
+ signal,
201
+ env: scopedToolEnv()
202
+ });
187
203
  if (result.spawnError) {
188
204
  return `Error: ${result.spawnError.message}`;
189
205
  }
@@ -246,6 +262,16 @@ var ScriptBillingExhaustedError = class extends Error {
246
262
  this.stderr = stderr;
247
263
  }
248
264
  };
265
+ var ScriptExecutionError = class extends Error {
266
+ exitCode;
267
+ detail;
268
+ constructor(exitCode, detail, summary) {
269
+ super(summary ?? `script failed (exit ${exitCode ?? "unknown"})`);
270
+ this.name = "ScriptExecutionError";
271
+ this.exitCode = exitCode;
272
+ this.detail = detail;
273
+ }
274
+ };
249
275
 
250
276
  // src/skills/staticScriptSkill.ts
251
277
  var StaticScriptSkill = class {
@@ -284,19 +310,23 @@ var StaticScriptSkill = class {
284
310
  env: this.scriptEnv
285
311
  });
286
312
  if (result.spawnError) {
287
- throw new Error(`script spawn failed: ${result.spawnError.message}`);
313
+ throw new ScriptExecutionError(
314
+ null,
315
+ result.spawnError.message,
316
+ "script could not be started"
317
+ );
288
318
  }
289
319
  if (result.code === SCRIPT_EXIT_BILLING_EXHAUSTED) {
290
320
  throw new ScriptBillingExhaustedError(result.code, result.stdout, result.stderr);
291
321
  }
292
322
  if (result.code !== 0) {
293
323
  const detail = result.stderr.trim() || result.stdout.trim() || "(no output)";
294
- throw new Error(`script failed (exit ${result.code}): ${detail}`);
324
+ throw new ScriptExecutionError(result.code, detail);
295
325
  }
296
326
  const output = result.stdout.trim();
297
327
  if (output === "") {
298
328
  const detail = result.stderr.trim() || "(no stderr)";
299
- throw new Error(`script exited 0 but produced empty output: ${detail}`);
329
+ throw new ScriptExecutionError(result.code, detail, "script produced empty output");
300
330
  }
301
331
  return { data: output };
302
332
  }
@@ -338,19 +368,23 @@ var DynamicScriptSkill = class {
338
368
  env: this.scriptEnv
339
369
  });
340
370
  if (result.spawnError) {
341
- throw new Error(`script spawn failed: ${result.spawnError.message}`);
371
+ throw new ScriptExecutionError(
372
+ null,
373
+ result.spawnError.message,
374
+ "script could not be started"
375
+ );
342
376
  }
343
377
  if (result.code === SCRIPT_EXIT_BILLING_EXHAUSTED) {
344
378
  throw new ScriptBillingExhaustedError(result.code, result.stdout, result.stderr);
345
379
  }
346
380
  if (result.code !== 0) {
347
381
  const detail = result.stderr.trim() || result.stdout.trim() || "(no output)";
348
- throw new Error(`script failed (exit ${result.code}): ${detail}`);
382
+ throw new ScriptExecutionError(result.code, detail);
349
383
  }
350
384
  const output = result.stdout.trim();
351
385
  if (output === "") {
352
386
  const detail = result.stderr.trim() || "(no stderr)";
353
- throw new Error(`script exited 0 but produced empty output: ${detail}`);
387
+ throw new ScriptExecutionError(result.code, detail, "script produced empty output");
354
388
  }
355
389
  return { data: output };
356
390
  }
@@ -364,7 +398,12 @@ function resolveInsidePath(rootDir, value) {
364
398
  }
365
399
  return candidate;
366
400
  }
367
- var LAMPORTS_PER_SOL = 1e9;
401
+ var LIMITS = {
402
+ // Upper bound for execution budgets (`max_execution_secs` / `execution_timeout_secs`).
403
+ // Distinct from MAX_TIMEOUT_SECS (the result-wait cap): execution budgets may be
404
+ // hours, so this exists only to keep `secs * 1000` within Node's setTimeout limit
405
+ // (2_147_483_647 ms) - a larger value overflows and fires the timer immediately.
406
+ MAX_EXECUTION_SECS: 2147483};
368
407
  var NATIVE_SOL = {
369
408
  chain: "solana",
370
409
  token: "sol",
@@ -441,11 +480,15 @@ var VALID_MODES = [
441
480
  "dynamic-script"
442
481
  ];
443
482
  function solToLamports(sol) {
444
- const asNumber = typeof sol === "string" ? Number(sol) : sol;
445
- if (!Number.isFinite(asNumber) || asNumber < 0) {
483
+ const asString = (typeof sol === "string" ? sol : String(sol)).trim();
484
+ if (/^0+(?:\.0+)?$/.test(asString)) {
485
+ return 0n;
486
+ }
487
+ try {
488
+ return parseAssetAmount(NATIVE_SOL, asString);
489
+ } catch {
446
490
  throw new Error(`Invalid SOL amount: ${sol}`);
447
491
  }
448
- return BigInt(Math.round(asNumber * LAMPORTS_PER_SOL));
449
492
  }
450
493
  function resolveSkillAsset(skillName, token, mint) {
451
494
  if (token === void 0 || token === null) {
@@ -667,6 +710,11 @@ function validateMaxExecutionSecs(skillName, raw) {
667
710
  `SKILL.md "${skillName}": "max_execution_secs" must be a non-negative integer (0 = unlimited)`
668
711
  );
669
712
  }
713
+ if (raw > LIMITS.MAX_EXECUTION_SECS) {
714
+ throw new Error(
715
+ `SKILL.md "${skillName}": "max_execution_secs" must be <= ${LIMITS.MAX_EXECUTION_SECS} (larger values overflow setTimeout)`
716
+ );
717
+ }
670
718
  return raw;
671
719
  }
672
720
  function validateSkillFrontmatter(frontmatter, systemPrompt, options = {}) {
@@ -704,7 +752,7 @@ function validateSkillFrontmatter(frontmatter, systemPrompt, options = {}) {
704
752
  }
705
753
  const priceString = typeof priceRaw === "number" ? String(priceRaw) : priceRaw;
706
754
  if (asset === NATIVE_SOL) {
707
- priceSubunits = solToLamports(priceRaw);
755
+ priceSubunits = solToLamports(priceString);
708
756
  } else {
709
757
  try {
710
758
  priceSubunits = parseAssetAmount(asset, priceString);
@@ -829,6 +877,14 @@ function validateSkillFrontmatter(frontmatter, systemPrompt, options = {}) {
829
877
  };
830
878
  }
831
879
  function buildSkillFromParsed(parsed, skillDir, logger) {
880
+ let imageFile = parsed.imageFile;
881
+ if (imageFile !== void 0 && resolveInsidePath(skillDir, imageFile) === null) {
882
+ logger.warn?.(
883
+ { skill: parsed.name, imageFile },
884
+ 'SKILL.md "image_file" escapes the skill directory; ignoring it'
885
+ );
886
+ imageFile = void 0;
887
+ }
832
888
  switch (parsed.mode) {
833
889
  case "llm":
834
890
  return new ScriptSkill({
@@ -843,7 +899,7 @@ function buildSkillFromParsed(parsed, skillDir, logger) {
843
899
  maxToolRounds: parsed.maxToolRounds,
844
900
  llmOverride: parsed.llmOverride,
845
901
  image: parsed.image,
846
- imageFile: parsed.imageFile,
902
+ imageFile,
847
903
  logger
848
904
  });
849
905
  case "static-file": {
@@ -866,7 +922,7 @@ function buildSkillFromParsed(parsed, skillDir, logger) {
866
922
  asset: parsed.asset,
867
923
  outputFilePath,
868
924
  image: parsed.image,
869
- imageFile: parsed.imageFile,
925
+ imageFile,
870
926
  llmOverride: parsed.llmOverride
871
927
  });
872
928
  }
@@ -892,7 +948,7 @@ function buildSkillFromParsed(parsed, skillDir, logger) {
892
948
  scriptArgs: parsed.scriptArgs,
893
949
  scriptTimeoutMs: parsed.scriptTimeoutMs ?? DEFAULT_SCRIPT_TIMEOUT_MS,
894
950
  image: parsed.image,
895
- imageFile: parsed.imageFile,
951
+ imageFile,
896
952
  llmOverride: parsed.llmOverride
897
953
  });
898
954
  }