Skip to content

Conversation

@shige
Copy link
Member

@shige shige commented Nov 21, 2025

User description

Implement end-to-end data flow to pass team's activeCustomerId through the AI Gateway as X-Stripe-Customer-ID header for both text generation and embeddings.

Metadata and type changes:

  • Add activeCustomerId to GenerationMetadata schema
  • Update TeamForPlan type to include activeCustomerId field

Text generation flow:

  • Pass activeCustomerId from metadata.team to gateway options
  • Update generate-content-job to include activeCustomerId in schema
  • Update all job invocation sites to pass activeCustomerId

Embeddings flow:

  • Add xStripeCustomerId parameter to GenerateEmbeddingsOptions
  • Pass activeCustomerId from telemetry context to embeddings generation
  • Support customer ID in document ingest process

This completes the Stripe Token Billing integration by connecting team.activeCustomerId from the database to the actual LLM and embedding API requests.


PR Type

Enhancement


Description

  • Add activeCustomerId field to team metadata schemas

  • Pass activeCustomerId through text generation job invocations

  • Pass activeCustomerId to embeddings generation with X-Stripe-Customer-ID header

  • Support customer ID in document ingest telemetry context


Diagram Walkthrough

flowchart LR
  DB["Database<br/>Team.activeCustomerId"]
  META["GenerationMetadata<br/>Schema"]
  TRACE["Trace Functions<br/>TeamForPlan Type"]
  GEN["Text Generation<br/>Job Invocations"]
  EMB["Embeddings<br/>Generation"]
  HEADER["X-Stripe-Customer-ID<br/>Header"]
  
  DB -->|"Add field"| META
  META -->|"Update type"| TRACE
  TRACE -->|"Pass to jobs"| GEN
  TRACE -->|"Pass to embeddings"| EMB
  EMB -->|"Set header"| HEADER
Loading

File Walkthrough

Relevant files
Enhancement
giselle.ts
Add activeCustomerId to team metadata in giselle app         

apps/studio.giselles.ai/app/giselle.ts

  • Updated TeamForPlan type to include activeCustomerId field
  • Added activeCustomerId to team object in embeddings trace call
  • Added activeCustomerId to team object in both generate-content job
    invocations
+8/-2     
generation-metadata.ts
Add activeCustomerId to GenerationMetadata schema               

apps/studio.giselles.ai/lib/generation-metadata.ts

  • Added activeCustomerId as nullable string field to GenerationMetadata
    schema
+1/-0     
trace.ts
Add activeCustomerId to trace TeamForPlan type                     

apps/studio.giselles.ai/lib/trace.ts

  • Updated TeamForPlan type to include activeCustomerId field
+4/-1     
generate-embeddings.ts
Add Stripe customer ID header to embeddings generation     

apps/studio.giselles.ai/lib/vector-stores/document/ingest/generate-embeddings.ts

  • Added xStripeCustomerId optional parameter to
    GenerateEmbeddingsOptions interface
  • Pass xStripeCustomerId to embedder.embedMany() call with
    X-Stripe-Customer-ID header
+12/-1   
ingest-document.ts
Pass activeCustomerId to embeddings generation                     

apps/studio.giselles.ai/lib/vector-stores/document/ingest/ingest-document.ts

  • Pass activeCustomerId from telemetry context to generateEmbeddings
    function
+2/-0     
generate-content-job.ts
Add activeCustomerId to generate-content job schema           

apps/studio.giselles.ai/trigger/generate-content-job.ts

  • Added activeCustomerId field to generate-content job schema
  • Pass activeCustomerId to traceGenerationForTeam in both onSuccess and
    onError handlers
+5/-2     

Note

