Conversation
There was a problem hiding this comment.
Pull request overview
Adds a shared prompt library for Foundation Models (separating legacy 26.0–26.3 prompts from optimized 26.4+ prompts) and introduces macOS 26.4 token-budget measurement to log prompt usage and trim oversized prompt inputs before generation (lyrics + playlist refinement), while keeping command parsing behavior stable.
Changes:
- Introduces
FoundationModelsPromptLibrary+FoundationModelsPromptVersionto centralize prompts and select 26.4+ optimized variants. - Adds prompt budgeting utilities (
tokenCount-based) to log prompt utilization and fit/truncate large prompt inputs on macOS 26.4+. - Updates Command Bar, Lyrics, and Playlist refinement flows to use the shared prompt library and prompt fitting where applicable, plus adds prompt-library-focused tests.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| Tests/KasetTests/FoundationModelsPromptLibraryTests.swift | Adds unit tests covering prompt variants and helper formatting/truncation behavior. |
| Sources/Kaset/Views/PlaylistDetailView.swift | Switches playlist refinement prompts to the shared library and trims track lines to fit the 26.4+ context budget. |
| Sources/Kaset/Views/LyricsView.swift | Switches lyrics prompts to the shared library and trims lyrics text to fit the 26.4+ context budget. |
| Sources/Kaset/Views/CommandBarView.swift | Moves command instructions into the shared library and logs prompt budget (26.4+). |
| Sources/Kaset/Services/AI/FoundationModelsService.swift | Adds prompt budget measurement + prompt fitting helpers (content truncation + line dropping) using 26.4 token-count APIs. |
| Sources/Kaset/Services/AI/FoundationModelsPromptLibrary.swift | New shared prompt library including legacy and optimized prompt variants plus helper formatting/truncation functions. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| var low = 1 | ||
| var high = lines.count | ||
| var bestFit = 1 |
There was a problem hiding this comment.
fittedLineCount always returns at least 1 when lines is non-empty (low/bestFit start at 1). If even a single line exceeds the available token budget (e.g., very long instructions/tools or reserveTokens leaving tokenLimit near 0), this will still return 1 and the caller will build an oversized prompt. Consider allowing a 0-line result (initialize bestFit to 0 and search 0...lines.count, or explicitly check whether 1 line fits and return 0 if it doesn’t).
| var low = 1 | |
| var high = lines.count | |
| var bestFit = 1 | |
| var low = 0 | |
| var high = lines.count | |
| var bestFit = 0 |
| Example: "rolling stones 90s hits" | ||
| -> action: play, query: "rolling stones 90s hits", artist: "Rolling Stones", era: "1990s" | ||
|
|
||
| Example: "upbeat rolling stones songs from the 90s" | ||
| -> action: play, query: "upbeat rolling stones songs", artist: "Rolling Stones", mood: "upbeat", era: "1990s" | ||
|
|
||
| Example: "chill jazz for studying" | ||
| -> action: play, query: "chill jazz for studying", genre: "jazz", mood: "chill", activity: "study" | ||
|
|
||
| Example: "acoustic covers of pop hits" | ||
| -> action: play, query: "acoustic covers of pop hits", genre: "pop", version: "acoustic cover" | ||
|
|
||
| Example: "80s synthwave" | ||
| -> action: play, query: "80s synthwave", genre: "synthwave", era: "1980s" | ||
|
|
||
| Example: "add some energetic workout music to queue" | ||
| -> action: queue, query: "energetic workout music", mood: "energetic", activity: "workout" | ||
|
|
||
| Example: "best of queen" | ||
| -> action: play, query: "best of queen", artist: "Queen" | ||
|
|
||
| COMPONENT EXTRACTION RULES: | ||
| - query: ALWAYS include the full natural language request (minus action words) | ||
| - artist: Extract artist name if mentioned ("Beatles", "Taylor Swift", "Rolling Stones") | ||
| - genre: rock, pop, jazz, classical, hip-hop, r&b, electronic, country, folk, metal, indie, latin, k-pop | ||
| - mood: upbeat, chill, sad, happy, energetic, relaxing, melancholic, romantic, aggressive, peaceful, groovy | ||
| - era: Use decade format (1960s, 1970s, 1980s, 1990s, 2000s, 2010s, 2020s) or "classic" | ||
| - version: acoustic, live, remix, instrumental, cover, unplugged, remastered | ||
| - activity: workout, study, sleep, party, driving, cooking, focus, running, yoga | ||
|
|
||
| For simple commands: skip/next -> skip, pause/stop -> pause, play/resume -> resume, | ||
| shuffle my queue -> shuffle (shuffleScope: queue), like this -> like, clear queue -> queue (query: "__clear__") | ||
| """ |
There was a problem hiding this comment.
legacy26_0To26_3 is described as a legacy prompt, but the copied text isn’t identical to the previous inline prompt (e.g., the examples now use -> instead of the original →). If you want truly backward-compatible behavior for 26.0–26.3, consider preserving the legacy prompt text verbatim and only changing the optimized 26.4+ variant.
Summary
Testing
Notes