Skip to content

[4/4] feat(settings): add commit message model picker - #1230

Open
Rafael-Silva-Oliveira wants to merge 4 commits into
Zoo-Code-Org:mainfrom
Rafael-Silva-Oliveira:feat/commit-msg-4-settings
Open

[4/4] feat(settings): add commit message model picker#1230
Rafael-Silva-Oliveira wants to merge 4 commits into
Zoo-Code-Org:mainfrom
Rafael-Silva-Oliveira:feat/commit-msg-4-settings

Conversation

@Rafael-Silva-Oliveira

@Rafael-Silva-Oliveira Rafael-Silva-Oliveira commented Aug 12, 2026

Copy link
Copy Markdown

Related GitHub Issue

Closes: #291

Part of: #145 · Stack 4 of 4 · Depends on #1227, #1228, #1229 · Replaces the all-in-one #1218

Description

Adds the Commit Message Model picker to Settings → Providers, so the profile used
for commit messages can be chosen without editing configuration by hand. The setting
itself (commitMessageApiConfigId) landed in stack 2; this is the control that sets it.

Why Providers rather than Prompts. The enhancement equivalent lives in the Prompts
tab, so there is a reasonable argument either way. This sits in Providers because it
selects a provider profile, directly below the profile it relates to — the prompt text
lives in Prompts, the model choice lives with the models. Happy to move it if you would
rather keep the two pickers together.

Binds to cachedState, saves with the Save button, per the SettingsView pattern in
AGENTS.md — not an immediate-persist postMessage. The value is included in the
updateSettings payload and round-trips through getStateToPostToWebview, so the
selection survives a reload rather than visually reverting.

Accessibility. A sibling <label> does not name a Radix trigger, so the label and
trigger are linked with aria-labelledby and the relationship is covered by a test
rather than assumed.

Test Procedure

CommitMessageModelSelect.spec.tsx covers: rendering the profile list alongside the
fallback option, the "-" sentinel mapping to "", showing a saved profile, storing a
selected id, and the label-to-trigger accessibility relationship.

SettingsView.spec.tsx gains a test asserting the setting survives the cachedState
round trip into the updateSettings payload — the failure mode being a control that
renders and appears to save but is dropped from the payload.

Translations for all 17 locales are included, not left as English fallbacks.

Manual verification: set the picker to a specific profile → Save → reload the window →
selection persists → generating a message uses the chosen provider.

Local checks: pnpm lint, pnpm check-types (11/11 packages), full webview-ui suite
(1679 passed), full src suite (7389 passed, 37 skipped),
node scripts/find-missing-translations.js.

Pre-Submission Checklist

  • Issue Linked: This PR is linked to an approved GitHub Issue (see "Related GitHub Issue" above).
  • Scope: My changes are focused on the linked issue (one major feature/fix per PR).
  • Self-Review: I have performed a thorough self-review of my code.
  • Testing: New and/or updated tests have been added to cover my changes (if applicable).
  • Visual Snapshot (UI changes only): see below.
  • Documentation Impact: I have considered if my changes require documentation updates.
  • Contribution Guidelines: I have read and agree to the Contributor Guidelines.

Visual Snapshots

Check #1218

Documentation Updates

  • No documentation updates are required.
  • Yes, documentation updates are required.

Worth a line in the docs alongside the Source Control button from stack 3, noting that a
small fast profile is usually the right choice here.

Additional Notes

This completes the stack. Of the #145 sub-issues, #289 (progress/cancellation UX) is only
partially addressed — progress and error handling are done, but there is no cancel
button, because no progress location renders one that would work while nearly every
provider ignores completePrompt's abort signal. #292 (telemetry) is untouched. Both
remain open for follow-up.

Review order: #1227#1228#1229 → 4. All target main because GitHub cannot base
a cross-fork PR on another fork's branch, so this diff appears cumulative until the
parents merge. The Commits tab shows only this PR's own commit.

Summary by CodeRabbit

  • New Features

    • Added a Source Control command to generate Conventional Commits-style messages from staged or working-tree changes.
    • Generated messages are inserted into the Git commit input and include progress and error notifications.
    • Added an optional dedicated model setting, with fallback to the current configuration.
    • Command icons now support light and dark image variants.
  • Localization

    • Added translated command, settings, prompt, status, and error messages across supported languages.
  • Tests

    • Added coverage for generation, repository handling, settings persistence, and command execution.

