Skip to content

Use configured AI providers for meeting summaries - #1076

Open
andrewmitchell-automations wants to merge 5 commits into
altic-dev:mainfrom
andrewmitchell-automations:feat/meeting-summary-ai-providers
Open

andrewmitchell-automations wants to merge 5 commits into
altic-dev:mainfrom
andrewmitchell-automations:feat/meeting-summary-ai-providers

Conversation

@andrewmitchell-automations

Copy link
Copy Markdown

Description

Meeting summaries are currently disabled on main ("coming soon") because on-device generation was inaccurate. This PR turns them back on for completed meetings, using only the cloud providers the user has already configured and verified in AI Providers. It continues #1028 by @grohith327 (their commits are squashed and rebased onto current main as the first commit, with authorship kept) and narrows its scope:

  • Reuses the existing provider setup. The provider/model picker reads the same verified catalog as Command Mode (commandModeModelCatalog()), resolves base URL, API key, reasoning, and temperature settings the same way, and sends the request through the existing LLMClient. Anthropic works through its OpenAI-compatible endpoint, as in the rest of the app.
  • Removed from Add selectable providers for FluidMeet summaries #1028: the Claude Code / Codex CLI runner, the separate native Anthropic client, the "Use AI Settings" migration shim (it only migrated state from unreleased builds of Add selectable providers for FluidMeet summaries #1028), and the on-device option in this view.
  • Summary choice stays independent of dictation and Command Mode. On first use it starts from the AI Settings provider if that provider is verified.
  • No verified provider: the tab shows "Set up a provider" and opens AI Providers.
  • Dictation, Command Mode, and Rewrite keep working during a cloud summary. Cloud summaries use their own admission token. They do not take the exclusive ASR audio lease or the processing gate that the on-device path needs. Only one summary runs at a time.
  • Pre-release Add selectable providers for FluidMeet summaries #1028 selections (meeting:*) are reset, and older on-device summaries stay hidden while that path is disabled.
  • Truncated output is rejected and the previous summary is kept. Only length / max_tokens / content_filter (Chat Completions) or an incomplete status (Responses API) counts as truncated, so providers that report a normal stop as eos or end_turn still work.
  • Reasoning models get the same 32k output budget that Command Mode uses.
  • Saved summaries record provider and model provenance (never the API key).

The on-device download/delete code in MeetingSummaryController is left unchanged so it can be enabled again later. It is not reachable from this view.

Type of Change

  • 🐞 Bug fix
  • ✨ New feature
  • 💥 Breaking change
  • 🧹 Chore
  • 📝 Documentation update

Related Issue or Discussion

Related to #1022 (cloud-model half; local model choice is not included).
Supersedes #1028.

Testing

Verification steps:

  1. In AI Providers, add and verify a provider (tested with Anthropic).
  2. Open a completed meeting → Meet Summary tab.
  3. Choose provider, model, and summary type → Generate summary.
  4. Expected: the summary appears under "Generated with · ", and reopening the meeting shows it again.
  5. With no verified provider, the tab shows "Set up a provider".

Result: live run on a 52-minute Zoom meeting with Anthropic claude-haiku-4-5-20251001 produced a detailed summary with provenance (screenshots below).

  • Tested on Intel Mac
  • Tested on Apple Silicon Mac
  • Tested on macOS version: 27.2
  • Ran linter locally: swiftlint --strict with the CI image (ghcr.io/realm/swiftlint:0.63.2), 0 violations
  • Ran formatter locally: SwiftFormat --lint is clean on the new/rewritten files; remaining findings are in lines unchanged from main
  • Ran tests locally: MeetingSummaryProviderTests, MeetingSummaryActivityTests, MeetingSummaryInputTests — 24 passed. Full xcodebuild test (CI flags): the only failures were 9 UpdateInstallationPipelineTests (invalidSignature(-67050)), which fail the same way on unmodified main on this Mac, and one AudioTopologyDiagnosticsTests count assertion that passed 3/3 on rerun.

Not tested: Intel; the "Set up a provider" state was checked in code and tests, not in a screenshot.

Screenshots / Video

Provider and model picker with a verified provider:

Provider pickers

Summary types:

Summary types

Generating (transcript destination shown):

Summarizing

Result with provenance (meeting content redacted):

Summary result

Notes

