Skip to content

Conversation

@potofpie
Copy link
Member

@potofpie potofpie commented Aug 14, 2025

Summary by CodeRabbit

  • New Features

    • Added a --no-build option to both dev and cloud deploy to skip the build/preflight build step.
  • Bug Fixes

    • Improved build error logging and handling so dev server and deploy flows behave more predictably on build failures.
    • Broadened runtime compatibility for fetch/abort detection and adjusted module shim behavior to avoid conflicts.
  • Documentation

    • Updated examples and help text to show --no-build usage.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 14, 2025

Walkthrough

Adds a hidden --no-build flag to dev and cloud commands to optionally skip bundling, refactors dev's build/restart flow into a guarded build closure, adds a bundler debug log on esbuild errors, introduces a node-fetch runtime patch, enhances patch rewriting for JS/TS/const forms, and updates PreflightCheck to accept noBuild.

Changes

Cohort / File(s) Summary
Dev CLI flow
cmd/dev.go
Add hidden --no-build flag; parse early; factor build into var build func(initial bool) bool guarded by noBuild; log and skip build when set; use build(false) for rebuilds; preserve ErrBuildFailed handling.
Cloud CLI / Preflight
cmd/cloud.go, internal/deployer/deployer.go
Add --no-build flag to cloud deploy; read and pass noBuild into PreflightCheck; make bundling conditional on noBuild; update PreflightCheck signature to include noBuild; expand bundler.BundleContext fields.
Bundler logging & errors
internal/bundler/bundler.go
When esbuild reports errors in DevMode, emit ctx.Logger.Debug("build failed: %v", result.Errors) before returning ErrBuildFailed.
Bundler runtime patch
internal/bundler/node-fetch.go
New file registering post-call patch for isAbortSignal in node-fetch v2.7.0 and v3.3.2; patch returns true for truthy original results or when the first arg is an object.
Patch rewriting enhancements
internal/bundler/patch.go
Support JS vs TS-like loaders; detect function and const function-expression forms; preserve export/async; generate appropriate wrapper headers; forward args/await promises; add debug logging.
JS shim global binding
internal/bundler/shim.go
Change embedded shim to set globalThis.__dirname guarded by an existence check instead of a module-local const __dirname binding.

Sequence Diagram(s)

sequenceDiagram
  participant U as User
  participant Dev as dev cmd
  participant B as Bundler
  participant S as Server

  U->>Dev: run dev [--no-build]
  alt no-build = false
    Dev->>B: build(initial=true)
    alt esbuild errors (DevMode)
      B-->>Dev: ErrBuildFailed (ctx.Logger.Debug logged)
      Dev->>Dev: stop spinner, continue (no exit)
    else other bundling error
      B-->>Dev: error -> exit (ErrInvalidConfiguration)
    else success
      B-->>Dev: ok
      Dev->>S: start server
    end
  else no-build = true
    Dev->>Dev: log "Skipping build (no-build flag set)"
    Dev->>S: start server (skip initial build)
  end

  loop file changes
    Dev->>B: build(initial=false) [if building enabled]
    B-->>Dev: ok / ErrBuildFailed / error
    alt ok
      Dev->>S: restart server
    else ErrBuildFailed
      Dev->>Dev: stop spinner, continue (no exit)
    else other error
      Dev->>Dev: exit with configuration error
    end
  end
Loading
sequenceDiagram
  participant U as User
  participant Cloud as cloud cmd
  participant P as Preflight
  participant B as Bundler
  participant D as Deployer

  U->>Cloud: run deploy [--no-build]
  Cloud->>P: PreflightCheck(..., noBuild)
  alt noBuild = false
    P->>B: bundle project
    alt bundle error
      B-->>P: error -> P returns error
    else success
      B-->>P: ok -> P returns mutator
    end
  else noBuild = true
    P-->>Cloud: skip bundling, return mutator
  end
  Cloud->>D: proceed with deploy
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • pec1985
  • robindiddams

Poem

