Skip to content

LMStudio followups#44

Merged
hbmartin merged 5 commits intomainfrom
lmstudio-followup
Oct 1, 2025
Merged

LMStudio followups#44
hbmartin merged 5 commits intomainfrom
lmstudio-followup

Conversation

@hbmartin
Copy link
Copy Markdown
Owner

@hbmartin hbmartin commented Oct 1, 2025

PR Type

Enhancement


Description

  • Refactor provider access logic into centralized utility function

  • Add configuration validation and error handling for providers

  • Update LMStudio provider description and add model filtering

  • Bump version to 0.4.0 with dependency updates


Diagram Walkthrough

flowchart LR
  A["Multiple Files"] --> B["getProvidersWithAccess()"]
  B --> C["ModelCatalog"]
  B --> D["useModelsWithConfiguredProvider"]
  E["LMStudioProvider"] --> F["Updated Description"]
  E --> G["Model Filtering"]
  H["Configuration"] --> I["Validation Logic"]
Loading

File Walkthrough

Relevant files
Enhancement
providerCredentials.ts
Add centralized provider access utility                                   

src/lib/catalog/providerCredentials.ts

  • Create new utility function getProvidersWithAccess()
  • Consolidate logic for getting providers with credentials or no
    credential requirements
  • Filter providers to only include those registered in provider registry
+28/-0   
ModelCatalog.ts
Refactor provider logic and add validation                             

src/lib/catalog/ModelCatalog.ts

  • Replace duplicate provider access logic with getProvidersWithAccess()
    calls
  • Add configuration validation with
    assertValidConfigAndRemoveEmptyKeys()
  • Add error handling for invalid configurations and missing fetchModels
    function
  • Improve status management for providers
+27/-15 
useModelsWithConfiguredProvider.ts
Simplify provider access in hook                                                 

src/lib/hooks/useModelsWithConfiguredProvider.ts

  • Replace complex provider filtering logic with getProvidersWithAccess()
    call
  • Remove duplicate code for combining credentialed and non-credentialed
    providers
  • Simplify provider state management
+3/-13   
LmStudioProvider.ts
Update LMStudio provider description and filtering             

src/lib/providers/LmStudioProvider.ts

  • Update provider description to reflect local AI model hosting
  • Add TODO comment about model sorting considerations
  • Filter out embeddings models from model list
+2/-1     
Miscellaneous
useModelCatalog.ts
Clean up refresh function signature                                           

src/lib/hooks/useModelCatalog.ts

  • Remove unused force option from refresh function signature
+1/-1     
Dependencies
package.json
Version bump and dependency updates                                           

package.json

  • Bump version from 0.3.0 to 0.4.0
  • Add @ai-sdk/openai-compatible as optional peer dependency
  • Update various dev dependencies to latest versions
+14/-10 


Important

Refactor provider access logic, add configuration validation, update LMStudio provider, and bump version to 0.4.0 with dependency updates.

  • Provider Access Refactoring:
    • Centralized provider access logic in getProvidersWithAccess() in providerCredentials.ts.
    • Replaced duplicate logic in ModelCatalog.ts and useModelsWithConfiguredProvider.ts with getProvidersWithAccess().
  • Configuration Validation:
    • Added assertValidConfigAndRemoveEmptyKeys() in ModelCatalog.ts for configuration validation.
    • Improved error handling for invalid configurations in ModelCatalog.ts.
  • LMStudio Provider Updates:
    • Updated description in LmStudioProvider.ts to emphasize local AI model hosting.
    • Filtered out embeddings models in LmStudioProvider.ts.
  • Miscellaneous:
    • Removed unused force option from refresh function in useModelCatalog.ts.
    • Bumped version to 0.4.0 and updated dependencies in package.json.

This description was created by Ellipsis for 18823fe. You can customize this summary. It will automatically update as commits are pushed.


Summary by CodeRabbit

  • New Features

    • Access providers that don’t require credentials alongside credentialed ones.
  • Improvements

    • More consistent provider selection for catalog prefetch/refresh and fewer redundant fetches.
    • Simplified refresh action (no extra options) and updated LM Studio description to emphasize local/offline models.
  • Tests

    • Removed a test related to refresh gating behavior.
  • Chores

    • Bump to v0.4.0, dependency updates, and an optional OpenAI-compatible peer dependency.

@sourcery-ai
Copy link
Copy Markdown
Contributor

sourcery-ai Bot commented Oct 1, 2025

Reviewer's Guide

This PR centralizes provider access logic via a new utility, strengthens configuration validation and status handling in the model catalog, streamlines hook provider resolution, refines the LMStudio provider metadata, adjusts hook signatures, and updates the package version along with various dependency bumps.

Class diagram for ModelCatalog and provider access changes

