Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Changelog

## 0.3.0

`@trychert/sdk` 0.3.0 (npm). Python source is versioned 0.3.0, but this release
does **not** publish it: `chert-sdk` remains 0.2.3 on PyPI.

### Changed

- **Missing-transcript errors have a new `code`.** When a FaceTime response
contains `error.code: "transcript_not_found"`, JavaScript
`ChertApiError.code` is now `transcript_not_found`, not `request_failed` as in
0.2.3. The formatted error text includes that code and changes too. Update
handlers that matched `request_failed` for missing transcripts to match
`transcript_not_found`; do not branch on formatted error text. The new
transcript helper also reports a missing transcript as an error, not an empty
transcript. This release is not purely additive.

### Added

- **Inspect FaceTime error codes without retaining server messages.** JavaScript
`ChertApiError.serverCode` exposes recognized codes, maps unrecognized or
malformed codes to `unknown`, and is `undefined` when no code is provided.
This property is additive; it does not make the release's `code` behavior
unchanged (see **Changed** above). Error text keeps its existing format and
does not include raw server messages. Raw server messages and response bodies
are not retained in the error.
- **Add public resource helpers.** JavaScript adds project discovery,
integration metadata and recorded call transcripts, plus chat creation,
recorded chat history and message status. Chat creation requires a stable
idempotency key; replay outcomes must be reconciled rather than treated as
delivery receipts. Project discovery uses a signed-in user bearer.
- **Add Better Auth phone transport alongside email.** The optional server-only
`@trychert/sdk/better-auth` subpath sends phone verification messages through
Chert. Better Auth owns code storage, verification and expiry. This transport
does not guarantee iMessage-only delivery or prevent SMS fallback. Codes can
remain in the recipient's message history after they expire.
- **Add direct-media request fields.** Customer-managed calls can describe
`media_transport: "direct"`, `media_url`, `media_token` and an optional remote
participant identity. Existing LiveKit request bodies are unchanged. These
fields do not establish hosted service availability or media interoperability.
- **Preserve deployment URLs and replay details.** Integration helpers retain
inherited host configuration and recorded chat replay outcomes. Setup guides
distinguish package availability from service support.

Other language clients remain source previews, not new registry releases.
Custom video, living services, screen sharing, call video composition and
terminal billing retain their documented service-availability limits.

## 0.2.3

