Skip to content

fix(bubble-runtime): add Promise.all instrumentation support with map callbacks#250

Merged
zhubzy merged 7 commits intomainfrom
fix/more-loggin-instrumentation
Dec 28, 2025
Merged

fix(bubble-runtime): add Promise.all instrumentation support with map callbacks#250
zhubzy merged 7 commits intomainfrom
fix/more-loggin-instrumentation

Conversation

@zhubzy
Copy link
Contributor

@zhubzy zhubzy commented Dec 28, 2025

Summary

Related Issues

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Refactor
  • Other (please describe):

Checklist

  • My code follows the code style of this project
  • I have added appropriate tests for my changes
  • I have run pnpm check and all tests pass
  • I have tested my changes locally
  • I have linked relevant issues
  • I have added screenshots for UI changes (if applicable)

Screenshots (if applicable)

Additional Context

Summary by CodeRabbit

  • New Features

    • Studio hooks: added updateUpdatedAt and date-based revalidation to improve execution/run validation.
  • Bug Fixes

    • Fixed script sanitization to prevent unintended pattern replacements in placeholder handling.
  • Tests

    • Added Promise.all and complex-script test fixtures and reactivated related execution tests.
  • Chores

    • Improved error recording during script execution and reduced token-usage console noise via a configurable flag.

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

Copilot AI review requested due to automatic review settings December 28, 2025 17:08
@coderabbitai
Copy link

coderabbitai bot commented Dec 28, 2025

Caution

Review failed

The pull request is closed.

📝 Walkthrough

Walkthrough

Adds conditional token-usage logging, call-site deduplication and concise-arrow inline replacement for Promise.all elements, propagates callText through injector, records dynamic-import parsing errors, fixes placeholder restoration in script sanitization, adds two complex test fixtures, and updates tests and studio hooks related to revalidation and updatedAt handling.

Changes

Cohort / File(s) Summary
Logging & Feature Flag
packages/bubble-core/src/logging/BubbleLogger.ts
Added SHOULD_ENABLE_TOKEN_USAGE_LOGGING_IN_CONSOLE (false) and guarded token-usage console/log emissions so token details are only logged when the flag is true.
Parser — Call-site deduplication
packages/bubble-runtime/src/extraction/BubbleParser.ts
Added processedCallSiteIndexes: Map<string, number>, extended getNextInvocationIndex to accept callExprStartOffset, reset map between parses, and capture callRange/callText for concise arrow-function Promise.all elements.
Injector — Inline replacement & callText
packages/bubble-runtime/src/injection/LoggerInjector.ts
Propagated optional callText through invocation details, updated injectLoggingForInvocation and injectPromiseAllElementLogging signatures, and added inline async-IIFE replacement scaffolding (indentation/prevInvocationVar) when callText is present.
Runtime — Error recording
packages/bubble-runtime/src/runtime/BubbleRunner.ts
On dynamic import failure in runAll, push formatted error into this.bubbleScript.parsingErrors in addition to logging and throwing.
Sanitizer — Placeholder restoration fix
packages/bubble-runtime/src/utils/sanitize-script.ts
Restored placeholders using a function-based replacement (() => placeholders[i]) to avoid $-pattern interpretation during String.replace.
Tests — Fixtures & suite
packages/bubble-runtime/tests/fixtures/index.ts
packages/bubble-runtime/src/runtime/BubbleRunner.test.ts
Added string-literal-complex and promises-all-map fixture keys; re-enabled/added tests and improved diagnostic printing of parsing errors in expectValidScript.
New fixtures — Promise.all / map flow
packages/bubble-runtime/tests/fixtures/promises-all-map.ts
New ExecutionMonitorCron flow: fetches recent executions from Postgres, groups by user, analyzes groups in parallel with Gemini AI, and sends aggregated Slack reports (full orchestration + error handling).
New fixtures — String literal complex flow
packages/bubble-runtime/tests/fixtures/string-literal-complex.ts
New AmazonProductSourcingFlow webhook flow: scrapes Amazon bestsellers via Apify, finds suppliers per product using ResearchAgentTool, compiles structured output and handles errors.
Studio hooks — revalidation & updatedAt
apps/bubble-studio/src/hooks/useRunExecution.ts
apps/bubble-studio/src/hooks/useValidateCode.ts
apps/bubble-studio/src/hooks/useBubbleFlow.ts
Added date-based revalidation check and combined validation condition in useRunExecution; added updateUpdatedAt to useBubbleFlow and invoked it on successful validate-with-sync in useValidateCode.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • iqbalbhatti49

Poem

🐇 Nimble paws tap at the code tonight,

