@sellable/install
Version:
One-command installer for Sellable MCP in Claude Code, Codex, and Hermes
78 lines (70 loc) • 2.5 kB
JavaScript
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();
}