See the [0.2.3 release notes](https://github.com/cherthq/sdk/releases/tag/v0.2.3)
for the npm and PyPI release, including the text-send route correction and
unchanged limits on unavailable services.
53 changes: 29 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,20 @@

Open-source clients for Chert messaging and FaceTime control-plane services.
This repository contains JavaScript/TypeScript, Python, Rust, C#/.NET, C++ and Go
clients. **Language coverage and release status differ:** JavaScript is published;
the other clients are source previews, with unified channel support under review.
clients. **Language coverage and release status differ:** npm targets 0.3.0;
Python source is 0.3.0 but PyPI remains 0.2.3. Other clients are source previews.
See the [changelog](CHANGELOG.md) for release changes and availability.

**New here? Start with the [setup guide](docs/SETUP.md).** Coding agents can read
[`llms.txt`](llms.txt) or run `chert-sdk context`.

Better Auth users: the [iMessage phone transport](docs/BETTER_AUTH.md) is a
source preview for the next SDK release, not in npm 0.2.3. It adds phone
Better Auth users: the [iMessage phone transport](docs/BETTER_AUTH.md) ships in
npm 0.3.0. It adds phone
verification alongside existing email auth, not instead of it.

### Unreleased public resource helpers
### Public resource helpers in 0.3.0

The following helpers are **source previews on `main`, not in npm 0.2.3**:
The following helpers ship in **npm 0.3.0**:

```ts
import { ChertClient, ChertControlPlane } from '@trychert/sdk';
Expand Down Expand Up @@ -69,14 +70,18 @@ sensitive data; do not log them or assume that server text is sanitized.

FaceTime control-plane failures expose recognized server error codes as the
enumerable `ChertApiError.serverCode`. Unrecognized codes map to `unknown`;
when no code is provided, `serverCode` is undefined. The existing `code` remains
unchanged, and the default error text does not include server messages.
when no code is provided, `serverCode` is undefined. This property is additive,
but 0.3.0 also changes `code` for `transcript_not_found` responses from
`request_failed` to `transcript_not_found`. Update missing-transcript handlers
accordingly. The formatted text includes `code`, so it changes in that case;
do not branch on that text. Raw server messages are not retained or included
in default error text. See [Changed in 0.3.0](CHANGELOG.md#changed).

## Languages and release status

| Language | Available on `main` | Release / unified-channel work | Documentation |
| --- | --- | --- | --- |
| JavaScript / TypeScript | iMessage, FaceTime control plane, provider adapters, CLI | This guide targets `@trychert/sdk@0.2.3`; see [npm](https://www.npmjs.com/package/@trychert/sdk) for available versions. Binary: `chert-sdk` | [Quickstart below](#javascript--typescript) |
| JavaScript / TypeScript | iMessage, FaceTime control plane, provider adapters, CLI | This guide targets `@trychert/sdk@0.3.0`; see [npm](https://www.npmjs.com/package/@trychert/sdk) for available versions. Binary: `chert-sdk` | [Quickstart below](#javascript--typescript) |
| Python 3.10+ | iMessage and FaceTime control plane (`trychert`); legacy `chert` imports retained | [`chert-sdk` 0.2.3 on PyPI](https://pypi.org/project/chert-sdk/0.2.3/): `pip install chert-sdk==0.2.3` | [Python guide](python/README.md) |
| Rust 1.88+ | Async iMessage and FaceTime clients (`trychert_sdk`) | Unpublished `chert-sdk`; source preview only | [Rust guide](rust/README.md) |
| C# / .NET 8 | iMessage and FaceTime HTTP clients (`TryChert`) | Unpublished `chert-sdk` NuGet package; source preview only | [.NET guide](dotnet/README.md) |
Expand Down Expand Up @@ -108,22 +113,22 @@ build/test source; do not substitute a similarly named registry package.

## JavaScript / TypeScript

The examples below target **`@trychert/sdk@0.2.3`**. The
The examples below target **`@trychert/sdk@0.3.0`**. The
[npm package page](https://www.npmjs.com/package/@trychert/sdk) lists available
versions. Package availability does not establish live backend support.

```sh
npm install @trychert/sdk@0.2.3
npm install @trychert/sdk@0.3.0
# Alternatives:
pnpm add @trychert/sdk@0.2.3
bun add @trychert/sdk@0.2.3
pnpm add @trychert/sdk@0.3.0
bun add @trychert/sdk@0.3.0

npx --package=@trychert/sdk@0.2.3 chert-sdk --help
bunx --package @trychert/sdk@0.2.3 chert-sdk --help
npx --package=@trychert/sdk@0.3.0 chert-sdk --help
bunx --package @trychert/sdk@0.3.0 chert-sdk --help
```

ESM and declarations are shipped for Node 22.12+, current Bun and Deno 2 with
npm compatibility. Deno imports use `npm:@trychert/sdk@0.2.3` (append subpaths
npm compatibility. Deno imports use `npm:@trychert/sdk@0.3.0` (append subpaths
after the version). CommonJS `require()` is not a supported migration target.
The npm package is `@trychert/sdk`; the CLI binary remains `chert-sdk`.

Expand Down Expand Up @@ -245,12 +250,12 @@ plan-change policy exists, and the CLI has no `switch` command. Dedicated purcha
unavailable (`billing_dedicated_unqualified`) until dedicated fulfilment is enabled.

```sh
bunx --package @trychert/sdk@0.2.3 chert-sdk context
bunx --package @trychert/sdk@0.2.3 chert-sdk facetime status
bunx --package @trychert/sdk@0.2.3 chert-sdk facetime lines
bunx --package @trychert/sdk@0.2.3 chert-sdk facetime workers
bunx --package @trychert/sdk@0.2.3 chert-sdk adopt ./my-app # Dry-run migration report
bunx --package @trychert/sdk@0.2.3 chert-sdk adopt ./my-app --write # Applies supported rewrites
bunx --package @trychert/sdk@0.3.0 chert-sdk context
bunx --package @trychert/sdk@0.3.0 chert-sdk facetime status
bunx --package @trychert/sdk@0.3.0 chert-sdk facetime lines
bunx --package @trychert/sdk@0.3.0 chert-sdk facetime workers
bunx --package @trychert/sdk@0.3.0 chert-sdk adopt ./my-app # Dry-run migration report
bunx --package @trychert/sdk@0.3.0 chert-sdk adopt ./my-app --write # Applies supported rewrites
```

`context` prints JSON with the SDK version, which credentials are set (never
Expand All @@ -271,7 +276,7 @@ preserved. `chert-adopt` becomes `chert-sdk adopt`.

The published scoped package remains available and is not unpublished or
deprecated by this change. Existing installs and imports keep working without
migration. To upgrade, update the dependency to `@trychert/sdk@0.2.3`
migration. To upgrade, update the dependency to `@trychert/sdk@0.3.0`
(published, `latest`), regenerate your consumer lockfile and rerun tests.
No import rename is needed: root imports stay `@trychert/sdk` and subpaths
stay `@trychert/sdk/<subpath>`.
Expand All @@ -280,7 +285,7 @@ stay `@trychert/sdk/<subpath>`.

The canonical npm package is `@trychert/sdk`, not `chert-sdk`. If you installed
the accidental unscoped 0.1.0 package (since unpublished from npm), remove that
dependency and install `@trychert/sdk@0.2.3`. Change root imports
dependency and install `@trychert/sdk@0.3.0`. Change root imports
from `chert-sdk` to `@trychert/sdk` and preserve subpath suffixes (for example,
`chert-sdk/facetime` becomes `@trychert/sdk/facetime`). Regenerate your consumer
lockfile and rerun tests. The identity correction does not change the default
Expand Down
4 changes: 2 additions & 2 deletions docs/BETTER_AUTH.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Better Auth: iMessage phone transport alongside email

**Source preview; not included in npm 0.2.3.** This integration adds the server-only
`@trychert/sdk/better-auth` subpath in the next SDK release. It is not a separate
**Included in npm 0.3.0.** This integration adds the server-only
`@trychert/sdk/better-auth` subpath. It is not a separate
auth system or package. Better Auth is optional: the SDK transport has no Better
Auth runtime dependency. Tested against Better Auth 1.7.14's
[phone-number sendOTP hook](https://www.better-auth.com/docs/plugins/phone-number).
Expand Down
4 changes: 2 additions & 2 deletions docs/SETUP.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ Coding agents can read the same material from [`llms.txt`](https://github.com/ch
The SDKs and the FaceTime agent CLI are separate packages with separate commands.
The SDK's `chert-sdk` CLI has no `login`, `onboard`, `new` or `dev` command.

For Better Auth, see the [phone transport guide](BETTER_AUTH.md): source preview,
not included in npm 0.2.3. Existing email auth stays enabled alongside phone.
For Better Auth, see the [phone transport guide](BETTER_AUTH.md), included in
npm 0.3.0. Existing email auth stays enabled alongside phone.

## 1. Install

Expand Down
3 changes: 2 additions & 1 deletion llms.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@

Rules for coding agents:

- Better Auth phone transport (`@trychert/sdk/better-auth`) is source preview only, not in npm 0.2.3. See docs/BETTER_AUTH.md. Email remains supported alongside phone. Never auto-fallback to SMS after an uncertain send.
- npm targets 0.3.0. Python source is 0.3.0 but PyPI remains 0.2.3; do not request a nonexistent Python 0.3.0 release.
- Better Auth phone transport (`@trychert/sdk/better-auth`) ships in npm 0.3.0. See docs/BETTER_AUTH.md. Email remains supported alongside phone. Never auto-fallback to SMS after an uncertain send.
- Run `chert-sdk context` (or `npx --package=@trychert/sdk chert-sdk context`) first. It prints JSON with the SDK version, which credentials are set (never their values), FaceTime identity and lines, and docs links. `--offline` makes no requests.
- Credentials are per service: `CHERT_API_KEY` (iMessage), `CHERT_FACETIME_TOKEN` plus `CHERT_PROJECT_ID` (FaceTime). They are not interchangeable. Never print or commit them. In `CHERT_FACETIME_TOKEN`, identity (`facetime status`) needs a CLI login (`ftu_`); lines, workers, calls and assistants take a project API key (`ftk_`).
- `chert-sdk imessage send` needs `--confirm` and a stable `--idempotency-key`. Send only to recipients who agreed, and only when the user asked.
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
{
"name": "@trychert/sdk",
"version": "0.2.3",
"version": "0.3.0",
"description": "Unified Chert iMessage, FaceTime control-plane, provider adapters and migration CLI",
"type": "module",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"engines": { "node": ">=22.12" },
"publishConfig": { "access": "public" },
"files": ["dist", "README.md", "LICENSE", "COMPATIBILITY.md", "llms.txt", "docs/SETUP.md", "docs/BETTER_AUTH.md"],
"files": ["dist", "README.md", "CHANGELOG.md", "LICENSE", "COMPATIBILITY.md", "llms.txt", "docs/SETUP.md", "docs/BETTER_AUTH.md"],
"bin": {
"chert-sdk": "./dist/unified/cli.js"
},
Expand Down
4 changes: 2 additions & 2 deletions packages/adopt/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ adapter still rejects unsupported operations before sending.

The public entry point is `chert-sdk adopt`. New rewrites install `@trychert/sdk`
and import `@trychert/sdk/<adapter>`; the `@cherthq/*` names below are private
workspace names. This guide targets `@trychert/sdk@0.2.3`; the
workspace names. This guide targets `@trychert/sdk@0.3.0`; the
[npm package page](https://www.npmjs.com/package/@trychert/sdk) lists available
versions. Run it from the published package with
`npx --package=@trychert/sdk@0.2.3 chert-sdk adopt ./my-app` (dry run). Existing `@trychert/sdk@0.1.0`
`npx --package=@trychert/sdk@0.3.0 chert-sdk adopt ./my-app` (dry run). Existing `@trychert/sdk@0.1.0`
imports need no rename; see the [upgrade guide](../../README.md#upgrading-from-trychertsdk010).

```sh
Expand Down
2 changes: 1 addition & 1 deletion packages/adopt/src/providers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export const CHERT_WEBHOOK_ENV = 'CHERT_WEBHOOK_SECRET';
// Legacy package names remain in the coverage table for workspace compatibility.
// New integrations install one SDK and import the equivalent adapter subpath.
export const sdkImport = (legacy: string) => legacy.replace('@cherthq/', '@trychert/sdk/');
export const SDK_VERSION = '0.2.3';
export const SDK_VERSION = '0.3.0';

export const PROVIDERS: Provider[] = [
{
Expand Down
6 changes: 3 additions & 3 deletions packages/adopt/tests/adopt.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ describe('dry run, write and safety', () => {
"private": true,
"type": "module",
"dependencies": {
"@trychert/sdk": "0.2.3",
"@trychert/sdk": "0.3.0",
"express": "4.21.2"
}
}
Expand All @@ -220,7 +220,7 @@ describe('dry run, write and safety', () => {
expect(run(dir, '--write').code).toBe(0);
expect(readFileSync(join(dir, 'src/notifier.ts'), 'utf8')).toStartWith('import Blooio from "@trychert/sdk/blooio-adapter";\nimport type { MessageSendResponse } from "@blooio/sdk/resources/messages";');
expect(readFileSync(join(dir, 'src/legacy.cjs'), 'utf8')).toBe(readFileSync(join(fixtures, 'blooio-ts/src/legacy.cjs'), 'utf8'));
expect(JSON.parse(readFileSync(join(dir, 'package.json'), 'utf8')).dependencies).toEqual({ '@blooio/sdk': '0.0.2', '@trychert/sdk': '0.2.3' });
expect(JSON.parse(readFileSync(join(dir, 'package.json'), 'utf8')).dependencies).toEqual({ '@blooio/sdk': '0.0.2', '@trychert/sdk': '0.3.0' });
expect(readFileSync(join(dir, 'ADOPTION_REPORT.md'), 'utf8')).toContain('`src/legacy.cjs:4` Blooio SDK 0.0.2 `messages.cancel`: Message cancellation is rejected');
});

Expand All @@ -234,7 +234,7 @@ describe('dry run, write and safety', () => {

const v4 = project('blooio-v4-ts');
expect(run(v4, '--write').code).toBe(0);
expect(JSON.parse(readFileSync(join(v4, 'package.json'), 'utf8')).dependencies).toEqual({ '@trychert/sdk': '0.2.3' });
expect(JSON.parse(readFileSync(join(v4, 'package.json'), 'utf8')).dependencies).toEqual({ '@trychert/sdk': '0.3.0' });
expect(readFileSync(join(v4, 'src/api.ts'), 'utf8')).toBe(readFileSync(join(fixtures, 'blooio-v4-ts/src/api.ts'), 'utf8'));
});

Expand Down
2 changes: 1 addition & 1 deletion packages/control-plane/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Chert FaceTime client

The `@trychert/sdk/facetime` export provides typed HTTP methods for the Chert FaceTime
API. This guide targets `@trychert/sdk@0.2.3`; the
API. This guide targets `@trychert/sdk@0.3.0`; the
[npm package page](https://www.npmjs.com/package/@trychert/sdk) lists available
versions. Use a reviewed local tarball for local validation. See the root guide
for supported Node, Bun and Deno versions.
Expand Down
2 changes: 1 addition & 1 deletion packages/imessage/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ fallback or automatic retries. An optional `baseURL` accepts HTTPS or loopback
HTTP: root origins get `/api/v1`; explicit deployment path prefixes and trailing
slashes retain their existing semantics. `/api/v1` is not duplicated. Only
omitted/undefined values select the default; empty/null values are rejected.
The public import is `@trychert/sdk/imessage`. This guide targets 0.2.3; the
The public import is `@trychert/sdk/imessage`. This guide targets 0.3.0; the
[npm package page](https://www.npmjs.com/package/@trychert/sdk) lists available
versions. Requests require a backend supporting the documented contracts and
authorized access. Verify feature availability for your project; package
Expand Down
6 changes: 4 additions & 2 deletions python/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,16 @@ Python 3.10+ synchronous SDK with no runtime dependencies and no CLI.
The distribution name is **`chert-sdk`**; the import namespace is **`trychert`**.
[`chert-sdk` 0.2.3](https://pypi.org/project/chert-sdk/0.2.3/) is published on PyPI.
The legacy `chert` import and explicit-URL constructor calls remain compatible.
The source version is 0.3.0, but Python 0.3.0 is **not published** by the npm
0.3.0 release. Install 0.2.3 from PyPI until a separate Python release is ready.

```sh
python -m pip install chert-sdk==0.2.3
# or: uv add chert-sdk==0.2.3
```

This guide matches the published 0.2.3 package, which was built from this source
tree. The version follows the npm `@trychert/sdk` 0.2.3 release. 0.2.3 sends text to
The published 0.2.3 package matched the npm `@trychert/sdk` 0.2.3 release;
newer source can differ. 0.2.3 sends text to
`POST /api/v1/send` (0.2.2 and earlier used a route production does not serve), accepts
`queued`, `sent` and `duplicate` receipts, rejects idempotency keys with surrounding
whitespace, and adds call video composition and terminal billing, which are not
Expand Down
2 changes: 1 addition & 1 deletion python/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "chert-sdk"
version = "0.2.3"
version = "0.3.0"
description = "Explicit synchronous iMessage and FaceTime control-plane clients"
readme = "README.md"
requires-python = ">=3.10"
Expand Down
2 changes: 1 addition & 1 deletion python/tests/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ def test_installed_build_backend_produces_importable_dependency_free_wheel(self)
self.assertEqual(result.returncode, 0, result.stderr)
wheel, = Path(temp).glob("*.whl")
with zipfile.ZipFile(wheel) as archive:
metadata = archive.read("chert_sdk-0.2.3.dist-info/METADATA").decode()
metadata = archive.read("chert_sdk-0.3.0.dist-info/METADATA").decode()
self.assertIn("Name: chert-sdk\n", metadata)
self.assertNotIn("Requires-Dist:", metadata)
self.assertIn("Requires-Python: >=3.10", metadata)
Expand Down
2 changes: 1 addition & 1 deletion scripts/test-package.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ try {
const installed = join(temporary, 'node_modules/@trychert/sdk');
const manifest = JSON.parse(readFileSync(join(installed, 'package.json'), 'utf8'));
assert.equal(manifest.name, '@trychert/sdk');
assert.equal(manifest.version, '0.2.3');
assert.equal(manifest.version, '0.3.0');
assert.deepEqual(manifest.bin, { 'chert-sdk': './dist/unified/cli.js' });
assert.notEqual(manifest.private, true);
assert.equal(manifest.publishConfig.access, 'public');
Expand Down
Loading