DEV Community

Jia
Jia

Posted on

Replay Dify and Cursor Requests in Node.js Before Blaming Vector Engine

When a team connects Dify, Cursor, and a small Node.js service to the same Vector Engine account, a failing request can look more mysterious than it really is. The error may appear inside Dify, then show up differently in Cursor, while the Node.js service logs only a failed HTTP status. If the shared provider is an OpenAI-compatible API gateway, the practical question is not "which tool is broken?" The question is "which request did each tool actually send?"

I like to treat Vector Engine as an LLM API provider layer with a small, visible contract:

  • Base URL: the endpoint used by every tool
  • API Key: the key scope assigned to that tool or service
  • model name: the exact model route configured in Dify, Cursor, and Node.js
  • payload shape: messages, tools, temperature, and optional metadata
  • error owner: who checks model_not_found, 401, 404, timeout, and quota responses

This article shows a lightweight replay check that keeps secrets out of logs while making request drift easy to see.

Step 1: Record the request contract, not the full secret

Do not paste live API keys into tickets or shared chat. Record the existence and a short fingerprint instead.

function keyFingerprint(value) {
  if (!value) return "missing";
  return `${value.slice(0, 4)}...${value.slice(-4)}`;
}

const contract = {
  tool: process.env.TOOL_NAME || "node-service",
  baseUrl: process.env.VECTOR_ENGINE_BASE_URL,
  apiKeyFingerprint: keyFingerprint(process.env.VECTOR_ENGINE_API_KEY),
  model: process.env.VECTOR_ENGINE_MODEL,
};

console.log(JSON.stringify(contract, null, 2));
Enter fullscreen mode Exit fullscreen mode

For Dify, copy the Base URL, API Key presence, and model name from the provider settings. For Cursor, copy the OpenAI-compatible provider settings. For Node.js, print the values during startup, but never print the raw key.

Step 2: Replay one small chat completion from Node.js

Use the same Base URL and model name that the tool is supposed to use. This script helps confirm whether Vector Engine can route the model before you blame Dify or Cursor.

const BASE_URL = process.env.VECTOR_ENGINE_BASE_URL;
const API_KEY = process.env.VECTOR_ENGINE_API_KEY;
const MODEL = process.env.VECTOR_ENGINE_MODEL;

async function replay() {
  if (!BASE_URL || !API_KEY || !MODEL) {
    throw new Error("Missing Base URL, API Key, or model name");
  }

  const response = await fetch(`${BASE_URL}/v1/chat/completions`, {
    method: "POST",
    headers: {
      "content-type": "application/json",
      authorization: `Bearer ${API_KEY}`,
    },
    body: JSON.stringify({
      model: MODEL,
      messages: [
        { role: "system", content: "Return a short health response." },
        { role: "user", content: "ping" },
      ],
    }),
  });

  const body = await response.json().catch(() => ({}));

  console.log({
    status: response.status,
    model: MODEL,
    errorCode: body?.error?.code,
    errorMessage: body?.error?.message,
    responseId: body?.id,
  });

  if (body?.error?.code === "model_not_found") {
    process.exitCode = 2;
  }
}

replay().catch((error) => {
  console.error(error.message);
  process.exitCode = 1;
});
Enter fullscreen mode Exit fullscreen mode

Run it with the same provider values:

VECTOR_ENGINE_BASE_URL="your-openai-compatible-base-url" \
VECTOR_ENGINE_API_KEY="your-tool-key" \
VECTOR_ENGINE_MODEL="your-model-name" \
node replay-vector-engine.js
Enter fullscreen mode Exit fullscreen mode

Step 3: Compare tool behavior

Use a small table when Dify, Cursor, and Node.js disagree.

Symptom Likely place to check Practical action
Node.js succeeds, Dify fails Dify provider settings Compare Base URL, model name, and whether the workflow uses another provider node
Node.js succeeds, Cursor fails Cursor provider settings Confirm the OpenAI-compatible API gateway entry and selected model route
All tools return model_not_found Vector Engine route or model name Check whether the configured route name exists and whether the account can access it
401 from one tool only API Key scope Rotate or replace that tool key without changing unrelated tools
404 from all tools Base URL path Confirm the /v1/chat/completions path is being appended once, not twice

This habit keeps the provider discussion concrete. Instead of arguing about whether Dify, Cursor, or Vector Engine is responsible, you compare three facts: Base URL, API Key scope, and model name.

Step 4: Keep the replay script in the repo

The script is small enough to keep beside your Node.js service. Use it after model route changes, before onboarding a new tool, and when a model_not_found error appears in only one tool. Over time, this becomes a practical support artifact for the LLM API provider layer.

Registration URL: https://api.vectorengine.cn/register?aff=Igym


在怀疑向量引擎之前,先用 Node.js 回放 Dify 和 Cursor 请求

