Skip to content

Conversation

@benceruleanlu
Copy link
Member

@benceruleanlu benceruleanlu commented Jan 13, 2026

This extends pip install fallback behavior when a PyPI mirror is configured by adding multiple --extra-index-url values, ending with standard PyPI, so packages missing on TUNA (e.g. comfy-kitchen) still resolve.

Fallback order:

┆Issue is synchronized with this Notion page by Unito

@benceruleanlu benceruleanlu requested a review from a team as a code owner January 13, 2026 23:17
Copilot AI review requested due to automatic review settings January 13, 2026 23:17
@dosubot dosubot bot added the size:XS This PR changes 0-9 lines, ignoring generated files. label Jan 13, 2026
@coderabbitai
Copy link

coderabbitai bot commented Jan 13, 2026

📝 Walkthrough

Walkthrough

Exposes getPipInstallArgs and changes PipInstallConfig.extraIndexUrl?: stringextraIndexUrls?: string[]; adds PYPI_FALLBACK_INDEX_URLS constant and a private getPypiFallbackIndexUrls(); threads derived extraIndexUrls into requirement-install flows (installRequirements, installComfyUIRequirements, installComfyUIManagerRequirements).

Changes

Cohort / File(s) Summary
Virtual environment logic
src/virtualEnvironment.ts
Add and export getPipInstallArgs(config: PipInstallConfig): string[]; change PipInstallConfig to use extraIndexUrls?: string[]; add private `getPypiFallbackIndexUrls(): string[]
Constants
src/constants.ts
Add exported PYPI_FALLBACK_INDEX_URLS: string[] containing two mirror URLs plus TorchMirrorUrl.Default.
Tests
tests/unit/virtualEnvironment.test.ts
Add tests for getPipInstallArgs asserting -r requirements, --index-url, multiple --extra-index-url entries (including TorchMirrorUrl.Default), and --index-strategy handling.
✨ Finishing touches
  • 📝 Generate docstrings


📜 Recent review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3221503 and 2c051db.

📒 Files selected for processing (2)
  • src/constants.ts
  • src/virtualEnvironment.ts
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,mts,cts}

📄 CodeRabbit inference engine (.cursor/rules/typescript.mdc)

**/*.{ts,mts,cts}: Use features available in TypeScript 5.x
Use ESM only (type: module). Avoid CommonJS (require, module.exports)
Target ESNext runtime APIs and syntax. Prefer top-level await only when it improves clarity
Code must compile with strict mode and noImplicitAny enabled, with zero implicit any
Use unknown instead of any. Narrow with type guards. any is allowed only when interfacing with untyped code and must be localized and justified
Use interface for public object shapes intended for extension/implementation
Use type for unions, mapped/conditional types, function types, and when composition is needed
Model domain variants with a discriminant field (e.g., kind: 'X' | 'Y'). Use exhaustive switch statements
Prefer as const objects and string/number literal unions over enum
Prefer readonly properties and ReadonlyArray<T> where appropriate. Do not mutate function parameters
Prefer T[] over Array<T> for readability
Prefer Record<Key, T> for simple maps; use Map/Set when iteration semantics or key types require it
Avoid non-null assertions (!). Use optional chaining, nullish coalescing, and explicit guards
Use satisfies to enforce object literal conformance without widening values
Prefer named exports. Default exports are allowed only when a module clearly has a single primary export
Use import type { X } from '…' for type-only imports. Keep value and type imports separated when helpful for clarity and bundling
Exported functions, classes, and public APIs must have explicit parameter and return types. Internal locals can rely on inference
Prefer arrow functions for local functions and callbacks. Use function declarations when hoisting or this binding is required
Modules should be pure. Avoid executing logic at import time unless necessary (e.g., polyfills)
Prefer async/await over raw then/catch chains. Keep linear flow and use try/catch for failures
Either await promises or deliberately mark them...

Files:

  • src/constants.ts
  • src/virtualEnvironment.ts
src/**/*.{ts,mts,cts}

📄 CodeRabbit inference engine (.cursor/rules/typescript.mdc)

Centralize reusable domain types in src/** where discoverable. Avoid ad-hoc inline types for shared structures

Files:

  • src/constants.ts
  • src/virtualEnvironment.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: TypeScript: Do not use the any type; use unknown when the type is genuinely unknown
Use JSDoc format for method documentation with common tags @param and @return (omit @return for void return type); use {@link } to reference symbols

Files:

  • src/constants.ts
  • src/virtualEnvironment.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use ESLint and Prettier for code formatting; run yarn lint and yarn format before committing

Files:

  • src/constants.ts
  • src/virtualEnvironment.ts
🧬 Code graph analysis (1)
src/virtualEnvironment.ts (1)
src/constants.ts (1)
  • PYPI_FALLBACK_INDEX_URLS (194-198)
⏰ 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). (4)
  • GitHub Check: build-and-test-e2e-windows / integration-windows-test
  • GitHub Check: build-apple-debug-all / build-macos-debug
  • GitHub Check: lint-and-format (windows-latest)
  • GitHub Check: lint-and-format (macos-latest)
🔇 Additional comments (5)
src/constants.ts (1)

194-198: LGTM!

The fallback URL list is well-structured with consistent trailing slashes. Using TorchMirrorUrl.Default instead of a literal string for the PyPI URL maintains consistency with the existing constant definition.

src/virtualEnvironment.ts (4)

61-93: LGTM!

The function correctly handles multiple extra index URLs by iterating and appending each as a separate --extra-index-url argument. The export enables testing as intended.


159-166: LGTM with minor observation.

The filtering logic correctly prevents duplicate index URLs when the configured pypiMirror matches a fallback URL. The strict equality comparison works well since all URLs in PYPI_FALLBACK_INDEX_URLS use consistent formatting.

Note: If a user configures a pypiMirror with different trailing-slash formatting than the constants (e.g., without trailing slash), the filter won't deduplicate. This is likely acceptable since the mirror list uses well-known URLs.


411-417: Consistent fallback URL integration across installation methods.

The pattern is applied uniformly to installRequirements, installComfyUIRequirements, and installComfyUIManagerRequirements. This ensures packages missing from a configured mirror can be resolved from fallback sources.


46-54: Interface signature change is correct and properly implemented.

The rename from extraIndexUrl to extraIndexUrls with the array type accurately reflects the new capability. Verification confirms no external usages of the old property name remain in the codebase. All callers have been updated to use the new plural property.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.


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.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds fallback to the default PyPI index when users configure a custom PyPI mirror, addressing package availability issues for mirrors that don't contain all packages (e.g., comfy-kitchen missing from https://pypi.tuna.tsinghua.edu.cn/).

Changes:

  • Add TorchMirrorUrl.Default as extraIndexUrl when pypiMirror is set
  • Apply consistently across three install methods that use requirements files

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@benceruleanlu benceruleanlu marked this pull request as draft January 13, 2026 23:34
@benceruleanlu benceruleanlu marked this pull request as ready for review January 13, 2026 23:45
@benceruleanlu benceruleanlu requested a review from a team as a code owner January 13, 2026 23:45
@dosubot dosubot bot added size:M This PR changes 30-99 lines, ignoring generated files. and removed size:XS This PR changes 0-9 lines, ignoring generated files. labels Jan 13, 2026
Copy link

@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

🤖 Fix all issues with AI agents
In `@src/constants.ts`:
- Around line 194-201: PYPI_FALLBACK_INDEX_URLS contains an inconsistent SJTU
mirror string without a trailing slash; update the SJTU entry (the element in
the PYPI_FALLBACK_INDEX_URLS array that currently equals
'https://mirror.sjtu.edu.cn/pypi/web/simple') to include the trailing slash so
it matches the other mirror URLs and preserves consistency.
📜 Review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7ec35db and 3221503.

📒 Files selected for processing (3)
  • src/constants.ts
  • src/virtualEnvironment.ts
  • tests/unit/virtualEnvironment.test.ts
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{ts,mts,cts}

📄 CodeRabbit inference engine (.cursor/rules/typescript.mdc)

**/*.{ts,mts,cts}: Use features available in TypeScript 5.x
Use ESM only (type: module). Avoid CommonJS (require, module.exports)
Target ESNext runtime APIs and syntax. Prefer top-level await only when it improves clarity
Code must compile with strict mode and noImplicitAny enabled, with zero implicit any
Use unknown instead of any. Narrow with type guards. any is allowed only when interfacing with untyped code and must be localized and justified
Use interface for public object shapes intended for extension/implementation
Use type for unions, mapped/conditional types, function types, and when composition is needed
Model domain variants with a discriminant field (e.g., kind: 'X' | 'Y'). Use exhaustive switch statements
Prefer as const objects and string/number literal unions over enum
Prefer readonly properties and ReadonlyArray<T> where appropriate. Do not mutate function parameters
Prefer T[] over Array<T> for readability
Prefer Record<Key, T> for simple maps; use Map/Set when iteration semantics or key types require it
Avoid non-null assertions (!). Use optional chaining, nullish coalescing, and explicit guards
Use satisfies to enforce object literal conformance without widening values
Prefer named exports. Default exports are allowed only when a module clearly has a single primary export
Use import type { X } from '…' for type-only imports. Keep value and type imports separated when helpful for clarity and bundling
Exported functions, classes, and public APIs must have explicit parameter and return types. Internal locals can rely on inference
Prefer arrow functions for local functions and callbacks. Use function declarations when hoisting or this binding is required
Modules should be pure. Avoid executing logic at import time unless necessary (e.g., polyfills)
Prefer async/await over raw then/catch chains. Keep linear flow and use try/catch for failures
Either await promises or deliberately mark them...

Files:

  • src/constants.ts
  • tests/unit/virtualEnvironment.test.ts
  • src/virtualEnvironment.ts
src/**/*.{ts,mts,cts}

📄 CodeRabbit inference engine (.cursor/rules/typescript.mdc)

Centralize reusable domain types in src/** where discoverable. Avoid ad-hoc inline types for shared structures

Files:

  • src/constants.ts
  • src/virtualEnvironment.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: TypeScript: Do not use the any type; use unknown when the type is genuinely unknown
Use JSDoc format for method documentation with common tags @param and @return (omit @return for void return type); use {@link } to reference symbols

Files:

  • src/constants.ts
  • tests/unit/virtualEnvironment.test.ts
  • src/virtualEnvironment.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use ESLint and Prettier for code formatting; run yarn lint and yarn format before committing

Files:

  • src/constants.ts
  • tests/unit/virtualEnvironment.test.ts
  • src/virtualEnvironment.ts
tests/**/*.{ts,mts,cts}

📄 CodeRabbit inference engine (.cursor/rules/typescript.mdc)

Test code may relax some strictness to maximize ergonomics. Keep type escapes localized

Files:

  • tests/unit/virtualEnvironment.test.ts
tests/unit/**/*.test.{js,ts}

📄 CodeRabbit inference engine (.cursor/rules/vitest.mdc)

tests/unit/**/*.test.{js,ts}: Use vitest for unit testing
Do not build custom testing infrastructure; use Vitest and existing helpers
Store tests in the tests/unit/ directory with directory structure matching that of the tested file in src/
Tests should be cross-platform compatible; ensure proper use of path.normalize, path.join, and path.sep for Windows, macOS, and Linux compatibility
Mocks should be cleanly written, easy to understand, and reusable where possible
Prefer the use of test.extend over loose variables in Vitest tests
Use test instead of it for defining tests

Files:

  • tests/unit/virtualEnvironment.test.ts
tests/unit/**/*.{test,spec}.ts

📄 CodeRabbit inference engine (AGENTS.md)

Use Vitest for creating unit tests; do not attempt to create custom testing infrastructure

Files:

  • tests/unit/virtualEnvironment.test.ts
🧠 Learnings (10)
📚 Learning: 2025-11-25T20:49:40.925Z
Learnt from: CR
Repo: Comfy-Org/desktop PR: 0
File: .cursor/rules/integration-testing.mdc:0-0
Timestamp: 2025-11-25T20:49:40.925Z
Learning: Applies to tests/integration/**/*.spec.ts : Leverage TestEnvironment for state manipulation and error simulation instead of manual setup

Applied to files:

  • tests/unit/virtualEnvironment.test.ts
📚 Learning: 2025-11-25T20:50:25.371Z
Learnt from: CR
Repo: Comfy-Org/desktop PR: 0
File: .cursor/rules/vitest.mdc:0-0
Timestamp: 2025-11-25T20:50:25.371Z
Learning: Applies to tests/unit/**/*.test.{js,ts} : Use `vitest` for unit testing

Applied to files:

  • tests/unit/virtualEnvironment.test.ts
📚 Learning: 2025-11-25T20:50:25.371Z
Learnt from: CR
Repo: Comfy-Org/desktop PR: 0
File: .cursor/rules/vitest.mdc:0-0
Timestamp: 2025-11-25T20:50:25.371Z
Learning: Applies to tests/unit/**/*.test.{js,ts} : Do not build custom testing infrastructure; use Vitest and existing helpers

Applied to files:

  • tests/unit/virtualEnvironment.test.ts
📚 Learning: 2025-12-18T19:46:11.878Z
Learnt from: CR
Repo: Comfy-Org/desktop PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-18T19:46:11.878Z
Learning: Applies to tests/unit/**/*.{test,spec}.ts : Use Vitest for creating unit tests; do not attempt to create custom testing infrastructure

Applied to files:

  • tests/unit/virtualEnvironment.test.ts
📚 Learning: 2025-11-25T20:50:25.371Z
Learnt from: CR
Repo: Comfy-Org/desktop PR: 0
File: .cursor/rules/vitest.mdc:0-0
Timestamp: 2025-11-25T20:50:25.371Z
Learning: Applies to tests/unit/**/*.test.{js,ts} : Prefer the use of `test.extend` over loose variables in Vitest tests

Applied to files:

  • tests/unit/virtualEnvironment.test.ts
📚 Learning: 2025-11-25T20:50:25.371Z
Learnt from: CR
Repo: Comfy-Org/desktop PR: 0
File: .cursor/rules/vitest.mdc:0-0
Timestamp: 2025-11-25T20:50:25.371Z
Learning: Applies to tests/unit/**/*.test.{js,ts} : Tests should be cross-platform compatible; ensure proper use of `path.normalize`, `path.join`, and `path.sep` for Windows, macOS, and Linux compatibility

Applied to files:

  • tests/unit/virtualEnvironment.test.ts
📚 Learning: 2025-11-25T20:49:50.649Z
Learnt from: CR
Repo: Comfy-Org/desktop PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-25T20:49:50.649Z
Learning: Applies to tests/integration/**/*.{ts,js} : Use `path.join()` and `path.sep` to ensure file path handling works consistently across Windows, macOS, and Linux platforms

Applied to files:

  • tests/unit/virtualEnvironment.test.ts
📚 Learning: 2025-11-25T20:49:40.925Z
Learnt from: CR
Repo: Comfy-Org/desktop PR: 0
File: .cursor/rules/integration-testing.mdc:0-0
Timestamp: 2025-11-25T20:49:40.925Z
Learning: Applies to tests/integration/**/*.spec.ts : Use Playwright + TypeScript for Electron testing in integration tests

Applied to files:

  • tests/unit/virtualEnvironment.test.ts
📚 Learning: 2025-11-25T20:49:40.925Z
Learnt from: CR
Repo: Comfy-Org/desktop PR: 0
File: .cursor/rules/integration-testing.mdc:0-0
Timestamp: 2025-11-25T20:49:40.925Z
Learning: Applies to tests/integration/**/*.spec.ts : Import fixtures from testExtensions.ts, not raw Playwright

Applied to files:

  • tests/unit/virtualEnvironment.test.ts
📚 Learning: 2025-11-25T20:49:40.925Z
Learnt from: CR
Repo: Comfy-Org/desktop PR: 0
File: .cursor/rules/integration-testing.mdc:0-0
Timestamp: 2025-11-25T20:49:40.925Z
Learning: Applies to tests/integration/**/*.spec.ts : Mock native dialogs when needed using app.app.evaluate() with electron.dialog overrides

Applied to files:

  • tests/unit/virtualEnvironment.test.ts
🧬 Code graph analysis (2)
tests/unit/virtualEnvironment.test.ts (1)
src/virtualEnvironment.ts (1)
  • getPipInstallArgs (61-93)
src/virtualEnvironment.ts (1)
src/constants.ts (1)
  • PYPI_FALLBACK_INDEX_URLS (194-201)
⏰ 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). (3)
  • GitHub Check: build-apple-debug-all / build-macos-debug
  • GitHub Check: build-and-test-e2e-windows / integration-windows-test
  • GitHub Check: lint-and-format (windows-latest)
🔇 Additional comments (7)
src/virtualEnvironment.ts (6)

46-54: LGTM!

The interface update from extraIndexUrl?: string to extraIndexUrls?: string[] correctly reflects the new multi-URL capability and follows proper naming conventions.


61-93: LGTM!

The function correctly builds pip install arguments, including proper iteration over multiple extra index URLs. The export enables unit testing of this logic.


159-168: Verify the intended behavior for users without a custom mirror.

The fallback URLs are only applied when pypiMirror is configured. Users without a custom mirror won't receive fallbacks. If the intent is also to provide resilience for default PyPI users (e.g., when pypi.org is slow/unavailable), consider whether fallbacks should always be applied.

If this is the intended design (fallbacks only for mirror users), this implementation is correct.


413-419: LGTM!

Fallback index URLs are correctly integrated into the requirements installation flow.


829-834: LGTM!

Consistent with the other installation methods.


861-866: LGTM!

ComfyUI Manager requirements installation correctly uses fallback index URLs.

tests/unit/virtualEnvironment.test.ts (1)

155-180: LGTM!

The test correctly validates the getPipInstallArgs function with multiple extra index URLs and the index strategy option. The assertion verifies both the correct arguments and their ordering.

Consider adding edge case tests for completeness (e.g., extraIndexUrls: [] or extraIndexUrls: undefined), though the current test covers the primary use case well.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment on lines 194 to 201
export const PYPI_FALLBACK_INDEX_URLS: string[] = [
'https://mirrors.aliyun.com/pypi/simple/',
'https://mirrors.ustc.edu.cn/pypi/simple/',
'https://mirrors.cloud.tencent.com/pypi/simple/',
'https://mirrors.huaweicloud.com/repository/pypi/simple/',
'https://mirror.sjtu.edu.cn/pypi/web/simple',
TorchMirrorUrl.Default,
];
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Minor inconsistency: trailing slash missing on SJTU mirror URL.

Line 199 (https://mirror.sjtu.edu.cn/pypi/web/simple) lacks a trailing slash, while all other mirror URLs include one. While pip typically handles both forms, consistency is preferable.

✨ Suggested fix
 export const PYPI_FALLBACK_INDEX_URLS: string[] = [
   'https://mirrors.aliyun.com/pypi/simple/',
   'https://mirrors.ustc.edu.cn/pypi/simple/',
   'https://mirrors.cloud.tencent.com/pypi/simple/',
   'https://mirrors.huaweicloud.com/repository/pypi/simple/',
-  'https://mirror.sjtu.edu.cn/pypi/web/simple',
+  'https://mirror.sjtu.edu.cn/pypi/web/simple/',
   TorchMirrorUrl.Default,
 ];
📝 Committable suggestion

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

Suggested change
export const PYPI_FALLBACK_INDEX_URLS: string[] = [
'https://mirrors.aliyun.com/pypi/simple/',
'https://mirrors.ustc.edu.cn/pypi/simple/',
'https://mirrors.cloud.tencent.com/pypi/simple/',
'https://mirrors.huaweicloud.com/repository/pypi/simple/',
'https://mirror.sjtu.edu.cn/pypi/web/simple',
TorchMirrorUrl.Default,
];
export const PYPI_FALLBACK_INDEX_URLS: string[] = [
'https://mirrors.aliyun.com/pypi/simple/',
'https://mirrors.ustc.edu.cn/pypi/simple/',
'https://mirrors.cloud.tencent.com/pypi/simple/',
'https://mirrors.huaweicloud.com/repository/pypi/simple/',
'https://mirror.sjtu.edu.cn/pypi/web/simple/',
TorchMirrorUrl.Default,
];
🤖 Prompt for AI Agents
In `@src/constants.ts` around lines 194 - 201, PYPI_FALLBACK_INDEX_URLS contains
an inconsistent SJTU mirror string without a trailing slash; update the SJTU
entry (the element in the PYPI_FALLBACK_INDEX_URLS array that currently equals
'https://mirror.sjtu.edu.cn/pypi/web/simple') to include the trailing slash so
it matches the other mirror URLs and preserves consistency.

@benceruleanlu benceruleanlu changed the title Add TorchMirrorUrl.Default as extraIndexUrl Add PyPI mirror fallbacks Jan 14, 2026
@benceruleanlu benceruleanlu merged commit aef7859 into main Jan 14, 2026
7 of 8 checks passed
@benceruleanlu benceruleanlu deleted the bl-pypi-simple-fallback branch January 14, 2026 05:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies size:M This PR changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants