Skip to content

Cell - Ta Client ​

The client for ta serve: depends only on platform-native WebSocket, and works in browsers, Electron, mobile apps, and Node.js >= 22.4.

ts
import { SessionStore, TaConnection } from '@celljs/ta-client';

const connection = new TaConnection({ url, token });   // from ~/.ta/agent/serve.json
await connection.connect();
const { sessionId } = await connection.server.openSession({ cwd: '/repo' });

const store = new SessionStore(connection, sessionId);
store.subscribe(state => render(state));   // notified once per batch of events
await store.attach();
await store.prompt('Fix the failing tests');
  • TaConnection: auto-reconnects after disconnect using exponential backoff. onReconnecting(delayMs, attempt) notifies you before each wait, and reconnect() skips the wait and retries immediately. connection.server (sessions), workspace, terminals, settings, packages, auth (login to model services, subscribe to events with onAuthEvent), and relay (paired devices) are typed proxies for ta serve's services, all sharing one connection. The createSocket option lets you use a different transport, like RelaySocket through Relay (@celljs/ta-relay). Calls during disconnection fail immediately (TaRemoteError, code is CELL_TA_CONNECTION_LOST) without queuing; whether to retry is up to the caller (reuse clientMessageId when retrying). Connections that drop re-establish themselves; operations from before the drop complete with the previous code if the server still has them.
  • SessionStore: the client-side state for one session (messages, tool runs, pending dialogs, extension status bars). After reconnect, it resends missed events by seq. If it can't catch up (a gap), it auto-syncs with getMessages.
  • Client tools: the model can call tools run by the client (e.g., read clipboard, let the user pick something in the UI). Declare them when opening a session; SessionStore runs them and returns the results:
ts
const pickColor: ClientTool = {
    definition: { name: 'pick_color', description: 'Ask the user to pick a color', parameters: { type: 'object', properties: {} } },
    run: async () => await showColorPicker(),   // text returned to model; errors mean tool failure
};
const { sessionId } = await connection.server.openSession({ cwd, clientTools: [pickColor.definition] });
const store = new SessionStore(connection, sessionId, { clientTools: [pickColor] });

Call requests broadcast to all connected clients; the first result wins (same as dialogs). Each call runs once per client, and after disconnect, resends the already-calculated result instead of running again. If run is aborted or the session closes, the call ends as failed. The same client tools work in codemode scripts using tools.pick_color().

  • openSession's appendSystemPrompt appends a system prompt line to the session (like pi's --append-system-prompt), allowing clients to give the Agent a role.
  • SessionReducer: a pure function (state, event) => state, never mutating old state, so UIs can compare by reference.