llama_cpp_flutter 0.6.1
llama_cpp_flutter: ^0.6.1 copied to clipboard
On-device LLM inference for Flutter: llama.cpp with Metal on iOS/macOS, wllama on web. Streaming sessions, chat formats, model downloads, and memory-aware multi-agent orchestration.
Changelog #
0.6.1 #
-
Fixed: a failed model download or import on the web reported
TypeError: Cannot close a ERRORED writable streaminstead of the real cause. When a write into OPFS rejected — quota exhausted, the origin's storage evicted, the connection dropped mid-transfer — the recovery path calledclose()on the writable, which is invalid once the stream has errored. TheTypeErrorthat raised was thrown from inside thecatchblock, so it displaced theArtifactStorageExceptionthat would have named the actual failure. The stream is now discarded withabort(), which is valid in that state, and the happy-pathclose()is guarded so a late sink error surfaces as anArtifactStorageExceptiontoo. Because theTypeErroralso escaped before the cleanup that followed it, a failed import left its partial file and in-flight marker behind in OPFS rather than removing them; that cleanup now runs. -
Fixed: loading a GGUF of 2 GiB or more on the web failed with
Unsupported operation: Uint64 accessor not supported by dart2js. Such a file cannot be staged in wasm32, so it goes through the client-side splitter — which read and wrote its 64-bit header fields withByteData.get/setUint64. Those accessors throw under dart2js, the one platform the splitter runs on, so the path failed for every oversized model. The 64-bit fields are now composed from their two 32-bit halves. GGUF header tests run under--platform chrometo keep the JS path covered.
0.6.0 #
Breaking: agents is no longer a dependency. This package now depends
only on extensions, so the agent framework layered on top — if any — is
entirely the host app's choice. The practical win is the SDK floor: Dart
^3.11.5 → ^3.9.0, Flutter >=3.41.7 → >=3.35.0, since the old floor
came from agents rather than from anything in this package. extensions
remains a direct dependency and the ChatClient API is unchanged.
Two removals, both pre-1.0 and both easy to restore in your own code:
-
AgentHandle.agentis gone. It built aChatClientAgentfrom the handle's profile. Build it yourself fromAgentHandle.chatClient— the profile is still carried verbatim onAgentHandle.profile(id,name,description,instructions,tools), andchatClientstill returns one cached instance per handle, so an agent built from it keeps a single KV-cache identity:final agent = ChatClientAgent( handle.chatClient, options: ChatClientAgentOptions() ..id = handle.profile.id ..name = handle.profile.name ?? handle.profile.id ..description = handle.profile.description ..chatOptions = ChatOptions( instructions: handle.profile.instructions, tools: handle.profile.tools, ), ); -
messagesWithRuntimeContextis gone, andmessagesWithInstructionsno longer calls it — it now only materializesChatOptions.instructionsas the leading system message. This is a silent behavior change for anyone who calledmessagesWithInstructionsdirectly: messages are no longer reordered.What it did: text-only messages attributed to an
AIContextProviderwere pulled out and re-inserted as oneRuntime context:turn immediately before the latest user message. Detecting them required theagentsattribution API, so the behavior cannot live here anymore. It is worth re-implementing in whatever agent layer replaces it, because the reasoning is non-obvious: such context must not be merged into the system instructions, since that text is the head of the rendered prompt and any per-turn change to it invalidates the whole llama.cpp KV-cache prefix and forces a full re-prefill every turn. Placing it after the stable history keeps the prefix reusable while the model still reads it right before the request. SeemessagesWithRuntimeContextin 0.5.0 for the implementation.
AgentProfile.tools keeps its List<AITool>? type (AITool comes from
extensions); it is configuration only, and nothing in this package
executes it.
0.5.0 #
-
New
ArtifactStore, exported frompackage:llama_cpp_flutter: app-managed storage for model artifacts, with one API on every platform — a directory the app names on iOS/macOS, the origin-private file system on web. Build one withcreateArtifactStore, thenfetcha URL orimportFile/importStreama local file into it, andresolvethe stored keys into thelocalPath/localMmprojPath/localDraftPathargumentsloadModeltakes.list,lookup,totalSizeBytes, anddeleteare what a model-library UI needs to show users what is on their device and take it back off.This is the alternative to an engine's opaque cache. Previously a host app could either hand
loadModela path it managed entirely itself (native only) or let the runtime download to somewhere it could not enumerate — on web, into wllama's internal URL cache.Downloads resume where they stopped and never report a partial file as complete: native transfers finalize through
ModelDownloader's.partrename, and web transfers carry an in-flight marker alongside the data.importFilecopies by default — a macOS document picker hands back the user's real path — and moves only when the caller opts in withmoveSource, renaming instead of duplicating a multi-gigabyte GGUF when the source is on the same volume. Storage failures surface asArtifactStorageException, withisQuotaExceededset when the browser is out of room.On web,
resolvereturns opaque handles rather than blob URLs, and the runtime dereferences them straight to their stored files. A model past the ~2 GiB wasm32 per-file limit is split into stageable parts from disk, as the runtime's own oversized-model path already did — so managed storage handles large models transparently instead of reading gigabytes back through the network stack. Speculative-decoding draft models stay native-only. -
The web runtime's oversized-model cache now writes through the same OPFS directory and names as
ArtifactStore, so a model it downloaded on its own is listable and deletable through managed storage. Artifacts cached by earlier versions are adopted in place, not re-downloaded. -
package:llama_cpp_flutter/gguf.dartaddsimportedArtifactFileNameandartifactDisplayNamealongsidestableArtifactFileName. -
Example: the hidden model cache is now a user-managed model library built on
ArtifactStore. Models are added from the catalog, from a download URL, or from GGUF files on the device — each with an optional vision projector and, on native, a draft model — and the library shows what is stored, what it costs, and which model is loaded. Entries are editable (save, or save and reload), deletion is confirmed and removes only files no other entry references, and the catalog is persisted and reconciled with storage at startup. Image attachments are enabled only while the loaded model has a projector.
0.4.0 #
-
New
TokenSmootherstream transformer and theStream<String>.smoothed()extension, exported frompackage:llama_cpp_flutter/chat.dart. Token streams arrive in bursts; the smoother re-paces them into a steady, typewriter-style grapheme stream for display.The release rate tracks the measured arrival rate rather than draining the backlog on a fixed schedule — it estimates how fast text is arriving, releases at that rate while holding about
windowin reserve, and uses the backlog only as a correction, with the rate low-pass filtered oversmoothingso speed changes ramp instead of jump. The rate is fractional and carried across frames, so it can emit slower than one grapheme per frame and match a slow model instead of outrunning it. Against a 5 tok/s source the worst gap between graphemes is 64 ms (median 48 ms), versus 152 ms (median 16 ms) for fixed-window draining, which empties its buffer in four frames and then stalls.Grapheme clusters (emoji ZWJ sequences) are never split, an
atomicpredicate keeps in-band markers from rendering half-formed, and the tail drains withinwindowof the source ending. Opt-in by design — generation is not smoothed automatically, so headless and batch callers are unaffected. Apply it where the text is rendered:session.generate(prompt).smoothed(). -
Adds a direct dependency on
package:characters.
0.3.2 #
- Example: the web demo now deploys to GitHub Pages on every push to
main, and vendorscoi-serviceworkerto inject COOP/COEP headers on hosts that can't set them — keeping wllama multi-threaded on Pages. No library changes.
0.3.1 #
- Upstream: llama.cpp
b10069→b10091on both backends. The native xcframework re-pins to theb10091release, and the vendored wasm is now built from wllama 3.5.1 sources with its llama.cpp submodule at that same tag (previously the stock npm build, whose embedded llama.cpp dated from June 2026). Keep loading@wllama/wllama3.5.1 on the page — the JS pairing is unchanged. Verified in-browser: model download, load, and streamed generation. - New maintenance pipeline:
tool/update_deps.sh(native re-pin with ABI check),tool/update_wllama.sh(wasm refresh with recorded provenance),tool/check_llama_ext_abi.sh(staging-ABI tripwire), a CI workflow (analyze/test, ABI check, macOS link build), and a weekly workflow that re-pins both backends to the same llama.cpp release and opens a PR — including rebuilding the wllama wasm against the pinned tag.
0.3.0 #
- New:
generateEvents()onLlamaSession— a typedStream<LlamaGenerationEvent>(LlamaTextEvent/LlamaCompletedEvent/LlamaWarningEvent) over the same generation contract asgenerate(). A successful run always ends with a completed event carrying the engine's stats, so finish reason and token accounting cannot be missed. Non-breaking: implemented as an extension over the existing string stream. - Fixed: the native session now reports
capabilities.canSetImageTokenBudgetasfalsefor sessions loaded without a multimodal projector (previously alwaystrue, and callingsetImageTokenBudgeton a text-only session could only fail natively).
0.2.0 #
Pre-1.0 API cleanup release. Pinned upstream: llama.cpp b10069
(xcframework, sha256-verified); wllama wasm vendored as a Flutter asset.
Breaking changes #
- The bridge session type is renamed
LlamaSession→LlamaBridgeSession(bridge.dart); the neutralLlamaSessionin the main entrypoint is unchanged. LlamaChatTurnnow carries a typed role (LlamaChatRole, includingtool) and ordered content parts (LlamaContentPart:LlamaTextPart/LlamaImagePart/LlamaAudioPart) instead of a role string with separatetext/images/audiofields. The old fields remain as read-only getters derived fromparts; construct turns withparts:orLlamaChatTurn.text(...). Interleaved text/media ordering is now preserved end to end (the web runtime sends parts in author order).- The main entrypoint exports far less. Concrete chat formats, templates,
and stream decoders moved to
package:llama_cpp_flutter/chat.dart; GGUF metadata reading and artifact cache naming topackage:llama_cpp_flutter/gguf.dart; the orchestration layer topackage:llama_cpp_flutter/orchestration.dart.resolveChatFormat,detectChatFormatNameForGguf,createLlamaChatClient,ModelSpec,ModelDownloader, and the runtime API stay in the main entrypoint. - Overriding the pinned xcframework tag
(
LLAMA_CPP_TAG_OVERRIDE) now requires the matchingLLAMA_XCFRAMEWORK_ZIP_SHA256_OVERRIDE, or an explicitLLAMA_CPP_ALLOW_UNVERIFIED=1opt-out (development only); previously verification was silently skipped.
Changed #
- SDK floor lowered from Dart
^3.12.0/ Flutter>=3.44.0to Dart^3.11.5/ Flutter>=3.41.7(the floor now comes from theagentsdependency, not this package). createLlamaRuntime()gainsartifactCacheDirectoryfor download-on-load, and throws a clearUnsupportedErroron IO platforms without a native backend (Android, Windows, Linux) instead of failing later with a missing-plugin error.LlamaSessiondocuments its concurrency and lifecycle contract (one generation at a time; overlappinggeneratesupersedes;canceland dispose-during-generation semantics).- Core data classes (
ModelSpec,SamplingDefaults,LlamaGenerationStats,LlamaSessionCapabilities,ImageTiling,AgentSnapshot) gain value equality andtoString;LlamaSessionCapabilitiesandModelSpecassert their invariants.
0.1.0 #
Initial release.
- Cross-platform
LlamaRuntime/LlamaSessionAPI over llama.cpp:- iOS / macOS via a vendored Metal-enabled
llama.xcframework(downloaded from official llama.cpp releases duringpod install) with a typed Pigeon bridge. All native calls run on a dedicated worker isolate so model loading and token streaming never block the UI. - Web via
@wllama/wllama, with the matchingwllama.wasmshipped as a Flutter asset.
- iOS / macOS via a vendored Metal-enabled
ChatClientimplementations for theagentsframework, backed by local GGUF models.- Chat format layer with auto-detection from GGUF metadata: ChatML, Gemma, LFM2, Llama 3, Mistral, and Qwen templates, including streaming tool-call decoding (Hermes-style and model-specific markers).
- GGUF utilities: metadata reader, split-model (
-00001-of-0000N) support, and a resumable Hugging Face model downloader. - Memory-aware multi-agent orchestration over a single loaded model: memory estimation and budget planning, runtime memory monitoring, session snapshot store, and artifact staging.
- MTP speculative decoding on iOS/macOS via the
LlamaExtShimstaging ABI, with a CI ABI-drift check. - Prompt inspector diagnostics for examining rendered prompts.