@elisym/sdk 0.12.4 → 0.12.5
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 +392 -88
- package/dist/skills.cjs.map +1 -1
- package/dist/skills.d.cts +183 -3
- package/dist/skills.d.ts +183 -3
- package/dist/skills.js +385 -89
- package/dist/skills.js.map +1 -1
- package/package.json +1 -1
package/dist/skills.cjs
CHANGED
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
var child_process = require('child_process');
|
|
4
4
|
var string_decoder = require('string_decoder');
|
|
5
|
-
var
|
|
5
|
+
var promises = require('fs/promises');
|
|
6
6
|
var path = require('path');
|
|
7
|
+
var fs = require('fs');
|
|
7
8
|
var YAML = require('yaml');
|
|
8
9
|
var Decimal = require('decimal.js-light');
|
|
9
10
|
|
|
@@ -29,9 +30,9 @@ function sleepWithSignal(ms, signal) {
|
|
|
29
30
|
return Promise.reject(createAbortError());
|
|
30
31
|
}
|
|
31
32
|
if (!signal) {
|
|
32
|
-
return new Promise((
|
|
33
|
+
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
33
34
|
}
|
|
34
|
-
return new Promise((
|
|
35
|
+
return new Promise((resolve2, reject) => {
|
|
35
36
|
const cleanup = () => {
|
|
36
37
|
clearTimeout(timer);
|
|
37
38
|
signal.removeEventListener("abort", onAbort);
|
|
@@ -42,7 +43,7 @@ function sleepWithSignal(ms, signal) {
|
|
|
42
43
|
};
|
|
43
44
|
const timer = setTimeout(() => {
|
|
44
45
|
cleanup();
|
|
45
|
-
|
|
46
|
+
resolve2();
|
|
46
47
|
}, ms);
|
|
47
48
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
48
49
|
});
|
|
@@ -309,14 +310,61 @@ function createLlmClient(config) {
|
|
|
309
310
|
}
|
|
310
311
|
return createAnthropicClient(config);
|
|
311
312
|
}
|
|
312
|
-
var
|
|
313
|
-
var
|
|
313
|
+
var MAX_SCRIPT_OUTPUT = 1e6;
|
|
314
|
+
var DEFAULT_SCRIPT_TIMEOUT_MS = 6e4;
|
|
315
|
+
function runScript(cmd, args, opts) {
|
|
316
|
+
return new Promise((resolveResult) => {
|
|
317
|
+
const maxOutput = opts.maxOutput ?? MAX_SCRIPT_OUTPUT;
|
|
318
|
+
const timeoutMs = opts.timeoutMs ?? DEFAULT_SCRIPT_TIMEOUT_MS;
|
|
319
|
+
const child = child_process.spawn(cmd, args, {
|
|
320
|
+
cwd: opts.cwd,
|
|
321
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
322
|
+
timeout: timeoutMs,
|
|
323
|
+
killSignal: "SIGKILL",
|
|
324
|
+
signal: opts.signal
|
|
325
|
+
});
|
|
326
|
+
let stdout = "";
|
|
327
|
+
let stderr = "";
|
|
328
|
+
const stdoutDecoder = new string_decoder.StringDecoder("utf8");
|
|
329
|
+
const stderrDecoder = new string_decoder.StringDecoder("utf8");
|
|
330
|
+
child.stdout?.on("data", (data) => {
|
|
331
|
+
if (stdout.length < maxOutput) {
|
|
332
|
+
stdout += stdoutDecoder.write(data);
|
|
333
|
+
if (stdout.length > maxOutput) {
|
|
334
|
+
stdout = stdout.slice(0, maxOutput);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
});
|
|
338
|
+
child.stderr?.on("data", (data) => {
|
|
339
|
+
if (stderr.length < maxOutput) {
|
|
340
|
+
stderr += stderrDecoder.write(data);
|
|
341
|
+
if (stderr.length > maxOutput) {
|
|
342
|
+
stderr = stderr.slice(0, maxOutput);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
});
|
|
346
|
+
child.on("close", (code) => {
|
|
347
|
+
stdout += stdoutDecoder.end();
|
|
348
|
+
stderr += stderrDecoder.end();
|
|
349
|
+
resolveResult({ stdout, stderr, code });
|
|
350
|
+
});
|
|
351
|
+
child.on("error", (err) => {
|
|
352
|
+
resolveResult({ stdout, stderr, code: null, spawnError: err });
|
|
353
|
+
});
|
|
354
|
+
if (child.stdin) {
|
|
355
|
+
child.stdin.on("error", () => {
|
|
356
|
+
});
|
|
357
|
+
child.stdin.end(opts.stdin ?? "");
|
|
358
|
+
}
|
|
359
|
+
});
|
|
360
|
+
}
|
|
314
361
|
var ScriptSkill = class {
|
|
315
362
|
name;
|
|
316
363
|
description;
|
|
317
364
|
capabilities;
|
|
318
365
|
priceSubunits;
|
|
319
366
|
asset;
|
|
367
|
+
mode = "llm";
|
|
320
368
|
image;
|
|
321
369
|
imageFile;
|
|
322
370
|
skillDir;
|
|
@@ -388,76 +436,163 @@ var ScriptSkill = class {
|
|
|
388
436
|
}
|
|
389
437
|
throw new Error(`Max tool rounds (${this.maxToolRounds}) exceeded`);
|
|
390
438
|
}
|
|
391
|
-
runTool(toolDef, call, signal) {
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
439
|
+
async runTool(toolDef, call, signal) {
|
|
440
|
+
const args = [...toolDef.command];
|
|
441
|
+
const cmd = args.shift();
|
|
442
|
+
if (!cmd) {
|
|
443
|
+
return `Error: tool "${toolDef.name}" has an empty command`;
|
|
444
|
+
}
|
|
445
|
+
const params = toolDef.parameters ?? [];
|
|
446
|
+
for (let index = 0; index < params.length; index++) {
|
|
447
|
+
const param = params[index];
|
|
448
|
+
if (!param) {
|
|
449
|
+
continue;
|
|
398
450
|
}
|
|
399
|
-
const
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
if (!param) {
|
|
403
|
-
continue;
|
|
404
|
-
}
|
|
405
|
-
const value = call.arguments[param.name];
|
|
406
|
-
if (value === void 0) {
|
|
407
|
-
continue;
|
|
408
|
-
}
|
|
409
|
-
if (param.required && index === 0) {
|
|
410
|
-
args.push(String(value));
|
|
411
|
-
} else {
|
|
412
|
-
args.push(`--${param.name}`, String(value));
|
|
413
|
-
}
|
|
451
|
+
const value = call.arguments[param.name];
|
|
452
|
+
if (value === void 0) {
|
|
453
|
+
continue;
|
|
414
454
|
}
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
455
|
+
if (param.required && index === 0) {
|
|
456
|
+
args.push(String(value));
|
|
457
|
+
} else {
|
|
458
|
+
args.push(`--${param.name}`, String(value));
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
const result = await runScript(cmd, args, { cwd: this.skillDir, signal });
|
|
462
|
+
if (result.spawnError) {
|
|
463
|
+
return `Error: ${result.spawnError.message}`;
|
|
464
|
+
}
|
|
465
|
+
if (result.code === 0) {
|
|
466
|
+
return result.stdout.trim();
|
|
467
|
+
}
|
|
468
|
+
this.logger.debug?.(
|
|
469
|
+
{ tool: toolDef.name, code: result.code, stderrLen: result.stderr.length },
|
|
470
|
+
"skill tool exited non-zero"
|
|
471
|
+
);
|
|
472
|
+
return `Error (exit ${result.code}): ${result.stderr.trim() || result.stdout.trim()}`;
|
|
473
|
+
}
|
|
474
|
+
};
|
|
475
|
+
var MAX_STATIC_FILE_SIZE = 256 * 1024;
|
|
476
|
+
var StaticFileSkill = class {
|
|
477
|
+
name;
|
|
478
|
+
description;
|
|
479
|
+
capabilities;
|
|
480
|
+
priceSubunits;
|
|
481
|
+
asset;
|
|
482
|
+
mode = "static-file";
|
|
483
|
+
image;
|
|
484
|
+
imageFile;
|
|
485
|
+
outputFilePath;
|
|
486
|
+
constructor(params) {
|
|
487
|
+
this.name = params.name;
|
|
488
|
+
this.description = params.description;
|
|
489
|
+
this.capabilities = params.capabilities;
|
|
490
|
+
this.priceSubunits = params.priceSubunits;
|
|
491
|
+
this.asset = params.asset;
|
|
492
|
+
this.image = params.image;
|
|
493
|
+
this.imageFile = params.imageFile;
|
|
494
|
+
this.outputFilePath = params.outputFilePath;
|
|
495
|
+
}
|
|
496
|
+
async execute(_input, _ctx) {
|
|
497
|
+
const buffer = await promises.readFile(this.outputFilePath);
|
|
498
|
+
if (buffer.length > MAX_STATIC_FILE_SIZE) {
|
|
499
|
+
throw new Error(
|
|
500
|
+
`static-file output exceeds ${MAX_STATIC_FILE_SIZE} bytes (got ${buffer.length})`
|
|
501
|
+
);
|
|
502
|
+
}
|
|
503
|
+
return { data: buffer.toString("utf-8") };
|
|
504
|
+
}
|
|
505
|
+
};
|
|
506
|
+
var StaticScriptSkill = class {
|
|
507
|
+
name;
|
|
508
|
+
description;
|
|
509
|
+
capabilities;
|
|
510
|
+
priceSubunits;
|
|
511
|
+
asset;
|
|
512
|
+
mode = "static-script";
|
|
513
|
+
image;
|
|
514
|
+
imageFile;
|
|
515
|
+
scriptPath;
|
|
516
|
+
scriptArgs;
|
|
517
|
+
scriptTimeoutMs;
|
|
518
|
+
constructor(params) {
|
|
519
|
+
this.name = params.name;
|
|
520
|
+
this.description = params.description;
|
|
521
|
+
this.capabilities = params.capabilities;
|
|
522
|
+
this.priceSubunits = params.priceSubunits;
|
|
523
|
+
this.asset = params.asset;
|
|
524
|
+
this.image = params.image;
|
|
525
|
+
this.imageFile = params.imageFile;
|
|
526
|
+
this.scriptPath = params.scriptPath;
|
|
527
|
+
this.scriptArgs = params.scriptArgs;
|
|
528
|
+
this.scriptTimeoutMs = params.scriptTimeoutMs;
|
|
529
|
+
}
|
|
530
|
+
async execute(_input, ctx) {
|
|
531
|
+
const result = await runScript(this.scriptPath, this.scriptArgs, {
|
|
532
|
+
cwd: path.dirname(this.scriptPath),
|
|
533
|
+
signal: ctx.signal,
|
|
534
|
+
timeoutMs: this.scriptTimeoutMs
|
|
535
|
+
});
|
|
536
|
+
if (result.spawnError) {
|
|
537
|
+
throw new Error(`script spawn failed: ${result.spawnError.message}`);
|
|
538
|
+
}
|
|
539
|
+
if (result.code !== 0) {
|
|
540
|
+
const detail = result.stderr.trim() || result.stdout.trim() || "(no output)";
|
|
541
|
+
throw new Error(`script failed (exit ${result.code}): ${detail}`);
|
|
542
|
+
}
|
|
543
|
+
return { data: result.stdout.trim() };
|
|
544
|
+
}
|
|
545
|
+
};
|
|
546
|
+
var DynamicScriptSkill = class {
|
|
547
|
+
name;
|
|
548
|
+
description;
|
|
549
|
+
capabilities;
|
|
550
|
+
priceSubunits;
|
|
551
|
+
asset;
|
|
552
|
+
mode = "dynamic-script";
|
|
553
|
+
image;
|
|
554
|
+
imageFile;
|
|
555
|
+
scriptPath;
|
|
556
|
+
scriptArgs;
|
|
557
|
+
scriptTimeoutMs;
|
|
558
|
+
constructor(params) {
|
|
559
|
+
this.name = params.name;
|
|
560
|
+
this.description = params.description;
|
|
561
|
+
this.capabilities = params.capabilities;
|
|
562
|
+
this.priceSubunits = params.priceSubunits;
|
|
563
|
+
this.asset = params.asset;
|
|
564
|
+
this.image = params.image;
|
|
565
|
+
this.imageFile = params.imageFile;
|
|
566
|
+
this.scriptPath = params.scriptPath;
|
|
567
|
+
this.scriptArgs = params.scriptArgs;
|
|
568
|
+
this.scriptTimeoutMs = params.scriptTimeoutMs;
|
|
569
|
+
}
|
|
570
|
+
async execute(input, ctx) {
|
|
571
|
+
const result = await runScript(this.scriptPath, this.scriptArgs, {
|
|
572
|
+
cwd: path.dirname(this.scriptPath),
|
|
573
|
+
stdin: input.data,
|
|
574
|
+
signal: ctx.signal,
|
|
575
|
+
timeoutMs: this.scriptTimeoutMs
|
|
458
576
|
});
|
|
577
|
+
if (result.spawnError) {
|
|
578
|
+
throw new Error(`script spawn failed: ${result.spawnError.message}`);
|
|
579
|
+
}
|
|
580
|
+
if (result.code !== 0) {
|
|
581
|
+
const detail = result.stderr.trim() || result.stdout.trim() || "(no output)";
|
|
582
|
+
throw new Error(`script failed (exit ${result.code}): ${detail}`);
|
|
583
|
+
}
|
|
584
|
+
return { data: result.stdout.trim() };
|
|
459
585
|
}
|
|
460
586
|
};
|
|
587
|
+
function resolveInsidePath(rootDir, value) {
|
|
588
|
+
const root = path.resolve(rootDir);
|
|
589
|
+
const candidate = path.resolve(root, value);
|
|
590
|
+
const rel = path.relative(root, candidate);
|
|
591
|
+
if (rel === "" || rel.startsWith("..") || rel.includes(`..${path.sep}`)) {
|
|
592
|
+
return null;
|
|
593
|
+
}
|
|
594
|
+
return candidate;
|
|
595
|
+
}
|
|
461
596
|
var LAMPORTS_PER_SOL = 1e9;
|
|
462
597
|
var NATIVE_SOL = {
|
|
463
598
|
chain: "solana",
|
|
@@ -527,6 +662,12 @@ Decimal__default.default.clone({ toExpNeg: -100, toExpPos: 100, precision: 50 })
|
|
|
527
662
|
|
|
528
663
|
// src/skills/loader.ts
|
|
529
664
|
var DEFAULT_MAX_TOOL_ROUNDS = 10;
|
|
665
|
+
var VALID_MODES = [
|
|
666
|
+
"llm",
|
|
667
|
+
"static-file",
|
|
668
|
+
"static-script",
|
|
669
|
+
"dynamic-script"
|
|
670
|
+
];
|
|
530
671
|
function solToLamports(sol) {
|
|
531
672
|
const asNumber = typeof sol === "string" ? Number(sol) : sol;
|
|
532
673
|
if (!Number.isFinite(asNumber) || asNumber < 0) {
|
|
@@ -643,6 +784,43 @@ function validateTool(raw, skillName, index) {
|
|
|
643
784
|
parameters
|
|
644
785
|
};
|
|
645
786
|
}
|
|
787
|
+
function validateMode(skillName, raw) {
|
|
788
|
+
if (raw === void 0 || raw === null) {
|
|
789
|
+
return "llm";
|
|
790
|
+
}
|
|
791
|
+
if (typeof raw !== "string") {
|
|
792
|
+
throw new Error(`SKILL.md "${skillName}": "mode" must be a string`);
|
|
793
|
+
}
|
|
794
|
+
if (!VALID_MODES.includes(raw)) {
|
|
795
|
+
throw new Error(
|
|
796
|
+
`SKILL.md "${skillName}": invalid mode "${raw}". Allowed: ${VALID_MODES.join(", ")}`
|
|
797
|
+
);
|
|
798
|
+
}
|
|
799
|
+
return raw;
|
|
800
|
+
}
|
|
801
|
+
function validateScriptArgs(skillName, raw) {
|
|
802
|
+
if (raw === void 0 || raw === null) {
|
|
803
|
+
return [];
|
|
804
|
+
}
|
|
805
|
+
if (!Array.isArray(raw)) {
|
|
806
|
+
throw new Error(`SKILL.md "${skillName}": "script_args" must be an array of strings`);
|
|
807
|
+
}
|
|
808
|
+
for (const part of raw) {
|
|
809
|
+
if (typeof part !== "string") {
|
|
810
|
+
throw new Error(`SKILL.md "${skillName}": "script_args" entries must be strings`);
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
return raw;
|
|
814
|
+
}
|
|
815
|
+
function validateScriptTimeoutMs(skillName, raw) {
|
|
816
|
+
if (raw === void 0 || raw === null) {
|
|
817
|
+
return void 0;
|
|
818
|
+
}
|
|
819
|
+
if (typeof raw !== "number" || !Number.isInteger(raw) || raw <= 0) {
|
|
820
|
+
throw new Error(`SKILL.md "${skillName}": "script_timeout_ms" must be a positive integer`);
|
|
821
|
+
}
|
|
822
|
+
return raw;
|
|
823
|
+
}
|
|
646
824
|
function validateSkillFrontmatter(frontmatter, systemPrompt, options = {}) {
|
|
647
825
|
if (typeof frontmatter.name !== "string" || frontmatter.name.length === 0) {
|
|
648
826
|
throw new Error('SKILL.md: missing or invalid "name" field');
|
|
@@ -694,8 +872,14 @@ function validateSkillFrontmatter(frontmatter, systemPrompt, options = {}) {
|
|
|
694
872
|
);
|
|
695
873
|
}
|
|
696
874
|
}
|
|
875
|
+
const mode = validateMode(frontmatter.name, frontmatter.mode);
|
|
697
876
|
const tools = [];
|
|
698
877
|
if (frontmatter.tools !== void 0) {
|
|
878
|
+
if (mode !== "llm") {
|
|
879
|
+
throw new Error(
|
|
880
|
+
`SKILL.md "${frontmatter.name}": "tools" is only valid in mode 'llm' (got '${mode}')`
|
|
881
|
+
);
|
|
882
|
+
}
|
|
699
883
|
if (!Array.isArray(frontmatter.tools)) {
|
|
700
884
|
throw new Error(`SKILL.md "${frontmatter.name}": "tools" must be an array`);
|
|
701
885
|
}
|
|
@@ -705,6 +889,11 @@ function validateSkillFrontmatter(frontmatter, systemPrompt, options = {}) {
|
|
|
705
889
|
}
|
|
706
890
|
let maxToolRounds = DEFAULT_MAX_TOOL_ROUNDS;
|
|
707
891
|
if (frontmatter.max_tool_rounds !== void 0) {
|
|
892
|
+
if (mode !== "llm") {
|
|
893
|
+
throw new Error(
|
|
894
|
+
`SKILL.md "${frontmatter.name}": "max_tool_rounds" is only valid in mode 'llm' (got '${mode}')`
|
|
895
|
+
);
|
|
896
|
+
}
|
|
708
897
|
if (typeof frontmatter.max_tool_rounds !== "number" || !Number.isInteger(frontmatter.max_tool_rounds) || frontmatter.max_tool_rounds <= 0) {
|
|
709
898
|
throw new Error(
|
|
710
899
|
`SKILL.md "${frontmatter.name}": "max_tool_rounds" must be a positive integer`
|
|
@@ -712,6 +901,56 @@ function validateSkillFrontmatter(frontmatter, systemPrompt, options = {}) {
|
|
|
712
901
|
}
|
|
713
902
|
maxToolRounds = frontmatter.max_tool_rounds;
|
|
714
903
|
}
|
|
904
|
+
let outputFile;
|
|
905
|
+
let script;
|
|
906
|
+
let scriptArgs = [];
|
|
907
|
+
let scriptTimeoutMs;
|
|
908
|
+
if (mode === "static-file") {
|
|
909
|
+
if (typeof frontmatter.output_file !== "string" || frontmatter.output_file.length === 0) {
|
|
910
|
+
throw new Error(
|
|
911
|
+
`SKILL.md "${frontmatter.name}": mode 'static-file' requires "output_file" (string)`
|
|
912
|
+
);
|
|
913
|
+
}
|
|
914
|
+
if (frontmatter.script !== void 0) {
|
|
915
|
+
throw new Error(
|
|
916
|
+
`SKILL.md "${frontmatter.name}": "script" is not valid in mode 'static-file'`
|
|
917
|
+
);
|
|
918
|
+
}
|
|
919
|
+
outputFile = frontmatter.output_file;
|
|
920
|
+
} else if (mode === "static-script" || mode === "dynamic-script") {
|
|
921
|
+
if (typeof frontmatter.script !== "string" || frontmatter.script.length === 0) {
|
|
922
|
+
throw new Error(`SKILL.md "${frontmatter.name}": mode '${mode}' requires "script" (string)`);
|
|
923
|
+
}
|
|
924
|
+
if (frontmatter.output_file !== void 0) {
|
|
925
|
+
throw new Error(
|
|
926
|
+
`SKILL.md "${frontmatter.name}": "output_file" is only valid in mode 'static-file'`
|
|
927
|
+
);
|
|
928
|
+
}
|
|
929
|
+
script = frontmatter.script;
|
|
930
|
+
scriptArgs = validateScriptArgs(frontmatter.name, frontmatter.script_args);
|
|
931
|
+
scriptTimeoutMs = validateScriptTimeoutMs(frontmatter.name, frontmatter.script_timeout_ms);
|
|
932
|
+
} else {
|
|
933
|
+
if (frontmatter.output_file !== void 0) {
|
|
934
|
+
throw new Error(
|
|
935
|
+
`SKILL.md "${frontmatter.name}": "output_file" is only valid in mode 'static-file'`
|
|
936
|
+
);
|
|
937
|
+
}
|
|
938
|
+
if (frontmatter.script !== void 0) {
|
|
939
|
+
throw new Error(
|
|
940
|
+
`SKILL.md "${frontmatter.name}": "script" is only valid in script modes (static-script, dynamic-script)`
|
|
941
|
+
);
|
|
942
|
+
}
|
|
943
|
+
if (frontmatter.script_args !== void 0) {
|
|
944
|
+
throw new Error(
|
|
945
|
+
`SKILL.md "${frontmatter.name}": "script_args" is only valid in script modes`
|
|
946
|
+
);
|
|
947
|
+
}
|
|
948
|
+
if (frontmatter.script_timeout_ms !== void 0) {
|
|
949
|
+
throw new Error(
|
|
950
|
+
`SKILL.md "${frontmatter.name}": "script_timeout_ms" is only valid in script modes`
|
|
951
|
+
);
|
|
952
|
+
}
|
|
953
|
+
}
|
|
715
954
|
const image = typeof frontmatter.image === "string" ? frontmatter.image : void 0;
|
|
716
955
|
const imageFile = typeof frontmatter.image_file === "string" ? frontmatter.image_file : void 0;
|
|
717
956
|
return {
|
|
@@ -720,13 +959,85 @@ function validateSkillFrontmatter(frontmatter, systemPrompt, options = {}) {
|
|
|
720
959
|
capabilities,
|
|
721
960
|
priceSubunits,
|
|
722
961
|
asset,
|
|
962
|
+
mode,
|
|
723
963
|
systemPrompt,
|
|
724
964
|
tools,
|
|
725
965
|
maxToolRounds,
|
|
726
966
|
image,
|
|
727
|
-
imageFile
|
|
967
|
+
imageFile,
|
|
968
|
+
outputFile,
|
|
969
|
+
script,
|
|
970
|
+
scriptArgs,
|
|
971
|
+
scriptTimeoutMs
|
|
728
972
|
};
|
|
729
973
|
}
|
|
974
|
+
function buildSkillFromParsed(parsed, skillDir, logger) {
|
|
975
|
+
switch (parsed.mode) {
|
|
976
|
+
case "llm":
|
|
977
|
+
return new ScriptSkill({
|
|
978
|
+
name: parsed.name,
|
|
979
|
+
description: parsed.description,
|
|
980
|
+
capabilities: parsed.capabilities,
|
|
981
|
+
priceSubunits: parsed.priceSubunits,
|
|
982
|
+
asset: parsed.asset,
|
|
983
|
+
skillDir,
|
|
984
|
+
systemPrompt: parsed.systemPrompt,
|
|
985
|
+
tools: parsed.tools,
|
|
986
|
+
maxToolRounds: parsed.maxToolRounds,
|
|
987
|
+
image: parsed.image,
|
|
988
|
+
imageFile: parsed.imageFile,
|
|
989
|
+
logger
|
|
990
|
+
});
|
|
991
|
+
case "static-file": {
|
|
992
|
+
if (parsed.outputFile === void 0) {
|
|
993
|
+
throw new Error(
|
|
994
|
+
`SKILL.md "${parsed.name}": internal error - outputFile missing for mode 'static-file'`
|
|
995
|
+
);
|
|
996
|
+
}
|
|
997
|
+
const outputFilePath = resolveInsidePath(skillDir, parsed.outputFile);
|
|
998
|
+
if (!outputFilePath) {
|
|
999
|
+
throw new Error(
|
|
1000
|
+
`SKILL.md "${parsed.name}": "output_file" must stay inside the skill directory`
|
|
1001
|
+
);
|
|
1002
|
+
}
|
|
1003
|
+
return new StaticFileSkill({
|
|
1004
|
+
name: parsed.name,
|
|
1005
|
+
description: parsed.description,
|
|
1006
|
+
capabilities: parsed.capabilities,
|
|
1007
|
+
priceSubunits: parsed.priceSubunits,
|
|
1008
|
+
asset: parsed.asset,
|
|
1009
|
+
outputFilePath,
|
|
1010
|
+
image: parsed.image,
|
|
1011
|
+
imageFile: parsed.imageFile
|
|
1012
|
+
});
|
|
1013
|
+
}
|
|
1014
|
+
case "static-script":
|
|
1015
|
+
case "dynamic-script": {
|
|
1016
|
+
if (parsed.script === void 0) {
|
|
1017
|
+
throw new Error(
|
|
1018
|
+
`SKILL.md "${parsed.name}": internal error - script missing for mode '${parsed.mode}'`
|
|
1019
|
+
);
|
|
1020
|
+
}
|
|
1021
|
+
const scriptPath = resolveInsidePath(skillDir, parsed.script);
|
|
1022
|
+
if (!scriptPath) {
|
|
1023
|
+
throw new Error(`SKILL.md "${parsed.name}": "script" must stay inside the skill directory`);
|
|
1024
|
+
}
|
|
1025
|
+
const Ctor = parsed.mode === "static-script" ? StaticScriptSkill : DynamicScriptSkill;
|
|
1026
|
+
return new Ctor({
|
|
1027
|
+
name: parsed.name,
|
|
1028
|
+
description: parsed.description,
|
|
1029
|
+
capabilities: parsed.capabilities,
|
|
1030
|
+
priceSubunits: parsed.priceSubunits,
|
|
1031
|
+
asset: parsed.asset,
|
|
1032
|
+
scriptPath,
|
|
1033
|
+
scriptArgs: parsed.scriptArgs,
|
|
1034
|
+
scriptTimeoutMs: parsed.scriptTimeoutMs ?? DEFAULT_SCRIPT_TIMEOUT_MS,
|
|
1035
|
+
image: parsed.image,
|
|
1036
|
+
imageFile: parsed.imageFile
|
|
1037
|
+
});
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
730
1041
|
function loadSkillsFromDir(skillsDir, options = {}) {
|
|
731
1042
|
const logger = options.logger ?? {};
|
|
732
1043
|
const skills = [];
|
|
@@ -751,22 +1062,7 @@ function loadSkillsFromDir(skillsDir, options = {}) {
|
|
|
751
1062
|
const content = fs.readFileSync(skillMdPath, "utf-8");
|
|
752
1063
|
const { frontmatter, systemPrompt } = parseSkillMd(content);
|
|
753
1064
|
const parsed = validateSkillFrontmatter(frontmatter, systemPrompt, options);
|
|
754
|
-
skills.push(
|
|
755
|
-
new ScriptSkill({
|
|
756
|
-
name: parsed.name,
|
|
757
|
-
description: parsed.description,
|
|
758
|
-
capabilities: parsed.capabilities,
|
|
759
|
-
priceSubunits: parsed.priceSubunits,
|
|
760
|
-
asset: parsed.asset,
|
|
761
|
-
skillDir: entryPath,
|
|
762
|
-
systemPrompt: parsed.systemPrompt,
|
|
763
|
-
tools: parsed.tools,
|
|
764
|
-
maxToolRounds: parsed.maxToolRounds,
|
|
765
|
-
image: parsed.image,
|
|
766
|
-
imageFile: parsed.imageFile,
|
|
767
|
-
logger
|
|
768
|
-
})
|
|
769
|
-
);
|
|
1065
|
+
skills.push(buildSkillFromParsed(parsed, entryPath, logger));
|
|
770
1066
|
} catch (error) {
|
|
771
1067
|
const message = error instanceof Error ? error.message : String(error);
|
|
772
1068
|
logger.warn?.({ dir: entry, err: message }, "skipping malformed skill directory");
|
|
@@ -776,12 +1072,20 @@ function loadSkillsFromDir(skillsDir, options = {}) {
|
|
|
776
1072
|
}
|
|
777
1073
|
|
|
778
1074
|
exports.DEFAULT_MAX_TOOL_ROUNDS = DEFAULT_MAX_TOOL_ROUNDS;
|
|
1075
|
+
exports.DEFAULT_SCRIPT_TIMEOUT_MS = DEFAULT_SCRIPT_TIMEOUT_MS;
|
|
1076
|
+
exports.DynamicScriptSkill = DynamicScriptSkill;
|
|
1077
|
+
exports.MAX_SCRIPT_OUTPUT = MAX_SCRIPT_OUTPUT;
|
|
1078
|
+
exports.MAX_STATIC_FILE_SIZE = MAX_STATIC_FILE_SIZE;
|
|
779
1079
|
exports.ScriptSkill = ScriptSkill;
|
|
1080
|
+
exports.StaticFileSkill = StaticFileSkill;
|
|
1081
|
+
exports.StaticScriptSkill = StaticScriptSkill;
|
|
780
1082
|
exports.createAnthropicClient = createAnthropicClient;
|
|
781
1083
|
exports.createLlmClient = createLlmClient;
|
|
782
1084
|
exports.createOpenAIClient = createOpenAIClient;
|
|
783
1085
|
exports.loadSkillsFromDir = loadSkillsFromDir;
|
|
784
1086
|
exports.parseSkillMd = parseSkillMd;
|
|
1087
|
+
exports.resolveInsidePath = resolveInsidePath;
|
|
1088
|
+
exports.runScript = runScript;
|
|
785
1089
|
exports.validateSkillFrontmatter = validateSkillFrontmatter;
|
|
786
1090
|
//# sourceMappingURL=skills.cjs.map
|
|
787
1091
|
//# sourceMappingURL=skills.cjs.map
|