@clavata/sdk

中文文档
0.5.0发布于 2026/06/03ISCTypeScriptESM + CJS近 30 天下载 1.2万

This directory contains the JS version of our SDK.

原始使用文档
文档目录6 节
  1. Getting started
  2. Configuration
  3. RPC Methods
  4. Refusals
  5. Monorepo development
  6. Contributing

Clavata JavaScript SDK

This directory contains the Clavata JavaScript SDK with type definitions.

Getting started

Email [email protected] if you do not already have an API key/token.

Initialize the SDK to get started making requests to the Clavata API.

import Clavata from "@clavata/sdk";

// API key can be provided directly or via environment variable
const client = new Clavata({ apiKey: "<YOUR_CLAVATA_API_KEY>" } as Options);

Configuration

The client constructor accepts the following options:

interface Options {
  // Your API key. If not provided you _must_ then set CLAVATA_API_KEY as an environment variable
  apiKey?: string;
  // Optional
  server?: string; // Server endpoint (default: "gateway.app.clavata.ai:443")
  insecure?: boolean; // Use insecure connection. (default: false)
  keepalive?: {
    // Connection keepalive settings
    timeout: number; // How long to wait for a response to a keepalive ping before considering the connection dead (in ms). (default: 10000)
    permitWithoutCalls: boolean; // Allows keepalive pings to maintain idle connections. (default: true)
    time: number; // How frequently to send keepalive pings to check if the connection is alive (in ms). (default: 10000)
  };
  maxMessageLength?: number; // Max message size (default: 100MB)
  retryConfig:
    | {
        // Configuration for automatic retries. Will retry by default. Set to `false` to disable this. See https://grpc.io/docs/guides/retry for more info.
        maxAttempts?: number; // Maximum number of retry attempts (default: 5)
        initialBackoff?: string; // Initial backoff time in milliseconds (default: "1s")
        maxBackoff?: string; // Maximum backoff time (default: "30s")
        backoffMultiplier?: number; // Multiplier for backoff time after each retry (default: 2.0)
        jitter?: number; // Jitter factor between 0 and 1 (default: 0.2, 0 = no jitter, 1 = full jitter)
      }
    | false;
}

If neither an API key is provided to the constructor nor is a process.env.CLAVATA_API_KEY environment variable set then the constructor will throw an error.

RPC Methods

getJob(jobId: string): Promise<Job | undefined>

  • Retrieves a job by its UUID.

listJobs(request: ListJobsRequest): Promise<ListJobsResponse>

  • Lists jobs with filtering parameters.

createJob(request: CreateJobRequest): Promise<CreateJobResponse[]>

  • Creates a new job with the provided content data and returns the id and status of the job that can be requested at a later point in time. If you need to await the result use evaluate instead.

evaluate(request: EvaluateRequest): Promise<AsyncIterable<EvaluateMessage | StreamError>>

  • Evaluates each input and returns a stream of responses or errors. Order is not guaranteed, so using metadata or a contentHash is advised when sending multiple pieces to evaluate in a single call.
  • Example:
const stream = client.evaluate({
  contentData: [
    {
      metadata: { id: "1" },
      content: { value: "Hello, world!", $case: "text" },
      contentType: "text",
    },
    {
      metadata: { id: "2" },
      content: { value: Buffer.from("<BASE64_DATA>", "base64"), $case: "image" },
      contentType: "image/png",
    },
    {
      metadata: { id: "3" },
      content: { value: "<IMAGE_URL>", $case: "imageUrl" },
      contentType: "image/jpeg",
    },
  ],
  policyId: "00000000-0000-0000-0000-000000000000",
});

for await (const item of stream) {
  if (item instanceof StreamError) throw item;

  const { metadata, report } = item;
  console.log({ id: metadata?.id, matches: report?.matches });
}

beta.evaluateLabels(request: EvaluateLabelsRequest): Promise<EvaluateLabelsResponse>

  • Labels v2 evaluation is currently beta and exposed through client.beta.evaluateLabels.
  • Evaluates one content item against 1-10 explicit Labels v2 label version IDs.
  • Requires Labels v2 to be enabled for your customer account.
  • Results are returned in requested label version ID order.
  • The standard response includes contentHash and, for each result, labelId, labelVersionId, jobUuid, either evaluation (outcome, score, threshold) or error, and no nested report. This is typically sufficient for most SDK uses.
  • Per-label failures are returned in the response as result errors; transport, authentication, and platform errors still reject the call.
  • Set includeEvaluationReport: true only when you need optional nested report data on successful per-label evaluations, such as report.matches.
  • Example:
const response = await client.beta.evaluateLabels({
  content: {
    metadata: { id: "1" },
    content: { value: "Hello, world!", $case: "text" },
    contentType: "text",
  },
  labelVersionIds: ["00000000-0000-0000-0000-000000000000", "11111111-1111-1111-1111-111111111111"],
  threshold: 0.5,
});

for (const result of response.results) {
  if (result.error) {
    console.log({
      labelId: result.labelId,
      labelVersionId: result.labelVersionId,
      jobUuid: result.jobUuid,
      error: result.error.message,
    });
    continue;
  }

  console.log({
    labelId: result.labelId,
    labelVersionId: result.labelVersionId,
    jobUuid: result.jobUuid,
    outcome: result.evaluation?.outcome,
    score: result.evaluation?.score,
    threshold: result.evaluation?.threshold,
  });
}

When includeEvaluationReport: true is set and the backend returns report data, result.evaluation?.report has the same shape as policy evaluation reports, including matches.

Generated LabelsService CRUD, version, draft, tag, batch, and dataset APIs are private and are not part of the public SDK surface.

Refusals

Under certain circumstances, the Clavata API will refuse to evaluate content as requested. There are only a few possible reasons for this:

  1. The content (image) matches a known hash in our CSAM database. This can be either an exact match or a perceptual hash match.
  2. The content (image) is in an unsupported format. Currently, Clavata supports webp, png and jpg images.
  3. The content was corrupt. Usually because the content was incomplete or the encoding (for images) was incorrect.

When a refusal occurs, a StreamError will be returned (for evaluate) or thrown (for createJob). You can check whether the error was caused by a refusal using the getRefusalReason() method on the StreamError type. If the error was not caused by a refusal, this method will return undefined. If the error is due to a refusal, a RefusalReason will be returned.

The RefusalReason type is a enum with strings matching one of:

  • "CSAM"
  • "UNSUPPORTED_IMAGE_FORMAT"
  • "INVALID_IMAGE"

There is also an "UNKNOWN" option, but this case indicates something went wrong decoding the "reason" information in the response.


import { RefusalReason } from "@clavata/sdk";

const stream = client.evaluate(...)

for await (const item of stream) {
  if (item instanceof StreamError) {
    const reason = item.getRefusalReason();
    if (!reason) {
      // Not a refusal, you can check the other possible identification methods like
      if (item.isTransient()) {
        // Transient error so we can retry
      }
    }

    // It was a refusal, so we can use a switch statement to figure out why
    switch (reason) {
      case RefusalReason.CSAM:
        // Handle CSAM appropriately
        break;
      case RefusalReason.UNSUPPORTED_IMAGE_FORMAT:
        // Convert image and try again
        break;
      case RefusalReason.INVALID_IMAGE:
        // data corruption, maybe try to re-download from CDN and try again?
        break;
      default:
        // unknown reason for refusal
    }
  }
}

Getting the Refusal Error

If you prefer, you can convert a StreamError into a RefusalError with the toRefusalError() method. Once again, if the error was not caused by a refusal, this method will return undefined. If, however, a refusal did occur the RefusalError type that is returned has the following interface that you can use to understand why:

interface RefusalError {
  isCSAM(): boolean;
  isUnsupportedImageFormat(): boolean;
  isInvalidImage(): boolean;
  isUnknown(): boolean;
  getReason(): RefusalReason;
}

// So you can do this:
if (item instanceof StreamError) {
  const refusalErr = item.toRefusalError();
  if (refusalErr.isCSAM()) {
    // Take action based on the content having been CSAM
  }
}

Which interface you use to determine the reason is up to you, they are functionally equivalent.

Refusals and createJob

When calling createJob, a promise is returned. If an error occurs, that error is automatically converted to a StreamError by the SDK and re-thrown. You can then catch the StreamError and check for refusals the same way.

Monorepo development

When working in the Olympus monorepo, see SDK workflow for unit tests, live smoke (examples/sdk), and publishing (below).

Contributing

Update the version with npm version <new_version> to the next SEMVER then run npm publish.

版本与发布记录

@clavata/sdk 共发布 15 个版本,首次发布于 2025/03/20;过去 12 个月发布了 1 个版本。

版本发布日期距今
0.5.0latest2026/06/035 个月前
0.4.12025/10/251 年前
0.4.02025/08/071.3 年前
0.3.02025/06/271.4 年前
0.2.32025/06/101.4 年前
0.2.22025/05/281.5 年前

关于 @clavata/sdk 的常见问题

@clavata/sdk 是什么?

This directory contains the JS version of our SDK.

如何安装 @clavata/sdk?

在项目目录运行 npm install @clavata/sdk,或使用 pnpm add / yarn add / bun add。

@clavata/sdk 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@clavata/sdk 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@clavata/sdk 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js 22.13.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@clavata/sdk 可以商用吗?

@clavata/sdk 使用 ISC 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@clavata/sdk 的下载量有多少?

根据 npm 官方下载统计,@clavata/sdk 在 2026/10/10 – 2026/11/08 这 30 天内被下载 11,818 次,日均约 394 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@clavata/sdk 还在维护吗?

最新版本 0.5.0 发布于 2026/06/03(5 个月前);至今共发布 15 个版本,其中过去 12 个月发布了 1 个;首次发布于 2025/03/20。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。