diff --git a/README.md b/README.md index d6737ba1..ad6be516 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ The dev runner builds **Inlay Dev**, with separate settings and visible Dev labe ## Get started on one Mac -You need Apple Silicon, macOS 14+, full Xcode 26+ with the Metal compiler, Bun 1.4.2, CMake, and Git. Xcode provides Swift; the client/MLX build requires Swift 6.2+. Bun manages JavaScript dependencies and builds standalone server executables. +The app runs on Apple Silicon and macOS 14 or later. `Package.swift` and `LSMinimumSystemVersion` both set that floor to 14.0. Building requires a Mac: `scripts/build-app.sh` exits on Linux and other systems. The build needs full Xcode 26 or later, including the Metal compiler, because the client and the MLX helper require Swift 6.2+. You also need Bun 1.4.2, CMake, and Git. Xcode provides Swift. Bun manages JavaScript dependencies and builds standalone server executables. Linux can build and run the server; it cannot build `Inlay.app`. ```sh git clone --recurse-submodules https://github.com/davis7dotsh/inlay.git @@ -23,7 +23,7 @@ export INLAY_TEXT_MODEL="$PWD/.local/models/Qwen3-4B-Instruct-2507-MLX-4bit" Use your own model paths if they are already installed. The script builds the server and client, starts **http://localhost:8391**, and opens `build/Inlay Dev.app`. The first build fetches dependencies and the small Silero speech detector. -1. Grant **Inlay Dev** Microphone and Accessibility permissions. +1. Grant **Inlay Dev** Microphone and Accessibility. The window treats those two as required. Accessibility also listens for the dictation key, so do not add a separate Input Monitoring grant. Microphone is under **System Settings → Privacy & Security → Microphone**. Accessibility is under **Privacy & Security → Accessibility**, except on macOS 27 and later, where that list is **Privacy & Security → Device Control and Data Access**. If the server is on another machine, allow **Local Network** when macOS asks. 2. Wait for the server to be ready. Focus a text field, hold **Right Option**, speak, and release. 3. Change the shortcut under **This Mac**, choose inputs under **Microphone**, and edit shared cleanup instructions or dictionary entries under **Server preferences**. @@ -61,7 +61,14 @@ bun install --frozen-lockfile bun run dev ``` -This listens on `127.0.0.1:8392`, uses `.local/dev-server/data`, and creates a private token file at `.local/dev-server/token`. Set the model-path exports above and build the native helpers once with `./scripts/build-server.sh` for dictation. Without helpers/models, the server still starts and health reports unavailable inference. On the same Mac, open [server liveness](http://localhost:8392/v1/liveness). +This listens on `127.0.0.1:8392`, uses `.local/dev-server/data`, and creates a private token file at `.local/dev-server/token`. Build the native helpers once with `./scripts/build-server.sh` for dictation. On macOS, export the Parakeet and MLX paths from the Mac setup above. On Linux, keep the Parakeet path and point `INLAY_TEXT_MODEL` at the GGUF file instead: + +```sh +export INLAY_SPEECH_MODEL="$PWD/.local/models/ggml-parakeet-tdt-0.6b-v3-f16.bin" +export INLAY_TEXT_MODEL="$PWD/.local/models/Qwen3-4B-Instruct-2507-Q4_K_M.gguf" +``` + +The MLX directory does not run on Linux. If those variables are unset, `bun run dev` looks under `~/Library/Application Support/Inlay/Models` and `~/.inlay/models` on macOS, and under `.local/models` and `.local/dev-server/models` on Linux. Without helpers or models, the server still starts and health reports unavailable inference. On the same Mac, open [server liveness](http://localhost:8392/v1/liveness). ```sh bun run fmt @@ -78,10 +85,10 @@ For the packaged Mac app and server: ./scripts/run-dev.sh start --skip-build # Start existing builds ./scripts/run-dev.sh status ./scripts/run-dev.sh stop -./scripts/run-dev.sh restart # Rebuild and restart the server +./scripts/run-dev.sh restart # Rebuild the server and Mac client, then restart ``` -Keep the model-path exports set when starting the server. After rebuilding an already-open client, quit and reopen it to load the new executable. Signing uses an available Apple Development identity or ad-hoc signing; ad-hoc rebuilds may require granting permissions again. +Keep `INLAY_SPEECH_MODEL` and `INLAY_TEXT_MODEL` set when starting the server. On Linux, `INLAY_TEXT_MODEL` must be the GGUF file, and `run-dev.sh` builds and starts the server without the app. After rebuilding an already-open client, quit and reopen it to load the new executable. `scripts/build-app.sh` signs with `INLAY_SIGNING_IDENTITY` when that is set. Otherwise it uses the Apple Development identity only when exactly one is installed, and ad-hoc signs in every other case. Ad-hoc rebuilds may require granting permissions again. A plain build does not notarize the app; notarization is the `--dist` distribution build described under [Releases](#releases). The dev runner stores shared history/settings in `.local/server`, device preferences in `.local/client`, and logs in `.local/server.log`. Keep experiment notes and generated artifacts under the ignored `.local/` directory too. Quitting the app leaves the server running. Recordings require an online, available server and have a three-minute limit. @@ -89,6 +96,10 @@ For newly launched Electron apps, Inlay requests accessibility support when a ta All connected Macs share history, tagged by device. Both original and inference audio are kept by default; **Keep original microphone audio** changes original retention for future takes. Back up the server data directory to preserve history. +## Releases + +GitHub Releases come from tags: a `client-v*` tag publishes the notarized `Inlay.dmg` from the `Client release package` workflow, and a `server-v*` tag publishes the server tarballs from `Server release packages`. Manual workflow runs upload Actions artifacts instead of publishing a release. You can also build the Mac app locally with `./scripts/build-app.sh` and copy `build/Inlay.app` where you want it. Pull-request CI builds the Mac app bundle to verify it, but not the MLX helper or the CUDA package, and publishes nothing. Details, artifact names, and checksums are in [how releases are produced](Server/README.md#releases). + ## Reference - [Server setup and models](Server/README.md) diff --git a/Server/README.md b/Server/README.md index 4e969b1e..88b4d05a 100644 --- a/Server/README.md +++ b/Server/README.md @@ -9,7 +9,9 @@ The server is an independent TypeScript/Fastify HTTP process that owns models, s ## Linux -The `Server release packages` workflow builds `inlay-server-linux-x64-cuda.tar.gz` as a workflow artifact on `server-v*` tags and manual dispatch. Download the matching `server-v*` package from [GitHub Releases](https://github.com/davis7dotsh/inlay/releases) and verify it against the published `.sha256` before extracting. The package targets SM 80, 86, 89, 90, 120, and 121; Tesla T4 and RTX 20-series (SM 75) will not run it. The helpers link the CUDA runtime statically and load `libcuda.so.1` from the host driver, which must be 580.95.05 or newer for CUDA 13.0.2. Keep model weights outside the package. +The [Server release packages](#releases) workflow builds tarballs on `server-v*` tags and manual dispatch. Tag runs publish them to a GitHub Release; manual runs upload them as Actions artifacts only. CPU packages are `inlay-server-linux-x64-cpu.tar.gz` and `inlay-server-linux-arm64-cpu.tar.gz`. The CUDA package is `inlay-server-linux-x64-cuda.tar.gz`. There is no ARM CUDA package. Download the matching `server-v*` package from [GitHub Releases](https://github.com/davis7dotsh/inlay/releases) and verify it against the published `.sha256` before extracting. CPU and CUDA packages install the same way; the commands below use the CUDA filename. + +The CUDA package targets SM 80, 86, 89, 90, 120, and 121. Tesla T4 and RTX 20-series (SM 75) will not run it. The helpers link the CUDA runtime statically and load `libcuda.so.1` from the host driver, which must be 580.95.05 or newer for CUDA 13.0.2. Keep model weights outside the package. The CPU packages do not use the GPU. The unit runs as the `inlay` user and listens on `127.0.0.1:8391`. For remote clients, put it behind an HTTPS reverse proxy or bind it to the host's Tailscale IP with a `sudo systemctl edit inlay-server` override (`Environment=INLAY_SERVER_HOST=100.x.y.z`); see [remote access](#remote-access). The `inlay` user must be able to open the host NVIDIA device nodes; if they are group-accessible only, add `inlay` to that group (usually `render` or `video`). @@ -47,7 +49,7 @@ Run these commands from the repository root. Weights use about 4 GB of disk; run INLAY_MODEL_DIR="$PWD/.local/models" ./scripts/download-model.sh ``` -This installs and verifies `ggml-parakeet-tdt-0.6b-v3-f16.bin`. The URL, revision, and checksum are pinned in `scripts/download-model.sh` and `Sources/InlayCore/SpeechModel.swift`. The server build separately downloads the pinned Silero VAD model. Existing Whisper weights cannot be reused; see [upgrade guidance](../README.md#upgrade-an-existing-installation). +This installs and verifies `ggml-parakeet-tdt-0.6b-v3-f16.bin`. The download URL and revision are pinned in `scripts/download-model.sh`; sizes and checksums live in `Server/api/model-pins.json`, the source for the generated `Server/src/generated/model-pins.ts` and `Sources/InlayCore/GeneratedModelPins.swift` (used through `Sources/InlayCore/SpeechModel.swift`). The packaged TypeScript server checks the generated pins before it loads weights. The server build separately downloads the pinned Silero VAD model. Existing Whisper weights cannot be reused; see [upgrade guidance](../README.md#upgrade-an-existing-installation). Parakeet automatically recognizes 25 European languages. The language preference guides proofreading and does not force recognition. The preference values are unchanged; choose Automatic for languages without a named proofreading option. The helper exposes no detected language ID. Parakeet takes no recognition vocabulary; dictionary replacements and Qwen hints still apply. Older language preferences remain accepted for proofreading and never block automatic recognition; they do not expand Parakeet’s supported speech languages. @@ -94,9 +96,30 @@ bun run build:server # Native coordinator in build/server bun run build:server --all # Mac arm64, Linux x64 and Linux arm64 ``` -Cross builds live under `build/server-coordinators`. Bun cross-compiles the coordinator; complete installation archives combine it with helpers built on each matching platform. Installed packages need neither Bun nor Node. Full Linux release packages target Ubuntu 24.04 or a compatible glibc/libstdc++ environment; Mac packages require Apple Silicon and macOS 14+. Linux x64 coordinators use Bun's baseline CPU target. Native helper CPU/CUDA compatibility remains determined by its CMake build flags. +Cross builds live under `build/server-coordinators`. Bun cross-compiles the coordinator; complete installation archives combine it with helpers built on each matching platform. Installed packages need neither Bun nor Node. Full Linux packages target Ubuntu 24.04 or a compatible glibc/libstdc++ environment. Mac server packages require Apple Silicon and macOS 14+. Linux x64 coordinators use Bun's baseline CPU target. Native helper CPU/CUDA compatibility remains determined by its CMake build flags. + +Server [releases](#releases) do not include `Inlay.app`; the client ships from its own release workflow. Extract a package, keep its `server` directory together, install the pinned model weights separately, then use the arguments below. + +## Releases + +Two tag-triggered workflows publish GitHub Releases. A `server-v*` tag releases the server tarballs below; a `client-v*` tag releases the notarized `Inlay.dmg` built by [`.github/workflows/client-release.yml`](../.github/workflows/client-release.yml) (`Client release package`, `./scripts/build-app.sh --with-server --dist` on `macos-26`). Running either workflow manually uploads the same builds as Actions artifacts and publishes nothing. You can also copy `build/Inlay.app` from a local `./scripts/build-app.sh` run. + +[`.github/workflows/server-release.yml`](../.github/workflows/server-release.yml) (`Server release packages`) runs when a tag matching `server-v*` is pushed, or when someone starts it with `workflow_dispatch`. The build jobs run with `contents: read` and upload artifacts; on tag runs, a separate publish job with `contents: write` creates or updates the GitHub Release with every tarball and checksum. Each artifact is a zip of one tarball plus a `shasum -a 256` checksum file. Retention is the repository default. The tarball's top directory is `server`: the executable, native helpers, Silero VAD, notices, and on Linux `inlay-server.service`. + +| Artifact | Build | +| ------------------------------ | --------------------------------------------------------- | +| `inlay-server-darwin-arm64` | `./scripts/build-server.sh` on the `macos-26` runner | +| `inlay-server-linux-x64-cpu` | `./scripts/build-server.sh` on `ubuntu-24.04` | +| `inlay-server-linux-arm64-cpu` | `./scripts/build-server.sh` on `ubuntu-24.04-arm` | +| `inlay-server-linux-x64-cuda` | `docker build -f Server/Dockerfile --target cuda-package` | + +The three `build-server.sh` jobs set `INLAY_NATIVE=OFF`, `INLAY_CUDA=OFF`, and `INLAY_BUILD_JOBS=4`. Linux jobs install CMake, a C/C++ toolchain, pkg-config, and libcurl headers first. The Mac job downloads the Metal toolchain (`xcodebuild -downloadComponent MetalToolchain`) and then ad-hoc signs the helpers and `inlay-server`. The server binary is signed with `Server/entitlements.plist` so Bun can JIT. That is not Developer ID signing, not notarization, and not `Inlay.app`. `Inlay.app` uses `Resources/Inlay.entitlements` (microphone) and is signed by `scripts/build-app.sh`; only its `--with-server --dist` mode performs Developer ID signing and notarization, as in the client release workflow. + +The CUDA job does not run `bun run check`, `bun run lint`, or `bun run fmt:check` before the image build. The other three jobs do. CUDA architectures come from the Dockerfile default `80;86;89;90;120;121`. + +Pull-request CI is [`.github/workflows/server.yml`](../.github/workflows/server.yml). On every pull request and on pushes to `main` it runs formatting, lint, and TypeScript checks; compiles the Swift packages on `macos-26` without launching the app; cross-compiles Bun coordinators; builds complete Linux CPU packages; and builds `Inlay.app` with `./scripts/build-app.sh`, verifying the bundle's signature and metadata. `swift build` does not compile the MLX Metal helper. This workflow does not build the Mac server package or the CUDA package, and it does not publish anything. -The release workflow produces complete platform tarballs and SHA-256 checksums, including the Linux CUDA package above. Extract a package, retain its `server` directory together, install the pinned model weights separately, then use the arguments below. Developer ID distribution still requires signing/notarization credentials; the draft Mac build is ad-hoc signed with Bun's executable entitlements. +For a tagged release, download the tarball from the GitHub Release; for a manual run, download the artifact from the workflow run and unzip it. Either way, check the `.sha256` file, then extract the tarball as in [Linux](#linux). Model weights stay outside the package. The archive lock uses Bun FFI to call libc `flock`, matching the reference Swift server. The lock is held for the server process lifetime. A running Swift server and Bun server must never share a data directory. @@ -123,7 +146,7 @@ On Linux, replace the last path with the GGUF file. Add `--dev` for a developmen Check `curl http://localhost:8391/v1/liveness` for reachability; for readiness detail use the app, or `curl -H "Authorization: Bearer " http://localhost:8391/v1/health`. HTTP reachability alone does not mean inference is available. The `ready` field means the server can accept a recording, including while other recordings are uploading or processing. Finished uploads queue for inference: each helper stage (speech, proofreading) runs one job at a time, but different jobs overlap across stages, so one take can be proofread while the next is transcribed. Model runtime fields separately report whether helpers are loaded. Quitting a client does not stop this process. On macOS, `./scripts/install-service.sh` installs a LaunchAgent (see above); elsewhere, use systemd or container supervision for boot/restart behavior. -For server-only development alongside an installed Inlay instance, use `--port 8392 --data-dir "$PWD/.local/typescript-server" --dev` with your helper/model arguments. Start the executable directly or use `bun run dev:server` with those arguments. The client dev runner starts the app and defaults to port 8391; avoid it when preserving a running installation. +`bun run dev` is the hot-reloading source server and already isolates itself on port 8392 under `.local/dev-server`. `bun run dev:server` runs `Server/src/main.ts` without those defaults: pass `--host`, `--port`, `--data-dir`, the helper paths, and the model paths yourself, or start `./build/server/inlay-server` the same way. Do not reuse `.local/typescript-server`; that directory is not a current default. The client dev runner (`./scripts/run-dev.sh`) binds `127.0.0.1` on port 8391 and uses `.local/server`. Avoid it when preserving a running installation. | Argument | Environment variable | | ----------------------------------- | -------------------------------------------------- | diff --git a/docs/architecture.md b/docs/architecture.md index 828bccb8..137237b5 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -1,6 +1,6 @@ # Architecture -Inlay's native Swift macOS client handles microphone capture, shortcuts, and cursor insertion. An independent TypeScript/Fastify server, compiled with Bun, owns inference, shared settings, and history. Both processes use the same OpenAPI v1 contract whether they run on one machine or across the network. +Inlay's native Swift macOS client handles microphone capture, shortcuts, and cursor insertion. An independent TypeScript/Fastify server, compiled with Bun, owns inference, shared settings, and history. Both processes use API version 4. The contract is `Server/api/openapi.yaml` (OpenAPI 3.1). HTTP paths stay under `/v1`, and the client requires `apiVersion` 4 before dictation. The same contract applies on one machine or across the network. ## Code map @@ -57,7 +57,7 @@ The regular app uses `~/Library/Application Support/Inlay`; Dev uses `~/Library/ ## Storage -The server's `--data-dir` (normally `.local/server` in development) contains: +The server's `--data-dir` contains the layout below. `./scripts/run-dev.sh` uses `.local/server`. `bun run dev` uses `.local/dev-server/data` and ignores an inherited `INLAY_SERVER_DATA_DIR`. An installed Linux service uses `/var/lib/inlay`. ```text preferences.json diff --git a/docs/development.md b/docs/development.md index 6d38d64f..47a7b688 100644 --- a/docs/development.md +++ b/docs/development.md @@ -16,13 +16,13 @@ bun run dev - The launcher ignores inherited `INLAY_SERVER_DATA_DIR` settings. Select another development archive explicitly with `--data-dir`. - A private token is created once at `.local/dev-server/token` and reused on reload. Do not print or commit its value. Use the token in the native client's server settings; `INLAY_SERVER_TOKEN_FILE` or `--token-file` can select an existing token file. - On the same Mac, open [server liveness](http://localhost:8392/v1/liveness) in the collaborative browser. For another machine, discover its current Tailscale hostname/address and use the selected port; follow [remote access](../Server/README.md#remote-access) for HTTPS and token setup. -- The server starts without native assets and reports `ready: false`. To enable dictation, follow [model setup](../Server/README.md#models), set `INLAY_SPEECH_MODEL` to the pinned Parakeet v3 `.bin` and `INLAY_TEXT_MODEL` to the Qwen model, and run `./scripts/build-server.sh` once to build the real helpers and VAD. Existing helpers can be selected with `INLAY_ENGINE_PATH`, `INLAY_TEXT_ENGINE_PATH`, and `INLAY_VAD_PATH`. +- The server starts without native assets and reports `ready: false`. To enable dictation, follow [model setup](../Server/README.md#models), set `INLAY_SPEECH_MODEL` to the pinned Parakeet v3 `.bin`, and set `INLAY_TEXT_MODEL` to the Qwen MLX directory on macOS or the Qwen GGUF file on Linux. Then run `./scripts/build-server.sh` once to build the real helpers and VAD. Existing helpers can be selected with `INLAY_ENGINE_PATH`, `INLAY_TEXT_ENGINE_PATH`, and `INLAY_VAD_PATH`. The MLX directory does not run on Linux. - Pass normal server arguments to override defaults, for example `bun run dev --port 8393 --data-dir "$PWD/.local/another-dev-archive"`. Use `bun run dev --help` for arguments. Keep model files outside Git. ## Native app - Inlay has no browser UI. Browser-origin API requests are rejected; do not weaken that policy to create a verification shortcut. -- On an Apple Silicon Mac with Xcode 26+ and Swift 6.2+, run `./scripts/build-dev-app.sh`. Launch `build/Inlay Dev.app` with `INLAY_CLIENT_DATA_DIR` set to a new workspace-local client directory, so its preferences and credentials remain separate from the regular app: +- The deployment target is macOS 14. Building the app requires an Apple Silicon Mac, full Xcode 26 or later, and Swift 6.2+. `./scripts/build-app.sh` and `./scripts/build-dev-app.sh` exit on Linux. On a Mac, run `./scripts/build-dev-app.sh`. Launch `build/Inlay Dev.app` with `INLAY_CLIENT_DATA_DIR` set to a new workspace-local client directory, so its preferences and credentials remain separate from the regular app: ```sh mkdir -p .local/dev-client @@ -32,7 +32,7 @@ open --env "INLAY_CLIENT_DATA_DIR=$PWD/.local/dev-client" "build/Inlay Dev.app" - Under **This Mac**, select `http://localhost:8392` and the development server's token. For a server on another machine, the client requires HTTPS for remote hostnames; on the connected tailnet, a literal Tailscale IP may use HTTP. - With `INLAY_CLIENT_DATA_DIR` set, Inlay Dev keeps temporary recordings and previews under that directory too, separate from other running Inlay apps. -- Grant **Inlay Dev** Microphone and Accessibility permissions. Use **Test microphone** for an in-app transcript; use the recording shortcut in a separate editable app to verify insertion. +- Grant **Inlay Dev** Microphone and Accessibility. Those are the only permissions the window requires. Accessibility also covers the dictation key; do not grant Input Monitoring separately. On macOS 27 and later the Accessibility list is **System Settings → Privacy & Security → Device Control and Data Access**. Earlier versions keep it under **Privacy & Security → Accessibility**. If the server is on another machine, allow Local Network when macOS asks. Use **Test microphone** for an in-app transcript; use the recording shortcut in a separate editable app to verify insertion. - `./scripts/run-dev.sh` remains available to build/start the packaged server and Mac client together. It uses port 8391 by default; choose an unused `INLAY_SERVER_PORT` and a separate archive before using it alongside an existing installation. Do not stop or restart an existing server without authorization. ## Computer-use verification diff --git a/docs/typescript-server-plan.md b/docs/typescript-server-plan.md index cb3777c9..b0192030 100644 --- a/docs/typescript-server-plan.md +++ b/docs/typescript-server-plan.md @@ -1,6 +1,8 @@ # Bun TypeScript server implementation plan -Keep the native Swift client and replace the packaged HTTP coordinator with TypeScript, Fastify, and a Bun executable. Preserve API v1, existing archive layout, text behavior, and native inference helpers. The reference Swift server and domain packages remain available for source comparison. Verification follows [the development guide](development.md); automated tests are not allowed. +This is the historical plan for replacing the packaged coordinator. It is not the current setup. The shipped server is `Server/`. The API version is 4, with routes still under `/v1`. Speech recognition is Parakeet, not Whisper. Current development uses [the development guide](development.md): `bun run dev` on port 8392 with data in `.local/dev-server`. Do not follow the API v1, Whisper, or `.local/typescript-server` notes below as present-day instructions. + +Keep the native Swift client and replace the packaged HTTP coordinator with TypeScript, Fastify, and a Bun executable. The plan below was written to preserve the then-current API, archive layout, text behavior, and native inference helpers. The reference Swift server and domain packages remained available for source comparison at the time; the Swift server has since been deleted. Verification follows [the development guide](development.md); automated tests are not allowed. ## Phase 1: Contract and project foundation @@ -29,7 +31,7 @@ typeOverrides: ## Phase 3: Native inference and durable coordinator -- Supervise existing Whisper and Qwen helpers with fixed argument arrays, bounded JSON-lines parsing, one outstanding request per helper, readiness, warm reuse, deadlines, output validation, and stale-process generation guards. +- Supervise the speech and Qwen helpers with fixed argument arrays, bounded JSON-lines parsing, one outstanding request per helper, readiness, warm reuse, deadlines, output validation, and stale-process generation guards. The shipped speech helper is Parakeet. - Preserve pinned model verification, optional proofreading fallback, and cancellation by terminating/replacing busy helpers. Preserve idle warm helpers on cancellation. - Port generation admission, per-device request idempotency, preference compare-and-swap revisions, chunk sequence/replay validation, finite samples, exact final frame counts, WAV sealing, disk checks, and serial FIFO processing. - Keep private file permissions, exclusive directory ownership, atomic metadata writes, paginated shared history, allowlisted artifacts, restart recovery, upload expiry, and Wispr Flow staging/reconciliation. @@ -52,6 +54,6 @@ typeOverrides: ## Intended result - Bun-managed Fastify server and standalone coordinators for the supported platforms. -- Full v1 contract with generated TypeScript and Swift transport models. +- The contract at the time of the plan, with generated TypeScript and Swift transport models. The shipped health field is API version 4. - Native Swift client behavior, native model helpers, and archive compatibility preserved. - Isolated verified draft, independent reviews, committed branch, and a green PR. diff --git a/docs/typescript-server-validation.md b/docs/typescript-server-validation.md index 695e2d8f..1a3d1301 100644 --- a/docs/typescript-server-validation.md +++ b/docs/typescript-server-validation.md @@ -1,7 +1,7 @@ # TypeScript server verification - Run `bun run check` for strict TypeScript and generated TypeScript/OpenAPI consistency, `bun run lint` for type-aware correctness, and `bun run fmt:check` for formatting. -- Verify generated Swift bindings with `bun run generate:api --check` and compile with `swift build --force-resolved-versions` on macOS with Swift 6.2+. CI also compiles standalone coordinators and complete CPU packages for supported platforms. +- Verify generated Swift bindings with `bun run generate:api --check` and compile with `swift build --force-resolved-versions` on macOS with Swift 6.2+. Pull-request CI compiles the Swift packages on `macos-26` (that `swift build` does not build the MLX helper), builds `Inlay.app` with `scripts/build-app.sh` and verifies the bundle, cross-compiles Bun coordinators for Apple Silicon and Linux, and builds complete Linux CPU packages. The Mac server package and the CUDA package are built only by [the release workflows](../Server/README.md#releases). - Start an isolated source instance with `bun run dev` and follow [the development guide](development.md) to verify changed behavior with computer use in **Inlay Dev**. Automated tests, fixtures, and smoke harnesses are not allowed. - Native helpers, Metal assets, and pinned model weights are required for real dictation. A reachable health endpoint with `ready: false` proves only that the HTTP server is running. - Linux packages target Ubuntu 24.04 or compatible glibc environments; the x64 coordinator uses Bun's baseline CPU target. CUDA, macOS signing/notarization, and native UI behavior require verification on suitable hardware with the necessary credentials. diff --git a/docs/wispr-flow-import-plan.md b/docs/wispr-flow-import-plan.md index e84e918f..86771b76 100644 --- a/docs/wispr-flow-import-plan.md +++ b/docs/wispr-flow-import-plan.md @@ -1,5 +1,7 @@ # Import Wispr Flow history into Inlay +The import path described here is already implemented. Live routes are in `Server/src/http-server.ts` and `Server/src/imports.ts`. The Mac reader is `Sources/Inlay/WisprFlowSourceReader.swift`, and History launches it from `Sources/Inlay/Views/HistoryPage.swift`. The reference Swift server (`Sources/InlayServerKit`) has been deleted; do not add a second import implementation. The sections below are the design record. + The current feature reads the local Wispr Flow database and its complete backups. It previews the recoverable rows, then imports only after an explicit click. The import archives source fields and media without running Inlay's models or changing Wispr Flow. Choosing an arbitrary SQLite file or ingesting an account export remains future work. ## Goal and source @@ -44,7 +46,7 @@ Keep Wispr Flow dictionary state as an import artifact. Any change to Inlay's ac ## Phase 3 — server import path and safe reruns -The Wispr import routes live in the TypeScript server (`Server/src/http-server.ts`, `Server/src/imports.ts`); the Swift reference server was deleted in Batch 8. +The packaged server implements the import routes in [`http-server.ts`](../Server/src/http-server.ts) and [`imports.ts`](../Server/src/imports.ts); the Swift reference server that originally held the same shape was deleted in Batch 8. The existing `POST /v1/generations` and audio/finish routes require a live recording and model readiness, so they must not be reused for historical rows. The server cannot open a client-side Wispr Flow path, especially when it runs on another machine. Use a bounded per-session protocol: send a small manifest and display text, upload allowlisted files with byte counts/checksums, then commit. Validate source ID, dates, text sizes, file signatures, attachment limits, and checksums on the server. Place files in a private staging directory, write metadata last, atomically move the complete directory under `generations//`, then publish it in memory. Extend the artifact endpoint's allowlist for typed imported files; never accept arbitrary filesystem paths from the client.