Skip to content

Expanding WaveEnv to cover all of frontend/app/block components#3024

Merged
sawka merged 15 commits intomainfrom
sawka/mock-for-block
Mar 10, 2026
Merged

Expanding WaveEnv to cover all of frontend/app/block components#3024
sawka merged 15 commits intomainfrom
sawka/mock-for-block

Conversation

@sawka
Copy link
Member

@sawka sawka commented Mar 10, 2026

  • lots of updates to WaveEnv to make it cover more functionality
  • Create BlockEnv as a narrowing of WaveEnv that covers all of frontend/app/block functionality
  • Fixed a lot of dependencies in the block components that caused unnecessarily re-renders
  • Added atom caching to WOS

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 10, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

The PR shifts block data access from global/WOS atoms into a WaveEnv/BlockEnv abstraction and updates mocks and types. Block rendering is refactored so view models are created from a viewType (makeDefaultViewModel(viewType)) and Block/SubBlock now route through internal BlockInner/SubBlockInner with viewType propagation. WaveEnv gains a wos namespace (getWaveObjectAtom/getWaveObjectLoadingAtom/isWaveObjectNullAtom/useWaveObjectValue), getSettingsKeyAtom, getConnConfigKeyAtom, getLocalHostDisplayNameAtom, and mockTabModel; wos caching and isWaveObjectNullAtom were added. Many UI components and store utilities were updated to use useWaveEnv, plus a new SKILL.md doc.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: expanding WaveEnv to cover all frontend/app/block components, which is the core focus of the PR.
Description check ✅ Passed The description is related to the changeset and mentions key improvements: WaveEnv expansion, BlockEnv creation, dependency fixes, and atom caching to WOS.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch sawka/mock-for-block

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.

@kilo-code-bot
Copy link
Contributor

kilo-code-bot bot commented Mar 10, 2026

Code Review Summary

Status: No New Issues Found | Recommendation: Merge

Overview

This PR introduces WaveEnv narrowing for better type safety and testability. It refactors multiple components to use the useWaveEnv<BlockEnv>() pattern instead of direct imports.

Severity Count
CRITICAL 0
WARNING 0
SUGGESTION 0

Changes Reviewed

The refactoring is well-structured:

  • Converts direct RPC and atom access to use waveEnv pattern
  • Introduces WaveEnvSubset<T> type for precise dependency declaration
  • Updates mock implementations in mockwaveenv.ts consistently
  • Changes block data loading to use waveEnv.wos.isWaveObjectNullAtom()

The existing comments on this PR already cover the areas of concern. The current code in connstatusoverlay.tsx now includes waveEnv in the useCallback dependency arrays (lines 62, 149, 164).

Files Reviewed (13 files)
  • .kilocode/skills/waveenv/SKILL.md - New skill documentation
  • frontend/app/aipanel/aipanel.tsx - Uses renamed function
  • frontend/app/block/block.tsx - Uses waveEnv pattern
  • frontend/app/block/blockenv.ts - New WaveEnvSubset type
  • frontend/app/block/blockutil.tsx - Function signature updates
  • frontend/app/block/blockframe.tsx - Uses waveEnv pattern
  • frontend/app/block/connectionbutton.tsx - Uses waveEnv pattern
  • frontend/app/block/connstatusoverlay.tsx - Uses waveEnv pattern
  • frontend/app/block/durable-session-flyover.tsx - Uses waveEnv pattern
  • frontend/app/store/global.ts - Exports new function
  • frontend/app/store/tab-model.ts - Uses waveEnv
  • frontend/app/store/wos.ts - New atom caching
  • frontend/app/waveenv/waveenv.ts - New types
  • frontend/app/waveenv/waveenvimpl.ts - Implementation
  • frontend/app/workspace/widgets.tsx - Uses WaveEnvSubset
  • frontend/preview/mock/mockwaveenv.ts - Mock implementation

@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Mar 10, 2026

Deploying waveterm with  Cloudflare Pages  Cloudflare Pages

Latest commit: fc0c580
Status: ✅  Deploy successful!
Preview URL: https://353844f0.waveterm.pages.dev
Branch Preview URL: https://sawka-mock-for-block.waveterm.pages.dev

View logs

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

Caution

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

⚠️ Outside diff range comments (1)
frontend/app/block/block.tsx (1)

306-323: ⚠️ Potential issue | 🔴 Critical

Registry lookup must match remount strategy to prevent disposing active viewModels.

