Skip to content

fix(desktop): slim floating bar prompt context#7544

Open
aryaminus wants to merge 4 commits into
BasedHardware:mainfrom
aryaminus:fix/desktop-floating-bar-slim-prompt
Open

fix(desktop): slim floating bar prompt context#7544
aryaminus wants to merge 4 commits into
BasedHardware:mainfrom
aryaminus:fix/desktop-floating-bar-slim-prompt

Conversation

@aryaminus
Copy link
Copy Markdown
Contributor

@aryaminus aryaminus commented May 29, 2026

Summary

  • Builds a separate floating-bar system prompt style instead of reusing the full main chat prompt
  • Keeps main chat behavior unchanged: main sessions still include the local database schema and available skills
  • Trims floating-bar prompts by excluding the cached SQLite database schema and available-skills section, then caches that floating prompt for warmup and query fallback
  • Updates both floating entry points (FloatingControlBarWindow and AgentPill) to request the explicit .floating prompt style instead of relying on the floating prefix as an implicit sentinel

Why

Issue #6981 measured floating-bar chat latency at 6.6-11.1s per query and identified the shared main-chat prompt as a major contributor. The issue breakdown shows the floating session receiving the same large prompt as main chat, including about 12,280 chars of database schema and a skills section that is not needed for "what do you see on my screen?" style floating-bar queries.

The issue comments specifically call out:

  • full DB schema being sent to floating bar for both ACP and piMono paths
  • skills being unnecessary in the floating-bar prompt
  • a slim floating-bar prompt as the first recommended fix

This PR implements that narrow prompt-slimming recommendation without changing quota checks, save/sync timing, screenshot size, model defaults, or voice playback behavior.

Relation to existing work

Implementation details

  • Adds ChatSystemPromptStyle with .main and .floating
  • ChatSystemPromptStyle owns the schema/skills inclusion policy through includesDatabaseSchema and includesSkills
  • buildSystemPrompt(..., style: .main) preserves current main chat prompt behavior
  • buildFloatingBarSystemPrompt(...) prepends floatingBarSystemPromptPrefix but uses .floating, which omits:
    • cachedDatabaseSchema
    • <available_skills>
  • Caches cachedFloatingSystemPrompt during bridge warmup so floating sessions are prewarmed with the slimmer prompt
  • Uses the cached floating prompt during sendMessage(..., systemPromptStyle: .floating) and writes fallback rebuilds back into cachedFloatingSystemPrompt

Review follow-up

Addressed Greptile feedback in follow-up commit 615bc02:

  • fallback rebuild now writes back to cachedFloatingSystemPrompt
  • removed the parallel internal PromptProfile enum so there is one source of truth for prompt style policy

Expected impact

This directly removes the schema section called out in #6981 (schema:12280c in the posted logs) from floating-bar prompts. It should reduce prompt size, cache-write cost, and cold/warm inference latency for floating-bar queries while leaving the full main chat context intact.

Verification

  • xcrun swift build -c debug --package-path Desktop

🤖 Generated with OpenCode

@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 29, 2026

Greptile Summary

This PR builds a dedicated slim system prompt for the floating bar by adding a ChatSystemPromptStyle enum and an internal PromptProfile discriminator that strips the SQLite database schema (~12 kB) and the <available_skills> section from floating-bar queries, while leaving the main chat prompt unchanged. Both floating entry points (FloatingControlBarWindow and AgentPill) are updated to request the new .floating style instead of manually passing floatingBarSystemPromptPrefix.

  • Adds ChatSystemPromptStyle (.main/.floating) as the public routing discriminator, and the private PromptProfile (with includesDatabaseSchema/includesSkills properties) as the internal build-time gate.
  • Caches the slimmer cachedFloatingSystemPrompt at bridge warmup alongside cachedMainSystemPrompt, and provides a rebuild fallback in sendMessage when the cache is empty.
  • Removes the need for callers to pass systemPromptPrefix: ChatProvider.floatingBarSystemPromptPrefix manually.

Confidence Score: 4/5

Safe to merge; the prompt-slimming logic is correct and the two floating entry points are updated consistently.

The core change routes floating queries to a schema-free, skills-free prompt correctly and symmetrically in both entry points. The two findings are a missed cache-write in the fallback path (wasteful but not incorrect) and a parallel-enum design that will need coordinated updates if a third style is ever added. Neither affects correctness today.

desktop/Desktop/Sources/Providers/ChatProvider.swift — specifically the sendMessage fallback path and the relationship between ChatSystemPromptStyle and PromptProfile.

Important Files Changed

