↓
Rivya AI 文档

Rivya TypeScript SDK

使用测试版 Rivya TypeScript SDK 调用 Public API v1,覆盖模型、生成、文件、积分、Webhook,以及支持 SSE 流式响应的 Chat。

最近审阅于 2026年8月29日

Rivya 提供 TypeScript SDK beta,用于服务端 Public API 集成。

SDK 是 Rivya Public API v1 的薄客户端。底层合同仍以 OpenAPI 与 Schema 合同 为准,SDK 方法必须和 schema 保持一致。

本文介绍的是已经实现的 Public API v1 合同。实际运行仍取决于部署是否启用 Public API、账号是否有有效 API key,以及所选模型是否在实时模型列表中显示为 API 可用;文档存在不代表所有环境都能调用。

状态

当前 package 只作为仓库内 private beta 维护。只有在包名、metadata、changelog 和发布流程被明确批准后,才允许发布到 npm。

SDK 支持:

  • 查询模型列表

  • 创建和查询异步生成任务

  • Files API 上传和查询

  • 查询积分余额

  • webhook endpoint 管理、测试投递、事件列表、投递列表和 secret 轮换

  • webhook 签名校验

  • 非 streaming 与 streaming Chat completions,以及 API 创建的 chat sessions

Chat streaming 已在当前 private beta 中通过服务端 SSE parser 开放。secret API key 仍然只能放在服务端。

在当前仓库中使用

SDK 处于 beta 时,先使用本地 package source:

pnpm --dir packages/rivya-sdk typecheck

业务代码应把 secret API key 保存在服务端:

import { RivyaClient } from "@rivya/sdk";

const rivya = new RivyaClient({
  apiKey: process.env.RIVYA_API_KEY
});

不要把 secret API key 放进浏览器 bundle、localStorage、分析事件、截图或共享工单。

查询模型

models.list 是公开只读接口,不需要 API key:

const models = await rivya.models.list();

for (const model of models.data) {
  console.log(model.id, model.api_status, model.supported_api_inputs);
}

创建生成任务

使用 generations.create 创建异步图片、视频或音频生成任务:

const generation = await rivya.generations.create(
  {
    model: "z-image",
    prompt: "A clean editorial product image on a soft studio background",
    client_request_id: "order-123-preview"
  },
  {
    idempotencyKey: "order-123-preview"
  }
);

console.log(generation.id, generation.status);

再用 generations.retrieve 轮询:

const current = await rivya.generations.retrieve(generation.id);
console.log(current.status, current.result?.primary_url);

生产写请求建议使用 Idempotency-Key。SDK 中对应参数是 idempotencyKey。

上传文件

使用 files.upload 上传参考图片、视频或音频:

import { readFile } from "node:fs/promises";

const file = new Blob([await readFile("./reference.png")], {
  type: "image/png"
});

const uploaded = await rivya.files.upload({
  file,
  filename: "reference.png",
  kind: "image",
  model: "nano-banana-2-lite",
  client_request_id: "asset-123"
});

console.log(uploaded.id, uploaded.url);

使用 files.retrieve 重新读取已上传文件的元数据:

const sameFile = await rivya.files.retrieve(uploaded.id);
console.log(sameFile.mime_type, sameFile.duration_token);

在生成任务中使用文件时,把返回的公开字段放进 params.referenceMediaItems:

await rivya.generations.create({
  model: "nano-banana-2-lite",
  prompt: "Restyle this product photo for a clean editorial catalog page",
  params: {
    referenceMediaItems: [
      {
        url: uploaded.url,
        kind: uploaded.kind,
        name: uploaded.file_name,
        mimeType: uploaded.mime_type,
        durationSeconds: uploaded.duration_seconds ?? undefined,
        durationToken: uploaded.duration_token ?? undefined,
        width: uploaded.video_width ?? uploaded.width ?? undefined,
        height: uploaded.video_height ?? uploaded.height ?? undefined,
        sizeBytes: uploaded.video_file_size_bytes ?? uploaded.size_bytes,
        imageDimensionsToken: uploaded.image_dimensions_token ?? undefined,
        framesPerSecond: uploaded.frames_per_second ?? undefined,
        videoBitrateMbps: uploaded.video_bitrate_mbps ?? undefined,
        videoMetadataToken: uploaded.video_metadata_token ?? undefined
      }
    ]
  }
});

每张 Image5 或 Grok Imagine Image 2.0 参考图都必须携带原始模型绑定上传响应中的 width、height、size_bytes 和 image_dimensions_token。后续 files.retrieve 可能返回 null token;此时应重新上传源图片,不能猜测 MIME、宽高或字节数。图层拆分还会执行恰一张图片和几何边界校验;Grok Image 2 的标准图片编辑接受 1–5 张已签名 JPEG、PNG 或 WebP 参考图。

Video8 参考视频需要使用原始模型绑定上传响应中的 video_width、video_height、frames_per_second、video_bitrate_mbps、video_file_size_bytes 和 video_metadata_token,并分别传为 width、height、framesPerSecond、videoBitrateMbps、sizeBytes 和 videoMetadataToken。durationSeconds 与 durationToken 是独立的时长签名证明。后续 files.retrieve 缺少任一 token 时,请重新上传源视频。

Wan 3.0 的 text、frames 和 reference 三个互斥场景都使用相同的 SDK 字段映射。每个参考素材都必须使用 model: "wan-3-0-video" 上传;图片需要已签名图片字段,视频同时需要已签名时长和视频元数据,音频需要原始的 mime_type、size_bytes、duration_seconds 和 duration_token。在 params 中设置 seedance_scene、variant、resolution、aspect_ratio、duration、audio 和可选 seed。智能时长为 -1,按 30 秒预留,且不能与参考视频同时使用;文件转视频和链接转视频快捷模式仍不可用。

查询积分

const credits = await rivya.credits.retrieve();
console.log(credits.current_credits);

管理 Webhooks

当部署与账号已经开放 webhook 权限时,创建 webhook endpoint:

const endpoint = await rivya.webhooks.create({
  name: "Production webhook",
  url: "https://example.com/rivya/webhook",
  event_types: ["generation.succeeded", "generation.failed"]
});

console.log(endpoint.id, endpoint.signing_secret);

signing_secret 只会在创建或轮换时返回一次。请把它保存在服务端。

其他 webhook helper:

await rivya.webhooks.list();
await rivya.webhooks.retrieve(endpoint.id);
await rivya.webhooks.update(endpoint.id, { status: "disabled" });
await rivya.webhooks.test(endpoint.id);
await rivya.webhooks.rotateSecret(endpoint.id);
await rivya.webhooks.deliveries.list(endpoint.id, { limit: 20 });
await rivya.webhookEvents.list({ limit: 20 });

信任 webhook payload 前,先校验签名:

import { verifyRivyaWebhookSignature } from "@rivya/sdk";

const ok = await verifyRivyaWebhookSignature({
  rawBody,
  timestamp: request.headers.get("rivya-webhook-timestamp") || "",
  signatureHeader: request.headers.get("rivya-webhook-signature") || "",
  signingSecret: process.env.RIVYA_WEBHOOK_SIGNING_SECRET || ""
});

if (!ok) {
  throw new Error("Invalid Rivya webhook signature");
}

这个 SDK helper 使用的就是 API Webhooks 中记录的 HMAC-SHA256 合同。

Chat

使用 chat.completions.create 发送一轮非 streaming Chat API 请求:

const completion = await rivya.chat.completions.create(
  {
    model: "claude-sonnet-5-chat",
    message: "Write a concise launch plan for a new product image campaign",
    client_request_id: "chat-001"
  },
  {
    idempotencyKey: "chat-001"
  }
);

console.log(completion.session_id, completion.message.content);

用返回的 session_id 继续对话:

await rivya.chat.completions.create({
  model: "claude-sonnet-5-chat",
  session_id: completion.session_id,
  message: "Now turn that into a 5-step execution checklist."
});

读取 API 创建的 sessions:

await rivya.chat.sessions.list({ limit: 20 });
await rivya.chat.sessions.retrieve(completion.session_id);

使用 chat.completions.stream 以 async iterator 读取 Server-Sent Events:

const stream = await rivya.chat.completions.stream(
  {
    model: "claude-sonnet-5-chat",
    message: "Write a concise launch plan for a new product image campaign",
    client_request_id: "chat-stream-001"
  },
  {
    idempotencyKey: "chat-stream-001"
  }
);

for await (const event of stream) {
  if (event.event === "message.delta") {
    process.stdout.write(event.data.delta);
  }

  if (event.event === "message.completed") {
    console.log(event.data.message.id);
  }
}

message.delta 只适合用于展示增量。最终提交结果以 message.completed 为准,之后也可以用 chat.sessions.retrieve 读取。

错误处理

Public API 返回非 2xx 时,SDK 会抛出 RivyaAPIError:

import { RivyaAPIError } from "@rivya/sdk";

try {
  await rivya.generations.retrieve("task_missing");
} catch (error) {
  if (error instanceof RivyaAPIError) {
    console.log(error.status, error.code, error.requestId);
  }
}

RivyaAPIError 包含 HTTP status、公共错误码、message、可用时的 request id,以及安全的响应 header 子集。

验证

把 SDK 变更视为完成前,先运行:

pnpm sdk:check
pnpm --dir packages/rivya-sdk typecheck
pnpm content:api-docs

pnpm sdk:check 包含静态合同检查,也包含无网络 runtime 检查,覆盖错误解析、安全错误 header、幂等 header、Bearer 鉴权、公开模型列表、Chat streaming SSE parsing、Chat streaming error event 和 webhook 签名校验。

相关页面