When viewType changes, React remounts BlockInner and SubBlockInner by key (blockId:viewType), but the components still read from a registry keyed on blockId alone. The new instance can grab the stale model from the registry before the old instance's cleanup runs, then that cleanup disposes the model while the new tree uses it.

Prevent reuse by gating on viewModel.viewType === props.viewType, and guard cleanup to unregister only if the registry entry still points to the instance being torn down. Update useEffect dependencies to [props.nodeModel.blockId, viewModel] to properly track which instance owns the cleanup.

🔁 Minimal guard for the remount path
-    const bcm = getBlockComponentModel(props.nodeModel.blockId);
-    let viewModel = bcm?.viewModel;
-    if (viewModel == null) {
+    const bcm = getBlockComponentModel(props.nodeModel.blockId);
+    let viewModel = bcm?.viewModel;
+    if (viewModel == null || viewModel.viewType !== props.viewType) {
         // viewModel gets the full waveEnv
         viewModel = makeViewModel(props.nodeModel.blockId, props.viewType, props.nodeModel, tabModel, waveEnv);
         registerBlockComponentModel(props.nodeModel.blockId, { viewModel });
     }
     useEffect(() => {
         return () => {
-            unregisterBlockComponentModel(props.nodeModel.blockId);
+            if (getBlockComponentModel(props.nodeModel.blockId)?.viewModel === viewModel) {
+                unregisterBlockComponentModel(props.nodeModel.blockId);
+            }
             viewModel?.dispose?.();
         };
-    }, []);
+    }, [props.nodeModel.blockId, viewModel]);

Apply the same guard to SubBlockInner.