"I hop and whisper: skip the build today 🐇
Global dirname now lights the way.
Patches mend fetch and wrappers play,
Debug peeks when builds go astray,
A tiny thump — the CLI hops on its way."

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between f01ffbc and 8a0bdcc.

📒 Files selected for processing (1)
  • internal/bundler/shim.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • internal/bundler/shim.go
⏰ 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: Build and Test (macos-latest)
  • GitHub Check: Analyze (go)
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch teams-changes

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@coderabbitai coderabbitai bot requested a review from robindiddams August 14, 2025 13:30
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: 2

🧹 Nitpick comments (1)
internal/bundler/bundler.go (1)

298-301: Reduce debug log verbosity; summarize esbuild errors instead of dumping the full slice

In DevMode you already print nicely formatted errors to ctx.Writer. Logging the entire result.Errors slice can be very noisy and hard to read. Prefer logging a concise summary (e.g., count) here.

Apply this diff:

-			ctx.Logger.Debug("build failed: %v", result.Errors)
+			ctx.Logger.Debug("build failed (%d errors)", len(result.Errors))
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled

You can enable these settings in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between d7615cc and d5c1b72.

📒 Files selected for processing (3)
  • cmd/dev.go (4 hunks)
  • internal/bundler/bundler.go (1 hunks)
  • internal/bundler/shim.go (1 hunks)
⏰ 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: Build and Test (macos-latest)
  • GitHub Check: Analyze (go)
🔇 Additional comments (4)
cmd/dev.go (4)

43-45: Examples updated for --no-build flag look good

Nice addition to the usage examples; this improves discoverability of the new workflow.


49-49: Flag retrieval is correct

noBuild, _ := cmd.Flags().GetBool("no-build") aligns with the declared flag and is used consistently below.


198-202: Initial build gating matches the new flag’s intent

Skipping the initial build when --no-build is set is correct, and returning early on a failed initial build keeps UX consistent.


274-275: Flag registration looks correct

The new --no-build flag is properly declared with defaults and help text.

@coderabbitai coderabbitai bot requested review from jhaynie and pec1985 August 14, 2025 16:34
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: 1

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled
  • Linear integration is disabled

You can enable these settings in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between d5c1b72 and 48cb304.

