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