Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
160bf97
chore: replace test workflow with CI workflow and update README badge
codybrom Mar 10, 2026
1d1e5cd
chore: add .env.local to .gitignore
codybrom Mar 10, 2026
7449ef7
feat: add OpenAI-compatible API layer (tsfm-sdk/openai)
codybrom Mar 10, 2026
dc0e07b
feat: add Symbol.dispose, signal cleanup, ServiceCrashedError, and mo…
codybrom Mar 10, 2026
8830523
feat: tool calling, $defs/$ref schemas, JSON key reordering, and test…
codybrom Mar 11, 2026
cc44c61
feat: content_filter finish reason, OpenAI type compatibility, and te…
codybrom Mar 11, 2026
f31a9f7
docs: overhaul guide pages and align terminology with Apple conventions
codybrom Mar 11, 2026
af1f879
feat: typed transcript entries and guide documentation updates
codybrom Mar 11, 2026
40138da
feat: add Responses API, integration tests, docs, and lint fixes
codybrom Mar 12, 2026
859583f
feat: rename model to SystemLanguageModel, advanced examples, and doc…
codybrom Mar 12, 2026
f1080d1
feat: docs site overhaul — brand colors, typography, landing page, an…
codybrom Mar 12, 2026
3bbdbac
feat: update version to 0.3.0 in package.json and package-lock.json
codybrom Mar 12, 2026
a4e13d7
docs: add 0.3.0 changelog entry
codybrom Mar 12, 2026
dc318c8
feat: rename OpenAI compat layer to Chat & Responses APIs
codybrom Mar 12, 2026
6279a5d
feat: enhance code block styling for better responsiveness
codybrom Mar 12, 2026
bea2223
feat: add Chat & Responses APIs to README
codybrom Mar 12, 2026
58b5213
fix: defensive guards and session cleanup improvements
codybrom Mar 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .env.local.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Copy this file to .env.local and fill in values for OpenAI comparison examples.
# Only needed for: openai-real, responses-real, responses-advanced-real
OPENAI_API_KEY=sk-...
47 changes: 47 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: CI

on:
push:
branches: [main]
paths-ignore:
- "**.md"
- "docs/**"
- LICENSE.md
- NOTICE
pull_request:
branches: [main]
paths-ignore:
- "**.md"
- "docs/**"
- LICENSE.md
- NOTICE

jobs:
test:
runs-on: macos-latest
strategy:
matrix:
node-version: [20, 22]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: npm
- run: npm ci
- run: npm run lint
- run: npm run format:check
- run: npx vitest run tests/unit --coverage

build-dylib:
runs-on: macos-26
steps:
- uses: actions/checkout@v4
- name: Build native dylib from source
run: |
rm -f native/libFoundationModels.dylib
bash scripts/build-native.sh
- name: Verify dylib
run: |
file native/libFoundationModels.dylib
otool -L native/libFoundationModels.dylib
24 changes: 0 additions & 24 deletions .github/workflows/test.yml

This file was deleted.

