@elisym/sdk 0.23.0 → 0.24.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent-store.cjs +22 -0
- package/dist/agent-store.cjs.map +1 -1
- package/dist/agent-store.d.cts +9 -1
- package/dist/agent-store.d.ts +9 -1
- package/dist/agent-store.js +23 -2
- package/dist/agent-store.js.map +1 -1
- package/dist/index.cjs +134 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +206 -6
- package/dist/index.d.ts +206 -6
- package/dist/index.js +131 -10
- package/dist/index.js.map +1 -1
- package/dist/llm-health.cjs.map +1 -1
- package/dist/llm-health.d.cts +2 -2
- package/dist/llm-health.d.ts +2 -2
- package/dist/llm-health.js.map +1 -1
- package/dist/node.cjs +175 -0
- package/dist/node.cjs.map +1 -1
- package/dist/node.d.cts +46 -1
- package/dist/node.d.ts +46 -1
- package/dist/node.js +175 -1
- package/dist/node.js.map +1 -1
- package/dist/skills.cjs +128 -28
- package/dist/skills.cjs.map +1 -1
- package/dist/skills.d.cts +49 -1
- package/dist/skills.d.ts +49 -1
- package/dist/skills.js +130 -30
- package/dist/skills.js.map +1 -1
- package/dist/{types-Cdscy9kY.d.cts → types-CqN9kFTn.d.cts} +6 -1
- package/dist/{types-Cdscy9kY.d.ts → types-CqN9kFTn.d.ts} +6 -1
- package/package.json +4 -1
package/dist/skills.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/skills/scriptSkill.ts","../src/skills/staticFileSkill.ts","../src/llm-health/constants.ts","../src/llm-health/types.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\n// Env vars that carry agent/operator secrets and must not leak into skill tool\n// subprocesses. The child still inherits the rest of the environment (PATH,\n// HOME, locale, etc.) so legitimate tool scripts keep working.\nconst SECRET_ENV_VARS: readonly string[] = ['ANTHROPIC_API_KEY', 'OPENAI_API_KEY'];\n\nfunction scopedToolEnv(): NodeJS.ProcessEnv {\n const env: NodeJS.ProcessEnv = { ...process.env };\n for (const key of SECRET_ENV_VARS) {\n delete env[key];\n }\n return env;\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 const stringValue = String(value);\n // Reject values beginning with `-` so an LLM-supplied argument can never be\n // parsed as an option/flag by the target script (argument injection, #25). We\n // deliberately do NOT insert a `--` end-of-options sentinel: many tool scripts\n // read positionals directly ($1) and would receive the literal `--` as input.\n if (stringValue.startsWith('-')) {\n return `Error: tool \"${toolDef.name}\" argument \"${param.name}\" must not begin with \"-\".`;\n }\n if (param.required && index === 0) {\n args.push(stringValue);\n } else {\n args.push(`--${param.name}`, stringValue);\n }\n }\n\n // Scoped env: strip operator secrets (LLM API keys) so an untrusted tool\n // script cannot read them out of its environment.\n const result = await runScript(cmd, args, {\n cwd: this.skillDir,\n signal,\n env: scopedToolEnv(),\n });\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 {\n Skill,\n SkillContext,\n SkillInput,\n SkillLlmOverride,\n SkillMode,\n SkillOutput,\n} 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 * Declared LLM dependency. The skill itself never calls an LLM, but if\n * the file is produced by an external pipeline that depends on a key,\n * operators can declare the (provider, model) pair so the runtime can\n * health-monitor it. Carried through from SKILL.md as-is.\n */\n llmOverride?: SkillLlmOverride;\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 llmOverride?: SkillLlmOverride;\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.llmOverride = params.llmOverride;\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","/**\n * LLM health monitor and heartbeat tunable defaults. CLI and plugin consumers\n * can override via `process.env.ELISYM_LLM_HEALTH_TTL_MS` and\n * `ELISYM_LLM_HEARTBEAT_INTERVAL_MS` and pass the resolved values into\n * the monitor/heartbeat options.\n */\n\nexport const DEFAULT_HEALTH_TTL_MS = 10 * 60 * 1000;\nexport const DEFAULT_HEARTBEAT_INTERVAL_MS = 10 * 60 * 1000;\n\n/**\n * Interval between recovery probes after the LLM health monitor enters an\n * unhealthy state. The recovery loop is paused while the pair is healthy\n * and only kicks in reactively (after `markUnhealthyFromJob` or a failed\n * job). On the first successful probe the monitor returns to healthy and\n * the loop stops on its own.\n */\nexport const LAZY_RECOVERY_INTERVAL_MS = 5 * 60 * 1000;\n\n/**\n * Exit code contract: a `dynamic-script` / `static-script` skill returns\n * this code from the script process to signal that the upstream LLM\n * provider rejected the request because credits / billing are exhausted.\n * The agent runtime treats this as the script's equivalent of the\n * `mode: 'llm'` 402 path: it calls `markUnhealthyFromJob(provider, model)`\n * on the health monitor (which starts the lazy recovery loop) and rejects\n * subsequent jobs against the same pair until a recovery probe succeeds.\n *\n * Any other non-zero exit is a generic failure and does NOT touch health\n * state - operators should reserve this code for billing-exhausted only.\n *\n * 42 was chosen because it sits outside POSIX shell conventions (1-2\n * generic, 126-128 shell-internal, 130+ signals) and `sysexits.h`\n * (64-78 - usage / data / host / config errors), so it doesn't collide\n * with other meaningful exit codes a script might naturally produce.\n */\nexport const SCRIPT_EXIT_BILLING_EXHAUSTED = 42;\n\n/**\n * Number of consecutive `unavailable` results tolerated before\n * `assertReady` starts throwing. The first `unavailable - 1` are treated\n * as transient blips so a brief network hiccup does not block jobs.\n */\nexport const UNAVAILABLE_TOLERANCE = 3;\n\n/**\n * Free-LLM rate-limit defaults. Applied when a SKILL.md with\n * `mode: 'llm'` and `price: 0` does not declare its own `rate_limit`.\n */\nexport const DEFAULT_FREE_LLM_PER_CUSTOMER_WINDOW_MS = 60 * 60 * 1000;\nexport const DEFAULT_FREE_LLM_PER_CUSTOMER_MAX = 3;\n\nexport const DEFAULT_FREE_LLM_GLOBAL_WINDOW_MS = 60 * 1000;\nexport const DEFAULT_FREE_LLM_GLOBAL_MAX = 30;\n\nexport const DEFAULT_FREE_LLM_MAX_TRACKED_KEYS = 1000;\n","/**\n * Shared types for the LLM health monitor. Provider-agnostic: the\n * actual HTTP probe lives in CLI/plugin and is supplied via dependency\n * injection (`verifyFn`).\n */\n\nexport type LlmHealthStatus = 'unknown' | 'healthy' | 'invalid' | 'billing' | 'unavailable';\n\n/**\n * Result of probing an API key with a specific model. Discriminated on\n * `ok`, then on `reason` for failures. Adding a new failure reason is a\n * breaking change for exhaustive switches; update consumers in lockstep.\n *\n * - `invalid`: HTTP 401/403 - key rejected outright.\n * - `billing`: HTTP 402, or 400 with credit/billing/insufficient marker,\n * or OpenAI's 429 with `insufficient_quota`. Operator out of credits.\n * - `unavailable`: transient (HTTP 429 without quota marker, 5xx, network\n * error). May resolve on retry.\n */\nexport type LlmKeyVerification =\n | { ok: true }\n | { ok: false; reason: 'invalid'; status: number; body: string }\n | { ok: false; reason: 'billing'; status?: number; body?: string }\n | { ok: false; reason: 'unavailable'; error: string };\n\nexport type LlmHealthErrorReason = 'invalid' | 'billing' | 'unavailable';\n\n/**\n * Thrown by `LlmHealthMonitor.assertReady` when the gate refuses a job.\n * Carries the operator-facing reason so callers can log it; customer-facing\n * messages should be sanitized at the call site (see `runtime.ts` preflight).\n */\nexport class LlmHealthError extends Error {\n readonly reason: LlmHealthErrorReason;\n readonly provider: string;\n readonly model: string;\n\n constructor(reason: LlmHealthErrorReason, provider: string, model: string, detail: string) {\n super(`LLM ${provider}/${model} ${reason}: ${detail}`);\n this.name = 'LlmHealthError';\n this.reason = reason;\n this.provider = provider;\n this.model = model;\n }\n}\n\n/**\n * Thrown by SDK script skills (`static-script`, `dynamic-script`) when the\n * spawned process exits with `SCRIPT_EXIT_BILLING_EXHAUSTED` (= 42). The\n * runtime catches this and calls `markUnhealthyFromJob` on the matching\n * (provider, model) pair declared in SKILL.md, so subsequent jobs are\n * gated until the lazy recovery loop re-probes the key. The exit code is\n * the script-side equivalent of the LLM-mode 402 path.\n *\n * The error does NOT carry provider/model itself - the script doesn't\n * know which pair the agent registered with the monitor; the runtime\n * reads them from the matched skill's `llmOverride` declaration.\n */\nexport class ScriptBillingExhaustedError extends Error {\n readonly exitCode: number;\n readonly stderr: string;\n readonly stdout: string;\n\n constructor(exitCode: number, stdout: string, stderr: string) {\n const detail = stderr.trim() || stdout.trim() || '(no output)';\n super(`script exited with billing-exhausted code ${exitCode}: ${detail}`);\n this.name = 'ScriptBillingExhaustedError';\n this.exitCode = exitCode;\n this.stdout = stdout;\n this.stderr = stderr;\n }\n}\n\n/**\n * Thrown by the SDK script skills when a tool/script fails (non-zero exit, spawn\n * error, or exit 0 with empty output). `message` is a generic, stable summary\n * that is SAFE to forward to a remote customer. The raw stderr/stdout lives on\n * `detail` for the operator log and health-monitor classification ONLY - it must\n * never be sent across the trust boundary to a customer.\n */\nexport class ScriptExecutionError extends Error {\n readonly exitCode: number | null;\n readonly detail: string;\n\n constructor(exitCode: number | null, detail: string, summary?: string) {\n super(summary ?? `script failed (exit ${exitCode ?? 'unknown'})`);\n this.name = 'ScriptExecutionError';\n this.exitCode = exitCode;\n this.detail = detail;\n }\n}\n\n/**\n * Per-skill rate-limit declaration. Snake-case in SKILL.md frontmatter,\n * camelCase here. Applies to any skill mode but the framework adds a\n * default cap only for free LLM skills.\n */\nexport interface SkillRateLimit {\n perWindowMs: number;\n maxPerWindow: number;\n}\n\n/** Read-only health snapshot for logs/tests. */\nexport interface LlmHealthSnapshotEntry {\n provider: string;\n model: string;\n status: LlmHealthStatus;\n lastVerifiedAt: number;\n lastReason: string | undefined;\n consecutiveFailures: number;\n}\n","import { dirname } from 'node:path';\nimport { SCRIPT_EXIT_BILLING_EXHAUSTED } from '../llm-health/constants';\nimport { ScriptBillingExhaustedError, ScriptExecutionError } from '../llm-health/types';\nimport type { Asset } from '../payment/assets';\nimport { runScript } from './scriptSkill';\nimport type {\n Skill,\n SkillContext,\n SkillInput,\n SkillLlmOverride,\n SkillMode,\n SkillOutput,\n} 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 * Declared LLM dependency. The (provider, model) pair tells the runtime\n * which API key the script reaches under the hood so it can be\n * health-monitored. Carried through from SKILL.md as-is; the script\n * itself reads the key from its environment.\n */\n llmOverride?: SkillLlmOverride;\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 llmOverride?: SkillLlmOverride;\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.llmOverride = params.llmOverride;\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 ScriptExecutionError(\n null,\n result.spawnError.message,\n 'script could not be started',\n );\n }\n if (result.code === SCRIPT_EXIT_BILLING_EXHAUSTED) {\n throw new ScriptBillingExhaustedError(result.code, result.stdout, result.stderr);\n }\n if (result.code !== 0) {\n const detail = result.stderr.trim() || result.stdout.trim() || '(no output)';\n // Generic message reaches the customer; raw stderr/stdout stays on `detail`\n // for the operator log and health-monitor classification only.\n throw new ScriptExecutionError(result.code, detail);\n }\n const output = result.stdout.trim();\n if (output === '') {\n // Exit 0 with no output is not a deliverable result: the marketplace\n // rejects empty results at delivery, but only after the ledger has\n // marked the job `executed`, and recovery then retries the empty\n // result on every tick forever. Failing here keeps the job on the\n // paid -> failed path so recovery terminates it. stderr (if any)\n // carries the underlying reason for the operator log.\n const detail = result.stderr.trim() || '(no stderr)';\n throw new ScriptExecutionError(result.code, detail, 'script produced empty output');\n }\n return { data: output };\n }\n}\n","import { dirname } from 'node:path';\nimport { SCRIPT_EXIT_BILLING_EXHAUSTED } from '../llm-health/constants';\nimport { ScriptBillingExhaustedError, ScriptExecutionError } from '../llm-health/types';\nimport type { Asset } from '../payment/assets';\nimport { runScript } from './scriptSkill';\nimport type {\n Skill,\n SkillContext,\n SkillInput,\n SkillLlmOverride,\n SkillMode,\n SkillOutput,\n} 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 * Declared LLM dependency. The (provider, model) pair tells the runtime\n * which API key the script reaches under the hood so it can be\n * health-monitored. Carried through from SKILL.md as-is; the script\n * itself reads the key from its environment.\n */\n llmOverride?: SkillLlmOverride;\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 llmOverride?: SkillLlmOverride;\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.llmOverride = params.llmOverride;\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 ScriptExecutionError(\n null,\n result.spawnError.message,\n 'script could not be started',\n );\n }\n if (result.code === SCRIPT_EXIT_BILLING_EXHAUSTED) {\n throw new ScriptBillingExhaustedError(result.code, result.stdout, result.stderr);\n }\n if (result.code !== 0) {\n const detail = result.stderr.trim() || result.stdout.trim() || '(no output)';\n // Generic message reaches the customer; raw stderr/stdout stays on `detail`\n // for the operator log and health-monitor classification only.\n throw new ScriptExecutionError(result.code, detail);\n }\n const output = result.stdout.trim();\n if (output === '') {\n // Exit 0 with no output is not a deliverable result: the marketplace\n // rejects empty results at delivery, but only after the ledger has\n // marked the job `executed`, and recovery then retries the empty\n // result on every tick forever. Failing here keeps the job on the\n // paid -> failed path so recovery terminates it. stderr (if any)\n // carries the underlying reason for the operator log.\n const detail = result.stderr.trim() || '(no stderr)';\n throw new ScriptExecutionError(result.code, detail, 'script produced empty output');\n }\n return { data: output };\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_LONG_FORM_ARTICLE = 30023;\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/** Discovery tag attached to elisym agent policy events (kind 30023). */\nexport const POLICY_T_TAG = 'elisym-policy';\n/** d-tag prefix for policy events: full d-tag = `<prefix><type>` (e.g. `elisym-policy-tos`). */\nexport const POLICY_D_TAG_PREFIX = 'elisym-policy-';\n/** Validation regex for policy `type` slug. Lowercase ASCII + hyphen, 1-32 chars, no leading/trailing hyphen. */\nexport const POLICY_TYPE_REGEX = /^[a-z0-9](?:[a-z0-9-]{0,30}[a-z0-9])?$/;\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 // Upper bound for execution budgets (`max_execution_secs` / `execution_timeout_secs`).\n // Distinct from MAX_TIMEOUT_SECS (the result-wait cap): execution budgets may be\n // hours, so this exists only to keep `secs * 1000` within Node's setTimeout limit\n // (2_147_483_647 ms) - a larger value overflows and fires the timer immediately.\n MAX_EXECUTION_SECS: 2_147_483,\n MAX_CAPABILITIES: 20,\n MAX_DESCRIPTION_LENGTH: 500,\n MAX_AGENT_NAME_LENGTH: 64,\n MAX_CAPABILITY_LENGTH: 64,\n MAX_POLICY_CONTENT_LENGTH: 50_000,\n MAX_POLICIES_PER_AGENT: 12,\n MAX_POLICY_TYPE_LENGTH: 32,\n MAX_POLICY_TITLE_LENGTH: 120,\n MAX_POLICY_SUMMARY_LENGTH: 280,\n MAX_POLICY_VERSION_LENGTH: 32,\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 { LIMITS } 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 /**\n * LLM provider id. For `mode: 'llm'` this overrides the agent default for\n * runtime LLM execution. For script modes, it declares the LLM the script\n * depends on so the agent can health-monitor the API key (startup probe +\n * reactive markUnhealthy + lazy recovery). Pairs with `model`.\n */\n provider?: unknown;\n /** LLM model id. Same semantics as `provider`. Must be set together with `provider`. */\n model?: unknown;\n /** Per-skill max_tokens override. Only valid for `mode: 'llm'`. */\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 * Optional per-skill execution budget in seconds. Applies to any skill mode.\n * `0` means unlimited. Omitted => the runtime falls through to the agent-level\n * `execution_timeout_secs`, then to unlimited.\n */\n max_execution_secs?: 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 / dependency. Present when SKILL.md declared at\n * least one of `provider`/`model`/`max_tokens`. Parse-time invariant:\n * `provider` set iff `model` set; `max_tokens` only when mode === 'llm'.\n *\n * For mode 'llm': the runtime uses these to construct the LLM client.\n * For script modes: the (provider, model) pair declares the API key the\n * script depends on so the agent can health-monitor it.\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 * Per-skill execution budget in seconds (any mode). `0` => explicitly\n * unlimited. `undefined` => caller falls through to the agent-level default,\n * then to unlimited.\n */\n executionTimeoutSecs?: 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 asString = (typeof sol === 'string' ? sol : String(sol)).trim();\n // Free skills declare price 0; `parseAssetAmount` rejects non-positive amounts,\n // so the zero case is handled here. Everything else goes through the exact\n // integer/string parser - no floating-point multiply (see money-math rule).\n if (/^0+(?:\\.0+)?$/.test(asString)) {\n return 0n;\n }\n try {\n return parseAssetAmount(NATIVE_SOL, asString);\n } catch {\n throw new Error(`Invalid SOL amount: ${sol}`);\n }\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 / dependency block. The\n * all-or-nothing rule applies to (`provider`, `model`); `max_tokens` is\n * independent.\n *\n * Semantics by mode:\n * - `mode: 'llm'`: provider+model override the agent default for runtime\n * LLM execution. `max_tokens` overrides the agent default cap.\n * - script modes (`static-script` / `dynamic-script` / `static-file`):\n * provider+model declare which LLM key the script depends on so the\n * agent runtime can health-monitor it (startup probe + reactive\n * markUnhealthy on `SCRIPT_EXIT_BILLING_EXHAUSTED` + lazy recovery).\n * `max_tokens` is rejected here - it has no runtime effect because\n * the script handles its own LLM call and token limits.\n *\n * Returns `undefined` when no LLM fields are declared at all.\n * Throws on partial pair, invalid provider, empty model, out-of-range\n * max_tokens, or `max_tokens` declared on a non-llm mode.\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 (hasMaxTokens && mode !== 'llm') {\n throw new Error(\n `SKILL.md \"${skillName}\": \"max_tokens\" is only valid in mode 'llm' (got '${mode}'). For script modes, control token limits inside the script.`,\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\nfunction validateMaxExecutionSecs(skillName: string, raw: unknown): number | undefined {\n if (raw === undefined || raw === null) {\n return undefined;\n }\n // Mode-agnostic: applies to every skill mode. `0` is allowed and means\n // \"explicitly unlimited\" (overrides any agent-level cap back to no limit).\n if (typeof raw !== 'number' || !Number.isInteger(raw) || raw < 0) {\n throw new Error(\n `SKILL.md \"${skillName}\": \"max_execution_secs\" must be a non-negative integer (0 = unlimited)`,\n );\n }\n if (raw > LIMITS.MAX_EXECUTION_SECS) {\n throw new Error(\n `SKILL.md \"${skillName}\": \"max_execution_secs\" must be <= ${LIMITS.MAX_EXECUTION_SECS} (larger values overflow setTimeout)`,\n );\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 // SOL prices route through `solToLamports`, which uses the same exact\n // integer parser as other assets but tolerates a 0 price so the\n // `allowFreeSkills` check below can run (parseAssetAmount rejects 0).\n priceSubunits = solToLamports(priceString);\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 const executionTimeoutSecs = validateMaxExecutionSecs(\n frontmatter.name,\n frontmatter.max_execution_secs,\n );\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 executionTimeoutSecs,\n };\n}\n\nfunction buildSkillFromParsed(parsed: ParsedSkill, skillDir: string, logger: LoaderLogger): Skill {\n // Containment for `image_file`, matching `script`/`output_file` (which throw).\n // The image is decorative, so an out-of-dir path is dropped with a warning\n // rather than failing the load. Without this, `image_file: ../../.secrets.json`\n // would be read and uploaded to a public media host at startup (exfiltration).\n let imageFile = parsed.imageFile;\n if (imageFile !== undefined && resolveInsidePath(skillDir, imageFile) === null) {\n logger.warn?.(\n { skill: parsed.name, imageFile },\n 'SKILL.md \"image_file\" escapes the skill directory; ignoring it',\n );\n imageFile = undefined;\n }\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,\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,\n llmOverride: parsed.llmOverride,\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,\n llmOverride: parsed.llmOverride,\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/llm-health/constants.ts","../src/llm-health/types.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","mkdtemp","join","tmpdir","stat","rm","resolve","relative","sep","Decimal","YAML","readdirSync","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\n// Env vars that carry agent/operator secrets and must not leak into skill tool\n// subprocesses. The child still inherits the rest of the environment (PATH,\n// HOME, locale, etc.) so legitimate tool scripts keep working.\nconst SECRET_ENV_VARS: readonly string[] = ['ANTHROPIC_API_KEY', 'OPENAI_API_KEY'];\n\nfunction scopedToolEnv(): NodeJS.ProcessEnv {\n const env: NodeJS.ProcessEnv = { ...process.env };\n for (const key of SECRET_ENV_VARS) {\n delete env[key];\n }\n return env;\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 const stringValue = String(value);\n // Reject values beginning with `-` so an LLM-supplied argument can never be\n // parsed as an option/flag by the target script (argument injection, #25). We\n // deliberately do NOT insert a `--` end-of-options sentinel: many tool scripts\n // read positionals directly ($1) and would receive the literal `--` as input.\n if (stringValue.startsWith('-')) {\n return `Error: tool \"${toolDef.name}\" argument \"${param.name}\" must not begin with \"-\".`;\n }\n if (param.required && index === 0) {\n args.push(stringValue);\n } else {\n args.push(`--${param.name}`, stringValue);\n }\n }\n\n // Scoped env: strip operator secrets (LLM API keys) so an untrusted tool\n // script cannot read them out of its environment.\n const result = await runScript(cmd, args, {\n cwd: this.skillDir,\n signal,\n env: scopedToolEnv(),\n });\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 {\n Skill,\n SkillContext,\n SkillInput,\n SkillLlmOverride,\n SkillMode,\n SkillOutput,\n} 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 * Declared LLM dependency. The skill itself never calls an LLM, but if\n * the file is produced by an external pipeline that depends on a key,\n * operators can declare the (provider, model) pair so the runtime can\n * health-monitor it. Carried through from SKILL.md as-is.\n */\n llmOverride?: SkillLlmOverride;\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 llmOverride?: SkillLlmOverride;\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.llmOverride = params.llmOverride;\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","/**\n * LLM health monitor and heartbeat tunable defaults. CLI and plugin consumers\n * can override via `process.env.ELISYM_LLM_HEALTH_TTL_MS` and\n * `ELISYM_LLM_HEARTBEAT_INTERVAL_MS` and pass the resolved values into\n * the monitor/heartbeat options.\n */\n\nexport const DEFAULT_HEALTH_TTL_MS = 10 * 60 * 1000;\nexport const DEFAULT_HEARTBEAT_INTERVAL_MS = 10 * 60 * 1000;\n\n/**\n * Interval between recovery probes after the LLM health monitor enters an\n * unhealthy state. The recovery loop is paused while the pair is healthy\n * and only kicks in reactively (after `markUnhealthyFromJob` or a failed\n * job). On the first successful probe the monitor returns to healthy and\n * the loop stops on its own.\n */\nexport const LAZY_RECOVERY_INTERVAL_MS = 5 * 60 * 1000;\n\n/**\n * Exit code contract: a `dynamic-script` / `static-script` skill returns\n * this code from the script process to signal that the upstream LLM\n * provider rejected the request because credits / billing are exhausted.\n * The agent runtime treats this as the script's equivalent of the\n * `mode: 'llm'` 402 path: it calls `markUnhealthyFromJob(provider, model)`\n * on the health monitor (which starts the lazy recovery loop) and rejects\n * subsequent jobs against the same pair until a recovery probe succeeds.\n *\n * Any other non-zero exit is a generic failure and does NOT touch health\n * state - operators should reserve this code for billing-exhausted only.\n *\n * 42 was chosen because it sits outside POSIX shell conventions (1-2\n * generic, 126-128 shell-internal, 130+ signals) and `sysexits.h`\n * (64-78 - usage / data / host / config errors), so it doesn't collide\n * with other meaningful exit codes a script might naturally produce.\n */\nexport const SCRIPT_EXIT_BILLING_EXHAUSTED = 42;\n\n/**\n * Number of consecutive `unavailable` results tolerated before\n * `assertReady` starts throwing. The first `unavailable - 1` are treated\n * as transient blips so a brief network hiccup does not block jobs.\n */\nexport const UNAVAILABLE_TOLERANCE = 3;\n\n/**\n * Free-LLM rate-limit defaults. Applied when a SKILL.md with\n * `mode: 'llm'` and `price: 0` does not declare its own `rate_limit`.\n */\nexport const DEFAULT_FREE_LLM_PER_CUSTOMER_WINDOW_MS = 60 * 60 * 1000;\nexport const DEFAULT_FREE_LLM_PER_CUSTOMER_MAX = 3;\n\nexport const DEFAULT_FREE_LLM_GLOBAL_WINDOW_MS = 60 * 1000;\nexport const DEFAULT_FREE_LLM_GLOBAL_MAX = 30;\n\nexport const DEFAULT_FREE_LLM_MAX_TRACKED_KEYS = 1000;\n","/**\n * Shared types for the LLM health monitor. Provider-agnostic: the\n * actual HTTP probe lives in CLI/plugin and is supplied via dependency\n * injection (`verifyFn`).\n */\n\nexport type LlmHealthStatus = 'unknown' | 'healthy' | 'invalid' | 'billing' | 'unavailable';\n\n/**\n * Result of probing an API key with a specific model. Discriminated on\n * `ok`, then on `reason` for failures. Adding a new failure reason is a\n * breaking change for exhaustive switches; update consumers in lockstep.\n *\n * - `invalid`: HTTP 401/403 - key rejected outright.\n * - `billing`: HTTP 402, or 400 with credit/billing/insufficient marker,\n * or OpenAI's 429 with `insufficient_quota`. Operator out of credits.\n * - `unavailable`: transient (HTTP 429 without quota marker, 5xx, network\n * error). May resolve on retry. `status` carries the HTTP status when the\n * failure was an HTTP response (absent for a network throw), letting callers\n * distinguish a transient 5xx/429 from a permanent 404 \"model no longer\n * exists\" without re-parsing `error`. Unlike `invalid`/`billing`,\n * `unavailable` is per-model and never cascades to sibling models.\n */\nexport type LlmKeyVerification =\n | { ok: true }\n | { ok: false; reason: 'invalid'; status: number; body: string }\n | { ok: false; reason: 'billing'; status?: number; body?: string }\n | { ok: false; reason: 'unavailable'; status?: number; error: string };\n\nexport type LlmHealthErrorReason = 'invalid' | 'billing' | 'unavailable';\n\n/**\n * Thrown by `LlmHealthMonitor.assertReady` when the gate refuses a job.\n * Carries the operator-facing reason so callers can log it; customer-facing\n * messages should be sanitized at the call site (see `runtime.ts` preflight).\n */\nexport class LlmHealthError extends Error {\n readonly reason: LlmHealthErrorReason;\n readonly provider: string;\n readonly model: string;\n\n constructor(reason: LlmHealthErrorReason, provider: string, model: string, detail: string) {\n super(`LLM ${provider}/${model} ${reason}: ${detail}`);\n this.name = 'LlmHealthError';\n this.reason = reason;\n this.provider = provider;\n this.model = model;\n }\n}\n\n/**\n * Thrown by SDK script skills (`static-script`, `dynamic-script`) when the\n * spawned process exits with `SCRIPT_EXIT_BILLING_EXHAUSTED` (= 42). The\n * runtime catches this and calls `markUnhealthyFromJob` on the matching\n * (provider, model) pair declared in SKILL.md, so subsequent jobs are\n * gated until the lazy recovery loop re-probes the key. The exit code is\n * the script-side equivalent of the LLM-mode 402 path.\n *\n * The error does NOT carry provider/model itself - the script doesn't\n * know which pair the agent registered with the monitor; the runtime\n * reads them from the matched skill's `llmOverride` declaration.\n */\nexport class ScriptBillingExhaustedError extends Error {\n readonly exitCode: number;\n readonly stderr: string;\n readonly stdout: string;\n\n constructor(exitCode: number, stdout: string, stderr: string) {\n const detail = stderr.trim() || stdout.trim() || '(no output)';\n super(`script exited with billing-exhausted code ${exitCode}: ${detail}`);\n this.name = 'ScriptBillingExhaustedError';\n this.exitCode = exitCode;\n this.stdout = stdout;\n this.stderr = stderr;\n }\n}\n\n/**\n * Thrown by the SDK script skills when a tool/script fails (non-zero exit, spawn\n * error, or exit 0 with empty output). `message` is a generic, stable summary\n * that is SAFE to forward to a remote customer. The raw stderr/stdout lives on\n * `detail` for the operator log and health-monitor classification ONLY - it must\n * never be sent across the trust boundary to a customer.\n */\nexport class ScriptExecutionError extends Error {\n readonly exitCode: number | null;\n readonly detail: string;\n\n constructor(exitCode: number | null, detail: string, summary?: string) {\n super(summary ?? `script failed (exit ${exitCode ?? 'unknown'})`);\n this.name = 'ScriptExecutionError';\n this.exitCode = exitCode;\n this.detail = detail;\n }\n}\n\n/**\n * Per-skill rate-limit declaration. Snake-case in SKILL.md frontmatter,\n * camelCase here. Applies to any skill mode but the framework adds a\n * default cap only for free LLM skills.\n */\nexport interface SkillRateLimit {\n perWindowMs: number;\n maxPerWindow: number;\n}\n\n/** Read-only health snapshot for logs/tests. */\nexport interface LlmHealthSnapshotEntry {\n provider: string;\n model: string;\n status: LlmHealthStatus;\n lastVerifiedAt: number;\n lastReason: string | undefined;\n consecutiveFailures: number;\n}\n","import { dirname } from 'node:path';\nimport { SCRIPT_EXIT_BILLING_EXHAUSTED } from '../llm-health/constants';\nimport { ScriptBillingExhaustedError, ScriptExecutionError } from '../llm-health/types';\nimport type { Asset } from '../payment/assets';\nimport { runScript } from './scriptSkill';\nimport type {\n Skill,\n SkillContext,\n SkillInput,\n SkillLlmOverride,\n SkillMode,\n SkillOutput,\n} 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 * Declared LLM dependency. The (provider, model) pair tells the runtime\n * which API key the script reaches under the hood so it can be\n * health-monitored. Carried through from SKILL.md as-is; the script\n * itself reads the key from its environment.\n */\n llmOverride?: SkillLlmOverride;\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 llmOverride?: SkillLlmOverride;\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.llmOverride = params.llmOverride;\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 ScriptExecutionError(\n null,\n result.spawnError.message,\n 'script could not be started',\n );\n }\n if (result.code === SCRIPT_EXIT_BILLING_EXHAUSTED) {\n throw new ScriptBillingExhaustedError(result.code, result.stdout, result.stderr);\n }\n if (result.code !== 0) {\n const detail = result.stderr.trim() || result.stdout.trim() || '(no output)';\n // Generic message reaches the customer; raw stderr/stdout stays on `detail`\n // for the operator log and health-monitor classification only.\n throw new ScriptExecutionError(result.code, detail);\n }\n const output = result.stdout.trim();\n if (output === '') {\n // Exit 0 with no output is not a deliverable result: the marketplace\n // rejects empty results at delivery, but only after the ledger has\n // marked the job `executed`, and recovery then retries the empty\n // result on every tick forever. Failing here keeps the job on the\n // paid -> failed path so recovery terminates it. stderr (if any)\n // carries the underlying reason for the operator log.\n const detail = result.stderr.trim() || '(no stderr)';\n throw new ScriptExecutionError(result.code, detail, 'script produced empty output');\n }\n return { data: output };\n }\n}\n","import { mkdtemp, rm, stat } from 'node:fs/promises';\nimport { tmpdir } from 'node:os';\nimport { dirname, join } from 'node:path';\nimport { SCRIPT_EXIT_BILLING_EXHAUSTED } from '../llm-health/constants';\nimport { ScriptBillingExhaustedError, ScriptExecutionError } from '../llm-health/types';\nimport type { Asset } from '../payment/assets';\nimport { runScript } from './scriptSkill';\nimport type {\n Skill,\n SkillContext,\n SkillInput,\n SkillLlmOverride,\n SkillMode,\n SkillOutput,\n} 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 * Declared LLM dependency. The (provider, model) pair tells the runtime\n * which API key the script reaches under the hood so it can be\n * health-monitored. Carried through from SKILL.md as-is; the script\n * itself reads the key from its environment.\n */\n llmOverride?: SkillLlmOverride;\n /**\n * MIME type the script declares for a file result (SKILL.md `output_mime`).\n * Used only when the script writes a file to `ELISYM_OUTPUT_FILE`; becomes the\n * iroh attachment's mime. Defaults to `application/octet-stream`.\n */\n outputMime?: 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 llmOverride?: SkillLlmOverride;\n private scriptPath: string;\n private scriptArgs: string[];\n private scriptTimeoutMs?: number;\n private scriptEnv?: NodeJS.ProcessEnv;\n private outputMime?: string;\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.llmOverride = params.llmOverride;\n this.scriptPath = params.scriptPath;\n this.scriptArgs = params.scriptArgs;\n this.scriptTimeoutMs = params.scriptTimeoutMs;\n this.scriptEnv = params.scriptEnv;\n this.outputMime = params.outputMime;\n }\n\n async execute(input: SkillInput, ctx: SkillContext): Promise<SkillOutput> {\n // File I/O contract (P2P via iroh): the runtime fetches a file INPUT to disk\n // and passes its path as `input.filePath`; the script reads it from\n // `ELISYM_INPUT_FILE`. For a file RESULT, the script writes to the path in\n // `ELISYM_OUTPUT_FILE` (a fresh temp file); if it does, the runtime seeds that\n // file via iroh. A script that ignores these vars keeps the original\n // stdin -> stdout text behavior unchanged.\n const outDir = await mkdtemp(join(tmpdir(), 'elisym-skill-out-'));\n const outputFile = join(outDir, 'output');\n const env: NodeJS.ProcessEnv = {\n ...(this.scriptEnv ?? process.env),\n ELISYM_OUTPUT_FILE: outputFile,\n };\n if (input.filePath !== undefined) {\n env.ELISYM_INPUT_FILE = input.filePath;\n }\n\n // Keep the temp dir only when we hand a file result back to the runtime: it\n // seeds the file AFTER execute() returns, so we cannot delete it here - we\n // pass a `cleanup` callback the runtime invokes once seeding is done. Every\n // other path - text result, error, no file written - cleans up in `finally`.\n let keepOutDir = false;\n try {\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,\n });\n if (result.spawnError) {\n throw new ScriptExecutionError(\n null,\n result.spawnError.message,\n 'script could not be started',\n );\n }\n if (result.code === SCRIPT_EXIT_BILLING_EXHAUSTED) {\n throw new ScriptBillingExhaustedError(result.code, result.stdout, result.stderr);\n }\n if (result.code !== 0) {\n const detail = result.stderr.trim() || result.stdout.trim() || '(no output)';\n // Generic message reaches the customer; raw stderr/stdout stays on `detail`\n // for the operator log and health-monitor classification only.\n throw new ScriptExecutionError(result.code, detail);\n }\n\n // File result: the script wrote a non-empty file to ELISYM_OUTPUT_FILE. The\n // stdout note (`data`) may be empty here - the runtime delivers the file\n // attachment, so the empty-output guard below intentionally does not apply.\n const outputStat = await stat(outputFile).catch(() => null);\n if (outputStat !== null && outputStat.isFile() && outputStat.size > 0) {\n keepOutDir = true;\n return {\n data: result.stdout.trim(),\n filePath: outputFile,\n outputMime: this.outputMime ?? 'application/octet-stream',\n cleanup: async () => {\n await rm(outDir, { recursive: true, force: true });\n },\n };\n }\n\n const output = result.stdout.trim();\n if (output === '') {\n // Exit 0 with no output is not a deliverable result: the marketplace\n // rejects empty results at delivery, but only after the ledger has\n // marked the job `executed`, and recovery then retries the empty\n // result on every tick forever. Failing here keeps the job on the\n // paid -> failed path so recovery terminates it. stderr (if any)\n // carries the underlying reason for the operator log.\n const detail = result.stderr.trim() || '(no stderr)';\n throw new ScriptExecutionError(result.code, detail, 'script produced empty output');\n }\n return { data: output };\n } finally {\n if (!keepOutDir) {\n await rm(outDir, { recursive: true, force: true }).catch(() => {});\n }\n }\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_LONG_FORM_ARTICLE = 30023;\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/** Discovery tag attached to elisym agent policy events (kind 30023). */\nexport const POLICY_T_TAG = 'elisym-policy';\n/** d-tag prefix for policy events: full d-tag = `<prefix><type>` (e.g. `elisym-policy-tos`). */\nexport const POLICY_D_TAG_PREFIX = 'elisym-policy-';\n/** Validation regex for policy `type` slug. Lowercase ASCII + hyphen, 1-32 chars, no leading/trailing hyphen. */\nexport const POLICY_TYPE_REGEX = /^[a-z0-9](?:[a-z0-9-]{0,30}[a-z0-9])?$/;\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 // Default ceiling for a single iroh file transfer (seed/fetch). A tunable\n // default, not a protocol constant - the transfer is resumable and its own\n // budget, decoupled from the result-wait window.\n IROH_FETCH_TIMEOUT_MS: 300_000,\n} as const;\n\n/** Protocol limits for input validation. */\nexport const LIMITS = {\n MAX_INPUT_LENGTH: 100_000,\n // NIP-44 v2 hard cap on encrypted plaintext: the pad() length prefix is a u16,\n // so the plaintext can be at most 65_535 BYTES (not chars). Encrypting anything\n // larger throws `invalid plaintext size` inside nip44Encrypt. This is the binding\n // limit for TARGETED (encrypted) jobs - lower than every relay's NIP-11 cap.\n NIP44_MAX_PLAINTEXT_BYTES: 65_535,\n // Spill threshold for encrypted content: above this many UTF-8 bytes, callers\n // route the text through iroh out-of-band instead of inlining it. A non-spilled\n // job is encrypted RAW (no envelope - see marketplace.submitJobRequest), so a\n // 60_000-byte input is a 60_000-byte plaintext; the ~5.5KB gap under the hard cap\n // is plain slack, and NIP44_MAX_PLAINTEXT_BYTES is the SDK backstop.\n MAX_ENCRYPTED_INLINE_BYTES: 60_000,\n // Ceiling above which a text/* attachment is NOT materialized back into a string\n // (re-inlined into SkillInput.data) - the consumer gets a filePath / explicit\n // fetch instead. Also bounds the in-memory git-diff buffer (memory-DoS guard).\n MAX_REINLINE_TEXT_BYTES: 4_194_304, // 4 MiB\n // Hard safety cap on a single file transferred via iroh, enforced on the\n // actual streamed bytes (never the sender-declared `size`). A tunable default;\n // providers may lower it per deployment.\n MAX_FILE_SIZE: 1_073_741_824, // 1 GiB\n\n MAX_TIMEOUT_SECS: 600,\n // Upper bound for execution budgets (`max_execution_secs` / `execution_timeout_secs`).\n // Distinct from MAX_TIMEOUT_SECS (the result-wait cap): execution budgets may be\n // hours, so this exists only to keep `secs * 1000` within Node's setTimeout limit\n // (2_147_483_647 ms) - a larger value overflows and fires the timer immediately.\n MAX_EXECUTION_SECS: 2_147_483,\n MAX_CAPABILITIES: 20,\n MAX_DESCRIPTION_LENGTH: 500,\n MAX_AGENT_NAME_LENGTH: 64,\n MAX_CAPABILITY_LENGTH: 64,\n MAX_POLICY_CONTENT_LENGTH: 50_000,\n MAX_POLICIES_PER_AGENT: 12,\n MAX_POLICY_TYPE_LENGTH: 32,\n MAX_POLICY_TITLE_LENGTH: 120,\n MAX_POLICY_SUMMARY_LENGTH: 280,\n MAX_POLICY_VERSION_LENGTH: 32,\n} as const;\n\nconst UTF8_ENCODER = new TextEncoder();\n\n/**\n * UTF-8 byte length of a string. All size guards on encrypted content measure\n * BYTES, not `String.length` (UTF-16 code units): NIP-44's plaintext cap is a\n * byte cap, so a multibyte string under the char cap can still exceed it.\n */\nexport function utf8ByteLength(value: string): number {\n return UTF8_ENCODER.encode(value).length;\n}\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 { LIMITS } 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 /**\n * LLM provider id. For `mode: 'llm'` this overrides the agent default for\n * runtime LLM execution. For script modes, it declares the LLM the script\n * depends on so the agent can health-monitor the API key (startup probe +\n * reactive markUnhealthy + lazy recovery). Pairs with `model`.\n */\n provider?: unknown;\n /** LLM model id. Same semantics as `provider`. Must be set together with `provider`. */\n model?: unknown;\n /** Per-skill max_tokens override. Only valid for `mode: 'llm'`. */\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 * MIME type for a file result. Only valid in mode 'dynamic-script' (the only\n * mode that can emit a file via `ELISYM_OUTPUT_FILE`). Becomes the iroh\n * attachment's mime; defaults to `application/octet-stream` when omitted.\n */\n output_mime?: unknown;\n /**\n * MIME the skill expects as a file input. Only valid in mode 'dynamic-script'\n * (the only mode that receives a file via `ELISYM_INPUT_FILE`). Discovery hint\n * only - the runtime still content-sniffs the actual file and does not enforce\n * this. Convention: `*` = any file, `image/*` = any image, `image/png` =\n * exact. Its presence signals \"this capability needs a file input\".\n */\n input_mime?: 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 * Optional per-skill execution budget in seconds. Applies to any skill mode.\n * `0` means unlimited. Omitted => the runtime falls through to the agent-level\n * `execution_timeout_secs`, then to unlimited.\n */\n max_execution_secs?: 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 / dependency. Present when SKILL.md declared at\n * least one of `provider`/`model`/`max_tokens`. Parse-time invariant:\n * `provider` set iff `model` set; `max_tokens` only when mode === 'llm'.\n *\n * For mode 'llm': the runtime uses these to construct the LLM client.\n * For script modes: the (provider, model) pair declares the API key the\n * script depends on so the agent can health-monitor it.\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 /** MIME for a file result (mode 'dynamic-script' only). */\n outputMime?: string;\n /**\n * MIME the skill expects as a file input (mode 'dynamic-script' only).\n * Discovery hint only; not enforced at runtime. Presence signals the\n * capability needs a file input (clients gate file-only flows on it).\n */\n inputMime?: string;\n /** Optional per-skill rate limit (any mode). */\n rateLimit?: SkillRateLimit;\n /**\n * Per-skill execution budget in seconds (any mode). `0` => explicitly\n * unlimited. `undefined` => caller falls through to the agent-level default,\n * then to unlimited.\n */\n executionTimeoutSecs?: 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 asString = (typeof sol === 'string' ? sol : String(sol)).trim();\n // Free skills declare price 0; `parseAssetAmount` rejects non-positive amounts,\n // so the zero case is handled here. Everything else goes through the exact\n // integer/string parser - no floating-point multiply (see money-math rule).\n if (/^0+(?:\\.0+)?$/.test(asString)) {\n return 0n;\n }\n try {\n return parseAssetAmount(NATIVE_SOL, asString);\n } catch {\n throw new Error(`Invalid SOL amount: ${sol}`);\n }\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 / dependency block. The\n * all-or-nothing rule applies to (`provider`, `model`); `max_tokens` is\n * independent.\n *\n * Semantics by mode:\n * - `mode: 'llm'`: provider+model override the agent default for runtime\n * LLM execution. `max_tokens` overrides the agent default cap.\n * - script modes (`static-script` / `dynamic-script` / `static-file`):\n * provider+model declare which LLM key the script depends on so the\n * agent runtime can health-monitor it (startup probe + reactive\n * markUnhealthy on `SCRIPT_EXIT_BILLING_EXHAUSTED` + lazy recovery).\n * `max_tokens` is rejected here - it has no runtime effect because\n * the script handles its own LLM call and token limits.\n *\n * Returns `undefined` when no LLM fields are declared at all.\n * Throws on partial pair, invalid provider, empty model, out-of-range\n * max_tokens, or `max_tokens` declared on a non-llm mode.\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 (hasMaxTokens && mode !== 'llm') {\n throw new Error(\n `SKILL.md \"${skillName}\": \"max_tokens\" is only valid in mode 'llm' (got '${mode}'). For script modes, control token limits inside the script.`,\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\n// Friendly parse-time check for `output_mime`. The on-wire FileAttachment schema\n// independently caps mime at 255 bytes; this just keeps a malformed value out of\n// the skill instance with a clear message.\nfunction validateOutputMime(skillName: string, raw: unknown): string | undefined {\n if (raw === undefined || raw === null) {\n return undefined;\n }\n if (typeof raw !== 'string' || raw.length === 0) {\n throw new Error(\n `SKILL.md \"${skillName}\": \"output_mime\" must be a non-empty string (e.g. \"image/png\")`,\n );\n }\n if (raw.length > 255) {\n throw new Error(`SKILL.md \"${skillName}\": \"output_mime\" too long (max 255 chars)`);\n }\n return raw;\n}\n\n// Parse-time check for `input_mime`. Discovery hint only (the runtime sniffs the\n// real file); no MIME-grammar validation so the `*`/`image/*` convention passes.\n// Capped at 255 chars to match the read-side guard in `parseCapabilityEvent`.\nfunction validateInputMime(skillName: string, raw: unknown): string | undefined {\n if (raw === undefined || raw === null) {\n return undefined;\n }\n if (typeof raw !== 'string' || raw.length === 0) {\n throw new Error(\n `SKILL.md \"${skillName}\": \"input_mime\" must be a non-empty string (e.g. \"image/png\" or \"*\")`,\n );\n }\n if (raw.length > 255) {\n throw new Error(`SKILL.md \"${skillName}\": \"input_mime\" too long (max 255 chars)`);\n }\n return raw;\n}\n\nfunction validateMaxExecutionSecs(skillName: string, raw: unknown): number | undefined {\n if (raw === undefined || raw === null) {\n return undefined;\n }\n // Mode-agnostic: applies to every skill mode. `0` is allowed and means\n // \"explicitly unlimited\" (overrides any agent-level cap back to no limit).\n if (typeof raw !== 'number' || !Number.isInteger(raw) || raw < 0) {\n throw new Error(\n `SKILL.md \"${skillName}\": \"max_execution_secs\" must be a non-negative integer (0 = unlimited)`,\n );\n }\n if (raw > LIMITS.MAX_EXECUTION_SECS) {\n throw new Error(\n `SKILL.md \"${skillName}\": \"max_execution_secs\" must be <= ${LIMITS.MAX_EXECUTION_SECS} (larger values overflow setTimeout)`,\n );\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 // SOL prices route through `solToLamports`, which uses the same exact\n // integer parser as other assets but tolerates a 0 price so the\n // `allowFreeSkills` check below can run (parseAssetAmount rejects 0).\n priceSubunits = solToLamports(priceString);\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 let outputMime: string | undefined;\n let inputMime: string | 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 if (frontmatter.output_mime !== undefined) {\n throw new Error(\n `SKILL.md \"${frontmatter.name}\": \"output_mime\" is only valid in mode 'dynamic-script'`,\n );\n }\n if (frontmatter.input_mime !== undefined) {\n throw new Error(\n `SKILL.md \"${frontmatter.name}\": \"input_mime\" is only valid in mode 'dynamic-script'`,\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 // Only dynamic-script can exchange files (via ELISYM_OUTPUT_FILE / ELISYM_INPUT_FILE).\n if (mode === 'dynamic-script') {\n outputMime = validateOutputMime(frontmatter.name, frontmatter.output_mime);\n inputMime = validateInputMime(frontmatter.name, frontmatter.input_mime);\n } else {\n if (frontmatter.output_mime !== undefined) {\n throw new Error(\n `SKILL.md \"${frontmatter.name}\": \"output_mime\" is only valid in mode 'dynamic-script'`,\n );\n }\n if (frontmatter.input_mime !== undefined) {\n throw new Error(\n `SKILL.md \"${frontmatter.name}\": \"input_mime\" is only valid in mode 'dynamic-script'`,\n );\n }\n }\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 if (frontmatter.output_mime !== undefined) {\n throw new Error(\n `SKILL.md \"${frontmatter.name}\": \"output_mime\" is only valid in mode 'dynamic-script'`,\n );\n }\n if (frontmatter.input_mime !== undefined) {\n throw new Error(\n `SKILL.md \"${frontmatter.name}\": \"input_mime\" is only valid in mode 'dynamic-script'`,\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 const executionTimeoutSecs = validateMaxExecutionSecs(\n frontmatter.name,\n frontmatter.max_execution_secs,\n );\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 outputMime,\n inputMime,\n rateLimit,\n executionTimeoutSecs,\n };\n}\n\nfunction buildSkillFromParsed(parsed: ParsedSkill, skillDir: string, logger: LoaderLogger): Skill {\n // Containment for `image_file`, matching `script`/`output_file` (which throw).\n // The image is decorative, so an out-of-dir path is dropped with a warning\n // rather than failing the load. Without this, `image_file: ../../.secrets.json`\n // would be read and uploaded to a public media host at startup (exfiltration).\n let imageFile = parsed.imageFile;\n if (imageFile !== undefined && resolveInsidePath(skillDir, imageFile) === null) {\n logger.warn?.(\n { skill: parsed.name, imageFile },\n 'SKILL.md \"image_file\" escapes the skill directory; ignoring it',\n );\n imageFile = undefined;\n }\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,\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,\n llmOverride: parsed.llmOverride,\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 scriptParams = {\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,\n llmOverride: parsed.llmOverride,\n };\n // Only dynamic-script supports a file result, so `outputMime` is threaded\n // only there (StaticScriptSkill has no such param).\n return parsed.mode === 'dynamic-script'\n ? new DynamicScriptSkill({ ...scriptParams, outputMime: parsed.outputMime })\n : new StaticScriptSkill(scriptParams);\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"]}
|