Call sites tidy, inline hops just right.
Tokens whisper only when asked to speak,
Errors caught in pages once too meek.
Hooray — the runtime hums, cheerful and bright!

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title directly describes the main feature: adding Promise.all instrumentation support with map callbacks, which is the central focus of the changeset across parser, injector, and test files.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 779e9ce and 6e5b15c.

📒 Files selected for processing (3)
  • apps/bubble-studio/src/hooks/useBubbleFlow.ts
  • apps/bubble-studio/src/hooks/useRunExecution.ts
  • apps/bubble-studio/src/hooks/useValidateCode.ts

Comment @coderabbitai help to get the list of available commands and usage tips.

@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Dec 28, 2025

Deploying bubblelab-documentation with  Cloudflare Pages  Cloudflare Pages

Latest commit: 6e5b15c
Status:⚡️  Build in progress...

View logs

@bubblelab-pearl
Copy link
Contributor

Suggested PR title from Pearl

Title: feat(parser): add comprehensive Promise.all pattern support with map callbacks

Body:

Summary

Enhances the BubbleParser to fully support Promise.all patterns with array.map() callbacks, including both expression-body and block-body arrow functions. Fixes invocation index double-counting and improves logging controls.

Changes

Parser Enhancements

  • Promise.all pattern detection: Added support for .map() callbacks in Promise.all arrays

    • Handles arrow function expression bodies: arr.map(x => this.method(x))
    • Handles arrow function block bodies: arr.map(x => { return this.method(x); })
    • Supports both literal arrays and variable arrays as map sources
    • Extracts callback expressions and creates proper parallel execution nodes
  • Invocation tracking improvements:

    • Added processedCallSiteIndexes map to prevent double-counting when same call site is processed multiple times
    • Modified getNextInvocationIndex() to accept callExprStartOffset for call site deduplication
    • Ensures consistent invocation indices across .map() callback processing and Promise.all resolution
  • Array element extraction: Refactored findArrayPushCalls() to findArrayElements() to handle both:

    • Array .push() pattern: arr.push(item1, item2, ...)
    • Array .map() pattern: const promises = items.map(item => this.process(item))

Logger Injection

  • Enhanced injectPromiseAllElementWrapper() to support inline replacement for arrow function expression bodies
  • Added callText parameter for precise code replacement in inline contexts
  • Wraps method calls in async IIFEs with proper logging instrumentation

Bug Fixes

  • fix(sanitize): prevent $ character misinterpretation in string replacements

    • Use function replacement to avoid $ being treated as special replacement pattern
    • Prevents substitution errors like $&, $$ in template strings
  • fix(runtime): add parsing errors to error list on dynamic import failure

    • Improves error visibility when script execution fails
  • fix(logger): remove debug console.log and add toggle for token usage logging

    • Added SHOULD_ENABLE_TOKEN_USAGE_LOGGING_IN_CONSOLE constant (default: false)
    • Reduces console noise in production

Testing

  • Added comprehensive test suite for Promise.all parsing patterns:

    • Direct array literal: Promise.all([this.a(), this.b()])
    • Array push pattern: arr.push(this.a()); Promise.all(arr)
    • Array map with expression body: arr.map(x => this.process(x))
    • Array map with block body: arr.map(x => { return this.process(x); })
    • Array map with variable arrays
  • Added test fixtures:

    • promise-all-patterns.ts: Multiple Promise.all test cases
    • promises-all-map.ts: Real-world execution monitor cron example
    • string-literal-complex.ts: Complex Amazon product sourcing flow
  • Un-skipped mapping-function-call test (now passing)

Technical Details

New helper methods in BubbleParser:

  • extractCallbackExpression(): Extracts expression from arrow/function callbacks
  • getSourceArrayElements(): Retrieves elements from literal or variable arrays
  • findReturnStatements(): Finds all return statements in block bodies

Breaking Changes

None

Related Issues

Closes issues related to Promise.all with .map() not being detected as parallel execution

@zhubzy zhubzy changed the title Fix/more loggin instrumentation feat(parser): add Promise.all instrumentation support with map callbacks Dec 28, 2025
@zhubzy zhubzy changed the title feat(parser): add Promise.all instrumentation support with map callbacks fix(bubble-runtime): add Promise.all instrumentation support with map callbacks Dec 28, 2025
@cloudflare-workers-and-pages
Copy link

Deploying bubble-studio with  Cloudflare Pages  Cloudflare Pages

Latest commit: 779e9ce
Status: ✅  Deploy successful!
Preview URL: https://2c485527.bubble-studio.pages.dev
Branch Preview URL: https://fix-more-loggin-instrumentat.bubble-studio.pages.dev

