seisei_apple 0.1.0-dev.8 copy "seisei_apple: ^0.1.0-dev.8" to clipboard
seisei_apple: ^0.1.0-dev.8 copied to clipboard

Apple Foundation Models provider and Flutter bridge for Seisei.

seisei_apple #

Apple Foundation Models provider boundary and Flutter bridge for Seisei.

This package contains:

  • AppleFoundationModelsProvider, which implements Seisei's generic provider contract.
  • FmCliBackend, a local /usr/bin/fm backend for development probes.
  • MethodChannelAppleFoundationModelsBackend, a Flutter method-channel backend for iOS and macOS apps.

First Run #

On macOS 27 machines that provide /usr/bin/fm, the fastest smoke path is:

fm available --model system
fm respond --no-stream 'Reply with exactly: seisei-ok'

To verify Seisei itself can use local AFM, run the package smoke command:

dart run bin/local_afm_smoke.dart
dart run bin/local_afm_smoke.dart --schema
dart run bin/local_afm_smoke.dart --stream

That command uses FmCliBackend, AppleFoundationModelsProvider, and SeiseiClient to send the prompt through the local system model. A passing run prints providerId: apple_system and response: seisei-ok. The --schema variant also writes a temporary ObjectSchema FoundationModels schema file and expects response: seisei-schema-ok. The --stream variant verifies that real streaming chunks arrive and that Seisei emits a terminal value. For schema-backed streams, safe intermediate structured snapshots are also decoded into GenerationChunk.partialValue while raw snapshots remain available in GenerationChunk.rawValue; changed structured paths are exposed through GenerationChunk.structuredPatches.

To verify direct PCC CLI access on the machine, run this from an interactive terminal:

fm available --model pcc
fm respond --model pcc --no-stream 'Reply with exactly: seisei-pcc-ok'

Those commands must be run in the same launch context you want to validate. On this macOS 27 machine, PCC is context-sensitive:

/usr/bin/fm available --model pcc

Run non-interactively, it exits nonzero with:

Error: PCC inference is not available in this context.

Run in an interactive PTY, it reports:

PCC model available

The same split applies to direct generation:

/usr/bin/fm respond --model pcc 'Reply with exactly: seisei-pcc-ok'

Run non-interactively, it fails with PCC inference is not available in this context. Run in an interactive PTY, it can return seisei-pcc-ok.

To verify PCC from the current Seisei Dart backend path, run:

dart run bin/local_afm_smoke.dart --mode pcc

That path currently uses FmCliBackend, which calls fm with captured subprocess output. On this machine that makes PCC report unavailable even when the direct interactive CLI probe succeeds. Treat that result as a validation of the current Seisei execution context, not as proof that PCC is generally unavailable on the machine.

From the repository root, dart tool/validate.dart --local-afm checks only the system-model path. Use dart tool/validate.dart --local-pcc when you want PCC to be a required local smoke test.

For a minimal Flutter host, create an app and point seisei_apple at this workspace with a path dependency:

flutter create --platforms=macos /tmp/seisei_afm_host
dependencies:
  seisei_apple:
    path: /path/to/your/seisei/packages/seisei_apple

Then use the native bridge directly from lib/main.dart:

final backend = MethodChannelAppleFoundationModelsBackend();
final availability = await backend.availability();
final response = await backend.respond(
  const AppleFoundationModelsRequest(
    prompt: 'Reply with exactly: seisei-ok',
    mode: AppleFoundationModelsMode.system,
  ),
);

For schema-backed generation, encode the generic Seisei object schema into a FoundationModels schema file and pass that file through provider metadata:

const encoder = FoundationModelsSchemaEncoder();
const schema = ObjectSchema(
  name: 'Draft',
  fields: {
    'author': ObjectField.object(
      schema: ObjectSchema(
        name: 'Author',
        fields: {
          'name': ObjectField.string(),
        },
      ),
    ),
    'count': ObjectField.integer(minimum: 0, maximum: 10),
    'published': ObjectField.boolean(),
    'status': ObjectField.string(enumValues: ['draft', 'published']),
    'title': ObjectField.string(),
  },
);
final schemaFile = await encoder.writeObjectFile(schema);

final provider = AppleFoundationModelsProvider(
  backend: MethodChannelAppleFoundationModelsBackend(),
);
final response = await SeiseiClient(provider: provider).generate(
  GenerationRequest<String>(
    prompt: 'Reply as JSON with title, count, and published fields.',
    metadata: encoder.metadataForFile(schemaFile),
    decode: (rawValue) {
      final object = schema.decode(rawValue, (value) => value);
      return object['title']! as String;
    },
  ),
);

The native bridge is intentionally narrow. It checks system-model availability and sends plain system-model prompts through FoundationModels.LanguageModelSession. It can also send schema-backed system model requests when schemaPath points to a JSON-encoded FoundationModels schema file, and it streams system-model text through a Flutter event channel. Schema-backed streams preserve raw intermediate structured snapshots and decode safe partial snapshots into GenerationChunk.partialValue. They also derive path-level GenerationChunk.structuredPatches from consecutive structured snapshots when the backend emits snapshot objects. FoundationModelsSchemaEncoder covers verified generic ObjectSchema features: nested objects, string enums, field-level anyOf unions, numeric ranges, string patterns, arrays, and optional fields. PCC is not implemented in the native bridge yet. On the current Xcode 26.5 SDK, the public Swift FoundationModels interface exposes SystemLanguageModel and LanguageModelSession(model: SystemLanguageModel), but no public PCC model type that Seisei can compile against.

If you want the typed Seisei client layer, add a direct seisei dependency in the host app and build AppleFoundationModelsProvider on top of the native backend. Keep the request in system mode and avoid PCC settings. For schema-backed requests outside FoundationModelsSchemaEncoder, use AppleFoundationModelsProvider.schemaPathMetadataKey with a provider-specific FoundationModels schema file.

CI tests use fake and mocked method-channel backends; /usr/bin/fm and local Apple Foundation Models are optional validation only.