diff --git a/frontend/app/aipanel/aipanel-contextmenu.ts b/frontend/app/aipanel/aipanel-contextmenu.ts index db6edc9577..a783af7a4c 100644 --- a/frontend/app/aipanel/aipanel-contextmenu.ts +++ b/frontend/app/aipanel/aipanel-contextmenu.ts @@ -3,23 +3,26 @@ import { waveAIHasSelection } from "@/app/aipanel/waveai-focus-utils"; import { ContextMenuModel } from "@/app/store/contextmenu"; +import { isDev } from "@/app/store/global"; import { RpcApi } from "@/app/store/wshclientapi"; import { TabRpcClient } from "@/app/store/wshrpcutil"; import { WaveAIModel } from "./waveai-model"; -export async function handleWaveAIContextMenu(e: React.MouseEvent, onClose?: () => void): Promise { +export async function handleWaveAIContextMenu(e: React.MouseEvent, showCopy: boolean): Promise { e.preventDefault(); e.stopPropagation(); const model = WaveAIModel.getInstance(); const menu: ContextMenuItem[] = []; - const hasSelection = waveAIHasSelection(); - if (hasSelection) { - menu.push({ - role: "copy", - }); - menu.push({ type: "separator" }); + if (showCopy) { + const hasSelection = waveAIHasSelection(); + if (hasSelection) { + menu.push({ + role: "copy", + }); + menu.push({ type: "separator" }); + } } menu.push({ @@ -103,6 +106,19 @@ export async function handleWaveAIContextMenu(e: React.MouseEvent, onClose?: () } ); } else { + if (isDev()) { + maxTokensSubmenu.push({ + label: "1k (Dev Testing)", + type: "checkbox", + checked: currentMaxTokens === 1024, + click: () => { + RpcApi.SetRTInfoCommand(TabRpcClient, { + oref: model.orefContext, + data: { "waveai:maxoutputtokens": 1024 }, + }); + }, + }); + } maxTokensSubmenu.push( { label: "4k", @@ -150,14 +166,16 @@ export async function handleWaveAIContextMenu(e: React.MouseEvent, onClose?: () submenu: maxTokensSubmenu, }); - menu.push({ type: "separator" }); + if (model.canCloseWaveAIPanel()) { + menu.push({ type: "separator" }); - menu.push({ - label: "Hide Wave AI", - click: () => { - onClose?.(); - }, - }); + menu.push({ + label: "Hide Wave AI", + click: () => { + model.closeWaveAIPanel(); + }, + }); + } ContextMenuModel.showContextMenu(menu, e); -} \ No newline at end of file +} diff --git a/frontend/app/aipanel/aipanel.tsx b/frontend/app/aipanel/aipanel.tsx index 6ef092909d..1fb3c05ba4 100644 --- a/frontend/app/aipanel/aipanel.tsx +++ b/frontend/app/aipanel/aipanel.tsx @@ -203,11 +203,7 @@ const AIErrorMessage = memo(({ errorMessage, onClear }: AIErrorMessageProps) => AIErrorMessage.displayName = "AIErrorMessage"; -interface AIPanelProps { - onClose?: () => void; -} - -const AIPanelComponentInner = memo(({ onClose }: AIPanelProps) => { +const AIPanelComponentInner = memo(() => { const [isDragOver, setIsDragOver] = useState(false); const [isReactDndDragOver, setIsReactDndDragOver] = useState(false); const [initialLoadDone, setInitialLoadDone] = useState(false); @@ -256,10 +252,6 @@ const AIPanelComponentInner = memo(({ onClose }: AIPanelProps) => { // console.log("AICHAT messages", messages); - const handleClearChat = useCallback(() => { - model.clearChat(); - }, [model]); - const handleKeyDown = (waveEvent: WaveKeyboardEvent): boolean => { if (checkKeyPressed(waveEvent, "Cmd:k")) { model.clearChat(); @@ -493,7 +485,7 @@ const AIPanelComponentInner = memo(({ onClose }: AIPanelProps) => { > {(isDragOver || isReactDndDragOver) && } {showBlockMask && } - +
@@ -504,7 +496,7 @@ const AIPanelComponentInner = memo(({ onClose }: AIPanelProps) => { {messages.length === 0 && initialLoadDone ? (
handleWaveAIContextMenu(e, onClose)} + onContextMenu={(e) => handleWaveAIContextMenu(e, true)} > {model.inBuilder ? : }
@@ -512,7 +504,7 @@ const AIPanelComponentInner = memo(({ onClose }: AIPanelProps) => { handleWaveAIContextMenu(e, onClose)} + onContextMenu={(e) => handleWaveAIContextMenu(e, true)} /> )} {errorMessage && ( @@ -529,10 +521,10 @@ const AIPanelComponentInner = memo(({ onClose }: AIPanelProps) => { AIPanelComponentInner.displayName = "AIPanelInner"; -const AIPanelComponent = ({ onClose }: AIPanelProps) => { +const AIPanelComponent = () => { return ( - + ); }; diff --git a/frontend/app/aipanel/aipanelheader.tsx b/frontend/app/aipanel/aipanelheader.tsx index d37287cb0d..d6b5d43cb2 100644 --- a/frontend/app/aipanel/aipanelheader.tsx +++ b/frontend/app/aipanel/aipanelheader.tsx @@ -1,38 +1,18 @@ // Copyright 2025, Command Line Inc. // SPDX-License-Identifier: Apache-2.0 -import { ContextMenuModel } from "@/app/store/contextmenu"; +import { handleWaveAIContextMenu } from "@/app/aipanel/aipanel-contextmenu"; import { useAtomValue } from "jotai"; import { memo } from "react"; import { WaveAIModel } from "./waveai-model"; -interface AIPanelHeaderProps { - onClose?: () => void; - model: WaveAIModel; - onClearChat?: () => void; -} - -export const AIPanelHeader = memo(({ onClose, model, onClearChat }: AIPanelHeaderProps) => { +export const AIPanelHeader = memo(() => { + const model = WaveAIModel.getInstance(); const widgetAccess = useAtomValue(model.widgetAccessAtom); const inBuilder = model.inBuilder; const handleKebabClick = (e: React.MouseEvent) => { - const menu: ContextMenuItem[] = [ - { - label: "New Chat", - click: () => { - onClearChat?.(); - }, - }, - { type: "separator" }, - { - label: "Hide Wave AI", - click: () => { - onClose?.(); - }, - }, - ]; - ContextMenuModel.showContextMenu(menu, e); + handleWaveAIContextMenu(e, false); }; return ( diff --git a/frontend/app/aipanel/waveai-model.tsx b/frontend/app/aipanel/waveai-model.tsx index 3daeb4872c..d19f890586 100644 --- a/frontend/app/aipanel/waveai-model.tsx +++ b/frontend/app/aipanel/waveai-model.tsx @@ -542,4 +542,18 @@ export class WaveAIModel { globalStore.set(this.restoreBackupStatus, "error"); } } + + canCloseWaveAIPanel(): boolean { + if (this.inBuilder) { + return false; + } + return true; + } + + closeWaveAIPanel() { + if (this.inBuilder) { + return; + } + WorkspaceLayoutModel.getInstance().setAIPanelVisible(false); + } } diff --git a/frontend/app/workspace/workspace.tsx b/frontend/app/workspace/workspace.tsx index e624e5f2a4..3a74047462 100644 --- a/frontend/app/workspace/workspace.tsx +++ b/frontend/app/workspace/workspace.tsx @@ -58,7 +58,7 @@ const WorkspaceElem = memo(() => { >
- workspaceLayoutModel.setAIPanelVisible(false)} /> +