1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ coverage
.vscode/settings.json
docs/.vitepress/dist
docs/.vitepress/cache
.env.local
46 changes: 45 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,49 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [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 via `ResponseStream`
- Parameter mapping: `temperature`, `max_tokens`/`max_completion_tokens`, `top_p`, `seed` → native `GenerationOptions`; unsupported params warned at runtime
- Error mapping: `ExceededContextWindowSizeError` → `finish_reason: "length"`, `GuardrailViolationError` → `finish_reason: "content_filter"`, `RefusalError` → `message.refusal`, `RateLimitedError` → HTTP 429
- `Stream` and `ResponseStream` async iterables with `toReadableStream()`, `close()`, `Symbol.dispose`, and `FinalizationRegistry` cleanup
- Tool calling via structured output with `$defs`/`$ref` schemas to prevent parameter name collisions
- JSON key reordering utility to match schema-defined property order
- `ServiceCrashedError` — detects crashed `generativeexperiencesd` service and provides recovery instructions
- `Symbol.dispose` support on `SystemLanguageModel`, `LanguageModelSession`, `Tool`, and `Client` for TC39 Explicit Resource Management
- Typed transcript entries: `TranscriptEntry`, `TranscriptContent`, `TranscriptTextContent`, `TranscriptStructuredContent`, `TranscriptToolCall`, `TranscriptEntryRole` types and `transcript.entries()` method
- `JsonSchema` and `JsonObject` exported types
- Automatic session cleanup on `process.exit`, `SIGINT`, and `SIGTERM` via global session tracking
- Enhanced `afmSchemaFormat()` with recursive normalization for nested objects, `$defs`/`$ref` support, and `x-order` fields
- `respondWithJsonSchema()` now accepts typed `JsonSchema` instead of `Record<string, unknown>`
- Tool callback error handling: synchronous errors in `call()` now invoke `FMBridgedToolFinishCall()` with error message to prevent session hang
- Enhanced `statusToError()`: maps `ModelManagerError Code=1041` to `InvalidGenerationSchemaError` with 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 `SystemLanguageModel` across all public APIs and documentation
- `Transcript.toDict()` and `fromDict()` now use `JsonObject` type instead of `Record<string, unknown>`
- `GeneratedContent.toObject()` now returns `JsonObject` instead of `Record<string, unknown>`
- `serializeOptions()` uses typed `SerializedSampling` and `SerializedOptions` interfaces internally
- Integration tests now use `waitUntilAvailable()` instead of synchronous `isAvailable()`

### 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
Expand Down Expand Up @@ -84,7 +127,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `build-native.sh` script for building the dylib from vendored Swift source
- `verify-native.js` postinstall script for SHA256 verification with automatic rebuild

[Unreleased]: https://github.com/codybrom/tsfm/compare/v0.2.3...HEAD
[Unreleased]: https://github.com/codybrom/tsfm/compare/v0.3.0...HEAD
[0.3.0]: https://github.com/codybrom/tsfm/compare/v0.2.3...v0.3.0
[0.2.3]: https://github.com/codybrom/tsfm/compare/v0.2.2...v0.2.3
[0.2.2]: https://github.com/codybrom/tsfm/compare/v0.2.1...v0.2.2
[0.2.1]: https://github.com/codybrom/tsfm/compare/v0.2.0...v0.2.1
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

<p align="center">
<a href="https://www.npmjs.com/package/tsfm-sdk"><img src="https://img.shields.io/npm/v/tsfm-sdk" alt="npm"></a>
<a href="https://github.com/codybrom/tsfm/actions/workflows/test.yml"><img src="https://github.com/codybrom/tsfm/actions/workflows/test.yml/badge.svg" alt="Tests"></a>
<a href="https://github.com/codybrom/tsfm/actions/workflows/ci.yml"><img src="https://github.com/codybrom/tsfm/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
<a href="LICENSE.md"><img src="https://img.shields.io/npm/l/tsfm-sdk" alt="license"></a>
</p>

Expand All @@ -22,6 +22,7 @@
- Structured output with typed schemas and generation guides
- Tool calling
- Transcript persistence
- Chat-style and Responses-style APIs via `tsfm-sdk/chat`

## Quick Start

Expand Down Expand Up @@ -56,6 +57,7 @@ model.dispose();
- [Streaming](https://tsfm.dev/guide/streaming) — token-by-token response streaming
- [Structured Output](https://tsfm.dev/guide/structured-output) — typed schemas with generation guides
- [Tools](https://tsfm.dev/guide/tools) — function calling
- [Chat & Responses APIs](https://tsfm.dev/guide/chat-api) — familiar Chat-style and Responses-style interfaces
- [API Reference](https://tsfm.dev/api/) — complete API docs
- [Examples](https://tsfm.dev/examples/) — runnable code for every feature

Expand Down
16 changes: 15 additions & 1 deletion docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export default defineConfig({
],

themeConfig: {
externalLinkIcon: true,
logo: "/logo.svg",

nav: [
Expand All @@ -46,7 +47,6 @@ export default defineConfig({
{ text: "Sessions", link: "/guide/sessions" },
{ text: "Streaming", link: "/guide/streaming" },
{ text: "Structured Output", link: "/guide/structured-output" },
{ text: "JSON Schema", link: "/guide/json-schema" },
{ text: "Tools", link: "/guide/tools" },
{ text: "Transcripts", link: "/guide/transcripts" },
],
Expand All @@ -58,6 +58,15 @@ export default defineConfig({
{ text: "Error Handling", link: "/guide/error-handling" },
],
},
{
text: "Integrations",
items: [
{
text: "Chat & Responses APIs",
link: "/guide/chat-api",
},
],
},
],
"/api/": [
{
Expand All @@ -71,6 +80,7 @@ export default defineConfig({
{ text: "Tool", link: "/api/tool" },
{ text: "Transcript", link: "/api/transcript" },
{ text: "Errors", link: "/api/errors" },
{ text: "Chat & Responses APIs", link: "/api/chat" },
],
},
],
Expand All @@ -87,6 +97,10 @@ export default defineConfig({
{ text: "Generation Options", link: "/examples/generation-options" },
{ text: "Transcripts", link: "/examples/transcript" },
{ text: "Content Tagging", link: "/examples/content-tagging" },
{
text: "Chat & Responses APIs",
link: "/examples/chat-api",
},
],
},
],
Expand Down
33 changes: 33 additions & 0 deletions docs/.vitepress/theme/HomeExplore.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<template>
<div class="home-explore">
<a
v-for="card in cards"
:key="card.title"
:href="card.link"
class="home-explore-card"
>
<span class="home-explore-title">{{ card.title }}</span>
<span class="home-explore-desc">{{ card.desc }}</span>
</a>
</div>
</template>

<script setup lang="ts">
const cards = [
{
title: "Guide",
desc: "Step-by-step walkthroughs for every feature",
link: "/guide/getting-started",
},
{
title: "API Reference",
desc: "Full reference for every class and method",
link: "/api/",
},
{
title: "Examples",
desc: "9 runnable examples you can copy, paste, and run",
link: "/examples/",
},
];
</script>
Loading
Loading