@ai-matrx/desktop-protocol

中文文档
0.21.102发布于 2026/10/28MITTypeScriptESM + CJS近 30 天下载 4.7万

The one wire contract between Matrx 2 (the desktop app) and every client that drives it — phone, web app, extension, server: zod schemas for the envelope and every cap.op, the 16-byte binary frame codec, a reconnecting request/stream/credit/reattach clien

原始使用文档
文档目录6 节
  1. Client
  2. Local transcription
  3. React
  4. Python (aidream)
  5. Python services (matrx-desktop)
  6. Changing the protocol

@ai-matrx/desktop-protocol

The one wire contract between Matrx 2 (the desktop app) and everything that drives it — the phone console, the web app, the extension and the server. One zod source; a generated JSON Schema and Pydantic twin that CI keeps byte-identical (SPEC P11: contracts are generated, never written twice).

pnpm add @ai-matrx/desktop-protocol
EntryWhat it is
@ai-matrx/desktop-protocolSchemas for the envelope and every cap.op, OPS / EVENTS registries, ErrorCode, close codes, DesktopProtocolError. Every schema name is also its inferred type.
@ai-matrx/desktop-protocol/frameThe 16-byte binary frame codec. Zod-free (the relay Worker's hot path).
@ai-matrx/desktop-protocol/clientcreateDesktopClient — reconnecting client with typed requests, credit-gated streams, transparent terminal reattach, heartbeat and relay reauth.
@ai-matrx/desktop-protocol/reactDesktopClientProvider, useDesktopConnection, useDesktopRequest, useDesktopEvent, useDesktopWake.

Client

import { createDesktopClient } from "@ai-matrx/desktop-protocol/client";

const client = createDesktopClient({
  url: `wss://relay.matrxserver.com/v1/devices/${deviceId}/connect`,
  // Re-read on every reconnect; tokens ride the subprotocol, never the URL.
  protocols: async () => ["matrx.v1", `bearer.${await getAccessToken()}`],
  getToken: getAccessToken, // answers relay.auth_expiring without dropping the socket
  clientType: "web",
  clientVersion: "1.0.0",
});

const listing = await client.request("fs.list", { path: "/Users/me" }); // typed by op name

const term = client.stream("exec.pty.start", { cols: 80, rows: 24 }, {
  onData: (bytes) => new Promise((done) => xterm.write(bytes, done)), // credit follows consumption
  onSnapshot: (bytes) => {
    xterm.reset();
    xterm.write(bytes);
  },
});
term.write("ls\n");
  • Backpressure: credit for a stream is granted only after onData returns (or its promise settles), so a slow phone never makes the relay or the Mac buffer without bound.
  • Reattach: a resource stream (terminal, watch) survives a dropped socket. On reconnect the client sends session.attach with since_seq = the last frame your onData consumed; the core replays the gap or sends gap + a screen snapshot. The same DesktopStream keeps working.
  • Errors are DesktopProtocolError with code, retryable and data.reason — branch on those, never on messages. A dropped socket rejects unary work with DEVICE_OFFLINE (retryable).
  • Terminal closes (4010 revoked, 4003 forbidden, 4004 not found, 4009 replaced, 4426 upgrade) end the client for good; everything else reconnects with the shared @ai-matrx/data/realtime backoff (stability reset + jitter) — including 1006 (a relay deploy drops every socket without a close frame) and 1012 (the relay's "the device reconnected": hello and reattach against the new core session).
  • Coming back: client.wake() (or bindDesktopWake(client) / useDesktopWake(), which call it on visibilitychange, pageshow, online and focus) dials at once while reconnecting and probes an open socket with a ping, redialing if nothing answers within 4 s.
  • Reload reattach: keep stream.resourceId and stream.lastSeq (e.g. in the URL); after a reload client.stream("session.attach", { resource_id, since_seq }) replays the gap and then behaves exactly like the original stream, including surviving later drops.
  • Background problems (malformed messages, sequence gaps, heartbeat death, reconnect alarm) go to onDiagnostic — loud by default (console.warn).

Local transcription

import { createDesktopTranscriber } from "@ai-matrx/desktop-protocol/client";

const transcriber = createDesktopTranscriber(client, { model: "base", onProgress: (p) => show(p) });
const { text, segments } = await transcriber.transcribe(recordingBlob); // on the person's computer
// Or as a voice input's transport: new BrowserAudioKernel({ transport: transcriber })

React

<DesktopClientProvider client={client}>
  <Files />
</DesktopClientProvider>

function Files() {
  const { status } = useDesktopConnection();
  const { data, error, loading, refetch } = useDesktopRequest("fs.list", { path: "/Users/me" });
  useDesktopEvent("fs.changed", () => void refetch());
}

Python (aidream)

from aidream._generated.desktop_protocol import OPS, FsListParams, validate_wire

params = validate_wire(FsListParams, raw_json)  # same verdict as zod, always

validate_wire is the one Python entry point: strict (no "2" → 2) and JavaScript-faithful (2.0 is the integer 2). OPS maps every op to its params/result models, kind and errors.

Python services (matrx-desktop)

The desktop's supervised Python services generate their models from the installed package with the same generator, so the core and the service can never drift:

python3 node_modules/@ai-matrx/desktop-protocol/scripts/gen_pydantic.py \
  --schema node_modules/@ai-matrx/desktop-protocol/generated/desktop-protocol.schema.json --out <module>.py

The module carries SERVICES, a typed handler Protocol per service (MlServiceHandlers) and CONTRACT_SHA256, which must equal the core's (import { CONTRACT_SHA256 }) in the service hello.

Changing the protocol

Edit src/schema/*.ts, then pnpm generate and commit all three files. Rules (enforced by pnpm lint and by generate): z.strictObject only; no .refine/.transform/z.coerce/ .meta; never optional and nullable at once; a new named schema goes into NAMED_SCHEMAS; add a parity case to corpus/parity-corpus.json for any new wire shape.

MIT © AI Matrix Engine

版本与发布记录

@ai-matrx/desktop-protocol 共发布 136 个版本,首次发布于 2026/10/02;过去 12 个月发布了 136 个版本。

版本发布日期距今
0.21.102latest2026/10/288 天前
0.21.1012026/10/289 天前
0.21.1002026/10/2511 天前
0.21.992026/10/2512 天前
0.21.982026/10/2412 天前
0.21.972026/10/2412 天前

关于 @ai-matrx/desktop-protocol 的常见问题

@ai-matrx/desktop-protocol 是什么?

The one wire contract between Matrx 2 (the desktop app) and every client that drives it — phone, web app, extension, server: zod schemas for the envelope and every cap.op, the 16-byte binary frame codec, a reconnecting request/stream/credit/reattach clien

如何安装 @ai-matrx/desktop-protocol?

在项目目录运行 npm install @ai-matrx/desktop-protocol,或使用 pnpm add / yarn add / bun add。

@ai-matrx/desktop-protocol 支持 TypeScript 吗?

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

@ai-matrx/desktop-protocol 支持 ESM 还是 CommonJS?

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

@ai-matrx/desktop-protocol 需要什么版本的 Node.js?

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

@ai-matrx/desktop-protocol 可以商用吗?

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

@ai-matrx/desktop-protocol 的下载量有多少?

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

@ai-matrx/desktop-protocol 还在维护吗?

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