Skip to content

feat(prompts): add reusable prompt presets#213

Merged
ymkiux merged 14 commits into
mainfrom
fix/sidebar-config-meta-copy
Jul 12, 2026
Merged

feat(prompts): add reusable prompt presets#213
ymkiux merged 14 commits into
mainfrom
fix/sidebar-config-meta-copy

Conversation

@awsl233777

@awsl233777 awsl233777 commented Jul 11, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Add a reusable Prompts preset pool as a sibling tab next to AGENTS.md and CLAUDE.md.
  • Add the preset pool as its own entry in the left Prompts sidebar, alongside AGENTS.md and CLAUDE.md.
  • Support saving editor content as presets, applying presets to either prompt file editor, renaming presets, and deleting presets with confirmation guards.
  • Persist prompt presets and the selected Prompts sub-tab in Web UI preferences.
  • Add locale strings for the preset pool and update English, Chinese, and Vietnamese README docs.
  • Force OpenAI bridge builtin conversion to route Codex Responses requests through upstream /chat/completions instead of probing upstream /responses first.

Behavior notes

  • Applying a prompt preset only updates the current editor content.
  • Users must still use the normal Save action to write changes to AGENTS.md or CLAUDE.md.
  • When codexmate_bridge = "openai" is enabled, the bridge now treats builtin conversion as forced conversion: upstream /responses is not called for Codex Responses requests; converted requests go to /chat/completions.

Validation

  • npm run lint
  • npm run test:unit
  • npm run test:e2e
  • git diff --check
  • node --test tests/unit/openai-bridge-upstream-responses.test.mjs
  • Isolated Web UI screenshot validation with a temporary HOME/config directory.

PR status

  • Do not merge automatically. This PR currently still requires review/check completion.

Summary by CodeRabbit

  • New Features
    • Added a shared Prompt presets pool with save, preview, rename, add/overwrite, apply-to-editor (paste), and delete, including confirmations, validation, and toast feedback.
    • Added/updated Prompts sidebar labeling to include preset-pool navigation.
  • Bug Fixes
    • Prevented unintended Prompts editor reloads during preset/apply interactions.
    • Improved OpenAI “Responses” handling for better compatibility via chat-completions-style routing/conversion.
  • Documentation
    • Updated README descriptions to clarify preset-pool behavior and manual save requirements.
  • Tests
    • Expanded unit/UI parity, i18n locale coverage, and OpenAI Responses compatibility tests.

@coderabbitai

coderabbitai Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Added a shared Web UI prompt preset pool with persistence, CRUD workflows, localized UI, tests, responsive styling, and documentation. The OpenAI bridge now converts Responses requests through chat completions without probing upstream Responses endpoints.

Changes

Prompt preset pool