Filename Overview
desktop/Desktop/Sources/Providers/ChatProvider.swift Core change: adds PromptProfile enum, updates buildSystemPrompt to gate schema/skills on profile, introduces buildFloatingBarSystemPrompt, caches cachedFloatingSystemPrompt at warmup, and routes sendMessage to the right cached prompt via systemPromptStyle. The fallback rebuild in sendMessage does not update the cache, and the two parallel enums (ChatSystemPromptStyle / PromptProfile) create a minor maintenance surface.
desktop/Desktop/Sources/FloatingControlBar/FloatingControlBarWindow.swift One-line change: swaps systemPromptPrefix: ChatProvider.floatingBarSystemPromptPrefix for systemPromptStyle: .floating. Correct and safe.
desktop/Desktop/Sources/FloatingControlBar/AgentPill.swift One-line change: same swap as FloatingControlBarWindow. Correct and safe.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[sendMessage called] --> B{isOnboarding && systemPromptPrefix set?}
    B -- Yes --> C[systemPrompt = systemPromptPrefix only]
    B -- No --> D{systemPromptStyle}
    D -- .floating --> E{cachedFloatingSystemPrompt empty?}
    E -- No --> F[systemPrompt = cachedFloatingSystemPrompt]
    E -- Yes --> G[buildFloatingBarSystemPrompt fallback rebuild]
    G --> F
    D -- .main --> H[systemPrompt = cachedMainSystemPrompt]
    F --> I{systemPromptPrefix set?}
    H --> I
    I -- Yes --> J[prefix + newline + systemPrompt]
    I -- No --> K[apply suffix if set]
    J --> K
    K --> L[pass to agentBridge.query]

    subgraph Warmup
        W1[formatMemoriesSection] --> W2[buildSystemPrompt profile:.main]
        W1 --> W3[buildFloatingBarSystemPrompt profile:.floating]
        W2 --> W4[cachedMainSystemPrompt]
        W3 --> W5[cachedFloatingSystemPrompt]
    end
Loading

Reviews (1): Last reviewed commit: "fix(desktop): use slim prompt for agent ..." | Re-trigger Greptile

Comment on lines +2646 to +2650
if systemPromptStyle == .floating {
systemPrompt = cachedFloatingSystemPrompt.isEmpty
? buildFloatingBarSystemPrompt(contextString: formatMemoriesSection())
: cachedFloatingSystemPrompt
} else {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 The fallback branch computes a fresh floating prompt but never writes it back to cachedFloatingSystemPrompt. If warmup failed (bridge start returned early before setting the cache), every subsequent floating query triggers a full buildFloatingBarSystemPrompt rebuild instead of amortising that cost after the first call. Caching the result here mirrors exactly what warmup does and avoids repeated rebuilds.

Suggested change
if systemPromptStyle == .floating {
systemPrompt = cachedFloatingSystemPrompt.isEmpty
? buildFloatingBarSystemPrompt(contextString: formatMemoriesSection())
: cachedFloatingSystemPrompt
} else {
if systemPromptStyle == .floating {
if cachedFloatingSystemPrompt.isEmpty {
cachedFloatingSystemPrompt = buildFloatingBarSystemPrompt(contextString: formatMemoriesSection())
}
systemPrompt = cachedFloatingSystemPrompt
} else {

Comment on lines +462 to 470
case main
case floating
}

/// State management for chat functionality with Claude Agent SDK
/// Uses hybrid architecture: Swift → Claude Agent (via Node.js bridge) for AI, Backend for persistence + context
@MainActor
class ChatProvider: ObservableObject {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Parallel enums for the same concept

ChatSystemPromptStyle (file-scope, public routing discriminator) and PromptProfile (private nested enum, build-time gate) both model the same .main/.floating distinction. The only code that converts between them is the implicit branch in sendMessage — there is no switch or mapping function. If a third style is added later (e.g. .task), both enums need updating and the if systemPromptStyle == .floating branch in sendMessage needs a matching arm, with no compiler enforcement of the mapping. Collapsing to a single enum (or adding an explicit promptProfile(for:) helper) would make the contract between the two clear.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

@aryaminus
Copy link
Copy Markdown
Contributor Author

aryaminus commented May 29, 2026

Addressed the Greptile review comments in follow-up commit 615bc02:

  • The floating prompt fallback now writes the rebuilt prompt back to cachedFloatingSystemPrompt, so a warmup/cache miss only rebuilds once.
  • Removed the parallel PromptProfile enum; ChatSystemPromptStyle now owns the schema/skills inclusion policy directly, so there is one enum for the main/floating prompt distinction.

Copy link
Copy Markdown
Collaborator

@kodjima33 kodjima33 left a comment

Choose a reason for hiding this comment

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

desktop bug-fix fast lane (3/5) but mergeStateStatus BLOCKED — downgraded merge to approve

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