@elisym/sdk 0.23.0 → 0.24.1
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/agent-store.cjs +22 -0
- package/dist/agent-store.cjs.map +1 -1
- package/dist/agent-store.d.cts +9 -1
- package/dist/agent-store.d.ts +9 -1
- package/dist/agent-store.js +23 -2
- package/dist/agent-store.js.map +1 -1
- package/dist/index.cjs +134 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +206 -6
- package/dist/index.d.ts +206 -6
- package/dist/index.js +131 -10
- package/dist/index.js.map +1 -1
- package/dist/llm-health.cjs.map +1 -1
- package/dist/llm-health.d.cts +2 -2
- package/dist/llm-health.d.ts +2 -2
- package/dist/llm-health.js.map +1 -1
- package/dist/node.cjs +175 -0
- package/dist/node.cjs.map +1 -1
- package/dist/node.d.cts +46 -1
- package/dist/node.d.ts +46 -1
- package/dist/node.js +175 -1
- package/dist/node.js.map +1 -1
- package/dist/skills.cjs +128 -28
- package/dist/skills.cjs.map +1 -1
- package/dist/skills.d.cts +49 -1
- package/dist/skills.d.ts +49 -1
- package/dist/skills.js +130 -30
- package/dist/skills.js.map +1 -1
- package/dist/{types-Cdscy9kY.d.cts → types-CqN9kFTn.d.cts} +6 -1
- package/dist/{types-Cdscy9kY.d.ts → types-CqN9kFTn.d.ts} +6 -1
- package/package.json +4 -1
package/dist/skills.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { A as Asset } from './assets-C-nzSYD4.cjs';
|
|
2
|
-
import { S as SkillRateLimit } from './types-
|
|
2
|
+
import { S as SkillRateLimit } from './types-CqN9kFTn.cjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Shared SKILL.md runtime types. A skill is a markdown document whose
|
|
@@ -12,10 +12,29 @@ interface SkillInput {
|
|
|
12
12
|
inputType: string;
|
|
13
13
|
tags: string[];
|
|
14
14
|
jobId: string;
|
|
15
|
+
/**
|
|
16
|
+
* Local path to a file input fetched out-of-band (P2P via iroh), when the job
|
|
17
|
+
* carried a file attachment. The runtime fetches it after payment and removes
|
|
18
|
+
* it after execution; the skill reads from disk rather than from `data`.
|
|
19
|
+
*/
|
|
20
|
+
filePath?: string;
|
|
15
21
|
}
|
|
16
22
|
interface SkillOutput {
|
|
17
23
|
data: string;
|
|
18
24
|
outputMime?: string;
|
|
25
|
+
/**
|
|
26
|
+
* Local path to a file result. When set, the runtime seeds the file via iroh
|
|
27
|
+
* and the customer fetches it out-of-band; `data` carries any text note (or '').
|
|
28
|
+
* `outputMime` is reused as the attachment's mime.
|
|
29
|
+
*/
|
|
30
|
+
filePath?: string;
|
|
31
|
+
/**
|
|
32
|
+
* Releases the resources backing `filePath` (e.g. a temp dir). The runtime
|
|
33
|
+
* calls it once it has seeded the file - or failed to - since seeding happens
|
|
34
|
+
* after `execute()` returns and the producer cannot release the file itself.
|
|
35
|
+
* Mirrors the input-side cleanup callback in the runtime's `resolveInputFile`.
|
|
36
|
+
*/
|
|
37
|
+
cleanup?: () => Promise<void>;
|
|
19
38
|
}
|
|
20
39
|
/**
|
|
21
40
|
* Optional per-skill LLM override declared in SKILL.md frontmatter.
|
|
@@ -342,6 +361,12 @@ interface DynamicScriptSkillParams {
|
|
|
342
361
|
* itself reads the key from its environment.
|
|
343
362
|
*/
|
|
344
363
|
llmOverride?: SkillLlmOverride;
|
|
364
|
+
/**
|
|
365
|
+
* MIME type the script declares for a file result (SKILL.md `output_mime`).
|
|
366
|
+
* Used only when the script writes a file to `ELISYM_OUTPUT_FILE`; becomes the
|
|
367
|
+
* iroh attachment's mime. Defaults to `application/octet-stream`.
|
|
368
|
+
*/
|
|
369
|
+
outputMime?: string;
|
|
345
370
|
}
|
|
346
371
|
/**
|
|
347
372
|
* Pipes the user's job input to the script's stdin and returns its
|
|
@@ -363,6 +388,7 @@ declare class DynamicScriptSkill implements Skill {
|
|
|
363
388
|
private scriptArgs;
|
|
364
389
|
private scriptTimeoutMs?;
|
|
365
390
|
private scriptEnv?;
|
|
391
|
+
private outputMime?;
|
|
366
392
|
constructor(params: DynamicScriptSkillParams);
|
|
367
393
|
execute(input: SkillInput, ctx: SkillContext): Promise<SkillOutput>;
|
|
368
394
|
}
|
|
@@ -411,6 +437,20 @@ interface SkillFrontmatter {
|
|
|
411
437
|
script_args?: unknown;
|
|
412
438
|
/** Optional override of `DEFAULT_SCRIPT_TIMEOUT_MS`. */
|
|
413
439
|
script_timeout_ms?: unknown;
|
|
440
|
+
/**
|
|
441
|
+
* MIME type for a file result. Only valid in mode 'dynamic-script' (the only
|
|
442
|
+
* mode that can emit a file via `ELISYM_OUTPUT_FILE`). Becomes the iroh
|
|
443
|
+
* attachment's mime; defaults to `application/octet-stream` when omitted.
|
|
444
|
+
*/
|
|
445
|
+
output_mime?: unknown;
|
|
446
|
+
/**
|
|
447
|
+
* MIME the skill expects as a file input. Only valid in mode 'dynamic-script'
|
|
448
|
+
* (the only mode that receives a file via `ELISYM_INPUT_FILE`). Discovery hint
|
|
449
|
+
* only - the runtime still content-sniffs the actual file and does not enforce
|
|
450
|
+
* this. Convention: `*` = any file, `image/*` = any image, `image/png` =
|
|
451
|
+
* exact. Its presence signals "this capability needs a file input".
|
|
452
|
+
*/
|
|
453
|
+
input_mime?: unknown;
|
|
414
454
|
/**
|
|
415
455
|
* Optional per-skill rate limit. Applies to any skill mode. Snake-case
|
|
416
456
|
* keys here match the YAML frontmatter convention; parsed into camelCase
|
|
@@ -455,6 +495,14 @@ interface ParsedSkill {
|
|
|
455
495
|
scriptArgs: string[];
|
|
456
496
|
/** Undefined => caller uses `DEFAULT_SCRIPT_TIMEOUT_MS`. */
|
|
457
497
|
scriptTimeoutMs?: number;
|
|
498
|
+
/** MIME for a file result (mode 'dynamic-script' only). */
|
|
499
|
+
outputMime?: string;
|
|
500
|
+
/**
|
|
501
|
+
* MIME the skill expects as a file input (mode 'dynamic-script' only).
|
|
502
|
+
* Discovery hint only; not enforced at runtime. Presence signals the
|
|
503
|
+
* capability needs a file input (clients gate file-only flows on it).
|
|
504
|
+
*/
|
|
505
|
+
inputMime?: string;
|
|
458
506
|
/** Optional per-skill rate limit (any mode). */
|
|
459
507
|
rateLimit?: SkillRateLimit;
|
|
460
508
|
/**
|
package/dist/skills.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { A as Asset } from './assets-C-nzSYD4.js';
|
|
2
|
-
import { S as SkillRateLimit } from './types-
|
|
2
|
+
import { S as SkillRateLimit } from './types-CqN9kFTn.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Shared SKILL.md runtime types. A skill is a markdown document whose
|
|
@@ -12,10 +12,29 @@ interface SkillInput {
|
|
|
12
12
|
inputType: string;
|
|
13
13
|
tags: string[];
|
|
14
14
|
jobId: string;
|
|
15
|
+
/**
|
|
16
|
+
* Local path to a file input fetched out-of-band (P2P via iroh), when the job
|
|
17
|
+
* carried a file attachment. The runtime fetches it after payment and removes
|
|
18
|
+
* it after execution; the skill reads from disk rather than from `data`.
|
|
19
|
+
*/
|
|
20
|
+
filePath?: string;
|
|
15
21
|
}
|
|
16
22
|
interface SkillOutput {
|
|
17
23
|
data: string;
|
|
18
24
|
outputMime?: string;
|
|
25
|
+
/**
|
|
26
|
+
* Local path to a file result. When set, the runtime seeds the file via iroh
|
|
27
|
+
* and the customer fetches it out-of-band; `data` carries any text note (or '').
|
|
28
|
+
* `outputMime` is reused as the attachment's mime.
|
|
29
|
+
*/
|
|
30
|
+
filePath?: string;
|
|
31
|
+
/**
|
|
32
|
+
* Releases the resources backing `filePath` (e.g. a temp dir). The runtime
|
|
33
|
+
* calls it once it has seeded the file - or failed to - since seeding happens
|
|
34
|
+
* after `execute()` returns and the producer cannot release the file itself.
|
|
35
|
+
* Mirrors the input-side cleanup callback in the runtime's `resolveInputFile`.
|
|
36
|
+
*/
|
|
37
|
+
cleanup?: () => Promise<void>;
|
|
19
38
|
}
|
|
20
39
|
/**
|
|
21
40
|
* Optional per-skill LLM override declared in SKILL.md frontmatter.
|
|
@@ -342,6 +361,12 @@ interface DynamicScriptSkillParams {
|
|
|
342
361
|
* itself reads the key from its environment.
|
|
343
362
|
*/
|
|
344
363
|
llmOverride?: SkillLlmOverride;
|
|
364
|
+
/**
|
|
365
|
+
* MIME type the script declares for a file result (SKILL.md `output_mime`).
|
|
366
|
+
* Used only when the script writes a file to `ELISYM_OUTPUT_FILE`; becomes the
|
|
367
|
+
* iroh attachment's mime. Defaults to `application/octet-stream`.
|
|
368
|
+
*/
|
|
369
|
+
outputMime?: string;
|
|
345
370
|
}
|
|
346
371
|
/**
|
|
347
372
|
* Pipes the user's job input to the script's stdin and returns its
|
|
@@ -363,6 +388,7 @@ declare class DynamicScriptSkill implements Skill {
|
|
|
363
388
|
private scriptArgs;
|
|
364
389
|
private scriptTimeoutMs?;
|
|
365
390
|
private scriptEnv?;
|
|
391
|
+
private outputMime?;
|
|
366
392
|
constructor(params: DynamicScriptSkillParams);
|
|
367
393
|
execute(input: SkillInput, ctx: SkillContext): Promise<SkillOutput>;
|
|
368
394
|
}
|
|
@@ -411,6 +437,20 @@ interface SkillFrontmatter {
|
|
|
411
437
|
script_args?: unknown;
|
|
412
438
|
/** Optional override of `DEFAULT_SCRIPT_TIMEOUT_MS`. */
|
|
413
439
|
script_timeout_ms?: unknown;
|
|
440
|
+
/**
|
|
441
|
+
* MIME type for a file result. Only valid in mode 'dynamic-script' (the only
|
|
442
|
+
* mode that can emit a file via `ELISYM_OUTPUT_FILE`). Becomes the iroh
|
|
443
|
+
* attachment's mime; defaults to `application/octet-stream` when omitted.
|
|
444
|
+
*/
|
|
445
|
+
output_mime?: unknown;
|
|
446
|
+
/**
|
|
447
|
+
* MIME the skill expects as a file input. Only valid in mode 'dynamic-script'
|
|
448
|
+
* (the only mode that receives a file via `ELISYM_INPUT_FILE`). Discovery hint
|
|
449
|
+
* only - the runtime still content-sniffs the actual file and does not enforce
|
|
450
|
+
* this. Convention: `*` = any file, `image/*` = any image, `image/png` =
|
|
451
|
+
* exact. Its presence signals "this capability needs a file input".
|
|
452
|
+
*/
|
|
453
|
+
input_mime?: unknown;
|
|
414
454
|
/**
|
|
415
455
|
* Optional per-skill rate limit. Applies to any skill mode. Snake-case
|
|
416
456
|
* keys here match the YAML frontmatter convention; parsed into camelCase
|
|
@@ -455,6 +495,14 @@ interface ParsedSkill {
|
|
|
455
495
|
scriptArgs: string[];
|
|
456
496
|
/** Undefined => caller uses `DEFAULT_SCRIPT_TIMEOUT_MS`. */
|
|
457
497
|
scriptTimeoutMs?: number;
|
|
498
|
+
/** MIME for a file result (mode 'dynamic-script' only). */
|
|
499
|
+
outputMime?: string;
|
|
500
|
+
/**
|
|
501
|
+
* MIME the skill expects as a file input (mode 'dynamic-script' only).
|
|
502
|
+
* Discovery hint only; not enforced at runtime. Presence signals the
|
|
503
|
+
* capability needs a file input (clients gate file-only flows on it).
|
|
504
|
+
*/
|
|
505
|
+
inputMime?: string;
|
|
458
506
|
/** Optional per-skill rate limit (any mode). */
|
|
459
507
|
rateLimit?: SkillRateLimit;
|
|
460
508
|
/**
|
package/dist/skills.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { spawn } from 'node:child_process';
|
|
2
2
|
import { StringDecoder } from 'node:string_decoder';
|
|
3
|
-
import { readFile } from 'node:fs/promises';
|
|
4
|
-
import { dirname, resolve, relative, sep
|
|
3
|
+
import { readFile, mkdtemp, stat, rm } from 'node:fs/promises';
|
|
4
|
+
import { dirname, join, resolve, relative, sep } from 'node:path';
|
|
5
|
+
import { tmpdir } from 'node:os';
|
|
5
6
|
import { readdirSync, statSync, readFileSync } from 'node:fs';
|
|
6
7
|
import YAML from 'yaml';
|
|
7
8
|
import Decimal from 'decimal.js-light';
|
|
@@ -345,6 +346,7 @@ var DynamicScriptSkill = class {
|
|
|
345
346
|
scriptArgs;
|
|
346
347
|
scriptTimeoutMs;
|
|
347
348
|
scriptEnv;
|
|
349
|
+
outputMime;
|
|
348
350
|
constructor(params) {
|
|
349
351
|
this.name = params.name;
|
|
350
352
|
this.description = params.description;
|
|
@@ -358,35 +360,65 @@ var DynamicScriptSkill = class {
|
|
|
358
360
|
this.scriptArgs = params.scriptArgs;
|
|
359
361
|
this.scriptTimeoutMs = params.scriptTimeoutMs;
|
|
360
362
|
this.scriptEnv = params.scriptEnv;
|
|
363
|
+
this.outputMime = params.outputMime;
|
|
361
364
|
}
|
|
362
365
|
async execute(input, ctx) {
|
|
363
|
-
const
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
throw new ScriptExecutionError(
|
|
372
|
-
null,
|
|
373
|
-
result.spawnError.message,
|
|
374
|
-
"script could not be started"
|
|
375
|
-
);
|
|
376
|
-
}
|
|
377
|
-
if (result.code === SCRIPT_EXIT_BILLING_EXHAUSTED) {
|
|
378
|
-
throw new ScriptBillingExhaustedError(result.code, result.stdout, result.stderr);
|
|
379
|
-
}
|
|
380
|
-
if (result.code !== 0) {
|
|
381
|
-
const detail = result.stderr.trim() || result.stdout.trim() || "(no output)";
|
|
382
|
-
throw new ScriptExecutionError(result.code, detail);
|
|
366
|
+
const outDir = await mkdtemp(join(tmpdir(), "elisym-skill-out-"));
|
|
367
|
+
const outputFile = join(outDir, "output");
|
|
368
|
+
const env = {
|
|
369
|
+
...this.scriptEnv ?? process.env,
|
|
370
|
+
ELISYM_OUTPUT_FILE: outputFile
|
|
371
|
+
};
|
|
372
|
+
if (input.filePath !== void 0) {
|
|
373
|
+
env.ELISYM_INPUT_FILE = input.filePath;
|
|
383
374
|
}
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
const
|
|
387
|
-
|
|
375
|
+
let keepOutDir = false;
|
|
376
|
+
try {
|
|
377
|
+
const result = await runScript(this.scriptPath, this.scriptArgs, {
|
|
378
|
+
cwd: dirname(this.scriptPath),
|
|
379
|
+
stdin: input.data,
|
|
380
|
+
signal: ctx.signal,
|
|
381
|
+
timeoutMs: this.scriptTimeoutMs,
|
|
382
|
+
env
|
|
383
|
+
});
|
|
384
|
+
if (result.spawnError) {
|
|
385
|
+
throw new ScriptExecutionError(
|
|
386
|
+
null,
|
|
387
|
+
result.spawnError.message,
|
|
388
|
+
"script could not be started"
|
|
389
|
+
);
|
|
390
|
+
}
|
|
391
|
+
if (result.code === SCRIPT_EXIT_BILLING_EXHAUSTED) {
|
|
392
|
+
throw new ScriptBillingExhaustedError(result.code, result.stdout, result.stderr);
|
|
393
|
+
}
|
|
394
|
+
if (result.code !== 0) {
|
|
395
|
+
const detail = result.stderr.trim() || result.stdout.trim() || "(no output)";
|
|
396
|
+
throw new ScriptExecutionError(result.code, detail);
|
|
397
|
+
}
|
|
398
|
+
const outputStat = await stat(outputFile).catch(() => null);
|
|
399
|
+
if (outputStat !== null && outputStat.isFile() && outputStat.size > 0) {
|
|
400
|
+
keepOutDir = true;
|
|
401
|
+
return {
|
|
402
|
+
data: result.stdout.trim(),
|
|
403
|
+
filePath: outputFile,
|
|
404
|
+
outputMime: this.outputMime ?? "application/octet-stream",
|
|
405
|
+
cleanup: async () => {
|
|
406
|
+
await rm(outDir, { recursive: true, force: true });
|
|
407
|
+
}
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
const output = result.stdout.trim();
|
|
411
|
+
if (output === "") {
|
|
412
|
+
const detail = result.stderr.trim() || "(no stderr)";
|
|
413
|
+
throw new ScriptExecutionError(result.code, detail, "script produced empty output");
|
|
414
|
+
}
|
|
415
|
+
return { data: output };
|
|
416
|
+
} finally {
|
|
417
|
+
if (!keepOutDir) {
|
|
418
|
+
await rm(outDir, { recursive: true, force: true }).catch(() => {
|
|
419
|
+
});
|
|
420
|
+
}
|
|
388
421
|
}
|
|
389
|
-
return { data: output };
|
|
390
422
|
}
|
|
391
423
|
};
|
|
392
424
|
function resolveInsidePath(rootDir, value) {
|
|
@@ -404,6 +436,7 @@ var LIMITS = {
|
|
|
404
436
|
// hours, so this exists only to keep `secs * 1000` within Node's setTimeout limit
|
|
405
437
|
// (2_147_483_647 ms) - a larger value overflows and fires the timer immediately.
|
|
406
438
|
MAX_EXECUTION_SECS: 2147483};
|
|
439
|
+
new TextEncoder();
|
|
407
440
|
var NATIVE_SOL = {
|
|
408
441
|
chain: "solana",
|
|
409
442
|
token: "sol",
|
|
@@ -701,6 +734,34 @@ function validateScriptTimeoutMs(skillName, raw) {
|
|
|
701
734
|
}
|
|
702
735
|
return raw;
|
|
703
736
|
}
|
|
737
|
+
function validateOutputMime(skillName, raw) {
|
|
738
|
+
if (raw === void 0 || raw === null) {
|
|
739
|
+
return void 0;
|
|
740
|
+
}
|
|
741
|
+
if (typeof raw !== "string" || raw.length === 0) {
|
|
742
|
+
throw new Error(
|
|
743
|
+
`SKILL.md "${skillName}": "output_mime" must be a non-empty string (e.g. "image/png")`
|
|
744
|
+
);
|
|
745
|
+
}
|
|
746
|
+
if (raw.length > 255) {
|
|
747
|
+
throw new Error(`SKILL.md "${skillName}": "output_mime" too long (max 255 chars)`);
|
|
748
|
+
}
|
|
749
|
+
return raw;
|
|
750
|
+
}
|
|
751
|
+
function validateInputMime(skillName, raw) {
|
|
752
|
+
if (raw === void 0 || raw === null) {
|
|
753
|
+
return void 0;
|
|
754
|
+
}
|
|
755
|
+
if (typeof raw !== "string" || raw.length === 0) {
|
|
756
|
+
throw new Error(
|
|
757
|
+
`SKILL.md "${skillName}": "input_mime" must be a non-empty string (e.g. "image/png" or "*")`
|
|
758
|
+
);
|
|
759
|
+
}
|
|
760
|
+
if (raw.length > 255) {
|
|
761
|
+
throw new Error(`SKILL.md "${skillName}": "input_mime" too long (max 255 chars)`);
|
|
762
|
+
}
|
|
763
|
+
return raw;
|
|
764
|
+
}
|
|
704
765
|
function validateMaxExecutionSecs(skillName, raw) {
|
|
705
766
|
if (raw === void 0 || raw === null) {
|
|
706
767
|
return void 0;
|
|
@@ -801,6 +862,8 @@ function validateSkillFrontmatter(frontmatter, systemPrompt, options = {}) {
|
|
|
801
862
|
let script;
|
|
802
863
|
let scriptArgs = [];
|
|
803
864
|
let scriptTimeoutMs;
|
|
865
|
+
let outputMime;
|
|
866
|
+
let inputMime;
|
|
804
867
|
if (mode === "static-file") {
|
|
805
868
|
if (typeof frontmatter.output_file !== "string" || frontmatter.output_file.length === 0) {
|
|
806
869
|
throw new Error(
|
|
@@ -812,6 +875,16 @@ function validateSkillFrontmatter(frontmatter, systemPrompt, options = {}) {
|
|
|
812
875
|
`SKILL.md "${frontmatter.name}": "script" is not valid in mode 'static-file'`
|
|
813
876
|
);
|
|
814
877
|
}
|
|
878
|
+
if (frontmatter.output_mime !== void 0) {
|
|
879
|
+
throw new Error(
|
|
880
|
+
`SKILL.md "${frontmatter.name}": "output_mime" is only valid in mode 'dynamic-script'`
|
|
881
|
+
);
|
|
882
|
+
}
|
|
883
|
+
if (frontmatter.input_mime !== void 0) {
|
|
884
|
+
throw new Error(
|
|
885
|
+
`SKILL.md "${frontmatter.name}": "input_mime" is only valid in mode 'dynamic-script'`
|
|
886
|
+
);
|
|
887
|
+
}
|
|
815
888
|
outputFile = frontmatter.output_file;
|
|
816
889
|
} else if (mode === "static-script" || mode === "dynamic-script") {
|
|
817
890
|
if (typeof frontmatter.script !== "string" || frontmatter.script.length === 0) {
|
|
@@ -825,6 +898,21 @@ function validateSkillFrontmatter(frontmatter, systemPrompt, options = {}) {
|
|
|
825
898
|
script = frontmatter.script;
|
|
826
899
|
scriptArgs = validateScriptArgs(frontmatter.name, frontmatter.script_args);
|
|
827
900
|
scriptTimeoutMs = validateScriptTimeoutMs(frontmatter.name, frontmatter.script_timeout_ms);
|
|
901
|
+
if (mode === "dynamic-script") {
|
|
902
|
+
outputMime = validateOutputMime(frontmatter.name, frontmatter.output_mime);
|
|
903
|
+
inputMime = validateInputMime(frontmatter.name, frontmatter.input_mime);
|
|
904
|
+
} else {
|
|
905
|
+
if (frontmatter.output_mime !== void 0) {
|
|
906
|
+
throw new Error(
|
|
907
|
+
`SKILL.md "${frontmatter.name}": "output_mime" is only valid in mode 'dynamic-script'`
|
|
908
|
+
);
|
|
909
|
+
}
|
|
910
|
+
if (frontmatter.input_mime !== void 0) {
|
|
911
|
+
throw new Error(
|
|
912
|
+
`SKILL.md "${frontmatter.name}": "input_mime" is only valid in mode 'dynamic-script'`
|
|
913
|
+
);
|
|
914
|
+
}
|
|
915
|
+
}
|
|
828
916
|
} else {
|
|
829
917
|
if (frontmatter.output_file !== void 0) {
|
|
830
918
|
throw new Error(
|
|
@@ -846,6 +934,16 @@ function validateSkillFrontmatter(frontmatter, systemPrompt, options = {}) {
|
|
|
846
934
|
`SKILL.md "${frontmatter.name}": "script_timeout_ms" is only valid in script modes`
|
|
847
935
|
);
|
|
848
936
|
}
|
|
937
|
+
if (frontmatter.output_mime !== void 0) {
|
|
938
|
+
throw new Error(
|
|
939
|
+
`SKILL.md "${frontmatter.name}": "output_mime" is only valid in mode 'dynamic-script'`
|
|
940
|
+
);
|
|
941
|
+
}
|
|
942
|
+
if (frontmatter.input_mime !== void 0) {
|
|
943
|
+
throw new Error(
|
|
944
|
+
`SKILL.md "${frontmatter.name}": "input_mime" is only valid in mode 'dynamic-script'`
|
|
945
|
+
);
|
|
946
|
+
}
|
|
849
947
|
}
|
|
850
948
|
const image = typeof frontmatter.image === "string" ? frontmatter.image : void 0;
|
|
851
949
|
const imageFile = typeof frontmatter.image_file === "string" ? frontmatter.image_file : void 0;
|
|
@@ -872,6 +970,8 @@ function validateSkillFrontmatter(frontmatter, systemPrompt, options = {}) {
|
|
|
872
970
|
script,
|
|
873
971
|
scriptArgs,
|
|
874
972
|
scriptTimeoutMs,
|
|
973
|
+
outputMime,
|
|
974
|
+
inputMime,
|
|
875
975
|
rateLimit,
|
|
876
976
|
executionTimeoutSecs
|
|
877
977
|
};
|
|
@@ -937,8 +1037,7 @@ function buildSkillFromParsed(parsed, skillDir, logger) {
|
|
|
937
1037
|
if (!scriptPath) {
|
|
938
1038
|
throw new Error(`SKILL.md "${parsed.name}": "script" must stay inside the skill directory`);
|
|
939
1039
|
}
|
|
940
|
-
const
|
|
941
|
-
return new Ctor({
|
|
1040
|
+
const scriptParams = {
|
|
942
1041
|
name: parsed.name,
|
|
943
1042
|
description: parsed.description,
|
|
944
1043
|
capabilities: parsed.capabilities,
|
|
@@ -950,7 +1049,8 @@ function buildSkillFromParsed(parsed, skillDir, logger) {
|
|
|
950
1049
|
image: parsed.image,
|
|
951
1050
|
imageFile,
|
|
952
1051
|
llmOverride: parsed.llmOverride
|
|
953
|
-
}
|
|
1052
|
+
};
|
|
1053
|
+
return parsed.mode === "dynamic-script" ? new DynamicScriptSkill({ ...scriptParams, outputMime: parsed.outputMime }) : new StaticScriptSkill(scriptParams);
|
|
954
1054
|
}
|
|
955
1055
|
}
|
|
956
1056
|
}
|