@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.cjs CHANGED
@@ -63,6 +63,14 @@ function runScript(cmd, args, opts) {
63
63
  }
64
64
  });
65
65
  }
66
+ var SECRET_ENV_VARS = ["ANTHROPIC_API_KEY", "OPENAI_API_KEY"];
67
+ function scopedToolEnv() {
68
+ const env = { ...process.env };
69
+ for (const key of SECRET_ENV_VARS) {
70
+ delete env[key];
71
+ }
72
+ return env;
73
+ }
66
74
  var ScriptSkill = class {
67
75
  name;
68
76
  description;
@@ -184,13 +192,21 @@ var ScriptSkill = class {
184
192
  if (value === void 0) {
185
193
  continue;
186
194
  }
195
+ const stringValue = String(value);
196
+ if (stringValue.startsWith("-")) {
197
+ return `Error: tool "${toolDef.name}" argument "${param.name}" must not begin with "-".`;
198
+ }
187
199
  if (param.required && index === 0) {
188
- args.push(String(value));
200
+ args.push(stringValue);
189
201
  } else {
190
- args.push(`--${param.name}`, String(value));
202
+ args.push(`--${param.name}`, stringValue);
191
203
  }
192
204
  }
193
- const result = await runScript(cmd, args, { cwd: this.skillDir, signal });
205
+ const result = await runScript(cmd, args, {
206
+ cwd: this.skillDir,
207
+ signal,
208
+ env: scopedToolEnv()
209
+ });
194
210
  if (result.spawnError) {
195
211
  return `Error: ${result.spawnError.message}`;
196
212
  }
@@ -253,6 +269,16 @@ var ScriptBillingExhaustedError = class extends Error {
253
269
  this.stderr = stderr;
254
270
  }
255
271
  };
272
+ var ScriptExecutionError = class extends Error {
273
+ exitCode;
274
+ detail;
275
+ constructor(exitCode, detail, summary) {
276
+ super(summary ?? `script failed (exit ${exitCode ?? "unknown"})`);
277
+ this.name = "ScriptExecutionError";
278
+ this.exitCode = exitCode;
279
+ this.detail = detail;
280
+ }
281
+ };
256
282
 
257
283
  // src/skills/staticScriptSkill.ts
258
284
  var StaticScriptSkill = class {
@@ -291,19 +317,23 @@ var StaticScriptSkill = class {
291
317
  env: this.scriptEnv
292
318
  });
293
319
  if (result.spawnError) {
294
- throw new Error(`script spawn failed: ${result.spawnError.message}`);
320
+ throw new ScriptExecutionError(
321
+ null,
322
+ result.spawnError.message,
323
+ "script could not be started"
324
+ );
295
325
  }
296
326
  if (result.code === SCRIPT_EXIT_BILLING_EXHAUSTED) {
297
327
  throw new ScriptBillingExhaustedError(result.code, result.stdout, result.stderr);
298
328
  }
299
329
  if (result.code !== 0) {
300
330
  const detail = result.stderr.trim() || result.stdout.trim() || "(no output)";
301
- throw new Error(`script failed (exit ${result.code}): ${detail}`);
331
+ throw new ScriptExecutionError(result.code, detail);
302
332
  }
303
333
  const output = result.stdout.trim();
304
334
  if (output === "") {
305
335
  const detail = result.stderr.trim() || "(no stderr)";
306
- throw new Error(`script exited 0 but produced empty output: ${detail}`);
336
+ throw new ScriptExecutionError(result.code, detail, "script produced empty output");
307
337
  }
308
338
  return { data: output };
309
339
  }
@@ -345,19 +375,23 @@ var DynamicScriptSkill = class {
345
375
  env: this.scriptEnv
346
376
  });
347
377
  if (result.spawnError) {
348
- throw new Error(`script spawn failed: ${result.spawnError.message}`);
378
+ throw new ScriptExecutionError(
379
+ null,
380
+ result.spawnError.message,
381
+ "script could not be started"
382
+ );
349
383
  }
350
384
  if (result.code === SCRIPT_EXIT_BILLING_EXHAUSTED) {
351
385
  throw new ScriptBillingExhaustedError(result.code, result.stdout, result.stderr);
352
386
  }
353
387
  if (result.code !== 0) {
354
388
  const detail = result.stderr.trim() || result.stdout.trim() || "(no output)";
355
- throw new Error(`script failed (exit ${result.code}): ${detail}`);
389
+ throw new ScriptExecutionError(result.code, detail);
356
390
  }
357
391
  const output = result.stdout.trim();
358
392
  if (output === "") {
359
393
  const detail = result.stderr.trim() || "(no stderr)";
360
- throw new Error(`script exited 0 but produced empty output: ${detail}`);
394
+ throw new ScriptExecutionError(result.code, detail, "script produced empty output");
361
395
  }
362
396
  return { data: output };
363
397
  }
@@ -371,7 +405,12 @@ function resolveInsidePath(rootDir, value) {
371
405
  }
