DEV Community

Jia
Jia

Posted on

Check Usage Accounting After Vector Engine Calls from Dify, Cursor, and Node.js

Many Vector Engine rollouts focus on whether a request succeeds. That is only the first part of the provider contract. Once Dify, Cursor, and a Node.js service share an OpenAI-compatible API gateway, the team also needs to know whether usage accounting is visible enough to debug cost spikes, route mistakes, and unexpected model changes.

This tutorial builds a small Node.js check that records the Base URL, API Key owner, model name, HTTP status, response id, and token usage fields returned through the LLM API provider layer. The check does not expose secrets, and it does not require a production prompt. It gives engineers one repeatable record they can compare against Dify and Cursor behavior when something looks wrong.

Use a dedicated test key or a low-risk service key:

VECTOR_ENGINE_BASE_URL=https://api.vectorengine.cn/v1
VECTOR_ENGINE_API_KEY=replace_with_your_key
VECTOR_ENGINE_MODEL=gpt-4o-mini
VECTOR_ENGINE_KEY_OWNER=nodejs-sandbox
Enter fullscreen mode Exit fullscreen mode

The key owner value is local metadata. It helps the log say which API Key was intended without printing the key. Keep the same route and model name visible in Dify and Cursor so a model_not_found error can be tied to a real route table instead of a guess.

Create usage-check.js:

const config = {
  baseUrl: process.env.VECTOR_ENGINE_BASE_URL,
  apiKey: process.env.VECTOR_ENGINE_API_KEY,
  model: process.env.VECTOR_ENGINE_MODEL,
  keyOwner: process.env.VECTOR_ENGINE_KEY_OWNER || "unknown"
};

function required(name, value) {
  if (!value) throw new Error(`Missing ${name}`);
  return value;
}

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

