feat: add prompt library view - #2036
Conversation
6d298f8 to
780e493
Compare
Greptile SummaryThis PR consolidates Skills and MCP into a new Library sidebar entry and adds a Prompts tab for managing reusable prompt presets. Prompts are persisted in a dedicated KV store (migrated from
Confidence Score: 5/5Safe to merge; all changes are additive feature work with no modifications to critical data paths. The feature is well-scoped — a new KV namespace, a new RPC controller, and new UI components — with no changes to existing storage schemas beyond removing the now-migrated reviewPrompt setting. The migration path is tested and the legacy importer is backward-compatible. The two quality issues noted are both non-blocking: redundant DB operations on every prompt fetch and a brief flicker of the task context bar during the initial async load. Neither causes data loss or incorrect behavior. src/main/core/prompt-library/service.ts (redundant DB calls after seed) and src/renderer/features/tasks/conversations/context-bar.tsx (async load flicker)
|
| Filename | Overview |
|---|---|
| src/main/core/prompt-library/service.ts | New service managing prompt library persistence and seeding from legacy settings; seedIfNeeded runs 4 DB operations on every getPrompts() call after the initial seed due to missing in-memory guard. |
| src/renderer/features/tasks/conversations/context-bar.tsx | Migrated from sync settings hook to async usePromptLibrary; prompt actions now gated on async data, causing a brief hide of the entire context bar during the initial fetch. |
| src/renderer/features/library/prompts/use-prompt-library.ts | Well-implemented TanStack Query hook with optimistic updates and rollback; staleTime of 5 min means no initial data is populated on first mount, contributing to the flicker in consumers. |
| src/renderer/features/library/library-view.tsx | New Library view shell with tab context; context default is non-null so the useLibraryTab guard never fires (noted in prior review thread). |
| src/renderer/features/library/prompts/prompt-library-view.tsx | CRUD UI for prompts; delete confirmation present; no differentiation between built-in and user prompts (reset path for review prompt noted in prior review). |
| src/renderer/features/tasks/conversations/prompt-actions-menu.tsx | New popover component for prompt selection; expandedIds state persists across open/close cycles (noted in prior review); otherwise clean. |
| src/main/db/legacy-port/importers/settings/importer.ts | Legacy reviewPrompt migration correctly redirected to promptLibraryStore.upsertReviewPrompt; test coverage updated accordingly. |
Sequence Diagram
sequenceDiagram
participant Renderer
participant RPC
participant PromptLibraryService
participant KV as KV Store (prompt-library)
participant DB as appSettings (legacy)
Note over PromptLibraryService: App startup
PromptLibraryService->>KV: get('seedVersion')
alt "seedVersion < SEED_VERSION"
PromptLibraryService->>DB: read legacy promptLibrary / reviewPrompt
PromptLibraryService->>KV: set('prompts', mergedPrompts)
PromptLibraryService->>KV: set('seedVersion', 1)
PromptLibraryService->>DB: delete legacy keys
else already seeded
PromptLibraryService->>DB: deleteLegacyPromptSettings (no-op)
end
Renderer->>RPC: promptLibrary.get()
RPC->>PromptLibraryService: getPrompts()
PromptLibraryService->>PromptLibraryService: seedIfNeeded()
PromptLibraryService->>KV: get('prompts')
KV-->>Renderer: PromptLibraryPrompt[]
Renderer->>RPC: promptLibrary.update(prompts)
RPC->>PromptLibraryService: updatePrompts(prompts)
PromptLibraryService->>KV: set('prompts', validated)
Prompt To Fix All With AI
Fix the following 4 code review issues. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 4
src/main/core/prompt-library/service.ts:20-21
`seedIfNeeded` resets `this.seedPromise` to `null` in `finally`, so every subsequent call to `getPrompts()` (triggered on each React Query cache miss, at most every 5 minutes) re-enters the method and executes a DB read (`seedVersion`) followed by three sequential `DELETE` statements in `deleteLegacyPromptSettings()`. After the initial seed those deletes are no-ops, but the round-trips accumulate. A simple boolean flag (`this.isSeeded`) set after the first successful seed would short-circuit this immediately in memory.
```suggestion
export class PromptLibraryService implements IInitializable {
private seedPromise: Promise<void> | null = null;
private isSeeded = false;
```
### Issue 2 of 4
src/main/core/prompt-library/service.ts:51-59
The guard only checks `this.seedPromise` (concurrent de-dup), but after `finally` resets it to `null` every call re-runs the DB logic. Checking `this.isSeeded` first would skip the entire block once the seed has been written.
```suggestion
private async seedIfNeeded(): Promise<void> {
if (this.isSeeded) return;
if (this.seedPromise) return this.seedPromise;
this.seedPromise = (async () => {
const seedVersion = await promptLibraryKV.get('seedVersion');
if ((seedVersion ?? 0) >= PROMPT_LIBRARY_SEED_VERSION) {
await this.deleteLegacyPromptSettings();
return;
}
```
### Issue 3 of 4
src/main/core/prompt-library/service.ts:89-91
Set `this.isSeeded = true` in `finally` so the flag is accurate even after a rejection-then-retry cycle.
```suggestion
})().finally(() => {
this.isSeeded = true;
this.seedPromise = null;
});
```
### Issue 4 of 4
src/renderer/features/tasks/conversations/context-bar.tsx:55-60
**Context bar flickers during prompt library initial load**
`promptLibrary` now comes from an async RPC query (`usePromptLibrary`). On first render, `data` is `undefined`, so `value` defaults to `[]` and `promptActions.length === 0`. For tasks without a linked issue or open draft comments, the third branch of the early-return is immediately `true`, so the entire bar disappears until the fetch resolves. Previously `reviewPrompt` came from the synchronous settings cache and always had a default value, so the bar rendered immediately. Adding `initialData` or `placeholderData` (e.g. an empty array) to the query — or seeding the React Query cache on app startup — would prevent the transient hide.
Reviews (3): Last reviewed commit: "Reseed prompt library after startup data..." | Re-trigger Greptile
|
still need to address the greptile comments @jschwxrz |
|
Also now that the prompt library is its own concept now and not part of the project settings anymore, we should not save the review prompts in the app settings KV table. We should either create a new table prompt_presets or store the presets in the regular KV table. |
|
@greptile review |
…-allow-custom-prompts-in-the-review-bottom-bar-prompt-library feat: add prompt library view



Summary
This adds a Library entry to the left sidebar and uses it as the shared home for reusable agent assets. The Library opens on a new Prompts tab, with Skills and MCP moved into sibling tabs that reuse their existing views and behavior.
The Prompts tab lets users manage prompt presets that can be inserted from task prompt menus. It includes the built-in review prompt, supports editing/resetting that review prompt, and adds custom prompt presets with create, edit, delete, and search flows. Custom prompts are persisted in app settings so they are available across tasks without introducing a new storage path.
The task bottom bar and create-task modal now expose prompts through a compact Prompts popover. Long prompt bodies are truncated by default, can be expanded inline for review, and the menu scrolls when many presets are available. The trigger intentionally stays compact and does not show a prompt count badge, which keeps the bottom bar stable as users add more presets.
promptlibraryfeature.mp4
Implementation Notes
libraryview and prompt modal using the existing renderer registries.promptLibraryto app settings schema/defaults and updates the settings hook so array settings replace cleanly instead of being object-merged.Validation
pnpm run formatpnpm run lintpasses with the existingcommand-palette-modal.tsxwarningpnpm run typecheckpnpm rebuild better-sqlite3pnpm test