AI use: Claude Code reviewed #1028, rebased it, removed the CLI and native Anthropic paths, wrote the new tests, and ran the checks above. I ran the live test on macOS 27.2 / Apple Silicon and reviewed every changed line.

  • A human created this PR or reviewed and approved it before submission, understands the full diff, and takes responsibility for the change.

🤖 Generated with Claude Code

grohith327 and others added 2 commits October 6, 2026 13:22
Squashed from altic-dev#1028 by @grohith327 and rebased onto
main after the beta.8 summary changes.
Summaries now run only through providers already verified in AI
Providers, using Command Mode's catalog and the shared LLMClient.

- Remove the Claude Code/Codex CLI runner, the separate Anthropic
  Messages client, the pre-release "Use AI Settings" migration, and
  the on-device option in the summary view.
- Run cloud summaries outside the ASR lease and processing gate so
  dictation, Command Mode, and Rewrite keep working meanwhile.
- Treat only length/max_tokens/content_filter as truncation so
  providers that report eos or end_turn still succeed.
- Give reasoning models Command Mode's 32k output budget.
- Default to the AI Settings provider on first use, reset pre-release
  selections, and show a setup prompt when nothing is verified.
- Keep older on-device summaries hidden while that path is disabled.

Co-Authored-By: grohith327 <grohith327@gmail.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@greptile-apps

greptile-apps Bot commented Oct 6, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 5/5

[Medium impact] The PR appears safe to merge, with a non-blocking cache-key issue for custom URL paths that differ only by case.

Summary

Enables completed-meeting summaries through providers already configured and verified in AI Providers.

  • Keeps summary choices separate from dictation and Command Mode.
  • Saves provider/model details and rejects incomplete results.
  • Keys learned temperature support by endpoint and isolates the fallback tests.
  • One non-blocking issue remains: the endpoint key also lowercases case-sensitive URL paths.

Reviews (3) · Last reviewed commit: "Key learned temperature support by provi..." · Reviewed by Greptile

claude-haiku-5-5, claude-opus-5 and claude-opus-5-5 reject the
temperature parameter with HTTP 400, but the name list in
isTemperatureUnsupported did not match them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Each new model that drops `temperature` (Opus 4.7, Sonnet 5, Haiku 5.5)
broke requests until the name list in isTemperatureUnsupported was
updated. Support is now learned per model ID and stored in UserDefaults:

- The model fetch records it from the /models listing: OpenRouter's
  supported_parameters, and Anthropic's budget_tokens thinking
  capability (every model that dropped it also dropped temperature).
- LLMClient records a model as unsupported when a request with
  temperature gets an HTTP 400 that names it, and retries once without
  temperature. The 400 arrives before any streamed output.
- The name list stays as the fallback for models with no learned value.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Comment thread Tests/FluidDictationIntegrationTests/TemperatureSupportTests.swift
Two providers can serve the same model ID with different parameter
support (for example a generic local ID such as "llama3"). A rejection
or listing from one provider no longer stops the other from receiving
temperature. isTemperatureUnsupported now takes the provider base URL;
every call site already had it. The saved key is renamed so values
stored under the old model-only key are ignored.

The name-list tests in TemperatureSupportTests now read an empty learned
store, so values saved by the test host cannot change their results.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
}

private static func key(_ model: String, baseURL: String) -> String {
var endpoint = baseURL.trimmingCharacters(in: .whitespacesAndNewlines).lowercased()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Different providers share temperature settings

ModelTemperatureSupport.key lowercases the whole baseURL, including its case-sensitive path. If custom providers use /TeamA/v1 and /teama/v1 with the same model, they share a cache entry even though requests go to different URLs. When one rejects temperature, the other silently loses its configured temperature too.

Normalize the scheme and host, but preserve the path’s case.

Prompt To Fix With AI
This is a comment left during a code review.
Path: Sources/Fluid/Services/ModelTemperatureSupport.swift
Line: 65

Comment:
**Different providers share temperature settings**

`ModelTemperatureSupport.key` lowercases the whole `baseURL`, including its case-sensitive path. If custom providers use `/TeamA/v1` and `/teama/v1` with the same model, they share a cache entry even though requests go to different URLs. When one rejects `temperature`, the other silently loses its configured temperature too.

Normalize the scheme and host, but preserve the path’s case.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Codex

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