UNPKG

@sellable/install

Version:

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

275 lines (272 loc) • 9.39 kB
import { randomBytes } from "node:crypto"; import { createHermesRunsClient } from "./hermes-runs-client.mjs"; async function boundedJson(response) { const reader = response.body?.getReader(); if (!reader) throw new Error("empty_response"); let size = 0; const chunks = []; try { while (true) { const value = await reader.read(); if (value.done) break; size += value.value.byteLength; if (size > 512 * 1024) { await reader.cancel(); throw new Error("response_too_large"); } chunks.push(value.value); } } finally { reader.releaseLock(); } return JSON.parse(Buffer.concat(chunks).toString("utf8")); } /** Text/structured-output adapter. All calls remain on the approved origin; * tools, retries and provider/model fallback are deliberately not synthesized. * The existing native client still validates the normalized run lifecycle. */ export function createOpenAiRunsClient({ connection, responseSchema, modelSelection, apiKey, fetchImpl = fetch, }) { const runs = new Map(); const json = (value, status = 200) => new Response(JSON.stringify(value), { status, headers: { "content-type": "application/json" }, }); const bridge = async (url, init = {}) => { const path = String(url).slice(connection.baseUrl.length); if (path === "/v1/runs" && init.method === "POST") { const request = JSON.parse(init.body); if ( !request.model && modelSelection && request.session_id?.startsWith("sellable_opener_stage_") ) { request.provider = modelSelection.provider; request.model = modelSelection.model; request.model_options = { ...request.model_options, reasoning_effort: modelSelection.reasoningEffort, }; } const model = connection.models.find( (item) => item.provider === request.provider && item.model === request.model && item.reasoningEfforts.includes( request.model_options?.reasoning_effort ) ); if (!model) return json({ error: "model_not_allowed" }, 403); const run = { run_id: `run_${randomBytes(16).toString("hex")}`, status: "running", controller: new AbortController(), }; const schema = request.model_options?.sellable_opener_output_contract?.schema ?? responseSchema; const structured = schema && connection.structuredOutputs !== false; const instructions = structured || !schema ? request.instructions : `${request.instructions}\nReturn only JSON conforming to this schema:\n${JSON.stringify(schema)}`; const history = (request.conversation_history ?? []).map( ({ role, content }) => ({ role, content }) ); const effort = request.model_options?.reasoning_effort; const responses = connection.protocol === "openai-responses"; const body = responses ? { model: request.model, instructions, input: [...history, { role: "user", content: request.input }], stream: false, store: false, max_output_tokens: 4096, ...(effort && effort !== "none" ? { reasoning: { effort } } : {}), ...(structured ? { text: { format: { type: "json_schema", name: "endpoint_output", strict: true, schema, }, }, } : {}), } : { model: request.model, messages: [ { role: "system", content: instructions }, ...history, { role: "user", content: request.input }, ], stream: false, max_tokens: 4096, ...(effort && effort !== "none" ? { reasoning_effort: effort } : {}), ...(structured ? { response_format: { type: "json_schema", json_schema: { name: "endpoint_output", strict: true, schema, }, }, } : {}), }; runs.set(run.run_id, run); run.promise = (async () => { try { const response = await fetchImpl( `${connection.baseUrl}/${responses ? "responses" : "chat/completions"}`, { method: "POST", headers: { authorization: init.headers.authorization, "content-type": "application/json", }, body: JSON.stringify(body), redirect: "error", signal: AbortSignal.any([ run.controller.signal, AbortSignal.timeout(750_000), ]), } ); if (!response.ok) throw new Error( response.status === 401 || response.status === 403 ? "access_denied" : "provider_unavailable" ); const value = await boundedJson(response); const output = responses ? (value.output ?? []) .filter((item) => item.type === "message") .flatMap((item) => item.content ?? []) .filter((item) => item.type === "output_text") .map((item) => item.text) .join("") : value.choices?.[0]?.message?.content; if ( typeof output !== "string" || !output.trim() || Buffer.byteLength(output) > 48 * 1024 || (responses ? value.status !== "completed" : value.choices?.[0]?.finish_reason !== "stop") || typeof value.model !== "string" || !/^[A-Za-z0-9][A-Za-z0-9._:/-]{0,127}$/.test(value.model) || (value.model !== request.model && !new RegExp( `^${request.model.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}-[0-9]{4}-?[0-9]{2}-?[0-9]{2}$` ).test(value.model)) ) throw new Error("output_rejected"); Object.assign(run, { status: "completed", output, runtime: { provider: request.provider, model: value.model }, usage: { input_tokens: value.usage?.input_tokens ?? value.usage?.prompt_tokens ?? 0, output_tokens: value.usage?.output_tokens ?? value.usage?.completion_tokens ?? 0, }, }); } catch (error) { Object.assign(run, { status: "failed", error: error.message === "access_denied" ? "connection_access_denied" : "connection_generation_failed", }); } })(); return json({ run_id: run.run_id, status: "started" }, 202); } const match = /^\/v1\/runs\/(run_[a-f0-9]{32})(?:\/(events|stop))?$/.exec( path ); const run = match && runs.get(match[1]); if (!run) return json({ error: "run_missing" }, 404); const snapshot = () => ({ run_id: run.run_id, status: run.status, ...(run.status === "completed" ? { output: run.output, runtime: run.runtime, usage: run.usage } : run.status === "failed" ? { error: run.error } : {}), }); if (match[2] === "stop") { run.controller.abort(); // Aborting HTTP cannot prove cancellation at a remote inference server. return json({ error: "stop_uncertain" }, 409); } if (match[2] === "events") { if (init.signal?.aborted) throw new Error("stream_aborted"); let closed = false; let abort; const cleanup = () => { closed = true; init.signal?.removeEventListener("abort", abort); }; return new Response( new ReadableStream({ start(controller) { abort = () => { if (!closed) { cleanup(); controller.error(new Error("stream_aborted")); } }; init.signal?.addEventListener("abort", abort, { once: true }); if (init.signal?.aborted) { abort(); return; } void run.promise.then(() => { if (closed) return; cleanup(); controller.enqueue( new TextEncoder().encode( `data: ${JSON.stringify({ event: run.status === "completed" ? "run.completed" : "run.failed", timestamp: new Date().toISOString(), ...snapshot() })}\n\n` ) ); controller.close(); }); }, cancel() { cleanup(); }, }), { headers: { "content-type": "text/event-stream" } } ); } return json(snapshot()); }; return createHermesRunsClient({ baseUrl: connection.baseUrl, ...(apiKey === undefined ? { apiKeyFile: connection.apiKeyFile } : { apiKey }), fetchImpl: bridge, }); }