Skip to content

Add Apple on-device (FoundationModels) coach provider + rich notifications#30

Merged
saksham2001 merged 3 commits into
saksham2001:mainfrom
hoveeman:apple-on-device-coach-for-upstream
Jun 30, 2026
Merged

Add Apple on-device (FoundationModels) coach provider + rich notifications#30
saksham2001 merged 3 commits into
saksham2001:mainfrom
hoveeman:apple-on-device-coach-for-upstream

Conversation

@hoveeman

Copy link
Copy Markdown
Contributor

Adds an "On-device (Apple)" provider that runs the AI coach entirely on the device via FoundationModels — no API key, no network, fully private. It falls back to a chosen cloud provider (OpenAI/Gemini/OpenRouter) when the local model is unavailable or a generation fails.

Give this a try as I was having some issues with PRs. let me know if i need to take another look.

Provider:

  • AppleFoundationModelsClient: a ResponsesClient adapter (one-shot, tool-less in v1) using FoundationModels guided generation for structured cards, with a text/JSON fallback. Mirrors the GeminiClient request-body translation.
  • AppleOnDeviceAvailability: friendly wrapper over SystemLanguageModel availability; guarded with #if canImport(FoundationModels) / @available so the project still compiles on older SDKs.
  • FallbackResponsesClient + CoachClientResolver: unify provider resolution across chat/summaries/notifications and add the on-device → cloud-backup chain.
  • Settings: On-device provider option, cloud-backup picker, privacy card.

Notifications (leveraging free/private local inference):

  • Richer check-ins: actionable tip + tappable follow-up + adaptive skip.
  • New midday slot alongside morning/evening.
  • Proactive anomaly alerts (low SpO2, short sleep), event-driven and on-device-only, deduped per kind per day.
  • On-device check-ins use a BGProcessingTask (longer budget, no network required); cloud providers keep BGAppRefreshTask. Adds the com.pulseloop.coach.process background-task identifier.
  • Fixes a latent crash: background scheduling now gates on actual BGTask registration (the host app could otherwise submit an unregistered identifier under XCTest).

How was this tested?

Tested on my iPhone 17 Pro Max

@hoveeman hoveeman requested a review from saksham2001 as a code owner June 28, 2026 21:12
…cations

Adds an "On-device (Apple)" provider that runs the AI coach entirely on the
device via FoundationModels — no API key, no network, fully private. It falls
back to a chosen cloud provider (OpenAI/Gemini/OpenRouter) when the local model
is unavailable or a generation fails.

Provider:
- AppleFoundationModelsClient: a ResponsesClient adapter (one-shot, tool-less in
  v1) using FoundationModels guided generation for structured cards, with a
  text/JSON fallback. Mirrors the GeminiClient request-body translation.
- AppleOnDeviceAvailability: friendly wrapper over SystemLanguageModel
  availability; guarded with #if canImport(FoundationModels) / @available so the
  project still compiles on older SDKs.
- FallbackResponsesClient + CoachClientResolver: unify provider resolution
  across chat/summaries/notifications and add the on-device → cloud-backup chain.
- Settings: On-device provider option, cloud-backup picker, privacy card.

Notifications (leveraging free/private local inference):
- Richer check-ins: actionable tip + tappable follow-up + adaptive skip.
- New midday slot alongside morning/evening.
- Proactive anomaly alerts (low SpO2, short sleep), event-driven and
  on-device-only, deduped per kind per day.
- On-device check-ins use a BGProcessingTask (longer budget, no network
  required); cloud providers keep BGAppRefreshTask. Adds the
  com.pulseloop.coach.process background-task identifier.
- Fixes a latent crash: background scheduling now gates on actual BGTask
  registration (the host app could otherwise submit an unregistered identifier
  under XCTest).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@hoveeman hoveeman force-pushed the apple-on-device-coach-for-upstream branch from baa1ca2 to 5e1a1fb Compare June 28, 2026 21:16
@hoveeman

Copy link
Copy Markdown
Contributor Author

Some screenshots:

IMG_7332 IMG_7330 IMG_7331

@saksham2001

Copy link
Copy Markdown
Owner

This is really cool! What iOS version did you test this on @hoveeman? Did you have to update to iOS 27?

@hoveeman

Copy link
Copy Markdown
Contributor Author

This is really cool! What iOS version did you test this on @hoveeman? Did you have to update to iOS 27?

i am on 26.5.1

My son has his phone on iOS 27. I'll try and get it loaded on his as well.

@saksham2001 saksham2001 left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a great feature, thank you @hoveeman! I tested the PR and I love the on-device model - some of the replies seem better than bigger models. The tool calls also work well.

I made some minor changes to not fallback to other models (so we can clearly see the error and user can switch manually to a model that works). Also made some configurations changes like removing the input image feature as that is not available for the on-device model yet.

@saksham2001 saksham2001 merged commit c42ec85 into saksham2001:main Jun 30, 2026
2 checks passed
@hoveeman

Copy link
Copy Markdown
Contributor Author

This is a great feature, thank you @hoveeman! I tested the PR and I love the on-device model - some of the replies seem better than bigger models. The tool calls also work well.

I made some minor changes to not fallback to other models (so we can clearly see the error and user can switch manually to a model that works). Also made some configurations changes like removing the input image feature as that is not available for the on-device model yet.

That's great! Glad you enjoyed it! There may be an opportunity to add a fallback model in the future for certain types of prompts that may not work properly with the on device model. However for now, that's a good idea to remove it!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants