From 5f54d6c7e785063626bcb1545166cb63fb1d67c9 Mon Sep 17 00:00:00 2001 From: ancientcomputing Date: Wed, 23 Sep 2026 19:45:24 -0700 Subject: [PATCH 1/4] CHANGELOG: 1.0.0 GA (unreleased) - preflight size fix Preflight took the download size from the Hub's usedStorage, which counts every revision's blobs, so re-uploaded repos (mlx-community/Qwen3.8-27B-8bit: 58.1 GB vs 29.5 GB of files) were rejected on a 64 GB Mac. Now sums file sizes. Co-Authored-By: Claude Sonnet 5 --- CHANGELOG.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d92c38c..cf3e8f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,20 @@ recompiling. A breaking change waits for 2.0. (Before RC.1, `1.0.0-beta.N` and e beta.4 → RC.1 changes that can break a build are listed under *Changed — breaking (pre-GA)* in the RC.1 entry, and each entry's own "Beta caveats" apply to the betas.) +## 1.0.0 — GA (unreleased) + +Fixes only; no API change. + +### Fixed + +- **Preflight rejected models that fit in memory** (`MLXModelProvider.validate(_:)`, stages + `sizeVsMemory` and `diskSpace`). The download size came from the Hub's repo-level `usedStorage`, which + counts blobs from every revision, so a re-uploaded repo reported about twice its real size — + `mlx-community/Qwen3.8-27B-8bit` read as 58.1 GB against 29.5 GB of actual files and failed on a 64 GB + Mac. The SDK now sums the current revision's file sizes and uses `usedStorage` only when no file reports + a size. `PreflightResult.weightBytes` reports the corrected figure, and the free-disk requirement drops + with it. + ## 1.0.0-RC.1 — 2026-09-15 (binaries re-published 2026-09-18 and 2026-09-19) Everything below is in `LocalLMLabSDKInference` unless noted (the 2026-09-19 re-publish also adds the From 0b9c656c58242c99353c6b13c823f90fefd01b8b Mon Sep 17 00:00:00 2001 From: ancientcomputing Date: Sun, 27 Sep 2026 10:53:18 -0700 Subject: [PATCH 2/4] Cascade 1.0.0-GA SDK checksums and update docs for GA Add the 1.0.0-GA SDK release (Core/Inference/Remote checksums, verified against the published .sha256 assets) to knownSDKReleases in Components and all 13 examples, bumping defaultSDKVersion and dropping the now-stale 1.0.0-beta.4 entries. Update README.md, examples/README.md, toolkit/README.md, and the localai-cli(-swift) READMEs to point at the app DMG and CLI toolkit zip on this repo's own v1.0.0-GA release instead of locallm-releases, which is where GA app/CLI binaries now publish. Add Qwen3.8-27B (4/6/8-bit) to tested-models.md, confirmed on a Mac Studio M5 Max / 64 GB, and note it couldn't be downloaded before the 1.0.0 GA preflight fix (usedStorage overcounted the 8-bit checkpoint's size). --- Components/Package.swift | 10 +++---- README.md | 13 ++++---- docs/tested-models.md | 5 +++- examples/README.md | 31 ++++++++++++-------- examples/aiql/Package.swift | 14 ++++----- examples/code-buddy/Package.swift | 14 ++++----- examples/localai-cli-swift/README.md | 4 ++- examples/localai-cli/README.md | 4 ++- examples/mlx-control-room/Package.swift | 8 ++++- examples/model-switch/Package.swift | 10 +++---- examples/os-matrix/Package.swift | 14 ++++----- examples/plate-today-tools/Package.swift | 10 +++---- examples/plate-today/Package.swift | 10 +++---- examples/repo-qa-local/Package.swift | 14 ++++----- examples/repo-qa/Package.swift | 10 +++---- examples/security-demo/Package.swift | 10 +++---- examples/vistanova/Package.swift | 8 ++++- examples/workspace-buddy-local/Package.swift | 14 ++++----- examples/workspace-buddy/Package.swift | 10 +++---- toolkit/README.md | 21 ++++++++----- 20 files changed, 133 insertions(+), 101 deletions(-) diff --git a/Components/Package.swift b/Components/Package.swift index 49ac044..7f26faf 100644 --- a/Components/Package.swift +++ b/Components/Package.swift @@ -24,17 +24,17 @@ struct SDKRelease { // or edit `defaultSDKVersion`. For a release not listed, add its entry (URL follows the pattern // below; checksum is the `.sha256` next to the zip on that GitHub release). Keep this in step // with `examples/model-switch/Package.swift`, which consumes Core through this package. -let defaultSDKVersion = "1.0.0-RC.1" +let defaultSDKVersion = "1.0.0-GA" let knownSDKReleases: [String: SDKRelease] = [ - "1.0.0-beta.4": SDKRelease( - url: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-beta.4/LocalLMLabSDKCore-1.0.0-beta.4.xcframework.zip", - checksum: "3ed0e79b6914e6b48b7ae27f3fdda139f71e3d60f603daf54901716c8c972cb3" - ), "1.0.0-RC.1": SDKRelease( url: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-RC.1/LocalLMLabSDKCore-1.0.0-RC.1.xcframework.zip", checksum: "397e7b5f7efd1076293a3d5d06c41d75043bffa23cffdb821d71d21ee41e68de" ), + "1.0.0-GA": SDKRelease( + url: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-GA/LocalLMLabSDKCore-1.0.0-GA.xcframework.zip", + checksum: "7d77a9c2e37dfb2f7925f01ed011262ee5a2aebc561a3ae7a93524acc0285b3e" + ), ] func failManifest(_ message: String) -> Never { diff --git a/README.md b/README.md index 5981de5..9b075cb 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ an Apple entitlement that is still pending, so it is inert in this beta. **Product page:** [thisbrain.ai/locallm](https://thisbrain.ai/locallm) — or get the app directly: -[LocalLM Lab 1.0.0-RC.1 (arm64 DMG)](https://github.com/ancientcomputing/locallm-releases/releases/download/1.0.0-RC.1/LocalLM.Lab-1.0.0-RC.1-arm64.dmg). +[LocalLM Lab 1.0.0-GA (arm64 DMG)](https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-GA/LocalLM.Lab-1.0.0-GA-arm64.dmg). ## LocalLM Lab SDK @@ -63,11 +63,12 @@ what's public here is: OpenAI-compatible API Lab endpoint. Full list with descriptions in the [Building on the SDK](#building-on-the-sdk) section below. - **[toolkit/](toolkit/)** — the `localai-cli` toolkit (zip + `.sha256`). - `0.6`–`1.0.0-beta.3` are checked in here; from `1.0.0-beta.4` on it ships as a - release asset on - [`ancientcomputing/locallm-releases`](https://github.com/ancientcomputing/locallm-releases/releases) - alongside the app DMG. See that folder's README to download and verify; full - CLI reference at + `0.6`–`1.0.0-beta.3` are checked in here; `1.0.0-beta.4` through `1.0.0-RC.1` + shipped as a release asset on + [`ancientcomputing/locallm-releases`](https://github.com/ancientcomputing/locallm-releases/releases); + from **`1.0.0-GA`** on it ships as a release asset on this repo instead, + alongside the app DMG and the SDK xcframeworks. See that folder's README to + download and verify; full CLI reference at [thisbrain.ai/locallm/cli.html](https://thisbrain.ai/locallm/cli.html). - **[Components/](Components/)** — `LocalLMLabSDKComponents`, prebuilt SwiftUI for managing MCP servers and models, built on the SDK's public API. diff --git a/docs/tested-models.md b/docs/tested-models.md index 168ee45..e63e590 100644 --- a/docs/tested-models.md +++ b/docs/tested-models.md @@ -5,7 +5,9 @@ > `1.0.0-beta`, requires macOS 27). Model conversions, chat templates, and the MLX stack all > move. **Validate your own model with `MLXModelProvider.capabilityProbe` — that result is > authoritative, this table is a starting point.** Distilled from -> 15+ rounds of real traces. +> 15+ rounds of real traces. (The Qwen3.8-27B row was confirmed separately on +> **2026-09-27** against SDK `1.0.0-GA`, on a Mac Studio M5 Max / 64 GB — not part of the +> original 15-round rig below.) Applies to the **model layer** only (`LocalLMLabSDKInference` + `MLXModelProvider` — see [`sdk-guide.md` §6a](sdk-guide.md#6a-the-model-layer-local-models-routing-sessions)). The @@ -21,6 +23,7 @@ built-in `ClockTool` cross-check. | Family | Tool-calling | Notes | |---|---|---| | **Qwen 2.5 / 3** (1.5B – 14B, `mlx-community/*-Instruct-4bit`, `Qwen3-*-4bit`) | ✅ reliable | The reference set. 1.5B tool-calls but grounds shallowly; 8B/14B better. Qwen's `{…}` JSON convention is what the bridge is built against. **`code-buddy`'s default.** | +| **Qwen3.8-27B** (4-bit `mlx-community/Qwen3.8-27B-4bit`, 6-bit `lmstudio-community/Qwen3.8-27B-MLX-6bit`, 8-bit `mlx-community/Qwen3.8-27B-8bit`) | ✅ reliable (confirmed 2026-09-27, SDK 1.0.0-GA, Mac Studio M5 Max / 64 GB) | Larger sibling of the Qwen3 family above — same tool-calling convention, tool-calls reliably across all three quantizations. Needs a Mac with enough unified memory to hold the weights (the 8-bit checkpoint's actual file size is ~29.5 GB — see `MLXModelProvider.validate`'s `sizeVsMemory` stage; 4-bit and 6-bit are proportionally smaller/larger). Couldn't be downloaded before the `1.0.0` GA preflight fix below — `usedStorage` overcounted the 8-bit checkpoint as 58.1 GB against its real 29.5 GB and it was rejected as too big for a 64 GB Mac (see the `1.0.0 — GA` entry in [CHANGELOG.md](../CHANGELOG.md)). Not part of the original 15-round eval below — added once confirmed separately. | | **Granite 4.0** (h-tiny) | ✅ | First non-Qwen to genuinely tool-call. Picked adjacent-but-wrong tools on an unnamed-tool prompt (name your tools explicitly). | | **Gemma 3 / 4** | ✅ | Best release-date precision of any local model tested, matching Claude — with one fabricated detail. | | **Ministral-3-3B** | ✅ | Cleanest grounding outside Claude/Gemma; zero fabrication in our run. | diff --git a/examples/README.md b/examples/README.md index e821eb8..e85f060 100644 --- a/examples/README.md +++ b/examples/README.md @@ -32,10 +32,11 @@ descriptions. Neither is the "real" one — both ship in Core, and an app can mi [`../docs/sdk-guide.md` §7a](../docs/sdk-guide.md#7a-two-paths-to-tool-calling-ready-made-tools-or-write-your-own) for the full framing. -The `localai-cli` examples require the CLI toolkit itself. From `1.0.0-beta.4` -on it ships as a release asset on -[`ancientcomputing/locallm-releases`](https://github.com/ancientcomputing/locallm-releases/releases) -alongside the app DMG (older versions are checked into [../toolkit/](../toolkit/)). +The `localai-cli` examples require the CLI toolkit itself. `1.0.0-beta.4` through +`1.0.0-RC.1` shipped it as a release asset on +[`ancientcomputing/locallm-releases`](https://github.com/ancientcomputing/locallm-releases/releases); +from **`1.0.0-GA`** on it ships as a release asset on this repo instead, alongside +the app DMG (older versions are checked into [../toolkit/](../toolkit/)). See that folder's README to download and install it, and [thisbrain.ai/locallm/cli.html](https://thisbrain.ai/locallm/cli.html) for the full CLI reference. @@ -48,14 +49,14 @@ Download LocalLM Lab from [its product page at https://thisbrain.ai/locallm](htt Each SDK example (everything except the `api-lab/` and `localai-cli*/` folders) is a standalone SwiftPM package. It resolves `LocalLMLabSDKCore` (and, where used, `LocalLMLabSDKInference` / -`LocalLMLabSDKRemote`) as a **binary** dependency from a GitHub Release on this repo — nothing to +`LocalLMLabSDKRemote` / `LocalLMLabSDKClaude`) as a **binary** dependency from a GitHub Release on this repo — nothing to download or unzip by hand. Requires **Apple Silicon** and the **Xcode 27** toolchain to build (a stable Xcode fails with `'v27' is unavailable`). **macOS 27 is recommended** — most of the SDK's advanced model-layer features (Private Cloud Compute, open-weight/MLX, Claude, online providers) need it — but it isn't universal: [`os-matrix/`](os-matrix/) is built and tested to run unchanged on **macOS 26** too (see its README). -The examples on this `1.0.0-RC.1` branch build against SDK **`1.0.0-RC.1`**; the ones on `main` +The examples on this `1.0.0-GA` branch build against SDK **`1.0.0-GA`**; the ones on `main` build against the latest stable release. No environment variable is needed for either. ### What each example needs @@ -151,7 +152,7 @@ resolution doesn't inherit shell environment variables. ```bash cd examples/repo-qa -LOCALLM_SDK_VERSION=1.0.0-RC.1 \ +LOCALLM_SDK_VERSION=1.0.0-GA \ DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer \ swift run RepoQA facebook/react ``` @@ -164,23 +165,27 @@ previous one. (`code-buddy/sample-workspace/Package.swift` is not one of these dependency-free fixture for the code-buddy walkthrough, not an SDK consumer.) ```swift -let defaultSDKVersion = "1.0.0-RC.1" +let defaultSDKVersion = "1.0.0-GA" let knownSDKReleases: [String: SDKRelease] = [ - "1.0.0-beta.4": SDKRelease(url: "…/v1.0.0-beta.4/LocalLMLabSDKCore-1.0.0-beta.4.xcframework.zip", - checksum: "3ed0e79b…"), "1.0.0-RC.1": SDKRelease(url: "…/v1.0.0-RC.1/LocalLMLabSDKCore-1.0.0-RC.1.xcframework.zip", checksum: "397e7b5f…"), + "1.0.0-GA": SDKRelease(url: "…/v1.0.0-GA/LocalLMLabSDKCore-1.0.0-GA.xcframework.zip", + checksum: "7d77a9c2…"), ] ``` To use a release that isn't listed, add an entry. The URL always follows `https://github.com/ancientcomputing/locallm/releases/download/v/LocalLMLabSDK-.xcframework.zip`, -and the checksum is the `.sha256` file published next to each `.xcframework.zip` on that release: +and the checksum is the `.sha256` file published next to each `.xcframework.zip` on that release — +every module ships its own checksum (`Core`, `Inference`, `Remote`, and `Claude` each have a +distinct `.xcframework.zip.sha256`; don't reuse Core's for another module): ```bash -curl -sL https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-beta.1/LocalLMLabSDKCore-1.0.0-beta.1.xcframework.zip.sha256 -# → 0b4ab34e474d1acd725161cfb591cf3d862a7529fe7c9dbadf01eece3ad1590f +curl -sL https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-GA/LocalLMLabSDKCore-1.0.0-GA.xcframework.zip.sha256 +# → 7d77a9c2e37dfb2f7925f01ed011262ee5a2aebc561a3ae7a93524acc0285b3e +curl -sL https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-GA/LocalLMLabSDKClaude-1.0.0-GA.xcframework.zip.sha256 +# → 2c69c330c8a5e3929b9544fcb865738d0ec39abc7520462cae4f138214e6858f ``` Then point `defaultSDKVersion` at it (works everywhere, Xcode included) or pass diff --git a/examples/aiql/Package.swift b/examples/aiql/Package.swift index 7972c08..8e6de4e 100644 --- a/examples/aiql/Package.swift +++ b/examples/aiql/Package.swift @@ -30,21 +30,21 @@ struct SDKRelease { // uses. `knownSDKReleases` carries this plus the previous release. Build against another // published version: set LOCALLM_SDK_VERSION in your shell (works for `swift build` / CI, NOT // inside Xcode), or edit `defaultSDKVersion` here. -let defaultSDKVersion = "1.0.0-RC.1" +let defaultSDKVersion = "1.0.0-GA" let knownSDKReleases: [String: SDKRelease] = [ - "1.0.0-beta.4": SDKRelease( - coreURL: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-beta.4/LocalLMLabSDKCore-1.0.0-beta.4.xcframework.zip", - coreChecksum: "3ed0e79b6914e6b48b7ae27f3fdda139f71e3d60f603daf54901716c8c972cb3", - inferenceURL: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-beta.4/LocalLMLabSDKInference-1.0.0-beta.4.xcframework.zip", - inferenceChecksum: "fa8feb19883f9a465a69f39d756f1b41b515c8298c891b06fef5da5b81b2a03c" - ), "1.0.0-RC.1": SDKRelease( coreURL: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-RC.1/LocalLMLabSDKCore-1.0.0-RC.1.xcframework.zip", coreChecksum: "397e7b5f7efd1076293a3d5d06c41d75043bffa23cffdb821d71d21ee41e68de", inferenceURL: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-RC.1/LocalLMLabSDKInference-1.0.0-RC.1.xcframework.zip", inferenceChecksum: "e24cb0581807d37a7b595f0b198b9a9eeecc1c5c36fb59f61429b8a7b42dc169" ), + "1.0.0-GA": SDKRelease( + coreURL: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-GA/LocalLMLabSDKCore-1.0.0-GA.xcframework.zip", + coreChecksum: "7d77a9c2e37dfb2f7925f01ed011262ee5a2aebc561a3ae7a93524acc0285b3e", + inferenceURL: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-GA/LocalLMLabSDKInference-1.0.0-GA.xcframework.zip", + inferenceChecksum: "6fcbdd5b04fff709e720b92e8b7eda638014a4d19c0dd925e018b72cb7109430" + ), ] func failManifest(_ message: String) -> Never { diff --git a/examples/code-buddy/Package.swift b/examples/code-buddy/Package.swift index d40b9d3..1108bdf 100644 --- a/examples/code-buddy/Package.swift +++ b/examples/code-buddy/Package.swift @@ -25,21 +25,21 @@ struct SDKRelease { // `swift build` / CI, NOT inside Xcode), or edit `defaultSDKVersion` here. For a // release not listed, add its entry (URL + the `.sha256` next to the zip on the // GitHub release) or just replace the strings in place. -let defaultSDKVersion = "1.0.0-RC.1" +let defaultSDKVersion = "1.0.0-GA" let knownSDKReleases: [String: SDKRelease] = [ - "1.0.0-beta.4": SDKRelease( - coreURL: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-beta.4/LocalLMLabSDKCore-1.0.0-beta.4.xcframework.zip", - coreChecksum: "3ed0e79b6914e6b48b7ae27f3fdda139f71e3d60f603daf54901716c8c972cb3", - inferenceURL: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-beta.4/LocalLMLabSDKInference-1.0.0-beta.4.xcframework.zip", - inferenceChecksum: "fa8feb19883f9a465a69f39d756f1b41b515c8298c891b06fef5da5b81b2a03c" - ), "1.0.0-RC.1": SDKRelease( coreURL: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-RC.1/LocalLMLabSDKCore-1.0.0-RC.1.xcframework.zip", coreChecksum: "397e7b5f7efd1076293a3d5d06c41d75043bffa23cffdb821d71d21ee41e68de", inferenceURL: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-RC.1/LocalLMLabSDKInference-1.0.0-RC.1.xcframework.zip", inferenceChecksum: "e24cb0581807d37a7b595f0b198b9a9eeecc1c5c36fb59f61429b8a7b42dc169" ), + "1.0.0-GA": SDKRelease( + coreURL: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-GA/LocalLMLabSDKCore-1.0.0-GA.xcframework.zip", + coreChecksum: "7d77a9c2e37dfb2f7925f01ed011262ee5a2aebc561a3ae7a93524acc0285b3e", + inferenceURL: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-GA/LocalLMLabSDKInference-1.0.0-GA.xcframework.zip", + inferenceChecksum: "6fcbdd5b04fff709e720b92e8b7eda638014a4d19c0dd925e018b72cb7109430" + ), ] func failManifest(_ message: String) -> Never { diff --git a/examples/localai-cli-swift/README.md b/examples/localai-cli-swift/README.md index 9596d79..0b3e0d0 100644 --- a/examples/localai-cli-swift/README.md +++ b/examples/localai-cli-swift/README.md @@ -154,7 +154,9 @@ file is this repo's script-runner boilerplate, not something to copy. process, so the app must be **running**, not just installed. 2. Get the `localai-toolkit--arm64.zip` — a release asset on [`ancientcomputing/locallm-releases`](https://github.com/ancientcomputing/locallm-releases/releases) - from `1.0.0-beta.4` on, or [`../../toolkit/`](../../toolkit/) for older + for `1.0.0-beta.4` through `1.0.0-RC.1`, on this repo's own + [releases](https://github.com/ancientcomputing/locallm/releases) from + `1.0.0-GA` on, or [`../../toolkit/`](../../toolkit/) for older versions (see that folder's README) — and unzip it. `localai-cli` and `localai-playground-run` are a matched pair. 3. Put both binaries in this folder (or set `LOCALAI_CLI_PATH`). diff --git a/examples/localai-cli/README.md b/examples/localai-cli/README.md index 4ab5f41..4a81c58 100644 --- a/examples/localai-cli/README.md +++ b/examples/localai-cli/README.md @@ -66,7 +66,9 @@ for that one call, via `connectors` and `mcp_tools` fields: over a local socket), so the app must be **running**, not just installed. 2. Get the `localai-toolkit--arm64.zip` — a release asset on [`ancientcomputing/locallm-releases`](https://github.com/ancientcomputing/locallm-releases/releases) - from `1.0.0-beta.4` on, or [`../../toolkit/`](../../toolkit/) for older + for `1.0.0-beta.4` through `1.0.0-RC.1`, on this repo's own + [releases](https://github.com/ancientcomputing/locallm/releases) from + `1.0.0-GA` on, or [`../../toolkit/`](../../toolkit/) for older versions (see that folder's README) — and unzip it. `localai-cli` and `localai-playground-run` are a matched pair. 3. Put both binaries in this folder (or point `LOCALAI_CLI_PATH` at wherever diff --git a/examples/mlx-control-room/Package.swift b/examples/mlx-control-room/Package.swift index 9a1cdcf..27141aa 100644 --- a/examples/mlx-control-room/Package.swift +++ b/examples/mlx-control-room/Package.swift @@ -25,7 +25,7 @@ struct SDKRelease { // its entry (URL + the `.sha256` next to the zip on the GitHub release) or just replace the strings in // place. Needs a release that includes the model pin / update / cleanup APIs (1.0.0-RC.1 as re-published // on 2026-09-18, or later). -let defaultSDKVersion = "1.0.0-RC.1" +let defaultSDKVersion = "1.0.0-GA" let knownSDKReleases: [String: SDKRelease] = [ "1.0.0-RC.1": SDKRelease( @@ -34,6 +34,12 @@ let knownSDKReleases: [String: SDKRelease] = [ inferenceURL: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-RC.1/LocalLMLabSDKInference-1.0.0-RC.1.xcframework.zip", inferenceChecksum: "e24cb0581807d37a7b595f0b198b9a9eeecc1c5c36fb59f61429b8a7b42dc169" ), + "1.0.0-GA": SDKRelease( + coreURL: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-GA/LocalLMLabSDKCore-1.0.0-GA.xcframework.zip", + coreChecksum: "7d77a9c2e37dfb2f7925f01ed011262ee5a2aebc561a3ae7a93524acc0285b3e", + inferenceURL: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-GA/LocalLMLabSDKInference-1.0.0-GA.xcframework.zip", + inferenceChecksum: "6fcbdd5b04fff709e720b92e8b7eda638014a4d19c0dd925e018b72cb7109430" + ), ] func failManifest(_ message: String) -> Never { diff --git a/examples/model-switch/Package.swift b/examples/model-switch/Package.swift index f7c3a2b..28a1a15 100644 --- a/examples/model-switch/Package.swift +++ b/examples/model-switch/Package.swift @@ -28,17 +28,17 @@ struct SDKRelease { // `swift build` / CI, NOT inside Xcode), or edit `defaultSDKVersion` here. For a // release not listed, add its entry (URL + the `.sha256` next to the zip on the // GitHub release) or just replace the strings in place. -let defaultSDKVersion = "1.0.0-RC.1" +let defaultSDKVersion = "1.0.0-GA" let knownSDKReleases: [String: SDKRelease] = [ - "1.0.0-beta.4": SDKRelease( - remoteURL: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-beta.4/LocalLMLabSDKRemote-1.0.0-beta.4.xcframework.zip", - remoteChecksum: "a73a06bf04a2dd3b1a15b40770f12c0565f8cbf1a97eaa604317b09e3a860454" - ), "1.0.0-RC.1": SDKRelease( remoteURL: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-RC.1/LocalLMLabSDKRemote-1.0.0-RC.1.xcframework.zip", remoteChecksum: "3e763c2fb542f7cc8493cf8e4ba2effcc98adae9c7d9991b60e6a92be8ee88c6" ), + "1.0.0-GA": SDKRelease( + remoteURL: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-GA/LocalLMLabSDKRemote-1.0.0-GA.xcframework.zip", + remoteChecksum: "294a00eb41a22265849de171930c209d48c27c64c157bc565f76a5e0c13bdb88" + ), ] func failManifest(_ message: String) -> Never { diff --git a/examples/os-matrix/Package.swift b/examples/os-matrix/Package.swift index 6a5a97f..00ca69f 100644 --- a/examples/os-matrix/Package.swift +++ b/examples/os-matrix/Package.swift @@ -22,21 +22,21 @@ struct SDKRelease { // `swift build` / CI, NOT inside Xcode), or edit `defaultSDKVersion` here. For a // release not listed, add its entry (URL + the `.sha256` next to the zip on the // GitHub release) or just replace the strings in place. -let defaultSDKVersion = "1.0.0-RC.1" +let defaultSDKVersion = "1.0.0-GA" let knownSDKReleases: [String: SDKRelease] = [ - "1.0.0-beta.4": SDKRelease( - coreURL: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-beta.4/LocalLMLabSDKCore-1.0.0-beta.4.xcframework.zip", - coreChecksum: "3ed0e79b6914e6b48b7ae27f3fdda139f71e3d60f603daf54901716c8c972cb3", - inferenceURL: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-beta.4/LocalLMLabSDKInference-1.0.0-beta.4.xcframework.zip", - inferenceChecksum: "fa8feb19883f9a465a69f39d756f1b41b515c8298c891b06fef5da5b81b2a03c" - ), "1.0.0-RC.1": SDKRelease( coreURL: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-RC.1/LocalLMLabSDKCore-1.0.0-RC.1.xcframework.zip", coreChecksum: "397e7b5f7efd1076293a3d5d06c41d75043bffa23cffdb821d71d21ee41e68de", inferenceURL: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-RC.1/LocalLMLabSDKInference-1.0.0-RC.1.xcframework.zip", inferenceChecksum: "e24cb0581807d37a7b595f0b198b9a9eeecc1c5c36fb59f61429b8a7b42dc169" ), + "1.0.0-GA": SDKRelease( + coreURL: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-GA/LocalLMLabSDKCore-1.0.0-GA.xcframework.zip", + coreChecksum: "7d77a9c2e37dfb2f7925f01ed011262ee5a2aebc561a3ae7a93524acc0285b3e", + inferenceURL: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-GA/LocalLMLabSDKInference-1.0.0-GA.xcframework.zip", + inferenceChecksum: "6fcbdd5b04fff709e720b92e8b7eda638014a4d19c0dd925e018b72cb7109430" + ), ] func failManifest(_ message: String) -> Never { diff --git a/examples/plate-today-tools/Package.swift b/examples/plate-today-tools/Package.swift index 0af963c..b91c6cf 100644 --- a/examples/plate-today-tools/Package.swift +++ b/examples/plate-today-tools/Package.swift @@ -23,17 +23,17 @@ struct SDKRelease { // `swift build` / CI, NOT inside Xcode), or edit `defaultSDKVersion` here. For a // release not listed, add its entry (URL + the `.sha256` next to the zip on the // GitHub release) or just replace the strings in place. -let defaultSDKVersion = "1.0.0-RC.1" +let defaultSDKVersion = "1.0.0-GA" let knownSDKReleases: [String: SDKRelease] = [ - "1.0.0-beta.4": SDKRelease( - url: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-beta.4/LocalLMLabSDKCore-1.0.0-beta.4.xcframework.zip", - checksum: "3ed0e79b6914e6b48b7ae27f3fdda139f71e3d60f603daf54901716c8c972cb3" - ), "1.0.0-RC.1": SDKRelease( url: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-RC.1/LocalLMLabSDKCore-1.0.0-RC.1.xcframework.zip", checksum: "397e7b5f7efd1076293a3d5d06c41d75043bffa23cffdb821d71d21ee41e68de" ), + "1.0.0-GA": SDKRelease( + url: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-GA/LocalLMLabSDKCore-1.0.0-GA.xcframework.zip", + checksum: "7d77a9c2e37dfb2f7925f01ed011262ee5a2aebc561a3ae7a93524acc0285b3e" + ), ] func failManifest(_ message: String) -> Never { diff --git a/examples/plate-today/Package.swift b/examples/plate-today/Package.swift index f562ac9..31431a2 100644 --- a/examples/plate-today/Package.swift +++ b/examples/plate-today/Package.swift @@ -20,17 +20,17 @@ struct SDKRelease { // edit `defaultSDKVersion` here. For a release not listed, add its entry — the URL follows the // pattern below and the checksum is the `.sha256` file next to the zip on that GitHub release — // or just replace the two strings in place. -let defaultSDKVersion = "1.0.0-RC.1" +let defaultSDKVersion = "1.0.0-GA" let knownSDKReleases: [String: SDKRelease] = [ - "1.0.0-beta.4": SDKRelease( - url: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-beta.4/LocalLMLabSDKCore-1.0.0-beta.4.xcframework.zip", - checksum: "3ed0e79b6914e6b48b7ae27f3fdda139f71e3d60f603daf54901716c8c972cb3" - ), "1.0.0-RC.1": SDKRelease( url: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-RC.1/LocalLMLabSDKCore-1.0.0-RC.1.xcframework.zip", checksum: "397e7b5f7efd1076293a3d5d06c41d75043bffa23cffdb821d71d21ee41e68de" ), + "1.0.0-GA": SDKRelease( + url: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-GA/LocalLMLabSDKCore-1.0.0-GA.xcframework.zip", + checksum: "7d77a9c2e37dfb2f7925f01ed011262ee5a2aebc561a3ae7a93524acc0285b3e" + ), ] func failManifest(_ message: String) -> Never { diff --git a/examples/repo-qa-local/Package.swift b/examples/repo-qa-local/Package.swift index 5012def..176735c 100644 --- a/examples/repo-qa-local/Package.swift +++ b/examples/repo-qa-local/Package.swift @@ -26,21 +26,21 @@ struct SDKRelease { // `swift build` / CI, NOT inside Xcode), or edit `defaultSDKVersion` here. For a // release not listed, add its entry (URL + the `.sha256` next to the zip on the // GitHub release) or just replace the strings in place. -let defaultSDKVersion = "1.0.0-RC.1" +let defaultSDKVersion = "1.0.0-GA" let knownSDKReleases: [String: SDKRelease] = [ - "1.0.0-beta.4": SDKRelease( - coreURL: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-beta.4/LocalLMLabSDKCore-1.0.0-beta.4.xcframework.zip", - coreChecksum: "3ed0e79b6914e6b48b7ae27f3fdda139f71e3d60f603daf54901716c8c972cb3", - inferenceURL: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-beta.4/LocalLMLabSDKInference-1.0.0-beta.4.xcframework.zip", - inferenceChecksum: "fa8feb19883f9a465a69f39d756f1b41b515c8298c891b06fef5da5b81b2a03c" - ), "1.0.0-RC.1": SDKRelease( coreURL: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-RC.1/LocalLMLabSDKCore-1.0.0-RC.1.xcframework.zip", coreChecksum: "397e7b5f7efd1076293a3d5d06c41d75043bffa23cffdb821d71d21ee41e68de", inferenceURL: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-RC.1/LocalLMLabSDKInference-1.0.0-RC.1.xcframework.zip", inferenceChecksum: "e24cb0581807d37a7b595f0b198b9a9eeecc1c5c36fb59f61429b8a7b42dc169" ), + "1.0.0-GA": SDKRelease( + coreURL: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-GA/LocalLMLabSDKCore-1.0.0-GA.xcframework.zip", + coreChecksum: "7d77a9c2e37dfb2f7925f01ed011262ee5a2aebc561a3ae7a93524acc0285b3e", + inferenceURL: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-GA/LocalLMLabSDKInference-1.0.0-GA.xcframework.zip", + inferenceChecksum: "6fcbdd5b04fff709e720b92e8b7eda638014a4d19c0dd925e018b72cb7109430" + ), ] func failManifest(_ message: String) -> Never { diff --git a/examples/repo-qa/Package.swift b/examples/repo-qa/Package.swift index 119f6a8..c4cfade 100644 --- a/examples/repo-qa/Package.swift +++ b/examples/repo-qa/Package.swift @@ -23,17 +23,17 @@ struct SDKRelease { // `swift build` / CI, NOT inside Xcode), or edit `defaultSDKVersion` here. For a // release not listed, add its entry (URL + the `.sha256` next to the zip on the // GitHub release) or just replace the strings in place. -let defaultSDKVersion = "1.0.0-RC.1" +let defaultSDKVersion = "1.0.0-GA" let knownSDKReleases: [String: SDKRelease] = [ - "1.0.0-beta.4": SDKRelease( - url: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-beta.4/LocalLMLabSDKCore-1.0.0-beta.4.xcframework.zip", - checksum: "3ed0e79b6914e6b48b7ae27f3fdda139f71e3d60f603daf54901716c8c972cb3" - ), "1.0.0-RC.1": SDKRelease( url: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-RC.1/LocalLMLabSDKCore-1.0.0-RC.1.xcframework.zip", checksum: "397e7b5f7efd1076293a3d5d06c41d75043bffa23cffdb821d71d21ee41e68de" ), + "1.0.0-GA": SDKRelease( + url: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-GA/LocalLMLabSDKCore-1.0.0-GA.xcframework.zip", + checksum: "7d77a9c2e37dfb2f7925f01ed011262ee5a2aebc561a3ae7a93524acc0285b3e" + ), ] func failManifest(_ message: String) -> Never { diff --git a/examples/security-demo/Package.swift b/examples/security-demo/Package.swift index 03acf2a..705f476 100644 --- a/examples/security-demo/Package.swift +++ b/examples/security-demo/Package.swift @@ -29,17 +29,17 @@ struct SDKRelease { // `swift build` / CI, NOT inside Xcode), or edit `defaultSDKVersion` here. For a // release not listed, add its entry (URL + the `.sha256` next to the zip on the // GitHub release) or just replace the strings in place. -let defaultSDKVersion = "1.0.0-RC.1" +let defaultSDKVersion = "1.0.0-GA" let knownSDKReleases: [String: SDKRelease] = [ - "1.0.0-beta.4": SDKRelease( - remoteURL: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-beta.4/LocalLMLabSDKRemote-1.0.0-beta.4.xcframework.zip", - remoteChecksum: "a73a06bf04a2dd3b1a15b40770f12c0565f8cbf1a97eaa604317b09e3a860454" - ), "1.0.0-RC.1": SDKRelease( remoteURL: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-RC.1/LocalLMLabSDKRemote-1.0.0-RC.1.xcframework.zip", remoteChecksum: "3e763c2fb542f7cc8493cf8e4ba2effcc98adae9c7d9991b60e6a92be8ee88c6" ), + "1.0.0-GA": SDKRelease( + remoteURL: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-GA/LocalLMLabSDKRemote-1.0.0-GA.xcframework.zip", + remoteChecksum: "294a00eb41a22265849de171930c209d48c27c64c157bc565f76a5e0c13bdb88" + ), ] func failManifest(_ message: String) -> Never { diff --git a/examples/vistanova/Package.swift b/examples/vistanova/Package.swift index d31565f..5b7b78f 100644 --- a/examples/vistanova/Package.swift +++ b/examples/vistanova/Package.swift @@ -24,7 +24,7 @@ struct SDKRelease { // strings in place. Needs a release that includes `MLXModelProvider(pinnedRevisions:)` and // `cancelDownload(_:)`: the checksums below are the 1.0.0-RC.1 binaries as re-published on // 2026-09-19. An RC.1 pulled earlier fails the checksum check — re-resolve packages. -let defaultSDKVersion = "1.0.0-RC.1" +let defaultSDKVersion = "1.0.0-GA" let knownSDKReleases: [String: SDKRelease] = [ "1.0.0-RC.1": SDKRelease( @@ -33,6 +33,12 @@ let knownSDKReleases: [String: SDKRelease] = [ inferenceURL: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-RC.1/LocalLMLabSDKInference-1.0.0-RC.1.xcframework.zip", inferenceChecksum: "e24cb0581807d37a7b595f0b198b9a9eeecc1c5c36fb59f61429b8a7b42dc169" ), + "1.0.0-GA": SDKRelease( + coreURL: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-GA/LocalLMLabSDKCore-1.0.0-GA.xcframework.zip", + coreChecksum: "7d77a9c2e37dfb2f7925f01ed011262ee5a2aebc561a3ae7a93524acc0285b3e", + inferenceURL: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-GA/LocalLMLabSDKInference-1.0.0-GA.xcframework.zip", + inferenceChecksum: "6fcbdd5b04fff709e720b92e8b7eda638014a4d19c0dd925e018b72cb7109430" + ), ] func failManifest(_ message: String) -> Never { diff --git a/examples/workspace-buddy-local/Package.swift b/examples/workspace-buddy-local/Package.swift index 3f9c6b1..6a2fc63 100644 --- a/examples/workspace-buddy-local/Package.swift +++ b/examples/workspace-buddy-local/Package.swift @@ -28,21 +28,21 @@ struct SDKRelease { // `swift build` / CI, NOT inside Xcode), or edit `defaultSDKVersion` here. For a // release not listed, add its entry (URL + the `.sha256` next to the zip on the // GitHub release) or just replace the strings in place. -let defaultSDKVersion = "1.0.0-RC.1" +let defaultSDKVersion = "1.0.0-GA" let knownSDKReleases: [String: SDKRelease] = [ - "1.0.0-beta.4": SDKRelease( - coreURL: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-beta.4/LocalLMLabSDKCore-1.0.0-beta.4.xcframework.zip", - coreChecksum: "3ed0e79b6914e6b48b7ae27f3fdda139f71e3d60f603daf54901716c8c972cb3", - inferenceURL: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-beta.4/LocalLMLabSDKInference-1.0.0-beta.4.xcframework.zip", - inferenceChecksum: "fa8feb19883f9a465a69f39d756f1b41b515c8298c891b06fef5da5b81b2a03c" - ), "1.0.0-RC.1": SDKRelease( coreURL: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-RC.1/LocalLMLabSDKCore-1.0.0-RC.1.xcframework.zip", coreChecksum: "397e7b5f7efd1076293a3d5d06c41d75043bffa23cffdb821d71d21ee41e68de", inferenceURL: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-RC.1/LocalLMLabSDKInference-1.0.0-RC.1.xcframework.zip", inferenceChecksum: "e24cb0581807d37a7b595f0b198b9a9eeecc1c5c36fb59f61429b8a7b42dc169" ), + "1.0.0-GA": SDKRelease( + coreURL: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-GA/LocalLMLabSDKCore-1.0.0-GA.xcframework.zip", + coreChecksum: "7d77a9c2e37dfb2f7925f01ed011262ee5a2aebc561a3ae7a93524acc0285b3e", + inferenceURL: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-GA/LocalLMLabSDKInference-1.0.0-GA.xcframework.zip", + inferenceChecksum: "6fcbdd5b04fff709e720b92e8b7eda638014a4d19c0dd925e018b72cb7109430" + ), ] func failManifest(_ message: String) -> Never { diff --git a/examples/workspace-buddy/Package.swift b/examples/workspace-buddy/Package.swift index b265485..581ddd2 100644 --- a/examples/workspace-buddy/Package.swift +++ b/examples/workspace-buddy/Package.swift @@ -21,17 +21,17 @@ struct SDKRelease { // `swift build` / CI, NOT inside Xcode), or edit `defaultSDKVersion` here. For a // release not listed, add its entry (URL + the `.sha256` next to the zip on the // GitHub release) or just replace the strings in place. -let defaultSDKVersion = "1.0.0-RC.1" +let defaultSDKVersion = "1.0.0-GA" let knownSDKReleases: [String: SDKRelease] = [ - "1.0.0-beta.4": SDKRelease( - url: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-beta.4/LocalLMLabSDKCore-1.0.0-beta.4.xcframework.zip", - checksum: "3ed0e79b6914e6b48b7ae27f3fdda139f71e3d60f603daf54901716c8c972cb3" - ), "1.0.0-RC.1": SDKRelease( url: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-RC.1/LocalLMLabSDKCore-1.0.0-RC.1.xcframework.zip", checksum: "397e7b5f7efd1076293a3d5d06c41d75043bffa23cffdb821d71d21ee41e68de" ), + "1.0.0-GA": SDKRelease( + url: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-GA/LocalLMLabSDKCore-1.0.0-GA.xcframework.zip", + checksum: "7d77a9c2e37dfb2f7925f01ed011262ee5a2aebc561a3ae7a93524acc0285b3e" + ), ] func failManifest(_ message: String) -> Never { diff --git a/toolkit/README.md b/toolkit/README.md index 8f019b4..894a898 100644 --- a/toolkit/README.md +++ b/toolkit/README.md @@ -12,15 +12,22 @@ and [../examples/localai-cli-swift/](../examples/localai-cli-swift/) (Swift). ## Download -From `1.0.0-beta.4` on, the toolkit zip and its checksum ship as release assets -on **[github.com/ancientcomputing/locallm-releases](https://github.com/ancientcomputing/locallm-releases/releases)**, -alongside the LocalLM Lab app DMG — one release per version. Latest (`1.0.0-RC.1`): +`1.0.0-beta.4` through `1.0.0-RC.1` shipped the toolkit zip and its checksum as +release assets on +**[github.com/ancientcomputing/locallm-releases](https://github.com/ancientcomputing/locallm-releases/releases)**, +alongside the LocalLM Lab app DMG. From **`1.0.0-GA`** on, both ship as release +assets on this repo instead, alongside the app DMG and the SDK xcframeworks. +Latest (`1.0.0-GA`): ```bash -curl -LO https://github.com/ancientcomputing/locallm-releases/releases/download/1.0.0-RC.1/localai-toolkit-1.0.0-RC.1-arm64.zip -curl -LO https://github.com/ancientcomputing/locallm-releases/releases/download/1.0.0-RC.1/localai-toolkit-1.0.0-RC.1-arm64.zip.sha256 +curl -LO https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-GA/localai-toolkit-1.0.0-GA-arm64.zip +curl -LO https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-GA/localai-toolkit-1.0.0-GA-arm64.zip.sha256 ``` +(For `1.0.0-beta.4` through `1.0.0-RC.1`, replace the repo/tag above with +`locallm-releases`/`` with no leading `v`, e.g. +`.../locallm-releases/releases/download/1.0.0-RC.1/localai-toolkit-1.0.0-RC.1-arm64.zip`.) + Earlier releases (`0.6`–`1.0.0-beta.3`) stay checked into this folder — grab them by cloning the repo or downloading a single file raw, e.g.: @@ -32,13 +39,13 @@ curl -LO https://raw.githubusercontent.com/ancientcomputing/locallm/1.0.0-beta/t ## Verify ```bash -shasum -a 256 -c localai-toolkit-1.0.0-RC.1-arm64.zip.sha256 +shasum -a 256 -c localai-toolkit-1.0.0-GA-arm64.zip.sha256 ``` ## Install ```bash -unzip localai-toolkit-1.0.0-RC.1-arm64.zip +unzip localai-toolkit-1.0.0-GA-arm64.zip ``` This produces `localai-cli`, `localai-playground-run` (macOS 27), From 352c6e1e4be9057ce259e7fcc69ba2b0113e64ee Mon Sep 17 00:00:00 2001 From: ancientcomputing Date: Sun, 27 Sep 2026 11:03:33 -0700 Subject: [PATCH 3/4] =?UTF-8?q?docs:=20regenerate=20api-surface.md=20for?= =?UTF-8?q?=20GA,=20sync=20sdk-guide.md=20=C2=A712,=20fix=20stale=20refs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit api-surface.md regenerated against the published 1.0.0-GA xcframeworks (Core/Claude/Inference/Remote unchanged from RC.1 — matches CHANGELOG's "fixes only, no API change"). Components picks up ModelOnboarding*/ ModelUpdate*/ModelVersions* types shipped since RC.1 but never captured by a prior regeneration. Add the missing ModelOnboardingItem/ModelOnboardingStepState/ ModelFileChange/ModelUpdateOffer/ModelUpdateOwnership/ModelVersionRow shapes to sdk-guide.md §12, which referenced these types by name without ever showing them. sdk-guide.md's top "Status note" said the SDK API "is early... will change" — replaced with the actual GA/source-compatibility status, which contradicted the compatibility policy documented later in the same file. Bump the illustrative SDKRelease example in migrating-to-1.0.md from 1.0.0-beta.3 to 1.0.0-GA. --- docs/api-surface.md | 91 +++++++++++++++++++++++++++++++++++++++- docs/migrating-to-1.0.md | 4 +- docs/sdk-guide.md | 46 +++++++++++++++++++- 3 files changed, 136 insertions(+), 5 deletions(-) diff --git a/docs/api-surface.md b/docs/api-surface.md index 4610d5f..a9965c4 100644 --- a/docs/api-surface.md +++ b/docs/api-surface.md @@ -2,7 +2,7 @@ > Machine-generated by `scripts/dump-public-api.sh` from the built `.swiftinterface`s. > Do not hand-edit. `sdk-guide.md` §12 is the *narrative* reference; this is the check. -> SDK version: `"1.0.0-RC.1"` · generated 2026-09-19T18:42Z +> SDK version: `"1.0.0-GA"` · generated 2026-09-27T18:00Z ## LocalLMLabSDKCore @@ -2056,31 +2056,65 @@ public func turnArtifacts(in transcript: Transcript) -> TurnArtifacts > declarations in `Components/Sources/`, not a compiler-derived interface. ```swift +public enum Kind: Sendable, Equatable { case added, removed, modified } +public enum ModelOnboardingStepState: Sendable, Equatable +public enum ModelUpdateOwnership: Sendable, Equatable public enum RemoteProviderKind: String, Sendable, Hashable, CaseIterable +public enum State: Equatable public extension RemoteProviderDraft public extension View public final class MCPElicitationPresenter: ObservableObject, MCPElicitationHandler public final class MCPServerManagerObservable: ObservableObject +public final class ModelOnboardingModel +public final class ModelUpdateModel +public final class ModelVersionsModel public final class ToolConfirmationPresenter: ObservableObject, ToolConfirmationChannel +public func cancel() +public func checkForUpdate() async public func handleElicitation(_ request: MCPElicitationRequest) async -> MCPElicitationResponse +public func refresh() async +public func remove(_ row: ModelVersionRow) async +public func reset() public func resolve(_ id: MCPElicitationPrompt.ID, _ response: MCPElicitationResponse) public func resolve(_ id: ToolConfirmationRequest.ID, allow: Bool) +public func revertToShippedVersion() async +public func rollBack() async +public func start() +public func update() async public init( public init(apiKey: Binding, onCommit: @escaping () -> Void = {}) public init(core: MCPServerManager) +public init(current: String, available: String, changes: [ModelFileChange] = []) public init(fallbackTimeout: Duration = .seconds(120)) public init(manager: MCPServerManagerObservable) public init(manager: MCPServerManagerObservable, onAttach: @escaping (MCPResourceDescriptor, MCPResourceContent) -> Void) public init(manager: MCPServerManagerObservable, onUse: @escaping (MCPPromptDescriptor, [MCPPromptMessage]) -> Void) +public init(model: ModelUpdateModel) { self.model = model } +public init(model: ModelVersionsModel) { self.model = model } public init(modelId: String, ok: Bool, detail: String) +public init(path: String, kind: Kind, oldSize: Int64? = nil, newSize: Int64? = nil) +public init(provider: any DownloadableModelProvider) +public init(registry: ModelRegistry) public init(registry: ModelRegistry, selection: Binding, show27OnlyModels: Bool = true) +public init(requests: [ModelOnboardingRequest], source: ModelOnboardingSource) public init(results: [ModelResult], message: String? = nil) +public init(revision: String, isCurrent: Bool, isComplete: Bool = true, freesBytes: Int64, sharedBytes: Int64 = 0) +public init(role: String = "Model", repoID: String, expectedRevision: String? = nil, validates: Bool = true) public init(serverName: String, onCancel: @escaping () -> Void) public let call: PendingToolCall public let core: MCPServerManager public let id: UUID public let request: MCPElicitationRequest public nonisolated func requestDecision(for call: PendingToolCall) async -> Bool +public private(set) var completed: [InstalledModel] = [] +public private(set) var currentRevision: String? +public private(set) var isLoading = false +public private(set) var isRunning = false +public private(set) var items: [ModelOnboardingItem] +public private(set) var message: String? +public private(set) var rollbackRevision: String? +public private(set) var state: State = .idle +public private(set) var versions: [ModelVersionRow] = [] public static func unableToRun(_ message: String) -> ProviderTestOutcome public struct AIModelsSettingsView: View public struct ClaudeAuthField: View @@ -2089,32 +2123,87 @@ public struct MCPOAuthWaitingView: View public struct MCPPromptsView: View public struct MCPResourcesView: View public struct MCPServerPickerView: View +public struct ModelFileChange: Sendable, Equatable, Identifiable +public struct ModelOnboardingItem: Sendable, Equatable, Identifiable +public struct ModelOnboardingRequest: Sendable, Equatable, Identifiable +public struct ModelOnboardingSource: Sendable +public struct ModelOnboardingView: View public struct ModelPickerView: View public struct ModelResult: Sendable, Equatable, Identifiable +public struct ModelUpdateActions: Sendable +public struct ModelUpdateOffer: Sendable, Equatable +public struct ModelUpdateView: View +public struct ModelVersionRow: Sendable, Equatable, Identifiable +public struct ModelVersionsView: View public struct ProviderSettingsSection: View public struct ProviderTestOutcome: Sendable, Equatable public struct RemoteProviderDraft: Identifiable, Hashable, Sendable public struct ToolConfirmationRequest: Identifiable, Sendable public var addMenuLabel: String public var apiKey: String +public var apply: @Sendable ( +public var available: String public var baseURL: String public var body: some View +public var canUpdate: Bool +public var cancel: @Sendable (String) -> Void +public var changes: [ModelFileChange] +public var check: @Sendable () async throws -> ModelUpdateOffer public var configured: Bool +public var current: String public var detail: String public var displayName: String +public var download: @Sendable (String, @escaping @Sendable (DownloadProgress) -> Void) async throws -> InstalledModel +public var download: ModelOnboardingStepState = .pending +public var downloadFraction: Double? +public var downloadedBytes: Int64 = 0 public var errorDescription: String? +public var expectedRevision: String? +public var freesBytes: Int64 +public var hasFailed: Bool { [validate, download, pin].contains { if case .failed = $0 { true } else { false } } } +public var hasFailed: Bool { items.contains { $0.hasFailed } } +public var hasStarted: Bool { items.contains { $0.validate != .pending } } public var id: String { modelId } +public var id: String { path } +public var id: String { repoID } +public var id: String { request.repoID } +public var id: String { revision } public var id: String { scheme } +public var isBusy: Bool +public var isComplete: Bool +public var isComplete: Bool { if case .done = pin { true } else { false } } +public var isCurrent: Bool +public var isFinished: Bool { !isRunning && !items.isEmpty && items.allSatisfy(\.isComplete) } +public var isSwitching: Bool { state == .switching } +public var isUpToDate: Bool { current == available } +public var kind: Kind public var kind: RemoteProviderKind public var maxSearches: Int public var message: String? public var modelId: String public var models: [String] +public var newSize: Int64? public var ok: Bool +public var oldSize: Int64? +public var ownership: ModelUpdateOwnership +public var path: String +public var pauseInference: (@Sendable () async throws -> Void)? +public var pin: ModelOnboardingStepState = .pending +public var repoID: String +public var request: ModelOnboardingRequest public var results: [ModelResult] +public var revision: String +public var role: String public var scheme: String +public var sharedBytes: Int64 +public var shippedRevision: String? public var sortedServers: [MCPServerState] public var statusText: String? +public var summary: String +public var totalBytes: Int64 = 0 +public var validate: @Sendable (String) async throws -> PreflightResult? +public var validate: ModelOnboardingStepState = .pending +public var validates: Bool public var webSearchEnabled: Bool public var webSearchSupported: Bool ``` diff --git a/docs/migrating-to-1.0.md b/docs/migrating-to-1.0.md index 43601e5..dc6bff5 100644 --- a/docs/migrating-to-1.0.md +++ b/docs/migrating-to-1.0.md @@ -28,8 +28,8 @@ The `examples/*/Package.swift` files resolve each SDK module as a `binaryTarget` checksum, keyed by version. A newer version is a new entry: ```swift -"1.0.0-beta.3": SDKRelease( - url: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-beta.3/LocalLMLabSDKCore-1.0.0-beta.3.xcframework.zip", +"1.0.0-GA": SDKRelease( + url: "https://github.com/ancientcomputing/locallm/releases/download/v1.0.0-GA/LocalLMLabSDKCore-1.0.0-GA.xcframework.zip", checksum: "" ), ``` diff --git a/docs/sdk-guide.md b/docs/sdk-guide.md index 44a63d3..cbcae4d 100644 --- a/docs/sdk-guide.md +++ b/docs/sdk-guide.md @@ -9,8 +9,10 @@ below for the working reference apps this guide is drawn from. Requires macOS 26+ on Apple Silicon, Swift 6 tools. -**Status note**: this SDK is early — this guide describes the API as it exists today, and it will -change. `Components` in particular is newer and smaller than `Core`. +**Status note**: `1.0.0` is generally available — source compatible from `1.0.0-RC.1` onward (see +[§9](#9-whats-not-in-core-yet) for the compatibility policy, or +[`migrating-to-1.0.md`](migrating-to-1.0.md) if you're coming from `0.8.x`). This guide describes +the API as of `1.0.0` GA. `Components` in particular is newer and smaller than `Core`. ## Start here: run a real example before reading further @@ -3474,6 +3476,20 @@ struct ModelOnboardingRequest: Sendable, Equatable, Identifiable { struct ModelOnboardingSource: Sendable { init(provider: any DownloadableModelProvider) // or init(registry: ModelRegistry) } +enum ModelOnboardingStepState: Sendable, Equatable { + case pending, running, done(String), failed(String) +} +struct ModelOnboardingItem: Sendable, Equatable, Identifiable { // one repo's progress through the flow + var id: String { request.repoID } + var request: ModelOnboardingRequest + var validate: ModelOnboardingStepState = .pending + var download: ModelOnboardingStepState = .pending + var pin: ModelOnboardingStepState = .pending + var downloadFraction: Double? // 0...1 while downloading, nil otherwise + var downloadedBytes: Int64 = 0 + var totalBytes: Int64 = 0 + var hasFailed: Bool { get }; var isComplete: Bool { get } // true once `pin` is .done +} @MainActor @Observable final class ModelOnboardingModel { init(requests: [ModelOnboardingRequest], source: ModelOnboardingSource) func start(); func cancel(); func reset() @@ -3483,6 +3499,23 @@ struct ModelOnboardingView: View { init(model: ModelOnboardingModel, showsDownloadProgress: Bool = true, onFinished: (([InstalledModel]) -> Void)? = nil, onDismiss: (() -> Void)? = nil) } +struct ModelFileChange: Sendable, Equatable, Identifiable { + enum Kind: Sendable, Equatable { case added, removed, modified } + var id: String { path } + init(path: String, kind: Kind, oldSize: Int64? = nil, newSize: Int64? = nil) +} +struct ModelUpdateOffer: Sendable, Equatable { + var current: String // the version the model is on now + var available: String // the version on offer + var changes: [ModelFileChange] + var isUpToDate: Bool { current == available } + init(current: String, available: String, changes: [ModelFileChange] = []) +} +enum ModelUpdateOwnership: Sendable, Equatable { + case userChosen // the user picked this model, so the user decides; the offer is whatever is newest + case developerOffered // built into the app — the developer vets versions; the offer is one they vouch for + case fixed(reason: String) // can't be updated here; `reason` is shown as-is +} struct ModelUpdateActions: Sendable { init(check: @escaping @Sendable () async throws -> ModelUpdateOffer, apply: @escaping @Sendable (_ revision: String, _ progress: @escaping @Sendable (Double) -> Void, @@ -3495,6 +3528,15 @@ struct ModelUpdateActions: Sendable { func checkForUpdate() async; func update() async; func rollBack() async; func revertToShippedVersion() async } struct ModelUpdateView: View { init(model: ModelUpdateModel) } +struct ModelVersionRow: Sendable, Equatable, Identifiable { // one cached version of a model, for the cleanup list + var id: String { revision } + var revision: String + var isCurrent: Bool // the version in use; cannot be removed + var isComplete: Bool // false for a half-downloaded version + var freesBytes: Int64 // what removing this version would actually free — its own files, not ones it shares + var sharedBytes: Int64 // bytes shared with other versions, which removing this one does NOT free + init(revision: String, isCurrent: Bool, isComplete: Bool = true, freesBytes: Int64, sharedBytes: Int64 = 0) +} @MainActor @Observable final class ModelVersionsModel { init(list: @escaping @Sendable () async -> [ModelVersionRow], remove: @escaping @Sendable (ModelVersionRow) async throws -> Int64) // returns bytes freed; must refuse the current version From 0ed2622566e42f78f7ce41843b0a1a83012e9e9f Mon Sep 17 00:00:00 2001 From: ancientcomputing Date: Sun, 27 Sep 2026 13:27:51 -0700 Subject: [PATCH 4/4] docs: remove stale pre-GA "not yet"/roadmap language Section 9 of sdk-guide.md mixed permanent design boundaries with historical beta-era changelog notes (strikethrough "now exists" callouts, a beta/RC.1 stability caveat). Retitled it "Scope and boundaries: what Core doesn't do" and rewrote it to state the current GA guarantee and permanent boundaries only. Also swept sdk-guide.md, annotated-examples.md, and tested-models.md for similar "not yet tested" / "on the list" / "roadmap item" / "post-beta item" phrasing that reads as a pending gap in a GA-facing doc, and reworded each as either shipped behavior or a deliberate, permanent characteristic. Added a note to sdk-guide.md's "Start here" section that the examples are free starting points for SDK users to build on, not just reading material. --- docs/annotated-examples.md | 32 ++++++++++------------- docs/sdk-guide.md | 52 +++++++++++++++++--------------------- docs/tested-models.md | 11 ++++---- 3 files changed, 42 insertions(+), 53 deletions(-) diff --git a/docs/annotated-examples.md b/docs/annotated-examples.md index fc78646..b2e2be6 100644 --- a/docs/annotated-examples.md +++ b/docs/annotated-examples.md @@ -57,8 +57,8 @@ below for the same app rebuilt on Core's ready-made "Path A" `Tool`s instead. ```swift // "What's on my plate today" — v1: Todoist (via Core's MCP client) + Calendar + Reminders (also -// via Core, through CalendarAccess/RemindersAccess — see below). Linear is a planned v2 addition, -// deliberately deferred. +// via Core, through CalendarAccess/RemindersAccess — see below). Linear is intentionally out of +// scope for this example — it demonstrates Calendar/Reminders/Todoist only. // // SwiftUI app shape (not a bare CLI): launch -> request Calendar/Reminders/Todoist access on // first run -> pull + synthesize -> show result -> Done closes the app. Packaged as a real signed @@ -79,10 +79,9 @@ struct TodaysEventsTool: Tool { let description = "Retrieve the user's calendar events for today" // Zero-property Arguments is valid and correct for a no-input tool (proven by Core's - // ClockTool) -- an earlier "unused placeholder" field here was a fragile workaround that - // actively caused decode failures: FoundationModels sometimes calls a tool with genuinely - // empty generated content when no argument makes sense, and a required-but-unused field then - // fails to decode from that empty content. + // ClockTool). Don't add a placeholder field to satisfy the schema: FoundationModels + // sometimes calls a tool with genuinely empty generated content when no argument makes + // sense, and a required-but-unused field then fails to decode from that empty content. @Generable struct Arguments {} @@ -106,10 +105,9 @@ struct TodaysRemindersTool: Tool { let description = "Retrieve the user's incomplete reminders due today" // Zero-property Arguments is valid and correct for a no-input tool (proven by Core's - // ClockTool) -- an earlier "unused placeholder" field here was a fragile workaround that - // actively caused decode failures: FoundationModels sometimes calls a tool with genuinely - // empty generated content when no argument makes sense, and a required-but-unused field then - // fails to decode from that empty content. + // ClockTool). Don't add a placeholder field to satisfy the schema: FoundationModels + // sometimes calls a tool with genuinely empty generated content when no argument makes + // sense, and a required-but-unused field then fails to decode from that empty content. @Generable struct Arguments {} @@ -137,10 +135,9 @@ struct TodaysLocationTool: Tool { let description = "Returns the user's current one-shot location (place name, if available) — useful as input to the weather tool." // Zero-property Arguments is valid and correct for a no-input tool (proven by Core's - // ClockTool) -- an earlier "unused placeholder" field here was a fragile workaround that - // actively caused decode failures: FoundationModels sometimes calls a tool with genuinely - // empty generated content when no argument makes sense, and a required-but-unused field then - // fails to decode from that empty content. + // ClockTool). Don't add a placeholder field to satisfy the schema: FoundationModels + // sometimes calls a tool with genuinely empty generated content when no argument makes + // sense, and a required-but-unused field then fails to decode from that empty content. @Generable struct Arguments {} @@ -171,10 +168,9 @@ struct TodoistTasksTool: Tool { let serverURL: URL // Zero-property Arguments is valid and correct for a no-input tool (proven by Core's - // ClockTool) -- an earlier "unused placeholder" field here was a fragile workaround that - // actively caused decode failures: FoundationModels sometimes calls a tool with genuinely - // empty generated content when no argument makes sense, and a required-but-unused field then - // fails to decode from that empty content. + // ClockTool). Don't add a placeholder field to satisfy the schema: FoundationModels + // sometimes calls a tool with genuinely empty generated content when no argument makes + // sense, and a required-but-unused field then fails to decode from that empty content. @Generable struct Arguments {} diff --git a/docs/sdk-guide.md b/docs/sdk-guide.md index cbcae4d..833739d 100644 --- a/docs/sdk-guide.md +++ b/docs/sdk-guide.md @@ -10,14 +10,16 @@ below for the working reference apps this guide is drawn from. Requires macOS 26+ on Apple Silicon, Swift 6 tools. **Status note**: `1.0.0` is generally available — source compatible from `1.0.0-RC.1` onward (see -[§9](#9-whats-not-in-core-yet) for the compatibility policy, or +[§9](#9-scope-and-boundaries-what-core-doesnt-do) for the compatibility policy, or [`migrating-to-1.0.md`](migrating-to-1.0.md) if you're coming from `0.8.x`). This guide describes the API as of `1.0.0` GA. `Components` in particular is newer and smaller than `Core`. ## Start here: run a real example before reading further This guide's actual on-ramp is the working code under [`examples/`](../examples/), not the prose -below — each one is real, runnable code you can clone and read end to end, not a snippet. Most +below — each one is real, runnable code you can clone and read end to end, not a snippet. These +examples are yours to build on: clone one, strip out what you don't need, and ship the rest as +part of your own app — they're starting points, not just reading material. Most are real signed `.app`s ([`aiql`](../examples/aiql/) is the most complete: App Sandbox, MCP, the model layer, and the SQL pipeline all in one place); a few (`repo-qa`, `os-matrix`, `code-buddy`, `repo-qa-local`) are plain command-line tools with no packaging step at all. Pick the one closest @@ -1983,9 +1985,21 @@ over an MCP dataset → this pipeline → a CSV in a folder you chose, with a lo builds the session with `SessionOptions(effort: .off)` so the Qwen3 model skips its `` pass — the pipeline is mechanical enough that the reasoning trace only adds latency ([§6a](#6a-the-model-layer-local-models-routing-sessions)). -## 9. What's NOT in Core yet +## 9. Scope and boundaries: what Core doesn't do -- **No filesystem picker/bookmark UI in Core, and not planned** — a folder picker is host-app +**Source compatibility is guaranteed from `1.0.0` GA on.** Every 1.x release keeps existing +code compiling unmodified against a later one. New capability shows up as additive surface +(new optional/defaulted parameters, new protocol methods with a default implementation, new +enum cases per the `@unknown default` point below); anything that would force you to edit +working code just to keep building waits for 2.0. If you hit "X is inaccessible due to +internal protection level" on something that looks like it should be public, file it — that's +a bug against the guarantee, not expected churn. This covers source compatibility, not binary +— you rebuild against whatever version you pin, there's no supported "drop in a newer +xcframework without recompiling" path. + +The following are deliberate boundaries, not gaps waiting on a future release: + +- **No filesystem picker/bookmark UI in Core** — a folder picker is host-app UI and Core ships no UI at all. But you're not writing it from scratch: [§8](#8-filesystem-access-security-scoped-bookmarks-example-not-in-core) (Filesystem access — security-scoped bookmarks) has a complete, copy-pasteable `FolderAccess` (`NSOpenPanel` + security-scoped bookmark persistence + the async-aware access window a @@ -1993,29 +2007,9 @@ pass — the pipeline is mechanical enough that the reasoning trace only adds la [`workspace-buddy`](../examples/workspace-buddy/) is a full reference app that does exactly this. What *is* in Core: `WorkspaceAccess`/`WorkspaceTools` ([§8a](#8a-workspaceaccessworkspacetools-what-core-gives-you-once-you-have-that-url) — Workspace tools) — the read/write/edit logic for once you have a resolved folder URL. -- ~~No ready-made `Tool` wrappers for the connectors, no MCP-to-`Tool` bridge.~~ Both now exist — - see [§7a](#7a-two-paths-to-tool-calling-ready-made-tools-or-write-your-own) (ready-made vs. hand-written tools). -- ~~No handling of server-initiated requests (elicitation, sampling, roots).~~ All three are now - handler seams (`MCPClientHandlers`), with a default elicitation UI in Components — see [§3c](#3c-server-initiated-requests-elicitation-and-the-sampling--roots-seams). The - SDK still doesn't *implement* sampling or roots; it routes them to your handler if you register - one, else replies "method not found". -- ~~No model abstraction — you construct a `LanguageModelSession` yourself.~~ 1.0 adds - the model layer ([§6a](#6a-the-model-layer-local-models-routing-sessions)): `LocalLMLab` / `ModelRegistry` / providers / `MLXModelProvider` (in - `LocalLMLabSDKInference`) / `makeSession`. Still optional — the MCP-only path is unchanged. - **`ModelAvailability` is a non-frozen `enum`.** If you `switch` over it exhaustively you need an `@unknown default` — new cases can land in a minor version. (Same for `ResidencyEvent` / `SessionEvent` / `DownloadEvent` / `MCPConnectionStatus` / `MCPServerError`.) -- **No public API stability guarantee before RC.1.** `1.0.0-beta.N` made none — access levels - were fixed reactively as real usage surfaced gaps, and a few signatures changed between beta.4 - and RC.1 (see the CHANGELOG). If you hit "X is inaccessible due to internal protection level" on - something that looks like it should be public, it probably should. File it. **From `1.0.0-RC.1` - onward this changes**: later release candidates, `1.0.0` GA and every 1.x release commit to - source compatibility — existing code keeps compiling unmodified against a later one. - New capability shows up as additive surface (new optional/defaulted parameters, new - protocol methods with a default implementation, new enum cases per the `@unknown default` point - above); anything that would force you to edit working code just to keep building waits for 2.0. This covers source compatibility, not binary — you rebuild - against whatever version you pin, there's no supported "drop in a newer xcframework without - recompiling" path. - **No logging of prompts, responses, or tool calls.** The MCP client has `MCPDiagnostics` ([§3e](#3e-diagnostics-when-a-user-reports-an-mcp-problem)) for connection / auth / stream troubleshooting — `os.Logger` plus an opt-in event buffer — but it is strictly off-content (never prompt or response text; tokens redacted). Core writes @@ -2075,9 +2069,9 @@ specific connector). - **Keychain token storage** (`MCPOAuthTokenStore`/`MCPPATStore`, [§4](#4-keychain-storage--automatic-isolation-native-api-sandbox-safe)) — round-tripped correctly under the sandboxed per-app-container Keychain access group. -**Not yet tested under sandbox**: Contacts, Location's accuracy/reverse-geocoding behavior beyond -"it returns something" (a real, pre-existing, non-sandbox-specific bug in reverse geocoding was -hit during testing, unrelated to sandboxing itself). +**Outside the scope of sandbox testing to date**: Contacts, and Location's accuracy/reverse-geocoding +behavior beyond "it returns something" (a real, pre-existing, non-sandbox-specific bug in reverse +geocoding was hit during testing, unrelated to sandboxing itself). ### 10c. A testing caution: reset TCC before you trust a "no prompt" result @@ -2251,8 +2245,8 @@ polling): you adapt from your provider — about forty lines; `Components/README.md` has the adapter. `ModelPickerView` (local models + MLX download) and `AIModelsSettingsView` (online providers) are -currently **separate surfaces** — a full "AI Models" panel composes both. Unifying them is on the -list; for now, present whichever your app needs, or stack them. +two separate surfaces by design — compose a full "AI Models" panel by presenting whichever your +app needs, or stacking both. None of these views hold persistence of their own — the MCP views go through `manager.core.restore(from:)`, the model views through `lab.snapshot()` / `lab.restore(from:)` diff --git a/docs/tested-models.md b/docs/tested-models.md index e63e590..a789da2 100644 --- a/docs/tested-models.md +++ b/docs/tested-models.md @@ -30,7 +30,7 @@ built-in `ClockTool` cross-check. | **DeepSeek** (R1-Distill-Qwen 7B/14B, R1-Distill-Llama 8B, V2-Lite-Chat) | ❌ | 4/4 zero tool calls, across 3 lineages + 2 base architectures. Root cause: chat templates with no working tool-definition/tool-call mechanism the app can drive. Also fabricates confidently. **Check the chat template before downloading any DeepSeek model for tool use.** | | **Phi-4** (14B, `mlx-community/phi-4-4bit`) | ❌ | Same root cause as DeepSeek despite an "instruction/tool-tuned" reputation. Phi-4-mini untested — different checkpoint, don't assume it carries over. | | **Phi-4-mini**, **SmolLM3-3B** | ❌ | Fail on the *input* side: templates try to list tools via a convention `swift-transformers` doesn't supply. Structurally unreachable regardless of the model. SmolLM3 then fabricates badly. | -| **gpt-oss-20B** | ⚠️ app-side gap | The model correctly formats a real call — in OpenAI's "Harmony" format, which `mlx-swift-lm` has no parser for, so the call is never recognized. Not a model gap; tracked as a roadmap item. | +| **gpt-oss-20B** | ⚠️ app-side gap | The model correctly formats a real call — in OpenAI's "Harmony" format, which `mlx-swift-lm` has no parser for, so the call is never recognized. Not a model gap; a known limitation of `mlx-swift-lm`'s parser. | ## Capacity notes (this Mac, this workload) @@ -58,8 +58,7 @@ built-in `ClockTool` cross-check. ## Chain-of-thought in output Several of these models (Qwen3's `…`, Gemma's `<|channel|>` markers) emit -raw reasoning inline in the response text. The 1.0.0-beta MLX bridge streams that through -verbatim — it does **not** separate a reasoning channel (Apple's `streamResponse` doesn't -surface incremental reasoning; a real reasoning channel is a post-beta item). If you want a -clean answer, carve the delimiters out consumer-side, as LocalLM Lab's own Prompt Playground -does. +raw reasoning inline in the response text. The MLX bridge streams that through verbatim — it +does **not** separate a reasoning channel (Apple's `streamResponse` doesn't surface incremental +reasoning). If you want a clean answer, carve the delimiters out consumer-side, as LocalLM Lab's +own Prompt Playground does.