Skip to content

Send FM trailing context, length hint, per-app tone, bigger prefix budget#344

Merged
FuJacob merged 2 commits into
mainfrom
feat/fm-richer-context
May 28, 2026
Merged

Send FM trailing context, length hint, per-app tone, bigger prefix budget#344
FuJacob merged 2 commits into
mainfrom
feat/fm-richer-context

Conversation

@FuJacob

@FuJacob FuJacob commented May 28, 2026

Copy link
Copy Markdown
Owner

Summary

Four prompt-side improvements bundled because they all live in the FM prompt channel and were all measurable against the eval suite from the parent stack:

  • Trailing context. The suffix (text after the caret) was captured but never sent to FM. Mid-line insertions now get a Text after the caret: section so the model can bridge into existing text rather than overwrite it.
  • Length hint. The user's word-count preset (Return only the next 7 to 12 words.) is reintroduced on the prompt channel — not instructions, so it does not bust the cached session prefix from PR 2. Apple's model lands cleaner stopping points with a natural-language cue than with maximumResponseTokens alone.
  • Per-app tone hint. A small bundle-ID dictionary maps focused-app categories (code editor, email, chat, browser) to one-line tone cues injected into the prompt. Unknown bundles fall through to no hint.
  • Bigger FM-side prefix budget. SuggestionConfiguration gains FM-only prefix caps (2500 chars / 150 words) so Apple's larger context can take more surrounding sentences without crowding instructions. Llama keeps its existing tighter window.

Stacked on refactor/fm-positive-frame. Use the eval suite from the head of the stack to compare mid-word truncation, mid-line bridging, and category drift.

Validation

xcodebuild -project Cotabby.xcodeproj -scheme Cotabby -destination 'platform=macOS' build CODE_SIGNING_ALLOWED=NO
** BUILD SUCCEEDED **

xcodebuild test ... -only-testing:CotabbyTests/FoundationModelPromptRendererTests -only-testing:CotabbyTests/SuggestionRequestFactoryTests -only-testing:CotabbyTests/SuggestionEngineRouterTests
Executed 33 tests, with 0 failures (0 unexpected)

swiftlint lint --quiet → no violations.

Manual: focus a real text field in Mail / Slack / Xcode / Safari and verify the diagnostics panel shows the matching per-app tone hint and (where applicable) the trailing-text section.

Linked issues

Refs the FM-quality investigation.

Risk / rollout notes

  • SuggestionConfiguration gained two new memberwise fields (maxPrefixWordsFoundationModel, maxPrefixCharactersFoundationModel). Production uses .standard, which is updated; the two explicit-constructor test sites were updated alongside.
  • SuggestionRequestFactory.truncatedPromptPrefix now takes an optional engine: parameter (defaulting to .llamaOpenSource) so external callers stay source-compatible. The internal call from buildRequest and the coordinator's clipboard-filter call both pass the active engine explicitly.
  • The per-app tone-hint dictionary is intentionally small. Adding bundle IDs is a one-line change in FoundationModelPromptRenderer; the absence of a hint is the safe default.
  • Diagnostic preview now surfaces the length cue (it lives on the prompt channel), so the test_promptPreview assertion was flipped — and a new assertion ensures the cue still does NOT appear in instructions (so the session-cache key remains stable across word-count preset changes... wait, those should invalidate; correction: word-count preset only changes the prompt, not instructions, so cache stays warm).

Greptile Summary

This PR enriches the Foundation Models prompt channel with four coordinated improvements: trailing-context injection (bounded by maxSuffixCharacters), a natural-language length hint on the per-request prompt, per-app tone cues keyed by bundle-ID prefix, and a separate, larger prefix budget (2500 chars / 150 words) for the FM path.

  • Trailing text is now capped at maxSuffixCharacters before being sent, closing the previously identified gap where a caret at the top of a long document would flood the 4096-token context window.
  • SuggestionConfiguration gains two new FM-specific prefix cap fields; all existing explicit constructors in tests were updated alongside, and truncatedPromptPrefix selects the right budget via an engine switch with a backward-compatible default.
  • The bundle-ID tone-hint dictionary deliberately excludes terminal emulators and Cursor (whose ToDesktop hash is unstable), with tests covering both known-match and exclusion cases; one entry (com.apple.mobilesms) references an iOS-only bundle ID that will not match macOS Messages.

Confidence Score: 5/5

Safe to merge — all prompt-channel changes are additive and the most significant correctness fix (trailing-text overflow) is properly addressed.

The trailing-text cap is correctly applied before injection, the engine-aware prefix budget switch is clean with a backward-compatible default, and the tone-hint dictionary's safe-default-on-no-match design means unknown or mismatched bundle IDs degrade gracefully. The one dead entry (com.apple.mobilesms) silently misses macOS Messages but causes no harm. Tests cover the new code paths thoroughly.

FoundationModelPromptRenderer.swift — the chatBundlePrefixes list contains one iOS-only entry that will not fire on macOS.

