Skip to content

Conversation

@sawka
Copy link
Member

@sawka sawka commented Nov 7, 2025

No description provided.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 7, 2025

Warning

Rate limit exceeded

@sawka has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 23 minutes and 23 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 6b29a30 and 82a08d4.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (5)
  • emain/preload.ts (1 hunks)
  • frontend/types/custom.d.ts (1 hunks)
  • frontend/types/gotypes.d.ts (1 hunks)
  • go.mod (1 hunks)
  • tsunami/build/build.go (5 hunks)

Walkthrough

This PR adds Tsunami configuration keys and scaffold build support, updates build tooling and Taskfile tasks to produce a dist/tsunamiscaffold, extends Electron menu and IPC to support workspace/builder-specific app menus, adds secret declaration and manifest generation to the Tsunami engine and client, moves several build/runtime Go options to configurable settings (SDK version, Go path), adjusts AI/OpenAI endpoint handling, and makes multiple frontend adjustments (context menus, AI panel behavior, types). Several documentation files were removed.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60–90 minutes

Areas requiring extra attention during review:

  • emain/emain-menu.ts — large refactor to modular menu builders and WebContents routing plus new IPC handlers.
  • tsunami/engine/clientimpl.go & tsunami/app/defaultclient.go — new secret management, concurrency (SecretsLock), manifest assembly and JSON output.
  • tsunami/build/build.go, tsunami/cmd/main-tsunami.go, pkg/buildercontroller/buildercontroller.go — SDK/Go-path/config wiring, BuildOpts changes, and defaults propagation.
  • tsunami/engine/render.go & tsunami/engine/errcomponent.go — removal and addition of error-rendering code; verify no dead references and panic handling remains correct.
  • Taskfile.yml & electron-builder.config.cjs — new scaffold build task and ASAR unpack inclusion; ensure duplicate Taskfile entries and packaging behavior are correct.
  • preload.ts, frontend types & usage (tabbar.tsx, builder-buildpanel.tsx, contextmenu) — new IPC APIs (showWorkspaceAppMenu/showBuilderAppMenu) and type signature changes; validate IPC routing and type updates.
  • pkg/aiusechat changes & uctypes DefaultAIEndpoint — header behavior and endpoint selection logic.
  • schema/settings.json, pkg/wconfig changes, frontend/types/gotypes.d.ts — consistency across type/schema/config key additions.
  • go.mod addition and any indirect dependency impacts.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 2 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 7.14% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The PR title 'more work on tsunami builder' is vague and generic, lacking specificity about which aspects of tsunami builder are being modified. Replace with a more specific title that describes the main change, such as 'Add tsunami configuration settings and build scaffolding' or 'Integrate tsunami SDK version and path configuration'.
Description check ❓ Inconclusive No pull request description was provided by the author, making it impossible to assess whether the description is related to the changeset. Add a description explaining the purpose, scope, and key changes in this pull request to help reviewers understand the intent.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link
Contributor

@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

Caution

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

⚠️ Outside diff range comments (3)
emain/emain-menu.ts (1)

33-43: Fix Wave window webContents detection

Because WaveBrowserWindow extends electron.BrowserWindow, the first branch always matches Wave windows and returns the shell BrowserWindow.webContents. As a result, “Reload Tab”, zoom, context menu click routing, etc. now hit the wrong target and no longer reach the active tab’s BrowserView. Please check for the Wave subclass first so we can keep targeting the tab view, and only fall back to the generic BrowserWindow branch for Tsunami builder windows.

 function getWindowWebContents(window: electron.BaseWindow): electron.WebContents {
     if (window == null) {
         return null;
     }
-    // Check BrowserWindow first (for Tsunami Builder windows)
-    if (window instanceof electron.BrowserWindow) {
-        return window.webContents;
-    }
-    // Check WaveBrowserWindow (for main Wave windows with tab views)
-    if (window instanceof WaveBrowserWindow) {
-        if (window.activeTabView) {
-            return window.activeTabView.webContents;
-        }
-        return null;
-    }
+    if (window instanceof WaveBrowserWindow) {
+        return window.activeTabView?.webContents ?? null;
+    }
+    if (window instanceof electron.BrowserWindow) {
+        return window.webContents;
+    }
     return null;
 }
tsunami/build/build.go (2)

553-564: Avoid self-referential UI symlink when no SDK replace path

When SdkReplacePath is empty (the new default when building against a released SDK version), filepath.Join("", "ui") produces the relative target "ui". The symlink at tempDir/ui then points back to itself, so any attempt to import github.com/wavetermdev/waveterm/tsunami/ui blows up with “too many levels of symbolic links,” breaking builds that rely on the module version instead of a local replace.

Only create this symlink when we actually have a real replace path (or skip entirely when using the module). One way to fix it:

-	uiTargetPath := filepath.Join(opts.SdkReplacePath, "ui")
-	if err := os.Symlink(uiTargetPath, uiLinkPath); err != nil {
+	if opts.SdkReplacePath == "" {
+		if opts.Verbose {
+			oc.Printf("Skipping UI symlink creation - no SdkReplacePath configured")
+		}
+	} else {
+		uiTargetPath := filepath.Join(opts.SdkReplacePath, "ui")
+		if err := os.Symlink(uiTargetPath, uiLinkPath); err != nil {
 			return buildEnv, fmt.Errorf("failed to create ui symlink: %w", err)
 		}
-	if opts.Verbose {
-		oc.Printf("Created UI symlink: %s -> %s", uiLinkPath, uiTargetPath)
-	}
+		if opts.Verbose {
+			oc.Printf("Created UI symlink: %s -> %s", uiLinkPath, uiTargetPath)
+		}
+	}

312-322: Honor GoPath when spawning Go tools

We now surface BuildOpts.GoPath, but both go mod tidy and the final go build still invoke "go" directly. Anyone relying on tsunami:gopath (or the watcher-resolved custom path) passes verifyEnvironment, yet the subsequent commands blow up because that binary isn’t on PATH.

Please thread the resolved executable through every Go invocation, e.g.:

-	tidyCmd := exec.Command("go", "mod", "tidy")
+	goExe := opts.GoPath
+	if goExe == "" {
+		goExe = "go"
+	}
+	tidyCmd := exec.Command(goExe, "mod", "tidy")
...
-	buildCmd := exec.Command("go", args...)
+	goExe := opts.GoPath
+	if goExe == "" {
+		goExe = "go"
+	}
+	buildCmd := exec.Command(goExe, args...)

Reuse the same helper for any other Go subprocess so the new configuration knob actually works.

Also applies to: 664-672

🧹 Nitpick comments (2)
frontend/app/aipanel/aimessage.tsx (1)

52-57: Approve the layout stability improvement.

The fixed height (h-[3lh]) prevents layout shift during streaming content, which improves the user experience. The container is already conditionally rendered at a higher level (lines 245-252), so it only appears when appropriate.

Note that when displayText is empty (e.g., waiting for tool approvals), this will show a 3-line-height empty space. If this is visually undesirable, consider applying the fixed height only when content is present.

Optional refinement:

-                <div
-                    ref={scrollRef}
-                    className="text-sm text-gray-500 overflow-y-auto h-[3lh] max-w-[600px] pl-9"
-                >
+                <div
+                    ref={scrollRef}
+                    className={cn(
+                        "text-sm text-gray-500 overflow-y-auto max-w-[600px] pl-9",
+                        displayText ? "h-[3lh]" : "max-h-[3lh]"
+                    )}
+                >
                     {displayText}
                 </div>
frontend/builder/builder-buildpanel.tsx (1)

39-39: Event handlers properly wired; note unused ref.

The preRef is declared but not currently used. If it's intended for future enhancements, consider adding a comment; otherwise, it can be removed to reduce clutter.

Also applies to: 80-85

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 58392f7 and e861e23.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (29)
  • .vscode/settings.json (1 hunks)
  • Taskfile.yml (3 hunks)
  • electron-builder.config.cjs (1 hunks)
  • emain/emain-menu.ts (13 hunks)
  • emain/preload.ts (1 hunks)
  • frontend/app/aipanel/aimessage.tsx (1 hunks)
  • frontend/app/aipanel/waveai-model.tsx (1 hunks)
  • frontend/app/store/contextmenu.ts (1 hunks)
  • frontend/app/tab/tabbar.tsx (1 hunks)
  • frontend/builder/builder-buildpanel.tsx (2 hunks)
  • frontend/types/custom.d.ts (1 hunks)
  • frontend/types/gotypes.d.ts (1 hunks)
  • go.mod (1 hunks)
  • pkg/aiusechat/openai/openai-convertmessage.go (2 hunks)
  • pkg/aiusechat/tsunami/global-keyboard-handling.md (0 hunks)
  • pkg/aiusechat/tsunami/graphing.md (0 hunks)
  • pkg/aiusechat/tsunami/system.md (0 hunks)
  • pkg/aiusechat/uctypes/usechat-types.go (1 hunks)
  • pkg/aiusechat/usechat.go (2 hunks)
  • pkg/buildercontroller/buildercontroller.go (3 hunks)
  • pkg/wconfig/metaconsts.go (1 hunks)
  • pkg/wconfig/settingsconfig.go (1 hunks)
  • schema/settings.json (1 hunks)
  • tsunami/app/atom.go (1 hunks)
  • tsunami/app/defaultclient.go (1 hunks)
  • tsunami/build/build.go (5 hunks)
  • tsunami/cmd/main-tsunami.go (3 hunks)
  • tsunami/engine/clientimpl.go (4 hunks)
  • tsunami/templates/app-main.go.tmpl (2 hunks)
💤 Files with no reviewable changes (3)
  • pkg/aiusechat/tsunami/global-keyboard-handling.md
  • pkg/aiusechat/tsunami/graphing.md
  • pkg/aiusechat/tsunami/system.md
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-10-15T03:21:02.229Z
Learnt from: sawka
Repo: wavetermdev/waveterm PR: 2433
File: pkg/aiusechat/tools_readfile.go:197-197
Timestamp: 2025-10-15T03:21:02.229Z
Learning: In Wave Terminal's AI tool definitions (pkg/aiusechat/tools_*.go), the Description field should not mention approval requirements even when ToolApproval returns ApprovalNeedsApproval. This prevents the LLM from asking users for approval before calling the tool, avoiding redundant double-approval prompts since the runtime will enforce approval anyway.

Applied to files:

  • pkg/aiusechat/openai/openai-convertmessage.go
  • pkg/aiusechat/usechat.go
📚 Learning: 2025-10-14T06:30:54.763Z
Learnt from: sawka
Repo: wavetermdev/waveterm PR: 2430
File: frontend/app/aipanel/aimessage.tsx:137-144
Timestamp: 2025-10-14T06:30:54.763Z
Learning: In `frontend/app/aipanel/aimessage.tsx`, the `AIToolUseGroup` component splits file operation tool calls into separate batches (`fileOpsNeedApproval` and `fileOpsNoApproval`) based on their approval state before passing them to `AIToolUseBatch`. This ensures each batch has homogeneous approval states, making group-level approval handling valid.

Applied to files:

  • frontend/app/aipanel/aimessage.tsx
📚 Learning: 2025-11-01T00:57:23.025Z
Learnt from: sawka
Repo: wavetermdev/waveterm PR: 2504
File: frontend/app/aipanel/aipanel-contextmenu.ts:15-16
Timestamp: 2025-11-01T00:57:23.025Z
Learning: In the waveterm codebase, types defined in custom.d.ts are globally available and do not require explicit imports. Backend types defined in gotypes.d.ts are also globally available.

Applied to files:

  • frontend/types/gotypes.d.ts
🧬 Code graph analysis (9)
pkg/aiusechat/openai/openai-convertmessage.go (1)
pkg/aiusechat/uctypes/usechat-types.go (1)
  • DefaultAIEndpoint (12-12)
frontend/builder/builder-buildpanel.tsx (2)
frontend/app/aipanel/waveai-model.tsx (1)
  • WaveAIModel (43-565)
frontend/app/store/contextmenu.ts (1)
  • ContextMenuModel (68-68)
tsunami/app/defaultclient.go (2)
tsunami/engine/clientimpl.go (2)
  • SecretMeta (48-51)
  • GetDefaultClient (115-117)
tsunami/app/atom.go (1)
  • SecretMeta (26-29)
pkg/aiusechat/usechat.go (1)
pkg/aiusechat/uctypes/usechat-types.go (1)
  • DefaultAIEndpoint (12-12)
frontend/app/store/contextmenu.ts (1)
frontend/app/store/global.ts (2)
  • atoms (816-816)
  • getApi (826-826)
pkg/buildercontroller/buildercontroller.go (3)
pkg/wconfig/filewatcher.go (1)
  • GetWatcher (33-57)
pkg/wavebase/wavebase.go (1)
  • GetWaveAppPath (113-115)
tsunami/cmd/main-tsunami.go (1)
  • TsunamiSdkVersion (17-17)
pkg/wconfig/settingsconfig.go (1)
tsunami/cmd/main-tsunami.go (1)
  • TsunamiSdkVersion (17-17)
tsunami/engine/clientimpl.go (3)
tsunami/app/atom.go (1)
  • SecretMeta (26-29)
tsunami/app/defaultclient.go (2)
  • DeclareSecret (166-176)
  • PrintAppManifest (178-181)
tsunami/engine/schema.go (2)
  • GenerateConfigSchema (295-298)
  • GenerateDataSchema (301-304)
emain/emain-menu.ts (6)
emain/emain-platform.ts (1)
  • unamePlatform (273-273)
emain/emain-tabview.ts (1)
  • clearTabCache (215-221)
emain/emain-window.ts (2)
  • getAllWaveWindows (652-654)
  • getWaveWindowByWorkspaceId (644-650)
emain/emain-builder.ts (2)
  • focusedBuilderWindow (20-20)
  • getBuilderWindowById (22-24)
frontend/app/store/wshclientapi.ts (1)
  • RpcApi (632-632)
emain/emain-wsh.ts (1)
  • ElectronWshClient (116-116)
⏰ 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). (5)
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Analyze (go)
  • GitHub Check: Build Docsite
  • GitHub Check: Build for TestDriver.ai
  • GitHub Check: merge-gatekeeper
🔇 Additional comments (17)
pkg/aiusechat/openai/openai-convertmessage.go (2)

148-150: LGTM! Useful debug logging.

The conditional endpoint logging helps developers identify when non-default endpoints are being used, which is valuable for debugging custom configurations.


319-323: LGTM! Clear request type identification.

The header logic correctly distinguishes builder requests from regular AI requests, which will help with backend routing and analytics.

pkg/aiusechat/uctypes/usechat-types.go (1)

12-12: Good refactoring to centralize the endpoint definition.

Moving the default AI endpoint to a shared constant in the types package provides a single source of truth and improves maintainability.

pkg/aiusechat/usechat.go (2)

100-100: LGTM! Correct usage of the centralized constant.

The change properly uses the newly centralized uctypes.DefaultAIEndpoint constant, completing the refactoring to provide a single source of truth for the default endpoint.


689-691: Verify that empty system prompt is intended for builder mode.

When BuilderId is present, the system prompt is now initialized to an empty slice. This is a significant change from the previous behavior where builder mode had specific system prompt text (BuilderSystemPromptText_OpenAI + tsunamiSystemDoc, per the summary).

Please confirm this is the intended behavior for the tsunami builder system. If system instructions for builders are being provided through a different mechanism (e.g., per-conversation or via tools), that's fine. Otherwise, the AI may lack important context about its role and capabilities in builder mode.

frontend/app/tab/tabbar.tsx (1)

634-635: Aligned with new workspace menu flow.

Switching to showWorkspaceAppMenu routes the ellipsis button through the dedicated workspace menu channel exposed by the preload bridge, so the renderer no longer needs to juggle ad-hoc context menu payloads. Looks good.

emain/preload.ts (1)

21-22: Preload surface covers the new menu IPC.

These bridge helpers keep renderer code within the blessed API while enabling the per-workspace and builder menu flows you introduced in the main process.

frontend/types/custom.d.ts (2)

90-91: LGTM! Clean API additions for workspace and builder menus.

The new methods follow the existing API patterns and provide clear separation of concerns for different menu contexts.


92-92: All call sites properly updated for breaking change.

The menu parameter is now required across all 9 call sites in the codebase, confirming the breaking API change has been implemented consistently:

  • frontend/builder/builder-buildpanel.tsx, frontend/app/workspace/widgets.tsx, frontend/app/tab/tab.tsx, frontend/app/view/preview/preview-model.tsx, frontend/app/view/preview/preview-directory.tsx (2 calls), frontend/app/app.tsx, frontend/app/block/blockframe.tsx, and frontend/app/aipanel/aipanel-contextmenu.ts all pass the menu parameter.
tsunami/cmd/main-tsunami.go (1)

17-17: LGTM! Clean SDK version constant usage.

The SDK version is properly centralized as a constant and consistently applied to both build and run command paths.

Also applies to: 77-77, 106-106

tsunami/app/atom.go (1)