Propagates team.activeCustomerId end-to-end and sends it to the AI Gateway (including embeddings) via X-Stripe-Customer-ID, updating schemas, tracing, and job wiring.

  • Schemas & Types
    • Add team.activeCustomerId to GenerationMetadata and extend TeamForPlan to include activeCustomerId.
  • Tracing/Telemetry
    • Include customerId in generation and embedding trace metadata in trace.ts and app/giselle.ts.
  • Jobs
    • Update generate-content job schema to carry activeCustomerId and pass it through success/error handlers and all invocation sites.
  • Embeddings Pipeline
    • Add xStripeCustomerId to generateEmbeddings options and forward as X-Stripe-Customer-ID header to embedder.embedMany.
    • Pass team activeCustomerId from ingest telemetry context to embeddings generation in ingest-document.ts.

Written by Cursor Bugbot for commit 26702eb. This will update automatically on new commits. Configure here.

Summary by CodeRabbit

  • Chores
    • Enhanced customer identification tracking throughout content generation and embedding systems.
    • Improved customer data propagation across analytics and tracing pipelines.
    • Added optional customer identifier field to metadata and generation schemas.

✏️ Tip: You can customize this high-level summary in your review settings.

Implement Stripe Customer ID header passing for both text generation and embeddings through the AI Gateway.

Text generation changes:
- Update generationModel function to accept xStripeCustomerId parameter
- Add X-Stripe-Customer-ID header to gateway when xStripeCustomerId is provided

Embeddings changes:
- Add EmbeddingOptions interface with headers parameter
- Update EmbedderFunction type to accept optional EmbeddingOptions on embed/embedMany
- Support per-request headers in AI SDK embedder implementation

This enables per-request customer tracking for Stripe Token Billing, allowing different customer IDs for each generation/embedding request.
Implement end-to-end data flow to pass team's activeCustomerId through the AI Gateway as X-Stripe-Customer-ID header for both text generation and embeddings.

Metadata and type changes:
- Add activeCustomerId to GenerationMetadata schema
- Update TeamForPlan type to include activeCustomerId field

Text generation flow:
- Pass activeCustomerId from metadata.team to gateway options
- Update generate-content-job to include activeCustomerId in schema
- Update all job invocation sites to pass activeCustomerId

Embeddings flow:
- Add xStripeCustomerId parameter to GenerateEmbeddingsOptions
- Pass activeCustomerId from telemetry context to embeddings generation
- Support customer ID in document ingest process

This completes the Stripe Token Billing integration by connecting team.activeCustomerId from the database to the actual LLM and embedding API requests.
@shige shige requested a review from Copilot November 21, 2025 04:13
@shige shige self-assigned this Nov 21, 2025
@changeset-bot
Copy link

changeset-bot bot commented Nov 21, 2025

⚠️ No Changeset found

Latest commit: 26702eb

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 Nov 21, 2025

Finished running flow.

Step 1
🟢
On Pull Request OpenedStatus: Success Updated: Nov 21, 2025 4:13am
Step 2
🟢
Manual QAStatus: Success Updated: Nov 21, 2025 4:15am
🟢
Prompt for AI AgentsStatus: Success Updated: Nov 21, 2025 4:15am
Step 3
🟢
Create a Comment for PRStatus: Success Updated: Nov 21, 2025 4:18am
Step 4
🟢
Create Pull Request CommentStatus: Success Updated: Nov 21, 2025 4:18am

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 21, 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

The pull request adds the activeCustomerId field to the TeamForPlan type and propagates it through generation metadata schemas, embedding request headers, and trigger job payloads. The field flows from team data through the embedding pipeline as an X-Stripe-Customer-ID header and is included in trace generation calls.

Changes