Rafael-Silva-Oliveira and others added 4 commits August 12, 2026 13:28
Adds `getCommitContext()`, which gathers the changes a commit message should
describe. Part 1 of 4 for AI commit-message generation; nothing consumes it yet.

Staged changes are collected first, since that is what a commit will actually
contain. When nothing is staged it falls back to the working tree so callers
still have something to summarize before staging. The fallback reads
`git status --short` rather than a diff because untracked files appear in no
diff and would otherwise be invisible.

The fallback deliberately runs `git diff` rather than `git diff HEAD`: the index
is known to be empty at that point so the output is identical, but `HEAD` does
not resolve in a repository without an initial commit, where it would fail.

Reuses the existing `checkGitInstalled`, `checkGitRepo`, and `truncateOutput`
helpers. `maxBuffer` is raised past Node's 1MB `exec` default, which real diffs
routinely exceed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Part 2 of 4 for AI commit-message generation. Adds the model-facing half:
a customizable prompt and a service that turns git context into a message.
No command or UI wires it up yet.

- Registers COMMIT_MESSAGE in `support-prompt.ts` alongside ENHANCE. Because
  the Prompts settings tab iterates the support-prompt registry, this gives the
  template an editor and a reset button without any new UI code. The default
  asks for Conventional Commits and tells the model to account for every changed
  file; without that instruction models describe the largest file and silently
  drop the rest.
- Adds `commitMessageApiConfigId` so a small, fast profile can be used for this
  task. Mirrors `enhancementApiConfigId`, including the `listApiConfigMeta`
  guard before `getProfile()` so a deleted profile falls back to the active
  configuration rather than throwing.
- Adds `generateCommitMessage()`, which resolves the repository from the git
  extension API, collects context, and writes the cleaned result into the SCM
  input box. Models wrap answers in fences and quotes despite instruction, so
  the response is stripped before use.

Progress is reported at `ProgressLocation.Window`; `SourceControl` drops the
title, and no location renders a cancel button that would work, since nearly
every provider ignores `completePrompt`'s abort signal.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Part 3 of 4 for AI commit-message generation. Wires the generator to a button
in the Source Control title bar, making the feature reachable for the first
time.

The command receives the clicked `SourceControl`, which lets the generator pick
the right repository in a multi-root workspace. It resolves the provider from
`registerCommands` rather than the visible instance, so the button works while
the Zoo Code sidebar is closed.

The icon is the existing zebra mark, reusing the `panel_light`/`panel_dark` pair
already shipped for the tab icon. That required widening `commandsSchema.icon`
in `packages/build`: it accepted only a codicon string, so a themed
{light, dark} pair would have thrown in `contributesSchema.parse()` during the
nightly manifest build. That path only runs under `vsix:nightly`, so the failure
would not have surfaced in normal development.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Part 4 of 4 for AI commit-message generation. Exposes `commitMessageApiConfigId`
in Settings > Providers, so the profile used for commit messages can be chosen
without editing configuration by hand.

The picker sits directly below the provider options, next to the profile it
selects. It binds to `cachedState` and saves with the Save button, following the
SettingsView pattern rather than persisting immediately.

A sibling label does not name a Radix trigger, so the label and trigger are
linked with `aria-labelledby` and the relationship is covered by a test.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Adds AI-generated commit messages from Git changes through a Source Control command. The change includes Git context extraction, provider-profile selection, settings persistence, prompt definitions, command registration, tests, and localization.

Changes

Commit message generation

