Skip to content

feat: add prompt templates feature#1844

Open
Prethish-Kumar wants to merge 4 commits intogeneralaction:mainfrom
Prethish-Kumar:prethish/prompt-templates-wq9iv
Open

feat: add prompt templates feature#1844
Prethish-Kumar wants to merge 4 commits intogeneralaction:mainfrom
Prethish-Kumar:prethish/prompt-templates-wq9iv

Conversation

@Prethish-Kumar
Copy link
Copy Markdown

@Prethish-Kumar Prethish-Kumar commented Apr 30, 2026

Summary

Replace the single global reviewPrompt setting workflow with a Prompt Templates system. Users can create, edit, reorder, and delete reusable prompt templates, then insert them from one-click actions in the task ContextBar.

PR Review Gaps Addressed

  • Added server-side template cap enforcement in the service (MAX_PROMPT_TEMPLATES) so direct RPC calls cannot bypass UI limits.
  • Removed unsafe non-null refetch assertion in update() and now return the updated model from known state.
  • Hardened reorder() to validate payload integrity:
    • all IDs must exist
    • all templates must be included
    • duplicate IDs are rejected
  • Deduplicated starter templates and max-limit constants into src/shared/prompt-templates.ts so main-process seeding and renderer empty-state stay in sync.
  • Fixed ContextBar overflow for many templates by enabling horizontal scrolling and preventing action button shrink, so all template actions remain accessible.

Final Polish Before Merge

  • Preserved full template names in action data so tooltips/accessibility use the untruncated label.
  • Improved Prompts tab and empty-state wording for clarity.
  • Added aria-labels to icon-only actions in template settings.
  • Disabled duplicate action when at max template limit to avoid avoidable error toasts.
  • Improved max-limit helper copy with clear next step.

What changed

  • Database: New prompt_templates SQLite table with Drizzle ORM schema + auto-generated migration.
  • Backend: PromptTemplateService with CRUD, validation, and atomic reorder transaction + RPC controller.
  • Frontend:
    • New "Prompts" tab in Settings with full CRUD UI (add, edit, delete, duplicate, reorder)
    • Empty state with 4 starter quick-add templates
    • Inline delete confirmation + character counts
    • usePromptTemplates React Query hook
    • ContextBar renders a button per template
  • Migration: Existing reviewPrompt value is migrated to the first template on startup; new users get 4 starter templates.
  • Cleanup: Removed ReviewPromptSettingsCard.tsx; legacy reviewPrompt schema/default remains for compatibility/migration.
  • Tests: Added prompt-template service tests (including reorder integrity guards) and updated context-actions.test.ts.

Validation

  • pnpm run format
  • pnpm run lint ✅ (0 errors; existing warnings only)
  • pnpm run typecheck
  • pnpm run test ✅ (73/73 files, 490 tests)

Replace the single reviewPrompt app setting with a dedicated prompt_templates
database table, full CRUD in Settings, and multi-template buttons in the
ContextBar.

- New SQLite table with Drizzle ORM and auto-generated migration
- PromptTemplateService with full CRUD, validation, and atomic reorder tx
- RPC controller registered under promptTemplates namespace
- React Query hook usePromptTemplates for list/create/update/delete/reorder
- New 'Prompts' tab in Settings with CRUD UI, reorder, duplicate, delete
- ContextBar renders a button per template with one-click paste into chat
- Migrate existing reviewPrompt setting into first template on startup
- Seed 4 default starter templates for new users
- Add empty state with starter quick-add buttons
- Add inline delete confirmation
- Add character counts on name and text inputs
- Update context-actions tests for template-based actions
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 30, 2026

Greptile Summary

This PR replaces the single reviewPrompt app setting with a full Prompt Templates system — new SQLite table, CRUD service, RPC controller, Settings UI, and ContextBar integration. The PR description's claimed improvements (server-side cap, safe update return, validated reorder, deduplicated constants) are all correctly implemented.

  • P1: The ContextBar renders all template buttons in a single fixed-height h-[41px] flex row with no overflow handling. With the 20-template cap, buttons beyond ~5–8 will be clipped and unreachable by the user.
  • P2: reorder() validates that every ID in the input exists, but does not verify the input covers all templates — a valid subset reorder will silently leave omitted templates with stale sort_order values.

Confidence Score: 4/5

Safe to merge with the ContextBar overflow fixed before the feature ships broadly

One P1 finding: the ContextBar renders all template buttons in a non-scrolling fixed-height row, making templates unreachable past ~5–8 items. Backend logic and migration are solid. Score is capped at 4 by the P1.

src/renderer/features/tasks/conversations/context-bar.tsx — needs overflow handling for the template button row

Important Files Changed

