-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Update raycast-ai-custom-providers extension #25180
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
Ernest0-Production
wants to merge
2
commits into
raycast:main
Choose a base branch
from
Ernest0-Production:ext/raycast-ai-custom-providers
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+4,751
−0
Open
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. | ||
|
|
||
| # dependencies | ||
| /node_modules | ||
|
|
||
| # Raycast specific files | ||
| raycast-env.d.ts | ||
| .raycast-swift-build | ||
| .swiftpm | ||
| compiled_raycast_swift | ||
| compiled_raycast_rust | ||
|
|
||
| # misc | ||
| .DS_Store |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| { | ||
| "printWidth": 120, | ||
| "singleQuote": false | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| # Raycast AI Custom Providers Changelog | ||
|
|
||
| ## [Initial Version] - {PR_MERGE_DATE} | ||
|
|
||
| - Initial version |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,133 @@ | ||
| <p align="center"> | ||
| <img width=180 src="./assets/extension-icon.png"> | ||
| </p> | ||
|
|
||
| # Custom Provider (Bring Your Own Models) | ||
|
|
||
| A Raycast extension that allows you to manage custom AI provider settings through a convenient interface. The extension works with the `providers.yaml` file used by Raycast AI to configure external providers (*see documentation [here](https://manual.raycast.com/ai#Custom%20Providers%20(Bring%20Your%20Own%20Models))*). | ||
|
|
||
| ## Features | ||
|
|
||
| - View a list of all configured providers | ||
| - View detailed information about each provider (models, API keys, additional parameters) | ||
| - Edit existing or add new providers and models | ||
|
|
||
| The extension automatically works with the Raycast AI configuration file located at: | ||
| ``` | ||
| ~/.config/raycast/ai/providers.yaml | ||
| ``` | ||
|
|
||
| > For security purposes, a backup copy of the `providers.yaml` file is created before making changes. | ||
|
|
||
| ## providers.yaml Structure | ||
|
|
||
| The `providers.yaml` file has the following structure: | ||
|
|
||
| ```yaml | ||
| providers: | ||
| - id: provider_id # Unique provider identifier (required) | ||
| name: Provider Name # Provider name (required) | ||
| base_url: https://api.example.com # Base API URL (required) | ||
|
|
||
| # API keys (optional) | ||
| # If authentication is required, specify at least one key | ||
| # If individual models require different keys, specify a separate `key` for each model | ||
| api_keys: | ||
| provider_key: ENV_VAR_NAME | ||
|
|
||
| # Additional parameters for `/chat/completions` endpoint (optional) | ||
| additional_parameters: | ||
| param1: value1 | ||
| param2: value2 | ||
|
|
||
| # List of provider models (required, minimum 1 model) | ||
| models: | ||
| - id: model_id # Model identifier used by the provider (required) | ||
| name: Model Name # Model name in Raycast (required) | ||
| provider: provider_key # Mapping to a specific API key (optional) | ||
| description: Model description # Model description (optional) | ||
| context: 128000 # Context window size (required) | ||
|
|
||
| # Model abilities (optional) | ||
| # All properties within abilities are also optional | ||
| abilities: | ||
| temperature: | ||
| supported: true | ||
| vision: | ||
| supported: true | ||
| system_message: | ||
| supported: true | ||
| tools: | ||
| supported: false | ||
| reasoning_effort: | ||
| supported: false | ||
| ``` | ||
|
|
||
| ### Configuration Examples | ||
|
|
||
| #### Simple Provider with One Model | ||
|
|
||
| ```yaml | ||
| providers: | ||
| - id: my_provider | ||
| name: My Provider | ||
| base_url: https://api.example.com | ||
| api_keys: | ||
| default: MY_API_KEY | ||
| models: | ||
| - id: gpt-4 | ||
| name: GPT-4 | ||
| context: 128000 | ||
| abilities: | ||
| temperature: | ||
| supported: true | ||
| vision: | ||
| supported: true | ||
| ``` | ||
|
|
||
| #### Provider with Multiple Models and Different API Keys | ||
|
|
||
| ```yaml | ||
| providers: | ||
| - id: multi_provider | ||
| name: Multi Provider | ||
| base_url: https://api.example.com | ||
| api_keys: | ||
| openai: OPENAI_KEY | ||
| anthropic: ANTHROPIC_KEY | ||
| models: | ||
| - id: gpt-4o | ||
| name: GPT-4o | ||
| provider: openai | ||
| context: 200000 | ||
| - id: claude-sonnet | ||
| name: Claude Sonnet | ||
| provider: anthropic | ||
| context: 200000 | ||
| ``` | ||
|
|
||
| #### Provider Without API Keys | ||
|
|
||
| ```yaml | ||
| providers: | ||
| - id: local_provider | ||
| name: Local Provider | ||
| base_url: http://localhost:4000 | ||
| models: | ||
| - id: local-model | ||
| name: Local Model | ||
| context: 128000 | ||
| ``` | ||
|
|
||
| ## Important Notes | ||
|
|
||
| 1. **API Compatibility**: Since the OpenAI API is not a standard, not all providers may work correctly with Raycast AI. It's recommended to check your provider's documentation. | ||
|
|
||
| 2. **Model Abilities**: If abilities are specified incorrectly, the model may not work correctly in Raycast AI. Always refer to the provider's documentation. | ||
|
|
||
| 3. **YAML Format**: The extension **DOES NOT** preserve comments and formatting where possible, but when manually editing the file, ensure the YAML syntax is correct. | ||
|
|
||
|
|
||
| ## License | ||
|
|
||
| MIT |
91 changes: 91 additions & 0 deletions
91
extensions/raycast-ai-custom-providers/ai-providers.template.yaml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,91 @@ | ||
| providers: | ||
| - id: perplexity | ||
| name: Perplexity | ||
| base_url: https://api.perplexity.ai | ||
| api_keys: | ||
| perplexity: PERPLEXITY_KEY | ||
| additional_parameters: | ||
| return_images: true | ||
| web_search_options: | ||
| search_context_size: medium | ||
| models: | ||
| - id: sonar | ||
| name: Sonar | ||
| provider: perplexity | ||
| description: Perplexity AI model for general-purpose queries | ||
| context: 128000 | ||
| abilities: | ||
| temperature: | ||
| supported: true | ||
| vision: | ||
| supported: true | ||
| system_message: | ||
| supported: true | ||
| tools: | ||
| supported: false | ||
| reasoning_effort: | ||
| supported: false | ||
| - id: sonar-pro | ||
| name: Sonar Pro | ||
| description: Perplexity AI model for complex queries | ||
| context: 200000 | ||
| abilities: | ||
| temperature: | ||
| supported: true | ||
| vision: | ||
| supported: true | ||
| system_message: | ||
| supported: true | ||
| tools: | ||
| supported: false | ||
| reasoning_effort: | ||
| supported: false | ||
| - id: my_provider | ||
| name: My Provider | ||
| base_url: http://localhost:4000 | ||
| api_keys: | ||
| openai: OPENAI_KEY | ||
| anthropic: ANTHROPIC_KEY | ||
| models: | ||
| - id: gpt-4o | ||
| name: GPT-4o | ||
| context: 200000 | ||
| provider: openai | ||
| abilities: | ||
| temperature: | ||
| supported: true | ||
| vision: | ||
| supported: true | ||
| system_message: | ||
| supported: true | ||
| tools: | ||
| supported: true | ||
| - id: claude-sonnet-4 | ||
| name: Claude Sonnet 4 | ||
| context: 200000 | ||
| provider: anthropic | ||
| abilities: | ||
| temperature: | ||
| supported: true | ||
| vision: | ||
| supported: true | ||
| system_message: | ||
| supported: true | ||
| tools: | ||
| supported: true | ||
| - id: litellm | ||
| name: LiteLLM | ||
| base_url: http://localhost:4000 | ||
| models: | ||
| - id: anthropic/claude-sonnet-4-20250514 | ||
| name: Claude Sonnet 4 | ||
| context: 200000 | ||
| abilities: | ||
| temperature: | ||
| supported: true | ||
| vision: | ||
| supported: true | ||
| system_message: | ||
| supported: true | ||
| tools: | ||
| supported: true | ||
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
114 changes: 114 additions & 0 deletions
114
extensions/raycast-ai-custom-providers/cursor/code-style.mdc
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,114 @@ | ||
| --- | ||
Ernest0-Production marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| alwaysApply: true | ||
| --- | ||
|
|
||
| # Cursor Rules for Raycast Extension Development | ||
|
|
||
| ## General Development Principles | ||
|
|
||
| ### Architecture and Data Flow | ||
| - **Commands are entry points**: Each command file in `/src` (e.g., `open-repository.tsx`) is a Raycast entry point. It's responsible for initializing state hooks and rendering the main UI view. | ||
| - **Views for UI**: UI is organized into `View` components (e.g., `BranchesView.tsx`) located in `/src/components/views/`. Commands render these views as the primary interface. | ||
| - **Actions for Operations**: All user operations are implemented as `Action` components in `/src/components/actions/`. They are used within the `ActionPanel` of `View` components. | ||
| - **Context for State Passing**: A shared context (containing state hooks and manager instances) is passed down from the command to all child `View` and `Action` components. This avoids prop drilling. | ||
| - **Hooks for Logic**: All state management and data fetching logic is encapsulated in custom hooks within `/src/hooks/`. | ||
|
|
||
| ### Naming Conventions | ||
| - **Commands**: `kebab-case` (e.g., `open-repository.tsx`) | ||
| - **Components**: `PascalCase` (e.g., `FileActions.tsx`, `BranchesView.tsx`) | ||
| - **Utilities**: `kebab-case` (e.g., `data-manager.ts`) | ||
| - **Hooks**: `camelCase` with a `use` prefix (e.g., `useRepository.ts`) | ||
| - **Types**: `PascalCase` (e.g., `Repository`, `Branch`) | ||
| - **Constants**: `UPPER_SNAKE_CASE` | ||
|
|
||
| ## Raycast API Best Practices | ||
|
|
||
| ### State Management and Data Fetching | ||
| - **Use `useCachedPromise` for Data**: All hooks that fetch data (e.g., `useBranches`, `useStatus`) must use `useCachedPromise` from `@raycast/utils`. The repository path must be part of the dependency array to ensure a separate cache for each repository. | ||
| - **Revalidate Data After Mutations**: After any operation that changes repository state, call the `.revalidate()` function on the relevant data hooks (`branches.revalidate()`, `status.revalidate()`) to refresh the UI. | ||
| - **Use `useCachedState` for UI State**: For simple, persistent UI state (like filters or dropdown selections), use `useCachedState`. | ||
|
|
||
| ### Error Handling and Toast Notifications | ||
| - **Manager Classes Handle Errors**: Manager classes are responsible for catching errors and displaying failure toasts. | ||
| - **Avoid Double Toasts**: `Action` components that call manager classes should not have their own `catch` blocks for showing error toasts, as this would result in duplicate notifications. A `try...catch` block can be used for cleanup or navigation on failure, but should not show a toast for errors already handled by the manager. | ||
| - **Use Streaming Toasts for Long Operations**: For long-running commands, manager classes' `outputHandler` provides real-time feedback using an animated toast that updates with `stdout`. | ||
| - **Use `showFailureToast` for Error Notifications**: Always use `showFailureToast` from `@raycast/utils` instead of `showToast` with `Toast.Style.Failure`. The `showFailureToast` function automatically handles error type casting and message extraction, eliminating the need for manual `error instanceof Error` checks. | ||
| ```ts | ||
| // Bad: Manual error handling with showToast | ||
| showToast({ | ||
| style: Toast.Style.Failure, | ||
| title: "Failed to load data", | ||
| message: error instanceof Error ? error.message : "Unknown error", | ||
| }); | ||
|
|
||
| // Good: Use showFailureToast which handles error casting automatically | ||
| showFailureToast(error, { title: "Failed to load data" }); | ||
| ``` | ||
|
|
||
| ### Icons and UI | ||
| - **Use Both Built-in and Custom Icons**: Use built-in icons from `@raycast/api`'s `Icon` where appropriate. For domain-specific concepts, use custom SVG icons from the `/assets` directory. | ||
| - **Create Semantic Icon Components**: For icons that change based on state (e.g., file status, remote provider), create a dedicated component in `/src/components/icons/` (e.g., `StatusIcons.tsx`) that returns the correct icon. | ||
|
|
||
| ### Confirming Destructive Operations | ||
| - **Use `confirmAlert()` for All Destructive Operations**: Any action that results in data loss or is hard to reverse (e.g., deleting a branch, discarding changes) must be wrapped in `confirmAlert()`. | ||
| - **Use `Alert.ActionStyle.Destructive`**: The primary confirmation button for a destructive action must use the `Destructive` style. | ||
|
|
||
| ### Preferences and Settings | ||
| - **Use `getPreferenceValues()` Directly**: Access user preferences directly via `getPreferenceValues()` from `@raycast/api`. Do not create wrapper utilities or config files. | ||
|
|
||
| ## TypeScript and Typing | ||
|
|
||
| ### JSDoc Comments | ||
| - **Document All Public Types**: All exported interfaces, types, and complex functions must have clear JSDoc comments explaining their purpose, properties, and parameters. This is crucial for maintainability. | ||
|
|
||
| ### Error Handling | ||
| - **Safely Access Error Messages**: Always check `error instanceof Error` before accessing `error.message` to avoid runtime errors. Provide a fallback for unknown error types. | ||
|
|
||
| ### Property Access | ||
| ```ts | ||
| // Bad example: extracts intermediate properties, making the code less clear | ||
| const primaryProvider = modelInfo?.providers?.[0]; | ||
| const inputPrice = primaryProvider?.pricing?.input_per_million; | ||
| text={inputPrice} // Not recommended | ||
|
|
||
| // Good example: uses full inline property access, preferred for clarity and consistency | ||
| text={modelInfo?.providers?.[0]?.pricing?.input_per_million} // Recommended | ||
| ``` | ||
| /* | ||
| Explanation: | ||
| - Bad: Extracting intermediate variables (`primaryProvider`, `inputPrice`) from nested structures makes the data flow less explicit, can lead to code duplication, and hinders maintainability. | ||
| - Good: Inline property access keeps the code concise, explicit, and consistent, even if it means duplicating the access path. | ||
| */ | ||
|
|
||
| ### Inline Computations | ||
|
|
||
| ```ts | ||
| // Bad example: extracting even simple single-line computations or ternaries to variables, which reduces code clarity and increases duplication risk | ||
| const modelName = cachedModel?.name || model.model_name; | ||
| title={modelName} // Not recommended | ||
|
|
||
| const markdown = markdownParts.length > 0 ? markdownParts.join("\n\n") : ""; | ||
| markdown={markdown} // Not recommended | ||
|
|
||
| // Good example: keep all single-line logic (ternary, mapping, arithmetic) inline at use site for clarity and consistent style | ||
| title={cachedModel?.name || model.model_name} // Recommended | ||
| markdown={markdownParts.length > 0 ? markdownParts.join("\n\n") : ""} // Recommended | ||
| ``` | ||
| **Explanation:** | ||
| - **Bad**: Extracting simple one-liners (ternary, mapping, arithmetic) to variables makes the code less transparent, increases cognitive load, and scatters state and logic. | ||
| - **Good**: Always write simple computations inline at the usage site, even if they are duplicated elsewhere. This matches the codebase style and maximizes directness/readability. | ||
|
|
||
| **Exception:** | ||
| If the logic spans multiple lines, involves branching/complex conditional, or inlining would seriously harm readability, then extract it to a variable as an exception. | ||
|
|
||
| ## Performance | ||
| - **Cache Results**: Rely on `useCachedPromise` to cache the results of expensive operations. | ||
|
|
||
| ## What NOT to Do | ||
| - ❌ Do not use emojis instead of built-in or custom SVG icons. | ||
| - ❌ Do not create separate storage managers for frecency data; use `useCachedPromise` or `useCachedState`. | ||
| - ❌ Do not create config files for preferences (use the API). | ||
| - ❌ Do not create `NavigationActions` (they are available in the Raycast API). | ||
| - ❌ Do not use non-English localization in the code; use only English with commonly accepted terminology. | ||
| - ❌ Do not use the following shortcut combinations in Actions: `cmd+enter`, `cmd+k`, `cmd+p`. | ||
| - ❌ Do not assign a shortcut to the first Action in an ActionPanel. | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.