classDiagram
  class ModelCatalog {
    +refresh(providerId)
    +refreshAll()
    +setStatus(providerId, status, message?)
    -providerRegistry
    -providerStorage
    -telemetry
  }
  class providerCredentials {
    +getProvidersWithAccess(providerRegistry, storage)
  }
  ModelCatalog --> providerCredentials : uses
  ModelCatalog --> "IProviderRegistry" : providerRegistry
  ModelCatalog --> "StorageAdapter" : providerStorage
  providerCredentials --> "IProviderRegistry" : providerRegistry
  providerCredentials --> "StorageAdapter" : storage

  class LmStudioProvider {
    +metadata: ProviderMetadata
    +fetchModels(config)
  }
  LmStudioProvider --> "ProviderMetadata" : metadata

  class ProviderMetadata {
    +id
    +name
    +description
    +icon
    +documentationUrl
    +fetchModelListPath
  }

  class useModelsWithConfiguredProvider {
    +setProvidersWithCreds(providers)
  }
  useModelsWithConfiguredProvider --> providerCredentials : uses

  class useModelCatalog {
    +refresh(providerId)
    +refreshAll()
    +addUserModel(providerId, modelId)
    +removeModel(providerId, modelId)
  }
Loading

Class diagram for getProvidersWithAccess utility

classDiagram
  class providerCredentials {
    +getProvidersWithAccess(providerRegistry, storage)
  }
  providerCredentials --> "IProviderRegistry" : providerRegistry
  providerCredentials --> "StorageAdapter" : storage

  class IProviderRegistry {
    +getProvidersNotRequiringCredentials()
    +hasProvider(providerId)
  }

  class StorageAdapter {
    +getProvidersWithCredentials()
  }
Loading

File-Level Changes

Change Details Files
Introduce a shared getProvidersWithAccess utility to unify credentialed and non-credentialed provider resolution
  • Add src/lib/catalog/providerCredentials.ts with getProvidersWithAccess implementation
  • Replace getProvidersWithCredentials usages in ModelCatalog and hooks with getProvidersWithAccess
  • Remove manual merging of credentialed and non-credentialed providers in multiple modules
src/lib/catalog/providerCredentials.ts
src/lib/catalog/ModelCatalog.ts
src/lib/hooks/useModelsWithConfiguredProvider.ts
src/lib/hooks/useModelCatalog.ts
Enhance provider configuration handling and status lifecycle in ModelCatalog.refresh
  • Clone stored config and validate with assertValidConfigAndRemoveEmptyKeys
  • Set status to 'missing-config' on validation errors
  • Short-circuit for providers without fetchModels
src/lib/catalog/ModelCatalog.ts
Simplify useModelsWithConfiguredProvider hook by removing redundant provider tracking
  • Use getProvidersWithAccess to fetch providers
  • Drop manual Set-based merging and separate handling of credential requirements
  • Directly pass providersWithCredentials to setProvidersWithCreds
src/lib/hooks/useModelsWithConfiguredProvider.ts
Adjust useModelCatalog hook signature for refresh
  • Remove optional force parameter from the refresh function signature
src/lib/hooks/useModelCatalog.ts
Update LMStudio provider metadata to reflect local model support
  • Change description to mention local AI model hosting
  • Add a TODO regarding discoveredAt sorting
src/lib/providers/LmStudioProvider.ts
Bump package version and update dependency versions
  • Increment package.json version from 0.3.0 to 0.4.0
  • Add optional @ai-sdk/openai-compatible support
  • Upgrade Storybook addons, Jest DOM, jiti, TypeScript, eslint-plugin-storybook, and other deps
package.json

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Oct 1, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Bumps package to v0.4.0 and adds an optional OpenAI-compatible peer; introduces getProvidersWithAccess and switches catalog/hooks to use it; simplifies hook refresh signature; updates LM Studio provider description; updates dev deps and removes a test case.

Changes

