diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..3e03c8f --- /dev/null +++ b/CHANGELOG.md @@ -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. diff --git a/README.md b/README.md index 4eb2a8e..45adb1d 100644 --- a/README.md +++ b/README.md @@ -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'; @@ -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) | @@ -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`. @@ -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 @@ -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/`. @@ -280,7 +285,7 @@ stay `@trychert/sdk/`. 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 diff --git a/docs/BETTER_AUTH.md b/docs/BETTER_AUTH.md index 8ef82d2..8d2b7ef 100644 --- a/docs/BETTER_AUTH.md +++ b/docs/BETTER_AUTH.md @@ -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). diff --git a/docs/SETUP.md b/docs/SETUP.md index dddbf3f..9cde214 100644 --- a/docs/SETUP.md +++ b/docs/SETUP.md @@ -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 diff --git a/llms.txt b/llms.txt index d709e70..9a0ce1c 100644 --- a/llms.txt +++ b/llms.txt @@ -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. diff --git a/package.json b/package.json index fa6d4fa..8ff852a 100644 --- a/package.json +++ b/package.json @@ -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" }, diff --git a/packages/adopt/README.md b/packages/adopt/README.md index 544d79e..46db495 100644 --- a/packages/adopt/README.md +++ b/packages/adopt/README.md @@ -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/`; 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 diff --git a/packages/adopt/src/providers.ts b/packages/adopt/src/providers.ts index 62fa725..6a35eee 100644 --- a/packages/adopt/src/providers.ts +++ b/packages/adopt/src/providers.ts @@ -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[] = [ { diff --git a/packages/adopt/tests/adopt.test.ts b/packages/adopt/tests/adopt.test.ts index f83c320..0e36141 100644 --- a/packages/adopt/tests/adopt.test.ts +++ b/packages/adopt/tests/adopt.test.ts @@ -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" } } @@ -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'); }); @@ -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')); }); diff --git a/packages/control-plane/README.md b/packages/control-plane/README.md index 54b4373..104ccff 100644 --- a/packages/control-plane/README.md +++ b/packages/control-plane/README.md @@ -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. diff --git a/packages/imessage/README.md b/packages/imessage/README.md index 668174d..72f8c94 100644 --- a/packages/imessage/README.md +++ b/packages/imessage/README.md @@ -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 diff --git a/python/README.md b/python/README.md index 380f67f..0612487 100644 --- a/python/README.md +++ b/python/README.md @@ -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 diff --git a/python/pyproject.toml b/python/pyproject.toml index b539ccb..064568e 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -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" diff --git a/python/tests/test_client.py b/python/tests/test_client.py index 296cd3c..80bfd56 100644 --- a/python/tests/test_client.py +++ b/python/tests/test_client.py @@ -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) diff --git a/scripts/test-package.ts b/scripts/test-package.ts index 0d40631..b539191 100644 --- a/scripts/test-package.ts +++ b/scripts/test-package.ts @@ -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');