# @av-pi-studio/client 中文文档

规范地址：https://npmcn.com/package/%40av-pi-studio/client/

版本：0\.0\.115
npm 元数据更新时间：2026-11-04T07:06:20.637Z
中文译文更新时间：2026-11-08T03:12:01.094Z
软件包许可：未声明

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40av-pi-studio/client
原文对照：https://npmcn.com/package/%40av-pi-studio/client/?lang=original
项目主页：https://github.com/avatsaev/pi-studio#readme
源码仓库：https://github.com/avatsaev/pi-studio

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：191 kB，28 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- 运行依赖：2 个
- 首次发布：2026-07-18T12:51:11.377Z
- 最新版本发布：2026-11-04T07:06:20.160Z
- 近 30 天下载量：1922（2026-10-07 至 2026-11-05，npm 官方下载统计）
- 已发布版本数：114（近 12 个月 114 个）

## 中文简介

与 Pi-Studio 守护进程交谈的客户端侧文库:一个低级的 WebSocket 驱动程序(`DaemonClient`)外加一个高水平,打入的SDK外观 (`PiStudioClient`) (中文(简体) ). 这个包裹是什么 `@av-pi-studio/cli` 以及未来网络/移动/台式计算机 c

## 安装

```sh
npm install @av-pi-studio/client
```

也可以使用：`pnpm add @av-pi-studio/client`、`yarn add @av-pi-studio/client`、`bun add @av-pi-studio/client`

## README

# `@av-pi-studio/client`

与 Pi- Studio 守护进程交谈的客户端端库: 低级 WebSocket 驱动程序 (单位:千美元)`DaemonClient`)外加一个高水平,打入的SDK外观 (`PiStudioClient`) (中文(简体) ). 这个包裹是什么 `@av-pi-studio/cli` 以及未来任何网络/移动/桌面客户端应基于什么 我也一样.

* * *

## 安装

```bash
npm install @av-pi-studio/client
```

## 两层

1.  **`DaemonClient`** ——低级WebSocket驱动程序:运输生命周期 `hello` 握手,JSON + 二进制框架解析,RPC请求/响应关联,乒乓活性, 和一个可插件 `Transport` 抽象化,因此测试(或未来的非网络Socket传输)可以 (c) 启动它们自己的实施.
2.  **`PiStudioClient`** - 一个高层的外表结束 `DaemonClient` 使用已键入、已命名的方法 (单位:千美元)`createAgent`, (中文(简体) ), `agent(id).send(...)`, (中文(简体) ), `providers.listModels(...)`,而不是原始的 `request(type, payload)` 打电话.

还包括:a **`ReconnectionManager`** (责任后退自动连接)和a **`TerminalStreamRouter`** (demuxs 二进制终端帧按槽).

## 快开始

```ts
import { DaemonClient, PiStudioClient, createWebSocketTransport } from "@av-pi-studio/client";

const daemon = new DaemonClient({
  url: "ws://127.0.0.1:6767",
  clientId: "my-stable-client-id",
  clientType: "cli", // "mobile" | "browser" | "cli" | "mcp"
});

await daemon.connect(); // resolves once the hello → status handshake completes

const client = new PiStudioClient(daemon);

const { agentId } = await client.createAgent({
  provider: "pi",
  model: "claude-3-5-sonnet",
  cwd: "~/my-project",
});

const agent = client.agent(agentId);
agent.timeline.subscribe((event) => console.log(event.kind, event));
await agent.send("Add a health-check endpoint");
```

## `DaemonClient`

### 连接生命周期

`idle → connecting → open → closing → closed`,通过 `onStateChange(handler)`。 。 。 .

### 关键方法

