Skip to content

feat: add Novita provider integration#2829

Draft
Alex-wuhu wants to merge 1 commit intogiselles-ai:mainfrom
Alex-wuhu:novita-integration
Draft

feat: add Novita provider integration#2829
Alex-wuhu wants to merge 1 commit intogiselles-ai:mainfrom
Alex-wuhu:novita-integration

Conversation

@Alex-wuhu
Copy link

Summary

This PR adds Novita LLM provider integration to Giselle, following the pattern of existing providers.

What's Changed

  • novita.ts: New provider implementing 3 Novita models:

      • DeepSeek V3.2
      • GLM-5 from Zhipu AI
      • MiniMax M2.5
  • language-models.ts: Registered Novita models in the language model registry

  • node-conversion.ts: Added conversion support for backward compatibility (maps Novita to OpenAI-compatible format)

  • .env.example: Added NOVITA_API_KEY environment variable

  • language-model.test.ts: Added tests for Novita model registration

Notes

  • All Novita models use the OpenAI-compatible API (same configuration pattern)
  • Model IDs use / separator per the codebase convention
  • Backward compatibility maintained by mapping to OpenAI format for legacy TextGenerationNode
  • No existing providers modified; all changes additive

- Introduce Novita language model provider
- Add 3 Novita models: DeepSeek V3.2, GLM-5, MiniMax M2.5
- Support backward compatibility via OpenAI-compatible conversion
- Add tests for Novita model registration
- Export NOVITA_API_KEY in .env.example
@vercel
Copy link

vercel bot commented Mar 13, 2026

@Alex-wuhu is attempting to deploy a commit to the Giselle Team on Vercel.

A member of the Team first needs to authorize it.

@giselles-ai
Copy link

giselles-ai bot commented Mar 13, 2026

Finished running flow.

Step 1
🟢
On Pull Request OpenedStatus: Success Updated: Mar 13, 2026 11:09am
Step 2
🟢
Manual QAStatus: Success Updated: Mar 13, 2026 11:12am
🟢
Prompt for AI AgentsStatus: Success Updated: Mar 13, 2026 11:12am
Step 3
🟢
Create a Comment for PRStatus: Success Updated: Mar 13, 2026 11:15am
Step 4
🟢
Create Pull Request CommentStatus: Success Updated: Mar 13, 2026 11:15am

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 13, 2026

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a2432a02-7a99-4f6c-8573-901369c883d2

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
📝 Coding Plan
  • Generate coding plan for human review comments

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.

Tip

CodeRabbit can use OpenGrep to find security vulnerabilities and bugs across 17+ programming languages.

OpenGrep is compatible with Semgrep configurations. Add an opengrep.yml or semgrep.yml configuration file to your project to enable OpenGrep analysis.

@changeset-bot
Copy link

changeset-bot bot commented Mar 13, 2026

⚠️ No Changeset found

Latest commit: 2234996

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

💥 An error occurred when fetching the changed packages and changesets in this PR
Some errors occurred when validating the changesets config:
The package or glob expression "giselles-ai" is specified in the `ignore` option but it is not found in the project. You may have misspelled the package name or provided an invalid glob expression. Note that glob expressions must be defined according to https://www.npmjs.com/package/micromatch.

@giselles-ai
Copy link

giselles-ai bot commented Mar 13, 2026

## 🔍 QA Testing Assistant by Giselle

### 📋 Manual QA Checklist

Based on the changes in this PR, here are the key areas to test manually:

  • UI/UX - Model Selection: Verify that "Novita" appears as a provider in the model selection dropdown and that DeepSeek V3.2, GLM-5, and MiniMax M2.5 are listed correctly under it.
  • Functionality - DeepSeek V3.2 Generation: Create a node, select Novita / DeepSeek V3.2, provide a prompt (e.g., "What is the capital of France?"), and confirm a coherent text response is generated.
  • Functionality - GLM-5 Generation: Create a node, select Novita / GLM-5, provide a prompt (e.g., "Write a short poem about the ocean."), and confirm a coherent text response is generated.
  • Functionality - MiniMax M2.5 Generation: Create a node, select Novita / MiniMax M2.5, provide a prompt (e.g., "List three benefits of exercise."), and confirm a coherent text response is generated.
  • Functionality - Backward Compatibility: Simulate loading a project file with a legacy Novita model ID (e.g., "zai-org/glm-5") and verify it loads correctly and is displayed as Novita / GLM-5.
  • Configuration - API Key: Ensure the application prompts for or correctly uses the NOVITA_API_KEY environment variable, and that generation fails gracefully if it's missing.