View logs

Copy link

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 enhances logging instrumentation for BubbleFlow execution, specifically improving support for Promise.all patterns and fixing string replacement bugs. The changes enable better tracking and debugging of parallel execution flows.

Key Changes

  • Added support for parsing and instrumenting Promise.all patterns with .map() callbacks in arrow function expression bodies
  • Fixed string replacement bug in sanitize-script that could cause issues with special characters like $
  • Improved error tracking by logging dynamic import failures to parsingErrors array

Reviewed changes

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

Show a summary per file
File Description
packages/bubble-runtime/tests/fixtures/string-literal-complex.ts New test fixture demonstrating complex Amazon product sourcing flow with nested API calls
packages/bubble-runtime/tests/fixtures/promises-all-map.ts New test fixture for execution monitoring using Promise.all with .map() pattern
packages/bubble-runtime/tests/fixtures/promise-all-patterns.ts New comprehensive test fixture covering various Promise.all usage patterns
packages/bubble-runtime/tests/fixtures/index.ts Exports for new test fixtures
packages/bubble-runtime/src/utils/sanitize-script.ts Fixed replacement string handling to avoid $ special character interpretation
packages/bubble-runtime/src/runtime/BubbleRunner.ts Added parsing error tracking for dynamic import failures
packages/bubble-runtime/src/runtime/BubbleRunner.test.ts Added tests for new Promise.all patterns and re-enabled previously skipped test
packages/bubble-runtime/src/injection/LoggerInjector.ts Enhanced Promise.all element logging with inline replacement support for arrow functions
packages/bubble-runtime/src/extraction/BubbleParser.ts Added .map() callback parsing, deduplication logic for invocation indexes, and helper methods
packages/bubble-runtime/src/extraction/BubbleParser.test.ts Added comprehensive tests for Promise.all parsing patterns
packages/bubble-core/src/logging/BubbleLogger.ts Removed debug console.log and gated token usage logging behind feature flag
Comments suppressed due to low confidence (2)

packages/bubble-runtime/src/injection/LoggerInjector.ts:717

  • There is code duplication in this method. The async IIFE construction code (lines 678-690) is duplicated in the wrappedLines array (lines 706-717). Consider extracting this into a helper function or reusing the asyncIIFE variable that is already constructed. The duplication makes maintenance harder and increases the risk of inconsistencies if one block is updated without the other.
    const wrappedLines = [
      `${indentation}(async () => {`,
      `${innerIndent}const __functionCallStart_${variableId} = Date.now();`,
      `${innerIndent}const ${argsVar} = ${argsArray};`,
      `${innerIndent}__bubbleFlowSelf.logger?.logFunctionCallStart(${variableId}, '${methodName}', ${argsVar}, ${lineNumber});`,
      `${innerIndent}const ${prevInvocationVar} = __bubbleFlowSelf?.__setInvocationCallSiteKey?.(${callSiteKeyLiteral});`,
      `${innerIndent}const ${resultVar} = await this.${methodName}(${args});`,
      `${innerIndent}const ${durationVar} = Date.now() - __functionCallStart_${variableId};`,
      `${innerIndent}__bubbleFlowSelf.logger?.logFunctionCallComplete(${variableId}, '${methodName}', ${resultVar}, ${durationVar}, ${lineNumber});`,
      `${innerIndent}__bubbleFlowSelf?.__restoreInvocationCallSiteKey?.(${prevInvocationVar});`,
      `${innerIndent}return ${resultVar};`,
      `${indentation}})()${trailingComma ? ',' : ''}`,

packages/bubble-runtime/src/extraction/BubbleParser.ts:4076

  • The findReturnStatements method walks the entire block statement AST and collects all return statements, but it doesn't stop at nested function boundaries. This means if there's a nested arrow function or function expression with its own return statement, those will be incorrectly included. The walk should skip traversing into nested ArrowFunctionExpression and FunctionExpression nodes to only collect return statements from the current function scope.
  private findReturnStatements(
    block: TSESTree.BlockStatement
  ): TSESTree.ReturnStatement[] {
    const returns: TSESTree.ReturnStatement[] = [];
    const walk = (node: TSESTree.Node) => {
      if (node.type === 'ReturnStatement') {
        returns.push(node);
      }
      for (const key in node) {
        const child = (node as any)[key];
        if (Array.isArray(child)) child.forEach(walk);
        else if (child?.type) walk(child);
      }
    };
    walk(block);
    return returns;
  }

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: 3

Caution

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

⚠️ Outside diff range comments (1)
packages/bubble-runtime/src/injection/LoggerInjector.ts (1)

355-377: Unconditionally wrapping arrow function callbacks in async IIFE changes semantics for non-Promise.all cases

The code correctly identifies arrow functions with concise bodies in BubbleParser.ts (line 1277) and routes them through injectPromiseAllElementLogging for inline instrumentation via callText. However, there is a semantic risk:

In BubbleParser.ts, any arrow function with a concise body (e.g., arr.map(item => this.transform(item))) gets invocationContext = 'promise_all_element' regardless of whether that arrow is actually part of a Promise.all call. Only a separate check (line 1331) validates true Promise.all array elements via isPromiseAllArrayElement.

In LoggerInjector.ts lines 685 and 713, injectPromiseAllElementLogging unconditionally injects await this.${methodName}(...) into the async IIFE wrapper. The hasAwait flag is captured in BubbleParser.ts but never passed through to the injection function, so the original await semantics are lost.

Impact: For items.map(item => this.sync(item)) where sync is synchronous and not awaited, after instrumentation the callback returns Promise[] instead of Value[], which breaks downstream code expecting the original return type.

Recommendation: Either narrow arrow function detection to confirm the arrow is actually used in Promise.all context, or pass hasAwait and method async information to injectPromiseAllElementLogging and only inject await when the original call was already asynchronous, falling back to synchronous wrapping for synchronous callbacks.

🧹 Nitpick comments (5)
packages/bubble-runtime/src/runtime/BubbleRunner.test.ts (1)

15-18: Parsing error logging in expectValidScript

Logging runner.bubbleScript.parsingErrors before asserting length is 0 is useful for debugging dynamic import / parsing failures; behavior is fine as-is. If you ever reuse this helper for negative/expected-failure tests, consider wiring this under the logOnError flag to keep test output quieter, but not required now.

packages/bubble-core/src/logging/BubbleLogger.ts (1)

5-5: Console token-usage logging flag is good; consider making it configurable

Gating the logTokenUsage info log behind SHOULD_ENABLE_TOKEN_USAGE_LOGGING_IN_CONSOLE removes noisy per-call logs while preserving aggregated usage via addServiceUsage, which is a nice improvement. Longer term, you may want this to be driven by LoggerConfig or an env toggle rather than a hardcoded constant so it can be enabled in specific environments without code changes.

Also applies to: 376-388

packages/bubble-runtime/tests/fixtures/promises-all-map.ts (1)

1-181: ExecutionMonitorCron fixture correctly exercises Promise.all + map pattern

The fixture cleanly wires together PostgreSQLBubble, AIAgentBubble, and SlackBubble with a Promise.all(userGroups.entries().map(...)) pattern, which is ideal for exercising the new parser/injector behavior. The parameterized query and error handling are reasonable for a test fixture. If you later promote this pattern to production code, you might tighten the Record<string, unknown> typings (e.g., a typed row interface for execution.email, flow_name, etc.), but it’s not required for test coverage here.

packages/bubble-runtime/src/runtime/BubbleRunner.ts (1)

462-472: Recording dynamic import failures in parsingErrors is useful—watch exposure of raw messages

Pushing Dynamic import failed: <message> into this.bubbleScript.parsingErrors makes it much easier for tests and tooling (e.g., expectValidScript) to surface syntax/import issues, which is a nice improvement. Just double-check whether parsingErrors are ever sent to clients or logs where absolute temp file paths from the import error message might be visible; if so, consider passing the message through your existing getSafeErrorMessage-style sanitization or replacing it with a more generic description.

packages/bubble-runtime/tests/fixtures/string-literal-complex.ts (1)

124-130: Consider simplifying the type assertion.

The nested type assertion is fragile and could mask runtime type mismatches. A cleaner approach would extract the suppliers with optional chaining and a fallback.

🔎 Proposed simplification
-    return (
-      (
-        result.data?.result as {
-          suppliers: { name: string; price: number; url: string }[];
-        }
-      )?.suppliers || []
-    );
+    const data = result.data?.result as { suppliers?: { name: string; price: number; url: string }[] } | undefined;
+    return data?.suppliers ?? [];
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7a586a2 and 779e9ce.

📒 Files selected for processing (9)
  • packages/bubble-core/src/logging/BubbleLogger.ts
  • packages/bubble-runtime/src/extraction/BubbleParser.ts
  • packages/bubble-runtime/src/injection/LoggerInjector.ts
  • packages/bubble-runtime/src/runtime/BubbleRunner.test.ts
  • packages/bubble-runtime/src/runtime/BubbleRunner.ts
  • packages/bubble-runtime/src/utils/sanitize-script.ts
  • packages/bubble-runtime/tests/fixtures/index.ts
  • packages/bubble-runtime/tests/fixtures/promises-all-map.ts
  • packages/bubble-runtime/tests/fixtures/string-literal-complex.ts
🧰 Additional context used
🧠 Learnings (14)
📓 Common learnings
Learnt from: CR
Repo: bubblelabai/BubbleLab PR: 0
File: .cursor/rules/bubblelab.mdc:0-0
Timestamp: 2025-12-22T09:55:47.873Z
Learning: Applies to packages/bubble-runtime/src/extraction/README.md : Refer to packages/bubble-runtime/src/extraction/README.md for information about bubble parsing, dependency graphs, and per-invocation cloning
📚 Learning: 2025-12-19T03:17:06.825Z
Learnt from: CR
Repo: bubblelabai/BubbleLab PR: 0
File: .cursor/rules/bundling.mdc:0-0
Timestamp: 2025-12-19T03:17:06.825Z
Learning: Applies to packages/bubble-core/dist/**/*.d.ts : All external imports (except relative imports) must be removed from the bundled output to prevent circular processing and external dependency issues

Applied to files:

  • packages/bubble-runtime/src/runtime/BubbleRunner.ts
  • packages/bubble-runtime/tests/fixtures/index.ts
  • packages/bubble-runtime/src/extraction/BubbleParser.ts
  • packages/bubble-runtime/src/runtime/BubbleRunner.test.ts
📚 Learning: 2025-12-19T03:17:06.825Z
Learnt from: CR
Repo: bubblelabai/BubbleLab PR: 0
File: .cursor/rules/bundling.mdc:0-0
Timestamp: 2025-12-19T03:17:06.825Z
Learning: Applies to packages/bubble-core/src/index.ts : All new types and classes added to bubble-core must be exported from `packages/bubble-core/src/index.ts` to ensure they are included in the generated bundle

Applied to files:

  • packages/bubble-runtime/src/runtime/BubbleRunner.ts
  • packages/bubble-runtime/tests/fixtures/index.ts
  • packages/bubble-runtime/tests/fixtures/string-literal-complex.ts
  • packages/bubble-runtime/src/runtime/BubbleRunner.test.ts
📚 Learning: 2025-12-19T03:17:06.825Z
Learnt from: CR
Repo: bubblelabai/BubbleLab PR: 0
File: .cursor/rules/bundling.mdc:0-0
Timestamp: 2025-12-19T03:17:06.825Z
Learning: Applies to packages/bubble-core/scripts/bubble-bundler.ts : The bundler script at `packages/bubble-core/scripts/bubble-bundler.ts` must use absolute file paths as cache keys to prevent collisions between packages with identically named files

Applied to files:

  • packages/bubble-runtime/src/runtime/BubbleRunner.ts
  • packages/bubble-runtime/tests/fixtures/index.ts
  • packages/bubble-runtime/src/runtime/BubbleRunner.test.ts
📚 Learning: 2025-12-22T09:55:47.873Z
Learnt from: CR
Repo: bubblelabai/BubbleLab PR: 0
File: .cursor/rules/bubblelab.mdc:0-0
Timestamp: 2025-12-22T09:55:47.873Z
Learning: Applies to packages/bubble-runtime/src/extraction/README.md : Refer to packages/bubble-runtime/src/extraction/README.md for information about bubble parsing, dependency graphs, and per-invocation cloning

Applied to files:

  • packages/bubble-runtime/src/runtime/BubbleRunner.ts
  • packages/bubble-runtime/src/extraction/BubbleParser.ts
  • packages/bubble-runtime/src/runtime/BubbleRunner.test.ts
📚 Learning: 2025-12-19T03:17:06.825Z
Learnt from: CR
Repo: bubblelabai/BubbleLab PR: 0
File: .cursor/rules/bundling.mdc:0-0
Timestamp: 2025-12-19T03:17:06.825Z
Learning: Applies to packages/bubble-core/dist/**/*.d.ts : The type bundling system for Monaco Editor must process TypeScript declaration files (.d.ts) and inline all dependencies into a single self-contained bundle in `packages/bubble-core/dist/bubble-bundle.d.ts`

Applied to files:

  • packages/bubble-runtime/src/runtime/BubbleRunner.ts
  • packages/bubble-runtime/tests/fixtures/index.ts
  • packages/bubble-runtime/tests/fixtures/string-literal-complex.ts
  • packages/bubble-runtime/src/runtime/BubbleRunner.test.ts
📚 Learning: 2025-12-19T03:17:06.825Z
Learnt from: CR
Repo: bubblelabai/BubbleLab PR: 0
File: .cursor/rules/bundling.mdc:0-0
Timestamp: 2025-12-19T03:17:06.825Z
Learning: Applies to apps/bubble-studio/src/components/MonacoEditor.tsx : The Monaco Editor integration in `apps/bubble-studio/src/components/MonacoEditor.tsx` must fetch the bundled types from `/bubble-types.txt`, wrap them in a module declaration for `bubblelab/bubble-core`, and add them to Monaco's TypeScript type system

Applied to files:

  • packages/bubble-runtime/src/runtime/BubbleRunner.ts
  • packages/bubble-runtime/tests/fixtures/index.ts
📚 Learning: 2025-12-19T03:17:06.825Z
Learnt from: CR
Repo: bubblelabai/BubbleLab PR: 0
File: .cursor/rules/bundling.mdc:0-0
Timestamp: 2025-12-19T03:17:06.825Z
Learning: Applies to apps/bubble-studio/public/bubble-types.txt : The bundle file at `apps/bubble-studio/public/bubble-types.txt` must be kept synchronized with `packages/bubble-core/dist/bubble-bundle.d.ts` after each build

Applied to files:

  • packages/bubble-runtime/src/runtime/BubbleRunner.ts
  • packages/bubble-runtime/tests/fixtures/index.ts
📚 Learning: 2025-12-19T03:17:06.825Z
Learnt from: CR
Repo: bubblelabai/BubbleLab PR: 0
File: .cursor/rules/bundling.mdc:0-0
Timestamp: 2025-12-19T03:17:06.825Z
Learning: The bundle process must run the TypeScript compiler (`tsc`) before executing the bundler script (`tsx scripts/bubble-bundler.ts`) to ensure all .d.ts files are generated

Applied to files:

  • packages/bubble-runtime/src/runtime/BubbleRunner.ts
  • packages/bubble-runtime/src/runtime/BubbleRunner.test.ts
📚 Learning: 2025-12-19T03:17:06.825Z
Learnt from: CR
Repo: bubblelabai/BubbleLab PR: 0
File: .cursor/rules/bundling.mdc:0-0
Timestamp: 2025-12-19T03:17:06.825Z
Learning: When adding new types to `bubblelab/shared-schemas`, they are automatically included in the bundle without requiring manual configuration changes

Applied to files:

  • packages/bubble-runtime/tests/fixtures/index.ts
📚 Learning: 2025-12-22T09:55:47.873Z
Learnt from: CR
Repo: bubblelabai/BubbleLab PR: 0
File: .cursor/rules/bubblelab.mdc:0-0
Timestamp: 2025-12-22T09:55:47.873Z
Learning: Applies to packages/bubble-shared-schemas/src/bubbleflow-generation-prompts.ts : Refer to packages/bubble-shared-schemas/src/bubbleflow-generation-prompts.ts for documentation on how bubble flow is supposed to be generated

Applied to files:

  • packages/bubble-runtime/tests/fixtures/promises-all-map.ts
  • packages/bubble-runtime/tests/fixtures/string-literal-complex.ts
  • packages/bubble-runtime/src/runtime/BubbleRunner.test.ts
📚 Learning: 2025-12-19T03:16:48.801Z
Learnt from: CR
Repo: bubblelabai/BubbleLab PR: 0
File: .cursor/rules/api.mdc:0-0
Timestamp: 2025-12-19T03:16:48.801Z
Learning: Applies to **/bubblelab-api/**/*.test.{js,ts} : Reference webhook.test as the example for how backend tests should be written

Applied to files:

  • packages/bubble-runtime/tests/fixtures/string-literal-complex.ts
  • packages/bubble-runtime/src/runtime/BubbleRunner.test.ts
📚 Learning: 2025-12-19T03:16:48.801Z
Learnt from: CR
Repo: bubblelabai/BubbleLab PR: 0
File: .cursor/rules/api.mdc:0-0
Timestamp: 2025-12-19T03:16:48.801Z
Learning: Applies to **/packages/bubble-shared-schemas/**/*.{ts,tsx} : Write shared schemas between frontend and backend in `/packages/bubble-shared-schemas` directory

Applied to files:

  • packages/bubble-runtime/tests/fixtures/string-literal-complex.ts
📚 Learning: 2025-12-19T03:16:48.801Z
Learnt from: CR
Repo: bubblelabai/BubbleLab PR: 0
File: .cursor/rules/api.mdc:0-0
Timestamp: 2025-12-19T03:16:48.801Z
Learning: Applies to **/bubblelab-api/**/*.test.{js,ts} : Use `pnpm bun test` command to run backend tests to ensure setup files are properly loaded

Applied to files:

  • packages/bubble-runtime/src/runtime/BubbleRunner.test.ts
🧬 Code graph analysis (1)
packages/bubble-runtime/tests/fixtures/promises-all-map.ts (2)
packages/bubble-shared-schemas/src/trigger.ts (1)
  • CronEvent (58-62)
packages/bubble-core/src/index.ts (2)
  • BubbleFlow (19-19)
  • PostgreSQLBubble (34-34)
⏰ 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). (2)
  • GitHub Check: test
  • GitHub Check: Cloudflare Pages: bubblelab-documentation
🔇 Additional comments (6)
packages/bubble-runtime/src/runtime/BubbleRunner.test.ts (1)

523-560: New flow tests give good coverage for map + complex string cases

Re‑enabling the mapping-function-call test and adding the promises-all-map and string-literal-complex flow tests is a solid way to exercise the new parser/injector behavior. The pattern of runAll + expectValidScript + result existence aligns with existing integration-style tests and looks consistent.

packages/bubble-runtime/src/utils/sanitize-script.ts (1)

57-64: Safe placeholder restoration avoids $ replacement pitfalls

Switching placeholder restoration to a function-based replacement correctly avoids $-pattern interpretation in replacement strings while preserving existing behavior. This is a solid, low-risk fix.

packages/bubble-runtime/tests/fixtures/index.ts (1)

72-74: New fixtures wired correctly into the registry

Adding string-literal-complex and promises-all-map to the fixtures map keeps FixtureName in sync with the new .ts files and allows the new BubbleRunner tests to load them via getFixture without any further changes. Looks good.

packages/bubble-runtime/tests/fixtures/string-literal-complex.ts (3)

1-7: LGTM!

Imports are appropriate for the workflow implementation. All imported symbols are used in the file.


9-44: LGTM!

Well-documented interfaces with proper typing. The @canBeFile annotations and field descriptions provide good clarity for payload configuration.


