UNPKG

comfyui-mcp

Version:

Local-first, agent-native control plane for ComfyUI — MCP server + autonomous sidebar agent that drives your live graph in natural language on ANY LLM: Claude/ChatGPT/Gemini on your subscription (no API key), free local models via Ollama (fully offline),

63 lines • 3.63 kB
// Helper for lazy-loading optional dependencies. // // Heavy or feature-gated packages (cloud SDKs, AI SDKs, cloudflared) live in // `optionalDependencies` so a `npm install --no-optional comfyui-mcp` install // still yields a working server. The features that need those deps surface a // clear "install <pkg>" error instead of crashing on import. import { ModelError } from "./errors.js"; const cache = new Map(); export function classifyImportFailure(spec, err) { const e = err; const message = typeof e?.message === "string" ? e.message : String(err); const notFound = e?.code === "ERR_MODULE_NOT_FOUND" || e?.code === "MODULE_NOT_FOUND"; if (!notFound) return { kind: "unloadable", detail: message }; // "Cannot find package 'x' imported from …" / "Cannot find module 'x'". const named = /Cannot find (?:package|module) ['"]([^'"]+)['"]/.exec(message)?.[1]; if (named === undefined) { // A not-found we cannot attribute. Treat it as the requested package rather // than inventing a transitive one — this is the pre-existing behaviour and // the common case. return { kind: "missing" }; } // SUBPATHS RUN BOTH WAYS, and only one direction is obvious. Requesting // "pkg/sub" makes Node report `Cannot find package 'pkg'` — it names the bare // PACKAGE, not what was asked for — so a `named === spec` test fails and the // package gets blamed as its own dependency. Found by a surviving mutant and // confirmed against real Node before fixing. const isSelf = named === spec || named.startsWith(`${spec}/`) || spec.startsWith(`${named}/`); return isSelf ? { kind: "missing" } : { kind: "missing-transitive", detail: named }; } export async function requireOptionalDep(spec, options) { const cached = cache.get(spec); if (cached !== undefined) return cached; try { const mod = (await import(spec)); cache.set(spec, mod); return mod; } catch (err) { const feature = options?.feature ?? spec; const installHint = options?.installHint ?? `npm install ${spec}`; const why = classifyImportFailure(spec, err); throw new ModelError(why.kind === "missing" ? `Optional dependency for ${feature} is not installed. To enable it, run: ${installHint}` : why.kind === "missing-transitive" ? `Optional dependency for ${feature} IS installed, but it could not load because ` + `${why.detail} is missing — one of its own dependencies, not this package. ` + `Running "${installHint}" will report nothing to do. Reinstall it so its ` + `dependency tree is resolved (npm install --force ${spec}), or install ${why.detail} directly.` : `Optional dependency for ${feature} IS installed, but it failed to LOAD: ${why.detail}. ` + `Running "${installHint}" will report nothing to do — the package is present and ` + `broken, which is usually a native binary built for a different Node/ABI or platform. ` + `Reinstall it (npm install --force ${spec}), or check that binary's own requirements.`, { // The code still distinguishes the two for programmatic callers: only a // genuinely absent package is MISSING. code: why.kind === "missing" ? "OPTIONAL_DEP_MISSING" : "OPTIONAL_DEP_UNLOADABLE", package: spec, cause: err instanceof Error ? err.message : String(err), }); } } //# sourceMappingURL=optional-dep.js.map