### ✨ Prompt for AI Agents

Use the following prompts with Cursor or Claude Code to automate E2E testing:

📝 E2E Test Generation Prompt
## **Prompt for AI Agent: Create E2E Tests for Novita Provider Integration**

### **1. Context Summary**

You are an expert QA engineer. Your task is to write E2E tests for a new feature using **Playwright** and **TypeScript**.

The Pull Request adds a new LLM provider, **"Novita"**, to our application, "Giselle Studio". This allows users to select and use three new language models from Novita. The integration follows the pattern of existing providers like OpenAI and uses an OpenAI-compatible API.

-   **Functionality Changes:**
    -   A new provider "Novita" is now available.
    -   Three new models are listed under this provider: `DeepSeek V3.2`, `GLM-5`, and `MiniMax M2.5`.
    -   The application requires a `NOVITA_API_KEY` environment variable to be set for the provider to function.
-   **Key User Flow:** The primary user journey is:
    1.  User opens the model selection UI in a generation node (e.g., a `TextGenerationNode`).
    2.  User sees and selects a model from the new "Novita" provider.
    3.  User configures the prompt and executes the generation.
    4.  The application makes an API call to the Novita service, and the result is displayed in the UI.
-   **Critical Paths:**
    -   Successful selection and execution of a Novita model.
    -   Saving and loading a project that uses a Novita model to ensure persistence works correctly.
    -   Ensuring the addition of Novita does not break existing provider functionality (regression).

### **2. Test Scenarios**

Generate a Playwright test file named `novita-provider.spec.ts`. Implement the following scenarios within a `describe('Novita Provider Integration', () => { ... })` block.

#### **Scenario 1: Model Discovery and Selection (Happy Path)**

-   **Goal:** Verify that the Novita provider and its models are visible and selectable in the UI.
-   **Steps:**
    1.  Navigate to the main canvas of Giselle Studio.
    2.  Create a `TextGenerationNode` (or a similar node that allows model selection).
    3.  Click the button to open the model selection modal/dropdown.
    4.  **Assert** that the "Novita" provider name is visible.
    5.  **Assert** that the following model names are visible under the Novita provider:
        -   `DeepSeek V3.2`
        -   `GLM-5`
        -   `MiniMax M2.5`
    6.  Select the `DeepSeek V3.2` model.
    7.  **Assert** that the model selector UI closes and the selected model is now displayed on the node.

#### **Scenario 2: End-to-End Generation with a Novita Model (Happy Path)**

-   **Goal:** Verify a full generation flow using a mocked Novita model.
-   **Steps:**
    1.  Start on a fresh canvas.
    2.  Set up an API mock using `page.route()` **before** performing any actions. The mock should intercept POST requests to the Novita API and return a predictable JSON response.
    3.  Create a `TextGenerationNode`.
    4.  Select the "Novita" model `novita/zai-org/glm-5` (`GLM-5`).
    5.  Enter a simple prompt like "Tell me a joke." into the node's input field.
    6.  Click the "Generate" or "Run" button for the node.
    7.  **Assert** that the node's output area is updated with the text from your mocked API response (e.g., "This is a mocked Novita joke.").
    8.  **Assert** that the network request was made to the correct Novita API endpoint.

#### **Scenario 3: Project Persistence**

-   **Goal:** Verify that a project using a Novita model can be saved and reloaded correctly.
-   **Steps:**
    1.  Create a `TextGenerationNode` and select the `novita/minimax/minimax-m2.5` model.
    2.  Use the application's "Save" functionality (assume a `data-testid="save-project-button"`).
    3.  Reload the page (`page.reload()`).
    4.  Use the application's "Load" functionality to open the saved project.
    5.  **Assert** that the `TextGenerationNode` is present on the canvas.
    6.  **Assert** that the selected model is still `novita/minimax/minimax-m2.5` (`MiniMax M2.5`).