📒 Files selected for processing (4)
  • cmd/cloud.go (3 hunks)
  • internal/bundler/node-fetch.go (1 hunks)
  • internal/bundler/patch.go (2 hunks)
  • internal/deployer/deployer.go (2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
internal/deployer/deployer.go (2)
internal/util/io.go (1)
  • ZipDirCallbackMutator (108-108)
internal/bundler/bundler.go (1)
  • Bundle (426-453)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (go)
🔇 Additional comments (12)
internal/bundler/patch.go (5)

104-104: LGTM - Well-designed JavaScript file detection.

The isJS flag using strings.HasSuffix(args.Path, ".js") provides a clean way to differentiate JavaScript from TypeScript files for loader selection.


108-116: Excellent enhancement to support const variable declarations.

The addition of isConstVariable detection significantly improves the patching system by supporting both function declarations (function foo()) and const variable function assignments (const foo = ()). The fallback logic is well-implemented with proper early exit when neither pattern is found.


125-130: Well-structured function name transformation logic.

The conditional logic for generating newfnname based on isConstVariable correctly handles both function declaration and const variable assignment patterns.


139-144: Smart differentiation between JS and TypeScript wrapper generation.

The wrapper generation logic appropriately handles the differences between JavaScript and TypeScript:

  • JavaScript: Uses arrow function syntax and arguments object
  • TypeScript: Uses traditional function syntax with rest parameters

This addresses the different argument handling capabilities between the two languages.


174-176: Correct loader selection based on file type.

The loader selection logic properly defaults to LoaderJS and switches to LoaderTS for non-JavaScript files, aligning with the file detection logic.

internal/bundler/node-fetch.go (1)

3-17: Well-implemented node-fetch AbortSignal patch.

The patch correctly enhances the isAbortSignal function with additional logic to handle AbortSignal detection. The After hook implementation:

  1. First checks if the original function already returned true
  2. Falls back to constructor name checking for AbortSignal objects
  3. Properly accesses the first argument via _args[0]

This is a solid runtime enhancement that maintains backward compatibility while extending functionality.

cmd/cloud.go (3)

201-201: LGTM - Proper flag extraction.

The noBuild flag is correctly extracted from command line arguments using the standard cobra flag parsing pattern.


312-312: Correct integration with PreflightCheck.

The noBuild parameter is properly passed to PreflightCheck, enabling conditional build behavior based on the command line flag. This aligns with the updated function signature in internal/deployer/deployer.go.


1020-1020: Good flag definition with appropriate default.

The --no-build flag is properly defined with:

  • Appropriate boolean type
  • Sensible default value (false)
  • Clear description of functionality
internal/deployer/deployer.go (3)

71-71: Good API design for conditional building.

The addition of the noBuild bool parameter to PreflightCheck provides a clean way to control build behavior. The parameter is appropriately positioned at the end to maintain backward compatibility concerns.


73-80: Well-structured bundler context initialization.

The BundleContext initialization is comprehensive and includes all necessary fields:

  • Logger for debugging and error reporting
  • ProjectDir for project location
  • Production: true for production builds
  • Proper context and writer setup

81-85: Clean conditional build logic.

The conditional bundling implementation is straightforward and effective:

  • Only runs bundling when noBuild is false
  • Preserves error handling when bundling occurs
  • Maintains the existing error propagation pattern

@coderabbitai coderabbitai bot requested a review from jhaynie August 14, 2025 18:38
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

♻️ Duplicate comments (1)
internal/bundler/patch.go (1)

139-141: Fix the duplicated prefix construction.

The current implementation duplicates the prefix by concatenating "export " with an existing fnprefix that may already contain "async ", resulting in malformed prefixes like "export async async ".

Apply this diff to fix the prefix concatenation:

-		if isExport {
-			fnprefix += "export " + fnprefix
-		}
+		if isExport {
+			fnprefix = "export " + fnprefix
+		}
🧹 Nitpick comments (1)
internal/bundler/node-fetch.go (1)

5-6: Remove debug print statement.

The debug print statement should be removed from production code as it will clutter the output during normal operations.

Apply this diff to remove the debug output:

-func init() {
-	fmt.Println("patching node-fetch")

Alternatively, if debugging output is needed, consider using the logger instead:

-	fmt.Println("patching node-fetch")
+	// Patch registration for node-fetch module
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled

You can enable these settings in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 48cb304 and caa95c5.

📒 Files selected for processing (2)
  • internal/bundler/node-fetch.go (1 hunks)
  • internal/bundler/patch.go (2 hunks)
⏰ 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: Build and Test (macos-latest)
  • GitHub Check: Analyze (go)
🔇 Additional comments (7)
internal/bundler/patch.go (6)

105-105: LGTM! Good file type detection logic.

The isJS flag properly distinguishes between JavaScript and TypeScript files based on the file extension, which drives the appropriate code path selection throughout the patching process.


109-117: LGTM! Good fallback handling for different function declaration patterns.

The code properly handles both traditional function declarations (function fname) and const variable function expressions (const fname = ). The fallback mechanism ensures comprehensive coverage of different JavaScript/TypeScript function declaration patterns.


124-127: LGTM! Good detection of function modifiers and debugging output.

The detection logic for isExport and isArrow is correct and the debugging output will help with troubleshooting patching issues.


129-134: LGTM! Proper handling of different function naming patterns.

The conditional logic correctly generates the appropriate function name format based on whether it's a const variable declaration or a traditional function declaration.


143-152: LGTM! Good wrapper generation for different syntaxes.

The wrapper generation correctly handles different scenarios:

  • JS files with arrow functions get arrow function wrappers
  • JS files with regular functions get regular function wrappers
  • Non-JS (TypeScript) files get traditional function wrappers with proper parameter destructuring
  • Proper argument handling with let args = arguments; for JS and (...args) for TypeScript

182-184: LGTM! Correct loader selection based on file type.

The loader selection properly defaults to LoaderJS and switches to LoaderTS for non-JS files, which aligns with the file type detection logic.

internal/bundler/node-fetch.go (1)

7-21: Please manually verify the node-fetch isAbortSignal patch

I wasn’t able to locate the upstream isAbortSignal implementation locally, so please confirm against node-fetch’s current source:

• Inspect the original isAbortSignal in node-fetch/lib/index.js to ensure your After logic preserves intended behavior
• Remove or replace console.log(_args[0]) before shipping to production
• Verify that treating any object as an abort signal won’t introduce false positives

@potofpie potofpie changed the title Teams changes Changes to make teams work Aug 14, 2025
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: 5

♻️ Duplicate comments (1)
internal/bundler/patch.go (1)

132-149: Fix export/async prefix construction and generate valid wrapper headers for function vs variable declarations

  • Current logic can duplicate tokens and place async in an invalid position (e.g., async const foo = () => {), and will emit invalid JS for non-arrow variable declarations (const foo = () {).
  • Build headers explicitly for each case: function declaration vs. variable declaration, JS vs. TS-like, and properly place export, default, and async.

Apply this diff to replace the prefix/header logic:

-						var fnprefix string
-						if isAsync {
-							fnprefix = "async "
-						}
-						if isExport {
-							fnprefix += "export " + fnprefix
-						}
-						contents = strings.Replace(contents, fnname, newfnname, 1)
-						if isJS {
-							if isArrow {
-								suffix.WriteString(fnprefix + fnname + "() => {\n")
-							} else {
-								suffix.WriteString(fnprefix + fnname + "() {\n")
-							}
-							suffix.WriteString("let args = arguments;\n")
-						} else {
-							suffix.WriteString(fnprefix + fnname + "(...args) {\n")
-						}
+						// Replace the original function name with the internal one
+						contents = strings.Replace(contents, fnname, newfnname, 1)
+
+						// Build wrapper header with correct export/async placement
+						var exportPrefix string
+						if isExport {
+							if isDefault && !isVarDecl {
+								exportPrefix = "export default "
+							} else {
+								exportPrefix = "export "
+							}
+						}
+						if isJS {
+							if isVarDecl {
+								header := exportPrefix + declKeyword + " " + fn + " = "
+								if isAsync {
+									header += "async "
+								}
+								// Use function expression to preserve `arguments` and `this`
+								suffix.WriteString(header + "function() {\n")
+							} else {
+								header := exportPrefix
+								if isAsync {
+									header += "async "
+								}
+								suffix.WriteString(header + "function " + fn + "() {\n")
+							}
+							suffix.WriteString("let args = arguments;\n")
+						} else {
+							if isVarDecl {
+								header := exportPrefix + declKeyword + " " + fn + " = "
+								if isAsync {
+									header += "async "
+								}
+								if isArrow {
+									suffix.WriteString(header + "(...args) => {\n")
+								} else {
+									suffix.WriteString(header + "function(...args) {\n")
+								}
+							} else {
+								header := exportPrefix
+								if isAsync {
+									header += "async "
+								}
+								suffix.WriteString(header + "function " + fn + "(...args) {\n")
+							}
+						}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled

You can enable these settings in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between caa95c5 and f27f788.

📒 Files selected for processing (2)
  • internal/bundler/node-fetch.go (1 hunks)
  • internal/bundler/patch.go (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • internal/bundler/node-fetch.go

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

♻️ Duplicate comments (1)
cmd/dev.go (1)

147-176: Nil-function panic concern resolved; refine skip-build logging and consider no-op build binding.

  • The earlier panic risk due to a nil build func is resolved by always assigning the closure. Good.
  • Current implementation logs “Skipping build…” on every restart in no-build mode, which can get noisy.

Minimal tweak to reduce log noise (log once on initial, debug thereafter):

-        if noBuild {
-            log.Info("Skipping build (no-build flag set)")
-            return true
-        }
+        if noBuild {
+            if initial {
+                log.Info("Skipping build (no-build flag set)")
+            } else {
+                log.Debug("Skipping build (no-build flag set)")
+            }
+            return true
+        }

Optional readability refactor: bind a no-op build function when disabled, removing the need to branch at every call:

-        var build func(initial bool) bool
-
-        build = func(initial bool) bool {
-            if noBuild {
-                log.Info("Skipping build (no-build flag set)")
-                return true
-            }
-            started := time.Now()
-            var ok bool
-            tui.ShowSpinner("Building project ...", func() {
-                if err := bundler.Bundle(bundler.BundleContext{
-                    Context:    ctx,
-                    Logger:     log,
-                    ProjectDir: dir,
-                    Production: false,
-                    DevMode:    true,
-                    Writer:     os.Stdout,
-                }); err != nil {
-                    if err == bundler.ErrBuildFailed {
-                        return
-                    }
-                    errsystem.New(errsystem.ErrInvalidConfiguration, err, errsystem.WithContextMessage(fmt.Sprintf("Failed to bundle project: %s", err))).ShowErrorAndExit()
-                }
-                ok = true
-            })
-            if ok && !initial {
-                log.Info("✨ Built in %s", time.Since(started).Round(time.Millisecond))
-            }
-            return ok
-        }
+        if noBuild {
+            log.Info("Skipping build (no-build flag set)")
+        }
+        build := func(initial bool) bool { return true } // no-op when --no-build
+        if !noBuild {
+            build = func(initial bool) bool {
+                started := time.Now()
+                var ok bool
+                tui.ShowSpinner("Building project ...", func() {
+                    if err := bundler.Bundle(bundler.BundleContext{
+                        Context:    ctx,
+                        Logger:     log,
+                        ProjectDir: dir,
+                        Production: false,
+                        DevMode:    true,
+                        Writer:     os.Stdout,
+                    }); err != nil {
+                        if err == bundler.ErrBuildFailed {
+                            return
+                        }
+                        errsystem.New(errsystem.ErrInvalidConfiguration, err, errsystem.WithContextMessage(fmt.Sprintf("Failed to bundle project: %s", err))).ShowErrorAndExit()
+                    }
+                    ok = true
+                })
+                if ok && !initial {
+                    log.Info("✨ Built in %s", time.Since(started).Round(time.Millisecond))
+                }
+                return ok
+            }
+        }

To ensure no-build mode doesn’t break runtime (e.g., if the run command expects built artifacts), please run:

#!/bin/bash
# Locate CreateRunProjectCmd and inspect how the project is launched.
rg -n "CreateRunProjectCmd" -A 80 internal | sed -n '1,200p'

# Look for indications that runtime depends on build outputs (e.g., dist/, .bundle/)
rg -n "dist/|build/|bundle|esbuild|outdir|outFile" internal -S -A 3

# Check for direct TS runners (tsx/ts-node) that would be compatible with --no-build
rg -n "ts-node|tsx|node --loader|bun run" internal -S -A 3
🧹 Nitpick comments (1)
cmd/dev.go (1)

43-44: Avoid documenting a hidden flag in Examples (inconsistency).

You’re marking --no-build as hidden but showcasing it in the Examples section. This is confusing for users relying on help output.

Apply this diff to remove the hidden flag from the examples (or unhide the flag in init):

   Examples:
     agentuity dev
-    agentuity dev --dir /path/to/project
-    agentuity dev --no-build
+    agentuity dev --dir /path/to/project
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled

You can enable these settings in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between e6f9e27 and 3459ff0.

📒 Files selected for processing (2)
  • cmd/cloud.go (3 hunks)
  • cmd/dev.go (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • cmd/cloud.go
🧰 Additional context used
🧬 Code Graph Analysis (1)
cmd/dev.go (1)
internal/util/api.go (1)
  • GetURLs (262-281)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (go)

Copy link
Member

@jhaynie jhaynie left a comment

Choose a reason for hiding this comment

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

See the one comment by the 🐇

@coderabbitai coderabbitai bot requested a review from jhaynie August 15, 2025 20:46
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

🔭 Outside diff range comments (1)
internal/bundler/patch.go (1)

91-96: Fix closure-capture bug for loop variables used inside OnLoad callback

Each OnLoad closure currently captures the same name/mod from the last iteration. Rebind them per-iteration to avoid wrong module being rewritten at runtime.

-			for name, mod := range patches {
-				path := "node_modules/" + mod.Module + "/.*"
+			for name, mod := range patches {
+				// Rebind loop vars so each closure captures its own values
+				name := name
+				mod := mod
+				path := "node_modules/" + mod.Module + "/.*"
 				if mod.Filename != "" {
 					path = "node_modules/" + mod.Module + "/" + mod.Filename + ".*"
 				}
 				build.OnLoad(api.OnLoadOptions{Filter: path, Namespace: "file"}, func(args api.OnLoadArgs) (api.OnLoadResult, error) {
♻️ Duplicate comments (5)
internal/bundler/patch.go (5)

104-104: Detect all common JS/TS extensions; avoid misclassifying .mjs/.cjs/.jsx/.mts/.cts

Only checking “.js” will send .mjs/.cjs/.jsx down the TS path and break bundling; similarly .mts/.cts should be TS. Classify by full extension set.

-					isJS := strings.HasSuffix(args.Path, ".js")
+					// Detect script type by extension
+					isJS := strings.HasSuffix(args.Path, ".js") ||
+						strings.HasSuffix(args.Path, ".mjs") ||
+						strings.HasSuffix(args.Path, ".cjs") ||
+						strings.HasSuffix(args.Path, ".jsx")
+					isTS := strings.HasSuffix(args.Path, ".ts") ||
+						strings.HasSuffix(args.Path, ".tsx") ||
+						strings.HasSuffix(args.Path, ".mts") ||
+						strings.HasSuffix(args.Path, ".cts")

181-184: Select esbuild loader based on TS-family check (not just “not JS”)

Use LoaderTS only for TS-family extensions; keep JS-family on LoaderJS even when not “.js”.

-					loader := api.LoaderJS
-					if !isJS {
-						loader = api.LoaderTS
-					}
+					loader := api.LoaderJS
+					if isTS {
+						loader = api.LoaderTS
+					}

108-116: Generalize detection: support const/let/var variable function declarations

Current logic only recognizes const fn =. Extend to let and var, and track the keyword for later emission.

-						var isConstVariable bool
+						var isVarDecl bool
+						var declKeyword string
 						if index == -1 {
-							fnname = "const " + fn + " = "
-							index = strings.Index(contents, fnname)
-							isConstVariable = true
-							if index == -1 {
-								continue
-							}
+							for _, kw := range []string{"const", "let", "var"} {
+								candidate := kw + " " + fn + " = "
+								if idx := strings.Index(contents, candidate); idx != -1 {
+									fnname = candidate
+									index = idx
+									isVarDecl = true
+									declKeyword = kw
+									break
+								}
+							}
+							if index == -1 {
+								continue
+							}
 						}

125-130: Preserve original var-decl kind when renaming the implementation

Carry through const/let/var when building the renamed symbol.

-						var newfnname string
-						if isConstVariable {
-							newfnname = "const " + newname + " = "
-						} else {
-							newfnname = "function " + newname
-						}
+						var newfnname string
+						if isVarDecl {
+							newfnname = declKeyword + " " + newname + " = "
+						} else {
+							newfnname = "function " + newname
+						}

123-137: Fix prefix construction and wrapper emission: preserve export default, place async correctly, and generate valid headers for var-decls

  • Current fnprefix logic can emit duplicated tokens and mis-order export/async.
  • export default is lost, changing module semantics.
  • Non-JS var-decl wrappers output const fn = (...args) { (missing =>) and place async before const, which is invalid.

Refactor to compute exportPrefix/asyncPrefix and emit correct headers for both function and variable declarations.

-						isAsync := strings.Contains(prefix, "async")
-						isExport := strings.Contains(prefix, "export")
+						isAsync := strings.Contains(prefix, "async")
+						isExport := strings.Contains(prefix, "export")
+						isDefault := strings.Contains(prefix, "default")
 						newname := "__agentuity_" + fn
-						var newfnname string
-						if isConstVariable {
-							newfnname = "const " + newname + " = "
-						} else {
-							newfnname = "function " + newname
-						}
-						var fnprefix string
-						if isAsync {
-							fnprefix = "async "
-						}
-						if isExport {
-							fnprefix += "export " + fnprefix
-						}
+						var newfnname string
+						if isVarDecl {
+							newfnname = declKeyword + " " + newname + " = "
+						} else {
+							newfnname = "function " + newname
+						}
+						// Build prefixes
+						var exportPrefix, asyncPrefix string
+						if isExport {
+							exportPrefix = "export "
+							if isDefault {
+								exportPrefix += "default "
+							}
+						}
+						// For function declarations, "async" prefixes the function.
+						// For variable declarations, "async" goes after "=" (see below).
+						if !isVarDecl && isAsync {
+							asyncPrefix = "async "
+						}
 						contents = strings.Replace(contents, fnname, newfnname, 1)
-						if isJS {
-							suffix.WriteString(fnprefix + "function " + fn + "() {\n")
-							suffix.WriteString("let args = arguments;\n")
-						} else {
-							suffix.WriteString(fnprefix + fnname + "(...args) {\n")
-						}
+						if isJS {
+							suffix.WriteString(exportPrefix + asyncPrefix + "function " + fn + "() {\n")
+							suffix.WriteString("let args = arguments;\n")
+						} else {
+							if isVarDecl {
+								if isAsync {
+									suffix.WriteString(exportPrefix + declKeyword + " " + fn + " = async (...args) => {\n")
+								} else {
+									suffix.WriteString(exportPrefix + declKeyword + " " + fn + " = (...args) => {\n")
+								}
+							} else {
+								suffix.WriteString(exportPrefix + asyncPrefix + "function " + fn + "(...args) {\n")
+							}
+						}

Also applies to: 139-144

🧹 Nitpick comments (3)
internal/bundler/patch.go (3)

105-106: Avoid confusing shadowing: rename inner mod (patchAction) to action

Shadowing mod (patchModule) with mod (patchAction) harms readability and is error-prone. Rename the inner variable and its uses.

-					for fn, mod := range mod.Functions {
+					for fn, action := range mod.Functions {
@@
-						if mod.Before != "" {
-							suffix.WriteString(mod.Before)
+						if action.Before != "" {
+							suffix.WriteString(action.Before)
 							suffix.WriteString("\n")
 						}
@@
-						if mod.After != "" {
-							suffix.WriteString(mod.After)
+						if action.After != "" {
+							suffix.WriteString(action.After)
 							suffix.WriteString("\n")
 						}

Also applies to: 146-149, 164-167


138-138: Replace targeted substring at the computed index to avoid accidental earlier replacement

strings.Replace(..., 1) will replace the first occurrence, which might not be the one at index if the pattern appears earlier. Replace at the exact index for correctness.

-						contents = strings.Replace(contents, fnname, newfnname, 1)
+						contents = contents[:index] + newfnname + contents[index+len(fnname):]

92-96: Nit: rename local path var to filter to avoid shadowing the imported path package

Pure readability; avoids confusion between path (string) and path (package).

-				path := "node_modules/" + mod.Module + "/.*"
-				if mod.Filename != "" {
-					path = "node_modules/" + mod.Module + "/" + mod.Filename + ".*"
-				}
-				build.OnLoad(api.OnLoadOptions{Filter: path, Namespace: "file"}, func(args api.OnLoadArgs) (api.OnLoadResult, error) {
+				filter := "node_modules/" + mod.Module + "/.*"
+				if mod.Filename != "" {
+					filter = "node_modules/" + mod.Module + "/" + mod.Filename + ".*"
+				}
+				build.OnLoad(api.OnLoadOptions{Filter: filter, Namespace: "file"}, func(args api.OnLoadArgs) (api.OnLoadResult, error) {
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 3459ff0 and f01ffbc.

📒 Files selected for processing (1)
  • internal/bundler/patch.go (2 hunks)
⏰ 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: Build and Test (macos-latest)
  • GitHub Check: Analyze (go)

@potofpie potofpie merged commit e24e93f into main Aug 18, 2025
14 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