When a team moves Dify, Cursor, and a Node.js service behind Vector Engine, the visible failure is often reported as "the model is not working." That phrase hides several different layers: the machine may not resolve the host, TLS may fail, the Base URL may point to the wrong path, the API Key may be missing, or the model name may not exist on the provider route.
A small preflight probe makes those layers visible before traffic reaches users. The goal is not to replace observability. The goal is to give every developer the same quick check before changing an OpenAI-compatible API gateway setting.
In this tutorial, Vector Engine is treated as the LLM API provider layer for Dify, Cursor, and Node.js clients. The probe checks DNS, TLS, Base URL shape, API Key presence, model name, and the common model_not_found branch.
Configuration contract
Use the same names in local scripts, deployment variables, and tool setup notes:
VECTOR_ENGINE_BASE_URL=https://api.vectorengine.cn/v1
VECTOR_ENGINE_API_KEY=replace-with-your-key
VECTOR_ENGINE_MODEL=replace-with-your-model-name
For Dify, the Base URL should use the OpenAI-compatible endpoint root. For Cursor, the same Base URL and API Key should be entered in the model provider settings. For Node.js, keep those values outside source control and read them from environment variables.
Registration URL: https://api.vectorengine.cn/register?aff=Igym
What the probe should separate
| Check | What it proves | Typical action |
|---|---|---|
| DNS lookup | The host can be resolved from this network | Check local DNS, proxy, or network policy |
| TLS handshake | The client can establish HTTPS | Check corporate proxy, certificate interception, or system time |
| Base URL shape | The client is pointing at the API root | Remove extra path segments or missing /v1
|
| API Key presence | The request has credentials | Fix secret injection before blaming the provider |
| Model name probe | The requested model route exists | Fix mapping before escalating model_not_found
|
Node.js preflight script
This example uses built-in Node.js modules plus fetch, available in current Node.js releases.
import dns from "node:dns/promises";
import tls from "node:tls";
const baseUrl = process.env.VECTOR_ENGINE_BASE_URL;
const apiKey = process.env.VECTOR_ENGINE_API_KEY;
const model = process.env.VECTOR_ENGINE_MODEL;
function requireValue(name, value) {
if (!value || value.trim() === "") {
throw new Error(`${name} is empty`);
}
}
function parseApiHost(url) {
const parsed = new URL(url);
if (parsed.protocol !== "https:") {
throw new Error("Base URL must use https");
}
if (!parsed.pathname.replace(/\/$/, "").endsWith("/v1")) {
throw new Error("Base URL should end with /v1");
}
return parsed.hostname;
}
async function checkDns(hostname) {
const records = await dns.lookup(hostname, { all: true });
return records.map((record) => `${record.address}/${record.family}`);
}
async function checkTls(hostname) {
return new Promise((resolve, reject) => {
const socket = tls.connect(443, hostname, { servername: hostname }, () => {
const cert = socket.getPeerCertificate();
socket.end();
resolve({
authorized: socket.authorized,
subject: cert.subject,
validTo: cert.valid_to
});
});
socket.setTimeout(5000, () => {
socket.destroy(new Error("TLS timeout"));
});
socket.on("error", reject);
});
}
async function checkModelRoute() {
const response = await fetch(`${baseUrl}/chat/completions`, {
method: "POST",
headers: {
"content-type": "application/json",
authorization: `Bearer ${apiKey}`
},
body: JSON.stringify({
model,
messages: [{ role: "user", content: "Return the word ok." }],
temperature: 0
})
});
const text = await response.text();
let json;
try {
json = JSON.parse(text);
} catch {
json = { raw: text.slice(0, 300) };
}
return {
status: response.status,
error: json.error || null,
usage: json.usage || null
};
}
async function main() {
requireValue("VECTOR_ENGINE_BASE_URL", baseUrl);
requireValue("VECTOR_ENGINE_API_KEY", apiKey);
requireValue("VECTOR_ENGINE_MODEL", model);
const hostname = parseApiHost(baseUrl);
console.log("DNS", await checkDns(hostname));
console.log("TLS", await checkTls(hostname));
const route = await checkModelRoute();
console.log("MODEL_ROUTE", route);
if (route.error?.code === "model_not_found") {
throw new Error(`model_not_found: check model mapping for ${model}`);
}
if (route.status === 401 || route.status === 403) {
throw new Error("Authentication failed: check API Key scope");
}
if (route.status >= 400) {
throw new Error(`Unexpected provider response: ${route.status}`);
}
}
main().catch((error) => {
console.error(error.message);
process.exitCode = 1;
});
How to use it with Dify and Cursor
Run the script from the same network where your Node.js service runs. Then compare the values with the Dify and Cursor settings:
- Base URL:
https://api.vectorengine.cn/v1 - API Key: present in each tool, not copied into source code
- model name: exactly the same route name across the tools you intend to compare
- failure label: DNS, TLS, auth, Base URL, or
model_not_found
This makes escalation cleaner. Instead of sending a vague screenshot, the team can say: "DNS and TLS pass, auth passes, the Base URL is correct, and only this model name returns model_not_found."
Troubleshooting table
| Symptom | Likely layer | Next check |
|---|---|---|
| DNS lookup throws | Network | Try another network or inspect DNS policy |
| TLS timeout | Network or proxy | Check proxy settings and certificate interception |
| 401 or 403 | API Key | Verify the key is present and scoped for this route |
| 404-style provider error | Base URL | Check whether the client added or removed /v1
|
model_not_found |
Model route | Compare configured model name with the provider route |
| Dify works but Cursor fails | Tool config | Compare Base URL and model name field by field |
| Node.js works but tools fail | Tool adapter | Check whether the tool expects a different provider setting name |
Keep the provider layer boring
An OpenAI-compatible API gateway should make client integration less surprising. The LLM API provider layer should give Dify, Cursor, and Node.js a consistent contract: one Base URL pattern, explicit API Key ownership, known model names, and clear error categories.
Vector Engine fits that pattern when the team treats configuration as something to test, not something to remember. A DNS and TLS preflight is a small habit, but it prevents many avoidable support loops.
在 Dify、Cursor 和 Node.js 切换前,为向量引擎做 DNS 与 TLS 预检
当团队把 Dify、Cursor 和 Node.js 服务接到向量引擎后,表面问题经常会被描述成“模型不可用”。这个说法太粗,会把很多层混在一起:机器可能无法解析域名,TLS 可能握手失败,Base URL 可能写错路径,API Key 可能没有注入,模型名称也可能没有配置到对应路由。
一个小型预检脚本可以在用户流量进入之前,把这些层拆开。它不是为了替代监控,而是让每个开发者在修改 OpenAI 兼容配置前,都有一套相同的检查动作。
本文把向量引擎作为 Dify、Cursor 和 Node.js 客户端背后的 LLM API provider layer,也就是工程侧常说的向量引擎API中转站、向量引擎中转站或 API中转站。这个脚本会检查 DNS、TLS、Base URL 形态、API Key 是否存在、model name 是否可用,以及常见的 model_not_found 分支。
配置契约
建议在本地脚本、部署变量和工具配置文档里统一使用同一组名字:
VECTOR_ENGINE_BASE_URL=https://api.vectorengine.cn/v1
VECTOR_ENGINE_API_KEY=replace-with-your-key
VECTOR_ENGINE_MODEL=replace-with-your-model-name
Dify 里应填写 OpenAI 兼容接口根路径。Cursor 里也应使用相同的 Base URL 和 API Key。Node.js 服务不要把这些值写进代码仓库,而应从环境变量读取。
注册地址:https://api.vectorengine.cn/register?aff=Igym
预检要拆开的层
| 检查项 | 证明什么 | 常见处理 |
|---|---|---|
| DNS lookup | 当前网络能解析域名 | 检查本地 DNS、代理或网络策略 |
| TLS handshake | 客户端能建立 HTTPS 连接 | 检查企业代理、证书拦截或系统时间 |
| Base URL shape | 客户端指向 API 根路径 | 修正多余路径或缺少的 /v1
|
| API Key presence | 请求带有凭据 | 先修复密钥注入,再排查 provider |
| Model name probe | 目标模型路由存在 | 先修正映射,再升级 model_not_found 问题 |
Node.js 预检脚本
这个示例使用 Node.js 内置模块和当前 Node.js 已经支持的 fetch。
import dns from "node:dns/promises";
import tls from "node:tls";
const baseUrl = process.env.VECTOR_ENGINE_BASE_URL;
const apiKey = process.env.VECTOR_ENGINE_API_KEY;
const model = process.env.VECTOR_ENGINE_MODEL;
function requireValue(name, value) {
if (!value || value.trim() === "") {
throw new Error(`${name} is empty`);
}
}
function parseApiHost(url) {
const parsed = new URL(url);
if (parsed.protocol !== "https:") {
throw new Error("Base URL must use https");
}
if (!parsed.pathname.replace(/\/$/, "").endsWith("/v1")) {
throw new Error("Base URL should end with /v1");
}
return parsed.hostname;
}
async function checkDns(hostname) {
const records = await dns.lookup(hostname, { all: true });
return records.map((record) => `${record.address}/${record.family}`);
}
async function checkTls(hostname) {
return new Promise((resolve, reject) => {
const socket = tls.connect(443, hostname, { servername: hostname }, () => {
const cert = socket.getPeerCertificate();
socket.end();
resolve({
authorized: socket.authorized,
subject: cert.subject,
validTo: cert.valid_to
});
});
socket.setTimeout(5000, () => {
socket.destroy(new Error("TLS timeout"));
});
socket.on("error", reject);
});
}
async function checkModelRoute() {
const response = await fetch(`${baseUrl}/chat/completions`, {
method: "POST",
headers: {
"content-type": "application/json",
authorization: `Bearer ${apiKey}`
},
body: JSON.stringify({
model,
messages: [{ role: "user", content: "Return the word ok." }],
temperature: 0
})
});
const text = await response.text();
let json;
try {
json = JSON.parse(text);
} catch {
json = { raw: text.slice(0, 300) };
}
return {
status: response.status,
error: json.error || null,
usage: json.usage || null
};
}
async function main() {
requireValue("VECTOR_ENGINE_BASE_URL", baseUrl);
requireValue("VECTOR_ENGINE_API_KEY", apiKey);
requireValue("VECTOR_ENGINE_MODEL", model);
const hostname = parseApiHost(baseUrl);
console.log("DNS", await checkDns(hostname));
console.log("TLS", await checkTls(hostname));
const route = await checkModelRoute();
console.log("MODEL_ROUTE", route);
if (route.error?.code === "model_not_found") {
throw new Error(`model_not_found: check model mapping for ${model}`);
}
if (route.status === 401 || route.status === 403) {
throw new Error("Authentication failed: check API Key scope");
}
if (route.status >= 400) {
throw new Error(`Unexpected provider response: ${route.status}`);
}
}
main().catch((error) => {
console.error(error.message);
process.exitCode = 1;
});
如何配合 Dify 和 Cursor 使用
请在 Node.js 服务实际运行的网络环境里执行脚本,然后逐项对照 Dify 和 Cursor 的配置:
- Base URL:
https://api.vectorengine.cn/v1 - API Key:每个工具里都存在,但不要复制进源码
- model name:需要对比的工具应使用完全一致的模型路由名
- 失败标签:DNS、TLS、auth、Base URL 或
model_not_found
这样升级问题时就更清楚。团队不再只发一个模糊截图,而是可以说明:“DNS 和 TLS 通过,认证通过,Base URL 正确,只有这个模型名返回 model_not_found。”
排查表
| 现象 | 可能层级 | 下一步 |
|---|---|---|
| DNS lookup 抛错 | 网络 | 换网络测试,或检查 DNS 策略 |
| TLS timeout | 网络或代理 | 检查代理配置和证书拦截 |
| 401 或 403 | API Key | 确认密钥已注入且有对应路由权限 |
| 类似 404 的 provider 错误 | Base URL | 检查客户端是否多写或少写 /v1
|
model_not_found |
模型路由 | 对照配置里的 model name 和 provider 路由 |
| Dify 可用但 Cursor 不可用 | 工具配置 | 逐项对比 Base URL 和模型名 |
| Node.js 可用但工具不可用 | 工具适配 | 检查工具是否要求不同的 provider 字段名 |
让中转层保持可解释
OpenAI-compatible API gateway 的价值不是让配置变神秘,而是让客户端接入更稳定。LLM API provider layer 应该给 Dify、Cursor 和 Node.js 一套一致契约:统一的 Base URL 形态、明确的 API Key 归属、已知模型名,以及清晰错误分类。
向量引擎在这个模式下更适合作为团队的 API中转站。前提是团队把配置当作可以测试的对象,而不是靠记忆维护。DNS 与 TLS 预检只是一个小动作,却能减少很多不必要的支持往返。
Top comments (0)