async function runUsageCheck() {
  const startedAt = new Date().toISOString();
  const response = await fetch(`${required("VECTOR_ENGINE_BASE_URL", config.baseUrl)}/chat/completions`, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${required("VECTOR_ENGINE_API_KEY", config.apiKey)}`,
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      model: required("VECTOR_ENGINE_MODEL", config.model),
      messages: [
        { role: "system", content: "Answer with one short sentence." },
        { role: "user", content: "Return a simple provider accounting check." }
      ]
    })
  });

  const raw = await response.text();
  let body;
  try {
    body = JSON.parse(raw);
  } catch {
    body = { parse_error: raw.slice(0, 300) };
  }

  return {
    startedAt,
    baseUrl: config.baseUrl,
    keyOwner: config.keyOwner,
    keyFingerprint: mask(config.apiKey),
    requestedModel: config.model,
    status: response.status,
    responseId: body.id || null,
    returnedModel: body.model || null,
    usage: body.usage || null,
    errorType: body.error?.type || null,
    errorCode: body.error?.code || null,
    errorMessage: body.error?.message || null
  };
}

runUsageCheck()
  .then(record => {
    console.log(JSON.stringify(record, null, 2));
    if (record.status >= 400) process.exitCode = 1;
  })
  .catch(error => {
    console.error(JSON.stringify({ fatal: error.message }, null, 2));
    process.exitCode = 1;
  });
Enter fullscreen mode Exit fullscreen mode

The output should be saved as operational evidence, not as customer data. A normal record includes a response id, a returned model, and a usage object. If the usage object is missing, the team should decide whether that route is acceptable for production. Some workflows can operate without token accounting; cost review workflows cannot.

Use this checklist before widening access:

  1. Confirm the Base URL is the same in Node.js, Dify, and Cursor.
  2. Confirm the model name exists in the Vector Engine route list used by the team.
  3. Confirm the API Key belongs to the expected environment and owner.
  4. Confirm the response includes enough usage fields for your cost review process.
  5. Confirm a model_not_found case is logged differently from auth, Base URL, and rate-limit failures.

For Dify, attach the workflow name and provider screen values to the same evidence record. For Cursor, record the workspace or user group, the selected model name, and the task type. For Node.js, record the service name and route label. The shared shape matters more than the exact logging system.

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

Vector Engine is useful as an OpenAI-compatible API gateway when it makes provider access more consistent. A usage accounting check extends that consistency into operations: the team can see which route was called, which key owner was expected, which model responded, and whether the provider layer returned enough data to support cost and failure review.


检查 Dify、Cursor 和 Node.js 调用向量引擎后的用量核算

很多向量引擎迁移只关注请求是否成功。这只是供应商契约的初始部分。 当 Dify、Cursor 和 Node.js 服务共用同一个 OpenAI 兼容 API 网关后,团队还需要知道用量核算是否足够清晰,能不能排查成本异常、路由错误和意外的模型变化。

这篇教程构建一个小型 Node.js 检查,记录通过 LLM API provider layer 返回的 Base URL、API Key 归属、模型名、HTTP 状态、响应 id 和 token usage 字段。它不会暴露密钥,也不需要生产提示词。它给工程师一个可重复的证据记录,用于和 Dify、Cursor 的行为做对比。

使用专用测试密钥或低风险服务密钥:

VECTOR_ENGINE_BASE_URL=https://api.vectorengine.cn/v1
VECTOR_ENGINE_API_KEY=replace_with_your_key
VECTOR_ENGINE_MODEL=gpt-4o-mini
VECTOR_ENGINE_KEY_OWNER=nodejs-sandbox
Enter fullscreen mode Exit fullscreen mode

key owner 是本地元数据。它帮助日志说明这个 API Key 的预期归属,但不会打印密钥本身。Dify 和 Cursor 中也要保持同一个路由和模型名可见,这样 model_not_found 才能对应到真实路由表,而不是靠猜。

创建 usage-check.js

const config = {
  baseUrl: process.env.VECTOR_ENGINE_BASE_URL,
  apiKey: process.env.VECTOR_ENGINE_API_KEY,
  model: process.env.VECTOR_ENGINE_MODEL,
  keyOwner: process.env.VECTOR_ENGINE_KEY_OWNER || "unknown"
};

function required(name, value) {
  if (!value) throw new Error(`Missing ${name}`);
  return value;
}

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

async function runUsageCheck() {
  const startedAt = new Date().toISOString();
  const response = await fetch(`${required("VECTOR_ENGINE_BASE_URL", config.baseUrl)}/chat/completions`, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${required("VECTOR_ENGINE_API_KEY", config.apiKey)}`,
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      model: required("VECTOR_ENGINE_MODEL", config.model),
      messages: [
        { role: "system", content: "Answer with one short sentence." },
        { role: "user", content: "Return a simple provider accounting check." }
      ]
    })
  });

  const raw = await response.text();
  let body;
  try {
    body = JSON.parse(raw);
  } catch {
    body = { parse_error: raw.slice(0, 300) };
  }

  return {
    startedAt,
    baseUrl: config.baseUrl,
    keyOwner: config.keyOwner,
    keyFingerprint: mask(config.apiKey),
    requestedModel: config.model,
    status: response.status,
    responseId: body.id || null,
    returnedModel: body.model || null,
    usage: body.usage || null,
    errorType: body.error?.type || null,
    errorCode: body.error?.code || null,
    errorMessage: body.error?.message || null
  };
}

runUsageCheck()
  .then(record => {
    console.log(JSON.stringify(record, null, 2));
    if (record.status >= 400) process.exitCode = 1;
  })
  .catch(error => {
    console.error(JSON.stringify({ fatal: error.message }, null, 2));
    process.exitCode = 1;
  });
Enter fullscreen mode Exit fullscreen mode

输出应该作为运维证据保存,而不是作为客户数据保存。正常记录会包含响应 id、返回模型和 usage 对象。如果缺少 usage 对象,团队就要判断这条路由是否适合生产。有些工作流可以没有 token 核算,但成本复盘工作流不适合。

扩大接入前使用这个清单:

  1. 确认 Node.js、Dify 和 Cursor 的 Base URL 一致。
  2. 确认模型名存在于团队使用的向量引擎路由列表。
  3. 确认 API Key 属于预期环境和负责人。
  4. 确认响应包含足够支持成本复盘的 usage 字段。
  5. 确认 model_not_found 与鉴权、Base URL、限流失败被分开记录。

对 Dify,要把工作流名称和供应商配置页面的值放进同一份证据记录。对 Cursor,要记录工作区或用户组、所选模型名和任务类型。对 Node.js,要记录服务名和路由标签。共享的记录形状比具体日志系统更重要。

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

当向量引擎让供应商访问更一致时,它作为 OpenAI 兼容 API 网关的价值会更明显。用量核算检查把这种一致性扩展到运营层:团队可以看到调用了哪条路由,预期的密钥归属是谁,哪个模型返回了结果,以及供应商层是否返回了足够支持成本和故障复盘的数据。对于向量引擎API中转站、向量引擎中转站 或 API中转站 场景,这种证据也能减少跨工具沟通成本。

Top comments (0)