| 方法 | 说明 |
| --- | --- |
| `connect()` | 打开运输工具,等待 `hello` → `status` 手握手来完成 `ServerInfoPayload` |
| `close(code?, reason?)` | 关闭运输。 没有分开的 `disconnect()`。 。 。 . |
| `request<T>(type, params?, timeoutMs?)` | 发送关联的 RPC, 解决响应或拒绝 `RpcError`编号 :`RpcTimeoutError` |
| `sendSession(message)` | 火灾和遗忘会话消息(以 `session` ——没有等待答复 |
| `sendBinary(data)` | 通过运输发送原始的二进制框架(终端/文件传输) |
| `ping(timeoutMs?)` | 发送 JSON `ping`,等待关联 `pong` (不是RFC 6455平调) |
| `hasFeature(flag)` | `true` 如果最后一个 `server_info.features.<flag>` 是事实 |
| `onSessionMessage(handler)` | 订阅每个入境者 `session` 消息; 返回未订阅的 fn |
| `onTerminalFrame(handler)` | 订阅每个已解码的二进制终端框架 |
| `onFileTransferFrame(handler)` | 订阅每个已解码的二进制文件传输框架 |
| `onStateChange(handler)` | 订阅连接状态过渡 |
| `state` 编号 : `serverId` 编号 : `features` 编号 : `serverCapabilities` | 当前连接状态和上次握手后的身份/能力 |

### 错误

| 类 | 扔的时候 |
| --- | --- |
| `RpcError` | 守护进程回复了 `rpc_error` 此项请求 |
| `RpcTimeoutError` | 未收到答复 `rpcTimeoutMs` —— 说 **仅操作级别失败**; 套接字未打开 |

### 构造选项

```ts
interface DaemonClientOptions {
  url: string;
  clientId: string;
  clientType: "mobile" | "browser" | "cli" | "mcp";
  protocolVersion?: number;              // defaults to the current protocol version
  appVersion?: string;
  capabilities?: Record<string, boolean>; // CLIENT_CAPS flags to advertise in `hello`
  transport?: Transport;                  // inject a stub for tests; defaults to native WebSocket
  rpcTimeoutMs?: number;                  // per-request timeout; never tears down the socket
  now?: () => number;                     // inject a clock for deterministic tests
}
```

## `PiStudioClient`

```ts
const client = new PiStudioClient(daemonClient);
```

| 成员 | 说明 |
| --- | --- |
| `createAgent(req)` | `create_agent_request` 难民保护委员会 |
| `agent(agentId)` | 为现有代理人采取的行动的范围`send`, (中文(简体) ), `interrupt`, (中文(简体) ), `update`, (中文(简体) ), `resume`, (中文(简体) ), `archive`, (中文(简体) ), `delete`, (中文(简体) ), `onUpdate`, (中文(简体) ), `timeline.fetch`编号 :`.subscribe`(中文(简体) ) |
| `workspace(workspaceId)` | 工作空间的范围行动 |
| `providers` | `listProviders()`, (中文(简体) ), `listModels(provider)`, (中文(简体) ), `listModes(provider)`, (中文(简体) ), `refreshSnapshot()` |
| `onAgentUpdate(handler)` 编号 : `onWorkspaceUpdate(handler)` | 订阅所有代理/工作空间的广播 |
| `connection` | 逃回深处 `DaemonClient` |
| `importAgentSession(daemon, args)` | 命名导出 - 按处理恢复提供者- 本地会话 |

## 自动重接

```ts
import { ReconnectionManager } from "@av-pi-studio/client";

const mgr = new ReconnectionManager(daemon, { initialDelayMs: 500, maxDelayMs: 30_000 });
mgr.onReconnected(({ attempt, serverId }) => console.log(`reconnected after ${attempt} tries`));
mgr.start(); // arms; automatically retries with exponential backoff on socket drop
mgr.stop();  // disarm
```

每次接通尝试电话 `daemon.connect()`,它重新发送完整 `hello` 握个手 能力和身份总是透明地得到补充.

## 终端帧路由

```ts
import { TerminalStreamRouter } from "@av-pi-studio/client";

const router = new TerminalStreamRouter(daemon);
router.start();                                   // begin routing (idempotent)
const unsubscribe = router.subscribeSlot(slot, {
  onOutput: (data) => { /* opcode Output */ },
  onSnapshot: (data) => { /* opcode Snapshot, sent on (re)subscribe */ },
  onRestore: (data) => { /* opcode Restore, reflowable/mode-gated */ },
});
router.sendInput(slot, bytes);                    // opcode Input = 0x02
router.sendResize(slot, rows, cols);              // opcode Resize = 0x03
router.stop();                                    // stop routing; subscribers retained
```

## 自定义运输

```ts
interface Transport {
  connect(url: string): Promise<void>;   // resolves once the raw connection is open (pre-handshake)
  sendText(data: string): void;
  sendBinary(data: Uint8Array): void;
  close(code?: number, reason?: string): void;
  readonly isOpen: boolean;

  onMessage: ((data: string | ArrayBuffer | Blob) => void) | null;
  onClose: ((code: number, reason: string) => void) | null;
  onError: ((error: unknown) => void) | null;
}
```

`createWebSocketTransport(factory?: WsFactory)` 是默认的节点/浏览器 WebSocket 备份 执行. `factory` 是可注入的 `(url, protocols?) => AnyWebSocket` ——为 或装有无记名字副规范的定制工厂(没有内置) `password` 参数;见 `web-client`是因为 `connection-store.ts` 以这种方式).