372
406
  return candidate;
373
407
  }
374
- var LAMPORTS_PER_SOL = 1e9;
408
+ var LIMITS = {
409
+ // Upper bound for execution budgets (`max_execution_secs` / `execution_timeout_secs`).
410
+ // Distinct from MAX_TIMEOUT_SECS (the result-wait cap): execution budgets may be
411
+ // hours, so this exists only to keep `secs * 1000` within Node's setTimeout limit
412
+ // (2_147_483_647 ms) - a larger value overflows and fires the timer immediately.
413
+ MAX_EXECUTION_SECS: 2147483};
375
414
  var NATIVE_SOL = {
376
415
  chain: "solana",
377
416
  token: "sol",
@@ -448,11 +487,15 @@ var VALID_MODES = [
448
487
  "dynamic-script"
449
488
  ];
450
489
  function solToLamports(sol) {
451
- const asNumber = typeof sol === "string" ? Number(sol) : sol;
452
- if (!Number.isFinite(asNumber) || asNumber < 0) {
490
+ const asString = (typeof sol === "string" ? sol : String(sol)).trim();
491
+ if (/^0+(?:\.0+)?$/.test(asString)) {
492
+ return 0n;
493
+ }
494
+ try {
495
+ return parseAssetAmount(NATIVE_SOL, asString);
496
+ } catch {
453
497
  throw new Error(`Invalid SOL amount: ${sol}`);
454
498
  }
455
- return BigInt(Math.round(asNumber * LAMPORTS_PER_SOL));
456
499
  }
457
500
  function resolveSkillAsset(skillName, token, mint) {
458
501
  if (token === void 0 || token === null) {
@@ -674,6 +717,11 @@ function validateMaxExecutionSecs(skillName, raw) {
674
717
  `SKILL.md "${skillName}": "max_execution_secs" must be a non-negative integer (0 = unlimited)`
675
718
  );
676
719
  }
720
+ if (raw > LIMITS.MAX_EXECUTION_SECS) {
721
+ throw new Error(
722
+ `SKILL.md "${skillName}": "max_execution_secs" must be <= ${LIMITS.MAX_EXECUTION_SECS} (larger values overflow setTimeout)`
723
+ );
724
+ }
677
725
  return raw;
678
726
  }
679
727
  function validateSkillFrontmatter(frontmatter, systemPrompt, options = {}) {
@@ -711,7 +759,7 @@ function validateSkillFrontmatter(frontmatter, systemPrompt, options = {}) {
711
759
  }
712
760
  const priceString = typeof priceRaw === "number" ? String(priceRaw) : priceRaw;
713
761
  if (asset === NATIVE_SOL) {
714
- priceSubunits = solToLamports(priceRaw);
762
+ priceSubunits = solToLamports(priceString);
715
763
  } else {
716
764
  try {
717
765
  priceSubunits = parseAssetAmount(asset, priceString);
@@ -836,6 +884,14 @@ function validateSkillFrontmatter(frontmatter, systemPrompt, options = {}) {
836
884
  };
837
885
  }
838
886
  function buildSkillFromParsed(parsed, skillDir, logger) {
887
+ let imageFile = parsed.imageFile;
888
+ if (imageFile !== void 0 && resolveInsidePath(skillDir, imageFile) === null) {
889
+ logger.warn?.(
890
+ { skill: parsed.name, imageFile },
891
+ 'SKILL.md "image_file" escapes the skill directory; ignoring it'
892
+ );
893
+ imageFile = void 0;
894
+ }
839
895
  switch (parsed.mode) {
840
896
  case "llm":
841
897
  return new ScriptSkill({
@@ -850,7 +906,7 @@ function buildSkillFromParsed(parsed, skillDir, logger) {
850
906
  maxToolRounds: parsed.maxToolRounds,
851
907
  llmOverride: parsed.llmOverride,
852
908
  image: parsed.image,
853
- imageFile: parsed.imageFile,
909
+ imageFile,
854
910
  logger
855
911
  });
856
912
  case "static-file": {
@@ -873,7 +929,7 @@ function buildSkillFromParsed(parsed, skillDir, logger) {
873
929
  asset: parsed.asset,
874
930
  outputFilePath,
875
931
  image: parsed.image,
876
- imageFile: parsed.imageFile,
932
+ imageFile,
877
933
  llmOverride: parsed.llmOverride
878
934
  });
879
935
  }
@@ -899,7 +955,7 @@ function buildSkillFromParsed(parsed, skillDir, logger) {
899
955
  scriptArgs: parsed.scriptArgs,
900
956
  scriptTimeoutMs: parsed.scriptTimeoutMs ?? DEFAULT_SCRIPT_TIMEOUT_MS,
901
957
  image: parsed.image,
902
- imageFile: parsed.imageFile,
958
+ imageFile,
903
959
  llmOverride: parsed.llmOverride
904
960
  });
905
961
  }