Cohort / File(s) Summary
Type Definitions
apps/studio.giselles.ai/app/giselle.ts, apps/studio.giselles.ai/lib/trace.ts
Updated TeamForPlan type to include activeCustomerId in the Pick from CurrentTeam
Metadata Schema
apps/studio.giselles.ai/lib/generation-metadata.ts
Added optional nullable activeCustomerId: z.string().nullable() field to the nested team object in GenerationMetadata
Embedding Pipeline
apps/studio.giselles.ai/lib/vector-stores/document/ingest/generate-embeddings.ts, apps/studio.giselles.ai/lib/vector-stores/document/ingest/ingest-document.ts
Added xStripeCustomerId optional field to GenerateEmbeddingsOptions; propagate it as "X-Stripe-Customer-ID" header in embedding requests and pass team.activeCustomerId when invoking generateEmbeddings
Trigger Job
apps/studio.giselles.ai/trigger/generate-content-job.ts
Added activeCustomerId: z.string().nullable() to the team schema; propagate activeCustomerId in team payload to traceGenerationForTeam calls in both completion and error handlers

Sequence Diagram

sequenceDiagram
    participant Meta as Generation Metadata
    participant Ingest as Document Ingest
    participant Embed as Embeddings Service
    participant Trace as Trace Generation
    
    Meta->>Ingest: telemetryContext.team{id, activeCustomerId, ...}
    Ingest->>Embed: xStripeCustomerId: team.activeCustomerId
    Embed->>Embed: headers: {"X-Stripe-Customer-ID": xStripeCustomerId}
    Note over Embed: Request with customer ID header
    Trace->>Trace: team{id, activeCustomerId, activeSubscriptionId, plan}
    Note over Trace: Trace includes enriched team data
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Consistent pattern of adding activeCustomerId across multiple files, but requires verification that the field propagates correctly through embedding headers and trace payloads
  • Check that the optional/nullable field handling is consistent across schemas (generation-metadata.ts uses .nullable(), job schema also allows null)
  • Verify the X-Stripe-Customer-ID header is only set when xStripeCustomerId is defined (conditional header handling in generate-embeddings.ts)

Possibly related PRs

Suggested labels

Possible security concern

Suggested reviewers

  • toyamarinyon

Poem

🐰 A customer ID hops through the trace,
From teams to embeddings, keeping pace,
Headers enriched, metadata bright,
Each stripe-bound request set just right! ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.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 accurately summarizes the main change: passing activeCustomerId through the AI Gateway for Stripe Token Billing integration, which is clearly reflected in all modified files.
Description check ✅ Passed The PR description is comprehensive and well-structured, covering all key aspects of the enhancement with clear sections for objectives, implementation details, and a helpful diagram.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch pass-active-customer-id-through-gateway

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.

@vercel
Copy link

vercel bot commented Nov 21, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
giselle Ready Ready Preview Comment Nov 21, 2025 4:49am
ui Ready Ready Preview Comment Nov 21, 2025 4:49am

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 implements the Stripe Token Billing integration by passing the team's activeCustomerId through the entire data flow to AI Gateway as the X-Stripe-Customer-ID header for both text generation and embeddings requests.

Key Changes:

  • Extended metadata schemas and type definitions to include activeCustomerId field
  • Updated text generation flow to pass activeCustomerId from metadata through to gateway options
  • Added xStripeCustomerId parameter to embeddings generation and document ingestion flows

Reviewed Changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated no comments.

Show a summary per file
File Description
apps/studio.giselles.ai/lib/generation-metadata.ts Added activeCustomerId field to GenerationMetadata schema
apps/studio.giselles.ai/lib/trace.ts Updated TeamForPlan type to include activeCustomerId
apps/studio.giselles.ai/app/giselle.ts Updated TeamForPlan type and passed activeCustomerId through generation metadata and trigger.dev job invocations
apps/studio.giselles.ai/trigger/generate-content-job.ts Added activeCustomerId to job schema and passed it through to telemetry context
apps/studio.giselles.ai/lib/vector-stores/document/ingest/generate-embeddings.ts Added xStripeCustomerId parameter and passed it as X-Stripe-Customer-ID header to embedder
apps/studio.giselles.ai/lib/vector-stores/document/ingest/ingest-document.ts Passed activeCustomerId from telemetry context to embeddings generation

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

@qodo-merge-for-open-source
Copy link

