Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .kilocode/skills/create-view/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,8 @@ Create a new file for your view model (e.g., `frontend/app/view/myview/myview-mo

```typescript
import { BlockNodeModel } from "@/app/block/blocktypes";
import { WOS, globalStore, useBlockAtom } from "@/store/global";
import { globalStore } from "@/app/store/jotaiStore";
import { WOS, useBlockAtom } from "@/store/global";
import * as jotai from "jotai";
import { MyView } from "./myview";

Expand Down
3 changes: 2 additions & 1 deletion aiprompts/newview.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,8 @@ Create a new file for your view model (e.g., `frontend/app/view/myview/myview-mo

```typescript
import { BlockNodeModel } from "@/app/block/blocktypes";
import { WOS, globalStore, useBlockAtom } from "@/store/global";
import { globalStore } from "@/app/store/jotaiStore";
import { WOS, useBlockAtom } from "@/store/global";
import * as jotai from "jotai";
import { MyView } from "./myview";

Expand Down
3 changes: 2 additions & 1 deletion frontend/app/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,14 @@ import {
} from "@/app/store/badge";
import { ClientModel } from "@/app/store/client-model";
import { GlobalModel } from "@/app/store/global-model";
import { globalStore } from "@/app/store/jotaiStore";
import { getTabModelByTabId, TabModelContext } from "@/app/store/tab-model";
import { WaveEnvContext } from "@/app/waveenv/waveenv";
import { makeWaveEnvImpl } from "@/app/waveenv/waveenvimpl";
import { Workspace } from "@/app/workspace/workspace";
import { getLayoutModelForStaticTab } from "@/layout/index";
import { ContextMenuModel } from "@/store/contextmenu";
import { atoms, createBlock, getSettingsPrefixAtom, globalStore } from "@/store/global";
import { atoms, createBlock, getSettingsPrefixAtom } from "@/store/global";
import { appHandleKeyDown, keyboardMouseDownHandler } from "@/store/keymodel";
import { getElemAsStr } from "@/util/focusutil";
import * as keyutil from "@/util/keyutil";
Expand Down
3 changes: 2 additions & 1 deletion frontend/app/modals/modalsrenderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import { NewInstallOnboardingModal } from "@/app/onboarding/onboarding";
import { CurrentOnboardingVersion } from "@/app/onboarding/onboarding-common";
import { UpgradeOnboardingModal } from "@/app/onboarding/onboarding-upgrade";
import { ClientModel } from "@/app/store/client-model";
import { atoms, globalPrimaryTabStartup, globalStore } from "@/store/global";
import { globalStore } from "@/app/store/jotaiStore";
import { atoms, globalPrimaryTabStartup } from "@/store/global";
import { modalsModel } from "@/store/modalmodel";
import * as jotai from "jotai";
import { useEffect } from "react";
Expand Down
2 changes: 1 addition & 1 deletion frontend/app/view/aifilediff/aifilediff.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import type { TabModel } from "@/app/store/tab-model";
import { TabRpcClient } from "@/app/store/wshrpcutil";
import { DiffViewer } from "@/app/view/codeeditor/diffviewer";
import type { WaveEnv, WaveEnvSubset } from "@/app/waveenv/waveenv";
import { globalStore, WOS } from "@/store/global";
import { globalStore } from "@/store/jotaiStore";
Copy link
Contributor

@coderabbitai coderabbitai bot Mar 18, 2026

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:

#!/bin/bash
set -euo pipefail

echo "# candidate jotaiStore modules"
fd 'jotaiStore\.(ts|tsx)$'

echo
echo "# globalStore exports / re-exports"
fd 'jotaiStore\.(ts|tsx)$' -x rg -n 'globalStore|export .* from'

echo
echo "# import under review"
sed -n '1,20p' frontend/app/view/aifilediff/aifilediff.tsx

Repository: wavetermdev/waveterm

Length of output: 907


Update import path to match the actual module location.

The import on line 9 uses @/store/jotaiStore, but the only jotaiStore module exists at frontend/app/store/jotaiStore.ts. This import will fail module resolution. Update it to match the path used throughout the rest of the migration:

Required change
-import { globalStore } from "@/store/jotaiStore";
+import { globalStore } from "@/app/store/jotaiStore";
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import { globalStore } from "@/store/jotaiStore";
import { globalStore } from "@/app/store/jotaiStore";
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/app/view/aifilediff/aifilediff.tsx` at line 9, The import currently
referencing "@/store/jotaiStore" should be updated to the actual module location
used elsewhere so the module resolves; replace the import statement that brings
in globalStore from "@/store/jotaiStore" with the correct module specifier used
in the migration (the module that exports globalStore from
frontend/app/store/jotaiStore.ts) so the named import globalStore continues to
be used unchanged.

Copy link
Member Author

Choose a reason for hiding this comment

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

in tsconfig.json:

        "@/store/*": ["frontend/app/store/*"],

Copy link
Contributor

Choose a reason for hiding this comment

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

@sawka, you're absolutely right — my mistake! The @/store/* alias in tsconfig.json maps to frontend/app/store/*, so @/store/jotaiStore correctly resolves to frontend/app/store/jotaiStore.ts. The import is perfectly valid. Sorry for the noise.


✏️ Learnings added
Learnt from: sawka
Repo: wavetermdev/waveterm PR: 3082
File: frontend/app/view/aifilediff/aifilediff.tsx:9-9
Timestamp: 2026-03-18T23:02:25.531Z
Learning: In the wavetermdev/waveterm repository, the TypeScript path alias `"@/store/*"` maps to `"frontend/app/store/*"` (configured in tsconfig.json). So imports like `import { globalStore } from "@/store/jotaiStore"` correctly resolve to `frontend/app/store/jotaiStore.ts` and should NOT be flagged as incorrect import paths.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

import { base64ToString } from "@/util/util";
import * as jotai from "jotai";
import { useEffect } from "react";
Expand Down
4 changes: 2 additions & 2 deletions frontend/app/view/preview/preview-edit.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
// Copyright 2025, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0

import { globalStore } from "@/app/store/jotaiStore";
import { tryReinjectKey } from "@/app/store/keymodel";
import { CodeEditor } from "@/app/view/codeeditor/codeeditor";
import { globalStore } from "@/store/global";
import { adaptFromReactOrNativeKeyEvent, checkKeyPressed } from "@/util/keyutil";
import { fireAndForget } from "@/util/util";
import { useAtomValue, useSetAtom } from "jotai";
import * as monaco from "monaco-editor";
import type * as MonacoTypes from "monaco-editor";
import * as monaco from "monaco-editor";
import { useEffect } from "react";
import type { SpecializedViewProps } from "./preview";

Expand Down
3 changes: 2 additions & 1 deletion frontend/app/view/preview/preview-markdown.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
// Copyright 2025, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0

import { globalStore } from "@/app/store/jotaiStore";
import { Markdown } from "@/element/markdown";
import { getOverrideConfigAtom, globalStore } from "@/store/global";
import { getOverrideConfigAtom } from "@/store/global";
import { useAtomValue } from "jotai";
import { useEffect, useMemo } from "react";
import type { SpecializedViewProps } from "./preview";
Expand Down
3 changes: 2 additions & 1 deletion frontend/app/view/preview/preview-model.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@

import { BlockNodeModel } from "@/app/block/blocktypes";
import { ContextMenuModel } from "@/app/store/contextmenu";
import { globalStore } from "@/app/store/jotaiStore";
import type { TabModel } from "@/app/store/tab-model";
import { TabRpcClient } from "@/app/store/wshrpcutil";
import { getOverrideConfigAtom, globalStore, refocusNode } from "@/store/global";
import { getOverrideConfigAtom, refocusNode } from "@/store/global";
import * as WOS from "@/store/wos";
import { goHistory, goHistoryBack, goHistoryForward } from "@/util/historyutil";
import { checkKeyPressed } from "@/util/keyutil";
Expand Down
2 changes: 1 addition & 1 deletion frontend/app/view/preview/preview-streaming.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import { Button } from "@/app/element/button";
import { CenteredDiv } from "@/app/element/quickelems";
import { globalStore } from "@/store/global";
import { globalStore } from "@/app/store/jotaiStore";
import { getWebServerEndpoint } from "@/util/endpoints";
import { formatRemoteUri } from "@/util/waveutil";
import { useAtomValue } from "jotai";
Expand Down
2 changes: 1 addition & 1 deletion frontend/app/view/preview/preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
// SPDX-License-Identifier: Apache-2.0

import { CenteredDiv } from "@/app/element/quickelems";
import { globalStore } from "@/app/store/jotaiStore";
import { TabRpcClient } from "@/app/store/wshrpcutil";
import { BlockHeaderSuggestionControl } from "@/app/suggestion/suggestion";
import { useWaveEnv } from "@/app/waveenv/waveenv";
import { globalStore } from "@/store/global";
import { isBlank, makeConnRoute } from "@/util/util";
import { useAtom, useAtomValue, useSetAtom } from "jotai";
import { memo, useEffect } from "react";
Expand Down
3 changes: 2 additions & 1 deletion frontend/app/view/term/term.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ import type { BlockNodeModel } from "@/app/block/blocktypes";
import { NullErrorBoundary } from "@/app/element/errorboundary";
import { Search, useSearch } from "@/app/element/search";
import { ContextMenuModel } from "@/app/store/contextmenu";
import { globalStore } from "@/app/store/jotaiStore";
import { useTabModel } from "@/app/store/tab-model";
import { waveEventSubscribeSingle } from "@/app/store/wps";
import { RpcApi } from "@/app/store/wshclientapi";
import { TabRpcClient } from "@/app/store/wshrpcutil";
import type { TermViewModel } from "@/app/view/term/term-model";
import { atoms, getOverrideConfigAtom, getSettingsPrefixAtom, globalStore, WOS } from "@/store/global";
import { atoms, getOverrideConfigAtom, getSettingsPrefixAtom, WOS } from "@/store/global";
import { fireAndForget, useAtomValueSafe } from "@/util/util";
import { computeBgStyleFromMeta } from "@/util/waveutil";
import { ISearchOptions } from "@xterm/addon-search";
Expand Down
3 changes: 2 additions & 1 deletion frontend/app/view/waveai/waveai.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@ import { Button } from "@/app/element/button";
import { Markdown } from "@/app/element/markdown";
import { TypingIndicator } from "@/app/element/typingindicator";
import { ClientModel } from "@/app/store/client-model";
import { globalStore } from "@/app/store/jotaiStore";
import type { TabModel } from "@/app/store/tab-model";
import { RpcResponseHelper, WshClient } from "@/app/store/wshclient";
import { RpcApi } from "@/app/store/wshclientapi";
import { makeFeBlockRouteId } from "@/app/store/wshrouter";
import { DefaultRouter, TabRpcClient } from "@/app/store/wshrpcutil";
import { WorkspaceLayoutModel } from "@/app/workspace/workspace-layout-model";
import { atoms, createBlock, fetchWaveFile, getApi, globalStore, WOS } from "@/store/global";
import { atoms, createBlock, fetchWaveFile, getApi, WOS } from "@/store/global";
import { BlockService, ObjectService } from "@/store/services";
import { adaptFromReactOrNativeKeyEvent, checkKeyPressed } from "@/util/keyutil";
import { fireAndForget, isBlank, makeIconClass, mergeMeta } from "@/util/util";
Expand Down
3 changes: 2 additions & 1 deletion frontend/app/view/webview/webview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import { BlockNodeModel } from "@/app/block/blocktypes";
import { Search, useSearch } from "@/app/element/search";
import { globalStore } from "@/app/store/jotaiStore";
import { getSimpleControlShiftAtom } from "@/app/store/keymodel";
import type { TabModel } from "@/app/store/tab-model";
import { makeORef } from "@/app/store/wos";
Expand All @@ -14,7 +15,7 @@ import {
} from "@/app/suggestion/suggestion";
import { MockBoundary } from "@/app/waveenv/mockboundary";
import { useWaveEnv } from "@/app/waveenv/waveenv";
import { globalStore, openLink } from "@/store/global";
import { openLink } from "@/store/global";
import { adaptFromReactOrNativeKeyEvent, checkKeyPressed } from "@/util/keyutil";
import { fireAndForget, useAtomValueSafe } from "@/util/util";
import clsx from "clsx";
Expand Down
3 changes: 2 additions & 1 deletion frontend/builder/app-selection-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
// SPDX-License-Identifier: Apache-2.0

import { FlexiModal } from "@/app/modals/modal";
import { globalStore } from "@/app/store/jotaiStore";
import { RpcApi } from "@/app/store/wshclientapi";
import { TabRpcClient } from "@/app/store/wshrpcutil";
import { atoms, getApi, globalStore } from "@/store/global";
import { atoms, getApi } from "@/store/global";
import * as WOS from "@/store/wos";
import { formatRelativeTime } from "@/util/util";
import { useEffect, useState } from "react";
Expand Down
5 changes: 3 additions & 2 deletions frontend/builder/builder-app.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
// Copyright 2025, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0

import { ModalsRenderer } from "@/app/modals/modalsrenderer";
import { globalStore } from "@/app/store/jotaiStore";
import { AppSelectionModal } from "@/builder/app-selection-modal";
import { BuilderWorkspace } from "@/builder/builder-workspace";
import { ModalsRenderer } from "@/app/modals/modalsrenderer";
import { atoms, globalStore, isDev } from "@/store/global";
import { atoms, isDev } from "@/store/global";
import { appHandleKeyDown } from "@/store/keymodel";
import * as keyutil from "@/util/keyutil";
import { isBlank } from "@/util/util";
Expand Down
45 changes: 45 additions & 0 deletions frontend/preview/mock/mock-node-model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright 2026, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0

import { globalStore } from "@/app/store/jotaiStore";
import type { NodeModel } from "@/layout/index";
import { atom } from "jotai";

export type MockNodeModelOpts = {
nodeId: string;
blockId: string;
innerRect?: { width: string; height: string };
numLeafs?: number;
};

export function makeMockNodeModel(opts: MockNodeModelOpts): NodeModel {
const isFocusedAtom = atom(true);
const isMagnifiedAtom = atom(false);

return {
additionalProps: atom({} as any),
innerRect: atom(opts.innerRect ?? { width: "1000px", height: "640px" }),
blockNum: atom(1),
numLeafs: atom(opts.numLeafs ?? 1),
nodeId: opts.nodeId,
blockId: opts.blockId,
addEphemeralNodeToLayout: () => {},
animationTimeS: atom(0),
isResizing: atom(false),
isFocused: isFocusedAtom,
isMagnified: isMagnifiedAtom,
anyMagnified: atom((get) => get(isMagnifiedAtom)),
isEphemeral: atom(false),
ready: atom(true),
disablePointerEvents: atom(false),
toggleMagnify: () => {
globalStore.set(isMagnifiedAtom, !globalStore.get(isMagnifiedAtom));
},
focusNode: () => {
globalStore.set(isFocusedAtom, true);
},
onClose: () => {},
dragHandleRef: { current: null },
displayContainerRef: { current: null },
};
}
Loading
Loading