当团队把 Dify、Cursor 和一个小型 Node.js 服务接到同一个向量引擎账号时,一次失败请求很容易被看成复杂平台问题。错误可能先出现在 Dify,随后在 Cursor 里表现不同,而 Node.js 服务日志里只留下一个 HTTP 状态。对于一个 OpenAI 兼容的向量引擎API中转站来说,真正要问的不是“哪个工具坏了”,而是“每个工具实际发出了什么请求”。

我通常把向量引擎中转站当成一个 LLM API provider layer,并把契约写得足够清楚:

  • Base URL:每个工具使用的入口地址
  • API Key:分配给具体工具或服务的密钥范围
  • model name:Dify、Cursor 和 Node.js 中配置的精确模型路由
  • 请求体形态:messages、tools、temperature 和可选元数据
  • 错误归属:谁负责处理 model_not_found、401、404、超时和配额类响应

下面的做法适合把敏感信息排除在日志之外,同时快速定位请求漂移。

步骤 1:记录请求契约,而不是记录完整密钥

不要把真实 API Key 粘贴到工单或共享聊天里。记录是否存在和一个短指纹即可。

function keyFingerprint(value) {
  if (!value) return "missing";
  return `${value.slice(0, 4)}...${value.slice(-4)}`;
}

const contract = {
  tool: process.env.TOOL_NAME || "node-service",
  baseUrl: process.env.VECTOR_ENGINE_BASE_URL,
  apiKeyFingerprint: keyFingerprint(process.env.VECTOR_ENGINE_API_KEY),
  model: process.env.VECTOR_ENGINE_MODEL,
};

console.log(JSON.stringify(contract, null, 2));
Enter fullscreen mode Exit fullscreen mode

在 Dify 里,记录 provider 设置中的 Base URL、API Key 是否存在、model name。 在 Cursor 里,记录 OpenAI-compatible provider 的配置。 在 Node.js 里,可以在启动阶段打印这些值,但不要打印原始密钥。

步骤 2:用 Node.js 回放一次小型 chat completion

使用工具应该使用的同一组 Base URL 和 model name。这个脚本能帮助你确认 API中转站是否可以正常路由模型,再决定是否排查 Dify 或 Cursor 的配置。

const BASE_URL = process.env.VECTOR_ENGINE_BASE_URL;
const API_KEY = process.env.VECTOR_ENGINE_API_KEY;
const MODEL = process.env.VECTOR_ENGINE_MODEL;

async function replay() {
  if (!BASE_URL || !API_KEY || !MODEL) {
    throw new Error("Missing Base URL, API Key, or model name");
  }

  const response = await fetch(`${BASE_URL}/v1/chat/completions`, {
    method: "POST",
    headers: {
      "content-type": "application/json",
      authorization: `Bearer ${API_KEY}`,
    },
    body: JSON.stringify({
      model: MODEL,
      messages: [
        { role: "system", content: "Return a short health response." },
        { role: "user", content: "ping" },
      ],
    }),
  });

  const body = await response.json().catch(() => ({}));

  console.log({
    status: response.status,
    model: MODEL,
    errorCode: body?.error?.code,
    errorMessage: body?.error?.message,
    responseId: body?.id,
  });

  if (body?.error?.code === "model_not_found") {
    process.exitCode = 2;
  }
}

replay().catch((error) => {
  console.error(error.message);
  process.exitCode = 1;
});
Enter fullscreen mode Exit fullscreen mode

用同一组 provider 参数运行:

VECTOR_ENGINE_BASE_URL="your-openai-compatible-base-url" \
VECTOR_ENGINE_API_KEY="your-tool-key" \
VECTOR_ENGINE_MODEL="your-model-name" \
node replay-vector-engine.js
Enter fullscreen mode Exit fullscreen mode

步骤 3:对比工具表现

当 Dify、Cursor 和 Node.js 的结果不一致时,可以用一张表把问题收敛。

现象 优先检查位置 实际动作
Node.js 成功,Dify 失败 Dify provider 设置 对比 Base URL、model name,以及 workflow 是否用了其他 provider 节点
Node.js 成功,Cursor 失败 Cursor provider 设置 确认 OpenAI-compatible API gateway 条目和模型路由
所有工具都返回 model_not_found 向量引擎路由或 model name 检查配置的路由名是否存在,以及账号是否有访问权限
只有一个工具返回 401 API Key 范围 替换该工具密钥,不影响其他工具
所有工具都返回 404 Base URL 路径 确认 /v1/chat/completions 只被拼接了一次

这种方式能把 provider 讨论变成具体证据。与其争论 Dify、Cursor 还是向量引擎负责,不如对比三个事实:Base URL、API Key 范围和 model name。

步骤 4:把回放脚本留在仓库里

这个脚本足够小,可以放在 Node.js 服务旁边。模型路由变更后、新工具接入前、某个工具单独出现 model_not_found 时,都可以运行它。长期看,它会成为向量引擎中转站支持流程里的实用证据。

注册地址:https://api.vectorengine.cn/register?aff=Igym

Top comments (0)