161-179: Sequential processing is acceptable for this fixture.

The for...of loop processes products sequentially. While Promise.all would be more performant, this pattern is appropriate for a test fixture that validates sequential async instrumentation paths (complementing the promises-all-map.ts fixture that covers parallel patterns).

Comment on lines +56 to +63
/**
* Track which call expressions have been assigned an invocation index.
* Key: `methodName:startOffset` (using AST range start position)
* Value: the assigned invocation index
* This prevents double-counting when the same call site is processed multiple times
* (e.g., once in .map() callback processing, again in Promise.all resolution)
*/
private processedCallSiteIndexes: Map<string, number> = new Map();
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Guard against return; (no value) in extractCallbackExpression to avoid crashes

The new helpers for .map-based Promise.all detection and call-site dedupe generally look good, and using processedCallSiteIndexes keyed by methodName:startOffset is a reasonable way to reuse invocation indices across multiple passes. One edge case, though:

  • In extractCallbackExpression, when handling block-bodied callbacks you do:
const returns = this.findReturnStatements(callback.body);
return returns[0]?.argument as TSESTree.Expression | null;

But ReturnStatement.argument can be null (e.g., return;). In that case callbackExpr will be null, later pushed into elements in findArrayElements, and eventually passed to detectFunctionCall / buildParallelExecutionNode, which expect a real TSESTree.Expression and will blow up on expr.type.