Layer / File(s) Summary
Command surface and registration
packages/build/src/types.ts, packages/types/src/vscode.ts, src/package.json, src/package.nls.*.json, src/activate/registerCommands.ts, src/activate/__tests__/registerCommands.spec.ts
Adds the generateCommitMessage command, localized titles, light/dark icons, Git SCM menu placement, command registration, and handler tests.
Git context and prompt contract
src/utils/git.ts, src/utils/__tests__/git.spec.ts, src/shared/support-prompt.ts
Adds staged and working-tree context extraction, untracked-file handling, empty-repository support, diff limits, and the COMMIT_MESSAGE prompt configuration.
Commit-message generation service
src/services/commit-message/index.ts, src/services/commit-message/__tests__/generateCommitMessage.spec.ts, src/i18n/locales/*/common.json
Adds repository resolution, provider fallback, progress reporting, output cleanup, Source Control input updates, localized errors, and service tests.
Commit-message model settings
packages/types/src/global-settings.ts, packages/types/src/vscode-extension-host.ts, src/core/webview/ClineProvider.ts, webview-ui/src/components/settings/*
Adds commitMessageApiConfigId to settings and extension state. Adds a searchable model selector with current-configuration fallback and persistence tests.
Prompt and settings localization
webview-ui/src/i18n/locales/*/prompts.json, webview-ui/src/i18n/locales/*/settings.json
Adds localized prompt descriptions and model-setting labels for the supported locales.

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

Possibly related issues

  • Issue 285: The changes add the dedicated commitMessageApiConfigId setting, profile selection and fallback logic, state plumbing, UI, and tests described by the issue.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The diff includes generation logic, Git context, command registration, prompts, and localization beyond issue #291's settings picker. Restrict this PR to the picker and its persistence tests, or link the additional stack issues and split the broader implementation into separately scoped PRs.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The PR satisfies #291 by adding profile selection, current-config fallback, cached-state persistence, save-flow integration, and tests.
Docstring Coverage ✅ Passed Docstring coverage is 80.00% which is sufficient. The required threshold is 80.00%.
Title check ✅ Passed The title clearly and concisely identifies the main change: adding a commit message model picker to settings.
Description check ✅ Passed The description covers the linked issue, implementation, testing, checklist, visual snapshots, documentation, and additional review context.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@codecov

codecov Bot commented Aug 12, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 89.06250% with 7 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/services/commit-message/index.ts 82.35% 1 Missing and 5 partials ⚠️
...ebview-ui/src/components/settings/SettingsView.tsx 0.00% 0 Missing and 1 partial ⚠️

📢 Thoughts on this report? Let us know!

@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.

Actionable comments posted: 6

🧹 Nitpick comments (1)
packages/types/src/global-settings.ts (1)

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

Add an explicit empty-string fallback test. CommitMessageModelSelect persists "", and updateSettings stores it unchanged. The service tests cover undefined and an unknown ID, but not ""; assert that generateCommitMessage uses apiConfiguration and does not call getProfile for "".

🤖 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 `@packages/types/src/global-settings.ts` at line 238, Extend the service tests
for generateCommitMessage to cover an empty commitMessageApiConfigId ("").
Assert that apiConfiguration is used and getProfile is not called, alongside the
existing undefined and unknown-ID cases.

Source: Learnings

🤖 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.

Inline comments:
In `@src/activate/__tests__/registerCommands.spec.ts`:
- Line 203: Update the test invocation of
handlers["zoo-code.generateCommitMessage"] to await the returned promise,
ensuring rejected asynchronous handlers fail the test instead of remaining
floating promises.

In `@src/services/commit-message/__tests__/generateCommitMessage.spec.ts`:
- Around line 44-53: Update the makeProvider test-double factory to avoid the
undocumented `as unknown as ClineProvider` assertion by using a properly typed
factory or an explicit, nearby explanation if the structural cast is required.
Preserve the existing mocked getState and providerSettingsManager behavior.

In `@src/services/commit-message/index.ts`:
- Around line 101-104: Handle getProfile() failure in the commit-message
generation flow around commitMessageApiConfigId so a deleted metadata-listed
profile falls back to apiConfiguration instead of propagating to the outer
generation-error handler. Update src/services/commit-message/index.ts lines
101-104 accordingly; in
src/services/commit-message/__tests__/generateCommitMessage.spec.ts lines
102-110, make getProfile() reject and assert generation uses apiConfiguration.

In `@src/utils/__tests__/git.spec.ts`:
- Around line 423-425: Expand the assertion in the diffCommands loop so the
regex rejects shell metacharacters including ;, &, |, backticks, $, <, and > in
addition to the existing quotes and parentheses. Keep the test focused on
validating every command produced by the diff command construction.

In `@webview-ui/src/i18n/locales/ca/settings.json`:
- Around line 360-361: Update the Catalan label and description in the settings
locale entry to use “commit” or “confirmació” for the Git operation instead of
“comissió,” while preserving the existing meaning about generating commit
messages and using the active profile when unselected.

In `@webview-ui/src/i18n/locales/es/prompts.json`:
- Around line 107-110: Update the COMMIT_MESSAGE localization entry to use the
Git term “commit” consistently: change the label to “Mensaje de commit” and
replace the corresponding “mensaje de confirmación” wording in the description,
preserving the rest of the Spanish text.

---

Nitpick comments:
In `@packages/types/src/global-settings.ts`:
- Line 238: Extend the service tests for generateCommitMessage to cover an empty
commitMessageApiConfigId (""). Assert that apiConfiguration is used and
getProfile is not called, alongside the existing undefined and unknown-ID cases.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 40e13bfb-c393-483b-88dd-341b862b9685

📥 Commits

Reviewing files that changed from the base of the PR and between abaf732 and 884c88f.

📒 Files selected for processing (89)
  • packages/build/src/types.ts
  • packages/types/src/global-settings.ts
  • packages/types/src/vscode-extension-host.ts
  • packages/types/src/vscode.ts
  • src/activate/__tests__/registerCommands.spec.ts
  • src/activate/registerCommands.ts
  • src/core/webview/ClineProvider.ts
  • src/i18n/locales/ca/common.json
  • src/i18n/locales/de/common.json
  • src/i18n/locales/en/common.json
  • src/i18n/locales/es/common.json
  • src/i18n/locales/fr/common.json
  • src/i18n/locales/hi/common.json
  • src/i18n/locales/id/common.json
  • src/i18n/locales/it/common.json
  • src/i18n/locales/ja/common.json
  • src/i18n/locales/ko/common.json
  • src/i18n/locales/nl/common.json
  • src/i18n/locales/pl/common.json
  • src/i18n/locales/pt-BR/common.json
  • src/i18n/locales/ru/common.json
  • src/i18n/locales/tr/common.json
  • src/i18n/locales/vi/common.json
  • src/i18n/locales/zh-CN/common.json
  • src/i18n/locales/zh-TW/common.json
  • src/package.json
  • src/package.nls.ca.json
  • src/package.nls.de.json
  • src/package.nls.es.json
  • src/package.nls.fr.json
  • src/package.nls.hi.json
  • src/package.nls.id.json
  • src/package.nls.it.json
  • src/package.nls.ja.json
  • src/package.nls.json
  • src/package.nls.ko.json
  • src/package.nls.nl.json
  • src/package.nls.pl.json
  • src/package.nls.pt-BR.json
  • src/package.nls.ru.json
  • src/package.nls.tr.json
  • src/package.nls.vi.json
  • src/package.nls.zh-CN.json
  • src/package.nls.zh-TW.json
  • src/services/commit-message/__tests__/generateCommitMessage.spec.ts
  • src/services/commit-message/index.ts
  • src/shared/support-prompt.ts
  • src/utils/__tests__/git.spec.ts
  • src/utils/git.ts
  • webview-ui/src/components/settings/CommitMessageModelSelect.tsx
  • webview-ui/src/components/settings/SettingsView.tsx
  • webview-ui/src/components/settings/__tests__/CommitMessageModelSelect.spec.tsx
  • webview-ui/src/components/settings/__tests__/SettingsView.spec.tsx
  • webview-ui/src/i18n/locales/ca/prompts.json
  • webview-ui/src/i18n/locales/ca/settings.json
  • webview-ui/src/i18n/locales/de/prompts.json
  • webview-ui/src/i18n/locales/de/settings.json
  • webview-ui/src/i18n/locales/en/prompts.json
  • webview-ui/src/i18n/locales/en/settings.json
  • webview-ui/src/i18n/locales/es/prompts.json
  • webview-ui/src/i18n/locales/es/settings.json
  • webview-ui/src/i18n/locales/fr/prompts.json
  • webview-ui/src/i18n/locales/fr/settings.json
  • webview-ui/src/i18n/locales/hi/prompts.json
  • webview-ui/src/i18n/locales/hi/settings.json
  • webview-ui/src/i18n/locales/id/prompts.json
  • webview-ui/src/i18n/locales/id/settings.json
  • webview-ui/src/i18n/locales/it/prompts.json
  • webview-ui/src/i18n/locales/it/settings.json
  • webview-ui/src/i18n/locales/ja/prompts.json
  • webview-ui/src/i18n/locales/ja/settings.json
  • webview-ui/src/i18n/locales/ko/prompts.json
  • webview-ui/src/i18n/locales/ko/settings.json
  • webview-ui/src/i18n/locales/nl/prompts.json
  • webview-ui/src/i18n/locales/nl/settings.json
  • webview-ui/src/i18n/locales/pl/prompts.json
  • webview-ui/src/i18n/locales/pl/settings.json
  • webview-ui/src/i18n/locales/pt-BR/prompts.json
  • webview-ui/src/i18n/locales/pt-BR/settings.json
  • webview-ui/src/i18n/locales/ru/prompts.json
  • webview-ui/src/i18n/locales/ru/settings.json
  • webview-ui/src/i18n/locales/tr/prompts.json
  • webview-ui/src/i18n/locales/tr/settings.json
  • webview-ui/src/i18n/locales/vi/prompts.json
  • webview-ui/src/i18n/locales/vi/settings.json
  • webview-ui/src/i18n/locales/zh-CN/prompts.json
  • webview-ui/src/i18n/locales/zh-CN/settings.json
  • webview-ui/src/i18n/locales/zh-TW/prompts.json
  • webview-ui/src/i18n/locales/zh-TW/settings.json

const { generateCommitMessage } = await import("../../services/commit-message")
const sourceControl = { rootUri: { fsPath: "/repo" } }

handlers["zoo-code.generateCommitMessage"](sourceControl)

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Await the asynchronous command handler.

Line 203 leaves the promise returned by generateCommitMessage unobserved. Await the call so a rejected handler fails the test instead of becoming a floating promise.

Proposed test fix
-		handlers["zoo-code.generateCommitMessage"](sourceControl)
+		await handlers["zoo-code.generateCommitMessage"](sourceControl)

As per coding guidelines, “Avoid floating promises; use void, await, or .catch() as appropriate.”

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
handlers["zoo-code.generateCommitMessage"](sourceControl)
await handlers["zoo-code.generateCommitMessage"](sourceControl)
🤖 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 `@src/activate/__tests__/registerCommands.spec.ts` at line 203, Update the test
invocation of handlers["zoo-code.generateCommitMessage"] to await the returned
promise, ensuring rejected asynchronous handlers fail the test instead of
remaining floating promises.

Source: Coding guidelines

Comment on lines +44 to +53
const makeProvider = (commitMessageApiConfigId?: string) =>
({
getState: vi.fn().mockResolvedValue({
apiConfiguration,
listApiConfigMeta,
customSupportPrompts: {},
commitMessageApiConfigId,
}),
providerSettingsManager: { getProfile },
}) as unknown as ClineProvider

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.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Replace the undocumented double assertion.

Line 53 uses as unknown as ClineProvider without a nearby reason. Use a typed test-double factory, or document why the structural cast is necessary.

🤖 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 `@src/services/commit-message/__tests__/generateCommitMessage.spec.ts` around
lines 44 - 53, Update the makeProvider test-double factory to avoid the
undocumented `as unknown as ClineProvider` assertion by using a properly typed
factory or an explicit, nearby explanation if the structural cast is required.
Preserve the existing mocked getState and providerSettingsManager behavior.

Source: Coding guidelines

Comment on lines +101 to +104
if (commitMessageApiConfigId && listApiConfigMeta?.find(({ id }) => id === commitMessageApiConfigId)) {
const { name: _, ...providerSettings } = await provider.providerSettingsManager.getProfile({
id: commitMessageApiConfigId,
})

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Handle profile deletion after state retrieval.

A profile can be deleted after getState() returns metadata. getProfile() then throws, and the outer catch reports generation failure instead of falling back to apiConfiguration.

  • src/services/commit-message/index.ts#L101-L104: Catch a getProfile() failure and retain apiConfiguration.
  • src/services/commit-message/__tests__/generateCommitMessage.spec.ts#L102-L110: Make getProfile() reject for a metadata-listed profile. Assert that generation uses apiConfiguration.
📍 Affects 2 files
  • src/services/commit-message/index.ts#L101-L104 (this comment)
  • src/services/commit-message/__tests__/generateCommitMessage.spec.ts#L102-L110
🤖 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 `@src/services/commit-message/index.ts` around lines 101 - 104, Handle
getProfile() failure in the commit-message generation flow around
commitMessageApiConfigId so a deleted metadata-listed profile falls back to
apiConfiguration instead of propagating to the outer generation-error handler.
Update src/services/commit-message/index.ts lines 101-104 accordingly; in
src/services/commit-message/__tests__/generateCommitMessage.spec.ts lines
102-110, make getProfile() reject and assert generation uses apiConfiguration.

Sources: Coding guidelines, Learnings

Comment on lines +423 to +425
for (const command of diffCommands) {
expect(command).not.toMatch(/['"()]/)
}

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.

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

Expand the shell-metacharacter assertion.

The current regex permits command separators and shell expansions such as ;, &, |, `, $, <, and >. A future change can reintroduce an unsafe diff argument while this test still passes.

Proposed fix
- expect(command).not.toMatch(/['"()]/)
+ expect(command).not.toMatch(/['"()|&;<>$`\\\r\n]/)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
for (const command of diffCommands) {
expect(command).not.toMatch(/['"()]/)
}
for (const command of diffCommands) {
expect(command).not.toMatch(/['"()|&;<>$`\\\r\n]/)
}
🧰 Tools
🪛 ast-grep (0.45.1)

[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { ExecException } from "child_process"
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)

🤖 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 `@src/utils/__tests__/git.spec.ts` around lines 423 - 425, Expand the assertion
in the diffCommands loop so the regex rejects shell metacharacters including ;,
&, |, backticks, $, <, and > in addition to the existing quotes and parentheses.
Keep the test focused on validating every command produced by the diff command
construction.

Source: Coding guidelines

Comment on lines +360 to +361
"label": "Model per als missatges de comissió",
"description": "Perfil utilitzat per generar missatges de comissió des del plafó de control de codi font. Normalment n'hi ha prou amb un model petit i ràpid. Deixa-ho sense seleccionar per fer servir el perfil actiu.",

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Correct the Catalan translation for Git commits.

comissió means “commission.” Use commit or confirmació for the Git operation. The current text describes commission messages instead of commit messages.

Proposed fix
-			"label": "Model per als missatges de comissió",
-			"description": "Perfil utilitzat per generar missatges de comissió des del plafó de control de codi font. Normalment n'hi ha prou amb un model petit i ràpid. Deixa-ho sense seleccionar per fer servir el perfil actiu.",
+			"label": "Model per als missatges de commit",
+			"description": "Perfil utilitzat per generar missatges de commit des del plafó de control de codi font. Normalment n'hi ha prou amb un model petit i ràpid. Deixa-ho sense seleccionar per fer servir el perfil actiu.",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"label": "Model per als missatges de comissió",
"description": "Perfil utilitzat per generar missatges de comissió des del plafó de control de codi font. Normalment n'hi ha prou amb un model petit i ràpid. Deixa-ho sense seleccionar per fer servir el perfil actiu.",
"label": "Model per als missatges de commit",
"description": "Perfil utilitzat per generar missatges de commit des del plafó de control de codi font. Normalment n'hi ha prou amb un model petit i ràpid. Deixa-ho sense seleccionar per fer servir el perfil actiu.",
🤖 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 `@webview-ui/src/i18n/locales/ca/settings.json` around lines 360 - 361, Update
the Catalan label and description in the settings locale entry to use “commit”
or “confirmació” for the Git operation instead of “comissió,” while preserving
the existing meaning about generating commit messages and using the active
profile when unselected.

Comment on lines +107 to +110
"COMMIT_MESSAGE": {
"label": "Mensaje de confirmación",
"description": "Resume tus cambios en un mensaje de confirmación. Disponible mediante el icono de Zoo Code en el panel de control de código fuente, que escribe el resultado directamente en el campo del mensaje de confirmación."
},

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use the Git term commit in the Spanish text.

"Mensaje de confirmación" means a confirmation message. Use "Mensaje de commit" in the label and description so the setting matches the Git feature.

🤖 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 `@webview-ui/src/i18n/locales/es/prompts.json` around lines 107 - 110, Update
the COMMIT_MESSAGE localization entry to use the Git term “commit” consistently:
change the label to “Mensaje de commit” and replace the corresponding “mensaje
de confirmación” wording in the description, preserving the rest of the Spanish
text.

@github-actions github-actions Bot added the awaiting-review PR changes are ready and waiting for maintainer re-review label Aug 12, 2026
{t("settings:providers.commitMessageModel.label")}
</label>
<Select
value={commitMessageApiConfigId || USE_CURRENT_CONFIG}

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.

What should the picker display when commitMessageApiConfigId no longer exists in listApiConfigMeta? Can it use the fallback value so Radix always has a matching item to display?

"providers": {
"providerDocumentation": "Documentació de {{provider}}",
"commitMessageModel": {
"label": "Model per als missatges de comissió",

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.

Should this use “missatges de commit” instead of “missatges de comissió”? “Comissió” means “commission,” not the Git operation.

)
})

it("includes the commit message model in the saved settings", async () => {

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.

Would this test be stronger if it selected a different profile before saving? That would cover the complete user-selection → cached-state → updateSettings path rather than only resaving the initial value.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

awaiting-review PR changes are ready and waiting for maintainer re-review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[ENHANCEMENT] Add commit-message API profile settings UI

2 participants