#### **Scenario 4: Regression Test for Existing Provider**

-   **Goal:** Ensure existing providers (e.g., OpenAI) were not affected.
-   **Steps:**
    1.  This can be a brief test.
    2.  Create a `TextGenerationNode`.
    3.  Select an OpenAI model (e.g., `openai/gpt-5`).
    4.  **Assert** that the model is selected successfully.
    5.  (Optional but good) Run a quick, mocked generation with the OpenAI model to confirm the flow is intact.

### **3. Playwright Implementation Instructions**

-   **Selectors:** Use `data-testid` attributes for robust selectors. Assume the following exist:
    -   `data-testid="model-selector-button"`: The button on a node to open the model list.
    -   `data-testid="model-provider-group-Novita"`: The container for Novita models.
    -   `data-testid="model-item-novita/deepseek/deepseek-v3.2"`: A specific model item in the list.
    -   `data-testid="prompt-input"`: The textarea for the user's prompt.
    -   `data-testid="run-generation-button"`: The button to trigger generation.
    -   `data-testid="generation-output"`: The element displaying the final result.

-   **API Mocking:** This is the most critical part. Use `page.route()` to mock the API call. The Novita provider uses an OpenAI-compatible API. The endpoint will likely be something like `https://api.novita.ai/v3/chat/completions`.

    ```typescript
    // Example of mocking the Novita API in a test
    await page.route('**/api.novita.ai/v3/chat/completions', async (route) => {
      // Assert that the request method is POST
      expect(route.request().method()).toBe('POST');
      
      // Assert that the API key is being sent
      const headers = route.request().headers();
      expect(headers['authorization']).toContain('Bearer sk-test-novita-key');

      // Fulfill the request with a mock response
      await route.fulfill({
        status: 200,
        contentType: 'application/json',
        body: JSON.stringify({
          id: 'chatcmpl-mock-id',
          object: 'chat.completion',
          created: Date.now(),
          model: 'novita/zai-org/glm-5',
          choices: [{
            index: 0,
            message: {
              role: 'assistant',
              content: 'This is a mocked Novita joke.',
            },
            finish_reason: 'stop',
          }],
          usage: {
            prompt_tokens: 5,
            completion_tokens: 7,
            total_tokens: 12,
          },
        }),
      });
    });
    ```

-   **Assertions:** Use Playwright's `expect` library.
    -   `await expect(page.getByTestId('...')).toBeVisible();`
    -   `await expect(page.getByTestId('generation-output')).toContainText('mocked Novita joke');`

### **4. MCP Integration Guidelines**

-   **Environment Setup:** The application checks for `NOVITA_API_KEY`. Ensure your test setup includes a `.env.test` file or similar mechanism to set this variable. The value can be a dummy string like `sk-test-novita-key`.
-   **Execution Command:** Structure the test execution command to allow for filtering. The command to run only this new test file would look like this:
    ```bash
    pnpm mcp playwright:test --filter="novita-provider.spec.ts"
    ```
-   **MCP Parameters:** No special MCP parameters are required for this test, but it should be runnable via the standard test execution script defined in `package.json`.

### **5. CI-Ready Code Requirements**

-   **File Structure:** Place the new test file `novita-provider.spec.ts` in the appropriate E2E test directory (e.g., `e2e/tests/`).
-   **Test Organization:**
    -   Use a top-level `describe('Novita Provider Integration', ...)` for the file.
    -   Use `test('should ...', async ({ page }) => { ... })` for each scenario. Test names should be descriptive.
    -   Use `beforeEach` to handle repetitive setup, like navigating to the initial page.
-   **Atomicity & Parallelization:** Each `test` block must be self-contained and not depend on the state from other tests. The use of `page.route` within each test that needs it ensures test isolation, making them safe for parallel execution in a CI environment.
-   **Error Handling:** Rely on Playwright's automatic waits and clear assertions. Avoid manual `waitFor` unless absolutely necessary. Ensure API mocks are correctly scoped to prevent them from leaking into other tests.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant