@elisym/sdk 0.14.0 → 0.15.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/index.cjs +144 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +27 -45
- package/dist/index.d.ts +27 -45
- package/dist/index.js +144 -3
- package/dist/index.js.map +1 -1
- package/dist/llm-health.cjs +426 -0
- package/dist/llm-health.cjs.map +1 -0
- package/dist/llm-health.d.cts +179 -0
- package/dist/llm-health.d.ts +179 -0
- package/dist/llm-health.js +410 -0
- package/dist/llm-health.js.map +1 -0
- package/dist/rateLimiter-CoEmZkSX.d.cts +45 -0
- package/dist/rateLimiter-CoEmZkSX.d.ts +45 -0
- package/dist/skills.cjs +40 -4
- package/dist/skills.cjs.map +1 -1
- package/dist/skills.d.cts +30 -1
- package/dist/skills.d.ts +30 -1
- package/dist/skills.js +40 -4
- package/dist/skills.js.map +1 -1
- package/dist/types-8vJ1I2KQ.d.cts +66 -0
- package/dist/types-8vJ1I2KQ.d.ts +66 -0
- package/package.json +11 -1
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sliding-window rate limiter keyed by an arbitrary string (typically a
|
|
3
|
+
* customer pubkey). Each key gets at most `maxPerWindow` requests inside a
|
|
4
|
+
* rolling `windowMs`. Stale timestamps are pruned lazily on every `check`.
|
|
5
|
+
* When the tracked-key set grows past `maxKeys`, the least-recently-used
|
|
6
|
+
* key is evicted so an attacker cannot exhaust memory by cycling keys.
|
|
7
|
+
*
|
|
8
|
+
* Thread-safety: not required. Designed for single-threaded JS consumers
|
|
9
|
+
* (Node/Bun event loops, browser main thread). No timers - pruning happens
|
|
10
|
+
* inside `check` and `prune`.
|
|
11
|
+
*/
|
|
12
|
+
interface SlidingWindowLimiterOptions {
|
|
13
|
+
/** Rolling window width, in ms. */
|
|
14
|
+
windowMs: number;
|
|
15
|
+
/** Max hits allowed per key inside the window. */
|
|
16
|
+
maxPerWindow: number;
|
|
17
|
+
/** Cap on total tracked keys. LRU-evicted past this cap. */
|
|
18
|
+
maxKeys: number;
|
|
19
|
+
}
|
|
20
|
+
interface RateLimitDecision {
|
|
21
|
+
allowed: boolean;
|
|
22
|
+
/** Wall-clock timestamp (ms) when the limit window will reset for this key. */
|
|
23
|
+
resetAt: number;
|
|
24
|
+
/** Number of hits inside the current window after this call (or the attempted hit if denied). */
|
|
25
|
+
count: number;
|
|
26
|
+
}
|
|
27
|
+
interface SlidingWindowLimiter {
|
|
28
|
+
/** Record a hit against `key`; return whether it was allowed. */
|
|
29
|
+
check(key: string, now?: number): RateLimitDecision;
|
|
30
|
+
/**
|
|
31
|
+
* Inspect the current state for `key` without recording a hit. Useful
|
|
32
|
+
* when a single request must clear multiple limiters and callers want
|
|
33
|
+
* to avoid double-counting against one limiter after another denies.
|
|
34
|
+
*/
|
|
35
|
+
peek(key: string, now?: number): RateLimitDecision;
|
|
36
|
+
/** Drop entries whose windows have fully elapsed. Bounded memory hygiene. */
|
|
37
|
+
prune(now?: number): void;
|
|
38
|
+
/** Current number of tracked keys. */
|
|
39
|
+
size(): number;
|
|
40
|
+
/** Clear all state. */
|
|
41
|
+
reset(): void;
|
|
42
|
+
}
|
|
43
|
+
declare function createSlidingWindowLimiter(options: SlidingWindowLimiterOptions): SlidingWindowLimiter;
|
|
44
|
+
|
|
45
|
+
export { type RateLimitDecision as R, type SlidingWindowLimiter as S, type SlidingWindowLimiterOptions as a, createSlidingWindowLimiter as c };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sliding-window rate limiter keyed by an arbitrary string (typically a
|
|
3
|
+
* customer pubkey). Each key gets at most `maxPerWindow` requests inside a
|
|
4
|
+
* rolling `windowMs`. Stale timestamps are pruned lazily on every `check`.
|
|
5
|
+
* When the tracked-key set grows past `maxKeys`, the least-recently-used
|
|
6
|
+
* key is evicted so an attacker cannot exhaust memory by cycling keys.
|
|
7
|
+
*
|
|
8
|
+
* Thread-safety: not required. Designed for single-threaded JS consumers
|
|
9
|
+
* (Node/Bun event loops, browser main thread). No timers - pruning happens
|
|
10
|
+
* inside `check` and `prune`.
|
|
11
|
+
*/
|
|
12
|
+
interface SlidingWindowLimiterOptions {
|
|
13
|
+
/** Rolling window width, in ms. */
|
|
14
|
+
windowMs: number;
|
|
15
|
+
/** Max hits allowed per key inside the window. */
|
|
16
|
+
maxPerWindow: number;
|
|
17
|
+
/** Cap on total tracked keys. LRU-evicted past this cap. */
|
|
18
|
+
maxKeys: number;
|
|
19
|
+
}
|
|
20
|
+
interface RateLimitDecision {
|
|
21
|
+
allowed: boolean;
|
|
22
|
+
/** Wall-clock timestamp (ms) when the limit window will reset for this key. */
|
|
23
|
+
resetAt: number;
|
|
24
|
+
/** Number of hits inside the current window after this call (or the attempted hit if denied). */
|
|
25
|
+
count: number;
|
|
26
|
+
}
|
|
27
|
+
interface SlidingWindowLimiter {
|
|
28
|
+
/** Record a hit against `key`; return whether it was allowed. */
|
|
29
|
+
check(key: string, now?: number): RateLimitDecision;
|
|
30
|
+
/**
|
|
31
|
+
* Inspect the current state for `key` without recording a hit. Useful
|
|
32
|
+
* when a single request must clear multiple limiters and callers want
|
|
33
|
+
* to avoid double-counting against one limiter after another denies.
|
|
34
|
+
*/
|
|
35
|
+
peek(key: string, now?: number): RateLimitDecision;
|
|
36
|
+
/** Drop entries whose windows have fully elapsed. Bounded memory hygiene. */
|
|
37
|
+
prune(now?: number): void;
|
|
38
|
+
/** Current number of tracked keys. */
|
|
39
|
+
size(): number;
|
|
40
|
+
/** Clear all state. */
|
|
41
|
+
reset(): void;
|
|
42
|
+
}
|
|
43
|
+
declare function createSlidingWindowLimiter(options: SlidingWindowLimiterOptions): SlidingWindowLimiter;
|
|
44
|
+
|
|
45
|
+
export { type RateLimitDecision as R, type SlidingWindowLimiter as S, type SlidingWindowLimiterOptions as a, createSlidingWindowLimiter as c };
|
package/dist/skills.cjs
CHANGED
|
@@ -25,7 +25,8 @@ function runScript(cmd, args, opts) {
|
|
|
25
25
|
stdio: ["pipe", "pipe", "pipe"],
|
|
26
26
|
timeout: timeoutMs,
|
|
27
27
|
killSignal: "SIGKILL",
|
|
28
|
-
signal: opts.signal
|
|
28
|
+
signal: opts.signal,
|
|
29
|
+
env: opts.env
|
|
29
30
|
});
|
|
30
31
|
let stdout = "";
|
|
31
32
|
let stderr = "";
|
|
@@ -246,6 +247,7 @@ var StaticScriptSkill = class {
|
|
|
246
247
|
scriptPath;
|
|
247
248
|
scriptArgs;
|
|
248
249
|
scriptTimeoutMs;
|
|
250
|
+
scriptEnv;
|
|
249
251
|
constructor(params) {
|
|
250
252
|
this.name = params.name;
|
|
251
253
|
this.description = params.description;
|
|
@@ -257,12 +259,14 @@ var StaticScriptSkill = class {
|
|
|
257
259
|
this.scriptPath = params.scriptPath;
|
|
258
260
|
this.scriptArgs = params.scriptArgs;
|
|
259
261
|
this.scriptTimeoutMs = params.scriptTimeoutMs;
|
|
262
|
+
this.scriptEnv = params.scriptEnv;
|
|
260
263
|
}
|
|
261
264
|
async execute(_input, ctx) {
|
|
262
265
|
const result = await runScript(this.scriptPath, this.scriptArgs, {
|
|
263
266
|
cwd: path.dirname(this.scriptPath),
|
|
264
267
|
signal: ctx.signal,
|
|
265
|
-
timeoutMs: this.scriptTimeoutMs
|
|
268
|
+
timeoutMs: this.scriptTimeoutMs,
|
|
269
|
+
env: this.scriptEnv
|
|
266
270
|
});
|
|
267
271
|
if (result.spawnError) {
|
|
268
272
|
throw new Error(`script spawn failed: ${result.spawnError.message}`);
|
|
@@ -286,6 +290,7 @@ var DynamicScriptSkill = class {
|
|
|
286
290
|
scriptPath;
|
|
287
291
|
scriptArgs;
|
|
288
292
|
scriptTimeoutMs;
|
|
293
|
+
scriptEnv;
|
|
289
294
|
constructor(params) {
|
|
290
295
|
this.name = params.name;
|
|
291
296
|
this.description = params.description;
|
|
@@ -297,13 +302,15 @@ var DynamicScriptSkill = class {
|
|
|
297
302
|
this.scriptPath = params.scriptPath;
|
|
298
303
|
this.scriptArgs = params.scriptArgs;
|
|
299
304
|
this.scriptTimeoutMs = params.scriptTimeoutMs;
|
|
305
|
+
this.scriptEnv = params.scriptEnv;
|
|
300
306
|
}
|
|
301
307
|
async execute(input, ctx) {
|
|
302
308
|
const result = await runScript(this.scriptPath, this.scriptArgs, {
|
|
303
309
|
cwd: path.dirname(this.scriptPath),
|
|
304
310
|
stdin: input.data,
|
|
305
311
|
signal: ctx.signal,
|
|
306
|
-
timeoutMs: this.scriptTimeoutMs
|
|
312
|
+
timeoutMs: this.scriptTimeoutMs,
|
|
313
|
+
env: this.scriptEnv
|
|
307
314
|
});
|
|
308
315
|
if (result.spawnError) {
|
|
309
316
|
throw new Error(`script spawn failed: ${result.spawnError.message}`);
|
|
@@ -582,6 +589,33 @@ function validateLlmOverride(skillName, frontmatter, mode) {
|
|
|
582
589
|
}
|
|
583
590
|
return override;
|
|
584
591
|
}
|
|
592
|
+
var MAX_RATE_LIMIT_WINDOW_SECS = 86400;
|
|
593
|
+
var MAX_RATE_LIMIT_PER_WINDOW = 1e4;
|
|
594
|
+
function validateRateLimit(skillName, raw) {
|
|
595
|
+
if (raw === void 0 || raw === null) {
|
|
596
|
+
return void 0;
|
|
597
|
+
}
|
|
598
|
+
if (typeof raw !== "object") {
|
|
599
|
+
throw new Error(`SKILL.md "${skillName}": "rate_limit" must be an object`);
|
|
600
|
+
}
|
|
601
|
+
const record = raw;
|
|
602
|
+
const perWindowSecs = record.per_window_secs;
|
|
603
|
+
const maxPerWindow = record.max_per_window;
|
|
604
|
+
if (typeof perWindowSecs !== "number" || !Number.isInteger(perWindowSecs) || perWindowSecs < 1 || perWindowSecs > MAX_RATE_LIMIT_WINDOW_SECS) {
|
|
605
|
+
throw new Error(
|
|
606
|
+
`SKILL.md "${skillName}": "rate_limit.per_window_secs" must be an integer between 1 and ${MAX_RATE_LIMIT_WINDOW_SECS}`
|
|
607
|
+
);
|
|
608
|
+
}
|
|
609
|
+
if (typeof maxPerWindow !== "number" || !Number.isInteger(maxPerWindow) || maxPerWindow < 1 || maxPerWindow > MAX_RATE_LIMIT_PER_WINDOW) {
|
|
610
|
+
throw new Error(
|
|
611
|
+
`SKILL.md "${skillName}": "rate_limit.max_per_window" must be an integer between 1 and ${MAX_RATE_LIMIT_PER_WINDOW}`
|
|
612
|
+
);
|
|
613
|
+
}
|
|
614
|
+
return {
|
|
615
|
+
perWindowMs: perWindowSecs * 1e3,
|
|
616
|
+
maxPerWindow
|
|
617
|
+
};
|
|
618
|
+
}
|
|
585
619
|
function validateScriptTimeoutMs(skillName, raw) {
|
|
586
620
|
if (raw === void 0 || raw === null) {
|
|
587
621
|
return void 0;
|
|
@@ -724,6 +758,7 @@ function validateSkillFrontmatter(frontmatter, systemPrompt, options = {}) {
|
|
|
724
758
|
const image = typeof frontmatter.image === "string" ? frontmatter.image : void 0;
|
|
725
759
|
const imageFile = typeof frontmatter.image_file === "string" ? frontmatter.image_file : void 0;
|
|
726
760
|
const llmOverride = validateLlmOverride(frontmatter.name, frontmatter, mode);
|
|
761
|
+
const rateLimit = validateRateLimit(frontmatter.name, frontmatter.rate_limit);
|
|
727
762
|
return {
|
|
728
763
|
name: frontmatter.name,
|
|
729
764
|
description: frontmatter.description,
|
|
@@ -740,7 +775,8 @@ function validateSkillFrontmatter(frontmatter, systemPrompt, options = {}) {
|
|
|
740
775
|
outputFile,
|
|
741
776
|
script,
|
|
742
777
|
scriptArgs,
|
|
743
|
-
scriptTimeoutMs
|
|
778
|
+
scriptTimeoutMs,
|
|
779
|
+
rateLimit
|
|
744
780
|
};
|
|
745
781
|
}
|
|
746
782
|
function buildSkillFromParsed(parsed, skillDir, logger) {
|
package/dist/skills.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/skills/scriptSkill.ts","../src/skills/staticFileSkill.ts","../src/skills/staticScriptSkill.ts","../src/skills/dynamicScriptSkill.ts","../src/skills/path-safety.ts","../src/constants.ts","../src/payment/assets.ts","../src/skills/loader.ts"],"names":["spawn","StringDecoder","readFile","dirname","resolve","relative","sep","Decimal","YAML","readdirSync","join","statSync","readFileSync"],"mappings":"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","file":"skills.cjs","sourcesContent":["import { spawn } from 'node:child_process';\nimport { StringDecoder } from 'node:string_decoder';\nimport type { Asset } from '../payment/assets';\nimport type {\n CompletionResult,\n LlmClient,\n Skill,\n SkillContext,\n SkillInput,\n SkillLlmOverride,\n SkillMode,\n SkillOutput,\n ToolCall,\n ToolDef,\n ToolResult,\n} from './types';\n\nexport const MAX_SCRIPT_OUTPUT = 1_000_000;\nexport const DEFAULT_SCRIPT_TIMEOUT_MS = 60_000;\n\nexport interface SkillToolDef {\n name: string;\n description: string;\n command: string[];\n parameters?: Array<{ name: string; description: string; required?: boolean }>;\n}\n\nexport interface ScriptSkillLogger {\n debug?(obj: Record<string, unknown>, msg?: string): void;\n}\n\nexport interface RunScriptOptions {\n cwd: string;\n /**\n * UTF-8 string written to the child's stdin, then stdin closed.\n * When undefined, stdin is closed immediately (EOF) so that children\n * which read stdin do not block until `timeoutMs`.\n */\n stdin?: string;\n /** Cancel the spawn. SIGKILL is sent on abort. */\n signal?: AbortSignal;\n /** Hard timeout in ms. Default `DEFAULT_SCRIPT_TIMEOUT_MS`. */\n timeoutMs?: number;\n /** Cap on stdout/stderr capture. Default `MAX_SCRIPT_OUTPUT`. */\n maxOutput?: number;\n}\n\nexport interface RunScriptResult {\n stdout: string;\n stderr: string;\n /** Null when the process was killed by signal before exiting. */\n code: number | null;\n /** Set when spawn itself failed (ENOENT, EACCES, etc.). */\n spawnError?: Error;\n}\n\n/**\n * Spawn `cmd` with `args` and capture stdout/stderr. Never uses `shell: true`,\n * so shell metacharacters in arguments are safe. Caller is responsible for\n * checking `code === 0` / interpreting `spawnError`.\n */\nexport function runScript(\n cmd: string,\n args: string[],\n opts: RunScriptOptions,\n): Promise<RunScriptResult> {\n return new Promise((resolveResult) => {\n const maxOutput = opts.maxOutput ?? MAX_SCRIPT_OUTPUT;\n const timeoutMs = opts.timeoutMs ?? DEFAULT_SCRIPT_TIMEOUT_MS;\n\n const child = spawn(cmd, args, {\n cwd: opts.cwd,\n stdio: ['pipe', 'pipe', 'pipe'],\n timeout: timeoutMs,\n killSignal: 'SIGKILL',\n signal: opts.signal,\n });\n\n let stdout = '';\n let stderr = '';\n const stdoutDecoder = new StringDecoder('utf8');\n const stderrDecoder = new StringDecoder('utf8');\n\n child.stdout?.on('data', (data: Buffer) => {\n if (stdout.length < maxOutput) {\n stdout += stdoutDecoder.write(data);\n if (stdout.length > maxOutput) {\n stdout = stdout.slice(0, maxOutput);\n }\n }\n });\n child.stderr?.on('data', (data: Buffer) => {\n if (stderr.length < maxOutput) {\n stderr += stderrDecoder.write(data);\n if (stderr.length > maxOutput) {\n stderr = stderr.slice(0, maxOutput);\n }\n }\n });\n\n child.on('close', (code) => {\n // Flush any bytes the decoder buffered because a multi-byte UTF-8\n // codepoint straddled the final chunk boundary.\n stdout += stdoutDecoder.end();\n stderr += stderrDecoder.end();\n resolveResult({ stdout, stderr, code });\n });\n\n child.on('error', (err) => {\n resolveResult({ stdout, stderr, code: null, spawnError: err });\n });\n\n if (child.stdin) {\n child.stdin.on('error', () => {\n // Ignore EPIPE - the child may exit without consuming all input.\n });\n // Always close stdin: a child that reads from stdin would otherwise\n // block until `timeoutMs` even when the caller has no input to send.\n child.stdin.end(opts.stdin ?? '');\n }\n });\n}\n\nexport interface ScriptSkillParams {\n name: string;\n description: string;\n capabilities: string[];\n priceSubunits: bigint;\n asset: Asset;\n skillDir: string;\n systemPrompt: string;\n tools: SkillToolDef[];\n maxToolRounds: number;\n /** Optional per-skill LLM override (provider/model pair and/or maxTokens). */\n llmOverride?: SkillLlmOverride;\n image?: string;\n imageFile?: string;\n logger?: ScriptSkillLogger;\n}\n\n/**\n * LLM-orchestrated skill runner. Tools are external scripts launched\n * via `child_process.spawn` (without `shell: true`, so shell\n * metacharacters in arguments are never interpreted - a security\n * property, not a convenience). Windows users cannot rely on\n * shell-script shebangs; target Linux/macOS for scripts.\n */\nexport class ScriptSkill implements Skill {\n name: string;\n description: string;\n capabilities: string[];\n priceSubunits: bigint;\n asset: Asset;\n mode: SkillMode = 'llm';\n readonly llmOverride?: SkillLlmOverride;\n image?: string;\n imageFile?: string;\n private skillDir: string;\n private systemPrompt: string;\n private tools: SkillToolDef[];\n private maxToolRounds: number;\n private logger: ScriptSkillLogger;\n\n constructor(params: ScriptSkillParams) {\n this.name = params.name;\n this.description = params.description;\n this.capabilities = params.capabilities;\n this.priceSubunits = params.priceSubunits;\n this.asset = params.asset;\n this.llmOverride = params.llmOverride;\n this.image = params.image;\n this.imageFile = params.imageFile;\n this.skillDir = params.skillDir;\n this.systemPrompt = params.systemPrompt;\n this.tools = params.tools;\n this.maxToolRounds = params.maxToolRounds;\n this.logger = params.logger ?? {};\n }\n\n async execute(input: SkillInput, ctx: SkillContext): Promise<SkillOutput> {\n const llm = this.resolveLlmClient(ctx);\n\n if (this.tools.length === 0) {\n const result = await llm.complete(this.systemPrompt, input.data, ctx.signal);\n return { data: result };\n }\n\n const toolDefs: ToolDef[] = this.tools.map((tool) => ({\n name: tool.name,\n description: tool.description,\n parameters: (tool.parameters ?? []).map((param) => ({\n name: param.name,\n description: param.description,\n required: param.required ?? true,\n })),\n }));\n\n const messages: unknown[] = [{ role: 'user', content: input.data }];\n\n for (let round = 0; round < this.maxToolRounds; round++) {\n if (ctx.signal?.aborted) {\n throw new Error('Job aborted');\n }\n const result: CompletionResult = await llm.completeWithTools(\n this.systemPrompt,\n messages,\n toolDefs,\n ctx.signal,\n );\n\n if (result.type === 'text') {\n return { data: result.text };\n }\n\n messages.push(result.assistantMessage);\n\n const toolResults: ToolResult[] = [];\n for (const call of result.calls) {\n const toolDef = this.tools.find((tool) => tool.name === call.name);\n if (!toolDef) {\n toolResults.push({\n callId: call.id,\n content: `Error: unknown tool \"${call.name}\"`,\n });\n continue;\n }\n const output = await this.runTool(toolDef, call, ctx.signal);\n toolResults.push({ callId: call.id, content: output });\n }\n\n messages.push(...llm.formatToolResultMessages(toolResults));\n }\n\n throw new Error(`Max tool rounds (${this.maxToolRounds}) exceeded`);\n }\n\n /**\n * Resolve the LLM client for this skill from the runtime context.\n *\n * Contract:\n * - When `llmOverride` is set, `ctx.getLlm` MUST be wired. Falling back to\n * `ctx.llm` (the agent default) would silently use the wrong configuration\n * for max-tokens-only overrides.\n * - When no override is set, prefer `ctx.getLlm()` (returns the agent\n * default), then fall back to `ctx.llm` for legacy callers that wire only\n * a single client.\n */\n private resolveLlmClient(ctx: SkillContext): LlmClient {\n let client: LlmClient | undefined;\n if (this.llmOverride) {\n client = ctx.getLlm?.(this.llmOverride);\n if (!client) {\n throw new Error(\n `Skill \"${this.name}\" requires ctx.getLlm to be configured (llmOverride is set)`,\n );\n }\n return client;\n }\n client = ctx.getLlm?.() ?? ctx.llm;\n if (!client) {\n throw new Error('LLM client not configured for skill runtime');\n }\n return client;\n }\n\n private async runTool(\n toolDef: SkillToolDef,\n call: ToolCall,\n signal?: AbortSignal,\n ): Promise<string> {\n const args = [...toolDef.command];\n const cmd = args.shift();\n if (!cmd) {\n return `Error: tool \"${toolDef.name}\" has an empty command`;\n }\n\n const params = toolDef.parameters ?? [];\n for (let index = 0; index < params.length; index++) {\n const param = params[index];\n if (!param) {\n continue;\n }\n const value = call.arguments[param.name];\n if (value === undefined) {\n continue;\n }\n if (param.required && index === 0) {\n args.push(String(value));\n } else {\n args.push(`--${param.name}`, String(value));\n }\n }\n\n const result = await runScript(cmd, args, { cwd: this.skillDir, signal });\n\n if (result.spawnError) {\n return `Error: ${result.spawnError.message}`;\n }\n if (result.code === 0) {\n return result.stdout.trim();\n }\n this.logger.debug?.(\n { tool: toolDef.name, code: result.code, stderrLen: result.stderr.length },\n 'skill tool exited non-zero',\n );\n return `Error (exit ${result.code}): ${result.stderr.trim() || result.stdout.trim()}`;\n }\n}\n","import { readFile } from 'node:fs/promises';\nimport type { Asset } from '../payment/assets';\nimport type { Skill, SkillContext, SkillInput, SkillMode, SkillOutput } from './types';\n\n/** Hard ceiling on result size for static-file skills. NIP-90 result events\n * travel through relays that may reject very large payloads; cap at 256 KB\n * of UTF-8. Larger files should use a script that streams to an external host. */\nexport const MAX_STATIC_FILE_SIZE = 256 * 1024;\n\nexport interface StaticFileSkillParams {\n name: string;\n description: string;\n capabilities: string[];\n priceSubunits: bigint;\n asset: Asset;\n /** Absolute path to the file whose contents are returned on each job. */\n outputFilePath: string;\n image?: string;\n imageFile?: string;\n}\n\n/**\n * Returns the contents of a fixed file as the job result. Reads on every\n * `execute()` so authors can edit the file without restarting the agent.\n */\nexport class StaticFileSkill implements Skill {\n name: string;\n description: string;\n capabilities: string[];\n priceSubunits: bigint;\n asset: Asset;\n mode: SkillMode = 'static-file';\n image?: string;\n imageFile?: string;\n private outputFilePath: string;\n\n constructor(params: StaticFileSkillParams) {\n this.name = params.name;\n this.description = params.description;\n this.capabilities = params.capabilities;\n this.priceSubunits = params.priceSubunits;\n this.asset = params.asset;\n this.image = params.image;\n this.imageFile = params.imageFile;\n this.outputFilePath = params.outputFilePath;\n }\n\n async execute(_input: SkillInput, _ctx: SkillContext): Promise<SkillOutput> {\n // Measure UTF-8 bytes, not JS string length: relays reject by byte size,\n // and a non-ASCII file is 1.5-4x its char count in UTF-8.\n const buffer = await readFile(this.outputFilePath);\n if (buffer.length > MAX_STATIC_FILE_SIZE) {\n throw new Error(\n `static-file output exceeds ${MAX_STATIC_FILE_SIZE} bytes (got ${buffer.length})`,\n );\n }\n return { data: buffer.toString('utf-8') };\n }\n}\n","import { dirname } from 'node:path';\nimport type { Asset } from '../payment/assets';\nimport { runScript } from './scriptSkill';\nimport type { Skill, SkillContext, SkillInput, SkillMode, SkillOutput } from './types';\n\nexport interface StaticScriptSkillParams {\n name: string;\n description: string;\n capabilities: string[];\n priceSubunits: bigint;\n asset: Asset;\n /** Absolute path to the script. */\n scriptPath: string;\n /** Extra args appended after the script path. */\n scriptArgs: string[];\n /** Optional override of the default 60s timeout. */\n scriptTimeoutMs?: number;\n image?: string;\n imageFile?: string;\n}\n\n/**\n * Spawns a configured script with no stdin and returns its trimmed stdout.\n * Throws on non-zero exit so the runtime surfaces a sanitized error.\n * The script runs with cwd set to its containing directory so relative\n * paths inside the script behave intuitively.\n */\nexport class StaticScriptSkill implements Skill {\n name: string;\n description: string;\n capabilities: string[];\n priceSubunits: bigint;\n asset: Asset;\n mode: SkillMode = 'static-script';\n image?: string;\n imageFile?: string;\n private scriptPath: string;\n private scriptArgs: string[];\n private scriptTimeoutMs?: number;\n\n constructor(params: StaticScriptSkillParams) {\n this.name = params.name;\n this.description = params.description;\n this.capabilities = params.capabilities;\n this.priceSubunits = params.priceSubunits;\n this.asset = params.asset;\n this.image = params.image;\n this.imageFile = params.imageFile;\n this.scriptPath = params.scriptPath;\n this.scriptArgs = params.scriptArgs;\n this.scriptTimeoutMs = params.scriptTimeoutMs;\n }\n\n async execute(_input: SkillInput, ctx: SkillContext): Promise<SkillOutput> {\n const result = await runScript(this.scriptPath, this.scriptArgs, {\n cwd: dirname(this.scriptPath),\n signal: ctx.signal,\n timeoutMs: this.scriptTimeoutMs,\n });\n if (result.spawnError) {\n throw new Error(`script spawn failed: ${result.spawnError.message}`);\n }\n if (result.code !== 0) {\n const detail = result.stderr.trim() || result.stdout.trim() || '(no output)';\n throw new Error(`script failed (exit ${result.code}): ${detail}`);\n }\n return { data: result.stdout.trim() };\n }\n}\n","import { dirname } from 'node:path';\nimport type { Asset } from '../payment/assets';\nimport { runScript } from './scriptSkill';\nimport type { Skill, SkillContext, SkillInput, SkillMode, SkillOutput } from './types';\n\nexport interface DynamicScriptSkillParams {\n name: string;\n description: string;\n capabilities: string[];\n priceSubunits: bigint;\n asset: Asset;\n /** Absolute path to the script. */\n scriptPath: string;\n /** Extra args appended after the script path. */\n scriptArgs: string[];\n /** Optional override of the default 60s timeout. */\n scriptTimeoutMs?: number;\n image?: string;\n imageFile?: string;\n}\n\n/**\n * Pipes the user's job input to the script's stdin and returns its\n * trimmed stdout. Enables script-backed capabilities (proxies to\n * external models, classical NLP, custom workers) without an LLM key\n * on the elisym side.\n */\nexport class DynamicScriptSkill implements Skill {\n name: string;\n description: string;\n capabilities: string[];\n priceSubunits: bigint;\n asset: Asset;\n mode: SkillMode = 'dynamic-script';\n image?: string;\n imageFile?: string;\n private scriptPath: string;\n private scriptArgs: string[];\n private scriptTimeoutMs?: number;\n\n constructor(params: DynamicScriptSkillParams) {\n this.name = params.name;\n this.description = params.description;\n this.capabilities = params.capabilities;\n this.priceSubunits = params.priceSubunits;\n this.asset = params.asset;\n this.image = params.image;\n this.imageFile = params.imageFile;\n this.scriptPath = params.scriptPath;\n this.scriptArgs = params.scriptArgs;\n this.scriptTimeoutMs = params.scriptTimeoutMs;\n }\n\n async execute(input: SkillInput, ctx: SkillContext): Promise<SkillOutput> {\n const result = await runScript(this.scriptPath, this.scriptArgs, {\n cwd: dirname(this.scriptPath),\n stdin: input.data,\n signal: ctx.signal,\n timeoutMs: this.scriptTimeoutMs,\n });\n if (result.spawnError) {\n throw new Error(`script spawn failed: ${result.spawnError.message}`);\n }\n if (result.code !== 0) {\n const detail = result.stderr.trim() || result.stdout.trim() || '(no output)';\n throw new Error(`script failed (exit ${result.code}): ${detail}`);\n }\n return { data: result.stdout.trim() };\n }\n}\n","import { relative, resolve, sep } from 'node:path';\n\n/**\n * Resolve `value` relative to `rootDir` and reject anything that escapes\n * the root (`..` segments, absolute paths outside it, or the root itself).\n *\n * Returns the absolute path on success, or null on rejection so callers\n * can surface a precise error message.\n */\nexport function resolveInsidePath(rootDir: string, value: string): string | null {\n const root = resolve(rootDir);\n const candidate = resolve(root, value);\n const rel = relative(root, candidate);\n if (rel === '' || rel.startsWith('..') || rel.includes(`..${sep}`)) {\n return null;\n }\n return candidate;\n}\n","import type { Address } from '@solana/kit';\n\nexport const RELAYS = [\n 'wss://relay.damus.io',\n 'wss://nos.lol',\n 'wss://relay.nostr.band',\n 'wss://relay.primal.net',\n 'wss://relay.snort.social',\n];\n\nexport const KIND_APP_HANDLER = 31990;\nexport const KIND_JOB_REQUEST_BASE = 5000;\nexport const KIND_JOB_RESULT_BASE = 6000;\nexport const KIND_JOB_FEEDBACK = 7000;\nexport const DEFAULT_KIND_OFFSET = 100;\n\n/** Default job request kind (5000 + 100). */\nexport const KIND_JOB_REQUEST = KIND_JOB_REQUEST_BASE + DEFAULT_KIND_OFFSET;\n/** Default job result kind (6000 + 100). */\nexport const KIND_JOB_RESULT = KIND_JOB_RESULT_BASE + DEFAULT_KIND_OFFSET;\n\n/** Compute a job request kind from an offset (5000 + offset). */\nexport function jobRequestKind(offset: number): number {\n if (!Number.isInteger(offset) || offset < 0 || offset >= 1000) {\n throw new Error(`Invalid kind offset: ${offset}. Must be integer 0-999.`);\n }\n return KIND_JOB_REQUEST_BASE + offset;\n}\n\n/** Compute a job result kind from an offset (6000 + offset). */\nexport function jobResultKind(offset: number): number {\n if (!Number.isInteger(offset) || offset < 0 || offset >= 1000) {\n throw new Error(`Invalid kind offset: ${offset}. Must be integer 0-999.`);\n }\n return KIND_JOB_RESULT_BASE + offset;\n}\n\n/** Ephemeral ping/pong kinds (not stored by relays, forwarded in real-time). */\nexport const KIND_PING = 20200;\nexport const KIND_PONG = 20201;\n\nexport const LAMPORTS_PER_SOL = 1_000_000_000;\n\n/**\n * Solana program ID for the elisym protocol config (devnet deployment).\n *\n * The Anchor program at this address is the source of truth for fee bps,\n * treasury address, and admin rotation state. Read via `getProtocolConfig`.\n */\nexport const PROTOCOL_PROGRAM_ID_DEVNET = 'BrX1CRkSgvcjxBvc2bgc3QqgWjinusofDmeP7ZVxvwrE' as Address;\n\n/**\n * Read-only marker pubkey attached as a non-signer account to every elisym\n * payment transaction. Lets indexers enumerate every elisym tx network-wide\n * via a single `getSignaturesForAddress(ELISYM_PROTOCOL_TAG)` call,\n * independent of fee size or recipient.\n *\n * The account does not need to exist on-chain; including its pubkey as an\n * extra read-only account in the provider transfer instruction is enough for\n * Solana's tx-by-account index to pick it up. The corresponding secret key\n * was generated and discarded - the tag never signs and never holds funds.\n */\nexport const ELISYM_PROTOCOL_TAG = 'ELiZksgwDt41LaeuPDLkUfWgFXhGgVayTMP7L5nTSEL8' as Address;\n\nexport type ProtocolCluster = 'devnet' | 'mainnet' | 'localnet';\n\n/**\n * Resolve the elisym-config program ID for a given Solana cluster.\n * Mainnet is intentionally unsupported until the program ships there.\n */\nexport function getProtocolProgramId(cluster: ProtocolCluster): Address {\n switch (cluster) {\n case 'devnet':\n case 'localnet':\n return PROTOCOL_PROGRAM_ID_DEVNET;\n case 'mainnet':\n throw new Error('Protocol program is not deployed on mainnet yet');\n }\n}\n\n/** Default values for timeouts, retries, and batch sizes. */\nexport const DEFAULTS = {\n SUBSCRIPTION_TIMEOUT_MS: 120_000,\n PING_TIMEOUT_MS: 3_000,\n PING_RETRIES: 2,\n PING_CACHE_TTL_MS: 30_000,\n PAYMENT_EXPIRY_SECS: 600,\n BATCH_SIZE: 250,\n QUERY_TIMEOUT_MS: 15_000,\n EOSE_TIMEOUT_MS: 3_000,\n VERIFY_RETRIES: 10,\n VERIFY_INTERVAL_MS: 3_000,\n VERIFY_BY_REF_RETRIES: 15,\n VERIFY_BY_REF_INTERVAL_MS: 2_000,\n RESULT_RETRY_COUNT: 3,\n RESULT_RETRY_BASE_MS: 1_000,\n QUERY_MAX_CONCURRENCY: 6,\n VERIFY_SIGNATURE_LIMIT: 25,\n} as const;\n\n/** Protocol limits for input validation. */\nexport const LIMITS = {\n MAX_INPUT_LENGTH: 100_000,\n MAX_TIMEOUT_SECS: 600,\n MAX_CAPABILITIES: 20,\n MAX_DESCRIPTION_LENGTH: 500,\n MAX_AGENT_NAME_LENGTH: 64,\n MAX_CAPABILITY_LENGTH: 64,\n} as const;\n","/**\n * Multi-asset / multi-chain payment model.\n *\n * `Asset` describes a currency a customer can spend: native coins (SOL, ETH, BTC)\n * or tokens (SPL, ERC-20). `assetKey` produces a stable string id for Map lookups.\n *\n * Today only `NATIVE_SOL` is in `KNOWN_ASSETS`. SPL (USDC) and other chains are\n * extended by adding entries to `KNOWN_ASSETS` and, where relevant, to the\n * MCP `DEFAULT_SESSION_LIMITS` catalogue.\n */\n\nimport Decimal from 'decimal.js-light';\n\nexport type Chain = 'solana';\n\nexport interface Asset {\n chain: Chain;\n /** Lowercase token id: 'sol', 'usdc', 'btc', 'eth'. */\n token: string;\n /** SPL mint / ERC-20 contract. Undefined for a native coin. */\n mint?: string;\n /** Subunits per whole (9 SOL, 6 USDC, 8 BTC, 18 ETH). */\n decimals: number;\n /** Display symbol: 'SOL', 'USDC'. */\n symbol: string;\n}\n\nexport const NATIVE_SOL: Asset = {\n chain: 'solana',\n token: 'sol',\n decimals: 9,\n symbol: 'SOL',\n};\n\nexport const USDC_SOLANA_DEVNET: Asset = {\n chain: 'solana',\n token: 'usdc',\n mint: '4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU',\n decimals: 6,\n symbol: 'USDC',\n};\n\nexport const KNOWN_ASSETS: readonly Asset[] = [NATIVE_SOL, USDC_SOLANA_DEVNET];\n\n/** Stable Map key for `Asset`. Same shape regardless of Asset identity. */\nexport function assetKey(a: Pick<Asset, 'chain' | 'token' | 'mint'>): string {\n return a.mint ? `${a.chain}:${a.token}:${a.mint}` : `${a.chain}:${a.token}`;\n}\n\n/** Find a known asset by (chain, token, mint). Returns undefined if unknown. */\nexport function resolveKnownAsset(chain: string, token: string, mint?: string): Asset | undefined {\n const key = mint ? `${chain}:${token}:${mint}` : `${chain}:${token}`;\n return KNOWN_ASSETS.find((asset) => assetKey(asset) === key);\n}\n\n/** Reverse lookup: given an assetKey string, return the known asset or undefined. */\nexport function assetByKey(key: string): Asset | undefined {\n return KNOWN_ASSETS.find((asset) => assetKey(asset) === key);\n}\n\n/**\n * Resolve the asset a payment request targets. Returns `NATIVE_SOL` when the\n * request has no `asset` field (back-compat with payment requests published\n * before multi-asset support). Throws when `asset` is present but refers to an\n * asset that isn't in `KNOWN_ASSETS` - callers that want to tolerate unknown\n * assets should check `resolveKnownAsset` directly instead.\n */\nexport function resolveAssetFromPaymentRequest(request: {\n asset?: { chain: string; token: string; mint?: string };\n}): Asset {\n if (!request.asset) {\n return NATIVE_SOL;\n }\n const found = resolveKnownAsset(request.asset.chain, request.asset.token, request.asset.mint);\n if (!found) {\n const display = request.asset.mint\n ? `${request.asset.chain}:${request.asset.token}:${request.asset.mint}`\n : `${request.asset.chain}:${request.asset.token}`;\n throw new Error(\n `Unknown asset in payment request: ${display}. ` +\n `Known assets: ${KNOWN_ASSETS.map(assetKey).join(', ')}`,\n );\n }\n return found;\n}\n\nconst DECIMAL_RE = /^(\\d+\\.\\d*|\\d*\\.\\d+|\\d+)$/;\n\n/**\n * Parse a human amount string (\"0.5\", \"1\", \"0.000001\") into raw subunits (BigInt).\n * Uses integer math to avoid float precision issues.\n *\n * Throws on: empty, negative, zero, malformed, too many fractional digits, or\n * a value exceeding `Number.MAX_SAFE_INTEGER` (to keep downstream `Number(...)`\n * call-sites safe).\n */\nexport function parseAssetAmount(asset: Asset, human: string): bigint {\n const trimmed = human.trim();\n if (!trimmed) {\n throw new Error(`${asset.symbol} amount is empty`);\n }\n if (trimmed.startsWith('-')) {\n throw new Error(`${asset.symbol} amount cannot be negative`);\n }\n if (!DECIMAL_RE.test(trimmed)) {\n throw new Error(\n `${asset.symbol} amount must be a non-negative decimal (e.g. \"0.5\", \"1\"); got \"${human}\"`,\n );\n }\n\n const dotPos = trimmed.indexOf('.');\n let wholePart: string;\n if (dotPos === -1) {\n wholePart = trimmed;\n } else if (dotPos === 0) {\n wholePart = '0';\n } else {\n wholePart = trimmed.slice(0, dotPos);\n }\n const fracPart = dotPos === -1 ? '' : trimmed.slice(dotPos + 1);\n\n if (fracPart.length > asset.decimals) {\n throw new Error(\n `${asset.symbol} amount has too many decimals (max ${asset.decimals}); got \"${human}\"`,\n );\n }\n\n const unit = 10n ** BigInt(asset.decimals);\n const whole = BigInt(wholePart);\n const frac = fracPart ? BigInt(fracPart.padEnd(asset.decimals, '0')) : 0n;\n const raw = whole * unit + frac;\n\n if (raw === 0n) {\n throw new Error(`${asset.symbol} amount must be positive; got \"${human}\"`);\n }\n if (raw > BigInt(Number.MAX_SAFE_INTEGER)) {\n throw new Error(\n `${asset.symbol} amount exceeds safe range (max ${Number.MAX_SAFE_INTEGER} subunits)`,\n );\n }\n return raw;\n}\n\n// Cloned config keeps `Decimal.toString()` from switching to exponential notation\n// for small fractional amounts (e.g. 1 lamport = 1e-9 SOL).\nconst FormatDecimal = Decimal.clone({ toExpNeg: -100, toExpPos: 100, precision: 50 });\n\n/**\n * Format raw subunits back to `\"<value> <SYMBOL>\"`. Trailing zeros and a bare\n * trailing dot are stripped, so 0.01 USDC renders as `\"0.01 USDC\"` rather than\n * `\"0.010000 USDC\"`.\n */\nexport function formatAssetAmount(asset: Asset, raw: bigint): string {\n const value = new FormatDecimal(raw.toString()).div(new FormatDecimal(10).pow(asset.decimals));\n return `${value.toString()} ${asset.symbol}`;\n}\n","import { readdirSync, readFileSync, statSync } from 'node:fs';\nimport { join } from 'node:path';\nimport YAML from 'yaml';\nimport { LAMPORTS_PER_SOL } from '../constants';\nimport {\n type Asset,\n NATIVE_SOL,\n USDC_SOLANA_DEVNET,\n parseAssetAmount,\n resolveKnownAsset,\n} from '../payment/assets';\nimport { DynamicScriptSkill } from './dynamicScriptSkill';\nimport { resolveInsidePath } from './path-safety';\nimport { DEFAULT_SCRIPT_TIMEOUT_MS, ScriptSkill, type SkillToolDef } from './scriptSkill';\nimport { StaticFileSkill } from './staticFileSkill';\nimport { StaticScriptSkill } from './staticScriptSkill';\nimport type { Skill, SkillLlmOverride, SkillMode } from './types';\n\nconst MAX_TOKENS_LIMIT = 200_000;\n\nexport const DEFAULT_MAX_TOOL_ROUNDS = 10;\n\nconst VALID_MODES: readonly SkillMode[] = [\n 'llm',\n 'static-file',\n 'static-script',\n 'dynamic-script',\n] as const;\n\nexport interface SkillFrontmatter {\n name?: unknown;\n description?: unknown;\n capabilities?: unknown;\n price?: unknown;\n /** Lowercase token id ('sol', 'usdc'). Defaults to 'sol' for back-compat. */\n token?: unknown;\n /** SPL mint (base58). Optional - resolved from known assets when omitted. */\n mint?: unknown;\n image?: unknown;\n image_file?: unknown;\n tools?: unknown;\n max_tool_rounds?: unknown;\n /** Optional per-skill LLM provider override (e.g. 'anthropic', 'openai'). Pairs with `model`. */\n provider?: unknown;\n /** Optional per-skill LLM model override. Pairs with `provider`. */\n model?: unknown;\n /** Optional per-skill max_tokens override. Independent of provider/model. */\n max_tokens?: unknown;\n /** Execution mode. Default 'llm'. */\n mode?: unknown;\n /** Required when mode === 'static-file'. Path relative to skill dir. */\n output_file?: unknown;\n /** Required when mode === 'static-script' | 'dynamic-script'. Path relative to skill dir. */\n script?: unknown;\n /** Optional positional args appended after the script. */\n script_args?: unknown;\n /** Optional override of `DEFAULT_SCRIPT_TIMEOUT_MS`. */\n script_timeout_ms?: unknown;\n}\n\nexport interface ParsedSkill {\n name: string;\n description: string;\n capabilities: string[];\n /** Price in subunits of `asset`. */\n priceSubunits: bigint;\n asset: Asset;\n mode: SkillMode;\n systemPrompt: string;\n tools: SkillToolDef[];\n maxToolRounds: number;\n /**\n * Per-skill LLM override (only present when mode === 'llm' and the SKILL.md\n * declared at least one of `provider`/`model`/`max_tokens`). Parse-time\n * invariant: `provider` set iff `model` set.\n */\n llmOverride?: SkillLlmOverride;\n image?: string;\n imageFile?: string;\n /** Set when mode === 'static-file'. */\n outputFile?: string;\n /** Set when mode is a script mode. */\n script?: string;\n /** Empty when no script. */\n scriptArgs: string[];\n /** Undefined => caller uses `DEFAULT_SCRIPT_TIMEOUT_MS`. */\n scriptTimeoutMs?: number;\n}\n\nexport interface LoaderLogger {\n debug?(obj: Record<string, unknown>, msg?: string): void;\n warn?(obj: Record<string, unknown>, msg?: string): void;\n}\n\nexport interface LoadSkillsOptions {\n /**\n * When true, SKILL.md may declare `price: 0` or omit `price` entirely\n * and the skill is loaded as free (`priceLamports === 0n`). Default\n * false: paid-only (plugin's historical behaviour).\n */\n allowFreeSkills?: boolean;\n logger?: LoaderLogger;\n}\n\nfunction solToLamports(sol: string | number): bigint {\n const asNumber = typeof sol === 'string' ? Number(sol) : sol;\n if (!Number.isFinite(asNumber) || asNumber < 0) {\n throw new Error(`Invalid SOL amount: ${sol}`);\n }\n return BigInt(Math.round(asNumber * LAMPORTS_PER_SOL));\n}\n\n/**\n * Resolve the asset a SKILL.md declares.\n *\n * - `token` absent or `'sol'` => native SOL (NATIVE_SOL).\n * - `token: 'usdc'` (+ optional `mint`) => resolved via `resolveKnownAsset`;\n * falls back to `USDC_SOLANA_DEVNET` when `mint` is omitted so operators\n * don't need to memorize the devnet mint address.\n * - Any unknown `token` throws.\n */\nfunction resolveSkillAsset(skillName: string, token: unknown, mint: unknown): Asset {\n if (token === undefined || token === null) {\n return NATIVE_SOL;\n }\n if (typeof token !== 'string' || token.length === 0) {\n throw new Error(`SKILL.md \"${skillName}\": \"token\" must be a non-empty string`);\n }\n let mintString: string | undefined;\n if (mint === undefined || mint === null) {\n mintString = undefined;\n } else if (typeof mint === 'string') {\n mintString = mint;\n } else {\n throw new Error(`SKILL.md \"${skillName}\": \"mint\" must be a base58 string`);\n }\n\n const normalized = token.toLowerCase();\n if (normalized === 'sol') {\n return NATIVE_SOL;\n }\n if (normalized === 'usdc' && mintString === undefined) {\n return USDC_SOLANA_DEVNET;\n }\n const resolved = resolveKnownAsset('solana', normalized, mintString);\n if (!resolved) {\n const display = mintString ? `solana:${normalized}:${mintString}` : `solana:${normalized}`;\n throw new Error(\n `SKILL.md \"${skillName}\": unknown asset ${display}. ` +\n `Known assets: sol, usdc (devnet mint 4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU).`,\n );\n }\n return resolved;\n}\n\nexport function parseSkillMd(content: string): {\n frontmatter: SkillFrontmatter;\n systemPrompt: string;\n} {\n const lines = content.split('\\n');\n let start = -1;\n let end = -1;\n\n for (let index = 0; index < lines.length; index++) {\n if (lines[index]?.trim() === '---') {\n if (start === -1) {\n start = index;\n } else {\n end = index;\n break;\n }\n }\n }\n\n if (start === -1 || end === -1) {\n throw new Error('SKILL.md must have YAML frontmatter between --- delimiters');\n }\n\n const yamlStr = lines.slice(start + 1, end).join('\\n');\n const frontmatter = YAML.parse(yamlStr) as SkillFrontmatter;\n const systemPrompt = lines\n .slice(end + 1)\n .join('\\n')\n .trim();\n return { frontmatter, systemPrompt };\n}\n\nfunction validateTool(raw: unknown, skillName: string, index: number): SkillToolDef {\n if (typeof raw !== 'object' || raw === null) {\n throw new Error(`skill \"${skillName}\" tool[${index}] must be an object`);\n }\n const tool = raw as Record<string, unknown>;\n if (typeof tool.name !== 'string' || tool.name.length === 0) {\n throw new Error(`skill \"${skillName}\" tool[${index}] missing name`);\n }\n if (typeof tool.description !== 'string' || tool.description.length === 0) {\n throw new Error(`skill \"${skillName}\" tool \"${tool.name}\" missing description`);\n }\n if (!Array.isArray(tool.command) || tool.command.length === 0) {\n throw new Error(`skill \"${skillName}\" tool \"${tool.name}\" missing command[] array`);\n }\n for (const part of tool.command) {\n if (typeof part !== 'string') {\n throw new Error(`skill \"${skillName}\" tool \"${tool.name}\" command[] must be strings`);\n }\n }\n const parameters: SkillToolDef['parameters'] = [];\n if (tool.parameters !== undefined) {\n if (!Array.isArray(tool.parameters)) {\n throw new Error(`skill \"${skillName}\" tool \"${tool.name}\" parameters must be an array`);\n }\n for (let paramIndex = 0; paramIndex < tool.parameters.length; paramIndex++) {\n const param = tool.parameters[paramIndex];\n if (typeof param !== 'object' || param === null) {\n throw new Error(\n `skill \"${skillName}\" tool \"${tool.name}\" parameter[${paramIndex}] must be an object`,\n );\n }\n const record = param as Record<string, unknown>;\n if (typeof record.name !== 'string' || record.name.length === 0) {\n throw new Error(\n `skill \"${skillName}\" tool \"${tool.name}\" parameter[${paramIndex}] missing name`,\n );\n }\n if (typeof record.description !== 'string') {\n throw new Error(\n `skill \"${skillName}\" tool \"${tool.name}\" parameter \"${record.name}\" missing description`,\n );\n }\n parameters.push({\n name: record.name,\n description: record.description,\n required: record.required === undefined ? undefined : Boolean(record.required),\n });\n }\n }\n return {\n name: tool.name,\n description: tool.description,\n command: tool.command as string[],\n parameters,\n };\n}\n\nfunction validateMode(skillName: string, raw: unknown): SkillMode {\n if (raw === undefined || raw === null) {\n return 'llm';\n }\n if (typeof raw !== 'string') {\n throw new Error(`SKILL.md \"${skillName}\": \"mode\" must be a string`);\n }\n if (!(VALID_MODES as readonly string[]).includes(raw)) {\n throw new Error(\n `SKILL.md \"${skillName}\": invalid mode \"${raw}\". Allowed: ${VALID_MODES.join(', ')}`,\n );\n }\n return raw as SkillMode;\n}\n\nfunction validateScriptArgs(skillName: string, raw: unknown): string[] {\n if (raw === undefined || raw === null) {\n return [];\n }\n if (!Array.isArray(raw)) {\n throw new Error(`SKILL.md \"${skillName}\": \"script_args\" must be an array of strings`);\n }\n for (const part of raw) {\n if (typeof part !== 'string') {\n throw new Error(`SKILL.md \"${skillName}\": \"script_args\" entries must be strings`);\n }\n }\n return raw as string[];\n}\n\n/**\n * Parse the optional per-skill LLM override block. The all-or-nothing rule\n * applies to (`provider`, `model`); `max_tokens` is independent.\n *\n * Returns `undefined` when no LLM override fields are declared at all.\n * Throws on partial pair, invalid provider, empty model, or out-of-range\n * max_tokens.\n *\n * Rejects all three fields when `mode !== 'llm'`.\n */\nfunction validateLlmOverride(\n skillName: string,\n frontmatter: SkillFrontmatter,\n mode: SkillMode,\n): SkillLlmOverride | undefined {\n const hasProvider = frontmatter.provider !== undefined && frontmatter.provider !== null;\n const hasModel = frontmatter.model !== undefined && frontmatter.model !== null;\n const hasMaxTokens = frontmatter.max_tokens !== undefined && frontmatter.max_tokens !== null;\n\n if (!hasProvider && !hasModel && !hasMaxTokens) {\n return undefined;\n }\n\n if (mode !== 'llm') {\n throw new Error(\n `SKILL.md \"${skillName}\": \"provider\"/\"model\"/\"max_tokens\" are only valid in mode 'llm' (got '${mode}')`,\n );\n }\n\n if (hasProvider !== hasModel) {\n throw new Error(\n `SKILL.md \"${skillName}\": \"provider\" and \"model\" must be set together (declare both, or neither)`,\n );\n }\n\n const override: SkillLlmOverride = {};\n\n if (hasProvider && hasModel) {\n if (typeof frontmatter.provider !== 'string' || frontmatter.provider.length === 0) {\n throw new Error(`SKILL.md \"${skillName}\": \"provider\" must be a non-empty string`);\n }\n if (typeof frontmatter.model !== 'string' || frontmatter.model.length === 0) {\n throw new Error(`SKILL.md \"${skillName}\": \"model\" must be a non-empty string`);\n }\n override.provider = frontmatter.provider;\n override.model = frontmatter.model;\n }\n\n if (hasMaxTokens) {\n if (\n typeof frontmatter.max_tokens !== 'number' ||\n !Number.isInteger(frontmatter.max_tokens) ||\n frontmatter.max_tokens <= 0 ||\n frontmatter.max_tokens > MAX_TOKENS_LIMIT\n ) {\n throw new Error(\n `SKILL.md \"${skillName}\": \"max_tokens\" must be a positive integer <= ${MAX_TOKENS_LIMIT}`,\n );\n }\n override.maxTokens = frontmatter.max_tokens;\n }\n\n return override;\n}\n\nfunction validateScriptTimeoutMs(skillName: string, raw: unknown): number | undefined {\n if (raw === undefined || raw === null) {\n return undefined;\n }\n if (typeof raw !== 'number' || !Number.isInteger(raw) || raw <= 0) {\n throw new Error(`SKILL.md \"${skillName}\": \"script_timeout_ms\" must be a positive integer`);\n }\n return raw;\n}\n\nexport function validateSkillFrontmatter(\n frontmatter: SkillFrontmatter,\n systemPrompt: string,\n options: LoadSkillsOptions = {},\n): ParsedSkill {\n if (typeof frontmatter.name !== 'string' || frontmatter.name.length === 0) {\n throw new Error('SKILL.md: missing or invalid \"name\" field');\n }\n if (typeof frontmatter.description !== 'string' || frontmatter.description.length === 0) {\n throw new Error('SKILL.md: missing or invalid \"description\" field');\n }\n if (!Array.isArray(frontmatter.capabilities) || frontmatter.capabilities.length === 0) {\n throw new Error('SKILL.md: \"capabilities\" must be a non-empty array');\n }\n const capabilities: string[] = [];\n for (const capability of frontmatter.capabilities) {\n if (typeof capability !== 'string' || capability.length === 0) {\n throw new Error(\n `SKILL.md \"${frontmatter.name}\": capability entries must be non-empty strings`,\n );\n }\n capabilities.push(capability);\n }\n\n const asset = resolveSkillAsset(frontmatter.name, frontmatter.token, frontmatter.mint);\n\n let priceSubunits: bigint;\n if (frontmatter.price === undefined || frontmatter.price === null) {\n if (!options.allowFreeSkills) {\n throw new Error(\n `SKILL.md \"${frontmatter.name}\": \"price\" is required (${asset.symbol}; e.g. ${\n asset === NATIVE_SOL ? '0.002' : '0.05'\n }). Free skills are not supported on the protocol yet.`,\n );\n }\n priceSubunits = 0n;\n } else {\n const priceRaw = frontmatter.price;\n if (typeof priceRaw !== 'number' && typeof priceRaw !== 'string') {\n throw new Error(`SKILL.md \"${frontmatter.name}\": \"price\" must be a number or numeric string`);\n }\n const priceString = typeof priceRaw === 'number' ? String(priceRaw) : priceRaw;\n if (asset === NATIVE_SOL) {\n // Preserve historical rounding behaviour: number * LAMPORTS_PER_SOL +\n // Math.round. `parseAssetAmount` would reject non-positive inputs before\n // we could check `allowFreeSkills`, so we keep the legacy path for SOL\n // and introduce the strict parser only for new token types.\n priceSubunits = solToLamports(priceRaw);\n } else {\n try {\n priceSubunits = parseAssetAmount(asset, priceString);\n } catch (error) {\n throw new Error(\n `SKILL.md \"${frontmatter.name}\": ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n if (priceSubunits <= 0n && !options.allowFreeSkills) {\n throw new Error(\n `SKILL.md \"${frontmatter.name}\": price must be > 0 ${asset.symbol} (got ${priceRaw}); free skills are not yet supported`,\n );\n }\n }\n\n const mode = validateMode(frontmatter.name, frontmatter.mode);\n\n const tools: SkillToolDef[] = [];\n if (frontmatter.tools !== undefined) {\n if (mode !== 'llm') {\n throw new Error(\n `SKILL.md \"${frontmatter.name}\": \"tools\" is only valid in mode 'llm' (got '${mode}')`,\n );\n }\n if (!Array.isArray(frontmatter.tools)) {\n throw new Error(`SKILL.md \"${frontmatter.name}\": \"tools\" must be an array`);\n }\n for (let index = 0; index < frontmatter.tools.length; index++) {\n tools.push(validateTool(frontmatter.tools[index], frontmatter.name, index));\n }\n }\n\n let maxToolRounds = DEFAULT_MAX_TOOL_ROUNDS;\n if (frontmatter.max_tool_rounds !== undefined) {\n if (mode !== 'llm') {\n throw new Error(\n `SKILL.md \"${frontmatter.name}\": \"max_tool_rounds\" is only valid in mode 'llm' (got '${mode}')`,\n );\n }\n if (\n typeof frontmatter.max_tool_rounds !== 'number' ||\n !Number.isInteger(frontmatter.max_tool_rounds) ||\n frontmatter.max_tool_rounds <= 0\n ) {\n throw new Error(\n `SKILL.md \"${frontmatter.name}\": \"max_tool_rounds\" must be a positive integer`,\n );\n }\n maxToolRounds = frontmatter.max_tool_rounds;\n }\n\n let outputFile: string | undefined;\n let script: string | undefined;\n let scriptArgs: string[] = [];\n let scriptTimeoutMs: number | undefined;\n\n if (mode === 'static-file') {\n if (typeof frontmatter.output_file !== 'string' || frontmatter.output_file.length === 0) {\n throw new Error(\n `SKILL.md \"${frontmatter.name}\": mode 'static-file' requires \"output_file\" (string)`,\n );\n }\n if (frontmatter.script !== undefined) {\n throw new Error(\n `SKILL.md \"${frontmatter.name}\": \"script\" is not valid in mode 'static-file'`,\n );\n }\n outputFile = frontmatter.output_file;\n } else if (mode === 'static-script' || mode === 'dynamic-script') {\n if (typeof frontmatter.script !== 'string' || frontmatter.script.length === 0) {\n throw new Error(`SKILL.md \"${frontmatter.name}\": mode '${mode}' requires \"script\" (string)`);\n }\n if (frontmatter.output_file !== undefined) {\n throw new Error(\n `SKILL.md \"${frontmatter.name}\": \"output_file\" is only valid in mode 'static-file'`,\n );\n }\n script = frontmatter.script;\n scriptArgs = validateScriptArgs(frontmatter.name, frontmatter.script_args);\n scriptTimeoutMs = validateScriptTimeoutMs(frontmatter.name, frontmatter.script_timeout_ms);\n } else {\n if (frontmatter.output_file !== undefined) {\n throw new Error(\n `SKILL.md \"${frontmatter.name}\": \"output_file\" is only valid in mode 'static-file'`,\n );\n }\n if (frontmatter.script !== undefined) {\n throw new Error(\n `SKILL.md \"${frontmatter.name}\": \"script\" is only valid in script modes (static-script, dynamic-script)`,\n );\n }\n if (frontmatter.script_args !== undefined) {\n throw new Error(\n `SKILL.md \"${frontmatter.name}\": \"script_args\" is only valid in script modes`,\n );\n }\n if (frontmatter.script_timeout_ms !== undefined) {\n throw new Error(\n `SKILL.md \"${frontmatter.name}\": \"script_timeout_ms\" is only valid in script modes`,\n );\n }\n }\n\n const image = typeof frontmatter.image === 'string' ? frontmatter.image : undefined;\n const imageFile = typeof frontmatter.image_file === 'string' ? frontmatter.image_file : undefined;\n\n const llmOverride = validateLlmOverride(frontmatter.name, frontmatter, mode);\n\n return {\n name: frontmatter.name,\n description: frontmatter.description,\n capabilities,\n priceSubunits,\n asset,\n mode,\n systemPrompt,\n tools,\n maxToolRounds,\n llmOverride,\n image,\n imageFile,\n outputFile,\n script,\n scriptArgs,\n scriptTimeoutMs,\n };\n}\n\nfunction buildSkillFromParsed(parsed: ParsedSkill, skillDir: string, logger: LoaderLogger): Skill {\n switch (parsed.mode) {\n case 'llm':\n return new ScriptSkill({\n name: parsed.name,\n description: parsed.description,\n capabilities: parsed.capabilities,\n priceSubunits: parsed.priceSubunits,\n asset: parsed.asset,\n skillDir,\n systemPrompt: parsed.systemPrompt,\n tools: parsed.tools,\n maxToolRounds: parsed.maxToolRounds,\n llmOverride: parsed.llmOverride,\n image: parsed.image,\n imageFile: parsed.imageFile,\n logger,\n });\n case 'static-file': {\n if (parsed.outputFile === undefined) {\n throw new Error(\n `SKILL.md \"${parsed.name}\": internal error - outputFile missing for mode 'static-file'`,\n );\n }\n const outputFilePath = resolveInsidePath(skillDir, parsed.outputFile);\n if (!outputFilePath) {\n throw new Error(\n `SKILL.md \"${parsed.name}\": \"output_file\" must stay inside the skill directory`,\n );\n }\n return new StaticFileSkill({\n name: parsed.name,\n description: parsed.description,\n capabilities: parsed.capabilities,\n priceSubunits: parsed.priceSubunits,\n asset: parsed.asset,\n outputFilePath,\n image: parsed.image,\n imageFile: parsed.imageFile,\n });\n }\n case 'static-script':\n case 'dynamic-script': {\n if (parsed.script === undefined) {\n throw new Error(\n `SKILL.md \"${parsed.name}\": internal error - script missing for mode '${parsed.mode}'`,\n );\n }\n const scriptPath = resolveInsidePath(skillDir, parsed.script);\n if (!scriptPath) {\n throw new Error(`SKILL.md \"${parsed.name}\": \"script\" must stay inside the skill directory`);\n }\n const Ctor = parsed.mode === 'static-script' ? StaticScriptSkill : DynamicScriptSkill;\n return new Ctor({\n name: parsed.name,\n description: parsed.description,\n capabilities: parsed.capabilities,\n priceSubunits: parsed.priceSubunits,\n asset: parsed.asset,\n scriptPath,\n scriptArgs: parsed.scriptArgs,\n scriptTimeoutMs: parsed.scriptTimeoutMs ?? DEFAULT_SCRIPT_TIMEOUT_MS,\n image: parsed.image,\n imageFile: parsed.imageFile,\n });\n }\n }\n}\n\n/**\n * Walk `skillsDir`, load each immediate subdirectory's SKILL.md, and\n * return constructed `Skill` instances (LLM or non-LLM depending on\n * frontmatter `mode`). Malformed directories are skipped with a `warn` log.\n */\nexport function loadSkillsFromDir(skillsDir: string, options: LoadSkillsOptions = {}): Skill[] {\n const logger = options.logger ?? {};\n const skills: Skill[] = [];\n\n let entries: string[];\n try {\n entries = readdirSync(skillsDir);\n } catch (error) {\n logger.debug?.({ err: error, skillsDir }, 'skills directory not readable; no skills loaded');\n return skills;\n }\n\n for (const entry of entries) {\n const entryPath = join(skillsDir, entry);\n try {\n if (!statSync(entryPath).isDirectory()) {\n continue;\n }\n } catch {\n continue;\n }\n\n const skillMdPath = join(entryPath, 'SKILL.md');\n try {\n const content = readFileSync(skillMdPath, 'utf-8');\n const { frontmatter, systemPrompt } = parseSkillMd(content);\n const parsed = validateSkillFrontmatter(frontmatter, systemPrompt, options);\n skills.push(buildSkillFromParsed(parsed, entryPath, logger));\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n logger.warn?.({ dir: entry, err: message }, 'skipping malformed skill directory');\n }\n }\n\n return skills;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/skills/scriptSkill.ts","../src/skills/staticFileSkill.ts","../src/skills/staticScriptSkill.ts","../src/skills/dynamicScriptSkill.ts","../src/skills/path-safety.ts","../src/constants.ts","../src/payment/assets.ts","../src/skills/loader.ts"],"names":["spawn","StringDecoder","readFile","dirname","resolve","relative","sep","Decimal","YAML","readdirSync","join","statSync","readFileSync"],"mappings":"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","file":"skills.cjs","sourcesContent":["import { spawn } from 'node:child_process';\nimport { StringDecoder } from 'node:string_decoder';\nimport type { Asset } from '../payment/assets';\nimport type {\n CompletionResult,\n LlmClient,\n Skill,\n SkillContext,\n SkillInput,\n SkillLlmOverride,\n SkillMode,\n SkillOutput,\n ToolCall,\n ToolDef,\n ToolResult,\n} from './types';\n\nexport const MAX_SCRIPT_OUTPUT = 1_000_000;\nexport const DEFAULT_SCRIPT_TIMEOUT_MS = 60_000;\n\nexport interface SkillToolDef {\n name: string;\n description: string;\n command: string[];\n parameters?: Array<{ name: string; description: string; required?: boolean }>;\n}\n\nexport interface ScriptSkillLogger {\n debug?(obj: Record<string, unknown>, msg?: string): void;\n}\n\nexport interface RunScriptOptions {\n cwd: string;\n /**\n * UTF-8 string written to the child's stdin, then stdin closed.\n * When undefined, stdin is closed immediately (EOF) so that children\n * which read stdin do not block until `timeoutMs`.\n */\n stdin?: string;\n /** Cancel the spawn. SIGKILL is sent on abort. */\n signal?: AbortSignal;\n /** Hard timeout in ms. Default `DEFAULT_SCRIPT_TIMEOUT_MS`. */\n timeoutMs?: number;\n /** Cap on stdout/stderr capture. Default `MAX_SCRIPT_OUTPUT`. */\n maxOutput?: number;\n /**\n * Full environment for the child. When omitted, the child inherits\n * `process.env`. Caller is responsible for spreading `process.env`\n * if PATH/HOME/etc. need to be preserved alongside extras.\n */\n env?: NodeJS.ProcessEnv;\n}\n\nexport interface RunScriptResult {\n stdout: string;\n stderr: string;\n /** Null when the process was killed by signal before exiting. */\n code: number | null;\n /** Set when spawn itself failed (ENOENT, EACCES, etc.). */\n spawnError?: Error;\n}\n\n/**\n * Spawn `cmd` with `args` and capture stdout/stderr. Never uses `shell: true`,\n * so shell metacharacters in arguments are safe. Caller is responsible for\n * checking `code === 0` / interpreting `spawnError`.\n */\nexport function runScript(\n cmd: string,\n args: string[],\n opts: RunScriptOptions,\n): Promise<RunScriptResult> {\n return new Promise((resolveResult) => {\n const maxOutput = opts.maxOutput ?? MAX_SCRIPT_OUTPUT;\n const timeoutMs = opts.timeoutMs ?? DEFAULT_SCRIPT_TIMEOUT_MS;\n\n const child = spawn(cmd, args, {\n cwd: opts.cwd,\n stdio: ['pipe', 'pipe', 'pipe'],\n timeout: timeoutMs,\n killSignal: 'SIGKILL',\n signal: opts.signal,\n env: opts.env,\n });\n\n let stdout = '';\n let stderr = '';\n const stdoutDecoder = new StringDecoder('utf8');\n const stderrDecoder = new StringDecoder('utf8');\n\n child.stdout?.on('data', (data: Buffer) => {\n if (stdout.length < maxOutput) {\n stdout += stdoutDecoder.write(data);\n if (stdout.length > maxOutput) {\n stdout = stdout.slice(0, maxOutput);\n }\n }\n });\n child.stderr?.on('data', (data: Buffer) => {\n if (stderr.length < maxOutput) {\n stderr += stderrDecoder.write(data);\n if (stderr.length > maxOutput) {\n stderr = stderr.slice(0, maxOutput);\n }\n }\n });\n\n child.on('close', (code) => {\n // Flush any bytes the decoder buffered because a multi-byte UTF-8\n // codepoint straddled the final chunk boundary.\n stdout += stdoutDecoder.end();\n stderr += stderrDecoder.end();\n resolveResult({ stdout, stderr, code });\n });\n\n child.on('error', (err) => {\n resolveResult({ stdout, stderr, code: null, spawnError: err });\n });\n\n if (child.stdin) {\n child.stdin.on('error', () => {\n // Ignore EPIPE - the child may exit without consuming all input.\n });\n // Always close stdin: a child that reads from stdin would otherwise\n // block until `timeoutMs` even when the caller has no input to send.\n child.stdin.end(opts.stdin ?? '');\n }\n });\n}\n\nexport interface ScriptSkillParams {\n name: string;\n description: string;\n capabilities: string[];\n priceSubunits: bigint;\n asset: Asset;\n skillDir: string;\n systemPrompt: string;\n tools: SkillToolDef[];\n maxToolRounds: number;\n /** Optional per-skill LLM override (provider/model pair and/or maxTokens). */\n llmOverride?: SkillLlmOverride;\n image?: string;\n imageFile?: string;\n logger?: ScriptSkillLogger;\n}\n\n/**\n * LLM-orchestrated skill runner. Tools are external scripts launched\n * via `child_process.spawn` (without `shell: true`, so shell\n * metacharacters in arguments are never interpreted - a security\n * property, not a convenience). Windows users cannot rely on\n * shell-script shebangs; target Linux/macOS for scripts.\n */\nexport class ScriptSkill implements Skill {\n name: string;\n description: string;\n capabilities: string[];\n priceSubunits: bigint;\n asset: Asset;\n mode: SkillMode = 'llm';\n readonly llmOverride?: SkillLlmOverride;\n image?: string;\n imageFile?: string;\n private skillDir: string;\n private systemPrompt: string;\n private tools: SkillToolDef[];\n private maxToolRounds: number;\n private logger: ScriptSkillLogger;\n\n constructor(params: ScriptSkillParams) {\n this.name = params.name;\n this.description = params.description;\n this.capabilities = params.capabilities;\n this.priceSubunits = params.priceSubunits;\n this.asset = params.asset;\n this.llmOverride = params.llmOverride;\n this.image = params.image;\n this.imageFile = params.imageFile;\n this.skillDir = params.skillDir;\n this.systemPrompt = params.systemPrompt;\n this.tools = params.tools;\n this.maxToolRounds = params.maxToolRounds;\n this.logger = params.logger ?? {};\n }\n\n async execute(input: SkillInput, ctx: SkillContext): Promise<SkillOutput> {\n const llm = this.resolveLlmClient(ctx);\n\n if (this.tools.length === 0) {\n const result = await llm.complete(this.systemPrompt, input.data, ctx.signal);\n return { data: result };\n }\n\n const toolDefs: ToolDef[] = this.tools.map((tool) => ({\n name: tool.name,\n description: tool.description,\n parameters: (tool.parameters ?? []).map((param) => ({\n name: param.name,\n description: param.description,\n required: param.required ?? true,\n })),\n }));\n\n const messages: unknown[] = [{ role: 'user', content: input.data }];\n\n for (let round = 0; round < this.maxToolRounds; round++) {\n if (ctx.signal?.aborted) {\n throw new Error('Job aborted');\n }\n const result: CompletionResult = await llm.completeWithTools(\n this.systemPrompt,\n messages,\n toolDefs,\n ctx.signal,\n );\n\n if (result.type === 'text') {\n return { data: result.text };\n }\n\n messages.push(result.assistantMessage);\n\n const toolResults: ToolResult[] = [];\n for (const call of result.calls) {\n const toolDef = this.tools.find((tool) => tool.name === call.name);\n if (!toolDef) {\n toolResults.push({\n callId: call.id,\n content: `Error: unknown tool \"${call.name}\"`,\n });\n continue;\n }\n const output = await this.runTool(toolDef, call, ctx.signal);\n toolResults.push({ callId: call.id, content: output });\n }\n\n messages.push(...llm.formatToolResultMessages(toolResults));\n }\n\n throw new Error(`Max tool rounds (${this.maxToolRounds}) exceeded`);\n }\n\n /**\n * Resolve the LLM client for this skill from the runtime context.\n *\n * Contract:\n * - When `llmOverride` is set, `ctx.getLlm` MUST be wired. Falling back to\n * `ctx.llm` (the agent default) would silently use the wrong configuration\n * for max-tokens-only overrides.\n * - When no override is set, prefer `ctx.getLlm()` (returns the agent\n * default), then fall back to `ctx.llm` for legacy callers that wire only\n * a single client.\n */\n private resolveLlmClient(ctx: SkillContext): LlmClient {\n let client: LlmClient | undefined;\n if (this.llmOverride) {\n client = ctx.getLlm?.(this.llmOverride);\n if (!client) {\n throw new Error(\n `Skill \"${this.name}\" requires ctx.getLlm to be configured (llmOverride is set)`,\n );\n }\n return client;\n }\n client = ctx.getLlm?.() ?? ctx.llm;\n if (!client) {\n throw new Error('LLM client not configured for skill runtime');\n }\n return client;\n }\n\n private async runTool(\n toolDef: SkillToolDef,\n call: ToolCall,\n signal?: AbortSignal,\n ): Promise<string> {\n const args = [...toolDef.command];\n const cmd = args.shift();\n if (!cmd) {\n return `Error: tool \"${toolDef.name}\" has an empty command`;\n }\n\n const params = toolDef.parameters ?? [];\n for (let index = 0; index < params.length; index++) {\n const param = params[index];\n if (!param) {\n continue;\n }\n const value = call.arguments[param.name];\n if (value === undefined) {\n continue;\n }\n if (param.required && index === 0) {\n args.push(String(value));\n } else {\n args.push(`--${param.name}`, String(value));\n }\n }\n\n const result = await runScript(cmd, args, { cwd: this.skillDir, signal });\n\n if (result.spawnError) {\n return `Error: ${result.spawnError.message}`;\n }\n if (result.code === 0) {\n return result.stdout.trim();\n }\n this.logger.debug?.(\n { tool: toolDef.name, code: result.code, stderrLen: result.stderr.length },\n 'skill tool exited non-zero',\n );\n return `Error (exit ${result.code}): ${result.stderr.trim() || result.stdout.trim()}`;\n }\n}\n","import { readFile } from 'node:fs/promises';\nimport type { Asset } from '../payment/assets';\nimport type { Skill, SkillContext, SkillInput, SkillMode, SkillOutput } from './types';\n\n/** Hard ceiling on result size for static-file skills. NIP-90 result events\n * travel through relays that may reject very large payloads; cap at 256 KB\n * of UTF-8. Larger files should use a script that streams to an external host. */\nexport const MAX_STATIC_FILE_SIZE = 256 * 1024;\n\nexport interface StaticFileSkillParams {\n name: string;\n description: string;\n capabilities: string[];\n priceSubunits: bigint;\n asset: Asset;\n /** Absolute path to the file whose contents are returned on each job. */\n outputFilePath: string;\n image?: string;\n imageFile?: string;\n}\n\n/**\n * Returns the contents of a fixed file as the job result. Reads on every\n * `execute()` so authors can edit the file without restarting the agent.\n */\nexport class StaticFileSkill implements Skill {\n name: string;\n description: string;\n capabilities: string[];\n priceSubunits: bigint;\n asset: Asset;\n mode: SkillMode = 'static-file';\n image?: string;\n imageFile?: string;\n private outputFilePath: string;\n\n constructor(params: StaticFileSkillParams) {\n this.name = params.name;\n this.description = params.description;\n this.capabilities = params.capabilities;\n this.priceSubunits = params.priceSubunits;\n this.asset = params.asset;\n this.image = params.image;\n this.imageFile = params.imageFile;\n this.outputFilePath = params.outputFilePath;\n }\n\n async execute(_input: SkillInput, _ctx: SkillContext): Promise<SkillOutput> {\n // Measure UTF-8 bytes, not JS string length: relays reject by byte size,\n // and a non-ASCII file is 1.5-4x its char count in UTF-8.\n const buffer = await readFile(this.outputFilePath);\n if (buffer.length > MAX_STATIC_FILE_SIZE) {\n throw new Error(\n `static-file output exceeds ${MAX_STATIC_FILE_SIZE} bytes (got ${buffer.length})`,\n );\n }\n return { data: buffer.toString('utf-8') };\n }\n}\n","import { dirname } from 'node:path';\nimport type { Asset } from '../payment/assets';\nimport { runScript } from './scriptSkill';\nimport type { Skill, SkillContext, SkillInput, SkillMode, SkillOutput } from './types';\n\nexport interface StaticScriptSkillParams {\n name: string;\n description: string;\n capabilities: string[];\n priceSubunits: bigint;\n asset: Asset;\n /** Absolute path to the script. */\n scriptPath: string;\n /** Extra args appended after the script path. */\n scriptArgs: string[];\n /** Optional override of the default 60s timeout. */\n scriptTimeoutMs?: number;\n /**\n * Full environment for the script. When omitted, the script inherits\n * `process.env`. Callers (typically the CLI loader) spread `process.env`\n * and add narrowly-scoped secrets like provider API keys.\n */\n scriptEnv?: NodeJS.ProcessEnv;\n image?: string;\n imageFile?: string;\n}\n\n/**\n * Spawns a configured script with no stdin and returns its trimmed stdout.\n * Throws on non-zero exit so the runtime surfaces a sanitized error.\n * The script runs with cwd set to its containing directory so relative\n * paths inside the script behave intuitively.\n */\nexport class StaticScriptSkill implements Skill {\n name: string;\n description: string;\n capabilities: string[];\n priceSubunits: bigint;\n asset: Asset;\n mode: SkillMode = 'static-script';\n image?: string;\n imageFile?: string;\n private scriptPath: string;\n private scriptArgs: string[];\n private scriptTimeoutMs?: number;\n private scriptEnv?: NodeJS.ProcessEnv;\n\n constructor(params: StaticScriptSkillParams) {\n this.name = params.name;\n this.description = params.description;\n this.capabilities = params.capabilities;\n this.priceSubunits = params.priceSubunits;\n this.asset = params.asset;\n this.image = params.image;\n this.imageFile = params.imageFile;\n this.scriptPath = params.scriptPath;\n this.scriptArgs = params.scriptArgs;\n this.scriptTimeoutMs = params.scriptTimeoutMs;\n this.scriptEnv = params.scriptEnv;\n }\n\n async execute(_input: SkillInput, ctx: SkillContext): Promise<SkillOutput> {\n const result = await runScript(this.scriptPath, this.scriptArgs, {\n cwd: dirname(this.scriptPath),\n signal: ctx.signal,\n timeoutMs: this.scriptTimeoutMs,\n env: this.scriptEnv,\n });\n if (result.spawnError) {\n throw new Error(`script spawn failed: ${result.spawnError.message}`);\n }\n if (result.code !== 0) {\n const detail = result.stderr.trim() || result.stdout.trim() || '(no output)';\n throw new Error(`script failed (exit ${result.code}): ${detail}`);\n }\n return { data: result.stdout.trim() };\n }\n}\n","import { dirname } from 'node:path';\nimport type { Asset } from '../payment/assets';\nimport { runScript } from './scriptSkill';\nimport type { Skill, SkillContext, SkillInput, SkillMode, SkillOutput } from './types';\n\nexport interface DynamicScriptSkillParams {\n name: string;\n description: string;\n capabilities: string[];\n priceSubunits: bigint;\n asset: Asset;\n /** Absolute path to the script. */\n scriptPath: string;\n /** Extra args appended after the script path. */\n scriptArgs: string[];\n /** Optional override of the default 60s timeout. */\n scriptTimeoutMs?: number;\n /**\n * Full environment for the script. When omitted, the script inherits\n * `process.env`. Callers (typically the CLI loader) spread `process.env`\n * and add narrowly-scoped secrets like provider API keys.\n */\n scriptEnv?: NodeJS.ProcessEnv;\n image?: string;\n imageFile?: string;\n}\n\n/**\n * Pipes the user's job input to the script's stdin and returns its\n * trimmed stdout. Enables script-backed capabilities (proxies to\n * external models, classical NLP, custom workers) without an LLM key\n * on the elisym side.\n */\nexport class DynamicScriptSkill implements Skill {\n name: string;\n description: string;\n capabilities: string[];\n priceSubunits: bigint;\n asset: Asset;\n mode: SkillMode = 'dynamic-script';\n image?: string;\n imageFile?: string;\n private scriptPath: string;\n private scriptArgs: string[];\n private scriptTimeoutMs?: number;\n private scriptEnv?: NodeJS.ProcessEnv;\n\n constructor(params: DynamicScriptSkillParams) {\n this.name = params.name;\n this.description = params.description;\n this.capabilities = params.capabilities;\n this.priceSubunits = params.priceSubunits;\n this.asset = params.asset;\n this.image = params.image;\n this.imageFile = params.imageFile;\n this.scriptPath = params.scriptPath;\n this.scriptArgs = params.scriptArgs;\n this.scriptTimeoutMs = params.scriptTimeoutMs;\n this.scriptEnv = params.scriptEnv;\n }\n\n async execute(input: SkillInput, ctx: SkillContext): Promise<SkillOutput> {\n const result = await runScript(this.scriptPath, this.scriptArgs, {\n cwd: dirname(this.scriptPath),\n stdin: input.data,\n signal: ctx.signal,\n timeoutMs: this.scriptTimeoutMs,\n env: this.scriptEnv,\n });\n if (result.spawnError) {\n throw new Error(`script spawn failed: ${result.spawnError.message}`);\n }\n if (result.code !== 0) {\n const detail = result.stderr.trim() || result.stdout.trim() || '(no output)';\n throw new Error(`script failed (exit ${result.code}): ${detail}`);\n }\n return { data: result.stdout.trim() };\n }\n}\n","import { relative, resolve, sep } from 'node:path';\n\n/**\n * Resolve `value` relative to `rootDir` and reject anything that escapes\n * the root (`..` segments, absolute paths outside it, or the root itself).\n *\n * Returns the absolute path on success, or null on rejection so callers\n * can surface a precise error message.\n */\nexport function resolveInsidePath(rootDir: string, value: string): string | null {\n const root = resolve(rootDir);\n const candidate = resolve(root, value);\n const rel = relative(root, candidate);\n if (rel === '' || rel.startsWith('..') || rel.includes(`..${sep}`)) {\n return null;\n }\n return candidate;\n}\n","import type { Address } from '@solana/kit';\n\nexport const RELAYS = [\n 'wss://relay.damus.io',\n 'wss://nos.lol',\n 'wss://relay.nostr.band',\n 'wss://relay.primal.net',\n 'wss://relay.snort.social',\n];\n\nexport const KIND_APP_HANDLER = 31990;\nexport const KIND_JOB_REQUEST_BASE = 5000;\nexport const KIND_JOB_RESULT_BASE = 6000;\nexport const KIND_JOB_FEEDBACK = 7000;\nexport const DEFAULT_KIND_OFFSET = 100;\n\n/** Default job request kind (5000 + 100). */\nexport const KIND_JOB_REQUEST = KIND_JOB_REQUEST_BASE + DEFAULT_KIND_OFFSET;\n/** Default job result kind (6000 + 100). */\nexport const KIND_JOB_RESULT = KIND_JOB_RESULT_BASE + DEFAULT_KIND_OFFSET;\n\n/** Compute a job request kind from an offset (5000 + offset). */\nexport function jobRequestKind(offset: number): number {\n if (!Number.isInteger(offset) || offset < 0 || offset >= 1000) {\n throw new Error(`Invalid kind offset: ${offset}. Must be integer 0-999.`);\n }\n return KIND_JOB_REQUEST_BASE + offset;\n}\n\n/** Compute a job result kind from an offset (6000 + offset). */\nexport function jobResultKind(offset: number): number {\n if (!Number.isInteger(offset) || offset < 0 || offset >= 1000) {\n throw new Error(`Invalid kind offset: ${offset}. Must be integer 0-999.`);\n }\n return KIND_JOB_RESULT_BASE + offset;\n}\n\n/** Ephemeral ping/pong kinds (not stored by relays, forwarded in real-time). */\nexport const KIND_PING = 20200;\nexport const KIND_PONG = 20201;\n\nexport const LAMPORTS_PER_SOL = 1_000_000_000;\n\n/**\n * Solana program ID for the elisym protocol config (devnet deployment).\n *\n * The Anchor program at this address is the source of truth for fee bps,\n * treasury address, and admin rotation state. Read via `getProtocolConfig`.\n */\nexport const PROTOCOL_PROGRAM_ID_DEVNET = 'BrX1CRkSgvcjxBvc2bgc3QqgWjinusofDmeP7ZVxvwrE' as Address;\n\n/**\n * Read-only marker pubkey attached as a non-signer account to every elisym\n * payment transaction. Lets indexers enumerate every elisym tx network-wide\n * via a single `getSignaturesForAddress(ELISYM_PROTOCOL_TAG)` call,\n * independent of fee size or recipient.\n *\n * The account does not need to exist on-chain; including its pubkey as an\n * extra read-only account in the provider transfer instruction is enough for\n * Solana's tx-by-account index to pick it up. The corresponding secret key\n * was generated and discarded - the tag never signs and never holds funds.\n */\nexport const ELISYM_PROTOCOL_TAG = 'ELiZksgwDt41LaeuPDLkUfWgFXhGgVayTMP7L5nTSEL8' as Address;\n\nexport type ProtocolCluster = 'devnet' | 'mainnet' | 'localnet';\n\n/**\n * Resolve the elisym-config program ID for a given Solana cluster.\n * Mainnet is intentionally unsupported until the program ships there.\n */\nexport function getProtocolProgramId(cluster: ProtocolCluster): Address {\n switch (cluster) {\n case 'devnet':\n case 'localnet':\n return PROTOCOL_PROGRAM_ID_DEVNET;\n case 'mainnet':\n throw new Error('Protocol program is not deployed on mainnet yet');\n }\n}\n\n/** Default values for timeouts, retries, and batch sizes. */\nexport const DEFAULTS = {\n SUBSCRIPTION_TIMEOUT_MS: 120_000,\n PING_TIMEOUT_MS: 3_000,\n PING_RETRIES: 2,\n PING_CACHE_TTL_MS: 30_000,\n PAYMENT_EXPIRY_SECS: 600,\n BATCH_SIZE: 250,\n QUERY_TIMEOUT_MS: 15_000,\n EOSE_TIMEOUT_MS: 3_000,\n VERIFY_RETRIES: 10,\n VERIFY_INTERVAL_MS: 3_000,\n VERIFY_BY_REF_RETRIES: 15,\n VERIFY_BY_REF_INTERVAL_MS: 2_000,\n RESULT_RETRY_COUNT: 3,\n RESULT_RETRY_BASE_MS: 1_000,\n QUERY_MAX_CONCURRENCY: 6,\n VERIFY_SIGNATURE_LIMIT: 25,\n} as const;\n\n/** Protocol limits for input validation. */\nexport const LIMITS = {\n MAX_INPUT_LENGTH: 100_000,\n MAX_TIMEOUT_SECS: 600,\n MAX_CAPABILITIES: 20,\n MAX_DESCRIPTION_LENGTH: 500,\n MAX_AGENT_NAME_LENGTH: 64,\n MAX_CAPABILITY_LENGTH: 64,\n} as const;\n","/**\n * Multi-asset / multi-chain payment model.\n *\n * `Asset` describes a currency a customer can spend: native coins (SOL, ETH, BTC)\n * or tokens (SPL, ERC-20). `assetKey` produces a stable string id for Map lookups.\n *\n * Today only `NATIVE_SOL` is in `KNOWN_ASSETS`. SPL (USDC) and other chains are\n * extended by adding entries to `KNOWN_ASSETS` and, where relevant, to the\n * MCP `DEFAULT_SESSION_LIMITS` catalogue.\n */\n\nimport Decimal from 'decimal.js-light';\n\nexport type Chain = 'solana';\n\nexport interface Asset {\n chain: Chain;\n /** Lowercase token id: 'sol', 'usdc', 'btc', 'eth'. */\n token: string;\n /** SPL mint / ERC-20 contract. Undefined for a native coin. */\n mint?: string;\n /** Subunits per whole (9 SOL, 6 USDC, 8 BTC, 18 ETH). */\n decimals: number;\n /** Display symbol: 'SOL', 'USDC'. */\n symbol: string;\n}\n\nexport const NATIVE_SOL: Asset = {\n chain: 'solana',\n token: 'sol',\n decimals: 9,\n symbol: 'SOL',\n};\n\nexport const USDC_SOLANA_DEVNET: Asset = {\n chain: 'solana',\n token: 'usdc',\n mint: '4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU',\n decimals: 6,\n symbol: 'USDC',\n};\n\nexport const KNOWN_ASSETS: readonly Asset[] = [NATIVE_SOL, USDC_SOLANA_DEVNET];\n\n/** Stable Map key for `Asset`. Same shape regardless of Asset identity. */\nexport function assetKey(a: Pick<Asset, 'chain' | 'token' | 'mint'>): string {\n return a.mint ? `${a.chain}:${a.token}:${a.mint}` : `${a.chain}:${a.token}`;\n}\n\n/** Find a known asset by (chain, token, mint). Returns undefined if unknown. */\nexport function resolveKnownAsset(chain: string, token: string, mint?: string): Asset | undefined {\n const key = mint ? `${chain}:${token}:${mint}` : `${chain}:${token}`;\n return KNOWN_ASSETS.find((asset) => assetKey(asset) === key);\n}\n\n/** Reverse lookup: given an assetKey string, return the known asset or undefined. */\nexport function assetByKey(key: string): Asset | undefined {\n return KNOWN_ASSETS.find((asset) => assetKey(asset) === key);\n}\n\n/**\n * Resolve the asset a payment request targets. Returns `NATIVE_SOL` when the\n * request has no `asset` field (back-compat with payment requests published\n * before multi-asset support). Throws when `asset` is present but refers to an\n * asset that isn't in `KNOWN_ASSETS` - callers that want to tolerate unknown\n * assets should check `resolveKnownAsset` directly instead.\n */\nexport function resolveAssetFromPaymentRequest(request: {\n asset?: { chain: string; token: string; mint?: string };\n}): Asset {\n if (!request.asset) {\n return NATIVE_SOL;\n }\n const found = resolveKnownAsset(request.asset.chain, request.asset.token, request.asset.mint);\n if (!found) {\n const display = request.asset.mint\n ? `${request.asset.chain}:${request.asset.token}:${request.asset.mint}`\n : `${request.asset.chain}:${request.asset.token}`;\n throw new Error(\n `Unknown asset in payment request: ${display}. ` +\n `Known assets: ${KNOWN_ASSETS.map(assetKey).join(', ')}`,\n );\n }\n return found;\n}\n\nconst DECIMAL_RE = /^(\\d+\\.\\d*|\\d*\\.\\d+|\\d+)$/;\n\n/**\n * Parse a human amount string (\"0.5\", \"1\", \"0.000001\") into raw subunits (BigInt).\n * Uses integer math to avoid float precision issues.\n *\n * Throws on: empty, negative, zero, malformed, too many fractional digits, or\n * a value exceeding `Number.MAX_SAFE_INTEGER` (to keep downstream `Number(...)`\n * call-sites safe).\n */\nexport function parseAssetAmount(asset: Asset, human: string): bigint {\n const trimmed = human.trim();\n if (!trimmed) {\n throw new Error(`${asset.symbol} amount is empty`);\n }\n if (trimmed.startsWith('-')) {\n throw new Error(`${asset.symbol} amount cannot be negative`);\n }\n if (!DECIMAL_RE.test(trimmed)) {\n throw new Error(\n `${asset.symbol} amount must be a non-negative decimal (e.g. \"0.5\", \"1\"); got \"${human}\"`,\n );\n }\n\n const dotPos = trimmed.indexOf('.');\n let wholePart: string;\n if (dotPos === -1) {\n wholePart = trimmed;\n } else if (dotPos === 0) {\n wholePart = '0';\n } else {\n wholePart = trimmed.slice(0, dotPos);\n }\n const fracPart = dotPos === -1 ? '' : trimmed.slice(dotPos + 1);\n\n if (fracPart.length > asset.decimals) {\n throw new Error(\n `${asset.symbol} amount has too many decimals (max ${asset.decimals}); got \"${human}\"`,\n );\n }\n\n const unit = 10n ** BigInt(asset.decimals);\n const whole = BigInt(wholePart);\n const frac = fracPart ? BigInt(fracPart.padEnd(asset.decimals, '0')) : 0n;\n const raw = whole * unit + frac;\n\n if (raw === 0n) {\n throw new Error(`${asset.symbol} amount must be positive; got \"${human}\"`);\n }\n if (raw > BigInt(Number.MAX_SAFE_INTEGER)) {\n throw new Error(\n `${asset.symbol} amount exceeds safe range (max ${Number.MAX_SAFE_INTEGER} subunits)`,\n );\n }\n return raw;\n}\n\n// Cloned config keeps `Decimal.toString()` from switching to exponential notation\n// for small fractional amounts (e.g. 1 lamport = 1e-9 SOL).\nconst FormatDecimal = Decimal.clone({ toExpNeg: -100, toExpPos: 100, precision: 50 });\n\n/**\n * Format raw subunits back to `\"<value> <SYMBOL>\"`. Trailing zeros and a bare\n * trailing dot are stripped, so 0.01 USDC renders as `\"0.01 USDC\"` rather than\n * `\"0.010000 USDC\"`.\n */\nexport function formatAssetAmount(asset: Asset, raw: bigint): string {\n const value = new FormatDecimal(raw.toString()).div(new FormatDecimal(10).pow(asset.decimals));\n return `${value.toString()} ${asset.symbol}`;\n}\n","import { readdirSync, readFileSync, statSync } from 'node:fs';\nimport { join } from 'node:path';\nimport YAML from 'yaml';\nimport { LAMPORTS_PER_SOL } from '../constants';\nimport type { SkillRateLimit } from '../llm-health/types';\nimport {\n type Asset,\n NATIVE_SOL,\n USDC_SOLANA_DEVNET,\n parseAssetAmount,\n resolveKnownAsset,\n} from '../payment/assets';\nimport { DynamicScriptSkill } from './dynamicScriptSkill';\nimport { resolveInsidePath } from './path-safety';\nimport { DEFAULT_SCRIPT_TIMEOUT_MS, ScriptSkill, type SkillToolDef } from './scriptSkill';\nimport { StaticFileSkill } from './staticFileSkill';\nimport { StaticScriptSkill } from './staticScriptSkill';\nimport type { Skill, SkillLlmOverride, SkillMode } from './types';\n\nconst MAX_TOKENS_LIMIT = 200_000;\n\nexport const DEFAULT_MAX_TOOL_ROUNDS = 10;\n\nconst VALID_MODES: readonly SkillMode[] = [\n 'llm',\n 'static-file',\n 'static-script',\n 'dynamic-script',\n] as const;\n\nexport interface SkillFrontmatter {\n name?: unknown;\n description?: unknown;\n capabilities?: unknown;\n price?: unknown;\n /** Lowercase token id ('sol', 'usdc'). Defaults to 'sol' for back-compat. */\n token?: unknown;\n /** SPL mint (base58). Optional - resolved from known assets when omitted. */\n mint?: unknown;\n image?: unknown;\n image_file?: unknown;\n tools?: unknown;\n max_tool_rounds?: unknown;\n /** Optional per-skill LLM provider override (e.g. 'anthropic', 'openai'). Pairs with `model`. */\n provider?: unknown;\n /** Optional per-skill LLM model override. Pairs with `provider`. */\n model?: unknown;\n /** Optional per-skill max_tokens override. Independent of provider/model. */\n max_tokens?: unknown;\n /** Execution mode. Default 'llm'. */\n mode?: unknown;\n /** Required when mode === 'static-file'. Path relative to skill dir. */\n output_file?: unknown;\n /** Required when mode === 'static-script' | 'dynamic-script'. Path relative to skill dir. */\n script?: unknown;\n /** Optional positional args appended after the script. */\n script_args?: unknown;\n /** Optional override of `DEFAULT_SCRIPT_TIMEOUT_MS`. */\n script_timeout_ms?: unknown;\n /**\n * Optional per-skill rate limit. Applies to any skill mode. Snake-case\n * keys here match the YAML frontmatter convention; parsed into camelCase\n * `rateLimit` on `ParsedSkill`.\n */\n rate_limit?: unknown;\n}\n\nexport interface ParsedSkill {\n name: string;\n description: string;\n capabilities: string[];\n /** Price in subunits of `asset`. */\n priceSubunits: bigint;\n asset: Asset;\n mode: SkillMode;\n systemPrompt: string;\n tools: SkillToolDef[];\n maxToolRounds: number;\n /**\n * Per-skill LLM override (only present when mode === 'llm' and the SKILL.md\n * declared at least one of `provider`/`model`/`max_tokens`). Parse-time\n * invariant: `provider` set iff `model` set.\n */\n llmOverride?: SkillLlmOverride;\n image?: string;\n imageFile?: string;\n /** Set when mode === 'static-file'. */\n outputFile?: string;\n /** Set when mode is a script mode. */\n script?: string;\n /** Empty when no script. */\n scriptArgs: string[];\n /** Undefined => caller uses `DEFAULT_SCRIPT_TIMEOUT_MS`. */\n scriptTimeoutMs?: number;\n /** Optional per-skill rate limit (any mode). */\n rateLimit?: SkillRateLimit;\n}\n\nexport interface LoaderLogger {\n debug?(obj: Record<string, unknown>, msg?: string): void;\n warn?(obj: Record<string, unknown>, msg?: string): void;\n}\n\nexport interface LoadSkillsOptions {\n /**\n * When true, SKILL.md may declare `price: 0` or omit `price` entirely\n * and the skill is loaded as free (`priceLamports === 0n`). Default\n * false: paid-only (plugin's historical behaviour).\n */\n allowFreeSkills?: boolean;\n logger?: LoaderLogger;\n}\n\nfunction solToLamports(sol: string | number): bigint {\n const asNumber = typeof sol === 'string' ? Number(sol) : sol;\n if (!Number.isFinite(asNumber) || asNumber < 0) {\n throw new Error(`Invalid SOL amount: ${sol}`);\n }\n return BigInt(Math.round(asNumber * LAMPORTS_PER_SOL));\n}\n\n/**\n * Resolve the asset a SKILL.md declares.\n *\n * - `token` absent or `'sol'` => native SOL (NATIVE_SOL).\n * - `token: 'usdc'` (+ optional `mint`) => resolved via `resolveKnownAsset`;\n * falls back to `USDC_SOLANA_DEVNET` when `mint` is omitted so operators\n * don't need to memorize the devnet mint address.\n * - Any unknown `token` throws.\n */\nfunction resolveSkillAsset(skillName: string, token: unknown, mint: unknown): Asset {\n if (token === undefined || token === null) {\n return NATIVE_SOL;\n }\n if (typeof token !== 'string' || token.length === 0) {\n throw new Error(`SKILL.md \"${skillName}\": \"token\" must be a non-empty string`);\n }\n let mintString: string | undefined;\n if (mint === undefined || mint === null) {\n mintString = undefined;\n } else if (typeof mint === 'string') {\n mintString = mint;\n } else {\n throw new Error(`SKILL.md \"${skillName}\": \"mint\" must be a base58 string`);\n }\n\n const normalized = token.toLowerCase();\n if (normalized === 'sol') {\n return NATIVE_SOL;\n }\n if (normalized === 'usdc' && mintString === undefined) {\n return USDC_SOLANA_DEVNET;\n }\n const resolved = resolveKnownAsset('solana', normalized, mintString);\n if (!resolved) {\n const display = mintString ? `solana:${normalized}:${mintString}` : `solana:${normalized}`;\n throw new Error(\n `SKILL.md \"${skillName}\": unknown asset ${display}. ` +\n `Known assets: sol, usdc (devnet mint 4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU).`,\n );\n }\n return resolved;\n}\n\nexport function parseSkillMd(content: string): {\n frontmatter: SkillFrontmatter;\n systemPrompt: string;\n} {\n const lines = content.split('\\n');\n let start = -1;\n let end = -1;\n\n for (let index = 0; index < lines.length; index++) {\n if (lines[index]?.trim() === '---') {\n if (start === -1) {\n start = index;\n } else {\n end = index;\n break;\n }\n }\n }\n\n if (start === -1 || end === -1) {\n throw new Error('SKILL.md must have YAML frontmatter between --- delimiters');\n }\n\n const yamlStr = lines.slice(start + 1, end).join('\\n');\n const frontmatter = YAML.parse(yamlStr) as SkillFrontmatter;\n const systemPrompt = lines\n .slice(end + 1)\n .join('\\n')\n .trim();\n return { frontmatter, systemPrompt };\n}\n\nfunction validateTool(raw: unknown, skillName: string, index: number): SkillToolDef {\n if (typeof raw !== 'object' || raw === null) {\n throw new Error(`skill \"${skillName}\" tool[${index}] must be an object`);\n }\n const tool = raw as Record<string, unknown>;\n if (typeof tool.name !== 'string' || tool.name.length === 0) {\n throw new Error(`skill \"${skillName}\" tool[${index}] missing name`);\n }\n if (typeof tool.description !== 'string' || tool.description.length === 0) {\n throw new Error(`skill \"${skillName}\" tool \"${tool.name}\" missing description`);\n }\n if (!Array.isArray(tool.command) || tool.command.length === 0) {\n throw new Error(`skill \"${skillName}\" tool \"${tool.name}\" missing command[] array`);\n }\n for (const part of tool.command) {\n if (typeof part !== 'string') {\n throw new Error(`skill \"${skillName}\" tool \"${tool.name}\" command[] must be strings`);\n }\n }\n const parameters: SkillToolDef['parameters'] = [];\n if (tool.parameters !== undefined) {\n if (!Array.isArray(tool.parameters)) {\n throw new Error(`skill \"${skillName}\" tool \"${tool.name}\" parameters must be an array`);\n }\n for (let paramIndex = 0; paramIndex < tool.parameters.length; paramIndex++) {\n const param = tool.parameters[paramIndex];\n if (typeof param !== 'object' || param === null) {\n throw new Error(\n `skill \"${skillName}\" tool \"${tool.name}\" parameter[${paramIndex}] must be an object`,\n );\n }\n const record = param as Record<string, unknown>;\n if (typeof record.name !== 'string' || record.name.length === 0) {\n throw new Error(\n `skill \"${skillName}\" tool \"${tool.name}\" parameter[${paramIndex}] missing name`,\n );\n }\n if (typeof record.description !== 'string') {\n throw new Error(\n `skill \"${skillName}\" tool \"${tool.name}\" parameter \"${record.name}\" missing description`,\n );\n }\n parameters.push({\n name: record.name,\n description: record.description,\n required: record.required === undefined ? undefined : Boolean(record.required),\n });\n }\n }\n return {\n name: tool.name,\n description: tool.description,\n command: tool.command as string[],\n parameters,\n };\n}\n\nfunction validateMode(skillName: string, raw: unknown): SkillMode {\n if (raw === undefined || raw === null) {\n return 'llm';\n }\n if (typeof raw !== 'string') {\n throw new Error(`SKILL.md \"${skillName}\": \"mode\" must be a string`);\n }\n if (!(VALID_MODES as readonly string[]).includes(raw)) {\n throw new Error(\n `SKILL.md \"${skillName}\": invalid mode \"${raw}\". Allowed: ${VALID_MODES.join(', ')}`,\n );\n }\n return raw as SkillMode;\n}\n\nfunction validateScriptArgs(skillName: string, raw: unknown): string[] {\n if (raw === undefined || raw === null) {\n return [];\n }\n if (!Array.isArray(raw)) {\n throw new Error(`SKILL.md \"${skillName}\": \"script_args\" must be an array of strings`);\n }\n for (const part of raw) {\n if (typeof part !== 'string') {\n throw new Error(`SKILL.md \"${skillName}\": \"script_args\" entries must be strings`);\n }\n }\n return raw as string[];\n}\n\n/**\n * Parse the optional per-skill LLM override block. The all-or-nothing rule\n * applies to (`provider`, `model`); `max_tokens` is independent.\n *\n * Returns `undefined` when no LLM override fields are declared at all.\n * Throws on partial pair, invalid provider, empty model, or out-of-range\n * max_tokens.\n *\n * Rejects all three fields when `mode !== 'llm'`.\n */\nfunction validateLlmOverride(\n skillName: string,\n frontmatter: SkillFrontmatter,\n mode: SkillMode,\n): SkillLlmOverride | undefined {\n const hasProvider = frontmatter.provider !== undefined && frontmatter.provider !== null;\n const hasModel = frontmatter.model !== undefined && frontmatter.model !== null;\n const hasMaxTokens = frontmatter.max_tokens !== undefined && frontmatter.max_tokens !== null;\n\n if (!hasProvider && !hasModel && !hasMaxTokens) {\n return undefined;\n }\n\n if (mode !== 'llm') {\n throw new Error(\n `SKILL.md \"${skillName}\": \"provider\"/\"model\"/\"max_tokens\" are only valid in mode 'llm' (got '${mode}')`,\n );\n }\n\n if (hasProvider !== hasModel) {\n throw new Error(\n `SKILL.md \"${skillName}\": \"provider\" and \"model\" must be set together (declare both, or neither)`,\n );\n }\n\n const override: SkillLlmOverride = {};\n\n if (hasProvider && hasModel) {\n if (typeof frontmatter.provider !== 'string' || frontmatter.provider.length === 0) {\n throw new Error(`SKILL.md \"${skillName}\": \"provider\" must be a non-empty string`);\n }\n if (typeof frontmatter.model !== 'string' || frontmatter.model.length === 0) {\n throw new Error(`SKILL.md \"${skillName}\": \"model\" must be a non-empty string`);\n }\n override.provider = frontmatter.provider;\n override.model = frontmatter.model;\n }\n\n if (hasMaxTokens) {\n if (\n typeof frontmatter.max_tokens !== 'number' ||\n !Number.isInteger(frontmatter.max_tokens) ||\n frontmatter.max_tokens <= 0 ||\n frontmatter.max_tokens > MAX_TOKENS_LIMIT\n ) {\n throw new Error(\n `SKILL.md \"${skillName}\": \"max_tokens\" must be a positive integer <= ${MAX_TOKENS_LIMIT}`,\n );\n }\n override.maxTokens = frontmatter.max_tokens;\n }\n\n return override;\n}\n\nconst MAX_RATE_LIMIT_WINDOW_SECS = 86400;\nconst MAX_RATE_LIMIT_PER_WINDOW = 10000;\n\n/**\n * Parse the optional per-skill `rate_limit` block. Snake-case in YAML,\n * camelCase in the returned shape. Returns `undefined` when absent.\n *\n * Throws on partial or out-of-range values - we want operators to notice\n * misconfigurations at startup rather than have them silently fall back\n * to defaults at runtime.\n */\nfunction validateRateLimit(skillName: string, raw: unknown): SkillRateLimit | undefined {\n if (raw === undefined || raw === null) {\n return undefined;\n }\n if (typeof raw !== 'object') {\n throw new Error(`SKILL.md \"${skillName}\": \"rate_limit\" must be an object`);\n }\n const record = raw as Record<string, unknown>;\n const perWindowSecs = record.per_window_secs;\n const maxPerWindow = record.max_per_window;\n if (\n typeof perWindowSecs !== 'number' ||\n !Number.isInteger(perWindowSecs) ||\n perWindowSecs < 1 ||\n perWindowSecs > MAX_RATE_LIMIT_WINDOW_SECS\n ) {\n throw new Error(\n `SKILL.md \"${skillName}\": \"rate_limit.per_window_secs\" must be an integer between 1 and ${MAX_RATE_LIMIT_WINDOW_SECS}`,\n );\n }\n if (\n typeof maxPerWindow !== 'number' ||\n !Number.isInteger(maxPerWindow) ||\n maxPerWindow < 1 ||\n maxPerWindow > MAX_RATE_LIMIT_PER_WINDOW\n ) {\n throw new Error(\n `SKILL.md \"${skillName}\": \"rate_limit.max_per_window\" must be an integer between 1 and ${MAX_RATE_LIMIT_PER_WINDOW}`,\n );\n }\n return {\n perWindowMs: perWindowSecs * 1000,\n maxPerWindow,\n };\n}\n\nfunction validateScriptTimeoutMs(skillName: string, raw: unknown): number | undefined {\n if (raw === undefined || raw === null) {\n return undefined;\n }\n if (typeof raw !== 'number' || !Number.isInteger(raw) || raw <= 0) {\n throw new Error(`SKILL.md \"${skillName}\": \"script_timeout_ms\" must be a positive integer`);\n }\n return raw;\n}\n\nexport function validateSkillFrontmatter(\n frontmatter: SkillFrontmatter,\n systemPrompt: string,\n options: LoadSkillsOptions = {},\n): ParsedSkill {\n if (typeof frontmatter.name !== 'string' || frontmatter.name.length === 0) {\n throw new Error('SKILL.md: missing or invalid \"name\" field');\n }\n if (typeof frontmatter.description !== 'string' || frontmatter.description.length === 0) {\n throw new Error('SKILL.md: missing or invalid \"description\" field');\n }\n if (!Array.isArray(frontmatter.capabilities) || frontmatter.capabilities.length === 0) {\n throw new Error('SKILL.md: \"capabilities\" must be a non-empty array');\n }\n const capabilities: string[] = [];\n for (const capability of frontmatter.capabilities) {\n if (typeof capability !== 'string' || capability.length === 0) {\n throw new Error(\n `SKILL.md \"${frontmatter.name}\": capability entries must be non-empty strings`,\n );\n }\n capabilities.push(capability);\n }\n\n const asset = resolveSkillAsset(frontmatter.name, frontmatter.token, frontmatter.mint);\n\n let priceSubunits: bigint;\n if (frontmatter.price === undefined || frontmatter.price === null) {\n if (!options.allowFreeSkills) {\n throw new Error(\n `SKILL.md \"${frontmatter.name}\": \"price\" is required (${asset.symbol}; e.g. ${\n asset === NATIVE_SOL ? '0.002' : '0.05'\n }). Free skills are not supported on the protocol yet.`,\n );\n }\n priceSubunits = 0n;\n } else {\n const priceRaw = frontmatter.price;\n if (typeof priceRaw !== 'number' && typeof priceRaw !== 'string') {\n throw new Error(`SKILL.md \"${frontmatter.name}\": \"price\" must be a number or numeric string`);\n }\n const priceString = typeof priceRaw === 'number' ? String(priceRaw) : priceRaw;\n if (asset === NATIVE_SOL) {\n // Preserve historical rounding behaviour: number * LAMPORTS_PER_SOL +\n // Math.round. `parseAssetAmount` would reject non-positive inputs before\n // we could check `allowFreeSkills`, so we keep the legacy path for SOL\n // and introduce the strict parser only for new token types.\n priceSubunits = solToLamports(priceRaw);\n } else {\n try {\n priceSubunits = parseAssetAmount(asset, priceString);\n } catch (error) {\n throw new Error(\n `SKILL.md \"${frontmatter.name}\": ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n if (priceSubunits <= 0n && !options.allowFreeSkills) {\n throw new Error(\n `SKILL.md \"${frontmatter.name}\": price must be > 0 ${asset.symbol} (got ${priceRaw}); free skills are not yet supported`,\n );\n }\n }\n\n const mode = validateMode(frontmatter.name, frontmatter.mode);\n\n const tools: SkillToolDef[] = [];\n if (frontmatter.tools !== undefined) {\n if (mode !== 'llm') {\n throw new Error(\n `SKILL.md \"${frontmatter.name}\": \"tools\" is only valid in mode 'llm' (got '${mode}')`,\n );\n }\n if (!Array.isArray(frontmatter.tools)) {\n throw new Error(`SKILL.md \"${frontmatter.name}\": \"tools\" must be an array`);\n }\n for (let index = 0; index < frontmatter.tools.length; index++) {\n tools.push(validateTool(frontmatter.tools[index], frontmatter.name, index));\n }\n }\n\n let maxToolRounds = DEFAULT_MAX_TOOL_ROUNDS;\n if (frontmatter.max_tool_rounds !== undefined) {\n if (mode !== 'llm') {\n throw new Error(\n `SKILL.md \"${frontmatter.name}\": \"max_tool_rounds\" is only valid in mode 'llm' (got '${mode}')`,\n );\n }\n if (\n typeof frontmatter.max_tool_rounds !== 'number' ||\n !Number.isInteger(frontmatter.max_tool_rounds) ||\n frontmatter.max_tool_rounds <= 0\n ) {\n throw new Error(\n `SKILL.md \"${frontmatter.name}\": \"max_tool_rounds\" must be a positive integer`,\n );\n }\n maxToolRounds = frontmatter.max_tool_rounds;\n }\n\n let outputFile: string | undefined;\n let script: string | undefined;\n let scriptArgs: string[] = [];\n let scriptTimeoutMs: number | undefined;\n\n if (mode === 'static-file') {\n if (typeof frontmatter.output_file !== 'string' || frontmatter.output_file.length === 0) {\n throw new Error(\n `SKILL.md \"${frontmatter.name}\": mode 'static-file' requires \"output_file\" (string)`,\n );\n }\n if (frontmatter.script !== undefined) {\n throw new Error(\n `SKILL.md \"${frontmatter.name}\": \"script\" is not valid in mode 'static-file'`,\n );\n }\n outputFile = frontmatter.output_file;\n } else if (mode === 'static-script' || mode === 'dynamic-script') {\n if (typeof frontmatter.script !== 'string' || frontmatter.script.length === 0) {\n throw new Error(`SKILL.md \"${frontmatter.name}\": mode '${mode}' requires \"script\" (string)`);\n }\n if (frontmatter.output_file !== undefined) {\n throw new Error(\n `SKILL.md \"${frontmatter.name}\": \"output_file\" is only valid in mode 'static-file'`,\n );\n }\n script = frontmatter.script;\n scriptArgs = validateScriptArgs(frontmatter.name, frontmatter.script_args);\n scriptTimeoutMs = validateScriptTimeoutMs(frontmatter.name, frontmatter.script_timeout_ms);\n } else {\n if (frontmatter.output_file !== undefined) {\n throw new Error(\n `SKILL.md \"${frontmatter.name}\": \"output_file\" is only valid in mode 'static-file'`,\n );\n }\n if (frontmatter.script !== undefined) {\n throw new Error(\n `SKILL.md \"${frontmatter.name}\": \"script\" is only valid in script modes (static-script, dynamic-script)`,\n );\n }\n if (frontmatter.script_args !== undefined) {\n throw new Error(\n `SKILL.md \"${frontmatter.name}\": \"script_args\" is only valid in script modes`,\n );\n }\n if (frontmatter.script_timeout_ms !== undefined) {\n throw new Error(\n `SKILL.md \"${frontmatter.name}\": \"script_timeout_ms\" is only valid in script modes`,\n );\n }\n }\n\n const image = typeof frontmatter.image === 'string' ? frontmatter.image : undefined;\n const imageFile = typeof frontmatter.image_file === 'string' ? frontmatter.image_file : undefined;\n\n const llmOverride = validateLlmOverride(frontmatter.name, frontmatter, mode);\n const rateLimit = validateRateLimit(frontmatter.name, frontmatter.rate_limit);\n\n return {\n name: frontmatter.name,\n description: frontmatter.description,\n capabilities,\n priceSubunits,\n asset,\n mode,\n systemPrompt,\n tools,\n maxToolRounds,\n llmOverride,\n image,\n imageFile,\n outputFile,\n script,\n scriptArgs,\n scriptTimeoutMs,\n rateLimit,\n };\n}\n\nfunction buildSkillFromParsed(parsed: ParsedSkill, skillDir: string, logger: LoaderLogger): Skill {\n switch (parsed.mode) {\n case 'llm':\n return new ScriptSkill({\n name: parsed.name,\n description: parsed.description,\n capabilities: parsed.capabilities,\n priceSubunits: parsed.priceSubunits,\n asset: parsed.asset,\n skillDir,\n systemPrompt: parsed.systemPrompt,\n tools: parsed.tools,\n maxToolRounds: parsed.maxToolRounds,\n llmOverride: parsed.llmOverride,\n image: parsed.image,\n imageFile: parsed.imageFile,\n logger,\n });\n case 'static-file': {\n if (parsed.outputFile === undefined) {\n throw new Error(\n `SKILL.md \"${parsed.name}\": internal error - outputFile missing for mode 'static-file'`,\n );\n }\n const outputFilePath = resolveInsidePath(skillDir, parsed.outputFile);\n if (!outputFilePath) {\n throw new Error(\n `SKILL.md \"${parsed.name}\": \"output_file\" must stay inside the skill directory`,\n );\n }\n return new StaticFileSkill({\n name: parsed.name,\n description: parsed.description,\n capabilities: parsed.capabilities,\n priceSubunits: parsed.priceSubunits,\n asset: parsed.asset,\n outputFilePath,\n image: parsed.image,\n imageFile: parsed.imageFile,\n });\n }\n case 'static-script':\n case 'dynamic-script': {\n if (parsed.script === undefined) {\n throw new Error(\n `SKILL.md \"${parsed.name}\": internal error - script missing for mode '${parsed.mode}'`,\n );\n }\n const scriptPath = resolveInsidePath(skillDir, parsed.script);\n if (!scriptPath) {\n throw new Error(`SKILL.md \"${parsed.name}\": \"script\" must stay inside the skill directory`);\n }\n const Ctor = parsed.mode === 'static-script' ? StaticScriptSkill : DynamicScriptSkill;\n return new Ctor({\n name: parsed.name,\n description: parsed.description,\n capabilities: parsed.capabilities,\n priceSubunits: parsed.priceSubunits,\n asset: parsed.asset,\n scriptPath,\n scriptArgs: parsed.scriptArgs,\n scriptTimeoutMs: parsed.scriptTimeoutMs ?? DEFAULT_SCRIPT_TIMEOUT_MS,\n image: parsed.image,\n imageFile: parsed.imageFile,\n });\n }\n }\n}\n\n/**\n * Walk `skillsDir`, load each immediate subdirectory's SKILL.md, and\n * return constructed `Skill` instances (LLM or non-LLM depending on\n * frontmatter `mode`). Malformed directories are skipped with a `warn` log.\n */\nexport function loadSkillsFromDir(skillsDir: string, options: LoadSkillsOptions = {}): Skill[] {\n const logger = options.logger ?? {};\n const skills: Skill[] = [];\n\n let entries: string[];\n try {\n entries = readdirSync(skillsDir);\n } catch (error) {\n logger.debug?.({ err: error, skillsDir }, 'skills directory not readable; no skills loaded');\n return skills;\n }\n\n for (const entry of entries) {\n const entryPath = join(skillsDir, entry);\n try {\n if (!statSync(entryPath).isDirectory()) {\n continue;\n }\n } catch {\n continue;\n }\n\n const skillMdPath = join(entryPath, 'SKILL.md');\n try {\n const content = readFileSync(skillMdPath, 'utf-8');\n const { frontmatter, systemPrompt } = parseSkillMd(content);\n const parsed = validateSkillFrontmatter(frontmatter, systemPrompt, options);\n skills.push(buildSkillFromParsed(parsed, entryPath, logger));\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n logger.warn?.({ dir: entry, err: message }, 'skipping malformed skill directory');\n }\n }\n\n return skills;\n}\n"]}
|