Suggestion: treat callbacks with only return; (or no return at all) as having no usable element expression:

const returns = this.findReturnStatements(callback.body);
const firstWithArg = returns.find(r => r.argument != null);
if (!firstWithArg || !firstWithArg.argument) {
  return null;
}
return firstWithArg.argument as TSESTree.Expression;

and then skip those entries in findArrayElements when callbackExpr is null. That keeps the parser robust for map callbacks that do side effects or explicit return; without a value.

Also applies to: 267-268, 3734-3737, 4198-4231, 3975-3993, 4061-4076

🤖 Prompt for AI Agents
In packages/bubble-runtime/src/extraction/BubbleParser.ts around lines 56 to 63,
guard extractCallbackExpression from returning a null/undefined
ReturnStatement.argument (e.g., `return;`) by selecting the first
ReturnStatement that has a non-null argument and returning its argument,
otherwise return null; then ensure findArrayElements skips null callbackExprs so
you don't push null into elements; apply the same pattern to the other mention
locations (lines ~267-268, 3734-3737, 3975-3993, 4061-4076, 4198-4231) to avoid
passing null expressions into detectFunctionCall/buildParallelExecutionNode.

Comment on lines +98 to +115
const supplierResearch = new ResearchAgentTool({
task: `Find suppliers for the product "${productName}" that offer it at a lower price than ${currency}${amazonPrice}.
Check AliExpress, Alibaba, and general wholesalers. Provide the supplier name, their price, and the product URL.`,
model: 'google/gemini-3-pro-preview',
expectedResultSchema: z.object({
suppliers: z
.array(
z.object({
name: z.string().describe('Name of the supplier or website'),
price: z.number().describe('The price offered by this supplier'),
url: z
.string()
.describe('Direct URL to the product on the supplier website'),
})
)
.describe('A list of alternative suppliers found'),
}),
});
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for ResearchAgentTool implementation and model definitions
echo "=== Searching for ResearchAgentTool class definition ==="
rg -n "class ResearchAgentTool|interface ResearchAgentTool" --type=ts