Filename Overview
src/renderer/features/tasks/conversations/context-bar.tsx Renders all template buttons in a fixed-height flex row with no overflow handling; with 20 max templates the bar will clip, making buttons inaccessible
src/main/core/prompt-templates/service.ts CRUD service with validation, server-side cap, and atomic reorder transaction; validation gap — subset reorder is silently accepted
src/main/core/prompt-templates/service.test.ts 10 well-structured service tests; missing coverage for MAX_PROMPT_TEMPLATES enforcement
src/shared/prompt-templates.ts Shared constants and interfaces correctly deduplicated; both service and frontend now import from this single source
src/main/index.ts Migration from reviewPrompt to templates is safe; seeds STARTER_PROMPT_TEMPLATES on first run
src/renderer/features/settings/components/PromptTemplatesSettingsCard.tsx Full CRUD UI with inline confirmation, character counts, and starter quick-add; imports from shared constants
src/renderer/features/settings/use-prompt-templates.ts React Query hook wiring create/update/delete/reorder mutations with cache invalidation; looks correct
drizzle/0008_harsh_overlord.sql New prompt_templates table with correct schema and sort_order index
src/main/core/prompt-templates/controller.ts Thin RPC controller delegating all calls to the service; no issues

Sequence Diagram

sequenceDiagram
    participant UI as PromptTemplatesSettingsCard
    participant Hook as usePromptTemplates
    participant RPC as promptTemplatesController
    participant Svc as PromptTemplateService
    participant DB as SQLite (prompt_templates)

    UI->>Hook: create(name, text)
    Hook->>RPC: rpc.promptTemplates.create(input)
    RPC->>Svc: create(input)
    Svc->>DB: SELECT COUNT(*) cap check
    Svc->>DB: SELECT MAX(sort_order)
    Svc->>DB: INSERT
    Svc-->>RPC: PromptTemplate
    RPC-->>Hook: PromptTemplate
    Hook->>Hook: invalidateQueries(['promptTemplates'])

    UI->>Hook: reorder([id2, id1])
    Hook->>RPC: rpc.promptTemplates.reorder(ids)
    RPC->>Svc: reorder(ids)
    Svc->>DB: SELECT id WHERE id IN (...)
    Svc->>DB: TRANSACTION UPDATE sort_order per id
    Svc-->>RPC: void

    Note over UI,DB: ContextBar also calls usePromptTemplates and renders one button per template
Loading
Prompt To Fix All With AI
Fix the following 3 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 3
src/renderer/features/tasks/conversations/context-bar.tsx:59-81
**ContextBar overflows with many templates**

The template buttons are rendered in a single fixed-height flex row (`h-[41px]`) without `overflow-x-auto` or any wrapping strategy. With the service cap at 20 templates and each button being roughly 80–130 px wide, users with more than ~5–8 templates will see buttons clipped at the edge of the bar with no way to reach them — making those templates permanently inaccessible without reducing the count. Consider adding `overflow-x-auto` to the container div, or capping the number of rendered template buttons in the UI regardless of the stored count.

### Issue 2 of 3
src/main/core/prompt-templates/service.ts:126-133
**Partial reorder silently accepted when IDs are a subset of all templates**

The guard validates that every ID in the input exists in the DB, but it does not check that the input covers *all* templates. A caller can pass a valid subset of IDs and only those rows get their `sort_order` updated — the omitted templates retain their old values, silently creating an inconsistent ordering. Given that the UI always sends the full list this is currently benign, but the service contract is weaker than the PR description implies.

```suggestion
    const [totalRow] = await this.db.select({ value: count() }).from(promptTemplates);
    if (ids.length !== totalRow.value) {
      throw new Error('Reorder list must include all existing prompt templates');
    }

    const existingRows = await this.db
      .select({ id: promptTemplates.id })
      .from(promptTemplates)
      .where(inArray(promptTemplates.id, ids));

    if (existingRows.length !== ids.length) {
      throw new Error('One or more prompt templates were not found');
    }
```

### Issue 3 of 3
src/main/core/prompt-templates/service.test.ts:67-71
**No test for the MAX_PROMPT_TEMPLATES server-side cap**

The service now enforces a server-side cap in `create()`, but none of the tests exercise that path. A test that creates 20 templates and then expects the 21st call to reject would confirm the guard is actually reachable.

```suggestion
  it('rejects text over 4000 chars', async () => {
    await expect(service.create({ name: 'valid', text: 'x'.repeat(4001) })).rejects.toThrow(
      'Template text must be 4000 characters or fewer'
    );
  });

  it('rejects create when template limit is reached', async () => {
    const { MAX_PROMPT_TEMPLATES } = await import('@shared/prompt-templates');
    for (let i = 0; i < MAX_PROMPT_TEMPLATES; i++) {
      await service.create({ name: `T${i}`, text: 'text' });
    }
    await expect(service.create({ name: 'Over', text: 'limit' })).rejects.toThrow(
      `You can create up to ${MAX_PROMPT_TEMPLATES} templates`
    );
  });
```

Reviews (2): Last reviewed commit: "fix: address prompt template review gaps" | Re-trigger Greptile

Comment thread src/main/core/prompt-templates/service.ts
Comment thread src/main/core/prompt-templates/service.ts Outdated
Comment thread src/main/core/prompt-templates/service.ts
Comment thread src/main/index.ts Outdated
@arnestrickmann
Copy link
Copy Markdown
Contributor

@greptile

Comment thread src/renderer/features/tasks/conversations/context-bar.tsx Outdated
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.

3 participants