### 中继运输(E2EE,通过 `@av-pi-studio/relay`(中文(简体) )

```ts
import { createRelayTransport, parsePairingUrl, relayDialUrl } from "@av-pi-studio/client";

// offer: { publicKey, publicKeyB64, host? } OR { publicKey, publicKeyB64, relay: { endpoint, useTls } }
const offer = parsePairingUrl(pairingUrlOrFragment);

// sessionId defaults to deriveRelaySessionId(offer.publicKey) — the SAME id the daemon's own
// outbound relay dial always registers under — so it never needs to be transmitted separately.
const transport = createRelayTransport({ daemonPublicKey: offer!.publicKey });

const daemon = new DaemonClient({
  url: relayDialUrl(offer!.relay!), // the relay's own address, not the daemon's
  clientId,
  clientType: "cli",
  transport,
});
await daemon.connect(); // completes the E2EE handshake before the `hello` RPC ever crosses the wire
```

`createRelayTransport` 执行完全相同的 `Transport` 合同为 `createWebSocketTransport` - 交换它通过 `DaemonClientOptions.transport` 和所有别的东西 `DaemonClient`编号 :`PiStudioClient` API 工作不变, 不管守护进程是直接的还是到达的 通过接力。 见 `@av-pi-studio/relay`运行中继服务器的 README `@av-pi-studio/server`读取一个守护进程.

## 设计规则

-   **`RpcTimeoutError` 从不关闭套接字.** 缓慢的RPC是操作级别失败,而不是 连接失败 .
-   **`clientId` 整个连接保持稳定** ——它识别逻辑客户端会话,而不是 物理联系.
-   **无 DOM/ Node 特定全球** 内 `daemon-client.ts` 或基数 `Transport` 类型——仅 `createWebSocketTransport` 本身触摸了平台 WebSocket, 而基础驱动程序从未 直接进口.

## 发展

```bash
npm run build       # tsc -b
npx vitest run packages/client
```

测试注入根 `Transport` 执行和模拟时钟——没有打开真正的插座.

## 常见问题

### @av-pi-studio/client 是什么？

与 Pi-Studio 守护进程交谈的客户端侧文库:一个低级的 WebSocket 驱动程序\(DaemonClient\)外加一个高水平,打入的SDK外观 \(PiStudioClient\) \(中文\(简体\) \)\. 这个包裹是什么 @av-pi-studio/cli 以及未来网络/移动/台式计算机 c

### 如何安装 @av-pi-studio/client？

在项目目录运行 npm install @av-pi-studio/client，或使用 pnpm add / yarn add / bun add。

### @av-pi-studio/client 支持 TypeScript 吗？

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

### @av-pi-studio/client 支持 ESM 还是 CommonJS？

以 ES Module 形式发布，推荐使用 import 引入。在 CommonJS 项目中，Node\.js 20\.19\+ / 22\.12\+ 可以直接 require\(\) 不含顶层 await 的 ES Module，更早的版本需要改用动态 import\(\)。

### @av-pi-studio/client 可以商用吗？

@av-pi-studio/client 使用 未声明 许可。package\.json 没有声明许可证。没有许可证的代码默认保留全部权利，商用前请联系作者或查看仓库中的 LICENSE 文件。以上为概括，不构成法律意见，请以许可原文为准。

### @av-pi-studio/client 的下载量有多少？

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

### @av-pi-studio/client 还在维护吗？

最新版本 0\.0\.115 发布于 2026/11/04（4 天前）；至今共发布 114 个版本，其中过去 12 个月发布了 114 个；首次发布于 2026/07/18。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