echo -e "\n=== Searching for model identifiers and validation ==="
rg -n "google/gemini|model.*:" --type=ts -A 2 | head -50

echo -e "\n=== Checking current file for model usage ==="
cat -n packages/bubble-runtime/tests/fixtures/string-literal-complex.ts | sed -n '98,115p'

echo -e "\n=== Searching for other ResearchAgentTool usages ==="
rg -n "ResearchAgentTool" --type=ts -B 2 -A 2

Repository: bubblelabai/BubbleLab

Length of output: 50377


🌐 Web query:

Google Gemini API model identifiers 2024 2025

💡 Result:

Here are the common Gemini API model identifiers used across 2024–2025 (major stable, preview, experimental names and notable variants):

  • gemini-1.5-pro, gemini-1.5-pro-002, gemini-1.5-pro-latest. [1][2]
  • gemini-1.5-flash, gemini-1.5-flash-002, gemini-1.5-flash-8b (and experimental variants). [1][2]
  • gemini-2.0-flash, gemini-2.0-flash-001, gemini-2.0-flash-lite-001. [2][3]
  • gemini-2.5-pro, gemini-2.5-flash, gemini-2.5-flash-lite (and preview suffixes like -preview-09-2025). [2][3][5]
  • gemini-2.5-flash-image (aka “nano banana”) and gemini-2.5-flash-image-preview. [2][5]
  • gemini-exp-* / gemini-exp-1114 / gemini-exp-1121 (experimental releases noted in 2024–2025). [1][2]

Notes / sources:

  • Official Gemini model page and naming/version guidance. [1]
  • Gemini API release notes / changelog (lists specific version IDs, preview/experimental releases, and deprecations through 2025). [2]
  • Vertex AI / Firebase docs showing model IDs available via Vertex/Firebase (Gemini 2.0 / 2.5 names and lifecycle). [3][5]

If you want, I can: (a) return a machine-readable list (JSON) of these IDs, or (b) query the live models.list endpoint and return the exact, currently-available model IDs for your project/region.


Use a valid Gemini model identifier.

The model 'google/gemini-3-pro-preview' is not listed in the official Gemini API documentation. Replace it with a currently supported model such as 'google/gemini-2.5-pro' or 'google/gemini-2.5-flash'.

🤖 Prompt for AI Agents
In packages/bubble-runtime/tests/fixtures/string-literal-complex.ts around lines
98 to 115, the test uses an unsupported Gemini model identifier
'google/gemini-3-pro-preview'; replace it with a valid, supported model such as
'google/gemini-2.5-pro' or 'google/gemini-2.5-flash' in the ResearchAgentTool
instantiation so the test uses an official Gemini model name recognized by the
API.

Comment on lines +137 to +141
async handle(payload: AmazonSourcingPayload): Promise<AmazonSourcingOutput> {
const {
amazonCategoryUrl = 'https://www.amazon.com/Best-Sellers/zgbs',
maxProducts = 5,
} = payload;
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Unused sheetName parameter.

The sheetName field is defined in AmazonSourcingPayload but is not destructured or used in the handle method. If this is intentional (e.g., placeholder for future functionality), consider adding a comment. Otherwise, remove it from the interface.

🤖 Prompt for AI Agents
In packages/bubble-runtime/tests/fixtures/string-literal-complex.ts around lines
137 to 141, the payload defines a sheetName field in AmazonSourcingPayload that
is not being destructured or used in handle; either add sheetName to the
destructuring (e.g., const { amazonCategoryUrl = ..., maxProducts = 5, sheetName
} = payload) and use it appropriately (or add a brief comment explaining it’s
intentionally unused), or remove sheetName from the AmazonSourcingPayload
interface if it’s not needed; update tests/types accordingly to keep signatures
consistent.

@zhubzy zhubzy merged commit 93a8fd4 into main Dec 28, 2025
1 of 3 checks passed
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.

3 participants