qodo-merge-for-open-source bot commented Nov 21, 2025

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
Header injection risk

Description: The xStripeCustomerId parameter is passed directly to HTTP headers without validation or
sanitization, potentially allowing header injection attacks if the customer ID contains
newline characters or other malicious content.
generate-embeddings.ts [123-130]

Referred Code
batch,
xStripeCustomerId
	? {
			headers: {
				"X-Stripe-Customer-ID": xStripeCustomerId,
			},
		}
	: undefined,
Unvalidated external input

Description: The activeCustomerId from telemetryContext is passed to generateEmbeddings without null
safety checks or validation, which could lead to unexpected behavior if the telemetry
context structure changes or contains malicious data.
ingest-document.ts [283-284]

Referred Code
xStripeCustomerId:
	telemetryContext?.team.activeCustomerId ?? undefined,
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
🟢
Generic: Comprehensive Audit Trails

Objective: To create a detailed and reliable record of critical system actions for security analysis
and compliance.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Meaningful Naming and Self-Documenting Code

Objective: Ensure all identifiers clearly express their purpose and intent, making code
self-documenting

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Robust Error Handling and Edge Case Management

Objective: Ensure comprehensive error handling that provides meaningful context and graceful
degradation

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Error Handling

Objective: To prevent the leakage of sensitive system information through error messages while
providing sufficient detail for internal debugging.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Logging Practices

Objective: To ensure logs are useful for debugging and auditing without exposing sensitive
information like PII, PHI, or cardholder data.

Status:
Customer ID Header Exposure: The activeCustomerId (Stripe customer ID) is passed as a header which may be logged by
HTTP clients, proxies, or API gateways.

Referred Code
const batchEmbeddings = await embedder.embedMany(
	batch,
	xStripeCustomerId
		? {
				headers: {
					"X-Stripe-Customer-ID": xStripeCustomerId,
				},
			}
		: undefined,

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Security-First Input Validation and Data Handling

Objective: Ensure all data inputs are validated, sanitized, and handled securely to prevent
vulnerabilities

Status:
Missing Customer ID Validation: The activeCustomerId field accepts any string without format validation, which could allow
injection of malicious header values.

Referred Code
	activeCustomerId: z.string().nullable(),
}),

Learn more about managing compliance generic rules or creating your own custom rules

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

@qodo-merge-for-open-source
Copy link

qodo-merge-for-open-source bot commented Nov 21, 2025

PR Code Suggestions ✨

No code suggestions found for the PR.

@giselles-ai
Copy link

giselles-ai bot commented Nov 21, 2025

🔍 QA Testing Assistant by Giselle

📋 Manual QA Checklist

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

  • 1. Text Generation with activeCustomerId: Verify that when a team has an activeCustomerId, the X-Stripe-Customer-ID header is present with the correct customer ID in outgoing AI Gateway requests for text generation.
  • 2. Text Generation without activeCustomerId: Verify that when a team does not have an activeCustomerId, the X-Stripe-Customer-ID header is not present in outgoing AI Gateway requests for text generation.
  • 3. Embeddings Generation with activeCustomerId: Verify that when a team has an activeCustomerId, the X-Stripe-Customer-ID header is present with the correct customer ID in outgoing AI Gateway requests for embeddings generation.
  • 4. Embeddings Generation without activeCustomerId: Verify that when a team does not have an activeCustomerId, the X-Stripe-Customer-ID header is not present in outgoing AI Gateway requests for embeddings generation.

✨ Prompt for AI Agents

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

📝 E2E Test Generation Prompt
## **Prompt for AI Code Assistant (e.g., Cursor, Claude Code)**

You are an expert QA engineer. Your task is to write a new E2E test suite using Playwright. This suite will validate the changes introduced in a recent Pull Request. The core goal of the PR was to pass a team's `activeCustomerId` to our AI Gateway via an `X-Stripe-Customer-ID` HTTP header for token-based billing with Stripe.

Please follow the detailed instructions below to create robust, maintainable, and CI-ready tests.

### **1. Context Summary**

*   **PR Description:** The PR implements the end-to-end data flow for passing a team's `activeCustomerId` to an external "AI Gateway" service. This is accomplished by adding the `X-Stripe-Customer-ID` header to all outgoing requests to that gateway.
*   **Key User Flows Affected:**
    1.  **AI Text Generation:** When a user generates text content.
    2.  **Document Ingestion (Embeddings):** When a user uploads a document to be processed and embedded.
*   **Critical Path to Test:** The most critical part of this change is verifying that the `X-Stripe-Customer-ID` header is correctly added to the server-side API calls made to the AI Gateway. Since Playwright cannot directly inspect server-to-server requests, **the tests MUST use network request interception (`page.route`) to mock the AI Gateway endpoints and inspect the headers of the intercepted requests.**

### **2. Test Scenarios**

Create a new test file named `stripe-billing-header.spec.ts`. The test suite should be described as `'Stripe Token Billing Header'`.

You will need to test two primary scenarios, each with a happy path and an edge case.

**Pre-requisite:** The tests will require two distinct test users/teams to be available:
*   **Team A:** A team with a valid `activeCustomerId` (e.g., `cus_test123456789`).
*   **Team B:** A team where `activeCustomerId` is `null` or not present.

You can assume helper functions `loginAsUserWithCustomerId()` and `loginAsUserWithoutCustomerId()` exist for setting up the test state.

**Scenario 1: AI Text Generation**

*   **Test 1.1 (Happy Path):**
    *   **Description:** `it('should send X-Stripe-Customer-ID header on text generation for a team with an activeCustomerId')`
    *   **Steps:**
        1.  Log in as a user from **Team A**.
        2.  Navigate to the content generation page.
        3.  Mock the AI Gateway's text generation endpoint.
        4.  Trigger a text generation (e.g., type in a prompt and click "Generate").
        5.  **Assert** that the intercepted request to the AI Gateway contains the `x-stripe-customer-id` header with the correct value (`cus_test123456789`).
        6.  **Assert** that the UI correctly displays the (mocked) generated content.

*   **Test 1.2 (Edge Case):**
    *   **Description:** `it('should NOT send X-Stripe-Customer-ID header on text generation for a team without an activeCustomerId')`
    *   **Steps:**
        1.  Log in as a user from **Team B**.
        2.  Navigate to the content generation page.
        3.  Mock the AI Gateway's text generation endpoint.
        4.  Trigger a text generation.
        5.  **Assert** that the intercepted request to the AI Gateway **does not** contain the `x-stripe-customer-id` header.
        6.  **Assert** that the text generation functionality still works from a UI perspective.

**Scenario 2: Document Ingestion (Embeddings)**

*   **Test 2.1 (Happy Path):**
    *   **Description:** `it('should send X-Stripe-Customer-ID header on document ingest for a team with an activeCustomerId')`
    *   **Steps:**
        1.  Log in as a user from **Team A**.
        2.  Navigate to the document upload/ingestion page.
        3.  Mock the AI Gateway's embeddings endpoint.
        4.  Upload a sample document (e.g., a simple `.txt` file).
        5.  **Assert** that the intercepted request to the AI Gateway's embedding endpoint contains the `x-stripe-customer-id` header with the correct value (`cus_test123456789`).
        6.  **Assert** that the UI shows a success state for the upload.

*   **Test 2.2 (Edge Case):**
    *   **Description:** `it('should NOT send X-Stripe-Customer-ID header on document ingest for a team without an activeCustomerId')`
    *   **Steps:**
        1.  Log in as a user from **Team B**.
        2.  Navigate to the document upload/ingestion page.
        3.  Mock the AI Gateway's embeddings endpoint.
        4.  Upload a sample document.
        5.  **Assert** that the intercepted request to the AI Gateway's embedding endpoint **does not** contain the `x-stripe-customer-id` header.
        6.  **Assert** that the document upload functionality still works from a UI perspective.

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

*   **Network Interception (Crucial):** Use `page.route()` to intercept and mock the outbound requests to the AI Gateway. This is how you will verify the headers. The URL for the gateway might be something like `**/api/ai-gateway/**`. Confirm the exact URL pattern.

    ```typescript
    // Example of mocking and capturing headers
    test('should send correct header', async ({ page }) => {
      let capturedHeader: string | undefined;

      // Mock the AI Gateway endpoint
      await page.route('**/api/ai-gateway/v1/generate', async (route) => {
        const headers = await route.request().allHeaders();
        capturedHeader = headers['x-stripe-customer-id'];
        
        // Fulfill the request with a mock response
        await route.fulfill({
          status: 200,
          contentType: 'application/json',
          body: JSON.stringify({ generatedText: 'This is a mock response.' }),
        });
      });

      // ... trigger the text generation in the UI ...

      // Assert the captured header
      expect(capturedHeader).toBe('cus_test123456789');
    });
    ```

*   **Selectors:** Use `data-testid` attributes for stable selectors. If they are not available, use role locators or other user-facing attributes.
    *   Text input: `page.getByRole('textbox', { name: /prompt/i })`
    *   Generate button: `page.getByRole('button', { name: /generate/i })`
    *   File input: `page.locator('input[type="file"]')`
    *   Upload button: `page.getByRole('button', { name: /upload/i })`

*   **Data Setup/Teardown:**
    *   Use a `test.beforeEach` block to handle logging in the user and setting up the network mocks for each test.
    *   Use a `test.afterEach` block to un-route the mocks if necessary (`page.unroute()`) to ensure clean test separation.

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

*   **Command Structure:** The test can be executed via Playwright MCP with a command targeting the new test file.
    ```bash
    # Example MCP command
    mcp playwright test tests/stripe-billing-header.spec.ts --project=chromium
    ```
*   **Environment Configuration:**
    *   Ensure environment variables for test user credentials (`TEST_USER_A_EMAIL`, `TEST_USER_A_PASSWORD`, etc.) are configured in the MCP environment.
    *   The base URL of the application should also be an environment variable (`BASE_URL`).

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

*   **Test Organization:**
    *   Use `test.describe('Stripe Token Billing Header', () => { ... });` to group all related tests.
    *   Create separate `test.describe` blocks for 'Text Generation' and 'Document Ingestion' within the main suite for clarity.
*   **Naming Conventions:**
    *   Use clear, descriptive names for tests as specified in the "Test Scenarios" section.
    *   Use descriptive variable names (e.g., `stripeCustomerIdHeader`).