Apply to both BlockInner (lines 306–323) and SubBlockInner (lines 363–370).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/app/block/block.tsx` around lines 306 - 323, The registry lookup and
cleanup in BlockInner and SubBlockInner can cause the new remounted instance to
reuse a viewModel that the old instance will dispose; fix by ensuring registry
entries are keyed/validated by viewType: when reading viewModel from
getBlockComponentModel(props.nodeModel.blockId) only accept it if
viewModel?.viewType === props.viewType, otherwise create a new viewModel via
makeViewModel(...) and register it with registerBlockComponentModel(...); in the
cleanup useEffect, only call unregisterBlockComponentModel(...) and
viewModel.dispose() if the current registry entry still points to this
instance’s viewModel (i.e., the registered model === viewModel) and change the
effect deps to [props.nodeModel.blockId, viewModel] so the cleanup is associated
with the correct instance; apply identical guards to SubBlockInner.
🧹 Nitpick comments (1)
frontend/app/block/connectionbutton.tsx (1)

24-24: Use useSetAtom instead of subscribing to the modal state.

Line 24 still subscribes this component to changeConnModalAtom even though the value is discarded. That reintroduces a rerender path the PR is trying to remove. const setConnModalOpen = jotai.useSetAtom(changeConnModalAtom) avoids the extra subscription.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/app/block/connectionbutton.tsx` at line 24, The component is
unnecessarily subscribing to changeConnModalAtom by calling jotai.useAtom and
discarding the value via _connModalOpen; replace that subscription with a
setter-only hook by using jotai.useSetAtom(changeConnModalAtom) so the component
no longer re-renders on atom value changes—update the declaration that currently
reads const [_connModalOpen, setConnModalOpen] =
jotai.useAtom(changeConnModalAtom) to use useSetAtom and keep the existing
setConnModalOpen reference.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@frontend/app/block/blockenv.ts`:
- Around line 17-19: The BlockEnv type currently defines api.openExternal but
the actual env implementations (makeWaveEnvImpl, makeMockWaveEnv) expose
electron.openExternal, so useWaveEnv<BlockEnv>() will yield undefined for
waveEnv.api; fix by aligning the shape: either rename BlockEnv.api to electron
(update the BlockEnv interface and all consumers to use electron.openExternal)
or add a real api property to makeWaveEnvImpl and makeMockWaveEnv that forwards
to electron.openExternal (e.g., set env.api.openExternal =
env.electron.openExternal) so WaveEnvContext, useWaveEnv, BlockEnv,
makeWaveEnvImpl, and makeMockWaveEnv all share the same property names.

In `@frontend/app/block/durable-session-flyover.tsx`:
- Around line 29-34: The runtime error is caused by calling
waveEnv.api.openExternal where waveEnv.api is undefined; change the call to use
the actual runtime shape—invoke waveEnv.electron.openExternal(...) instead of
waveEnv.api.openExternal (locate the use in durable-session-flyover.tsx where
useWaveEnv<BlockEnv>() returns waveEnv and reference BlockEnv and
makeWaveEnvImpl to confirm the runtime fields), or alternatively add an api
wrapper onto the WaveEnv implementation in makeWaveEnvImpl so waveEnv.api is
defined; prefer the simpler fix of replacing waveEnv.api.openExternal with
waveEnv.electron.openExternal to match the real object shape.

In `@frontend/app/store/tab-model.ts`:
- Around line 49-53: Cache key for TabModel must include the WaveEnv so an
env-less instance doesn't win; update getTabModelByTabId to derive a composite
key from tabId plus a canonical identifier from waveEnv (e.g., env.id or a
stable string) instead of using tabId alone, and use that composite key when
calling tabModelCache.get(...) and tabModelCache.set(...). Ensure TabModel
construction still receives the passed waveEnv and update any helper like
getActiveTabModel to use the same key derivation so env-specific models are
returned consistently.
- Around line 80-87: Rename the hook function maybeUseTabModel to
useMaybeTabModel to follow React hook naming, change its return type from
TabModel to TabModel | undefined, and update its implementation signature
accordingly (it already calls useWaveEnv() and useContext(TabModelContext));
then update all call sites (notably the caller in aipanel.tsx) to handle the
possible undefined return (add a null/undefined check or early return) so
consumers no longer assume a guaranteed TabModel.

In `@frontend/app/store/wos.ts`:
- Around line 221-258: The derived-atom cache entries (created by
getWaveObjectAtom, getWaveObjectLoadingAtom, and isWaveObjectNullAtom) close
over the original wov and must be evicted when the backing WaveObjectValue is
dropped; update the cache-clearing logic
(cleanWaveObjectCache/clearWaveObjectCache) to also remove
waveObjectDerivedAtomCache entries for the same oref by deleting keys with the
suffixes ":value", ":loading", and ":isnull" so that subsequent getWaveObject*
calls recreate atoms bound to the new wov.dataAtom instead of returning stale,
disconnected atoms.

In `@frontend/preview/mock/mockwaveenv.ts`:
- Around line 175-183: getLocalHostDisplayNameAtom currently constructs a new
atom on every call, breaking atom identity; change it to return a cached
singleton like connStatusAtomCache: create a module-/mock-init-scoped variable
(e.g., localHostDisplayNameAtomCache) and initialize it once with the same
atom<string>((get) => { const configValue =
get(atoms.settingsAtom)?.["conn:localhostdisplayname"]; return configValue ??
"user@localhost"; }) then have getLocalHostDisplayNameAtom return that cached
instance instead of creating a new atom on each invocation so consumers (e.g.,
connectionbutton.tsx) subscribe to the same atom.

---

Outside diff comments:
In `@frontend/app/block/block.tsx`:
- Around line 306-323: The registry lookup and cleanup in BlockInner and
SubBlockInner can cause the new remounted instance to reuse a viewModel that the
old instance will dispose; fix by ensuring registry entries are keyed/validated
by viewType: when reading viewModel from
getBlockComponentModel(props.nodeModel.blockId) only accept it if
viewModel?.viewType === props.viewType, otherwise create a new viewModel via
makeViewModel(...) and register it with registerBlockComponentModel(...); in the
cleanup useEffect, only call unregisterBlockComponentModel(...) and
viewModel.dispose() if the current registry entry still points to this
instance’s viewModel (i.e., the registered model === viewModel) and change the
effect deps to [props.nodeModel.blockId, viewModel] so the cleanup is associated
with the correct instance; apply identical guards to SubBlockInner.

---

Nitpick comments:
In `@frontend/app/block/connectionbutton.tsx`:
- Line 24: The component is unnecessarily subscribing to changeConnModalAtom by
calling jotai.useAtom and discarding the value via _connModalOpen; replace that
subscription with a setter-only hook by using
jotai.useSetAtom(changeConnModalAtom) so the component no longer re-renders on
atom value changes—update the declaration that currently reads const
[_connModalOpen, setConnModalOpen] = jotai.useAtom(changeConnModalAtom) to use
useSetAtom and keep the existing setConnModalOpen reference.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 38ce212c-2005-42cb-b115-6f6083b0fa0d

📥 Commits

Reviewing files that changed from the base of the PR and between 7119970 and 848a378.

📒 Files selected for processing (14)
  • frontend/app/block/block.tsx
  • frontend/app/block/blockenv.ts
  • frontend/app/block/blockframe-header.tsx
  • frontend/app/block/blockframe.tsx
  • frontend/app/block/blockutil.tsx
  • frontend/app/block/connectionbutton.tsx
  • frontend/app/block/connstatusoverlay.tsx
  • frontend/app/block/durable-session-flyover.tsx
  • frontend/app/store/global.ts
  • frontend/app/store/tab-model.ts
  • frontend/app/store/wos.ts
  • frontend/app/waveenv/waveenv.ts
  • frontend/app/waveenv/waveenvimpl.ts
  • frontend/preview/mock/mockwaveenv.ts

Comment on lines +49 to 53
export function getTabModelByTabId(tabId: string, waveEnv?: WaveEnv): TabModel {
let model = tabModelCache.get(tabId);
if (model == null) {
model = new TabModel(tabId);
model = new TabModel(tabId, waveEnv);
tabModelCache.set(tabId, model);
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 | 🟠 Major

Include waveEnv in the TabModel cache key.

tabModelCache is still keyed only by tabId, so the first model created for a tab wins. frontend/app/app.tsx:42-57 currently seeds the provider with getTabModelByTabId(tabId) without an env, which means later getTabModelByTabId(tabId, waveEnv) / getActiveTabModel(waveEnv) calls can still get the env-less instance and bypass the new mock/WaveEnv-backed path.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/app/store/tab-model.ts` around lines 49 - 53, Cache key for TabModel
must include the WaveEnv so an env-less instance doesn't win; update
getTabModelByTabId to derive a composite key from tabId plus a canonical
identifier from waveEnv (e.g., env.id or a stable string) instead of using tabId
alone, and use that composite key when calling tabModelCache.get(...) and
tabModelCache.set(...). Ensure TabModel construction still receives the passed
waveEnv and update any helper like getActiveTabModel to use the same key
derivation so env-specific models are returned consistently.

