@alia.onl/server

中文文档
1.3.1发布于 2026/10/26Apache-2.0TypeScriptESM + CJS零依赖构建来源已验证近 30 天下载 3138

Alia's server-side streaming client — one typed event stream for a backend that calls Alia's product API

原始使用文档
文档目录10 节
  1. Why it exists
  2. Install
  3. Use
  4. What it owns
  5. Errors
  6. Bring your own request
  7. Which credential
  8. Tests
  9. Licence
  10. Explicit Stop (1.3)

@alia.onl/server

Alia's client for the backend that calls Alia on a person's behalf.

@alia.onl/sdk is the client SDK: React and React Native components, hooks, a browser-side stream reader. This package is the other half — no React, no DOM beyond fetch and ReadableStream, no dependencies, Node 22+. It POSTs one turn to /v1/chat/completions and gives you a typed async iterable of what Alia wrote.

Why it exists

Alia can write these things on that stream:

On the wireWhat it is
data: {…choices[0].delta.content}an assistant text delta
data: {…choices[0].delta.reasoning}a reasoning delta
event: alia.tool_result + data: {…}a named product event
data: {…, "alia_meta": {"synthetic": true}}a stand-in message an older server wrote after a provider died; current servers end a failed turn with the error payload below
data: {"error":{"code":"agent_unavailable"}}Alia refusing, mid-stream
data: [DONE]the terminator

Every consumer that called Alia from a server wrote its own reader for that, and each got a different subset right. The expensive one is the error payload: a reader with no branch for it either throws a bare 502 that names nothing, or — worse — skips the frame it does not recognise and reports an empty answer. Both happened in production. This package makes that shape a typed error event carrying the server's own code, so a consumer cannot fail to see it.

Install

bun add @alia.onl/server   # or npm / pnpm / yarn

Use

import { AliaServerClient } from '@alia.onl/server';

const alia = new AliaServerClient({
  baseUrl: 'https://api.alia.onl',
  // Your product's Oxy service token — the bearer Oxy bills (ADR 0007).
  token: () => getMyServiceToken(),
});

const stream = await alia.stream(
  { agentId: MY_AGENT_ID, messages: [{ role: 'user', content: 'Hola' }] },
  { signal: request.signal },
);

for await (const event of stream) {
  switch (event.type) {
    case 'text':      process.stdout.write(event.text); break;
    case 'reasoning': break;
    case 'event':     onProductEvent(event.event, event.data); break;
    case 'finish':    break;
    case 'error':     throw new MyChatError(event.code);   // the SERVER's code
    case 'done':      break;
  }
}

The switch above is exhaustive: AliaStreamEvent is a closed union, so a default: never branch makes a new event kind a compile error rather than a silently dropped frame.

What it owns

  • Content-type checking. A 200 that is not text/event-stream is an AliaStreamError('not_event_stream'), never a buffered fallback parse.
  • SSE framing. Multi-line data:, comment frames, CRLF, event: message as SSE's default name, and byte boundaries falling anywhere — including mid-UTF-8. Text deltas are yielded verbatim and never merged, because a consumer reassembling markers across chunks depends on the exact bytes.
  • [DONE]. Iteration ends on it. A body that ends without it is an AliaStreamError('truncated') — a truncated turn must not read as a short one.
  • Error chunks, as error events carrying code, message, type, param.
  • Abort. Pass an AbortSignal; the request and the body read both stop, and leaving the for await early cancels the body.
  • Non-2xx, as AliaRequestError with status and, when the body carried one, code. The body's prose is deliberately not retained.

Errors

import { AliaRequestError, AliaStreamError } from '@alia.onl/server';

AliaStreamError carries failure (one of not_event_stream, no_body, malformed_json, unexpected_chunk, choice_without_delta, content_not_string, truncated, oversized) and shape — the offending chunk's keys, its choices length or type, and any error.code. shape holds no content: not the assistant's text, not the person's prompt. Log it whole.

AliaRequestError carries status and code.

An abort throws an Error whose name is AbortError, as fetch's does.

Bring your own request

import { readAliaEventStream } from '@alia.onl/server';

for await (const event of readAliaEventStream(response.body!, { signal })) { … }

Which credential

Alia receives the calling product's Oxy service token as the bearer. A person's own bearer is never forwarded. A turn for a signed-in person does not go through a product backend at all: the person opens the agent with their own Oxy session through @alia.onl/sdk (Alia ADR 0020). headers accepts a function for a header whose value changes on every request.

Tests

The test fixtures are not hand-written chunks. They are produced by the API's own SSE writers — packages/api/src/lib/streaming-helpers.ts, .../chat/sse-writer.ts, .../sse-emitter.ts — imported directly, so a change to what Alia puts on the wire fails this package's tests in the same commit.

bun run typecheck
bun run test
bun run build

Licence

Apache-2.0. See LICENSE and NOTICE.

Explicit Stop (1.3)

For a verified human session or exact app-only credential, choose a UUID v4 before stream() and supply turnId. cancelTurn({ turnId, conversationId }) uses the same authentication and surface headers; conversationId must be the value known at admission, including absence for a new conversation. Its signal is independent of the stream's AbortSignal. Aborting the latter only detaches the reader and allows background completion.

createAliaTurnControl(client, { controller, lifetimeSignal, conversationId }) creates the UUID before any asynchronous preparation. Send its id as the request's turnId; call stop() only for deliberate Stop. It deduplicates concurrent Stop calls, waits up to ten seconds for acknowledgement, and only then aborts the controller. A refused Stop rejects and remains retryable. Abort the stream controller directly for view teardown. The separate lifetimeSignal fences account changes or disposal of its authenticated owner; it must not be the stream signal, because a cancellation SSE frame can close the stream before the control request is acknowledged. The helper never refreshes or chooses an account. Await finish() before disposing the caller's linked transport. Each HTTP tool continuation gets a new handle, and stopping a local tool prevents further rounds without undoing work that already ran.

Deploy the API receiver before adopting this producer. Delegated service/channel callers without a verifiable original actor must omit turnId; their existing chat remains supported, but they cannot use this cancellation lane. Details and settlement/retry limits: explicit Stop.

版本与发布记录

@alia.onl/server 共发布 7 个版本,首次发布于 2026/09/18;过去 12 个月发布了 7 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
1.3.1latest2026/10/2612 天前
1.3.02026/10/2612 天前
1.2.02026/10/2513 天前
1.1.12026/10/1721 天前
1.1.02026/10/011 个月前
1.0.12026/09/181 个月前

关于 @alia.onl/server 的常见问题

@alia.onl/server 是什么?

Alia's server-side streaming client — one typed event stream for a backend that calls Alia's product API

如何安装 @alia.onl/server?

在项目目录运行 npm install @alia.onl/server,或使用 pnpm add / yarn add / bun add。

@alia.onl/server 支持 TypeScript 吗?

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

@alia.onl/server 支持 ESM 还是 CommonJS?

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

@alia.onl/server 需要什么版本的 Node.js?

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

@alia.onl/server 可以商用吗?

@alia.onl/server 使用 Apache-2.0 许可。宽松许可:允许商业使用、修改和再分发,并附带明确的专利授权;分发时需保留许可与 NOTICE 文件,修改过的文件要注明改动。以上为概括,不构成法律意见,请以许可原文为准。

@alia.onl/server 的下载量有多少?

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

@alia.onl/server 还在维护吗?

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