*   **Error Handling:** Playwright's built-in assertions (`expect`) are sufficient. Ensure tests fail clearly if an assertion is not met.
*   **Parallelization:** The tests should be written to be fully independent and capable of running in parallel. Avoid any shared state between test files. The use of `beforeEach` for setup helps ensure this. Add `test.describe.configure({ mode: 'parallel' });` at the top of the suite.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +122 to +126
const batchEmbeddings = await embedder.embedMany(
batch,
xStripeCustomerId
? {
headers: {

Choose a reason for hiding this comment

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

P1 Badge embedMany call now violates @giselles-ai/rag signature

The new call to embedder.embedMany(batch, { headers: ... }) uses a second argument, but the public EmbedderFunction exported by @giselles-ai/rag still declares embedMany(texts: string[]): Promise<number[][]> (see packages/rag/dist/index.d.ts lines 173‑185). With the current package version in the workspace, this change will fail TypeScript compilation for the studio app with an “Expected 1 arguments, but got 2” error, blocking builds until the rag types are updated or the extra parameter is removed.

Useful? React with 👍 / 👎.

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks for the review!

The EmbedderFunction type was updated in PR #XXX (PR2) to include the optional EmbeddingOptions parameter on both embed and embedMany methods (see packages/rag/src/embedder/types.ts).

The build artifacts in packages/rag/dist/index.d.ts should reflect this change after running pnpm build-sdk. All type checks pass successfully:

  • ✅ pnpm build-sdk
  • ✅ pnpm check-types
  • ✅ pnpm test

If you're seeing the old signature, it might be because the dist files need to be regenerated or the PR branch needs to be rebased.

@shige
Copy link
Member Author

shige commented Nov 21, 2025

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 21, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Contributor

@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)
apps/studio.giselles.ai/app/giselle.ts (1)

477-486: Missing activeCustomerId in run-task-job trigger.

The run-task-job trigger for the github-app flow (lines 481-485) doesn't include activeCustomerId in the team object, while the generate-content triggers do. This inconsistency means task runs won't have customer billing context.

Apply this diff to add the missing field:

 				await jobs.trigger<typeof runTaskJob>("run-task-job", {
 					taskId: task.id,
 					requestId,
 					userId: "github-app",
 					team: {
 						id: team.id,
 						subscriptionId: team.activeSubscriptionId,
 						plan: team.plan,
+						activeCustomerId: team.activeCustomerId,
 					},
 				});

Note: The stage/studio flow (lines 496-505) also needs the same addition.

♻️ Duplicate comments (2)
apps/studio.giselles.ai/lib/trace.ts (1)

24-44: activeCustomerId not passed to traceGeneration metadata.

The traceGenerationForTeam function accepts activeCustomerId via the team parameter but doesn't include it in the metadata object passed to traceGeneration() (line 34-40). The subscriptionId is included at line 38, but activeCustomerId is missing.

Apply this diff to include it in metadata:

 		metadata: {
 			generationId: args.generation.id,
 			teamPlan,
 			userId: args.userId,
 			subscriptionId: args.team.activeSubscriptionId ?? "",
+			activeCustomerId: args.team.activeCustomerId ?? "",
 			providerMetadata: args.providerMetadata,
 			requestId: args.requestId,
 			workspaceId: args.generation.context.origin.workspaceId,
 		},
apps/studio.giselles.ai/lib/vector-stores/document/ingest/generate-embeddings.ts (1)

122-131: embedMany call violates @giselles-ai/rag signature.

The embedder.embedMany() call now passes a second argument with headers, but the EmbedderFunction type from @giselles-ai/rag declares embedMany(texts: string[]): Promise<number[][]> with only one parameter. This will cause TypeScript compilation errors unless the rag package types have been updated to support the second parameter.

🧹 Nitpick comments (1)
apps/studio.giselles.ai/lib/vector-stores/document/ingest/ingest-document.ts (1)

283-284: Redundant ?? undefined with optional chaining.

The ?? undefined is redundant since telemetryContext?.team.activeCustomerId already evaluates to undefined when the property is not accessible.

Apply this diff to simplify:

-					xStripeCustomerId:
-						telemetryContext?.team.activeCustomerId ?? undefined,
+					xStripeCustomerId: telemetryContext?.team.activeCustomerId,
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a4d4bd0 and 7797543.

📒 Files selected for processing (6)
  • apps/studio.giselles.ai/app/giselle.ts (4 hunks)
  • apps/studio.giselles.ai/lib/generation-metadata.ts (1 hunks)
  • apps/studio.giselles.ai/lib/trace.ts (1 hunks)
  • apps/studio.giselles.ai/lib/vector-stores/document/ingest/generate-embeddings.ts (3 hunks)
  • apps/studio.giselles.ai/lib/vector-stores/document/ingest/ingest-document.ts (1 hunks)
  • apps/studio.giselles.ai/trigger/generate-content-job.ts (3 hunks)
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-08-19T02:30:10.738Z
Learnt from: satococoa
Repo: giselles-ai/giselle PR: 1663
File: packages/rag/src/query-service/postgres/index.ts:206-210
Timestamp: 2025-08-19T02:30:10.738Z
Learning: The multi-embedding backend currently only supports 3072 and 1536 dimensions. The hardcoded embedding cast logic in packages/rag/src/query-service/postgres/index.ts is intentionally limited to these two dimension sizes.

Applied to files:

  • apps/studio.giselles.ai/lib/vector-stores/document/ingest/generate-embeddings.ts
📚 Learning: 2025-11-13T08:16:38.293Z
Learnt from: shige
Repo: giselles-ai/giselle PR: 2172
File: packages/rag/src/embedder/gateway.ts:26-28
Timestamp: 2025-11-13T08:16:38.293Z
Learning: In packages/rag/src/embedder/gateway.ts, the toGatewayModelId function correctly uses forward slash format (provider/model) which matches the ai-sdk/gateway SDK's GatewayEmbeddingModelId type definition. Do not suggest changing this to colon format.

Applied to files:

  • apps/studio.giselles.ai/lib/vector-stores/document/ingest/generate-embeddings.ts
📚 Learning: 2025-11-13T08:16:38.293Z
Learnt from: shige
Repo: giselles-ai/giselle PR: 2172
File: packages/rag/src/embedder/gateway.ts:26-28
Timestamp: 2025-11-13T08:16:38.293Z
Learning: In packages/rag/src/embedder/profiles.ts, createEmbedderFromProfile already validates embedding profiles using isGatewaySupportedEmbeddingProfile before calling createGatewayEmbedder. Additional validation inside createGatewayEmbedder would be redundant.

Applied to files:

  • apps/studio.giselles.ai/lib/vector-stores/document/ingest/generate-embeddings.ts
🔇 Additional comments (7)
apps/studio.giselles.ai/lib/generation-metadata.ts (1)

10-10: LGTM!

The activeCustomerId field addition is properly typed as a nullable string, consistent with the subscriptionId field above it.

apps/studio.giselles.ai/trigger/generate-content-job.ts (2)

18-18: LGTM!

The activeCustomerId field addition to the schema is properly typed and consistent with the GenerationMetadata schema.


47-48: LGTM!

The activeCustomerId is correctly propagated to traceGenerationForTeam in both success (onComplete) and error (onError) handlers.

Also applies to: 63-64

apps/studio.giselles.ai/lib/trace.ts (1)

10-13: LGTM!

The TeamForPlan type correctly includes activeCustomerId in the picked fields from CurrentTeam.

apps/studio.giselles.ai/app/giselle.ts (3)

77-80: LGTM!

The TeamForPlan type correctly includes activeCustomerId, consistent with the type definition in apps/studio.giselles.ai/lib/trace.ts.


283-284: LGTM!

The activeCustomerId is correctly included when constructing the team object from parsed metadata in the embedding callback.


420-420: LGTM!

The activeCustomerId is correctly propagated to the generate-content trigger in both github-app and stage/studio flows.

Also applies to: 443-443

Include activeCustomerId in the metadata passed to traceGeneration and traceEmbedding functions, enabling customer-level tracking in Langfuse for both text generation and embedding operations.

Changes:
- Add customerId to traceGenerationForTeam metadata (lib/trace.ts)
- Add customerId to traceEmbeddingForTeam baseMetadata (app/giselle.ts)

This ensures Stripe Customer ID is tracked consistently across all telemetry data, alongside subscriptionId.
@shige shige marked this pull request as draft November 25, 2025 03:23
@shige shige force-pushed the add-xstripe-customer-id-header-to-gateway branch from a4d4bd0 to da4f6e0 Compare November 25, 2025 03:32
Base automatically changed from add-xstripe-customer-id-header-to-gateway to main November 25, 2025 08:31
@shige
Copy link
Member Author

shige commented Nov 27, 2025

Rework:
#2254
#2272
#2289

@shige shige closed this Nov 27, 2025
@shige shige deleted the pass-active-customer-id-through-gateway branch November 27, 2025 14:31
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.

2 participants