Comment on lines 80 to 87
export function maybeUseTabModel(): TabModel {
return useContext(TabModelContext);
const waveEnv = useWaveEnv();
const ctxModel = useContext(TabModelContext);
if (waveEnv?.mockTabModel != null) {
return waveEnv.mockTabModel;
}
return ctxModel;
}
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 | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cat -n frontend/app/store/tab-model.ts | head -100

Repository: wavetermdev/waveterm

Length of output: 3498


🏁 Script executed:

rg "maybeUseTabModel" --type ts --type tsx -B 2 -A 2

Repository: wavetermdev/waveterm

Length of output: 91


🏁 Script executed:

fd tsconfig.json -o exec cat {} \;

Repository: wavetermdev/waveterm

Length of output: 191


🏁 Script executed:

rg "maybeUseTabModel" -A 2 -B 2

Repository: wavetermdev/waveterm

Length of output: 1377


🏁 Script executed:

cat tsconfig.json

Repository: wavetermdev/waveterm

Length of output: 1138


🏁 Script executed:

cat -n frontend/app/aipanel/aipanel.tsx | grep -A 5 "maybeUseTabModel()"

Repository: wavetermdev/waveterm

Length of output: 484


Rename maybeUseTabModel to useMaybeTabModel and update return type to TabModel | undefined.

The function calls hooks (useWaveEnv() and useContext()) on lines 81–82 but doesn't follow the React hooks naming convention. Line 86 returns ctxModel, which has type TabModel | undefined per the TabModelContext definition (line 66), creating a type mismatch with the declared TabModel return type. The caller in frontend/app/aipanel/aipanel.tsx (line 260) doesn't check for undefined.

🧰 Tools
🪛 Biome (2.4.6)

[error] 81-81: This hook is being called from within a function or method that is not a hook or component.

(lint/correctness/useHookAtTopLevel)


[error] 82-82: This hook is being called from within a function or method that is not a hook or component.

