@elisym/sdk 0.12.4 → 0.13.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.d.cts CHANGED
@@ -16,12 +16,42 @@ interface SkillOutput {
16
16
  data: string;
17
17
  outputMime?: string;
18
18
  }
19
+ /**
20
+ * Optional per-skill LLM override declared in SKILL.md frontmatter.
21
+ *
22
+ * Parse-time invariant (enforced by `validateLlmOverride` in the loader):
23
+ * `provider` is set iff `model` is set. `maxTokens` is independent. So
24
+ * downstream code may rely on: when `provider !== undefined`, `model` is
25
+ * also defined.
26
+ */
27
+ interface SkillLlmOverride {
28
+ provider?: 'anthropic' | 'openai';
29
+ model?: string;
30
+ maxTokens?: number;
31
+ }
19
32
  interface SkillContext {
33
+ /** Agent-default LLM client. May be undefined when every LLM skill overrides. */
20
34
  llm?: LlmClient;
35
+ /**
36
+ * Resolve the LLM client for a skill. The runtime caches clients by
37
+ * resolved (provider, model, maxTokens) triple. Callers pass their
38
+ * `llmOverride` (or undefined for the agent default).
39
+ */
40
+ getLlm?: (override?: SkillLlmOverride) => LlmClient | undefined;
21
41
  agentName: string;
22
42
  agentDescription: string;
23
43
  signal?: AbortSignal;
24
44
  }
45
+ /**
46
+ * How the runtime produces a result for a job:
47
+ * - `llm`: feed input through Anthropic/OpenAI with the skill's system prompt (default).
48
+ * - `static-file`: return the contents of a fixed file. No input required.
49
+ * - `static-script`: spawn a script with no stdin. No input required.
50
+ * - `dynamic-script`: spawn a script and pipe the user's input to stdin.
51
+ *
52
+ * Static modes set `card.static = true` so the webapp hides its input box.
53
+ */
54
+ type SkillMode = 'llm' | 'static-file' | 'static-script' | 'dynamic-script';
25
55
  interface ToolDef {
26
56
  name: string;
27
57
  description: string;
@@ -61,6 +91,14 @@ interface Skill {
61
91
  priceSubunits: bigint;
62
92
  /** Asset the price is denominated in (NATIVE_SOL or USDC_SOLANA_DEVNET, etc.). */
63
93
  asset: Asset;
94
+ /** Execution mode. Default 'llm' for back-compat. */
95
+ mode: SkillMode;
96
+ /**
97
+ * Optional per-skill LLM config override (only set when mode === 'llm').
98
+ * Carried through from SKILL.md frontmatter so the runtime can route this
99
+ * skill to a non-default model/provider/max_tokens.
100
+ */
101
+ llmOverride?: SkillLlmOverride;
64
102
  image?: string;
65
103
  imageFile?: string;
66
104
  execute(input: SkillInput, ctx: SkillContext): Promise<SkillOutput>;
@@ -77,6 +115,8 @@ declare function createAnthropicClient(config: Omit<LlmClientConfig, 'provider'>
77
115
  declare function createOpenAIClient(config: Omit<LlmClientConfig, 'provider'>): LlmClient;
78
116
  declare function createLlmClient(config: LlmClientConfig): LlmClient;
79
117
 
118
+ declare const MAX_SCRIPT_OUTPUT = 1000000;
119
+ declare const DEFAULT_SCRIPT_TIMEOUT_MS = 60000;
80
120
  interface SkillToolDef {
81
121
  name: string;
82
122
  description: string;
@@ -90,6 +130,35 @@ interface SkillToolDef {
90
130
  interface ScriptSkillLogger {
91
131
  debug?(obj: Record<string, unknown>, msg?: string): void;
92
132
  }
133
+ interface RunScriptOptions {
134
+ cwd: string;
135
+ /**
136
+ * UTF-8 string written to the child's stdin, then stdin closed.
137
+ * When undefined, stdin is closed immediately (EOF) so that children
138
+ * which read stdin do not block until `timeoutMs`.
139
+ */
140
+ stdin?: string;
141
+ /** Cancel the spawn. SIGKILL is sent on abort. */
142
+ signal?: AbortSignal;
143
+ /** Hard timeout in ms. Default `DEFAULT_SCRIPT_TIMEOUT_MS`. */
144
+ timeoutMs?: number;
145
+ /** Cap on stdout/stderr capture. Default `MAX_SCRIPT_OUTPUT`. */
146
+ maxOutput?: number;
147
+ }
148
+ interface RunScriptResult {
149
+ stdout: string;
150
+ stderr: string;
151
+ /** Null when the process was killed by signal before exiting. */
152
+ code: number | null;
153
+ /** Set when spawn itself failed (ENOENT, EACCES, etc.). */
154
+ spawnError?: Error;
155
+ }
156
+ /**
157
+ * Spawn `cmd` with `args` and capture stdout/stderr. Never uses `shell: true`,
158
+ * so shell metacharacters in arguments are safe. Caller is responsible for
159
+ * checking `code === 0` / interpreting `spawnError`.
160
+ */
161
+ declare function runScript(cmd: string, args: string[], opts: RunScriptOptions): Promise<RunScriptResult>;
93
162
  interface ScriptSkillParams {
94
163
  name: string;
95
164
  description: string;
@@ -100,6 +169,8 @@ interface ScriptSkillParams {
100
169
  systemPrompt: string;
101
170
  tools: SkillToolDef[];
102
171
  maxToolRounds: number;
172
+ /** Optional per-skill LLM override (provider/model pair and/or maxTokens). */
173
+ llmOverride?: SkillLlmOverride;
103
174
  image?: string;
104
175
  imageFile?: string;
105
176
  logger?: ScriptSkillLogger;
@@ -117,6 +188,8 @@ declare class ScriptSkill implements Skill {
117
188
  capabilities: string[];
118
189
  priceSubunits: bigint;
119
190
  asset: Asset;
191
+ mode: SkillMode;
192
+ readonly llmOverride?: SkillLlmOverride;
120
193
  image?: string;
121
194
  imageFile?: string;
122
195
  private skillDir;
@@ -126,9 +199,137 @@ declare class ScriptSkill implements Skill {
126
199
  private logger;
127
200
  constructor(params: ScriptSkillParams);
128
201
  execute(input: SkillInput, ctx: SkillContext): Promise<SkillOutput>;
202
+ /**
203
+ * Resolve the LLM client for this skill from the runtime context.
204
+ *
205
+ * Contract:
206
+ * - When `llmOverride` is set, `ctx.getLlm` MUST be wired. Falling back to
207
+ * `ctx.llm` (the agent default) would silently use the wrong configuration
208
+ * for max-tokens-only overrides.
209
+ * - When no override is set, prefer `ctx.getLlm()` (returns the agent
210
+ * default), then fall back to `ctx.llm` for legacy callers that wire only
211
+ * a single client.
212
+ */
213
+ private resolveLlmClient;
129
214
  private runTool;
130
215
  }
131
216
 
217
+ /** Hard ceiling on result size for static-file skills. NIP-90 result events
218
+ * travel through relays that may reject very large payloads; cap at 256 KB
219
+ * of UTF-8. Larger files should use a script that streams to an external host. */
220
+ declare const MAX_STATIC_FILE_SIZE: number;
221
+ interface StaticFileSkillParams {
222
+ name: string;
223
+ description: string;
224
+ capabilities: string[];
225
+ priceSubunits: bigint;
226
+ asset: Asset;
227
+ /** Absolute path to the file whose contents are returned on each job. */
228
+ outputFilePath: string;
229
+ image?: string;
230
+ imageFile?: string;
231
+ }
232
+ /**
233
+ * Returns the contents of a fixed file as the job result. Reads on every
234
+ * `execute()` so authors can edit the file without restarting the agent.
235
+ */
236
+ declare class StaticFileSkill implements Skill {
237
+ name: string;
238
+ description: string;
239
+ capabilities: string[];
240
+ priceSubunits: bigint;
241
+ asset: Asset;
242
+ mode: SkillMode;
243
+ image?: string;
244
+ imageFile?: string;
245
+ private outputFilePath;
246
+ constructor(params: StaticFileSkillParams);
247
+ execute(_input: SkillInput, _ctx: SkillContext): Promise<SkillOutput>;
248
+ }
249
+
250
+ interface StaticScriptSkillParams {
251
+ name: string;
252
+ description: string;
253
+ capabilities: string[];
254
+ priceSubunits: bigint;
255
+ asset: Asset;
256
+ /** Absolute path to the script. */
257
+ scriptPath: string;
258
+ /** Extra args appended after the script path. */
259
+ scriptArgs: string[];
260
+ /** Optional override of the default 60s timeout. */
261
+ scriptTimeoutMs?: number;
262
+ image?: string;
263
+ imageFile?: string;
264
+ }
265
+ /**
266
+ * Spawns a configured script with no stdin and returns its trimmed stdout.
267
+ * Throws on non-zero exit so the runtime surfaces a sanitized error.
268
+ * The script runs with cwd set to its containing directory so relative
269
+ * paths inside the script behave intuitively.
270
+ */
271
+ declare class StaticScriptSkill implements Skill {
272
+ name: string;
273
+ description: string;
274
+ capabilities: string[];
275
+ priceSubunits: bigint;
276
+ asset: Asset;
277
+ mode: SkillMode;
278
+ image?: string;
279
+ imageFile?: string;
280
+ private scriptPath;
281
+ private scriptArgs;
282
+ private scriptTimeoutMs?;
283
+ constructor(params: StaticScriptSkillParams);
284
+ execute(_input: SkillInput, ctx: SkillContext): Promise<SkillOutput>;
285
+ }
286
+
287
+ interface DynamicScriptSkillParams {
288
+ name: string;
289
+ description: string;
290
+ capabilities: string[];
291
+ priceSubunits: bigint;
292
+ asset: Asset;
293
+ /** Absolute path to the script. */
294
+ scriptPath: string;
295
+ /** Extra args appended after the script path. */
296
+ scriptArgs: string[];
297
+ /** Optional override of the default 60s timeout. */
298
+ scriptTimeoutMs?: number;
299
+ image?: string;
300
+ imageFile?: string;
301
+ }
302
+ /**
303
+ * Pipes the user's job input to the script's stdin and returns its
304
+ * trimmed stdout. Enables script-backed capabilities (proxies to
305
+ * external models, classical NLP, custom workers) without an LLM key
306
+ * on the elisym side.
307
+ */
308
+ declare class DynamicScriptSkill implements Skill {
309
+ name: string;
310
+ description: string;
311
+ capabilities: string[];
312
+ priceSubunits: bigint;
313
+ asset: Asset;
314
+ mode: SkillMode;
315
+ image?: string;
316
+ imageFile?: string;
317
+ private scriptPath;
318
+ private scriptArgs;
319
+ private scriptTimeoutMs?;
320
+ constructor(params: DynamicScriptSkillParams);
321
+ execute(input: SkillInput, ctx: SkillContext): Promise<SkillOutput>;
322
+ }
323
+
324
+ /**
325
+ * Resolve `value` relative to `rootDir` and reject anything that escapes
326
+ * the root (`..` segments, absolute paths outside it, or the root itself).
327
+ *
328
+ * Returns the absolute path on success, or null on rejection so callers
329
+ * can surface a precise error message.
330
+ */
331
+ declare function resolveInsidePath(rootDir: string, value: string): string | null;
332
+
132
333
  declare const DEFAULT_MAX_TOOL_ROUNDS = 10;
133
334
  interface SkillFrontmatter {
134
335
  name?: unknown;
@@ -143,6 +344,22 @@ interface SkillFrontmatter {
143
344
  image_file?: unknown;
144
345
  tools?: unknown;
145
346
  max_tool_rounds?: unknown;
347
+ /** Optional per-skill LLM provider override ('anthropic' | 'openai'). Pairs with `model`. */
348
+ provider?: unknown;
349
+ /** Optional per-skill LLM model override. Pairs with `provider`. */
350
+ model?: unknown;
351
+ /** Optional per-skill max_tokens override. Independent of provider/model. */
352
+ max_tokens?: unknown;
353
+ /** Execution mode. Default 'llm'. */
354
+ mode?: unknown;
355
+ /** Required when mode === 'static-file'. Path relative to skill dir. */
356
+ output_file?: unknown;
357
+ /** Required when mode === 'static-script' | 'dynamic-script'. Path relative to skill dir. */
358
+ script?: unknown;
359
+ /** Optional positional args appended after the script. */
360
+ script_args?: unknown;
361
+ /** Optional override of `DEFAULT_SCRIPT_TIMEOUT_MS`. */
362
+ script_timeout_ms?: unknown;
146
363
  }
147
364
  interface ParsedSkill {
148
365
  name: string;
@@ -151,11 +368,26 @@ interface ParsedSkill {
151
368
  /** Price in subunits of `asset`. */
152
369
  priceSubunits: bigint;
153
370
  asset: Asset;
371
+ mode: SkillMode;
154
372
  systemPrompt: string;
155
373
  tools: SkillToolDef[];
156
374
  maxToolRounds: number;
375
+ /**
376
+ * Per-skill LLM override (only present when mode === 'llm' and the SKILL.md
377
+ * declared at least one of `provider`/`model`/`max_tokens`). Parse-time
378
+ * invariant: `provider` set iff `model` set.
379
+ */
380
+ llmOverride?: SkillLlmOverride;
157
381
  image?: string;
158
382
  imageFile?: string;
383
+ /** Set when mode === 'static-file'. */
384
+ outputFile?: string;
385
+ /** Set when mode is a script mode. */
386
+ script?: string;
387
+ /** Empty when no script. */
388
+ scriptArgs: string[];
389
+ /** Undefined => caller uses `DEFAULT_SCRIPT_TIMEOUT_MS`. */
390
+ scriptTimeoutMs?: number;
159
391
  }
160
392
  interface LoaderLogger {
161
393
  debug?(obj: Record<string, unknown>, msg?: string): void;
@@ -177,9 +409,9 @@ declare function parseSkillMd(content: string): {
177
409
  declare function validateSkillFrontmatter(frontmatter: SkillFrontmatter, systemPrompt: string, options?: LoadSkillsOptions): ParsedSkill;
178
410
  /**
179
411
  * Walk `skillsDir`, load each immediate subdirectory's SKILL.md, and
180
- * return constructed `ScriptSkill` instances. Malformed directories are
181
- * skipped with a `warn` log.
412
+ * return constructed `Skill` instances (LLM or non-LLM depending on
413
+ * frontmatter `mode`). Malformed directories are skipped with a `warn` log.
182
414
  */
183
415
  declare function loadSkillsFromDir(skillsDir: string, options?: LoadSkillsOptions): Skill[];
184
416
 
185
- export { type CompletionResult, DEFAULT_MAX_TOOL_ROUNDS, type LlmClient, type LlmClientConfig, type LlmProvider, type LoadSkillsOptions, type LoaderLogger, type ParsedSkill, ScriptSkill, type ScriptSkillLogger, type ScriptSkillParams, type Skill, type SkillContext, type SkillFrontmatter, type SkillInput, type SkillOutput, type SkillToolDef, type ToolCall, type ToolDef, type ToolResult, createAnthropicClient, createLlmClient, createOpenAIClient, loadSkillsFromDir, parseSkillMd, validateSkillFrontmatter };
417
+ export { type CompletionResult, DEFAULT_MAX_TOOL_ROUNDS, DEFAULT_SCRIPT_TIMEOUT_MS, DynamicScriptSkill, type DynamicScriptSkillParams, type LlmClient, type LlmClientConfig, type LlmProvider, type LoadSkillsOptions, type LoaderLogger, MAX_SCRIPT_OUTPUT, MAX_STATIC_FILE_SIZE, type ParsedSkill, type RunScriptOptions, type RunScriptResult, ScriptSkill, type ScriptSkillLogger, type ScriptSkillParams, type Skill, type SkillContext, type SkillFrontmatter, type SkillInput, type SkillLlmOverride, type SkillMode, type SkillOutput, type SkillToolDef, StaticFileSkill, type StaticFileSkillParams, StaticScriptSkill, type StaticScriptSkillParams, type ToolCall, type ToolDef, type ToolResult, createAnthropicClient, createLlmClient, createOpenAIClient, loadSkillsFromDir, parseSkillMd, resolveInsidePath, runScript, validateSkillFrontmatter };
package/dist/skills.d.ts CHANGED
@@ -16,12 +16,42 @@ interface SkillOutput {
16
16
  data: string;
17
17
  outputMime?: string;
18
18
  }
19
+ /**
20
+ * Optional per-skill LLM override declared in SKILL.md frontmatter.
21
+ *
22
+ * Parse-time invariant (enforced by `validateLlmOverride` in the loader):
23
+ * `provider` is set iff `model` is set. `maxTokens` is independent. So
24
+ * downstream code may rely on: when `provider !== undefined`, `model` is
25
+ * also defined.
26
+ */
27
+ interface SkillLlmOverride {
28
+ provider?: 'anthropic' | 'openai';
29
+ model?: string;
30
+ maxTokens?: number;
31
+ }
19
32
  interface SkillContext {
33
+ /** Agent-default LLM client. May be undefined when every LLM skill overrides. */
20
34
  llm?: LlmClient;
35
+ /**
36
+ * Resolve the LLM client for a skill. The runtime caches clients by
37
+ * resolved (provider, model, maxTokens) triple. Callers pass their
38
+ * `llmOverride` (or undefined for the agent default).
39
+ */
40
+ getLlm?: (override?: SkillLlmOverride) => LlmClient | undefined;
21
41
  agentName: string;
22
42
  agentDescription: string;
23
43
  signal?: AbortSignal;
24
44
  }
45
+ /**
46
+ * How the runtime produces a result for a job:
47
+ * - `llm`: feed input through Anthropic/OpenAI with the skill's system prompt (default).
48
+ * - `static-file`: return the contents of a fixed file. No input required.
49
+ * - `static-script`: spawn a script with no stdin. No input required.
50
+ * - `dynamic-script`: spawn a script and pipe the user's input to stdin.
51
+ *
52
+ * Static modes set `card.static = true` so the webapp hides its input box.
53
+ */
54
+ type SkillMode = 'llm' | 'static-file' | 'static-script' | 'dynamic-script';
25
55
  interface ToolDef {
26
56
  name: string;
27
57
  description: string;
@@ -61,6 +91,14 @@ interface Skill {
61
91
  priceSubunits: bigint;
62
92
  /** Asset the price is denominated in (NATIVE_SOL or USDC_SOLANA_DEVNET, etc.). */
63
93
  asset: Asset;
94
+ /** Execution mode. Default 'llm' for back-compat. */
95
+ mode: SkillMode;
96
+ /**
97
+ * Optional per-skill LLM config override (only set when mode === 'llm').
98
+ * Carried through from SKILL.md frontmatter so the runtime can route this
99
+ * skill to a non-default model/provider/max_tokens.
100
+ */
101
+ llmOverride?: SkillLlmOverride;
64
102
  image?: string;
65
103
  imageFile?: string;
66
104
  execute(input: SkillInput, ctx: SkillContext): Promise<SkillOutput>;
@@ -77,6 +115,8 @@ declare function createAnthropicClient(config: Omit<LlmClientConfig, 'provider'>
77
115
  declare function createOpenAIClient(config: Omit<LlmClientConfig, 'provider'>): LlmClient;
78
116
  declare function createLlmClient(config: LlmClientConfig): LlmClient;
79
117
 
118
+ declare const MAX_SCRIPT_OUTPUT = 1000000;
119
+ declare const DEFAULT_SCRIPT_TIMEOUT_MS = 60000;
80
120
  interface SkillToolDef {
81
121
  name: string;
82
122
  description: string;
@@ -90,6 +130,35 @@ interface SkillToolDef {
90
130
  interface ScriptSkillLogger {
91
131
  debug?(obj: Record<string, unknown>, msg?: string): void;
92
132
  }
133
+ interface RunScriptOptions {
134
+ cwd: string;
135
+ /**
136
+ * UTF-8 string written to the child's stdin, then stdin closed.
137
+ * When undefined, stdin is closed immediately (EOF) so that children
138
+ * which read stdin do not block until `timeoutMs`.
139
+ */
140
+ stdin?: string;
141
+ /** Cancel the spawn. SIGKILL is sent on abort. */
142
+ signal?: AbortSignal;
143
+ /** Hard timeout in ms. Default `DEFAULT_SCRIPT_TIMEOUT_MS`. */
144
+ timeoutMs?: number;
145
+ /** Cap on stdout/stderr capture. Default `MAX_SCRIPT_OUTPUT`. */
146
+ maxOutput?: number;
147
+ }
148
+ interface RunScriptResult {
149
+ stdout: string;
150
+ stderr: string;
151
+ /** Null when the process was killed by signal before exiting. */
152
+ code: number | null;
153
+ /** Set when spawn itself failed (ENOENT, EACCES, etc.). */
154
+ spawnError?: Error;
155
+ }
156
+ /**
157
+ * Spawn `cmd` with `args` and capture stdout/stderr. Never uses `shell: true`,
158
+ * so shell metacharacters in arguments are safe. Caller is responsible for
159
+ * checking `code === 0` / interpreting `spawnError`.
160
+ */
161
+ declare function runScript(cmd: string, args: string[], opts: RunScriptOptions): Promise<RunScriptResult>;
93
162
  interface ScriptSkillParams {
94
163
  name: string;
95
164
  description: string;
@@ -100,6 +169,8 @@ interface ScriptSkillParams {
100
169
  systemPrompt: string;
101
170
  tools: SkillToolDef[];
102
171
  maxToolRounds: number;
172
+ /** Optional per-skill LLM override (provider/model pair and/or maxTokens). */
173
+ llmOverride?: SkillLlmOverride;
103
174
  image?: string;
104
175
  imageFile?: string;
105
176
  logger?: ScriptSkillLogger;
@@ -117,6 +188,8 @@ declare class ScriptSkill implements Skill {
117
188
  capabilities: string[];
118
189
  priceSubunits: bigint;
119
190
  asset: Asset;
191
+ mode: SkillMode;
192
+ readonly llmOverride?: SkillLlmOverride;
120
193
  image?: string;
121
194
  imageFile?: string;
122
195
  private skillDir;
@@ -126,9 +199,137 @@ declare class ScriptSkill implements Skill {
126
199
  private logger;
127
200
  constructor(params: ScriptSkillParams);
128
201
  execute(input: SkillInput, ctx: SkillContext): Promise<SkillOutput>;
202
+ /**
203
+ * Resolve the LLM client for this skill from the runtime context.
204
+ *
205
+ * Contract:
206
+ * - When `llmOverride` is set, `ctx.getLlm` MUST be wired. Falling back to
207
+ * `ctx.llm` (the agent default) would silently use the wrong configuration
208
+ * for max-tokens-only overrides.
209
+ * - When no override is set, prefer `ctx.getLlm()` (returns the agent
210
+ * default), then fall back to `ctx.llm` for legacy callers that wire only
211
+ * a single client.
212
+ */
213
+ private resolveLlmClient;
129
214
  private runTool;
130
215
  }
131
216
 
217
+ /** Hard ceiling on result size for static-file skills. NIP-90 result events
218
+ * travel through relays that may reject very large payloads; cap at 256 KB
219
+ * of UTF-8. Larger files should use a script that streams to an external host. */
220
+ declare const MAX_STATIC_FILE_SIZE: number;
221
+ interface StaticFileSkillParams {
222
+ name: string;
223
+ description: string;
224
+ capabilities: string[];
225
+ priceSubunits: bigint;
226
+ asset: Asset;
227
+ /** Absolute path to the file whose contents are returned on each job. */
228
+ outputFilePath: string;
229
+ image?: string;
230
+ imageFile?: string;
231
+ }
232
+ /**
233
+ * Returns the contents of a fixed file as the job result. Reads on every
234
+ * `execute()` so authors can edit the file without restarting the agent.
235
+ */
236
+ declare class StaticFileSkill implements Skill {
237
+ name: string;
238
+ description: string;
239
+ capabilities: string[];
240
+ priceSubunits: bigint;
241
+ asset: Asset;
242
+ mode: SkillMode;
243
+ image?: string;
244
+ imageFile?: string;
245
+ private outputFilePath;
246
+ constructor(params: StaticFileSkillParams);
247
+ execute(_input: SkillInput, _ctx: SkillContext): Promise<SkillOutput>;
248
+ }
249
+
250
+ interface StaticScriptSkillParams {
251
+ name: string;
252
+ description: string;
253
+ capabilities: string[];
254
+ priceSubunits: bigint;
255
+ asset: Asset;
256
+ /** Absolute path to the script. */
257
+ scriptPath: string;
258
+ /** Extra args appended after the script path. */
259
+ scriptArgs: string[];
260
+ /** Optional override of the default 60s timeout. */
261
+ scriptTimeoutMs?: number;
262
+ image?: string;
263
+ imageFile?: string;
264
+ }
265
+ /**
266
+ * Spawns a configured script with no stdin and returns its trimmed stdout.
267
+ * Throws on non-zero exit so the runtime surfaces a sanitized error.
268
+ * The script runs with cwd set to its containing directory so relative
269
+ * paths inside the script behave intuitively.
270
+ */
271
+ declare class StaticScriptSkill implements Skill {
272
+ name: string;
273
+ description: string;
274
+ capabilities: string[];
275
+ priceSubunits: bigint;
276
+ asset: Asset;
277
+ mode: SkillMode;
278
+ image?: string;
279
+ imageFile?: string;
280
+ private scriptPath;
281
+ private scriptArgs;
282
+ private scriptTimeoutMs?;
283
+ constructor(params: StaticScriptSkillParams);
284
+ execute(_input: SkillInput, ctx: SkillContext): Promise<SkillOutput>;
285
+ }
286
+
287
+ interface DynamicScriptSkillParams {
288
+ name: string;
289
+ description: string;
290
+ capabilities: string[];
291
+ priceSubunits: bigint;
292
+ asset: Asset;
293
+ /** Absolute path to the script. */
294
+ scriptPath: string;
295
+ /** Extra args appended after the script path. */
296
+ scriptArgs: string[];
297
+ /** Optional override of the default 60s timeout. */
298
+ scriptTimeoutMs?: number;
299
+ image?: string;
300
+ imageFile?: string;
301
+ }
302
+ /**
303
+ * Pipes the user's job input to the script's stdin and returns its
304
+ * trimmed stdout. Enables script-backed capabilities (proxies to
305
+ * external models, classical NLP, custom workers) without an LLM key
306
+ * on the elisym side.
307
+ */
308
+ declare class DynamicScriptSkill implements Skill {
309
+ name: string;
310
+ description: string;
311
+ capabilities: string[];
312
+ priceSubunits: bigint;
313
+ asset: Asset;
314
+ mode: SkillMode;
315
+ image?: string;
316
+ imageFile?: string;
317
+ private scriptPath;
318
+ private scriptArgs;
319
+ private scriptTimeoutMs?;
320
+ constructor(params: DynamicScriptSkillParams);
321
+ execute(input: SkillInput, ctx: SkillContext): Promise<SkillOutput>;
322
+ }
323
+
324
+ /**
325
+ * Resolve `value` relative to `rootDir` and reject anything that escapes
326
+ * the root (`..` segments, absolute paths outside it, or the root itself).
327
+ *
328
+ * Returns the absolute path on success, or null on rejection so callers
329
+ * can surface a precise error message.
330
+ */
331
+ declare function resolveInsidePath(rootDir: string, value: string): string | null;
332
+
132
333
  declare const DEFAULT_MAX_TOOL_ROUNDS = 10;
133
334
  interface SkillFrontmatter {
134
335
  name?: unknown;
@@ -143,6 +344,22 @@ interface SkillFrontmatter {
143
344
  image_file?: unknown;
144
345
  tools?: unknown;
145
346
  max_tool_rounds?: unknown;
347
+ /** Optional per-skill LLM provider override ('anthropic' | 'openai'). Pairs with `model`. */
348
+ provider?: unknown;
349
+ /** Optional per-skill LLM model override. Pairs with `provider`. */
350
+ model?: unknown;
351
+ /** Optional per-skill max_tokens override. Independent of provider/model. */
352
+ max_tokens?: unknown;
353
+ /** Execution mode. Default 'llm'. */
354
+ mode?: unknown;
355
+ /** Required when mode === 'static-file'. Path relative to skill dir. */
356
+ output_file?: unknown;
357
+ /** Required when mode === 'static-script' | 'dynamic-script'. Path relative to skill dir. */
358
+ script?: unknown;
359
+ /** Optional positional args appended after the script. */
360
+ script_args?: unknown;
361
+ /** Optional override of `DEFAULT_SCRIPT_TIMEOUT_MS`. */
362
+ script_timeout_ms?: unknown;
146
363
  }
147
364
  interface ParsedSkill {
148
365
  name: string;
@@ -151,11 +368,26 @@ interface ParsedSkill {
151
368
  /** Price in subunits of `asset`. */
152
369
  priceSubunits: bigint;
153
370
  asset: Asset;
371
+ mode: SkillMode;
154
372
  systemPrompt: string;
155
373
  tools: SkillToolDef[];
156
374
  maxToolRounds: number;
375
+ /**
376
+ * Per-skill LLM override (only present when mode === 'llm' and the SKILL.md
377
+ * declared at least one of `provider`/`model`/`max_tokens`). Parse-time
378
+ * invariant: `provider` set iff `model` set.
379
+ */
380
+ llmOverride?: SkillLlmOverride;
157
381
  image?: string;
158
382
  imageFile?: string;
383
+ /** Set when mode === 'static-file'. */
384
+ outputFile?: string;
385
+ /** Set when mode is a script mode. */
386
+ script?: string;
387
+ /** Empty when no script. */
388
+ scriptArgs: string[];
389
+ /** Undefined => caller uses `DEFAULT_SCRIPT_TIMEOUT_MS`. */
390
+ scriptTimeoutMs?: number;
159
391
  }
160
392
  interface LoaderLogger {
161
393
  debug?(obj: Record<string, unknown>, msg?: string): void;
@@ -177,9 +409,9 @@ declare function parseSkillMd(content: string): {
177
409
  declare function validateSkillFrontmatter(frontmatter: SkillFrontmatter, systemPrompt: string, options?: LoadSkillsOptions): ParsedSkill;
178
410
  /**
179
411
  * Walk `skillsDir`, load each immediate subdirectory's SKILL.md, and
180
- * return constructed `ScriptSkill` instances. Malformed directories are
181
- * skipped with a `warn` log.
412
+ * return constructed `Skill` instances (LLM or non-LLM depending on
413
+ * frontmatter `mode`). Malformed directories are skipped with a `warn` log.
182
414
  */
183
415
  declare function loadSkillsFromDir(skillsDir: string, options?: LoadSkillsOptions): Skill[];
184
416
 
185
- export { type CompletionResult, DEFAULT_MAX_TOOL_ROUNDS, type LlmClient, type LlmClientConfig, type LlmProvider, type LoadSkillsOptions, type LoaderLogger, type ParsedSkill, ScriptSkill, type ScriptSkillLogger, type ScriptSkillParams, type Skill, type SkillContext, type SkillFrontmatter, type SkillInput, type SkillOutput, type SkillToolDef, type ToolCall, type ToolDef, type ToolResult, createAnthropicClient, createLlmClient, createOpenAIClient, loadSkillsFromDir, parseSkillMd, validateSkillFrontmatter };
417
+ export { type CompletionResult, DEFAULT_MAX_TOOL_ROUNDS, DEFAULT_SCRIPT_TIMEOUT_MS, DynamicScriptSkill, type DynamicScriptSkillParams, type LlmClient, type LlmClientConfig, type LlmProvider, type LoadSkillsOptions, type LoaderLogger, MAX_SCRIPT_OUTPUT, MAX_STATIC_FILE_SIZE, type ParsedSkill, type RunScriptOptions, type RunScriptResult, ScriptSkill, type ScriptSkillLogger, type ScriptSkillParams, type Skill, type SkillContext, type SkillFrontmatter, type SkillInput, type SkillLlmOverride, type SkillMode, type SkillOutput, type SkillToolDef, StaticFileSkill, type StaticFileSkillParams, StaticScriptSkill, type StaticScriptSkillParams, type ToolCall, type ToolDef, type ToolResult, createAnthropicClient, createLlmClient, createOpenAIClient, loadSkillsFromDir, parseSkillMd, resolveInsidePath, runScript, validateSkillFrontmatter };