UNPKG

@sellable/install

Version:

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

107 lines (103 loc) • 3.73 kB
import { pathToFileURL } from "node:url"; import { compileEndpointModelSelection, endpointModelSelectionChain, endpointModelSelectionSource, } from "./endpoint-model-selection.mjs"; import { createHermesRunsClient } from "./hermes-runs-client.mjs"; import { probeRunsClient } from "./workspace-connection-client.mjs"; // Fixed read-only machine command. Callers supply identities, never a URL, // credential path, shell command, or prompt. The machine holds no connection // registry, so no id names a connection it can check: a workspace connection // is probed by the server and shape-checked here by VERIFY. export async function checkRunsApiConnection(request) { return { connectionId: request.connectionId, state: "NOT_CONFIGURED", checkedAt: new Date().toISOString(), }; } export async function verifyRunsApiSelection( request, { env = process.env, makeDefaultClient = createHermesRunsClient } = {} ) { const result = (state, servedRuntime) => ({ connectionId: request.connectionId, state, checkedAt: new Date().toISOString(), ...(servedRuntime ? { servedRuntime } : {}), }); if ( request.runtimeId !== env.SELLABLE_RUNTIME_ID || !/^[A-Za-z0-9_-]{1,128}$/.test(request.profileId ?? "") ) return result("NOT_CONFIGURED"); const compiled = compileEndpointModelSelection(request.modelSelection); if (compiled === "invalid") return result("NOT_CONFIGURED"); // A fallback chain is verified one step per call. The control plane sends // the primary step's check the whole chain, so a machine whose compiler // cannot run a chain refuses it here and no chain is saved for it. const selection = endpointModelSelectionChain(compiled)[0] ?? null; // A workspace connection's key is fetched per attempt by the run, so the // machine holds none to probe with. This is a shape check only; the server // performs the connectivity probe (228-05). if (selection?.modelConnectionId) return result("REACHABLE"); if (request.connectionId !== endpointModelSelectionSource(selection)) return result("NOT_CONFIGURED"); const apiKeyFile = env.SELLABLE_AGENT_SERVER_AUTHENTICATED_KIND === "ADMIN" ? "/run/sellable-agent/admin-runtime/api-server-key" : `/run/sellable-agent/${request.profileId}/api-server-key`; let client; try { client = makeDefaultClient({ apiKeyFile }); } catch { return result("UNAVAILABLE"); } const probe = await probeRunsClient(client, selection, { signal: AbortSignal.timeout(70_000), submitVerification: true, }); return result(probe.state, probe.servedRuntime); } if ( process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href ) { try { const raw = process.argv[2]; if (!raw || raw.length > 4096) throw new Error(); const request = JSON.parse(Buffer.from(raw, "base64url").toString("utf8")); const verify = request.action === "VERIFY"; if ( Object.keys(request) .filter( (key) => !["action", "profileId", "modelSelection"].includes(key) ) .sort() .join(",") !== "agentId,connectionId,endpointId,runtimeId,workspaceId" || [ request.agentId, request.connectionId, request.endpointId, request.runtimeId, request.workspaceId, ].some( (value) => typeof value !== "string" || !/^[A-Za-z0-9_.:-]{1,128}$/.test(value) ) || (request.action !== undefined && !verify) ) throw new Error(); process.stdout.write( JSON.stringify( await (verify ? verifyRunsApiSelection(request) : checkRunsApiConnection(request)) ) ); } catch { process.exitCode = 1; } }