diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 03b077e..88078d5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -67,7 +67,9 @@ jobs: run: pnpm test - name: Build JavaScript packages - run: pnpm build + run: | + pnpm build + pnpm check:package-install browser: name: Browser microphone diff --git a/CHANGELOG.md b/CHANGELOG.md index 54e4830..a1c2593 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,15 +2,27 @@ Seda follows semantic versioning. Notable changes are recorded here. +## 0.3.0 + +- Made `SedaBrowser.prepare({ modelId })` the high-level readiness boundary. + `create()` remains a deprecated compatibility alias. +- Replaced model tiers as the primary interface with exact model ID, immutable + revision, variant, and runtime identity. Profiles remain convenience aliases. +- Moved language selection from preparation and startup to each transcription + or live stream, with fixed, prompted, automatic, and checkpoint capability + semantics. +- Added typed Python, Go, and Swift protocol clients with real Rust-sidecar + HTTP/WebSocket integration coverage in GitHub Actions. +- Declared the universal client as a peer of the browser and Node packages so + GitHub release tarballs can be installed without an unpublished npm package. + ## 0.2.0 - Added `@bearlyai/seda-browser`, a serverless in-browser runtime backed by a dedicated Worker, automatic WebGPU/WASM selection, and pinned Moonshine Tiny model caching. -- Made `SedaBrowser.prepare({ modelId })` the high-level readiness boundary, - followed by `microphone()`, live revisions, `stop()`, `cancel()`, and - `close()`—no port, token, or audio blobs. `create()` remains a deprecated - compatibility alias. +- Kept the high-level API to `SedaBrowser.create()`, `microphone()`, live + revisions, `stop()`, `cancel()`, and `close()`—no port, token, or audio blobs. - Extracted a runtime-neutral `TranscriptionSession` contract so native and browser inference share capture and application code. - Added model download/compile readiness progress, abortable initialization, @@ -20,13 +32,6 @@ Seda follows semantic versioning. Notable changes are recorded here. test using a checksum-verified speech fixture. - Reworked all browser documentation around complete microphone and Shift-to-talk flows, deployment requirements, model behavior, and error UX. -- Replaced model tiers as the primary interface with exact model ID, immutable - revision, variant, and runtime identity. Profiles remain convenience aliases. -- Moved language selection from preparation and startup to each transcription - or live stream, with fixed, prompted, automatic, and checkpoint capability - semantics. -- Added typed Python, Go, and Swift protocol clients with real Rust-sidecar - HTTP/WebSocket integration coverage in GitHub Actions. ## 0.1.1 diff --git a/Cargo.lock b/Cargo.lock index b6bbcd8..cf67220 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1264,7 +1264,7 @@ checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" [[package]] name = "seda-cli" -version = "0.2.0" +version = "0.3.0" dependencies = [ "anyhow", "axum", @@ -1292,7 +1292,7 @@ dependencies = [ [[package]] name = "seda-core" -version = "0.2.0" +version = "0.3.0" dependencies = [ "async-trait", "axum", @@ -1315,7 +1315,7 @@ dependencies = [ [[package]] name = "seda-parakeet" -version = "0.2.0" +version = "0.3.0" dependencies = [ "libloading", "seda-core", @@ -1326,7 +1326,7 @@ dependencies = [ [[package]] name = "seda-protocol" -version = "0.2.0" +version = "0.3.0" dependencies = [ "serde", "serde_json", diff --git a/Cargo.toml b/Cargo.toml index fcdff76..8965c92 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ members = [ resolver = "2" [workspace.package] -version = "0.2.0" +version = "0.3.0" edition = "2024" rust-version = "1.90" license = "Apache-2.0" diff --git a/README.md b/README.md index fc12ae5..363342e 100644 --- a/README.md +++ b/README.md @@ -44,8 +44,8 @@ GitHub release: ```sh pnpm add \ - https://github.com/bearlyai/seda/releases/download/v0.2.0/bearlyai-seda-0.2.0.tgz \ - https://github.com/bearlyai/seda/releases/download/v0.2.0/bearlyai-seda-browser-0.2.0.tgz + https://github.com/bearlyai/seda/releases/download/v0.3.0/bearlyai-seda-0.3.0.tgz \ + https://github.com/bearlyai/seda/releases/download/v0.3.0/bearlyai-seda-browser-0.3.0.tgz ``` Initialize the model once during application readiness: diff --git a/package.json b/package.json index 4a75bc9..0e67690 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "build:pages": "pnpm build && vite build examples/browser-demo --base /seda/ --outDir ../../dist/pages --emptyOutDir", "check": "pnpm run check:dependency-policy && pnpm --filter @bearlyai/seda check && pnpm --filter @bearlyai/seda build && pnpm --filter @bearlyai/seda-browser check && pnpm --filter @bearlyai/seda-browser build && pnpm --filter @bearlyai/seda-node check && tsc -p tsconfig.browser.json", "check:dependency-policy": "pnpm config list --json | node scripts/check-dependency-policy.mjs", + "check:package-install": "node scripts/check-package-install.mjs", "test": "pnpm --recursive test", "test:browser": "playwright test" }, diff --git a/packages/browser/README.md b/packages/browser/README.md index 304a809..9879a59 100644 --- a/packages/browser/README.md +++ b/packages/browser/README.md @@ -12,8 +12,8 @@ the GitHub release: ```sh pnpm add \ - https://github.com/bearlyai/seda/releases/download/v0.2.0/bearlyai-seda-0.2.0.tgz \ - https://github.com/bearlyai/seda/releases/download/v0.2.0/bearlyai-seda-browser-0.2.0.tgz + https://github.com/bearlyai/seda/releases/download/v0.3.0/bearlyai-seda-0.3.0.tgz \ + https://github.com/bearlyai/seda/releases/download/v0.3.0/bearlyai-seda-browser-0.3.0.tgz ``` Use a normal browser bundler such as Vite, webpack, Parcel, or esbuild. The diff --git a/packages/browser/package.json b/packages/browser/package.json index 4099cc8..4065147 100644 --- a/packages/browser/package.json +++ b/packages/browser/package.json @@ -1,6 +1,6 @@ { "name": "@bearlyai/seda-browser", - "version": "0.2.0", + "version": "0.3.0", "description": "Private, in-browser speech recognition for Seda using WebGPU or WASM", "type": "module", "license": "Apache-2.0", @@ -21,10 +21,11 @@ "check": "tsc -p tsconfig.json --noEmit", "test": "vitest run" }, - "dependencies": { - "@bearlyai/seda": "workspace:*" + "peerDependencies": { + "@bearlyai/seda": "^0.3.0" }, "devDependencies": { + "@bearlyai/seda": "workspace:*", "@huggingface/transformers": "3.7.6", "@webgpu/types": "0.1.69", "esbuild": "0.28.1", diff --git a/packages/browser/src/browser.ts b/packages/browser/src/browser.ts index 0ac3d79..5f9c07d 100644 --- a/packages/browser/src/browser.ts +++ b/packages/browser/src/browser.ts @@ -15,7 +15,7 @@ import type { } from "./types.js"; import { InferenceWorker } from "./worker-host.js"; -const VERSION = "0.2.0"; +const VERSION = "0.3.0"; const PROTOCOL = 1; export class SedaBrowser { diff --git a/packages/client/README.md b/packages/client/README.md index 33e4de4..657fb67 100644 --- a/packages/client/README.md +++ b/packages/client/README.md @@ -9,7 +9,7 @@ Until npm trusted publishing is configured, install the package attached to the GitHub release: ```sh -pnpm add https://github.com/bearlyai/seda/releases/download/v0.2.0/bearlyai-seda-0.2.0.tgz +pnpm add https://github.com/bearlyai/seda/releases/download/v0.3.0/bearlyai-seda-0.3.0.tgz ``` Start the native companion with your exact page origin: diff --git a/packages/client/package.json b/packages/client/package.json index fb6ba56..6a03a95 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -1,6 +1,6 @@ { "name": "@bearlyai/seda", - "version": "0.2.0", + "version": "0.3.0", "description": "Typed browser and Node client for the Seda local speech service", "type": "module", "license": "Apache-2.0", diff --git a/packages/node/README.md b/packages/node/README.md index 4b2d36b..4ec95b0 100644 --- a/packages/node/README.md +++ b/packages/node/README.md @@ -9,8 +9,8 @@ the GitHub release: ```sh pnpm add \ - https://github.com/bearlyai/seda/releases/download/v0.2.0/bearlyai-seda-0.2.0.tgz \ - https://github.com/bearlyai/seda/releases/download/v0.2.0/bearlyai-seda-node-0.2.0.tgz + https://github.com/bearlyai/seda/releases/download/v0.3.0/bearlyai-seda-0.3.0.tgz \ + https://github.com/bearlyai/seda/releases/download/v0.3.0/bearlyai-seda-node-0.3.0.tgz ``` Install the matching `seda` binary from the same release and put it on `PATH`, diff --git a/packages/node/package.json b/packages/node/package.json index e70e019..52a0fc6 100644 --- a/packages/node/package.json +++ b/packages/node/package.json @@ -1,6 +1,6 @@ { "name": "@bearlyai/seda-node", - "version": "0.2.0", + "version": "0.3.0", "description": "Lifecycle-managed Seda sidecar for Node and Electron", "type": "module", "license": "Apache-2.0", @@ -21,10 +21,13 @@ "test": "vitest run" }, "dependencies": { - "@bearlyai/seda": "workspace:*", "ws": "^8.18.2" }, + "peerDependencies": { + "@bearlyai/seda": "^0.3.0" + }, "devDependencies": { + "@bearlyai/seda": "workspace:*", "@types/node": "^24.0.3", "@types/ws": "^8.18.1", "typescript": "^5.8.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 325f4b8..4f51f24 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5,6 +5,7 @@ settings: excludeLinksFromLockfile: false overrides: + nanoid: 5.1.16 sharp: 0.35.3 importers: @@ -25,11 +26,10 @@ importers: version: 7.3.6(@types/node@24.13.3) packages/browser: - dependencies: + devDependencies: '@bearlyai/seda': specifier: workspace:* version: link:../client - devDependencies: '@huggingface/transformers': specifier: 3.7.6 version: 3.7.6(@types/node@24.13.3) @@ -66,13 +66,13 @@ importers: packages/node: dependencies: - '@bearlyai/seda': - specifier: workspace:* - version: link:../client ws: specifier: ^8.18.2 version: 8.21.1 devDependencies: + '@bearlyai/seda': + specifier: workspace:* + version: link:../client '@types/node': specifier: ^24.0.3 version: 24.13.3 @@ -834,9 +834,9 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - nanoid@3.3.16: - resolution: {integrity: sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + nanoid@5.1.16: + resolution: {integrity: sha512-kVrnsrJqMR8+oLJnGEmSWw9BivK5mt7H3FZatVRjrc5wGqFYuBxX1yG7+A7Gi5AefkX6t/oCkizcQgpu0cY1dQ==} + engines: {node: ^18 || >=20} hasBin: true object-keys@1.1.1: @@ -1691,7 +1691,7 @@ snapshots: ms@2.1.3: {} - nanoid@3.3.16: {} + nanoid@5.1.16: {} object-keys@1.1.1: {} @@ -1736,7 +1736,7 @@ snapshots: postcss@8.5.21: dependencies: - nanoid: 3.3.16 + nanoid: 5.1.16 picocolors: 1.1.1 source-map-js: 1.2.1 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 6d7a92f..4c1c9d2 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -9,6 +9,9 @@ minimumReleaseAgeStrict: true trustLockfile: false overrides: + # Vite/PostCSS uses only nanoid's stable top-level API. Pin the already-aged, + # unaffected ESM release while the new 3.x security patch is quarantined. + nanoid: "5.1.16" sharp: "0.35.3" allowBuilds: diff --git a/scripts/check-package-install.mjs b/scripts/check-package-install.mjs new file mode 100644 index 0000000..26cff1a --- /dev/null +++ b/scripts/check-package-install.mjs @@ -0,0 +1,81 @@ +import { mkdtemp, mkdir, readFile, rm, writeFile } from "node:fs/promises"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; +import { spawnSync } from "node:child_process"; + +const packageManager = process.env.npm_execpath; +if (!packageManager) { + throw new Error("Run this check through pnpm."); +} + +const rootPackage = JSON.parse(await readFile(new URL("../package.json", import.meta.url), "utf8")); +const clientPackage = JSON.parse(await readFile(new URL("../packages/client/package.json", import.meta.url), "utf8")); +const packageManagerVersion = rootPackage.packageManager; +const packageVersion = clientPackage.version; +const directory = await mkdtemp(join(tmpdir(), "seda-package-install-")); +const packedDirectory = join(directory, "packed"); + +const runPnpm = (args, cwd = new URL("..", import.meta.url)) => { + const result = spawnSync(process.execPath, [packageManager, ...args], { + cwd, + encoding: "utf8", + stdio: "pipe", + }); + if (result.status !== 0) { + throw new Error([result.stdout, result.stderr].filter(Boolean).join("\n")); + } +}; + +try { + await mkdir(packedDirectory); + for (const packageName of [ + "@bearlyai/seda", + "@bearlyai/seda-browser", + "@bearlyai/seda-node", + ]) { + runPnpm(["--filter", packageName, "pack", "--pack-destination", packedDirectory]); + } + + const packages = ["bearlyai-seda", "bearlyai-seda-browser", "bearlyai-seda-node"]; + await writeFile( + join(directory, "package.json"), + JSON.stringify( + { + name: "seda-package-install-check", + private: true, + type: "module", + packageManager: packageManagerVersion, + dependencies: Object.fromEntries( + packages.map((name) => [ + name === "bearlyai-seda" + ? "@bearlyai/seda" + : `@bearlyai/${name.replace("bearlyai-seda-", "seda-")}`, + `file:${join(packedDirectory, `${name}-${packageVersion}.tgz`)}`, + ]), + ), + }, + null, + 2, + ), + ); + await writeFile( + join(directory, "pnpm-workspace.yaml"), + "blockExoticSubdeps: true\nstrictDepBuilds: true\n", + ); + + runPnpm(["install"], directory); + const imported = spawnSync( + process.execPath, + [ + "--input-type=module", + "--eval", + 'await Promise.all([import("@bearlyai/seda"), import("@bearlyai/seda-browser"), import("@bearlyai/seda-node")]);', + ], + { cwd: directory, encoding: "utf8", stdio: "pipe" }, + ); + if (imported.status !== 0) { + throw new Error([imported.stdout, imported.stderr].filter(Boolean).join("\n")); + } +} finally { + await rm(directory, { recursive: true, force: true }); +} diff --git a/sdks/python/pyproject.toml b/sdks/python/pyproject.toml index fee4ca0..6de67d8 100644 --- a/sdks/python/pyproject.toml +++ b/sdks/python/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "bearlyai-seda" -version = "0.2.0" +version = "0.3.0" description = "Typed Python client for the local Seda speech runtime" readme = "README.md" requires-python = ">=3.11" diff --git a/sdks/swift/README.md b/sdks/swift/README.md index 2680acf..a1bd5db 100644 --- a/sdks/swift/README.md +++ b/sdks/swift/README.md @@ -8,7 +8,7 @@ iOS 16+. Add the package and link the `Seda` product: ```swift -.package(url: "https://github.com/bearlyai/seda.git", from: "0.2.0") +.package(url: "https://github.com/bearlyai/seda.git", from: "0.3.0") ``` On macOS, prepare and launch the helper by exact model ID: