UNPKG

@sellable/install

Version:

One-command installer for Sellable MCP in Claude Code, Codex, and Hermes

78 lines (70 loc) • 2.5 kB
#!/usr/bin/env node import { resolve } from "node:path"; import { fileURLToPath } from "node:url"; import { FlySkillsBridgeError, SKILLS_REQUEST_MAX_BYTES, executeExternalSkillsBridgeOperation, } from "./fly-skills-bridge.mjs"; export const FLY_SKILLS_EXEC_ARGUMENT_MAX_BYTES = 96 * 1024; export const FLY_SKILLS_EXEC_ARGUMENT_MAX_COUNT = 8; const BASE64URL_CHUNK = /^[A-Za-z0-9_-]+$/; const FLY_SKILLS_EXEC_ENCODED_MAX_BYTES = Math.ceil(SKILLS_REQUEST_MAX_BYTES / 3) * 4; export function decodeFlySkillsExecArguments(args) { if (!Array.isArray(args) || args.length === 0) { throw new FlySkillsBridgeError("skills_request_rejected"); } if (args.length > FLY_SKILLS_EXEC_ARGUMENT_MAX_COUNT) { throw new FlySkillsBridgeError("skills_request_too_large"); } let encoded = ""; for (const chunk of args) { if (typeof chunk !== "string" || !BASE64URL_CHUNK.test(chunk)) { throw new FlySkillsBridgeError("skills_request_rejected"); } if (Buffer.byteLength(chunk, "utf8") > FLY_SKILLS_EXEC_ARGUMENT_MAX_BYTES) { throw new FlySkillsBridgeError("skills_request_too_large"); } encoded += chunk; if (encoded.length > FLY_SKILLS_EXEC_ENCODED_MAX_BYTES) { throw new FlySkillsBridgeError("skills_request_too_large"); } } let bytes; try { bytes = Buffer.from(encoded, "base64url"); } catch { throw new FlySkillsBridgeError("skills_request_rejected"); } if (bytes.toString("base64url") !== encoded) { throw new FlySkillsBridgeError("skills_request_rejected"); } if (bytes.byteLength > SKILLS_REQUEST_MAX_BYTES) { throw new FlySkillsBridgeError("skills_request_too_large"); } try { const json = new TextDecoder("utf-8", { fatal: true }).decode(bytes); return JSON.parse(json); } catch { throw new FlySkillsBridgeError("skills_request_rejected"); } } export async function runFlySkillsBridgeExecCli() { try { const request = decodeFlySkillsExecArguments(process.argv.slice(2)); const result = executeExternalSkillsBridgeOperation(request); process.stdout.write(`${JSON.stringify(result)}\n`); process.exitCode = result.ok ? 0 : 2; } catch (error) { process.stdout.write( `${JSON.stringify({ ok: false, code: error instanceof FlySkillsBridgeError ? error.code : "skills_bridge_failed" })}\n` ); process.exitCode = 2; } } if ( resolve(process.argv[1] ?? "") === resolve(fileURLToPath(import.meta.url)) ) { await runFlySkillsBridgeExecCli(); }