Important Files Changed

Filename Overview
Cotabby/Support/FoundationModelPromptRenderer.swift Adds trailing-context injection (bounded by maxSuffixCharacters), length hint on the prompt channel, and per-app tone hints via bundle-prefix dictionaries; one iOS-only bundle ID (com.apple.mobilesms) will never match on macOS.
Cotabby/Models/SuggestionModels.swift Adds maxPrefixWordsFoundationModel and maxPrefixCharactersFoundationModel fields to SuggestionConfiguration; standard defaults set to 150 words / 2500 chars for the FM path.
Cotabby/Support/SuggestionRequestFactory.swift truncatedPromptPrefix gains an engine parameter (defaulting to .llamaOpenSource for source-compatibility) and selects the appropriate character/word budget via a switch; logic is clean and both call sites updated correctly.
Cotabby/App/Coordinators/SuggestionCoordinator+Prediction.swift One-line change: passes the active engine to truncatedPromptPrefix so the clipboard relevance filter evaluates against the same bounded window the downstream request uses.
CotabbyTests/PromptPolicyTests.swift Adds focused tests for trailing-text section, length hint placement, code-editor tone hint, terminal/Cursor exclusions, and unknown-bundle fallthrough; test_promptPreview assertion correctly flipped to verify length cue on prompt channel and absence from instructions.
CotabbyTests/SuggestionRequestFactoryTests.swift Updates two existing SuggestionConfiguration constructors with the new FM prefix fields and adds a new test pinning that llama and FM paths receive distinct prefix budgets.

Sequence Diagram

sequenceDiagram
    participant Coord as SuggestionCoordinator
    participant Factory as SuggestionRequestFactory
    participant FM as FoundationModelPromptRenderer
    participant Apple as Apple FM API

    Coord->>Factory: truncatedPromptPrefix(engine: .appleIntelligence)
    Note over Factory: Selects maxPrefixCharactersFoundationModel=2500<br/>maxPrefixWordsFoundationModel=150
    Factory-->>Coord: bounded prefixText

    Coord->>Factory: buildRequest(context, settings, configuration)
    Factory->>Factory: truncatedPromptPrefix(engine: appleIntelligence)
    Factory-->>Coord: SuggestionRequestBuildResult

    Coord->>FM: promptPreview(for: request)
    FM->>FM: sessionInstructions(for: request)
    Note over FM: Role + output contract + examples<br/>(no length hint, no tone hint)
    FM->>FM: prompt(for: request)
    Note over FM: appToneHint(bundleIdentifier)<br/>+ Text before caret (prefixText)<br/>+ Text after caret (trailingText, capped at maxSuffixCharacters)<br/>+ Write only the next continuation fragment.<br/>+ completionLengthInstruction
    FM-->>Coord: instructions + prompt

    Coord->>Apple: generate(instructions, prompt)
    Apple-->>Coord: completion text
Loading

Fix All in Codex Fix All in Claude Code

Reviews (4): Last reviewed commit: "Address Greptile review on #344" | Re-trigger Greptile

Comment thread Cotabby/Support/FoundationModelPromptRenderer.swift Outdated
Comment thread Cotabby/Support/FoundationModelPromptRenderer.swift Outdated
Comment thread Cotabby/Support/FoundationModelPromptRenderer.swift
FuJacob added a commit that referenced this pull request May 28, 2026
- Apply the maxSuffixCharacters cap to trailing text inside the FM
  renderer instead of relying on upstream truncation that does not
  exist; protects a long-document caret-at-top from pushing the entire
  document body through the 4096-token context window.
- Remove terminal emulators from the code-editor tone bucket so a
  prose context in a terminal stops getting code-shaped completions.
- Remove Cursor's opaque ToDesktop bundle ID since prefix-matching
  cannot survive Cursor updates; leave a note explaining why.
@FuJacob FuJacob force-pushed the refactor/fm-positive-frame branch from 6f1afe5 to 3a129d0 Compare May 28, 2026 10:16
FuJacob added 2 commits May 28, 2026 03:18
- Apply the maxSuffixCharacters cap to trailing text inside the FM
  renderer instead of relying on upstream truncation that does not
  exist; protects a long-document caret-at-top from pushing the entire
  document body through the 4096-token context window.
- Remove terminal emulators from the code-editor tone bucket so a
  prose context in a terminal stops getting code-shaped completions.
- Remove Cursor's opaque ToDesktop bundle ID since prefix-matching
  cannot survive Cursor updates; leave a note explaining why.
@FuJacob FuJacob force-pushed the feat/fm-richer-context branch from 5aece19 to 2238567 Compare May 28, 2026 10:21
@FuJacob FuJacob changed the base branch from refactor/fm-positive-frame to main May 28, 2026 10:21
@FuJacob FuJacob merged commit 3160301 into main May 28, 2026
4 checks passed
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.

1 participant