> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ariacompute.cn/llms.txt
> Use this file to discover all available pages before exploring further.

# 咏唱引擎 API 的 Node.js 客户端

> 一个基于 fetch 的咏唱引擎 Node.js 客户端：用 API 密钥认证、列出并下载模型，并查询钱包与计费接口。

咏唱引擎没有官方的 Node.js 包。在 Node 18+ 中使用内置的 `fetch` API 配合下面的极简封装即可。

## 客户端

```ts aria-compute.ts icon="node-js" lines theme={null}
import { createWriteStream } from "node:fs";
import { Readable } from "node:stream";
import { pipeline } from "node:stream/promises";

export interface AriaComputeOptions {
  apiKey: string;
  baseUrl?: string;
}

export class AriaCompute {
  private baseUrl: string;
  private headers: Record<string, string>;

  constructor(opts: AriaComputeOptions) {
    this.baseUrl = (opts.baseUrl ?? "https://ariacompute.cn/api").replace(/\/$/, "");
    this.headers = {
      Authorization: `Bearer ${opts.apiKey}`,
      Accept: "application/json",
    };
  }

  private async request<T>(path: string, init: RequestInit = {}): Promise<T> {
    const res = await fetch(`${this.baseUrl}${path}`, {
      ...init,
      headers: { ...this.headers, ...(init.headers ?? {}) },
    });
    if (!res.ok) throw new Error(`${res.status} ${res.statusText}: ${await res.text()}`);
    return res.json() as Promise<T>;
  }

  listModels() {
    return this.request<{ models: unknown[] }>("/models");
  }

  wallet() {
    return this.request<{ balance: number; currency: string }>("/billing/wallet");
  }

  createPayment(provider: "stripe" | "wechat" | "alipay", amount: number, currency: string) {
    return this.request("/billing/payments", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ provider, amount, currency }),
    });
  }

  async downloadModel(slug: string, quant: string, sdk: string, dest: string) {
    const url = `${this.baseUrl}/models/${slug}/download?quant=${quant}&sdk=${sdk}`;
    const res = await fetch(url, { headers: this.headers, redirect: "follow" });
    if (!res.ok || !res.body) throw new Error(`Download failed: ${res.status}`);
    await pipeline(Readable.fromWeb(res.body as any), createWriteStream(dest));
  }
}
```

## 用法

```ts theme={null}
import { AriaCompute } from "./aria-compute";

const client = new AriaCompute({ apiKey: process.env.ARIA_API_KEY! });

const { models } = await client.listModels();
console.log(models);

await client.downloadModel("gemma-4-e2b-it", "int4", "v1.0", "./gemma-4-e2b-it_q4.zip");

console.log(await client.wallet());
```

<Note>
  若使用国际站，请传入 `baseUrl: "https://ariacompute.com/api"`。账户、钱包与 API 密钥均按区域隔离。
</Note>

## 处理重定向

`GET /api/models/{slug}/download` 的响应要么是一个指向短时效 S3 预签名 URL 的 `302`，要么是一个流式 ZIP。`fetch` 配合 `redirect: "follow"` 可同时处理两者。若想要 JSON 信封（`{ mode, url, filename }`），请在请求上设置 `Accept: application/json`。