Cohort / File(s) Summary
Versioning & Dependencies
package.json
Version -> 0.4.0; adds optional peer @ai-sdk/openai-compatible in peerDependencies & peerDependenciesMeta; bumps Storybook, TypeScript, jest-dom, jiti, and other dev deps.
Provider Access Helper
src/lib/catalog/providerCredentials.ts
Adds getProvidersWithAccess(providerRegistry, storage): Promise<ProviderId[]> that unions credentialed provider IDs from storage with providers not requiring credentials from the registry, dedupes, and validates presence in registry.
Catalog Init / Refresh / Prefetch
src/lib/catalog/ModelCatalog.ts
Replaces getProvidersWithCredentials calls with getProvidersWithAccess(...) in init, prefetch, refresh and bulk-refresh; uses registry/providerStorage combo to determine providers to act on; minor whitespace/config validation placement adjusted.
Hooks: API & Access Changes
src/lib/hooks/useModelCatalog.ts, src/lib/hooks/useModelsWithConfiguredProvider.ts
refresh signature simplified to refresh(providerId): Promise<void> (removed optional opts); both hooks switched to use getProvidersWithAccess(providerRegistry, storage) instead of repo-level getProvidersWithCredentials; provider list derivation simplified.
Provider Metadata
src/lib/providers/LmStudioProvider.ts
Provider description updated to reference local/offline models (gpt-oss, Qwen, Gemma, DeepSeek); TODO added about discoveredAt sorting.
Tests
tests/catalog.modelCatalog.test.ts
Removed import addProviderWithCredentials and removed a test case that expected refresh gating on invalid config.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant UI
  participant Hook as useModelCatalog / useModelsWithConfiguredProvider
  participant Catalog as ModelCatalog
  participant Helper as getProvidersWithAccess
  participant Registry as ProviderRegistry
  participant Storage as ProviderStorage
  participant Provider as Provider

  UI->>Hook: init / refresh(providerId)
  Hook->>Catalog: init() / refresh(providerId)
  Catalog->>Helper: getProvidersWithAccess(Registry, Storage)
  Helper->>Storage: getProvidersWithCredentials()
  Storage-->>Helper: [credentialedIds]
  Helper->>Registry: getProvidersNotRequiringCredentials()
  Registry-->>Helper: [no-cred provider ids]
  Helper-->>Catalog: [deduped, validated provider ids]
  Catalog->>Registry: get provider by id
  Catalog->>Provider: provider.configuration.assertValidConfigAndRemoveEmptyKeys(config)
  alt invalid config
    Catalog-->>Hook: status = missing-config
    Hook-->>UI: update state
  else valid config
    alt provider lacks fetchModels
      Catalog-->>Hook: set ready (skip fetch)
    else has fetchModels
      Catalog->>Provider: fetchModels(validatedConfig)
      Provider-->>Catalog: models
      Catalog-->>Hook: update state with models
    end
    Hook-->>UI: update state
  end
Loading
sequenceDiagram
  autonumber
  participant Catalog as ModelCatalog
  participant Helper as getProvidersWithAccess
  participant Storage as ProviderStorage
  participant Registry as ProviderRegistry

  Catalog->>Helper: getProvidersWithAccess(Registry, Storage)
  Helper->>Storage: getProvidersWithCredentials()
  Storage-->>Helper: [credentialedIds]
  Helper->>Registry: getProvidersNotRequiringCredentials()
  Registry-->>Helper: [no-cred ids]
  Helper->>Helper: dedupe & filter by Registry.hasProvider
  Helper-->>Catalog: [accessible provider ids]
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

I hop through configs, checking keys and tracks,
Union creds and open doors, then tidy up the racks.
If fetch is missing, I gently skip the race,
I swap helpers, trim the args, and keep a careful pace.
From 0.3 to 0.4 — I nibble bugs and leave no trace. 🐇✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The title “LMStudio followups” accurately refers to the updates made to the LMStudio provider, which is one genuine aspect of this changeset, but it does not capture the broader refactoring of provider access, configuration validation, and version bump included in the PR. Despite its narrow focus, it remains a concise and real reference to the PR’s content, so it meets the criteria for a partially related title.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch lmstudio-followup

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 and usage tips.

@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello @hbmartin, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request primarily focuses on improving the maintainability and robustness of the model catalog by refactoring how accessible providers are determined and enhancing the LMStudio provider with better configuration handling. It also includes a routine update of project dependencies to their latest versions, ensuring compatibility and leveraging recent improvements.

Highlights

  • Core Logic Refactoring: Introduced a new utility function 'getProvidersWithAccess' to centralize the logic for identifying model providers that are accessible, streamlining model catalog management.
  • LMStudio Provider Enhancements: Updated the LMStudio provider's description for clarity and added a robust configuration validation step to ensure valid settings before attempting to fetch models.
  • Dependency Updates: Bumped the package version to '0.4.0' and updated numerous development dependencies, including Storybook, testing libraries, TypeScript, and various '@smithy' packages, along with adding '@ai-sdk/openai-compatible'.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@qodo-code-review
Copy link
Copy Markdown

qodo-code-review Bot commented Oct 1, 2025

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
🟢
No security concerns identified No security vulnerabilities detected by AI analysis. Human verification advised for critical code.
Ticket Compliance
🎫 No ticket provided
  • Create ticket/issue
Codebase Duplication Compliance
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
No custom compliance provided

Follow the guide to enable custom compliance check.

  • Update
Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
⚪ - Requires Further Human Verification
🏷️ - Compliance label

@socket-security
Copy link
Copy Markdown

socket-security Bot commented Oct 1, 2025

Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey there - I've reviewed your changes and they look great!

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location> `src/lib/catalog/ModelCatalog.ts:333` </location>
<code_context>
     const run = (async () => {
       try {
-        const config = await getProviderConfiguration(this.providerStorage, providerId);
+        const storedConfig = await getProviderConfiguration(this.providerStorage, providerId);
+        const config = storedConfig === undefined ? undefined : { ...storedConfig };
+
</code_context>

<issue_to_address>
**issue (complexity):** Consider extracting the configuration loading and validation logic into a helper with guard-clauses to simplify and flatten the refresh method.

```typescript
// Extract and flatten your “load‐and‐validate” logic into a helper with guard‐clauses,
// then call it at the top of refresh(). This removes the inner try/catch,
// the extra nesting, and centralizes validation in one place.

private async getValidatedConfig(providerId: ProviderId): Promise<ModelConfig | null> {
  // 1) load
  const stored = await getProviderConfiguration(this.providerStorage, providerId);
  if (!stored) {
    this.setStatus(providerId, 'missing-config', 'No configuration found');
    return null;
  }

  // 2) validate (assertValidConfig may remove empty keys in place)
  try {
    provider.configuration.assertValidConfigAndRemoveEmptyKeys(stored);
    return stored;
  } catch (err) {
    const msg = err instanceof Error ? err.message : String(err);
    this.setStatus(providerId, 'missing-config', msg);
    return null;
  }
}

// then in refresh():
const provider = this.providerRegistry.getProvider(providerId);

// LOAD & VALIDATE or early‐return
const config = await this.getValidatedConfig(providerId);
if (!config) return;

// type‐check guard
if (typeof provider.fetchModels !== 'function') {
  this.setStatus(providerId, 'ready');
  return;
}

// now the happy path only
this.setStatus(providerId, 'refreshing');
this.telemetry?.onFetchStart?.(providerId);
const models = await provider.fetchModels(config);
// …rest of your merge/persist logic…
```

Benefits:
- single helper for config load + validation
- no inner try/catch in refresh
- flat guard‐clauses at top
- preserves existing functionality and early‐returns
</issue_to_address>

### Comment 2
<location> `src/lib/catalog/providerCredentials.ts:15` </location>
<code_context>
+
+  const allProviders = new Set<ProviderId>();
+
+  for (const providerId of credentialedProviders) {
+    if (providerRegistry.hasProvider(providerId)) {
+      allProviders.add(providerId);
</code_context>

<issue_to_address>
**issue (complexity):** Consider merging the two loops into a single chained operation to simplify the function.

```suggestion
// You can collapse the two loops into a single chained operation,
// reducing boilerplate while preserving order & uniqueness.
export async function getProvidersWithAccess(
  providerRegistry: IProviderRegistry,
  storage: StorageAdapter
): Promise<ProviderId[]> {
  const credentialed = await getProvidersWithCredentials(storage);
  const noCredIds = providerRegistry
    .getProvidersNotRequiringCredentials()
    .map(({ metadata: { id } }) => id);

  return [
    ...new Set([
      ...credentialed,
      ...noCredIds
    ])
  ].filter(id => providerRegistry.hasProvider(id));
}
```

Steps:
1. Await credentialed IDs.
2. Map providers-no-creds to their `id`.
3. Merge both arrays into a `Set` to dedupe.
4. Filter out any IDs not in the registry.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread src/lib/catalog/ModelCatalog.ts Outdated
const run = (async () => {
try {
const config = await getProviderConfiguration(this.providerStorage, providerId);
const storedConfig = await getProviderConfiguration(this.providerStorage, providerId);
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.

issue (complexity): Consider extracting the configuration loading and validation logic into a helper with guard-clauses to simplify and flatten the refresh method.

// Extract and flatten your “load‐and‐validate” logic into a helper with guard‐clauses,
// then call it at the top of refresh(). This removes the inner try/catch,
// the extra nesting, and centralizes validation in one place.

private async getValidatedConfig(providerId: ProviderId): Promise<ModelConfig | null> {
  // 1) load
  const stored = await getProviderConfiguration(this.providerStorage, providerId);
  if (!stored) {
    this.setStatus(providerId, 'missing-config', 'No configuration found');
    return null;
  }

  // 2) validate (assertValidConfig may remove empty keys in place)
  try {
    provider.configuration.assertValidConfigAndRemoveEmptyKeys(stored);
    return stored;
  } catch (err) {
    const msg = err instanceof Error ? err.message : String(err);
    this.setStatus(providerId, 'missing-config', msg);
    return null;
  }
}

// then in refresh():
const provider = this.providerRegistry.getProvider(providerId);

// LOAD & VALIDATE or early‐return
const config = await this.getValidatedConfig(providerId);
if (!config) return;

// type‐check guard
if (typeof provider.fetchModels !== 'function') {
  this.setStatus(providerId, 'ready');
  return;
}

// now the happy path only
this.setStatus(providerId, 'refreshing');
this.telemetry?.onFetchStart?.(providerId);
const models = await provider.fetchModels(config);
// …rest of your merge/persist logic…

Benefits:

  • single helper for config load + validation
  • no inner try/catch in refresh
  • flat guard‐clauses at top
  • preserves existing functionality and early‐returns

Comment thread src/lib/catalog/providerCredentials.ts Outdated
@qodo-code-review
Copy link
Copy Markdown

qodo-code-review Bot commented Oct 1, 2025

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
Possible issue
Correct invalid semver version range
Suggestion Impact:The invalid range ">-1.0.0" was corrected to a valid semver range, changed to ">=1.0.0" (slightly different from the suggested "^1.0.0" but achieving the goal of validity).

code diff:

-    "@ai-sdk/openai-compatible": ">-1.0.0",
+    "@ai-sdk/openai-compatible": ">=1.0.0",

Correct the invalid semver range >-1.0.0 for the @ai-sdk/openai-compatible peer
dependency to a valid one, such as ^1.0.0.

package.json [96]

-"@ai-sdk/openai-compatible": ">-1.0.0",
+"@ai-sdk/openai-compatible": "^1.0.0",

[Suggestion processed]

Suggestion importance[1-10]: 8

__

Why: The suggestion correctly identifies that >-1.0.0 is an invalid semver range, which could cause dependency resolution issues for consumers of this package, making this a significant correctness fix.

Medium
General
Simplify provider gathering logic
Suggestion Impact:The commit refactored the logic to combine credentialed and non-credentialed providers into a single Set and filtered by registry presence, effectively removing redundant looping and checks as suggested, though using a different implementation.

code diff:

+// You can collapse the two loops into a single chained operation,
+// reducing boilerplate while preserving order & uniqueness.
+export async function getProvidersWithAccess(
+  providerRegistry: IProviderRegistry,
+  storage: StorageAdapter
+): Promise<ProviderId[]> {
+  const credentialed = await getProvidersWithCredentials(storage);
+  const noCredIds = providerRegistry
+    .getProvidersNotRequiringCredentials()
+    .map(({ metadata: { id } }) => id);
+
+  return [
+    ...new Set([
+      ...credentialed,
+      ...noCredIds
+    ])
+  ].filter(id => providerRegistry.hasProvider(id));
+}

Simplify the logic for populating allProviders by removing a redundant loop and
check, as providersNotRequiringCredentials are already guaranteed to be in the
providerRegistry.

src/lib/catalog/providerCredentials.ts [13-25]

-const allProviders = new Set<ProviderId>();
+const allProviders = new Set<ProviderId>(providersNotRequiringCredentials);
 
 for (const providerId of credentialedProviders) {
   if (providerRegistry.hasProvider(providerId)) {
     allProviders.add(providerId);
   }
 }
 
-for (const providerId of providersNotRequiringCredentials) {
-  if (providerRegistry.hasProvider(providerId)) {
-    allProviders.add(providerId);
-  }
-}
-

[Suggestion processed]

Suggestion importance[1-10]: 4

__

Why: The suggestion correctly identifies a redundant check and proposes a more concise and efficient way to populate the Set, improving code readability and removing unnecessary logic.

Low
Remove unnecessary object shallow copy
Suggestion Impact:The commit removed the shallow copy and directly assigned the result of getProviderConfiguration to config. Although it also refactored surrounding logic, it aligns with the suggestion’s intent to avoid the redundant spread.

code diff:

-        const storedConfig = await getProviderConfiguration(this.providerStorage, providerId);
-        const config = storedConfig === undefined ? undefined : { ...storedConfig };
-
-        try {
-          provider.configuration.assertValidConfigAndRemoveEmptyKeys(config);
-        } catch (validationError) {
-          const message =
-            validationError instanceof Error ? validationError.message : String(validationError);
-          this.setStatus(providerId, 'missing-config', message);
-          return;
-        }
-
-        if (typeof provider.fetchModels !== 'function') {
-          this.setStatus(providerId, 'ready');
-          return;
-        }
+        const config = await getProviderConfiguration(this.providerStorage, providerId);

Remove the unnecessary shallow copy of storedConfig before passing it to
assertValidConfigAndRemoveEmptyKeys, as the object is not referenced elsewhere.

src/lib/catalog/ModelCatalog.ts [334]

-const config = storedConfig === undefined ? undefined : { ...storedConfig };
+const config = storedConfig;

[Suggestion processed]

Suggestion importance[1-10]: 3

__

Why: The suggestion correctly identifies a redundant shallow copy. While the performance impact is negligible, removing it simplifies the code, as the object is not used elsewhere after being mutated.

Low
  • Update

Copy link
Copy Markdown
Contributor

@ellipsis-dev ellipsis-dev Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Changes requested ❌

Reviewed everything up to e477c34 in 1 minute and 43 seconds. Click for details.
  • Reviewed 258 lines of code in 6 files
  • Skipped 1 files when reviewing.
  • Skipped posting 3 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. src/lib/hooks/useModelsWithConfiguredProvider.ts:76
  • Draft comment:
    The deleteProvider function uses 'modelsWithCredentials' which is declared later via useMemo. Although closure will capture the latest value at invocation, reordering or adding a comment might improve clarity.
  • Reason this comment was not posted:
    Comment was not on a location in the diff, so it can't be submitted as a review comment.
2. package.json:96
  • Draft comment:
    There appears to be a typographical error in the version specification for '@ai-sdk/openai-compatible'. The version string ">-1.0.0" seems off; did you mean to write ">=1.0.0" instead?
  • Reason this comment was not posted:
    Marked as duplicate.
3. src/lib/providers/LmStudioProvider.ts:127
  • Draft comment:
    Typo in comment: consider changing 'effects' to 'affects' in order to improve clarity.
  • Reason this comment was not posted:
    Decided after close inspection that this draft comment was likely wrong and/or not actionable: usefulness confidence = 10% vs. threshold = 50% While the correction is technically accurate, this is a minor grammatical issue in a TODO comment. TODOs are typically informal internal notes. The meaning is still clear despite the grammatical error. This kind of nitpick doesn't affect code functionality and isn't the kind of substantial feedback we want to focus on in code reviews. The grammatical correction is accurate and could improve code quality. Some teams do value maintaining high standards even in comments. However, this level of nitpicking on informal TODO comments creates noise in the review process and distracts from more important issues. The meaning is clear despite the error. This comment should be deleted as it's too minor and focuses on a grammatical issue in an informal TODO comment rather than substantive code issues.

Workflow ID: wflow_OLoC101Jt5jymZJO

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.

Comment thread package.json Outdated
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces several valuable enhancements. The refactoring of provider access logic into a centralized getProvidersWithAccess utility is a great improvement for code clarity and maintainability. The added configuration validation and error handling in ModelCatalog significantly increase the robustness of the provider management. The updates to the LMStudio provider and dependency bumps are also welcome changes. I've identified a couple of minor areas for improvement.

Comment thread package.json Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
src/lib/providers/LmStudioProvider.ts (1)

127-127: Consider sorting implications of discoveredAt.

The TODO correctly flags a consideration: models fetched at different times will have different discoveredAt timestamps, which may affect display order if sorting is timestamp-based.

If you'd like to track this, I can help you implement a sorting strategy or open an issue to address it later.

src/lib/catalog/providerCredentials.ts (1)

15-19: Consider consolidating the two loops.

The two loops have identical structure and could be combined for better maintainability.

Apply this diff to consolidate:

-  const allProviders = new Set<ProviderId>();
-
-  for (const providerId of credentialedProviders) {
-    if (providerRegistry.hasProvider(providerId)) {
-      allProviders.add(providerId);
-    }
-  }
-
-  for (const providerId of providersNotRequiringCredentials) {
-    if (providerRegistry.hasProvider(providerId)) {
-      allProviders.add(providerId);
-    }
-  }
+  const allProviders = new Set<ProviderId>(
+    [...credentialedProviders, ...providersNotRequiringCredentials]
+      .filter((providerId) => providerRegistry.hasProvider(providerId))
+  );

Also applies to: 21-25

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 505b840 and e477c34.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (6)
  • package.json (5 hunks)
  • src/lib/catalog/ModelCatalog.ts (4 hunks)
  • src/lib/catalog/providerCredentials.ts (1 hunks)
  • src/lib/hooks/useModelCatalog.ts (1 hunks)
  • src/lib/hooks/useModelsWithConfiguredProvider.ts (2 hunks)
  • src/lib/providers/LmStudioProvider.ts (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (4)
src/lib/hooks/useModelCatalog.ts (3)
src/lib/providers/index.ts (1)
  • ProviderId (24-24)
src/lib/types/index.ts (1)
  • ProviderId (8-8)
src/lib/index.ts (1)
  • ProviderId (58-58)
src/lib/catalog/providerCredentials.ts (1)
src/lib/storage/repository.ts (1)
  • getProvidersWithCredentials (75-79)
src/lib/hooks/useModelsWithConfiguredProvider.ts (1)
src/lib/catalog/providerCredentials.ts (1)
  • getProvidersWithAccess (4-28)
src/lib/catalog/ModelCatalog.ts (2)
src/lib/catalog/providerCredentials.ts (1)
  • getProvidersWithAccess (4-28)
src/lib/storage/repository.ts (1)
  • getProviderConfiguration (120-125)
🪛 GitHub Actions: CI
src/lib/catalog/ModelCatalog.ts

[error] 337-337: TS2775: Assertions require every name in the call target to be declared with an explicit type annotation.

🪛 GitHub Check: Check AI SDK Compatibility
src/lib/catalog/ModelCatalog.ts

[failure] 337-337:
Assertions require every name in the call target to be declared with an explicit type annotation.

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Sourcery review
🔇 Additional comments (9)
package.json (2)

109-111: LGTM after fixing the version range.

Correctly declares the new peer dependency as optional, which aligns with the dynamic import pattern used in LmStudioProvider.


4-4: Version bump to 0.4.0 is appropriate.

The minor version bump correctly reflects the new features and refactors in this PR.

src/lib/providers/LmStudioProvider.ts (1)

78-78: Accurate description for local AI models.

The updated description correctly reflects that LM Studio hosts models locally rather than using OpenAI's cloud services.

src/lib/hooks/useModelCatalog.ts (2)

38-38: Implementation correctly matches simplified signature.

The memoized action now correctly delegates to catalog.refresh(providerId) without forwarding options.


13-13: Verified no internal refresh calls with two arguments
Ripgrep searches found no instances of refresh(providerId, {…}). Ensure no external consumers rely on the removed opts parameter.

src/lib/hooks/useModelsWithConfiguredProvider.ts (1)

11-11: Correctly migrated to getProvidersWithAccess.

The refactor properly replaces the credentials-only check with the broader access check, which accounts for both credentialed providers and those not requiring credentials. This aligns with the new pattern established in providerCredentials.ts.

Also applies to: 127-130

src/lib/catalog/providerCredentials.ts (1)

4-28: Well-structured provider access computation.

The function correctly computes the union of:

  1. Providers with stored credentials (that exist in the registry)
  2. Providers not requiring credentials (that exist in the registry)

The hasProvider validation prevents stale provider IDs from being included, and the Set ensures deduplication.

src/lib/catalog/ModelCatalog.ts (2)

200-203: LGTM!

The refactor to use getProvidersWithAccess correctly consolidates the logic for determining which providers should be prefetched.


383-386: LGTM!

The refactor correctly applies getProvidersWithAccess to determine which providers should be bulk-refreshed.

Comment thread package.json Outdated
Comment thread src/lib/catalog/ModelCatalog.ts Outdated
hbmartin and others added 2 commits October 1, 2025 08:24
Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e477c34 and 2854779.

📒 Files selected for processing (1)
  • src/lib/catalog/providerCredentials.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/lib/catalog/providerCredentials.ts (1)
src/lib/storage/repository.ts (1)
  • getProvidersWithCredentials (75-79)
🪛 Biome (2.1.2)
src/lib/catalog/providerCredentials.ts

[error] 16-32: Illegal use of an export declaration not at the top level

move this declaration to the top level

(parse)


[error] 44-44: Illegal return statement outside of a function

(parse)


[error] 44-45: Expected a statement but instead found '}'.

Expected a statement here.

(parse)

🪛 GitHub Actions: CI
src/lib/catalog/providerCredentials.ts

[error] 45-45: Declaration or statement expected. parseForESLint from parser @typescript-eslint/parser is invalid and will just be ignored.

🪛 GitHub Check: Check AI SDK Compatibility
src/lib/catalog/providerCredentials.ts

[failure] 45-45:
Declaration or statement expected.

Comment thread src/lib/catalog/providerCredentials.ts Outdated
Copy link
Copy Markdown
Contributor

@ellipsis-dev ellipsis-dev Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Important

Looks good to me! 👍

Reviewed 4019736 in 1 minute and 2 seconds. Click for details.
  • Reviewed 92 lines of code in 3 files
  • Skipped 0 files when reviewing.
  • Skipped posting 3 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. package.json:93
  • Draft comment:
    Version spec for @ai-sdk/openai-compatible updated from ">-1.0.0" to ">=1.0.0". This looks like a typo fix; please confirm the new spec meets compatibility requirements.
  • Reason this comment was not posted:
    Confidence changes required: 0% <= threshold 50% None
2. src/lib/catalog/ModelCatalog.ts:332
  • Draft comment:
    Removed explicit config validation and fetchModels check. Ensure that providers with missing/invalid configs or absent fetchModels are handled appropriately downstream.
  • Reason this comment was not posted:
    Comment did not seem useful. Confidence is useful = 0% <= threshold 50% The comment is asking the author to ensure that certain conditions are handled appropriately downstream. This falls under the category of asking the author to ensure behavior, which is against the rules. The comment does not provide a specific suggestion or point out a specific issue with the code.
3. src/lib/catalog/providerCredentials.ts:13
  • Draft comment:
    Simplified merging of credentialed and non-credentialed providers using Set looks clear and efficient.
  • Reason this comment was not posted:
    Confidence changes required: 0% <= threshold 50% None

Workflow ID: wflow_Evcu73OV2kh8Veld

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.

@openhands-ai
Copy link
Copy Markdown

openhands-ai Bot commented Oct 1, 2025

Looks like there are a few issues preventing this PR from being merged!

  • GitHub Actions are failing:
    • CI

If you'd like me to help, just leave a comment, like

@OpenHands please fix the failing actions on PR #44 at branch `lmstudio-followup`

Feel free to include any additional details that might help me get this PR into a better state.

You can manage your notification settings

Copy link
Copy Markdown
Contributor

@ellipsis-dev ellipsis-dev Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Important

Looks good to me! 👍

Reviewed 2061016 in 1 minute and 2 seconds. Click for details.
  • Reviewed 27 lines of code in 1 files
  • Skipped 0 files when reviewing.
  • Skipped posting 2 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. tests/catalog.modelCatalog.test.ts:6
  • Draft comment:
    Removed unused import 'addProviderWithCredentials' is good cleanup.
  • Reason this comment was not posted:
    Comment did not seem useful. Confidence is useful = 0% <= threshold 50% This comment is purely informative, as it only states that the removal of an unused import is a good cleanup. It does not provide any actionable feedback or suggestions for improvement.
2. tests/catalog.modelCatalog.test.ts:129
  • Draft comment:
    Removed test 'gates refresh when config is invalid...' – ensure that invalid config handling is covered elsewhere.
  • Reason this comment was not posted:
    Comment did not seem useful. Confidence is useful = 0% <= threshold 50% The comment is asking the author to ensure that invalid config handling is covered elsewhere, which violates the rule against asking the author to ensure something is tested or covered. It doesn't provide a specific suggestion or ask for a specific test to be written.

Workflow ID: wflow_VroWZ3f2UU4B7cxX

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

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

⚠️ Outside diff range comments (1)
src/lib/catalog/ModelCatalog.ts (1)

333-348: Insert configuration validation before fetching models
The PR mentions adding assertValidConfigAndRemoveEmptyKeys(), but ModelCatalog.ts (line 333) passes config straight to fetchModels. Call assertValidConfigAndRemoveEmptyKeys(config) from src/lib/providers/configuration.ts immediately after getProviderConfiguration and before provider.fetchModels(config).

🧹 Nitpick comments (1)
src/lib/catalog/providerCredentials.ts (1)

4-16: Consider adding error handling for storage retrieval.

The function doesn't handle potential errors from getProvidersWithCredentials. If storage access fails, the entire function will throw, which may disrupt initialization or refresh flows in calling code.

Consider wrapping the storage call in a try-catch or documenting that callers must handle storage errors:

 export async function getProvidersWithAccess(
   providerRegistry: IProviderRegistry,
   storage: StorageAdapter
 ): Promise<ProviderId[]> {
-  const credentialed = await getProvidersWithCredentials(storage);
+  let credentialed: ProviderId[];
+  try {
+    credentialed = await getProvidersWithCredentials(storage);
+  } catch (error) {
+    // Log error and fall back to empty array, or re-throw based on requirements
+    console.error('Failed to retrieve credentialed providers:', error);
+    credentialed = [];
+  }
   const noCredIds = providerRegistry
     .getProvidersNotRequiringCredentials()
     .map(({ metadata: { id } }) => id);
 
   return [...new Set([...credentialed, ...noCredIds])].filter((id) =>
     providerRegistry.hasProvider(id)
   );
 }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2854779 and 2061016.

📒 Files selected for processing (4)
  • package.json (5 hunks)
  • src/lib/catalog/ModelCatalog.ts (4 hunks)
  • src/lib/catalog/providerCredentials.ts (1 hunks)
  • tests/catalog.modelCatalog.test.ts (0 hunks)
💤 Files with no reviewable changes (1)
  • tests/catalog.modelCatalog.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • package.json
🧰 Additional context used
🧬 Code graph analysis (2)
src/lib/catalog/providerCredentials.ts (1)
src/lib/storage/repository.ts (1)
  • getProvidersWithCredentials (75-79)
src/lib/catalog/ModelCatalog.ts (1)
src/lib/catalog/providerCredentials.ts (1)
  • getProvidersWithAccess (4-16)
🔇 Additional comments (3)
src/lib/catalog/ModelCatalog.ts (3)

19-20: LGTM: Import updates align with the refactoring.

The imports correctly reflect the new centralized utility function getProvidersWithAccess while retaining getProviderConfiguration for per-provider config retrieval.


200-203: LGTM: Prefetch logic correctly uses the centralized utility.

The change to getProvidersWithAccess properly consolidates both credentialed and no-credential providers for the prefetch flow.


368-371: LGTM: Bulk refresh correctly uses the centralized utility.

The refreshAll method properly uses getProvidersWithAccess to determine which providers to refresh, consistent with the refactoring pattern.

Copy link
Copy Markdown
Contributor

@ellipsis-dev ellipsis-dev Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Important

Looks good to me! 👍

Reviewed 18823fe in 1 minute and 7 seconds. Click for details.
  • Reviewed 19 lines of code in 1 files
  • Skipped 0 files when reviewing.
  • Skipped posting 1 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. tests/catalog.modelCatalog.test.ts:67
  • Draft comment:
    Good removal of the unused 'storage' variable. This cleanup improves clarity; ensure it's not referenced elsewhere.
  • Reason this comment was not posted:
    Confidence changes required: 0% <= threshold 50% None

Workflow ID: wflow_RdKJ9KKNsbD3JSEN

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.

@hbmartin hbmartin merged commit 051a170 into main Oct 1, 2025
5 of 6 checks passed
@hbmartin hbmartin deleted the lmstudio-followup branch October 1, 2025 15:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant