Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
0.4.0 - 2026-08-14
Added
generable()— declarative typed schema builder for structured output with full TypeScript type inference, the equivalent of the Python SDK's@generabledecoratorSystemLanguageModel.contextSize— read the model's context window size (back-deployed from macOS 26.4 SDK)SystemLanguageModel.tokenCount()— count the tokens a prompt, instruction set, tool list, schema, or transcript consumes against the context window. Asynchronous, requires a macOS 26.4+ runtime.- Prompt attachments — every method taking a prompt now accepts
{ text, attachments }as well as a string. Requires macOS 27 and a native library built against the macOS 27 SDK; until then each attachment is refused with aPromptAttachmentErrornaming the reason. SystemLanguageModel.supportedLanguages— list supported language codesSystemLanguageModel.supportsLocale()— check if a specific locale is supportedLanguageModelSession.prewarm()— preload model resources and optionally cache a prompt prefix to reduce first-response latencyGeneratedContent.dispose()/Symbol.dispose— explicit resource cleanup for structured output results, withFinalizationRegistryauto-cleanup as a safety netTranscript.dispose()/Symbol.dispose— release the C object behind a standalone transcript fromfromJson()/fromDict(), withFinalizationRegistryauto-cleanup as a safety net. No-op for the transcript reached throughsession.transcript, which the session frees.GeneratedContent.toObject<T>()— pass the shape the schema guarantees instead of asserting at the call site. Defaults toJsonObject, so existing calls are unaffected.NativeTypeNametype export — compound array type names ("array<string>","array<integer>", etc.) for use withGenerationSchema.property()decodeString()— decode a C string pointer without freeing it, for use in callbacks where the C side owns the memoryTool.onCallnow receives parsed arguments as a second parameter:(toolName, args)instead of(toolName)- Input validation:
temperaturemust be ≥ 0,maximumResponseTokensmust be a positive integer — both throw immediately on invalid values - Explicit FFI type casts (
as NativePointer,as boolean, etc.) at all C call sites - 3 new examples:
contact-card(nested generable schemas),email-triage(JSON Schema + streaming + tools),journal(tools + transcript persistence) - ESLint:
no-floating-promisesandno-consoleforsrc/,no-evalandno-debuggerglobally - Unit tests for
generable(), streaming edge cases, compatreorderJsonwith array items, disposed session guards, stream queue-stall recovery, and all 3 new examples
Fixed
Transcript.fromJson()andfromDict()leaked their native object. Each allocated a C object with no way to release it, since the class had nodispose(), noSymbol.dispose, and noFinalizationRegistry.Building from source validated the wrong toolchain: the Xcode version check ran before
DEVELOPER_DIRwas repointed at an installedXcode-beta.app, so the build could use an SDK that was never checked.Streaming no longer discards a response whose text is exactly
null. The callback treated that string as a koffi coercion artifact, so such a response streamed as nothing at all. koffi marshals the end-of-stream signal to JSnull, never to the string, so there was no artifact to filter.Upstream C bridge moved to apple/python-apple-fm-sdk@e868e608, which changed the prompt parameter of all four response entry points from
const char *to an opaque composed-prompt object. The build now pins that revision, since koffi binds by symbol name and cannot see a changed parameter type.Stream setup failures no longer stall the request queue permanently (native init moved inside try/finally)
Stream idle timeout (30s) prevents permanent hangs when native callbacks stop firing. Armed between snapshots rather than after a tool-call snapshot, since the artifact it originally keyed on does not occur.
Disposed session methods (
respond,respondWithSchema,respondWithJsonSchema,streamResponse) now throwFoundationModelsErrorimmediately instead of calling into freed native memoryFinalizationRegistrycallbacks across all classes now log warnings viaconsole.warninstead of silently swallowing errorsBetter error message when
libFoundationModels.dylibis not found — lists all searched paths and suggestsnpm run buildStreaming iterator now resets the session (
FMLanguageModelSessionReset) on earlybreakto prevent stalled subsequent calls
Changed
- Declare
generable()property maps withsatisfies Record<string, PropertyDef>(or inline them at the call). Assigning them to a plainconstfirst widensoptional: truetoboolean, andInferSchemathen marks every property required. The bundled examples show the pattern. - Breaking:
engines.noderaised from>=20to>=24. Installing on Node 20 or 22 no longer works. koffiupgraded from^2.15.1to^3.1.5. This is the runtime FFI dependency, and its marshalling of null C strings differs from 2.x — see the streaming fix above.- Development toolchain moved to TypeScript 7 (
@typescript/native, with 6.0.2 available astsc6),openai7,@types/node26, and ESLint 10. - Building the dylib from source now requires Xcode 26.4+, the first SDK that declares
SystemLanguageModel.contextSize. The bundled prebuilt library is unaffected. generable()array properties now use compound type names ("array<string>","array<Name>") matching the Python SDK's C bridge conventionGenerationSchema.property()rejects bare"array"type — use compound form like"array<string>"or usegenerable()for automatic type resolution- Prettier scope widened from
src/to entire repo (excluding*.md); added.prettierignore - Standardized "Apple Foundation Models" terminology (dropped possessive "'s") across docs and config
- README license section rewritten with copyright notice and Apple trademark disclaimer
docs/tsconfig.jsonadded for VitePress theme type checking- CSS: added
.VPHero .taglinemax-width constraints for responsive layout
0.3.1 - 2026-03-12
Added
Tool.onCall— optional callback that fires at the start of each tool invocation, beforecall()runs. Useful for showing UI indicators while the model waits for tool results.
0.3.0 - 2026-03-11
Added
- Chat & Responses API layer (
tsfm-sdk/chat) — industry-standard Chat-style and Responses-style APIs- Chat Completions API (
client.chat.completions.create()) with full message history, streaming, structured output (json_schema), and tool calling - Responses API (
client.responses.create()) — string or structured input, function tools, and streaming viaResponseStream - Parameter mapping:
temperature,max_tokens/max_completion_tokens,top_p,seed→ nativeGenerationOptions; unsupported params warned at runtime - Error mapping:
ExceededContextWindowSizeError→finish_reason: "length",GuardrailViolationError→finish_reason: "content_filter",RefusalError→message.refusal,RateLimitedError→ HTTP 429 StreamandResponseStreamasync iterables withtoReadableStream(),close(),Symbol.dispose, andFinalizationRegistrycleanup- Tool calling via structured output with
$defs/$refschemas to prevent parameter name collisions - JSON key reordering utility to match schema-defined property order
- Chat Completions API (
ServiceCrashedError— detects crashedgenerativeexperiencesdservice and provides recovery instructionsSymbol.disposesupport onSystemLanguageModel,LanguageModelSession,Tool, andClientfor TC39 Explicit Resource Management- Typed transcript entries:
TranscriptEntry,TranscriptContent,TranscriptTextContent,TranscriptStructuredContent,TranscriptToolCall,TranscriptEntryRoletypes andtranscript.entries()method JsonSchemaandJsonObjectexported types- Automatic session cleanup on
process.exit,SIGINT, andSIGTERMvia global session tracking - Enhanced
afmSchemaFormat()with recursive normalization for nested objects,$defs/$refsupport, andx-orderfields respondWithJsonSchema()now accepts typedJsonSchemainstead ofRecord<string, unknown>- Tool callback error handling: synchronous errors in
call()now invokeFMBridgedToolFinishCall()with error message to prevent session hang - Enhanced
statusToError(): mapsModelManagerError Code=1041toInvalidGenerationSchemaErrorwith descriptive message - Integration tests for Chat & Responses API layer (chat completions and Responses API)
- Unit tests for all compat modules (~4,300 lines of new test coverage)
- 6 new examples in
examples/compat/demonstrating Chat Completions and Responses API - Retry helper for integration tests (
retryAttempts()) for flaky on-device model responses
Changed
- Renamed model class from internal name to
SystemLanguageModelacross all public APIs and documentation Transcript.toDict()andfromDict()now useJsonObjecttype instead ofRecord<string, unknown>GeneratedContent.toObject()now returnsJsonObjectinstead ofRecord<string, unknown>serializeOptions()uses typedSerializedSamplingandSerializedOptionsinterfaces internally- Integration tests now use
waitUntilAvailable()instead of synchronousisAvailable()
Documentation
- Complete Chat & Responses API guide (505 lines), API reference (568 lines), and examples page (321 lines)
- Docs site visual overhaul: brand colors shifted to teal, Apple-style typography and font rendering, WCAG AA contrast fixes
- Landing page redesigned with code examples and Chat API showcase
- Swift-equivalent references extracted into caption-style info boxes across all guide pages
- Code blocks now word-wrap; inline code uses inherited text color with subtle background
- All guide pages updated with Apple conventions terminology alignment
0.2.3 - 2026-03-10
Fixed
NOTICEfile now included in published npm package
0.2.2 - 2026-03-10
Changed
- Renamed package from
afm-ts-sdktotsfm-sdk - Renamed GitHub repository from
codybrom/afm-ts-sdktocodybrom/tsfm
0.2.1 - 2026-03-09
Added
- Branded
NativePointertype for compile-time C pointer type safety unregisterCallback()utility to centralize callback cleanup logic- Discriminated union for
GenerationGuidedata, enabling exhaustive type checking - Comprehensive JSDoc comments on public APIs (
SystemLanguageModel,LanguageModelSession,Tool,Transcript,SamplingMode) stripInternalin tsconfig to exclude@internalsymbols from.d.tsoutput- Unit tests for error hierarchy and
statusToError()mapping - Integration test suite covering basic responses, streaming, structured output, tools, and transcripts
- GitHub Actions CI workflow (macOS, Node.js 20/22, lint + format + unit tests)
- Organized examples directory with individual READMEs for each example
Changed
- Renamed all internal pointer variables from abbreviations (
ptr,cbPtr) to full names (pointer,callbackPointer,_nativeSession,_nativeTool,_nativeSchema, etc.) InvalidGenerationSchemaErrornow extendsGenerationErrorinstead ofFoundationModelsError- All error-throwing paths now use
FoundationModelsErrororGenerationErrorsubclasses instead of genericError - Replaced
GenerationGuideseparateguideType/valuefields with a singledatadiscriminated union
Removed
- Monolithic
example.tsfile (replaced by organizedexamples/directory)
0.2.0 - 2026-03-08
Added
decodeAndFreeString()utility in bindings to safely decode C string pointers and free memory viaFMFreeString- ESLint (flat config) and Prettier for code linting and formatting
tsxdev dependency for TypeScript execution
Changed
- C function signatures for string-returning functions now declare return type as
void *instead ofstrto retain the pointer for proper memory management - Tool callback error handling now wraps errors in
ToolCallErrorwith proper context - Updated README import paths
Fixed
- Critical memory leak in all string-returning C functions —
koffi'sstrreturn type was copying strings but discarding the original pointer before it could be freed
Removed
- Unused
FMLanguageModelSessionCreateDefaultbinding (sessions always route throughCreateFromSystemLanguageModel) - Unused
FMRetainbinding (all Swift-to-JS transfers usepassRetained, onlyFMReleaseis needed)
0.1.0 - 2026-03-08
Added
- TypeScript/Node.js bindings for Apple Foundation Models framework via koffi FFI
SystemLanguageModelclass with availability checks andwaitUntilAvailable()LanguageModelSessionwithrespond(),streamResponse(), andrespondWithJsonSchema()for text, streaming, and structured generationGenerationSchemaandGenerationSchemaPropertyfor typed structured output with generation guidesGenerationOptionsandSamplingModefor controlling temperature, token limits, and sampling strategies- Abstract
Toolbase class for function calling with schema-driven arguments Transcriptclass for session history export and import- Error hierarchy matching Python SDK status codes (11 specific error types)
- Prebuilt
libFoundationModels.dylibbundled for npm distribution (no Xcode required) build-native.shscript for building the dylib from vendored Swift sourceverify-native.jspostinstall script for SHA256 verification with automatic rebuild