(lint/correctness/useHookAtTopLevel)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/app/store/tab-model.ts` around lines 80 - 87, Rename the hook
function maybeUseTabModel to useMaybeTabModel to follow React hook naming,
change its return type from TabModel to TabModel | undefined, and update its
implementation signature accordingly (it already calls useWaveEnv() and
useContext(TabModelContext)); then update all call sites (notably the caller in
aipanel.tsx) to handle the possible undefined return (add a null/undefined check
or early return) so consumers no longer assume a guaranteed TabModel.

Comment on lines +221 to +258
const waveObjectDerivedAtomCache = new Map<string, Atom<any>>();

function getWaveObjectAtom<T extends WaveObj>(oref: string): Atom<T> {
const cacheKey = oref + ":value";
let cachedAtom = waveObjectDerivedAtomCache.get(cacheKey) as Atom<T>;
if (cachedAtom != null) {
return cachedAtom;
}
const wov = getWaveObjectValue<T>(oref);
return atom((get) => get(wov.dataAtom).value);
cachedAtom = atom((get) => get(wov.dataAtom).value);
waveObjectDerivedAtomCache.set(cacheKey, cachedAtom);
return cachedAtom;
}

function getWaveObjectLoadingAtom(oref: string): Atom<boolean> {
const cacheKey = oref + ":loading";
let cachedAtom = waveObjectDerivedAtomCache.get(cacheKey) as Atom<boolean>;
if (cachedAtom != null) {
return cachedAtom;
}
const wov = getWaveObjectValue(oref);
return atom((get) => {
cachedAtom = atom((get) => {
const dataValue = get(wov.dataAtom);
if (dataValue.loading) {
return null;
}
return dataValue.loading;
});
waveObjectDerivedAtomCache.set(cacheKey, cachedAtom);
return cachedAtom;
}

function isWaveObjectNullAtom(oref: string): Atom<boolean> {
const cacheKey = oref + ":isnull";
let cachedAtom = waveObjectDerivedAtomCache.get(cacheKey) as Atom<boolean>;
if (cachedAtom != null) {
return cachedAtom;
}
cachedAtom = atom((get) => get(getWaveObjectAtom(oref)) == null);
waveObjectDerivedAtomCache.set(cacheKey, cachedAtom);
return cachedAtom;
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 | 🟠 Major

Evict derived atoms when the backing wov is dropped.

These cached atoms close over the wov.dataAtom captured at creation time. cleanWaveObjectCache() / clearWaveObjectCache() only remove waveObjectValueCache entries, so a later read can return a stale derived atom that's disconnected from the newly created wov and never sees fresh loads or updates. Clear the :value / :loading / :isnull entries alongside the corresponding oref.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/app/store/wos.ts` around lines 221 - 258, The derived-atom cache
entries (created by getWaveObjectAtom, getWaveObjectLoadingAtom, and
isWaveObjectNullAtom) close over the original wov and must be evicted when the
backing WaveObjectValue is dropped; update the cache-clearing logic
(cleanWaveObjectCache/clearWaveObjectCache) to also remove
waveObjectDerivedAtomCache entries for the same oref by deleting keys with the
suffixes ":value", ":loading", and ":isnull" so that subsequent getWaveObject*
calls recreate atoms bound to the new wov.dataAtom instead of returning stale,
disconnected atoms.

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.

🧹 Nitpick comments (1)
frontend/app/block/durable-session-flyover.tsx (1)

199-199: Consider removing the redundant constant.