25-29: LGTM! Clean metadata structure for secrets.

The SecretMeta type follows the existing patterns in the file and provides appropriate fields for secret documentation and validation.

frontend/app/aipanel/waveai-model.tsx (1)

302-318: LGTM! Backward-compatible enhancement with clear logic.

The optional newLine parameter provides flexibility while maintaining backward compatibility. The logic correctly handles both newline and space insertion based on the current input state.

tsunami/app/defaultclient.go (2)

166-176: LGTM! Clean secret declaration wrapper.

The function properly handles nil metadata, maps to the engine layer, and returns the environment variable value. The implementation follows existing patterns in the file.


178-181: LGTM! Simple delegation function.

Clean wrapper that follows the existing delegation pattern in the file.

schema/settings.json (1)

253-268: LGTM! Clean schema additions for tsunami configuration.

The new properties are well-typed and follow the existing schema patterns. The wildcard property allows for future extensibility.

frontend/builder/builder-buildpanel.tsx (2)

11-33: LGTM! Well-structured context menu integration.

The context menu implementation provides a clean way to add build output to the AI context. The markdown formatting with code blocks and the "from builder output:" label provide good context for the AI.


54-72: LGTM! Efficient copy-on-select implementation.

The debounced copy-on-select feature enhances UX for build output. The 50ms debounce prevents excessive clipboard operations, and the useCallback hooks optimize performance.

Comment on lines +52 to +62

const workspace = globalStore.get(atoms.workspace);
let oid: string;

if (workspace != null) {
oid = workspace.oid;
} else {
oid = globalStore.get(atoms.builderId);
}

getApi().showContextMenu(oid, electronMenuItems);
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify builderId is always defined in builder context.

The fallback logic correctly handles both workspace and builder contexts. However, ensure that builderId is always defined when workspace is null, or add a defensive check.


🏁 Script executed:

#!/bin/bash
# Description: Verify builderId atom usage and initialization

# Search for builderId atom initialization and usage
rg -nP --type=ts -C3 '\bbuilderId\s*:.*Atom'

Length of output: 1112



---

🏁 Script executed:

```shell
#!/bin/bash
# Find builderIdAtom definition and initialization

# Search for builderIdAtom definition
rg -nP --type=ts -C5 '\bbuilderIdAtom\s*=' | head -50

# Search for builderIdAtom in wave.ts specifically
echo "---"
rg -nP --type=ts 'builderIdAtom' | grep -i 'wave\.ts'

Length of output: 897


🏁 Script executed:

#!/bin/bash
# Find where builderId is initialized and used
fd -e ts -e tsx | xargs grep -l "builderId" | grep -E '(wave|init|main|boot|startup)' || echo "No matches in startup files"

Length of output: 133



---

🏁 Script executed:

```shell
#!/bin/bash
# Find initGlobalAtoms call sites
rg -nP --type=ts 'initGlobalAtoms\s*\(' -A5 | head -40

# Check contextmenu.ts for builderId handling around line 58
rg -nP --type=ts -B10 -A5 'showContextMenu' frontend/app/store/contextmenu.ts

Length of output: 1712



---

🏁 Script executed:

```shell
#!/bin/bash
# Find initGlobalStoreContext and its call sites
rg -nP --type=ts 'initGlobalStoreContext' -B2 -A10

# Check what the ContextMenuModel.showContextMenu expects
rg -nP --type=ts 'showContextMenu.*oid' -B5 -A5

Length of output: 2594



---

🏁 Script executed:

```shell
#!/bin/bash
# Find GlobalInitOptions type definition
rg -nP --type=ts 'interface GlobalInitOptions|type GlobalInitOptions' -A10

Length of output: 627


Add null check for builderId in fallback logic.

The fallback at line 59 can assign an undefined value to oid. Since builderId is optional in GlobalInitOptions (line 43 of global.ts), and the API at line 92 of custom.d.ts requires a string parameter for showContextMenu, add a defensive guard:

oid = globalStore.get(atoms.builderId) ?? '';

Or log an error if both workspace and builderId are undefined, indicating an initialization problem.

🤖 Prompt for AI Agents
In frontend/app/store/contextmenu.ts around lines 52 to 62, the fallback assigns
builderId which may be undefined causing a non-string to be passed to
getApi().showContextMenu; change the fallback to defensively handle undefined by
using a safe default or error path (e.g., set oid =
globalStore.get(atoms.builderId) ?? '' or check both workspace and builderId and
log/throw an error if neither is present) so that showContextMenu always
receives a string and initialization problems are surfaced.

…icks up their classes automatically. remove brittle inline decls...
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

🧹 Nitpick comments (3)
tsunami/build/build.go (3)

73-75: Document the new BuildOpts fields.

The new SdkVersion and GoPath fields lack documentation. Consider adding comments to clarify:

  • SdkVersion: Expected format (e.g., v0.1.0, semantic versioning)
  • GoPath: Whether it should be an absolute path to the Go executable
  • The relationship between these fields and SdkReplacePath

Apply this diff to add documentation:

+	// SdkVersion specifies the version of the Tsunami SDK to use (e.g., "v0.1.0")
 	SdkVersion     string
+	// GoPath is the absolute path to the Go executable (optional, auto-detected if empty)
 	GoPath         string

138-158: Validation logic is sound, consider enhancing the error message.

The requirement for either SdkVersion or SdkReplacePath is appropriate, and the Go path resolution logic (with custom path support and auto-detection fallback) is well-implemented with good logging.

Consider making the error message more helpful:

 	if opts.SdkVersion == "" && opts.SdkReplacePath == "" {
-		return nil, fmt.Errorf("either SdkVersion or SdkReplacePath must be set")
+		return nil, fmt.Errorf("either SdkVersion or SdkReplacePath must be set in BuildOpts")
 	}

277-289: Consider validating SdkVersion format.

The use of opts.SdkVersion makes the build system more flexible. However, there's no validation that SdkVersion is in a valid format (e.g., semantic versioning like v0.1.0). While verifyEnvironment ensures either SdkVersion or SdkReplacePath is set, an invalid version format could cause issues with go mod tidy.

Consider adding validation before line 277:

+		// Validate SdkVersion format if provided
+		if opts.SdkVersion != "" {
+			versionRegex := regexp.MustCompile(`^v\d+\.\d+\.\d+`)
+			if !versionRegex.MatchString(opts.SdkVersion) {
+				return fmt.Errorf("invalid SdkVersion format: %s (expected format: v0.1.0)", opts.SdkVersion)
+			}
+		}
+
 		// Add requirement for tsunami SDK
 		if err := modFile.AddRequire("github.com/wavetermdev/waveterm/tsunami", opts.SdkVersion); err != nil {

Alternatively, verify that the existing validation in verifyEnvironment is sufficient by checking if modfile.AddRequire handles invalid versions gracefully.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e861e23 and 6b29a30.

📒 Files selected for processing (5)
  • Taskfile.yml (4 hunks)
  • tsunami/build/build.go (5 hunks)
  • tsunami/engine/errcomponent.go (1 hunks)
  • tsunami/engine/render.go (0 hunks)
  • tsunami/templates/tailwind.css (0 hunks)
💤 Files with no reviewable changes (2)
  • tsunami/templates/tailwind.css
  • tsunami/engine/render.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • Taskfile.yml
⏰ 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). (5)
  • GitHub Check: Build Docsite
  • GitHub Check: merge-gatekeeper
  • GitHub Check: Build for TestDriver.ai
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Analyze (go)
🔇 Additional comments (3)
tsunami/build/build.go (2)

98-133: LGTM! Go executable discovery logic is robust.

The exported FindGoExecutable function provides a reasonable fallback strategy, checking PATH first and then platform-specific common installation locations. The export allows external callers to reuse this logic.


305-308: LGTM! Logging improvements enhance debuggability.

The updated verbose output clearly shows the configured SDK version and conditionally displays the replace directive, making it easier to understand the build configuration.

tsunami/engine/errcomponent.go (1)

13-22: The original review comment is based on incorrect information and should be dismissed.

The search confirms that renderErrorComponent is actively called from render.go at line 185 within the callCFuncWithErrorGuard function's error handling defer block. The premise that "render.go no longer uses it" is factually incorrect. Additionally, no external packages import from the engine package, confirming this function is package-internal and appropriately non-exported. The design—keeping the function unexported as a private utility for panic error handling—is sound and requires no changes.

Likely an incorrect or invalid review comment.

@sawka sawka merged commit e9bc34a into main Nov 8, 2025
5 of 8 checks passed
@sawka sawka deleted the sawka/tsunami-build branch November 8, 2025 02:20
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.

2 participants