Skip to content

[#1] ✨ - Multiple AI providers#2

Merged
efraespada merged 22 commits into
developfrom
feature/1-multiple-ai-providers
May 24, 2026
Merged

[#1] ✨ - Multiple AI providers#2
efraespada merged 22 commits into
developfrom
feature/1-multiple-ai-providers

Conversation

@efraespada
Copy link
Copy Markdown
Member

@efraespada efraespada commented May 23, 2026

📌 Summary

This PR adds support for multiple AI providers for prompt optimization, separating it from Whisper transcription (which remains exclusively OpenAI). Users can now choose from 8 providers — OpenAI, Anthropic, Google Gemini, Azure OpenAI, Ollama, OpenCode, OpenRouter, and Cursor — each with its own credentials, model selection, and configuration flow. A new configuration webview and setup wizard streamline the multi-provider experience, while the RecordingSessionMode system introduces two distinct recording modes: "transcribe" (raw Whisper output) and "promptimize" (Whisper + optional optimization).


🎯 Related Issues / Tickets


🧩 Scope of Changes

  • Added: 8 provider-specific prompt transformers (OpenAI, Anthropic, Google, Azure, Ollama, OpenCode, OpenRouter, Cursor)
  • Added: PromptTransformerFactory — factory resolving the active provider from configuration
  • Added: ConfigurationPanel — new VS Code webview for unified settings (Whisper key + optimization provider + system prompt)
  • Added: ProviderPricingService — real-time cost comparison via token-costs npm package with static fallback
  • Added: RecordingSessionModetranscribe / promptimize modes with separate start/stop commands
  • Added: ConfigureTransformationProviderCommand, TestTransformationCommand, OpenConfigurationPanelCommand, FirstTimeSetupCommand
  • Added: ConfigurationValidationService — validates both Whisper and optimization setup with user-facing messages
  • Added: RecordingStatusBarItem — enhanced tooltip showing both service statuses
  • Added: ADR-0014 documenting the multi-provider decision
  • Added: __tests__/ — 15+ new test files covering providers, factory, validation, pricing, status bar, and integration
  • Updated: VSCodeConfigRepository — provider-specific settings (API keys via SecretStorage, model per provider)
  • Updated: StartRecordingUseCase / StopRecordingUseCase — split into transcribe-only and promptimize variants
  • Updated: extension.ts — registers all new commands and services
  • Updated: package.json — 8 new commands, new configuration keys, new dependencies (@anthropic-ai/sdk, @google/generative-ai, @cursor/sdk, token-costs, ollama)
  • Updated: README.md and all docs — rebranded to Promptimize with multi-provider guidance
  • Refactored: OpenAIPromptTransformer — simplified to match the new adapter pattern
  • Refactored: RecordingStatusBarItem — two-service status display

🛠️ Technical Details

  • Architecture: Each provider implements the IPromptTransformer port. The PromptTransformerFactory uses a switch on TransformationProvider to instantiate the correct adapter — no dynamic dispatch or reflection.
  • Credentials: Provider API keys are stored in VS Code SecretStorage under promptimize.apiKey.{provider}. This avoids any secrets in settings.json.
  • Pricing: ProviderPricingService fetches live pricing from token-costs (daily cache, 3s timeout) and falls back to static data from src/shared/constants/providerComparison.ts. Only OpenAI, Anthropic, Google, and OpenRouter support live pricing; Ollama, OpenCode, Azure, and Cursor always use static values.
  • Recording modes: Two independent command chains (start/stopTranscribeRecording and start/stopPromptimizeRecording) allow users to bypass optimization entirely or apply it. The status bar tracks which mode is active via RecordingSessionMode.
  • OpenCode & OpenRouter: Both use the OpenAI SDK with a custom baseURL, since their APIs are OpenAI-compatible. Cursor uses the @cursor/sdk with Agent.prompt(). Ollama uses its own REST API directly.
  • Backward compatibility: The old startRecording / stopRecording commands are deprecated but kept for migration. The default provider remains OpenAI, so existing single-provider setups work without changes.

🔍 How to Test

  1. Open the extension in VS Code development mode (F5).
  2. Run Promptimize: Setup Wizard — follow the flow to configure an OpenAI Whisper key.
  3. Run Promptimize: Open Configuration Panel — select a provider (e.g., Anthropic), enter its API key, and pick a model.
  4. Run Promptimize: Test Transformation — verify the selected provider responds correctly.
  5. Run Promptimize: Start Transcribe Recording — record audio, verify raw transcription output.
  6. Run Promptimize: Start Promptimize Recording — verify transcription + optimization output.
  7. Switch providers in the configuration panel and repeat steps 3–6 for at least 3 providers (OpenAI, Ollama local, Anthropic).
  8. Toggle optimization off — verify Promptimize: Start Transcribe Recording still works without a provider configured.

🧪 Test Coverage

  • Unit tests for all 8 prompt transformers (mock HTTP/SDK calls)
  • Unit tests for PromptTransformerFactory
  • Unit tests for ConfigurationValidationService
  • Unit tests for ProviderPricingService
  • Unit tests for TransformationProvider value object
  • Unit tests for RecordingStatusBarItem
  • Integration test for provider switching flow
  • Unit tests for FirstTimeSetupCommand, StartRecordingUseCase

⚠️ Breaking Changes

  • Old promptimize.startRecording / promptimize.stopRecording commands are deprecated (marked in the UI). Users should migrate to the Transcribe or Promptimize variants.
  • Configuration keys changed: promptimize.transformationModel is now scoped per-provider (e.g., promptimize.anthropicModel, promptimize.ollamaModel). The old key is read as fallback for OpenAI.

🚀 Deployment Notes

  • No special deployment steps

🔒 Security Considerations

  • Provider API keys stored in VS Code SecretStorage (encrypted at rest, never in settings.json)
  • No security impact

📈 Performance Impact

  • No performance impact — providers are instantiated lazily and only on optimization requests
  • ProviderPricingService uses a 1-hour cache with 3s timeout to avoid blocking the UI

📝 Notes for Reviewers

The largest files are the configuration webview (ConfigurationPanel.ts + HTML + CSS) and the provider adapters. Focus review on:

  • PromptTransformerFactory.ts:100–125 — exhaustiveness check via never type
  • VSCodeConfigRepository.ts — SecretStorage key management and per-provider setting resolution
  • Provider adapter HTTP error handling (all adapters wrap SDK calls in try/catch producing TransformationError)
  • The RecordingSessionMode state module is intentionally a simple singleton module (not injected) because it lives entirely in the sync presentation layer

✅ Checklist

  • I have self-reviewed my code
  • Code follows project standards and conventions (Clean Architecture, ESLint, Prettier)
  • Tests have been added or updated for all new code
  • Documentation has been updated (README, docs/, ADR-0014, issue templates)
  • No new warnings or lint errors
  • Changes are backward compatible with existing OpenAI-only configurations

…pt transformation

- Updated .eslintrc.js to ignore coverage and test directories.
- Expanded package.json to include new transformation provider commands and configuration options for multiple AI providers (OpenAI, Anthropic, Google Gemini, Azure, and Ollama).
- Enhanced VSCodeConfigRepository to manage settings for different transformation providers and their respective API keys.
- Updated README.md to document new features and configuration options for prompt transformation.
- Refactored transformation logic to support dynamic provider selection via PromptTransformerFactory.
- Updated pnpm-lock.yaml for new dependencies related to additional AI providers.
@docs-page
Copy link
Copy Markdown

docs-page Bot commented May 23, 2026

To view this pull requests documentation preview, visit the following URL:

docs.page/vypdev/cursor-whisper~2

Documentation is deployed and generated using docs.page.

@vypbot vypbot changed the title Feature/1 multiple ai providers [#1] ✨ - Multiple AI providers May 23, 2026
@vypbot vypbot self-requested a review May 23, 2026 05:05
@vypbot vypbot added this to vypdev May 23, 2026
@vypbot vypbot moved this to In Progress in vypdev May 23, 2026
@vypbot vypbot changed the base branch from develop to master May 23, 2026 05:05
@efraespada efraespada linked an issue May 23, 2026 that may be closed by this pull request
1 task
@vypbot vypbot changed the base branch from master to develop May 23, 2026 05:06
@vypbot vypbot added size: XXL Label to indicate a task of size XXL 100% Progress: 100% labels May 23, 2026
@vypbot
Copy link
Copy Markdown
Contributor

vypbot commented May 23, 2026

✨ Feature Actions

  1. The pull request's title was updated from Feature/1 multiple ai providers to [#1] ✨ - Multiple AI providers.
  2. The pull request was assigned to @efraespada (creator).
  3. @vypbot was requested to review the pull request.
  4. The pull request was linked to vypdev and moved to the column In Progress.
  5. The base branch was temporarily updated to master.
  6. The description was temporarily modified to include a reference to issue ✨🧑‍💻 - Multiple AI providers #1.
  7. The base branch was reverted to its original value: develop.
  8. The temporary issue reference ✨🧑‍💻 - Multiple AI providers #1 was removed from the description.
  9. Priority set to P2 in vypdev.

image

Debug log
[DEBUG] Setup done. Issue number: 1, isSingleAction: false, isIssue: false, isPullRequest: true, isPush: false
[DEBUG] ✅ No previous runs active. Continuing...
[INFO] Running PullRequestUseCase for PR #2.
[INFO] 🔀 Executing PullRequestUseCase.
[DEBUG] PR action opened
[DEBUG] PR isOpened true
[DEBUG] PR isMerged false
[DEBUG] PR isClosed false
[INFO] ✏️ Executing UpdateTitleUseCase.
[DEBUG] Issue title updated to: [#1] ✨ - Multiple AI providers
[INFO] 👤 Executing AssignMemberToIssueUseCase.
[DEBUG] #2 needs 1 assignees.
[DEBUG] Assigned PR creator @efraespada to #2.
[INFO] 👀 Executing AssignReviewersToIssueUseCase.
[DEBUG] #2 needs 1 reviewers.
[DEBUG] #2 needs 1 more reviewers.
[DEBUG] Checking team: tatooine
[DEBUG] Members: 2
[DEBUG] Requested size (1) exceeds available members (1). Returning all available members.
[INFO] 🔗 Executing LinkPullRequestProjectUseCase.
[DEBUG] Linked PR_kwDOSlXe6s7ejt-L with id PVTI_lADOA8wRO84Ajh7Bzgtly70 to project PVT_kwDOA8wRO84Ajh7B
[DEBUG] Content ID: PVTI_lADOA8wRO84Ajh7Bzgtly70
[DEBUG] Target field: {
  "id": "PVTSSF_lADOA8wRO84Ajh7Bzgb4L2E",
  "name": "Status",
  "options": [
    {
      "id": "f75ad846",
      "name": "Todo"
    },
    {
      "id": "47fc9ee4",
      "name": "In Progress"
    },
    {
      "id": "98236657",
      "name": "Done"
    }
  ]
}
[DEBUG] Target option: {
  "id": "47fc9ee4",
  "name": "In Progress"
}
[DEBUG] Target field ID: PVTSSF_lADOA8wRO84Ajh7Bzgb4L2E
[DEBUG] Target option ID: 47fc9ee4
[INFO] 🔗 Executing LinkPullRequestIssueUseCase.
[DEBUG] Changed base branch to master
[DEBUG] Updated PR #2 description with: <!--
Thank you for opening a Pull Request 🚀
Please fill out this template as completely as possible.
Clear PRs = faster reviews = better software.
-->

# 📌 Summary
<!--
Briefly explain what this PR does and why it is needed.
Focus on the intent, not the implementation details.
-->

---

## 🎯 Related Issues / Tickets
<!--
Link any related issues, tickets, or discussions.
Use GitHub keywords to auto-close issues when merged.
-->
- Closes #
- Related to #

---

## 🧩 Scope of Changes
<!--
Describe the scope and nature of the changes at a high level.
-->
- Added:
- Updated:
- Removed:
- Refactored:

---

## 🛠️ Technical Details
<!--
Explain important technical decisions, trade-offs, or architecture changes.
Include anything that may not be obvious from reading the code.
-->

---

## 🔍 How to Test
<!--
Provide clear, step-by-step instructions to test this change.
Assume the reviewer is unfamiliar with the context.
-->
1.
2.
3.

---

## 🧪 Test Coverage
<!--
Indicate what types of tests were added or updated.
-->
- [ ] Unit tests
- [ ] Integration tests
- [ ] End-to-end (E2E) tests
- [ ] Manual testing only (explain why)

---

## 📸 Screenshots / Recordings (UI changes only)
<!--
Include before/after screenshots or short videos if this PR affects the UI.
-->

---

## ⚠️ Breaking Changes
<!--
List any breaking changes and required migration steps.
If none, state "None".
-->
- None

---

## 🚀 Deployment Notes
<!--
Anything required or important during deployment:
- environment variables
- database migrations
- feature flags
- deployment order
-->
- [ ] Requires database migration
- [ ] Requires environment variable changes
- [ ] Requires feature flag toggle
- [ ] No special deployment steps

Details:

---

## 🔒 Security Considerations
<!--
Mention any security-related implications or validations.
-->
- [ ] No security impact
- [ ] Input validation changes
- [ ] Authentication / authorization changes
- [ ] Sensitive data handling changes

---

## 📈 Performance Impact
<!--
Describe any performance considerations, improvements, or regressions.
-->
- [ ] No performance impact
- [ ] Improves performance
- [ ] Potential performance regression (explain)

---

## 📝 Notes for Reviewers
<!--
Highlight areas that need special attention or context for reviewers.
-->

---

## ✅ Checklist
<!--
Confirm all items before requesting review.
-->
- [ ] I have self-reviewed my code
- [ ] Code follows project standards and conventions
- [ ] Tests have been added or updated
- [ ] Documentation has been updated (if applicable)
- [ ] No new warnings or lint errors
- [ ] Changes are backward compatible or breaking changes are documented

---

## 📚 Additional Context
<!--
Any extra information that may help reviewers understand this PR.
Links, references, or follow-up work.
-->


Resolves #1
[DEBUG] Changed base branch to develop
[DEBUG] Updated PR #2 description with: <!--
Thank you for opening a Pull Request 🚀
Please fill out this template as completely as possible.
Clear PRs = faster reviews = better software.
-->

# 📌 Summary
<!--
Briefly explain what this PR does and why it is needed.
Focus on the intent, not the implementation details.
-->

---

## 🎯 Related Issues / Tickets
<!--
Link any related issues, tickets, or discussions.
Use GitHub keywords to auto-close issues when merged.
-->
- Closes #
- Related to #

---

## 🧩 Scope of Changes
<!--
Describe the scope and nature of the changes at a high level.
-->
- Added:
- Updated:
- Removed:
- Refactored:

---

## 🛠️ Technical Details
<!--
Explain important technical decisions, trade-offs, or architecture changes.
Include anything that may not be obvious from reading the code.
-->

---

## 🔍 How to Test
<!--
Provide clear, step-by-step instructions to test this change.
Assume the reviewer is unfamiliar with the context.
-->
1.
2.
3.

---

## 🧪 Test Coverage
<!--
Indicate what types of tests were added or updated.
-->
- [ ] Unit tests
- [ ] Integration tests
- [ ] End-to-end (E2E) tests
- [ ] Manual testing only (explain why)

---

## 📸 Screenshots / Recordings (UI changes only)
<!--
Include before/after screenshots or short videos if this PR affects the UI.
-->

---

## ⚠️ Breaking Changes
<!--
List any breaking changes and required migration steps.
If none, state "None".
-->
- None

---

## 🚀 Deployment Notes
<!--
Anything required or important during deployment:
- environment variables
- database migrations
- feature flags
- deployment order
-->
- [ ] Requires database migration
- [ ] Requires environment variable changes
- [ ] Requires feature flag toggle
- [ ] No special deployment steps

Details:

---

## 🔒 Security Considerations
<!--
Mention any security-related implications or validations.
-->
- [ ] No security impact
- [ ] Input validation changes
- [ ] Authentication / authorization changes
- [ ] Sensitive data handling changes

---

## 📈 Performance Impact
<!--
Describe any performance considerations, improvements, or regressions.
-->
- [ ] No performance impact
- [ ] Improves performance
- [ ] Potential performance regression (explain)

---

## 📝 Notes for Reviewers
<!--
Highlight areas that need special attention or context for reviewers.
-->

---

## ✅ Checklist
<!--
Confirm all items before requesting review.
-->
- [ ] I have self-reviewed my code
- [ ] Code follows project standards and conventions
- [ ] Tests have been added or updated
- [ ] Documentation has been updated (if applicable)
- [ ] No new warnings or lint errors
- [ ] Changes are backward compatible or breaking changes are documented

---

## 📚 Additional Context
<!--
Any extra information that may help reviewers understand this PR.
Links, references, or follow-up work.
-->

[INFO] 🔄 Executing SyncSizeAndProgressLabelsFromIssueToPrUseCase.
[DEBUG] Synced size/progress labels from issue #1 to PR #2: size: XXL, 100%
[INFO] 📏 Executing CheckPriorityPullRequestSizeUseCase.
[DEBUG] Priority: priority: low
[DEBUG] Github Priority Label: P2
[DEBUG] Content ID: PVTI_lADOA8wRO84Ajh7Bzgtly70
[DEBUG] Target field: {
  "id": "PVTSSF_lADOA8wRO84Ajh7Bzgb4MPQ",
  "name": "Priority",
  "options": [
    {
      "id": "4af6496f",
      "name": "P0"
    },
    {
      "id": "f87877a5",
      "name": "P1"
    },
    {
      "id": "27f99ddc",
      "name": "P2"
    }
  ]
}
[DEBUG] Target option: {
  "id": "27f99ddc",
  "name": "P2"
}
[DEBUG] Target field ID: PVTSSF_lADOA8wRO84Ajh7Bzgb4MPQ
[DEBUG] Target option ID: 27f99ddc
[INFO] ✏️ Executing UpdatePullRequestDescriptionUseCase (AI PR description).
[DEBUG] PR description will be generated from workspace diff: base "develop", head "feature/1-multiple-ai-providers" (OpenCode agent will run git diff).
[DEBUG] UpdatePullRequestDescription: prompt length=4229, issue description length=835. Calling OpenCode Plan agent.
[INFO] OpenCode request [agent build] model=opencode/deepseek-v4-flash-free promptLength=4229
[INFO] OpenCode sending prompt (full):
You are in the repository workspace. Your task is to produce a pull request description by filling the project's PR template with information from the branch diff and the issue.

**Important – use full project context:** In addition to reading the relevant code (respecting any file ignore patterns specified), read the repository documentation (e.g. README, docs/) and any defined rules or conventions (e.g. .cursor/rules, CONTRIBUTING, project guidelines). This gives you a complete picture of the project and leads to better decisions in both quality of reasoning and efficiency.

**Branches:**
- **Base (target) branch:** `develop`
- **Head (source) branch:** `feature/1-multiple-ai-providers`

**Instructions:**
1. Read the pull request template file: `.github/pull_request_template.md`. Use its structure (headings, bullet lists, separators) as the skeleton for your output. The checkboxes in the template are **indicative only**: you may check the ones that apply based on the project and the diff, define different or fewer checkboxes if that fits better, or omit a section entirely if it does not apply.
2. Get the full diff by running: `git diff develop..feature/1-multiple-ai-providers` (or `git diff develop...feature/1-multiple-ai-providers` for merge-base). Use the diff to understand what changed.
3. Use the issue description below for context and intent.
4. Fill each section of the template with concrete content derived from the diff and the issue. Keep the same markdown structure (headings, horizontal rules). For checkbox sections (e.g. Test Coverage, Deployment Notes, Security): use the template's options as guidance; check or add only the items that apply, or skip the section if it does not apply.
   - **Summary:** brief explanation of what the PR does and why (intent, not implementation details).
   - **Related Issues:** include `Closes #1` and "Related to #" only if relevant.
   - **Scope of Changes:** use Added / Updated / Removed / Refactored with short bullet points (high level, not file-by-file).
   - **Technical Details:** important decisions, trade-offs, or non-obvious aspects.
   - **How to Test:** steps a reviewer can follow (infer from the changes when possible).
   - **Test Coverage / Deployment / Security / Performance / Checklist:** treat checkboxes as indicative; check the ones that apply from the diff and project context, or omit the section if it does not apply.
   - **Breaking Changes:** list any, or "None".
   - **Notes for Reviewers / Additional Context:** fill only if useful; otherwise a short placeholder or omit.
5. Do not output a single compact paragraph. Output the full filled template so the PR description is well-structured and easy to scan. Preserve the template's formatting (headings with # and ##, horizontal rules). Use checkboxes `- [ ]` / `- [x]` only where they add value; you may simplify or drop a section if it does not apply.
6. **Output format:** Return only the filled template content. Do not add any preamble, meta-commentary, or framing phrases (e.g. "Based on my analysis...", "After reviewing the diff...", "Here is the description..."). Start directly with the first heading of the template (e.g. # Summary). Do not wrap the output in code blocks.

**Issue description:**
### Is there an existing issue or feature request for this?

- [x] I have searched the existing issues and feature requests.

### What area does this improvement affect?

None

### What actions does this improvement affect?

_No response_

### Description of the idea or improvement

I want the Visual Studio Code extension to support multiple AI providers for prompt optimization based on the user's input.


### Current limitations or challenges

None

### Expected impact

High productivity with any provider

### Alternatives considered

_No response_

### Version of cursor whisper

_No response_

### Additional context or comments

_No response_

<!-- copilot-configuration-start
{
    "branchType": "feature",
    "workingBranch": "feature/1-multiple-ai-providers",
    "parentBranch": "develop"
}
copilot-configuration-end -->

Output only the filled template content (the PR description body), starting with the first heading. No preamble, no commentary.
[DEBUG] OpenCode prompt (full, no truncation):
You are in the repository workspace. Your task is to produce a pull request description by filling the project's PR template with information from the branch diff and the issue.

**Important – use full project context:** In addition to reading the relevant code (respecting any file ignore patterns specified), read the repository documentation (e.g. README, docs/) and any defined rules or conventions (e.g. .cursor/rules, CONTRIBUTING, project guidelines). This gives you a complete picture of the project and leads to better decisions in both quality of reasoning and efficiency.

**Branches:**
- **Base (target) branch:** `develop`
- **Head (source) branch:** `feature/1-multiple-ai-providers`

**Instructions:**
1. Read the pull request template file: `.github/pull_request_template.md`. Use its structure (headings, bullet lists, separators) as the skeleton for your output. The checkboxes in the template are **indicative only**: you may check the ones that apply based on the project and the diff, define different or fewer checkboxes if that fits better, or omit a section entirely if it does not apply.
2. Get the full diff by running: `git diff develop..feature/1-multiple-ai-providers` (or `git diff develop...feature/1-multiple-ai-providers` for merge-base). Use the diff to understand what changed.
3. Use the issue description below for context and intent.
4. Fill each section of the template with concrete content derived from the diff and the issue. Keep the same markdown structure (headings, horizontal rules). For checkbox sections (e.g. Test Coverage, Deployment Notes, Security): use the template's options as guidance; check or add only the items that apply, or skip the section if it does not apply.
   - **Summary:** brief explanation of what the PR does and why (intent, not implementation details).
   - **Related Issues:** include `Closes #1` and "Related to #" only if relevant.
   - **Scope of Changes:** use Added / Updated / Removed / Refactored with short bullet points (high level, not file-by-file).
   - **Technical Details:** important decisions, trade-offs, or non-obvious aspects.
   - **How to Test:** steps a reviewer can follow (infer from the changes when possible).
   - **Test Coverage / Deployment / Security / Performance / Checklist:** treat checkboxes as indicative; check the ones that apply from the diff and project context, or omit the section if it does not apply.
   - **Breaking Changes:** list any, or "None".
   - **Notes for Reviewers / Additional Context:** fill only if useful; otherwise a short placeholder or omit.
5. Do not output a single compact paragraph. Output the full filled template so the PR description is well-structured and easy to scan. Preserve the template's formatting (headings with # and ##, horizontal rules). Use checkboxes `- [ ]` / `- [x]` only where they add value; you may simplify or drop a section if it does not apply.
6. **Output format:** Return only the filled template content. Do not add any preamble, meta-commentary, or framing phrases (e.g. "Based on my analysis...", "After reviewing the diff...", "Here is the description..."). Start directly with the first heading of the template (e.g. # Summary). Do not wrap the output in code blocks.

**Issue description:**
### Is there an existing issue or feature request for this?

- [x] I have searched the existing issues and feature requests.

### What area does this improvement affect?

None

### What actions does this improvement affect?

_No response_

### Description of the idea or improvement

I want the Visual Studio Code extension to support multiple AI providers for prompt optimization based on the user's input.


### Current limitations or challenges

None

### Expected impact

High productivity with any provider

### Alternatives considered

_No response_

### Version of cursor whisper

_No response_

### Additional context or comments

_No response_

<!-- copilot-configuration-start
{
    "branchType": "feature",
    "workingBranch": "feature/1-multiple-ai-providers",
    "parentBranch": "develop"
}
copilot-configuration-end -->

Output only the filled template content (the PR description body), starting with the first heading. No preamble, no commentary.
[DEBUG] OpenCode message body: agent=build, model=opencode/deepseek-v4-flash-free, parts[0].text length=4229
[DEBUG] OpenCode session create body: {"title":"copilot"}
[DEBUG] OpenCode response [OpenCode session.create] status=200 bodyLength=367. Full body:
{"id":"ses_1acc5c094ffe5L5Jh281XFY7VF","slug":"brave-knight","projectID":"77ef4389ecb7e84212f621acffb099306ca6c110","directory":"/home/runner/work/cursor-whisper/cursor-whisper","path":"","cost":0,"tokens":{"input":0,"output":0,"reasoning":0,"cache":{"read":0,"write":0}},"title":"copilot","version":"1.15.10","time":{"created":1779512786795,"updated":1779512786795}}
[DEBUG] OpenCode POST /session/ses_1acc5c094ffe5L5Jh281XFY7VF/message body (keys): agent, model, parts (1 part(s))
[INFO] OpenCode: waiting for agent "build" message response (client timeout: 15 min)...
[DEBUG] OpenCode response [OpenCode agent "build" message] status=200 bodyLength=7922. Full body:
{"info":{"parentID":"msg_e533a3fba001Z7kDc6c70dyOdw","role":"assistant","mode":"build","agent":"build","path":{"cwd":"/home/runner/work/cursor-whisper/cursor-whisper","root":"/home/runner/work/cursor-whisper/cursor-whisper"},"cost":0,"tokens":{"total":39814,"input":733,"output":1433,"reasoning":16,"cache":{"write":0,"read":37632}},"modelID":"deepseek-v4-flash-free","providerID":"opencode","time":{"created":1779512823650,"completed":1779512837941},"finish":"stop","id":"msg_e533acf62001xuBP89pOA6cy4y","sessionID":"ses_1acc5c094ffe5L5Jh281XFY7VF"},"parts":[{"snapshot":"3d18443b9e247cebc8cf61276e40e14682732e0b","type":"step-start","id":"prt_e533ad290001BqA90yQvGKYXfy","sessionID":"ses_1acc5c094ffe5L5Jh281XFY7VF","messageID":"msg_e533acf62001xuBP89pOA6cy4y"},{"type":"reasoning","text":"Now I have a thorough understanding of everything. Let me compose the PR description.","time":{"start":1779512824801,"end":1779512824981},"id":"prt_e533ad3e1001fcIytYhi17rzLN","sessionID":"ses_1acc5c094ffe5L5Jh281XFY7VF","messageID":"msg_e533acf62001xuBP89pOA6cy4y"},{"type":"text","text":"# 📌 Summary\n\nAdd support for multiple AI providers for prompt transformation after Whisper transcription. Users can now choose from OpenAI (default), Anthropic, Google Gemini, Azure OpenAI, or local Ollama models — each with provider-specific API keys stored in VSCode SecretStorage and dedicated configuration commands.\n\n---\n\n## 🎯 Related Issues / Tickets\n\n- Closes #1\n\n---\n\n## 🧩 Scope of Changes\n\n- **Added:** `TransformationProvider` domain value object with `PROVIDER_METADATA`\n- **Added:** `AnthropicPromptTransformer`, `GooglePromptTransformer`, `AzureOpenAIPromptTransformer`, `OllamaPromptTransformer` — one adapter per provider\n- **Added:** `PromptTransformerFactory` to resolve the active provider from config\n- **Added:** `ConfigurablePromptTransformer` — wrapper that re-resolves provider on each call\n- **Added:** `ConfigureTransformationProviderCommand` — interactive quick-pick wizard for selecting provider, entering API keys, and picking models\n- **Added:** `TestTransformationCommand` — runs a sample transformation and shows side-by-side result in a webview\n- **Added:** `transformationUtils.ts` — shared system prompt, `buildUserPrompt`, `calculateImprovements`, `TransformationError`\n- **Added:** Unit tests for all new transformers, factory, utils, and value object\n- **Added:** Provider documentation (`docs/providers/`) and ADR-0014\n- **Updated:** `IConfigRepository` — added `getProviderApiKey`/`setProviderApiKey`, `anthropicModel`, `googleModel`, `azureEndpoint`, `azureDeployment`, `ollamaBaseUrl`, `ollamaModel` fields\n- **Updated:** `VSCodeConfigRepository` — provider API keys stored per-provider in `SecretStorage`; `updateConfig` handles all string fields generically\n- **Updated:** `OpenAIPromptTransformer` — refactored to use shared utils; removed inline system prompt and improvement heuristics\n- **Updated:** `ConfigureModelCommand` — detects non-OpenAI providers and redirects to provider configuration\n- **Updated:** `package.json` — added `@anthropic-ai/sdk`, `@google/generative-ai`, `axios` dependencies; new commands and configuration properties\n- **Updated:** `extension.ts` — wires `PromptTransformerFactory`, `ConfigurablePromptTransformer`, new commands\n\n---\n\n## 🛠️ Technical Details\n\n- **Factory pattern**: `PromptTransformerFactory.create()` resolves the active `TransformationProvider` from config and instantiates the corresponding adapter. A `ConfigurablePromptTransformer` wrapper re-resolves on every `transform()` call so changing settings takes effect without a reload.\n- **SecretStorage per provider**: Each provider gets its own key in VSCode SecretStorage under `cursor-whisper.apiKey.{provider}`, keeping keys isolated and secure. Ollama requires no key.\n- **Shared logic**: All transformers use the same system prompt (`TRANSFORMATION_SYSTEM_PROMPT`), user prompt builder, and improvement heuristics from `transformationUtils.ts` — ensuring consistent output quality regardless of provider.\n- **Validation**: `validateProvider()` checks the selected provider has the required config before transformation begins; graceful fallback to original transcription text on failure.\n- **Configuration UX**: A new `Configure Transformation Provider` command walks the user through provider selection → optional API key entry → optional model selection, with provider-specific prompts for Azure (endpoint + deployment) and Ollama (base URL).\n\n---\n\n## 🔍 How to Test\n\n1. Open the command palette and run `Cursor Whisper: Configure Transformation Provider`\n2. Select a provider (e.g., Anthropic, Google Gemini, Ollama) and enter the required API key\n3. Run `Cursor Whisper: Test Transformation` to verify the provider responds with a transformed prompt\n4. Switch back to OpenAI and confirm `Cursor Whisper: Configure Model` still works as before\n5. Verify existing recording → transcription → transformation pipeline still works end-to-end\n\n---\n\n## 🧪 Test Coverage\n\n- [x] Unit tests for `TransformationProvider` value object\n- [x] Unit tests for `OpenAIPromptTransformer`\n- [x] Unit tests for `AnthropicPromptTransformer`\n- [x] Unit tests for `GooglePromptTransformer`\n- [x] Unit tests for `AzureOpenAIPromptTransformer`\n- [x] Unit tests for `OllamaPromptTransformer`\n- [x] Unit tests for `PromptTransformerFactory`\n- [x] Unit tests for `transformationUtils`\n\n---\n\n## ⚠️ Breaking Changes\n\n- None. Existing OpenAI-only configs remain fully backward compatible; `transformationProvider` defaults to `openai`.\n\n---\n\n## 🚀 Deployment Notes\n\n- [ ] Requires database migration\n- [ ] Requires environment variable changes\n- [ ] Requires feature flag toggle\n- [x] No special deployment steps\n\n---\n\n## 🔒 Security Considerations\n\n- [x] No security impact\n- [ ] Input validation changes\n- [ ] Authentication / authorization changes\n- [x] Sensitive data handling changes — API keys stored per-provider in VSCode SecretStorage (encrypted at rest by the OS keychain); Ollama (local) requires no key\n\n---\n\n## 📈 Performance Impact\n\n- [ ] No performance impact\n- [ ] Improves performance\n- [x] Potential performance regression (explain) — users on slower local models (Ollama) may experience higher latency vs. cloud OpenAI; provider choice is user-controlled\n\n---\n\n## 📝 Notes for Reviewers\n\n- Ollama connectivity check (`GET /api/tags`) uses a 3-second timeout; the actual `POST /api/generate` has a 120-second timeout for long-running local inference.\n- Azure OpenAI adapter uses `api-version: 2024-02-15-preview` and sends the API key both as Bearer and `api-key` header for compatibility.\n- The `copilot` npm dependency was replaced with `axios` — this is unrelated to the feature but was cleaned up as part of the diff.\n\n---\n\n## ✅ Checklist\n\n- [x] I have self-reviewed my code\n- [x] Code follows project standards and conventions\n- [x] Tests have been added or updated\n- [x] Documentation has been updated (if applicable)\n- [x] No new warnings or lint errors\n- [x] Changes are backward compatible or breaking changes are documented\n\n---\n\n## 📚 Additional Context\n\n- ADR-0014 documents the architectural decision: `docs/adr/0014-multiple-transformation-providers.md`\n- Provider-specific docs: `docs/providers/{openai,anthropic,azure-openai,google-gemini,ollama}.md`","time":{"start":1779512824983,"end":1779512837902},"id":"prt_e533ad4970018dtlRSYsxbBZvR","sessionID":"ses_1acc5c094ffe5L5Jh281XFY7VF","messageID":"msg_e533acf62001xuBP89pOA6cy4y"},{"reason":"stop","snapshot":"3d18443b9e247cebc8cf61276e40e14682732e0b","type":"step-finish","tokens":{"total":39814,"input":733,"output":1433,"reasoning":16,"cache":{"write":0,"read":37632}},"cost":0,"id":"prt_e533b0722001P3iIXSBetlhQfo","sessionID":"ses_1acc5c094ffe5L5Jh281XFY7VF","messageID":"msg_e533acf62001xuBP89pOA6cy4y"}]}
[DEBUG] OpenCode agent "build" message parts: 4 part(s) — [0] type=step-start length=0 | [1] type=reasoning length=85 | [2] type=text length=6209 | [3] type=step-finish length=0
[DEBUG] OpenCode part [1] type=reasoning full text:
Now I have a thorough understanding of everything. Let me compose the PR description.
[DEBUG] OpenCode part [2] type=text full text:
# 📌 Summary

Add support for multiple AI providers for prompt transformation after Whisper transcription. Users can now choose from OpenAI (default), Anthropic, Google Gemini, Azure OpenAI, or local Ollama models — each with provider-specific API keys stored in VSCode SecretStorage and dedicated configuration commands.

---

## 🎯 Related Issues / Tickets

- Closes #1

---

## 🧩 Scope of Changes

- **Added:** `TransformationProvider` domain value object with `PROVIDER_METADATA`
- **Added:** `AnthropicPromptTransformer`, `GooglePromptTransformer`, `AzureOpenAIPromptTransformer`, `OllamaPromptTransformer` — one adapter per provider
- **Added:** `PromptTransformerFactory` to resolve the active provider from config
- **Added:** `ConfigurablePromptTransformer` — wrapper that re-resolves provider on each call
- **Added:** `ConfigureTransformationProviderCommand` — interactive quick-pick wizard for selecting provider, entering API keys, and picking models
- **Added:** `TestTransformationCommand` — runs a sample transformation and shows side-by-side result in a webview
- **Added:** `transformationUtils.ts` — shared system prompt, `buildUserPrompt`, `calculateImprovements`, `TransformationError`
- **Added:** Unit tests for all new transformers, factory, utils, and value object
- **Added:** Provider documentation (`docs/providers/`) and ADR-0014
- **Updated:** `IConfigRepository` — added `getProviderApiKey`/`setProviderApiKey`, `anthropicModel`, `googleModel`, `azureEndpoint`, `azureDeployment`, `ollamaBaseUrl`, `ollamaModel` fields
- **Updated:** `VSCodeConfigRepository` — provider API keys stored per-provider in `SecretStorage`; `updateConfig` handles all string fields generically
- **Updated:** `OpenAIPromptTransformer` — refactored to use shared utils; removed inline system prompt and improvement heuristics
- **Updated:** `ConfigureModelCommand` — detects non-OpenAI providers and redirects to provider configuration
- **Updated:** `package.json` — added `@anthropic-ai/sdk`, `@google/generative-ai`, `axios` dependencies; new commands and configuration properties
- **Updated:** `extension.ts` — wires `PromptTransformerFactory`, `ConfigurablePromptTransformer`, new commands

---

## 🛠️ Technical Details

- **Factory pattern**: `PromptTransformerFactory.create()` resolves the active `TransformationProvider` from config and instantiates the corresponding adapter. A `ConfigurablePromptTransformer` wrapper re-resolves on every `transform()` call so changing settings takes effect without a reload.
- **SecretStorage per provider**: Each provider gets its own key in VSCode SecretStorage under `cursor-whisper.apiKey.{provider}`, keeping keys isolated and secure. Ollama requires no key.
- **Shared logic**: All transformers use the same system prompt (`TRANSFORMATION_SYSTEM_PROMPT`), user prompt builder, and improvement heuristics from `transformationUtils.ts` — ensuring consistent output quality regardless of provider.
- **Validation**: `validateProvider()` checks the selected provider has the required config before transformation begins; graceful fallback to original transcription text on failure.
- **Configuration UX**: A new `Configure Transformation Provider` command walks the user through provider selection → optional API key entry → optional model selection, with provider-specific prompts for Azure (endpoint + deployment) and Ollama (base URL).

---

## 🔍 How to Test

1. Open the command palette and run `Cursor Whisper: Configure Transformation Provider`
2. Select a provider (e.g., Anthropic, Google Gemini, Ollama) and enter the required API key
3. Run `Cursor Whisper: Test Transformation` to verify the provider responds with a transformed prompt
4. Switch back to OpenAI and confirm `Cursor Whisper: Configure Model` still works as before
5. Verify existing recording → transcription → transformation pipeline still works end-to-end

---

## 🧪 Test Coverage

- [x] Unit tests for `TransformationProvider` value object
- [x] Unit tests for `OpenAIPromptTransformer`
- [x] Unit tests for `AnthropicPromptTransformer`
- [x] Unit tests for `GooglePromptTransformer`
- [x] Unit tests for `AzureOpenAIPromptTransformer`
- [x] Unit tests for `OllamaPromptTransformer`
- [x] Unit tests for `PromptTransformerFactory`
- [x] Unit tests for `transformationUtils`

---

## ⚠️ Breaking Changes

- None. Existing OpenAI-only configs remain fully backward compatible; `transformationProvider` defaults to `openai`.

---

## 🚀 Deployment Notes

- [ ] Requires database migration
- [ ] Requires environment variable changes
- [ ] Requires feature flag toggle
- [x] No special deployment steps

---

## 🔒 Security Considerations

- [x] No security impact
- [ ] Input validation changes
- [ ] Authentication / authorization changes
- [x] Sensitive data handling changes — API keys stored per-provider in VSCode SecretStorage (encrypted at rest by the OS keychain); Ollama (local) requires no key

---

## 📈 Performance Impact

- [ ] No performance impact
- [ ] Improves performance
- [x] Potential performance regression (explain) — users on slower local models (Ollama) may experience higher latency vs. cloud OpenAI; provider choice is user-controlled

---

## 📝 Notes for Reviewers

- Ollama connectivity check (`GET /api/tags`) uses a 3-second timeout; the actual `POST /api/generate` has a 120-second timeout for long-running local inference.
- Azure OpenAI adapter uses `api-version: 2024-02-15-preview` and sends the API key both as Bearer and `api-key` header for compatibility.
- The `copilot` npm dependency was replaced with `axios` — this is unrelated to the feature but was cleaned up as part of the diff.

---

## ✅ Checklist

- [x] I have self-reviewed my code
- [x] Code follows project standards and conventions
- [x] Tests have been added or updated
- [x] Documentation has been updated (if applicable)
- [x] No new warnings or lint errors
- [x] Changes are backward compatible or breaking changes are documented

---

## 📚 Additional Context

- ADR-0014 documents the architectural decision: `docs/adr/0014-multiple-transformation-providers.md`
- Provider-specific docs: `docs/providers/{openai,anthropic,azure-openai,google-gemini,ollama}.md`
[INFO] OpenCode response [agent build] responseLength=6209 sessionId=ses_1acc5c094ffe5L5Jh281XFY7VF
[DEBUG] UpdatePullRequestDescription: OpenCode response received. Description length=6209. Full description:
# 📌 Summary

Add support for multiple AI providers for prompt transformation after Whisper transcription. Users can now choose from OpenAI (default), Anthropic, Google Gemini, Azure OpenAI, or local Ollama models — each with provider-specific API keys stored in VSCode SecretStorage and dedicated configuration commands.

---

## 🎯 Related Issues / Tickets

- Closes #1

---

## 🧩 Scope of Changes

- **Added:** `TransformationProvider` domain value object with `PROVIDER_METADATA`
- **Added:** `AnthropicPromptTransformer`, `GooglePromptTransformer`, `AzureOpenAIPromptTransformer`, `OllamaPromptTransformer` — one adapter per provider
- **Added:** `PromptTransformerFactory` to resolve the active provider from config
- **Added:** `ConfigurablePromptTransformer` — wrapper that re-resolves provider on each call
- **Added:** `ConfigureTransformationProviderCommand` — interactive quick-pick wizard for selecting provider, entering API keys, and picking models
- **Added:** `TestTransformationCommand` — runs a sample transformation and shows side-by-side result in a webview
- **Added:** `transformationUtils.ts` — shared system prompt, `buildUserPrompt`, `calculateImprovements`, `TransformationError`
- **Added:** Unit tests for all new transformers, factory, utils, and value object
- **Added:** Provider documentation (`docs/providers/`) and ADR-0014
- **Updated:** `IConfigRepository` — added `getProviderApiKey`/`setProviderApiKey`, `anthropicModel`, `googleModel`, `azureEndpoint`, `azureDeployment`, `ollamaBaseUrl`, `ollamaModel` fields
- **Updated:** `VSCodeConfigRepository` — provider API keys stored per-provider in `SecretStorage`; `updateConfig` handles all string fields generically
- **Updated:** `OpenAIPromptTransformer` — refactored to use shared utils; removed inline system prompt and improvement heuristics
- **Updated:** `ConfigureModelCommand` — detects non-OpenAI providers and redirects to provider configuration
- **Updated:** `package.json` — added `@anthropic-ai/sdk`, `@google/generative-ai`, `axios` dependencies; new commands and configuration properties
- **Updated:** `extension.ts` — wires `PromptTransformerFactory`, `ConfigurablePromptTransformer`, new commands

---

## 🛠️ Technical Details

- **Factory pattern**: `PromptTransformerFactory.create()` resolves the active `TransformationProvider` from config and instantiates the corresponding adapter. A `ConfigurablePromptTransformer` wrapper re-resolves on every `transform()` call so changing settings takes effect without a reload.
- **SecretStorage per provider**: Each provider gets its own key in VSCode SecretStorage under `cursor-whisper.apiKey.{provider}`, keeping keys isolated and secure. Ollama requires no key.
- **Shared logic**: All transformers use the same system prompt (`TRANSFORMATION_SYSTEM_PROMPT`), user prompt builder, and improvement heuristics from `transformationUtils.ts` — ensuring consistent output quality regardless of provider.
- **Validation**: `validateProvider()` checks the selected provider has the required config before transformation begins; graceful fallback to original transcription text on failure.
- **Configuration UX**: A new `Configure Transformation Provider` command walks the user through provider selection → optional API key entry → optional model selection, with provider-specific prompts for Azure (endpoint + deployment) and Ollama (base URL).

---

## 🔍 How to Test

1. Open the command palette and run `Cursor Whisper: Configure Transformation Provider`
2. Select a provider (e.g., Anthropic, Google Gemini, Ollama) and enter the required API key
3. Run `Cursor Whisper: Test Transformation` to verify the provider responds with a transformed prompt
4. Switch back to OpenAI and confirm `Cursor Whisper: Configure Model` still works as before
5. Verify existing recording → transcription → transformation pipeline still works end-to-end

---

## 🧪 Test Coverage

- [x] Unit tests for `TransformationProvider` value object
- [x] Unit tests for `OpenAIPromptTransformer`
- [x] Unit tests for `AnthropicPromptTransformer`
- [x] Unit tests for `GooglePromptTransformer`
- [x] Unit tests for `AzureOpenAIPromptTransformer`
- [x] Unit tests for `OllamaPromptTransformer`
- [x] Unit tests for `PromptTransformerFactory`
- [x] Unit tests for `transformationUtils`

---

## ⚠️ Breaking Changes

- None. Existing OpenAI-only configs remain fully backward compatible; `transformationProvider` defaults to `openai`.

---

## 🚀 Deployment Notes

- [ ] Requires database migration
- [ ] Requires environment variable changes
- [ ] Requires feature flag toggle
- [x] No special deployment steps

---

## 🔒 Security Considerations

- [x] No security impact
- [ ] Input validation changes
- [ ] Authentication / authorization changes
- [x] Sensitive data handling changes — API keys stored per-provider in VSCode SecretStorage (encrypted at rest by the OS keychain); Ollama (local) requires no key

---

## 📈 Performance Impact

- [ ] No performance impact
- [ ] Improves performance
- [x] Potential performance regression (explain) — users on slower local models (Ollama) may experience higher latency vs. cloud OpenAI; provider choice is user-controlled

---

## 📝 Notes for Reviewers

- Ollama connectivity check (`GET /api/tags`) uses a 3-second timeout; the actual `POST /api/generate` has a 120-second timeout for long-running local inference.
- Azure OpenAI adapter uses `api-version: 2024-02-15-preview` and sends the API key both as Bearer and `api-key` header for compatibility.
- The `copilot` npm dependency was replaced with `axios` — this is unrelated to the feature but was cleaned up as part of the diff.

---

## ✅ Checklist

- [x] I have self-reviewed my code
- [x] Code follows project standards and conventions
- [x] Tests have been added or updated
- [x] Documentation has been updated (if applicable)
- [x] No new warnings or lint errors
- [x] Changes are backward compatible or breaking changes are documented

---

## 📚 Additional Context

- ADR-0014 documents the architectural decision: `docs/adr/0014-multiple-transformation-providers.md`
- Provider-specific docs: `docs/providers/{openai,anthropic,azure-openai,google-gemini,ollama}.md`
[DEBUG] Updated PR #2 description with: # 📌 Summary

Add support for multiple AI providers for prompt transformation after Whisper transcription. Users can now choose from OpenAI (default), Anthropic, Google Gemini, Azure OpenAI, or local Ollama models — each with provider-specific API keys stored in VSCode SecretStorage and dedicated configuration commands.

---

## 🎯 Related Issues / Tickets

- Closes #1

---

## 🧩 Scope of Changes

- **Added:** `TransformationProvider` domain value object with `PROVIDER_METADATA`
- **Added:** `AnthropicPromptTransformer`, `GooglePromptTransformer`, `AzureOpenAIPromptTransformer`, `OllamaPromptTransformer` — one adapter per provider
- **Added:** `PromptTransformerFactory` to resolve the active provider from config
- **Added:** `ConfigurablePromptTransformer` — wrapper that re-resolves provider on each call
- **Added:** `ConfigureTransformationProviderCommand` — interactive quick-pick wizard for selecting provider, entering API keys, and picking models
- **Added:** `TestTransformationCommand` — runs a sample transformation and shows side-by-side result in a webview
- **Added:** `transformationUtils.ts` — shared system prompt, `buildUserPrompt`, `calculateImprovements`, `TransformationError`
- **Added:** Unit tests for all new transformers, factory, utils, and value object
- **Added:** Provider documentation (`docs/providers/`) and ADR-0014
- **Updated:** `IConfigRepository` — added `getProviderApiKey`/`setProviderApiKey`, `anthropicModel`, `googleModel`, `azureEndpoint`, `azureDeployment`, `ollamaBaseUrl`, `ollamaModel` fields
- **Updated:** `VSCodeConfigRepository` — provider API keys stored per-provider in `SecretStorage`; `updateConfig` handles all string fields generically
- **Updated:** `OpenAIPromptTransformer` — refactored to use shared utils; removed inline system prompt and improvement heuristics
- **Updated:** `ConfigureModelCommand` — detects non-OpenAI providers and redirects to provider configuration
- **Updated:** `package.json` — added `@anthropic-ai/sdk`, `@google/generative-ai`, `axios` dependencies; new commands and configuration properties
- **Updated:** `extension.ts` — wires `PromptTransformerFactory`, `ConfigurablePromptTransformer`, new commands

---

## 🛠️ Technical Details

- **Factory pattern**: `PromptTransformerFactory.create()` resolves the active `TransformationProvider` from config and instantiates the corresponding adapter. A `ConfigurablePromptTransformer` wrapper re-resolves on every `transform()` call so changing settings takes effect without a reload.
- **SecretStorage per provider**: Each provider gets its own key in VSCode SecretStorage under `cursor-whisper.apiKey.{provider}`, keeping keys isolated and secure. Ollama requires no key.
- **Shared logic**: All transformers use the same system prompt (`TRANSFORMATION_SYSTEM_PROMPT`), user prompt builder, and improvement heuristics from `transformationUtils.ts` — ensuring consistent output quality regardless of provider.
- **Validation**: `validateProvider()` checks the selected provider has the required config before transformation begins; graceful fallback to original transcription text on failure.
- **Configuration UX**: A new `Configure Transformation Provider` command walks the user through provider selection → optional API key entry → optional model selection, with provider-specific prompts for Azure (endpoint + deployment) and Ollama (base URL).

---

## 🔍 How to Test

1. Open the command palette and run `Cursor Whisper: Configure Transformation Provider`
2. Select a provider (e.g., Anthropic, Google Gemini, Ollama) and enter the required API key
3. Run `Cursor Whisper: Test Transformation` to verify the provider responds with a transformed prompt
4. Switch back to OpenAI and confirm `Cursor Whisper: Configure Model` still works as before
5. Verify existing recording → transcription → transformation pipeline still works end-to-end

---

## 🧪 Test Coverage

- [x] Unit tests for `TransformationProvider` value object
- [x] Unit tests for `OpenAIPromptTransformer`
- [x] Unit tests for `AnthropicPromptTransformer`
- [x] Unit tests for `GooglePromptTransformer`
- [x] Unit tests for `AzureOpenAIPromptTransformer`
- [x] Unit tests for `OllamaPromptTransformer`
- [x] Unit tests for `PromptTransformerFactory`
- [x] Unit tests for `transformationUtils`

---

## ⚠️ Breaking Changes

- None. Existing OpenAI-only configs remain fully backward compatible; `transformationProvider` defaults to `openai`.

---

## 🚀 Deployment Notes

- [ ] Requires database migration
- [ ] Requires environment variable changes
- [ ] Requires feature flag toggle
- [x] No special deployment steps

---

## 🔒 Security Considerations

- [x] No security impact
- [ ] Input validation changes
- [ ] Authentication / authorization changes
- [x] Sensitive data handling changes — API keys stored per-provider in VSCode SecretStorage (encrypted at rest by the OS keychain); Ollama (local) requires no key

---

## 📈 Performance Impact

- [ ] No performance impact
- [ ] Improves performance
- [x] Potential performance regression (explain) — users on slower local models (Ollama) may experience higher latency vs. cloud OpenAI; provider choice is user-controlled

---

## 📝 Notes for Reviewers

- Ollama connectivity check (`GET /api/tags`) uses a 3-second timeout; the actual `POST /api/generate` has a 120-second timeout for long-running local inference.
- Azure OpenAI adapter uses `api-version: 2024-02-15-preview` and sends the API key both as Bearer and `api-key` header for compatibility.
- The `copilot` npm dependency was replaced with `axios` — this is unrelated to the feature but was cleaned up as part of the diff.

---

## ✅ Checklist

- [x] I have self-reviewed my code
- [x] Code follows project standards and conventions
- [x] Tests have been added or updated
- [x] Documentation has been updated (if applicable)
- [x] No new warnings or lint errors
- [x] Changes are backward compatible or breaking changes are documented

---

## 📚 Additional Context

- ADR-0014 documents the architectural decision: `docs/adr/0014-multiple-transformation-providers.md`
- Provider-specific docs: `docs/providers/{openai,anthropic,azure-openai,google-gemini,ollama}.md`
[INFO] Main run finished. Results: 12, total steps: 9.
[INFO] Publishing result: 12 result(s), 9 step(s), 0 error(s).
[INFO] 📄 Executing PublishResultUseCase.

🚀 Happy coding!

Made with ❤️ by vypdev/copilot

…vements

- Updated .eslintrc.js to ignore additional test patterns.
- Refactored logging in extension activation for consistency.
- Improved error handling in audio recording classes.
- Enhanced prompt transformation logic with new validation and error handling.
- Updated test cases for Azure and Ollama prompt transformers.
- Adjusted configuration repository to enable prompt transformation by default.
- Streamlined code formatting and structure across various files for better readability.
@vypbot vypbot added 95% Progress: 95% and removed 100% Progress: 100% labels May 23, 2026
Comment thread src/infrastructure/audio/NativeAudioRecorder.ts Outdated
…atus bar updates

- Integrated configuration validation on startup to ensure API key and transformation provider are set correctly.
- Updated StartRecordingUseCase to validate configuration before starting recording.
- Added transformation provider label management in the status bar for better user feedback.
- Improved error handling for missing or invalid configuration during recording.
…nt and error handling

- Enhanced configuration validation during startup to ensure all required settings are correctly configured.
- Updated StartRecordingUseCase to include pre-recording configuration checks.
- Improved status bar feedback with dynamic transformation provider labels.
- Strengthened error handling for scenarios involving missing or invalid configurations during recording.
…improvements

- Introduced a setup wizard for first-time users to configure OpenAI API key and optional prompt optimization provider.
- Updated configuration validation to ensure required settings are completed during startup.
- Improved status bar feedback to indicate setup status and prompt users for incomplete configurations.
- Enhanced command prompts for configuring API keys and transformation providers with clearer messaging.
- Updated documentation to reflect new setup process and configuration options.
…s and enhance user experience

- Replaced the setup wizard command with a direct configuration panel command for improved accessibility.
- Updated configuration validation messages to guide users towards the new configuration panel.
- Enhanced status bar items to reflect the new configuration command, promoting a more intuitive user interface.
- Adjusted test cases to align with the updated command structure and ensure consistent behavior across the extension.
…d configuration validation

- Introduced new commands for starting and stopping transcription and prompt optimization recordings.
- Updated package.json to reflect deprecated recording commands and added new keybindings.
- Enhanced configuration validation to ensure OpenAI API key is set for transcription and prompt optimization.
- Improved status bar feedback to indicate recording modes and configuration requirements.
- Refactored StartRecordingUseCase to handle different recording modes and session management.
- Updated tests to cover new recording functionalities and validation scenarios.
…ates

- Updated settings item text to include 'Settings' for clarity.
- Added command for opening the configuration panel directly from the status bar.
- Implemented logic to display a warning label when the configuration checklist is incomplete.
- Enhanced tests to verify the new setup state behavior and UI updates for the status bar items.
…master' branch; modify button text in configuration panel for clarity
- Added a new configuration option for the transformation system prompt in package.json.
- Updated the ConfigurationPanel to allow users to customize and reset the system prompt.
- Enhanced prompt transformer classes to utilize the configured system prompt.
- Improved tests to validate the new system prompt functionality and ensure correct behavior across different transformers.
- Updated the default system prompt to provide clearer transformation instructions.
…uracy

- Changed markdown description in package.json to link to the Configuration Guide instead of the Provider Guide.
- Revised progress documentation to reflect the current status of automated testing and documentation structure.
- Updated README to clarify provider setup instructions and project status references.
- Removed outdated references to provider setup documentation in quickstart and ADR files.
- Enhanced architecture overview to better describe the system's functionality and integration points.
@vypbot vypbot removed the 95% Progress: 95% label May 24, 2026
@vypbot vypbot added the 100% Progress: 100% label May 24, 2026
await useCase.execute('promptimize');
await vscode.window.showInformationMessage('Recording started');
} catch (error) {
if (error instanceof MissingApiKeyError) {
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.

MissingApiKeyError and ConfigError catch branches are unreachable dead code

Severity: low

Location: src/presentation/commands/StartRecordingCommand.ts:44

The catch block at lines 44-48 handles MissingApiKeyError and ConfigError, but neither is thrown within the try block. validateConfigurationForPromptimize returns a value (does not throw) and useCase.execute() only throws RecordingError. These branches will never execute.
Suggested fix:
Remove the MissingApiKeyError and ConfigError catch branches since they can never be triggered.

Written by vypdev/copilot for commit 51cd340232e0fb179ab054d6111870adfde909f1. This will update automatically on new commits.

…uter providers

- Added OpenCode and OpenRouter as new transformation providers in package.json.
- Updated configuration options to include OpenCode base URL and model identifier.
- Enhanced documentation to reflect the addition of new providers and their setup instructions.
- Improved validation and error handling for OpenCode and OpenRouter configurations.
- Updated tests to cover new provider functionalities and ensure correct behavior across the extension.
…nsion

- Introduced Cursor as a new transformation provider in package.json and updated related configuration options.
- Enhanced documentation to include setup instructions for the Cursor provider and its models.
- Updated validation logic to ensure proper configuration of Cursor API keys and models.
- Added tests to cover the new Cursor provider functionality and ensure correct behavior across the extension.
- Improved user interface elements to facilitate selection and configuration of the Cursor model.
const result = await Agent.prompt(fullPrompt, {
apiKey,
model: { id: model },
local: { cwd: process.cwd() },
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.

CursorPromptTransformer uses process.cwd() which is unreliable in VS Code extension host

Severity: medium

Location: src/infrastructure/transformation/CursorPromptTransformer.ts:59

CursorPromptTransformer.transform() at line 59 passes local: { cwd: process.cwd() } to Agent.prompt(). In a VS Code extension host, process.cwd() often returns the VS Code installation directory (e.g. /usr/share/code) rather than the user's workspace folder. This causes the Cursor SDK to operate relative to the wrong directory, potentially breaking file references and workspace-aware operations.
Suggested fix:
Replace process.cwd() with vscode.workspace.workspaceFolders?.[0]?.uri?.fsPath || process.cwd() to use the actual workspace folder when available, falling back to process.cwd() only when no workspace is open.

Written by vypdev/copilot for commit edd9c47e6addd66b0af2b47ab05fce927aec9e9a. This will update automatically on new commits.


async transform(
transcription: string,
context?: import('../../application/ports/IPromptTransformer').PromptContext
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.

ConfigurablePromptTransformer uses inline dynamic import for type annotation

Severity: low

Location: src/infrastructure/transformation/PromptTransformerFactory.ts:185

ConfigurablePromptTransformer.transform() at line 185 uses import('../../application/ports/IPromptTransformer').PromptContext as a dynamic import expression for a type annotation. This non-standard pattern may confuse bundlers (webpack), IDEs, and type checkers. The type should be imported at the top of the file via a regular import type statement.
Suggested fix:
Add import type { PromptContext } from '../../application/ports/IPromptTransformer' at the top of the file (alongside the existing import { IPromptTransformer } ... on line 2 or as a separate import type), and replace the inline import(...) expression with the simple name PromptContext.

Written by vypdev/copilot for commit edd9c47e6addd66b0af2b47ab05fce927aec9e9a. This will update automatically on new commits.

return { client: this.client, model };
}

const apiKey = new ApiKey(apiKeyStr);
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.

OpenRouterPromptTransformer uses OpenAI-specific ApiKey validation

Severity: high

Location: src/infrastructure/transformation/OpenRouterPromptTransformer.ts:45

OpenRouterPromptTransformer.ensureClient() at line 45 calls new ApiKey(apiKeyStr) which requires the key to start with sk- (OpenAI format). OpenRouter API keys use a different format and prefix, so this throws an uncaught Error('API key must start with sk-') before any transformation can occur, completely blocking OpenRouter provider usage.
Suggested fix:
Remove the ApiKey value object usage from OpenRouterPromptTransformer. The ApiKey class is OpenAI-specific (validates sk- prefix). For OpenRouter, simply validate that the key is non-empty without the sk- prefix check, consistent with how AnthropicPromptTransformer and GooglePromptTransformer handle API keys.

Written by vypdev/copilot for commit edd9c47e6addd66b0af2b47ab05fce927aec9e9a. This will update automatically on new commits.

…configuration

- Refactored status bar item creation to include explicit names for 'transcribe', 'promptimize', and 'settings'.
- Adjusted alignment values for status bar items to ensure consistent positioning.
- Enhanced unit tests to verify the correct creation and configuration of status bar items.
- Updated .vscodeignore to exclude additional test files and documentation from the build.
…oved documentation

- Added a new configuration option for `transcriptionHint` in package.json to allow users to specify optional vocabulary for improved recognition accuracy.
- Updated markdown descriptions for several configuration options to clarify their current status and future implementation plans.
- Revised README and documentation to include details about the new recording modes and updated keyboard shortcuts.
- Enhanced progress documentation to reflect the latest changes in configuration and user experience.
- Improved user interface elements to facilitate better understanding of the new features and settings.
…nhancements

- Added support for the token-costs npm package to fetch real-time provider pricing data.
- Updated ConfigurationPanel to include dynamic provider comparison data based on token-costs.
- Enhanced UI to display real-time pricing updates and fallback static data when necessary.
- Revised provider comparison logic to improve user experience and data accuracy.
- Updated configuration and documentation to reflect the new pricing strategy and architecture.
…s and documentation

- Changed the extension name from Cursor Whisper to Promptimize in package.json and all related files.
- Updated command names and titles to reflect the new branding throughout the extension.
- Revised documentation, including README, quick start guide, and configuration details, to align with the new name.
- Adjusted issue templates to reference Promptimize instead of Cursor Whisper.
- Enhanced user experience by ensuring all references to the old name are replaced for consistency.
- Changed descriptions in hotfix and release issue templates to reference Promptimize instead of Copilot.
- Updated disclaimers to clarify that only members of the Promptimize team can create these issues.
…ports

- Expanded options in bug report, feature request, chore task, and help request templates to cover more specific areas of concern and actions.
- Improved categorization of affected areas and actions to better guide users in reporting issues and requesting features.
- Added new options related to audio recording, transcription, and configuration to align with recent updates in the extension.
@efraespada efraespada merged commit 362c080 into develop May 24, 2026
2 checks passed
@github-project-automation github-project-automation Bot moved this from In Progress to Done in vypdev May 24, 2026
@vypbot
Copy link
Copy Markdown
Contributor

vypbot commented May 24, 2026

✨ Feature Actions

  1. ✨🧑‍💻 - Multiple AI providers #1 was automatically closed after merging this pull request.

image

Debug log
[DEBUG] Setup done. Issue number: 1, isSingleAction: false, isIssue: false, isPullRequest: true, isPush: false
[DEBUG] ⏳ Found 1 previous run(s) still active. Waiting 2s...
[DEBUG] ⏳ Found 1 previous run(s) still active. Waiting 2s...
[DEBUG] ⏳ Found 1 previous run(s) still active. Waiting 2s...
[DEBUG] ⏳ Found 1 previous run(s) still active. Waiting 2s...
[DEBUG] ⏳ Found 1 previous run(s) still active. Waiting 2s...
[DEBUG] ⏳ Found 1 previous run(s) still active. Waiting 2s...
[DEBUG] ⏳ Found 1 previous run(s) still active. Waiting 2s...
[DEBUG] ⏳ Found 1 previous run(s) still active. Waiting 2s...
[DEBUG] ⏳ Found 1 previous run(s) still active. Waiting 2s...
[DEBUG] ⏳ Found 1 previous run(s) still active. Waiting 2s...
[DEBUG] ⏳ Found 1 previous run(s) still active. Waiting 2s...
[DEBUG] ⏳ Found 1 previous run(s) still active. Waiting 2s...
[DEBUG] ⏳ Found 1 previous run(s) still active. Waiting 2s...
[DEBUG] ⏳ Found 1 previous run(s) still active. Waiting 2s...
[DEBUG] ⏳ Found 1 previous run(s) still active. Waiting 2s...
[DEBUG] ⏳ Found 1 previous run(s) still active. Waiting 2s...
[DEBUG] ⏳ Found 1 previous run(s) still active. Waiting 2s...
[DEBUG] ⏳ Found 1 previous run(s) still active. Waiting 2s...
[DEBUG] ⏳ Found 1 previous run(s) still active. Waiting 2s...
[DEBUG] ⏳ Found 1 previous run(s) still active. Waiting 2s...
[DEBUG] ⏳ Found 1 previous run(s) still active. Waiting 2s...
[DEBUG] ✅ No previous runs active. Continuing...
[INFO] Running PullRequestUseCase for PR #2.
[INFO] 🔀 Executing PullRequestUseCase.
[DEBUG] PR action closed
[DEBUG] PR isOpened false
[DEBUG] PR isMerged true
[DEBUG] PR isClosed true
[INFO] ✅ Executing CloseIssueAfterMergingUseCase.
[DEBUG] Issue #1 state: open
[DEBUG] Issue #1 has been closed.
[INFO] Issue #1 closed after merging PR #2.
[DEBUG] Comment added to Issue 1.
[INFO] Main run finished. Results: 1, total steps: 1.
[INFO] Publishing result: 1 result(s), 1 step(s), 0 error(s).
[INFO] 📄 Executing PublishResultUseCase.

🚀 Happy coding!

Made with ❤️ by vypdev/copilot

@vypbot vypbot mentioned this pull request May 24, 2026
1 task
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

100% Progress: 100% size: XXL Label to indicate a task of size XXL

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

✨🧑‍💻 - Multiple AI providers

2 participants