Layer / File(s) Summary
Preset state and persistence
web-ui/app.js, web-ui/modules/app.methods.web-ui-preferences.mjs
Adds preset state, sub-tab handling, normalized preference persistence, and guarded prompt loading.
Preset CRUD and editor application
web-ui/modules/app.methods.agents.mjs
Implements validation, save/overwrite, apply, rename, delete, selection, persistence, and feedback flows.
Preset interface and styling
web-ui/partials/index/..., web-ui/res/web-ui-render.precompiled.js, web-ui/styles/*.css
Adds preset navigation, management panels, actions, compiled rendering, and responsive styles.
Localization, validation, and documentation
web-ui/modules/i18n/locales/*.mjs, tests/unit/*, README*.md, package.json
Adds translations, behavior and navigation coverage, parity allowlists, test registration, package versioning, and documentation.

OpenAI Responses routing

Layer / File(s) Summary
Chat-completions conversion and routing
cli/openai-bridge.js
Moves conversion before streaming branching and directly proxies converted requests to chat completions while constructing Responses-compatible output.
Routing and payload validation
tests/unit/openai-bridge-upstream-responses.test.mjs
Updates coverage for SSE/JSON output, skipped Responses probing, authorization, tool normalization, and reasoning-effort mapping.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant PromptPresetMethods
  participant PromptEditor
  participant WebUiPreferences
  User->>PromptPresetMethods: Save or apply a prompt preset
  PromptPresetMethods->>PromptEditor: Update editor content
  PromptPresetMethods->>WebUiPreferences: Persist promptPresets
  WebUiPreferences-->>PromptPresetMethods: Return normalized preset state
  PromptPresetMethods-->>User: Show operation status
Loading
sequenceDiagram
  participant Client
  participant OpenAIBridge
  participant ChatCompletions
  Client->>OpenAIBridge: Send Responses request
  OpenAIBridge->>ChatCompletions: Send converted chat request
  ChatCompletions-->>OpenAIBridge: Return chat response or stream
  OpenAIBridge-->>Client: Return Responses-compatible JSON or SSE
Loading

Possibly related PRs

Suggested reviewers: ymkiux

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: adding reusable prompt presets in the Prompts area.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/sidebar-config-meta-copy

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ast-grep (0.44.1)
web-ui/res/web-ui-render.precompiled.js

ast-grep timed out on this file


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@awsl233777 awsl233777 changed the title fix(web-ui): tighten config sidebar meta copy feat(prompts): add reusable prompt presets Jul 11, 2026

@coderabbitai coderabbitai Bot left a comment

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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
web-ui/modules/app.methods.agents.mjs (1)

871-891: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Switching away from the presets tab can silently discard an unsaved draft.

switchPromptsSubTab('codex' | 'claude-project') unconditionally reassigns promptsSubTab, which triggers the promptsSubTab watcher's loadPromptsContent() call (see web-ui/app.js Line 752), overwriting agentsContent with the freshly-fetched file — with no confirmation. Since the whole point of the new presets tab is to let a user pause mid-edit, save the draft as a preset, and come back, a user who navigates to presets (without saving) and then clicks back to codex/claude-project loses their in-progress edit with no warning. applyPromptPresetToEditor (Lines 806-815) already guards this exact scenario via hasAgentsContentChanged() + requestConfirmDialog; the same guard is missing here for plain tab navigation.

🛡️ Suggested fix
-        switchPromptsSubTab(subTab) {
+        async switchPromptsSubTab(subTab) {
             const normalized = subTab === 'claude-project' || subTab === 'presets' ? subTab : 'codex';
             if (normalized === 'presets') {
                 this.promptsSubTab = normalized;
                 this.$nextTick(() => {
                     document.querySelector('.main-panel')?.scrollTo({ top: 0, left: 0, behavior: 'auto' });
                 });
                 return;
             }
+            if (this.promptsSubTab === 'presets' && normalized !== this.promptsSubTab && this.hasAgentsContentChanged()) {
+                const confirmed = await this.requestConfirmDialog({
+                    title: this.t('prompts.presets.confirm.discardTitle'),
+                    message: this.t('prompts.presets.confirm.discardMessage'),
+                    confirmText: this.t('prompts.presets.confirm.discardConfirm'),
+                    cancelText: this.t('common.cancel'),
+                    danger: true
+                });
+                if (!confirmed) return;
+            }
             if (normalized === 'claude-project' && !this.projectPathOptions.length && !this.projectPathOptionsLoading) {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web-ui/modules/app.methods.agents.mjs` around lines 871 - 891, Update
switchPromptsSubTab to guard navigation from the presets tab to codex or
claude-project with hasAgentsContentChanged() and requestConfirmDialog, matching
applyPromptPresetToEditor. Only change promptsSubTab and continue loading or
scrolling after confirmation; preserve existing behavior when there are no
unsaved changes or when entering presets.
🧹 Nitpick comments (4)
tests/unit/prompt-presets.test.mjs (2)

91-92: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Assert persisted state, not only write counts.

The tests do not verify that the final persisted snapshot contains the overwritten/deleted presets and cleared selection. Compare the serialized snapshot with the expected state to catch stale or partial persistence.

Also applies to: 145-145

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unit/prompt-presets.test.mjs` around lines 91 - 92, Update the
persistence assertions in the affected tests around the existing
persisted.length checks to verify the serialized persisted snapshot, not just
the number of writes. Compare the final snapshot against the expected state,
including overwritten and deleted presets and the cleared selection, in both
locations.

54-57: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Make confirmation responses controllable in the test VM.

requestConfirmDialog always returns true, so overwrite, apply, and delete cancellation paths are untested. Add a response queue or per-test override and assert that cancellation leaves state unchanged.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unit/prompt-presets.test.mjs` around lines 54 - 57, Update the test
VM’s requestConfirmDialog stub to support queued or per-test confirmation
responses instead of always returning true. Use false responses to cover
overwrite, apply, and delete cancellation paths, and assert each cancellation
leaves the relevant state unchanged while preserving existing confirmation
behavior.
web-ui/styles/modals-core.css (1)

779-791: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Deprecated word-break: break-word (flagged by stylelint).

Per CSS Text spec and MDN, word-break: break-word is deprecated; it's equivalent to overflow-wrap: anywhere + word-break: normal. Browsers still honor it for now, but prefer the modern properties.

🎨 Suggested fix
 .prompt-preset-preview {
     max-height: 180px;
     margin: 8px 0 0;
     padding: 10px;
     overflow: auto;
     white-space: pre-wrap;
-    word-break: break-word;
+    overflow-wrap: anywhere;
+    word-break: normal;
     border-radius: var(--radius-sm);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web-ui/styles/modals-core.css` around lines 779 - 791, Update the
.prompt-preset-preview rule to remove the deprecated word-break: break-word
declaration and use the modern equivalent properties: overflow-wrap: anywhere
and word-break: normal.

Source: Linters/SAST tools

web-ui/partials/index/panel-prompts.html (1)

60-78: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

selectedPromptPresetId is tracked but never surfaced in the UI.

web-ui/modules/app.methods.agents.mjs sets/clears selectedPromptPresetId on save, apply, and delete (and web-ui-preferences.mjs clears it defensively on preference sync), but no preset card here binds a class to preset.id === selectedPromptPresetId, so the tracked "currently selected/applied" preset is never visually indicated. Either surface it (e.g., highlight the active card) or, if unused, this is dead state that adds upkeep cost without benefit.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web-ui/partials/index/panel-prompts.html` around lines 60 - 78, Surface the
tracked selectedPromptPresetId in the prompt preset card UI by conditionally
applying the existing active/selected card styling when preset.id matches
selectedPromptPresetId. Update the article element in the promptPresets loop,
preserving the current card rendering and actions for unselected presets.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@web-ui/modules/app.methods.agents.mjs`:
- Around line 871-891: Update switchPromptsSubTab to guard navigation from the
presets tab to codex or claude-project with hasAgentsContentChanged() and
requestConfirmDialog, matching applyPromptPresetToEditor. Only change
promptsSubTab and continue loading or scrolling after confirmation; preserve
existing behavior when there are no unsaved changes or when entering presets.

---

Nitpick comments:
In `@tests/unit/prompt-presets.test.mjs`:
- Around line 91-92: Update the persistence assertions in the affected tests
around the existing persisted.length checks to verify the serialized persisted
snapshot, not just the number of writes. Compare the final snapshot against the
expected state, including overwritten and deleted presets and the cleared
selection, in both locations.
- Around line 54-57: Update the test VM’s requestConfirmDialog stub to support
queued or per-test confirmation responses instead of always returning true. Use
false responses to cover overwrite, apply, and delete cancellation paths, and
assert each cancellation leaves the relevant state unchanged while preserving
existing confirmation behavior.

In `@web-ui/partials/index/panel-prompts.html`:
- Around line 60-78: Surface the tracked selectedPromptPresetId in the prompt
preset card UI by conditionally applying the existing active/selected card
styling when preset.id matches selectedPromptPresetId. Update the article
element in the promptPresets loop, preserving the current card rendering and
actions for unselected presets.

In `@web-ui/styles/modals-core.css`:
- Around line 779-791: Update the .prompt-preset-preview rule to remove the
deprecated word-break: break-word declaration and use the modern equivalent
properties: overflow-wrap: anywhere and word-break: normal.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b693f286-cfc8-4fc9-95cb-a1870f27fc15

📥 Commits

Reviewing files that changed from the base of the PR and between 4d677fe and 8da6e32.

📒 Files selected for processing (17)
  • README.md
  • README.vi.md
  • README.zh.md
  • tests/unit/prompt-presets.test.mjs
  • tests/unit/run.mjs
  • tests/unit/web-ui-behavior-parity.test.mjs
  • web-ui/app.js
  • web-ui/modules/app.methods.agents.mjs
  • web-ui/modules/app.methods.web-ui-preferences.mjs
  • web-ui/modules/i18n/locales/en.mjs
  • web-ui/modules/i18n/locales/ja.mjs
  • web-ui/modules/i18n/locales/vi.mjs
  • web-ui/modules/i18n/locales/zh-tw.mjs
  • web-ui/modules/i18n/locales/zh.mjs
  • web-ui/partials/index/panel-prompts.html
  • web-ui/res/web-ui-render.precompiled.js
  • web-ui/styles/modals-core.css
✅ Files skipped from review due to trivial changes (5)
  • README.vi.md
  • tests/unit/run.mjs
  • README.md
  • README.zh.md
  • web-ui/modules/i18n/locales/zh.mjs
🚧 Files skipped from review as they are similar to previous changes (1)
  • web-ui/modules/i18n/locales/ja.mjs
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
  • GitHub Check: CodeRabbit
🧰 Additional context used
🪛 Stylelint (17.14.0)
web-ui/styles/modals-core.css

[error] 785-785: Deprecated keyword "break-word" for property "word-break" (declaration-property-value-keyword-no-deprecated)

(declaration-property-value-keyword-no-deprecated)

🔇 Additional comments (15)
web-ui/modules/i18n/locales/en.mjs (1)

170-176: LGTM!

Also applies to: 226-251

web-ui/modules/i18n/locales/vi.mjs (1)

130-137: LGTM!

Also applies to: 241-266

web-ui/modules/i18n/locales/zh-tw.mjs (1)

170-176: LGTM!

Also applies to: 226-251

tests/unit/prompt-presets.test.mjs (1)

1-53: LGTM!

Also applies to: 58-90, 93-144, 146-147

tests/unit/web-ui-behavior-parity.test.mjs (1)

378-383: LGTM!

Also applies to: 430-435, 658-668

web-ui/app.js (2)

77-82: LGTM!


739-755: 🎯 Functional Correctness

Watcher/skip-flag logic verified consistent.

The __skipNextPromptsSubTabLoad guard is set before the reactive promptsSubTab assignment in applyPromptPresetToEditor (agents.mjs), so the watcher correctly no-ops for that one transition, and persistWebUiPreferences still fires regardless of the skip flag. No double-load or missed-load found. Note: the unconditional loadPromptsContent() call for non-skipped, non-presets transitions can discard unsaved editor drafts when returning from the presets tab — see the corresponding comment on switchPromptsSubTab in web-ui/modules/app.methods.agents.mjs.

web-ui/modules/app.methods.web-ui-preferences.mjs (2)

69-86: 📐 Maintainability & Code Quality | 💤 Low value

Solid normalization/dedup logic.

De-dup via the seen Set with comma-operator side effect, ID fallback generation, and field coercion all look correct. One minor note: the epoch fallback for missing updatedAt (new Date(0).toISOString()) means callers relying on "empty string means unknown" (see formatPromptPresetTime in web-ui/modules/app.methods.agents.mjs) will never actually hit that fallback path, since this always returns a non-empty string.


336-336: LGTM!

Also applies to: 389-394

web-ui/modules/app.methods.agents.mjs (3)

712-754: LGTM!


755-824: LGTM!


825-870: LGTM!

web-ui/partials/index/panel-prompts.html (1)

11-11: LGTM!

Also applies to: 115-115

web-ui/res/web-ui-render.precompiled.js (1)

6677-6684: LGTM!

Also applies to: 6722-6819, 6828-7038

web-ui/styles/modals-core.css (1)

729-777: LGTM!

Also applies to: 793-802

@coderabbitai coderabbitai Bot left a comment

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.

🧹 Nitpick comments (1)
cli/openai-bridge.js (1)

501-512: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Unreachable SSE branch — dead code.

Reaching Line 501 implies the earlier if (streamRequested && wantsSse) guard (Line 435) was false and returned otherwise. Since converted.streamRequested is derived from the same stream === true as streamRequested (see convertResponsesRequestToChatCompletions), the condition converted.streamRequested && wantsSse is always false at this point, so this block never executes. A stream: true request without an text/event-stream Accept correctly falls through to the JSON response at Line 514.

♻️ Remove the dead SSE branch
-            if (converted.streamRequested && wantsSse) {
-                res.writeHead(200, {
-                    'Content-Type': 'text/event-stream; charset=utf-8',
-                    'Cache-Control': 'no-cache',
-                    'Connection': 'keep-alive',
-                    'X-Accel-Buffering': 'no'
-                });
-                if (typeof res.flushHeaders === 'function') res.flushHeaders();
-                sendResponsesSse(res, responsesPayload);
-                res.end();
-                return;
-            }
-
             res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cli/openai-bridge.js` around lines 501 - 512, Remove the unreachable SSE
response branch guarded by converted.streamRequested && wantsSse, including its
header setup, sendResponsesSse call, and early return. Preserve the earlier
streaming guard and allow non-SSE requests to continue to the existing JSON
response path.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@cli/openai-bridge.js`:
- Around line 501-512: Remove the unreachable SSE response branch guarded by
converted.streamRequested && wantsSse, including its header setup,
sendResponsesSse call, and early return. Preserve the earlier streaming guard
and allow non-SSE requests to continue to the existing JSON response path.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 37c4dc47-b6d8-4c9d-8e04-ada087ab380c

📥 Commits

Reviewing files that changed from the base of the PR and between 458a1be and 79083a8.

📒 Files selected for processing (6)
  • cli/openai-bridge.js
  • tests/unit/config-tabs-ui.test.mjs
  • tests/unit/openai-bridge-upstream-responses.test.mjs
  • web-ui/partials/index/panel-prompts.html
  • web-ui/res/web-ui-render.precompiled.js
  • web-ui/styles/modals-core.css
✅ Files skipped from review due to trivial changes (1)
  • web-ui/styles/modals-core.css
🚧 Files skipped from review as they are similar to previous changes (3)
  • tests/unit/config-tabs-ui.test.mjs
  • web-ui/partials/index/panel-prompts.html
  • web-ui/res/web-ui-render.precompiled.js
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
  • GitHub Check: CodeRabbit
🔇 Additional comments (3)
cli/openai-bridge.js (2)

428-435: LGTM!


435-464: LGTM!

tests/unit/openai-bridge-upstream-responses.test.mjs (1)

143-227: LGTM!

Also applies to: 229-294, 296-352, 535-541, 598-657, 667-732, 1215-1273, 1553-1606

@coderabbitai coderabbitai Bot left a comment

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.

🧹 Nitpick comments (1)
tests/unit/config-tabs-ui.test.mjs (1)

86-92: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider adding parity assertions for the prompts side tab.

Other side tabs verify @pointerdown, data-main-tab, :aria-current, and isMainTabNavActive (e.g., lines 46–48 for sessions, 371–374 for config/docs, 421–422 for settings/market). The prompts tab assertions don't cover these attributes. Adding them would keep the test suite consistent and catch regressions if the tab's active-state or pointer binding is accidentally removed.

💡 Optional parity assertions
     assert.match(html, /id="side-tab-prompts"/);
     assert.doesNotMatch(html, /id="side-tab-prompts-agents"/);
     assert.doesNotMatch(html, /id="side-tab-prompts-project"/);
     assert.doesNotMatch(html, /id="side-tab-prompts-presets"/);
     assert.match(html, /@click="onMainTabClick\('prompts', \$event\)"/);
+    assert.match(html, /@pointerdown="onMainTabPointerDown\('prompts', \$event\)"/);
+    assert.match(html, /data-main-tab="prompts"/);
+    assert.match(html, /:aria-current="mainTab === 'prompts' \? 'page' : null"/);
+    assert.match(html, /isMainTabNavActive\('prompts'\)/);
     assert.match(html, /t\('side\.prompts'\)/);
     assert.match(html, /t\('side\.prompts\.meta'\)/);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unit/config-tabs-ui.test.mjs` around lines 86 - 92, Extend the prompts
side-tab assertions around the existing prompts checks to cover parity with
other main tabs: verify its `@pointerdown` binding, data-main-tab value,
:aria-current binding, and isMainTabNavActive usage. Keep the existing prompts
content and click-handler assertions unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@tests/unit/config-tabs-ui.test.mjs`:
- Around line 86-92: Extend the prompts side-tab assertions around the existing
prompts checks to cover parity with other main tabs: verify its `@pointerdown`
binding, data-main-tab value, :aria-current binding, and isMainTabNavActive
usage. Keep the existing prompts content and click-handler assertions unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 3184b58e-789f-4fa7-8516-9279ef3d7caa

📥 Commits

Reviewing files that changed from the base of the PR and between 79083a8 and 6b96164.

📒 Files selected for processing (9)
  • tests/unit/config-tabs-ui.test.mjs
  • tests/unit/i18n-locales.test.mjs
  • web-ui/modules/i18n/locales/en.mjs
  • web-ui/modules/i18n/locales/ja.mjs
  • web-ui/modules/i18n/locales/vi.mjs
  • web-ui/modules/i18n/locales/zh-tw.mjs
  • web-ui/modules/i18n/locales/zh.mjs
  • web-ui/partials/index/layout-header.html
  • web-ui/res/web-ui-render.precompiled.js
✅ Files skipped from review due to trivial changes (4)
  • web-ui/modules/i18n/locales/en.mjs
  • web-ui/modules/i18n/locales/zh.mjs
  • web-ui/modules/i18n/locales/ja.mjs
  • web-ui/modules/i18n/locales/vi.mjs
🚧 Files skipped from review as they are similar to previous changes (3)
  • tests/unit/i18n-locales.test.mjs
  • web-ui/modules/i18n/locales/zh-tw.mjs
  • web-ui/res/web-ui-render.precompiled.js
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
  • GitHub Check: CodeRabbit
🔇 Additional comments (2)
web-ui/partials/index/layout-header.html (1)

258-270: LGTM!

tests/unit/config-tabs-ui.test.mjs (1)

86-97: LGTM!

@coderabbitai coderabbitai Bot left a comment

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.

🧹 Nitpick comments (1)
web-ui/modules/app.methods.agents.mjs (1)

834-840: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Applying a preset silently discards unsaved editor edits.

applyPromptPresetToEditor overwrites this.agentsContent unconditionally, with no check against hasAgentsContentChanged(). If the user has unsaved edits in the AGENTS.md/CLAUDE.md editor, clicking "paste" on a preset discards them with no confirmation — confirmed intentional by the test at tests/unit/prompt-presets.test.mjs:146-163 (agentsContent: 'dirty' vs agentsOriginalContent: 'original', asserting confirms.length === 0). Given other destructive actions in this file (e.g. closeAgentsModal) do guard via hasPendingAgentsDraft()/requestConfirmDialog, consider adding an analogous guard here to avoid silent loss of in-progress edits, even though the current behavior matches the documented PR intent.

♻️ Optional guard for unsaved edits
 async applyPromptPresetToEditor(preset) {
     if (!preset || typeof preset.content !== 'string' || !preset.content) return;
+    if (this.hasAgentsContentChanged()) {
+        const confirmed = await this.requestConfirmDialog({
+            title: this.t('prompts.presets.confirm.overwriteEditorTitle'),
+            message: this.t('prompts.presets.confirm.overwriteEditorMessage'),
+            confirmText: this.t('common.confirm'),
+            cancelText: this.t('common.cancel'),
+            danger: true
+        });
+        if (!confirmed) return;
+    }
     this.agentsContent = preset.content;
     this.onAgentsContentInput();
     this.selectedPromptPresetId = preset.id;
     this.showMessage(this.t('prompts.presets.toast.pasted'), 'success');
 },

Note: adopting this would require updating the existing test expectations (confirms.length assertions) accordingly.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web-ui/modules/app.methods.agents.mjs` around lines 834 - 840, Update
applyPromptPresetToEditor to check for unsaved editor content via
hasAgentsContentChanged() before overwriting agentsContent; when edits exist,
request confirmation through the established requestConfirmDialog flow and abort
unless confirmed. Preserve the existing preset application and success message
behavior when there are no pending edits or the user confirms, and update the
related test expectations.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@web-ui/modules/app.methods.agents.mjs`:
- Around line 834-840: Update applyPromptPresetToEditor to check for unsaved
editor content via hasAgentsContentChanged() before overwriting agentsContent;
when edits exist, request confirmation through the established
requestConfirmDialog flow and abort unless confirmed. Preserve the existing
preset application and success message behavior when there are no pending edits
or the user confirms, and update the related test expectations.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: c938c425-bbc3-40ce-bb89-9c4a2335f7be

📥 Commits

Reviewing files that changed from the base of the PR and between 18b2971 and e2e4000.

📒 Files selected for processing (11)
  • tests/unit/config-tabs-ui.test.mjs
  • tests/unit/i18n-locales.test.mjs
  • tests/unit/prompt-presets.test.mjs
  • web-ui/modules/app.methods.agents.mjs
  • web-ui/modules/i18n/locales/en.mjs
  • web-ui/modules/i18n/locales/ja.mjs
  • web-ui/modules/i18n/locales/vi.mjs
  • web-ui/modules/i18n/locales/zh-tw.mjs
  • web-ui/modules/i18n/locales/zh.mjs
  • web-ui/partials/index/panel-prompts.html
  • web-ui/res/web-ui-render.precompiled.js
✅ Files skipped from review due to trivial changes (4)
  • web-ui/modules/i18n/locales/zh-tw.mjs
  • web-ui/modules/i18n/locales/zh.mjs
  • web-ui/modules/i18n/locales/vi.mjs
  • web-ui/modules/i18n/locales/en.mjs
🚧 Files skipped from review as they are similar to previous changes (2)
  • tests/unit/i18n-locales.test.mjs
  • web-ui/res/web-ui-render.precompiled.js
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
  • GitHub Check: CodeRabbit
🔇 Additional comments (5)
web-ui/modules/app.methods.agents.mjs (1)

711-754: LGTM!

Also applies to: 786-833, 841-907

web-ui/partials/index/panel-prompts.html (1)

11-11: LGTM!

Also applies to: 36-85, 118-118

web-ui/modules/i18n/locales/ja.mjs (1)

147-147: LGTM!

Also applies to: 172-186, 230-254

tests/unit/config-tabs-ui.test.mjs (1)

86-103: LGTM!

tests/unit/prompt-presets.test.mjs (1)

146-163: LGTM!

@coderabbitai coderabbitai Bot left a comment

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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
web-ui/modules/app.methods.agents.mjs (1)

834-839: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Guard preset application while the editor is not writable.

The preset-list “Paste” action remains available during loading, saving, and diff preview. This method unconditionally replaces agentsContent, then onAgentsContentInput() clears the active diff. A click can therefore discard an unsaved draft or have its content overwritten by an in-flight file load. Guard this method with agentsLoading || agentsSaving || agentsDiffVisible, and mirror that guard in the row action buttons.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web-ui/modules/app.methods.agents.mjs` around lines 834 - 839, Update
applyPromptPresetToEditor to return immediately when agentsLoading,
agentsSaving, or agentsDiffVisible is true, before modifying agentsContent or
clearing the diff. Apply the same disabled/guard condition to the preset-list
row action buttons so Paste cannot be triggered while the editor is loading,
saving, or showing a diff.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@web-ui/modules/app.methods.agents.mjs`:
- Around line 834-839: Update applyPromptPresetToEditor to return immediately
when agentsLoading, agentsSaving, or agentsDiffVisible is true, before modifying
agentsContent or clearing the diff. Apply the same disabled/guard condition to
the preset-list row action buttons so Paste cannot be triggered while the editor
is loading, saving, or showing a diff.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 5bc2d1ba-b615-4e33-bae9-c57ad42a4829

📥 Commits

Reviewing files that changed from the base of the PR and between e2e4000 and 0153983.

📒 Files selected for processing (15)
  • tests/unit/config-tabs-ui.test.mjs
  • tests/unit/i18n-locales.test.mjs
  • tests/unit/prompt-presets.test.mjs
  • tests/unit/web-ui-behavior-parity.test.mjs
  • web-ui/app.js
  • web-ui/modules/app.methods.agents.mjs
  • web-ui/modules/app.methods.web-ui-preferences.mjs
  • web-ui/modules/i18n/locales/en.mjs
  • web-ui/modules/i18n/locales/ja.mjs
  • web-ui/modules/i18n/locales/vi.mjs
  • web-ui/modules/i18n/locales/zh-tw.mjs
  • web-ui/modules/i18n/locales/zh.mjs
  • web-ui/partials/index/panel-prompts.html
  • web-ui/res/web-ui-render.precompiled.js
  • web-ui/styles/modals-core.css
✅ Files skipped from review due to trivial changes (5)
  • web-ui/styles/modals-core.css
  • tests/unit/i18n-locales.test.mjs
  • web-ui/modules/i18n/locales/en.mjs
  • web-ui/modules/i18n/locales/zh.mjs
  • web-ui/modules/i18n/locales/vi.mjs
🚧 Files skipped from review as they are similar to previous changes (4)
  • tests/unit/config-tabs-ui.test.mjs
  • web-ui/modules/i18n/locales/zh-tw.mjs
  • tests/unit/web-ui-behavior-parity.test.mjs
  • tests/unit/prompt-presets.test.mjs
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
  • GitHub Check: CodeRabbit
🔇 Additional comments (8)
web-ui/app.js (2)

77-82: LGTM!

Also applies to: 735-745


746-751: 🎯 Functional Correctness

Drop this concern: __skipNextPromptsSubTabLoad is not armed in applyWebUiPreferences, so a no-op promptsSubTab restore cannot leave the watcher stuck.

			> Likely an incorrect or invalid review comment.
web-ui/modules/app.methods.web-ui-preferences.mjs (1)

63-85: LGTM!

Also applies to: 336-336, 389-394

web-ui/modules/app.methods.agents.mjs (2)

711-749: LGTM!

Also applies to: 895-896


750-752: 🗄️ Data Integrity & Integration

Preset persistence is best-effort, not transactional. persistWebUiPreferences() only queues a preference flush and swallows write errors, so these save/rename/delete flows can’t observe a rejection or roll back in-memory changes.

			> Likely an incorrect or invalid review comment.
web-ui/partials/index/panel-prompts.html (1)

35-35: LGTM!

Also applies to: 69-76, 95-132

web-ui/res/web-ui-render.precompiled.js (1)

365-380: LGTM!

Also applies to: 6763-6776

web-ui/modules/i18n/locales/ja.mjs (1)

147-147: LGTM!

Also applies to: 172-186, 230-255

@coderabbitai coderabbitai Bot left a comment

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.

🧹 Nitpick comments (1)
web-ui/styles/responsive.css (1)

623-638: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

The 540px preset rules are identical to the 720px rules and thus redundant.

Since max-width: 540px is a subset of max-width: 720px, the rules at lines 623–638 are already in effect at 540px. This duplication is a maintainability risk—if the 720px rules change, the 540px copy may be forgotten and diverge silently.

Note: the existing .prompts-editor-toolbar / .prompts-editor-actions rules follow the same pattern, so this may be an intentional convention. If so, consider adding a comment noting the duplication is deliberate.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@web-ui/styles/responsive.css` around lines 623 - 638, Remove the redundant
540px declarations for .prompt-presets-inline-row, .prompt-presets-inline-group,
.prompt-presets-inline-group--save, .prompt-presets-select, and
.prompt-presets-name-input because the max-width: 720px rules already apply; if
retaining the duplication to match the existing responsive convention, add a
concise comment documenting that it is intentional.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@web-ui/styles/responsive.css`:
- Around line 623-638: Remove the redundant 540px declarations for
.prompt-presets-inline-row, .prompt-presets-inline-group,
.prompt-presets-inline-group--save, .prompt-presets-select, and
.prompt-presets-name-input because the max-width: 720px rules already apply; if
retaining the duplication to match the existing responsive convention, add a
concise comment documenting that it is intentional.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 545c01c9-9dd9-41a0-8c4f-d484b6e86992

📥 Commits

Reviewing files that changed from the base of the PR and between 63632fa and afe6355.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (10)
  • package.json
  • web-ui/modules/i18n/locales/en.mjs
  • web-ui/modules/i18n/locales/ja.mjs
  • web-ui/modules/i18n/locales/vi.mjs
  • web-ui/modules/i18n/locales/zh-tw.mjs
  • web-ui/modules/i18n/locales/zh.mjs
  • web-ui/partials/index/panel-prompts.html
  • web-ui/res/web-ui-render.precompiled.js
  • web-ui/styles/modals-core.css
  • web-ui/styles/responsive.css
✅ Files skipped from review due to trivial changes (3)
  • package.json
  • web-ui/modules/i18n/locales/vi.mjs
  • web-ui/res/web-ui-render.precompiled.js
🚧 Files skipped from review as they are similar to previous changes (5)
  • web-ui/styles/modals-core.css
  • web-ui/partials/index/panel-prompts.html
  • web-ui/modules/i18n/locales/zh-tw.mjs
  • web-ui/modules/i18n/locales/en.mjs
  • web-ui/modules/i18n/locales/ja.mjs
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
  • GitHub Check: CodeRabbit
🔇 Additional comments (1)
web-ui/modules/i18n/locales/zh.mjs (1)

146-146: LGTM!

Also applies to: 184-185, 229-234, 245-252

@ymkiux ymkiux merged commit 005cbdb into main Jul 12, 2026
12 checks passed
@ymkiux ymkiux deleted the fix/sidebar-config-meta-copy branch July 12, 2026 04:08
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