showRestartButton is always true, making the conditional on line 250 {showRestartButton && ...} redundant. If this is placeholder logic for future conditional behavior, consider adding a comment explaining the intent. Otherwise, the constant and conditional can be removed for clarity.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/app/block/durable-session-flyover.tsx` at line 199, The constant
showRestartButton is always true, making the conditional render around it
redundant; remove the declaration of showRestartButton and the surrounding
conditional (the {showRestartButton && ...} JSX) and render the restart button
directly, or if this was intended as future conditional behavior, replace the
const showRestartButton = true with a short comment (e.g. // toggle to control
restart button visibility) and keep the {showRestartButton && ...} check so the
intent is documented; refer to the symbol showRestartButton and the JSX
conditional where the restart button is rendered to locate the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@frontend/app/block/durable-session-flyover.tsx`:
- Line 199: The constant showRestartButton is always true, making the
conditional render around it redundant; remove the declaration of
showRestartButton and the surrounding conditional (the {showRestartButton &&
...} JSX) and render the restart button directly, or if this was intended as
future conditional behavior, replace the const showRestartButton = true with a
short comment (e.g. // toggle to control restart button visibility) and keep the
{showRestartButton && ...} check so the intent is documented; refer to the
symbol showRestartButton and the JSX conditional where the restart button is
rendered to locate the change.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 655d30e9-9e21-4b0a-ad8d-b3320575298d

📥 Commits

Reviewing files that changed from the base of the PR and between 9ba3baa and 4ad7bad.

📒 Files selected for processing (2)
  • frontend/app/block/blockenv.ts
  • frontend/app/block/durable-session-flyover.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • frontend/app/block/blockenv.ts

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.

🧹 Nitpick comments (1)
.kilocode/skills/waveenv/SKILL.md (1)

121-122: Consider using anchors or removing line numbers from documentation links.

Line number references (:12, :23) will become stale as files evolve. Consider linking to the file without line numbers, or use a named export/heading anchor if supported. Alternatively, use a comment marker in the source files that documentation can reference.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.kilocode/skills/waveenv/SKILL.md around lines 121 - 122, The documentation
links in SKILL.md point to specific line numbers for BlockEnv and WidgetsEnv
which will become stale; update the links to target the file or a stable anchor
instead by removing the ":12" and ":23" line suffixes from the BlockEnv and
WidgetsEnv links, or add named export/heading anchors (or a comment marker) in
the source near the BlockEnv and WidgetsEnv declarations and update the SKILL.md
links to use those anchors so references stay stable as the files change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In @.kilocode/skills/waveenv/SKILL.md:
- Around line 121-122: The documentation links in SKILL.md point to specific
line numbers for BlockEnv and WidgetsEnv which will become stale; update the
links to target the file or a stable anchor instead by removing the ":12" and
":23" line suffixes from the BlockEnv and WidgetsEnv links, or add named
export/heading anchors (or a comment marker) in the source near the BlockEnv and
WidgetsEnv declarations and update the SKILL.md links to use those anchors so
references stay stable as the files change.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: a123c0af-94f6-414c-b8c0-94a39c25dcba

📥 Commits

Reviewing files that changed from the base of the PR and between 4ad7bad and 92d7bde.

📒 Files selected for processing (4)
  • .kilocode/skills/waveenv/SKILL.md
  • frontend/app/block/blockenv.ts
  • frontend/app/waveenv/waveenv.ts
  • frontend/app/workspace/widgets.tsx

const waveEnv = useWaveEnv<BlockEnv>();
const handleDisconnect = React.useCallback(() => {
const prtn = RpcApi.ConnDisconnectCommand(TabRpcClient, connName, { timeout: 5000 });
const prtn = waveEnv.rpc.ConnDisconnectCommand(TabRpcClient, connName, { timeout: 5000 });
Copy link
Contributor

Choose a reason for hiding this comment

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

CRITICAL: Missing waveEnv in useCallback dependency array. The callback uses waveEnv but only includes connName. This can cause stale closures.

@@ -138,13 +140,13 @@ export const ConnStatusOverlay = React.memo(
}, [width, connStatus, setShowError]);

Copy link
Contributor

Choose a reason for hiding this comment

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

CRITICAL: Missing waveEnv in useCallback dependency array. The callback uses waveEnv but only includes connName and nodeModel.blockId. This can cause stale closures.

@@ -155,19 +157,19 @@ export const ConnStatusOverlay = React.memo(
metamaptype: metamaptype,
};
Copy link
Contributor

Choose a reason for hiding this comment

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

CRITICAL: Missing waveEnv in useCallback dependency array. The callback uses waveEnv but only includes connName. This can cause stale closures.

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.

🧹 Nitpick comments (1)
.kilocode/skills/waveenv/SKILL.md (1)

16-18: Optional: Consider rephrasing to reduce repetition.

The phrase "you want to" appears twice in the same sentence. For stylistic variety, consider:

"Create a narrowing when writing a component (or group of components) for testing in the preview server, or to make the environmental dependencies of a component tree explicit."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.kilocode/skills/waveenv/SKILL.md around lines 16 - 18, The sentence under
the "When To Create One" heading repeats the phrase "you want to"; edit the
sentence to improve style and remove duplication (for example: "Create a
narrowing when writing a component (or group of components) for testing in the
preview server, or to make the environmental dependencies of a component tree
explicit."). Update the content in SKILL.md under the "When To Create One"
section to use the revised wording.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In @.kilocode/skills/waveenv/SKILL.md:
- Around line 16-18: The sentence under the "When To Create One" heading repeats
the phrase "you want to"; edit the sentence to improve style and remove
duplication (for example: "Create a narrowing when writing a component (or group
of components) for testing in the preview server, or to make the environmental
dependencies of a component tree explicit."). Update the content in SKILL.md
under the "When To Create One" section to use the revised wording.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 4d0ea686-e420-4b46-ae00-3367c58d29df

📥 Commits

Reviewing files that changed from the base of the PR and between 92d7bde and 3c8668c.

📒 Files selected for processing (1)
  • .kilocode/skills/waveenv/SKILL.md

@sawka sawka merged commit cb8166e into main Mar 10, 2026
8 checks passed
@sawka sawka deleted the sawka/mock-for-block branch March 10, 2026 23:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant