diff --git a/docs/docs/releasenotes.mdx b/docs/docs/releasenotes.mdx index 402e28162c..430a0394a3 100644 --- a/docs/docs/releasenotes.mdx +++ b/docs/docs/releasenotes.mdx @@ -6,6 +6,26 @@ sidebar_position: 200 # Release Notes +### v0.12.1 — Oct 20, 2025 + +Patch release focused on shell integration improvements and Wave AI enhancements. This release fixes syntax highlighting in the code editor and adds significant shell context tracking capabilities. + +**Shell Integration & Context:** +- **OSC 7 Support** - Added OSC 7 (current working directory) support across bash, zsh, fish, and pwsh shells. Wave now automatically tracks and restores your current directory across restarts for both local and remote terminals. +- **Shell Context Tracking** - Implemented shell integration for bash, zsh, and fish shells. Wave now tracks when your shell is ready to receive commands, the last command executed, and exit codes. This enhanced context enables better terminal management and lays the groundwork for Wave AI to write and execute commands intelligently. + +**Wave AI Improvements:** +- Display reasoning summaries in the UI while waiting for AI responses +- Added enhanced terminal context - Wave AI now has access to shell state including current directory, command history, and exit codes +- Added feedback buttons (thumbs up/down) for AI responses to help improve the experience +- Added copy button to easily copy AI responses to clipboard + +**Other Changes:** +- Mobile user agent emulation support for web widgets [#2442](https://github.com/wavetermdev/waveterm/issues/2442) +- [bugfix] Fixed padding for header buttons in code editor (Tailwind regression) +- [bugfix] Restored syntax highlighting in code editor preview blocks [#2427](https://github.com/wavetermdev/waveterm/issues/2427) +- Package updates and dependency bumps + ### v0.12.0 — Oct 16, 2025 **Wave v0.12 Has Arrived with Wave AI (beta)!** diff --git a/frontend/app/modals/about.tsx b/frontend/app/modals/about.tsx index 739efc5e4f..b448e4bbe7 100644 --- a/frontend/app/modals/about.tsx +++ b/frontend/app/modals/about.tsx @@ -17,7 +17,7 @@ const AboutModal = ({}: AboutModalProps) => { const [updaterChannel] = useState(() => getApi().getUpdaterChannel()); return ( - modalsModel.popModal()}> + modalsModel.popModal()}>
diff --git a/frontend/app/modals/modalsrenderer.tsx b/frontend/app/modals/modalsrenderer.tsx index e8a95ea925..8576fb3be3 100644 --- a/frontend/app/modals/modalsrenderer.tsx +++ b/frontend/app/modals/modalsrenderer.tsx @@ -2,13 +2,13 @@ // SPDX-License-Identifier: Apache-2.0 import { NewInstallOnboardingModal } from "@/app/onboarding/onboarding"; -import { CurrentOnboardingVersion } from "@/app/onboarding/onboarding-features"; +import { CurrentOnboardingVersion } from "@/app/onboarding/onboarding-common"; import { UpgradeOnboardingModal } from "@/app/onboarding/onboarding-upgrade"; import { atoms, globalPrimaryTabStartup, globalStore } from "@/store/global"; import { modalsModel } from "@/store/modalmodel"; import * as jotai from "jotai"; import { useEffect } from "react"; -import semver from "semver"; +import * as semver from "semver"; import { getModalComponent } from "./modalregistry"; const ModalsRenderer = () => { diff --git a/frontend/app/onboarding/onboarding-common.tsx b/frontend/app/onboarding/onboarding-common.tsx new file mode 100644 index 0000000000..80cec552c2 --- /dev/null +++ b/frontend/app/onboarding/onboarding-common.tsx @@ -0,0 +1,4 @@ +// Copyright 2025, Command Line Inc. +// SPDX-License-Identifier: Apache-2.0 + +export const CurrentOnboardingVersion = "v0.12.1"; diff --git a/frontend/app/onboarding/onboarding-features.tsx b/frontend/app/onboarding/onboarding-features.tsx index 2b88f7cb45..b5f1706c4c 100644 --- a/frontend/app/onboarding/onboarding-features.tsx +++ b/frontend/app/onboarding/onboarding-features.tsx @@ -12,11 +12,10 @@ import { TabRpcClient } from "@/app/store/wshrpcutil"; import { isMacOS } from "@/util/platformutil"; import { useEffect, useState } from "react"; import { FakeChat } from "./fakechat"; +import { CurrentOnboardingVersion } from "./onboarding-common"; import { EditBashrcCommand, ViewLogoCommand, ViewShortcutsCommand } from "./onboarding-command"; import { FakeLayout } from "./onboarding-layout"; -export const CurrentOnboardingVersion = "v0.12.0"; - type FeaturePageName = "waveai" | "magnify" | "files"; const OnboardingFooter = ({ diff --git a/frontend/app/onboarding/onboarding-upgrade-v0120.tsx b/frontend/app/onboarding/onboarding-upgrade-v0120.tsx new file mode 100644 index 0000000000..2e1fe52ca8 --- /dev/null +++ b/frontend/app/onboarding/onboarding-upgrade-v0120.tsx @@ -0,0 +1,201 @@ +// Copyright 2025, Command Line Inc. +// SPDX-License-Identifier: Apache-2.0 + +import Logo from "@/app/asset/logo.svg"; +import { Button } from "@/app/element/button"; +import { FlexiModal } from "@/app/modals/modal"; +import { CurrentOnboardingVersion } from "@/app/onboarding/onboarding-common"; +import { OnboardingFeatures } from "@/app/onboarding/onboarding-features"; +import { atoms, globalStore } from "@/app/store/global"; +import { disableGlobalKeybindings, enableGlobalKeybindings, globalRefocus } from "@/app/store/keymodel"; +import { modalsModel } from "@/app/store/modalmodel"; +import * as WOS from "@/app/store/wos"; +import { RpcApi } from "@/app/store/wshclientapi"; +import { TabRpcClient } from "@/app/store/wshrpcutil"; +import { OverlayScrollbarsComponent } from "overlayscrollbars-react"; +import { useEffect, useRef, useState } from "react"; +import { debounce } from "throttle-debounce"; + +const UpgradeOnboardingModal_v0_12_0 = () => { + const modalRef = useRef(null); + const [pageName, setPageName] = useState<"welcome" | "features">("welcome"); + const [isCompact, setIsCompact] = useState(window.innerHeight < 800); + + const updateModalHeight = () => { + const windowHeight = window.innerHeight; + setIsCompact(windowHeight < 800); + if (modalRef.current) { + const modalHeight = modalRef.current.offsetHeight; + const maxHeight = windowHeight * 0.9; + if (maxHeight < modalHeight) { + modalRef.current.style.height = `${maxHeight}px`; + } else { + modalRef.current.style.height = "auto"; + } + } + }; + + useEffect(() => { + updateModalHeight(); + const debouncedUpdateModalHeight = debounce(150, updateModalHeight); + window.addEventListener("resize", debouncedUpdateModalHeight); + return () => { + window.removeEventListener("resize", debouncedUpdateModalHeight); + }; + }, []); + + useEffect(() => { + disableGlobalKeybindings(); + return () => { + enableGlobalKeybindings(); + }; + }, []); + + const handleStarClick = async () => { + RpcApi.RecordTEventCommand( + TabRpcClient, + { + event: "onboarding:githubstar", + props: { "onboarding:githubstar": "star" }, + }, + { noresponse: true } + ); + const clientId = globalStore.get(atoms.clientId); + await RpcApi.SetMetaCommand(TabRpcClient, { + oref: WOS.makeORef("client", clientId), + meta: { "onboarding:githubstar": true }, + }); + window.open("https://github.com/wavetermdev/waveterm?ref=upgrade", "_blank"); + setPageName("features"); + }; + + const handleAlreadyStarred = async () => { + RpcApi.RecordTEventCommand( + TabRpcClient, + { + event: "onboarding:githubstar", + props: { "onboarding:githubstar": "already" }, + }, + { noresponse: true } + ); + const clientId = globalStore.get(atoms.clientId); + await RpcApi.SetMetaCommand(TabRpcClient, { + oref: WOS.makeORef("client", clientId), + meta: { "onboarding:githubstar": true }, + }); + setPageName("features"); + }; + + const handleMaybeLater = async () => { + RpcApi.RecordTEventCommand( + TabRpcClient, + { + event: "onboarding:githubstar", + props: { "onboarding:githubstar": "later" }, + }, + { noresponse: true } + ); + const clientId = globalStore.get(atoms.clientId); + await RpcApi.SetMetaCommand(TabRpcClient, { + oref: WOS.makeORef("client", clientId), + meta: { "onboarding:githubstar": false }, + }); + setPageName("features"); + }; + + const handleFeaturesComplete = () => { + const clientId = globalStore.get(atoms.clientId); + RpcApi.SetMetaCommand(TabRpcClient, { + oref: WOS.makeORef("client", clientId), + meta: { "onboarding:lastversion": CurrentOnboardingVersion }, + }); + globalStore.set(modalsModel.upgradeOnboardingOpen, false); + setTimeout(() => { + globalRefocus(); + }, 10); + }; + + let pageComp: React.JSX.Element = null; + if (pageName === "welcome") { + pageComp = ( +
+
+
+ +
+
Welcome to Wave v0.12!
+
+ +
+
+
+ + Wave AI +
+
+

+ Wave AI is your new terminal assistant with full context. It can read your terminal + output, analyze widgets, access files, and help you solve problems faster. +

+

+ Wave AI is in active beta with included AI credits while we refine the experience. + We're actively improving it and would love your feedback in{" "} + + Discord + + . +

+
+
+ +
+ +
+
Thanks for being an early Wave adopter! ⭐
+
+ A GitHub star shows your support for Wave (and open-source) and helps us reach more + developers. +
+
+
+
+
+
+ + + +
+
+
+ ); + } else if (pageName === "features") { + pageComp = ; + } + + if (pageComp == null) { + return null; + } + + const paddingClass = isCompact ? "!py-3 !px-[30px]" : "!p-[30px]"; + const widthClass = pageName === "features" ? "w-[800px]" : "w-[560px]"; + + return ( + +
+
{pageComp}
+ + ); +}; + +UpgradeOnboardingModal_v0_12_0.displayName = "UpgradeOnboardingModal_v0_12_0"; + +export { UpgradeOnboardingModal_v0_12_0 }; \ No newline at end of file diff --git a/frontend/app/onboarding/onboarding-upgrade-v0121.tsx b/frontend/app/onboarding/onboarding-upgrade-v0121.tsx new file mode 100644 index 0000000000..051b623cb7 --- /dev/null +++ b/frontend/app/onboarding/onboarding-upgrade-v0121.tsx @@ -0,0 +1,170 @@ +// Copyright 2025, Command Line Inc. +// SPDX-License-Identifier: Apache-2.0 + +import Logo from "@/app/asset/logo.svg"; +import { Button } from "@/app/element/button"; +import { FlexiModal } from "@/app/modals/modal"; +import { CurrentOnboardingVersion } from "@/app/onboarding/onboarding-common"; +import { atoms, globalStore } from "@/app/store/global"; +import { disableGlobalKeybindings, enableGlobalKeybindings, globalRefocus } from "@/app/store/keymodel"; +import { modalsModel } from "@/app/store/modalmodel"; +import * as WOS from "@/app/store/wos"; +import { RpcApi } from "@/app/store/wshclientapi"; +import { TabRpcClient } from "@/app/store/wshrpcutil"; +import { OverlayScrollbarsComponent } from "overlayscrollbars-react"; +import { useEffect, useRef, useState } from "react"; +import { debounce } from "throttle-debounce"; + +const UpgradeOnboardingModal_v0_12_1 = () => { + const modalRef = useRef(null); + const [isCompact, setIsCompact] = useState(window.innerHeight < 800); + + const updateModalHeight = () => { + const windowHeight = window.innerHeight; + setIsCompact(windowHeight < 800); + if (modalRef.current) { + const modalHeight = modalRef.current.offsetHeight; + const maxHeight = windowHeight * 0.9; + if (maxHeight < modalHeight) { + modalRef.current.style.height = `${maxHeight}px`; + } else { + modalRef.current.style.height = "auto"; + } + } + }; + + useEffect(() => { + updateModalHeight(); + const debouncedUpdateModalHeight = debounce(150, updateModalHeight); + window.addEventListener("resize", debouncedUpdateModalHeight); + return () => { + window.removeEventListener("resize", debouncedUpdateModalHeight); + }; + }, []); + + useEffect(() => { + disableGlobalKeybindings(); + return () => { + enableGlobalKeybindings(); + }; + }, []); + + const handleClose = () => { + const clientId = globalStore.get(atoms.clientId); + RpcApi.SetMetaCommand(TabRpcClient, { + oref: WOS.makeORef("client", clientId), + meta: { "onboarding:lastversion": CurrentOnboardingVersion }, + }); + globalStore.set(modalsModel.upgradeOnboardingOpen, false); + setTimeout(() => { + globalRefocus(); + }, 10); + }; + + const paddingClass = isCompact ? "!py-3 !px-[30px]" : "!p-[30px]"; + + return ( + +
+
+
+
+
+ +
+
Wave v0.12.1 Update
+
+ +
+
+

+ Patch release focused on shell integration improvements, Wave AI enhancements, and + restoring syntax highlighting in code editor blocks. +

+
+ +
+
+ +
+
+
+ Shell Integration & Context +
+
+
    +
  • + OSC 7 Support - Wave now automatically tracks and + restores your current directory across restarts for bash, zsh, fish, and + pwsh shells +
  • +
  • + Shell Context Tracking - Tracks when your shell is + ready, last command executed, and exit codes for better terminal + management +
  • +
+
+
+
+ +
+
+ +
+
+
+ Wave AI Improvements +
+
+
    +
  • Display reasoning summaries while waiting for AI responses
  • +
  • + Enhanced terminal context - AI now has access to shell state, current + directory, command history, and exit codes +
  • +
  • Added feedback buttons (thumbs up/down) for AI responses
  • +
  • Added copy button to easily copy AI responses to clipboard
  • +
+
+
+
+ +
+
+ +
+
+
+ Other Changes +
+
+
    +
  • Mobile user agent emulation support for web widgets
  • +
  • Fixed padding for header buttons in code editor
  • +
  • Restored syntax highlighting in code editor preview blocks
  • +
+
+
+
+
+
+
+
+ +
+
+
+
+ + ); +}; + +UpgradeOnboardingModal_v0_12_1.displayName = "UpgradeOnboardingModal_v0_12_1"; + +export { UpgradeOnboardingModal_v0_12_1 }; diff --git a/frontend/app/onboarding/onboarding-upgrade.tsx b/frontend/app/onboarding/onboarding-upgrade.tsx index 2de94f1e75..c2c7a98537 100644 --- a/frontend/app/onboarding/onboarding-upgrade.tsx +++ b/frontend/app/onboarding/onboarding-upgrade.tsx @@ -1,181 +1,39 @@ // Copyright 2025, Command Line Inc. // SPDX-License-Identifier: Apache-2.0 -import Logo from "@/app/asset/logo.svg"; -import { Button } from "@/app/element/button"; -import { FlexiModal } from "@/app/modals/modal"; -import { OnboardingFeatures } from "@/app/onboarding/onboarding-features"; import { atoms, globalStore } from "@/app/store/global"; -import { disableGlobalKeybindings, enableGlobalKeybindings, globalRefocus } from "@/app/store/keymodel"; import { modalsModel } from "@/app/store/modalmodel"; -import * as WOS from "@/app/store/wos"; -import { RpcApi } from "@/app/store/wshclientapi"; -import { TabRpcClient } from "@/app/store/wshrpcutil"; -import { OverlayScrollbarsComponent } from "overlayscrollbars-react"; -import { useEffect, useRef, useState } from "react"; -import { debounce } from "throttle-debounce"; +import { useAtomValue } from "jotai"; +import { useEffect, useRef } from "react"; +import * as semver from "semver"; +import { UpgradeOnboardingModal_v0_12_0 } from "./onboarding-upgrade-v0120"; +import { UpgradeOnboardingModal_v0_12_1 } from "./onboarding-upgrade-v0121"; const UpgradeOnboardingModal = () => { - const modalRef = useRef(null); - const [pageName, setPageName] = useState<"welcome" | "features">("welcome"); - const [isCompact, setIsCompact] = useState(window.innerHeight < 800); + const clientData = useAtomValue(atoms.client); + const initialVersionRef = useRef(null); - const updateModalHeight = () => { - const windowHeight = window.innerHeight; - setIsCompact(windowHeight < 800); - if (modalRef.current) { - const modalHeight = modalRef.current.offsetHeight; - const maxHeight = windowHeight * 0.9; - if (maxHeight < modalHeight) { - modalRef.current.style.height = `${maxHeight}px`; - } else { - modalRef.current.style.height = "auto"; - } - } - }; + if (initialVersionRef.current == null) { + initialVersionRef.current = clientData.meta?.["onboarding:lastversion"] ?? "v0.0.0"; + } - useEffect(() => { - updateModalHeight(); - const debouncedUpdateModalHeight = debounce(150, updateModalHeight); - window.addEventListener("resize", debouncedUpdateModalHeight); - return () => { - window.removeEventListener("resize", debouncedUpdateModalHeight); - }; - }, []); + const lastVersion = initialVersionRef.current; useEffect(() => { - disableGlobalKeybindings(); - return () => { - enableGlobalKeybindings(); - }; - }, []); - - const handleStarClick = async () => { - RpcApi.RecordTEventCommand(TabRpcClient, { - event: "onboarding:githubstar", - props: { "onboarding:githubstar": "star" }, - }, { noresponse: true }); - const clientId = globalStore.get(atoms.clientId); - await RpcApi.SetMetaCommand(TabRpcClient, { - oref: WOS.makeORef("client", clientId), - meta: { "onboarding:githubstar": true }, - }); - window.open("https://github.com/wavetermdev/waveterm?ref=upgrade", "_blank"); - setPageName("features"); - }; - - const handleAlreadyStarred = async () => { - RpcApi.RecordTEventCommand(TabRpcClient, { - event: "onboarding:githubstar", - props: { "onboarding:githubstar": "already" }, - }, { noresponse: true }); - const clientId = globalStore.get(atoms.clientId); - await RpcApi.SetMetaCommand(TabRpcClient, { - oref: WOS.makeORef("client", clientId), - meta: { "onboarding:githubstar": true }, - }); - setPageName("features"); - }; - - const handleMaybeLater = async () => { - RpcApi.RecordTEventCommand(TabRpcClient, { - event: "onboarding:githubstar", - props: { "onboarding:githubstar": "later" }, - }, { noresponse: true }); - const clientId = globalStore.get(atoms.clientId); - await RpcApi.SetMetaCommand(TabRpcClient, { - oref: WOS.makeORef("client", clientId), - meta: { "onboarding:githubstar": false }, - }); - setPageName("features"); - }; - - const handleFeaturesComplete = () => { - globalStore.set(modalsModel.upgradeOnboardingOpen, false); - setTimeout(() => { - globalRefocus(); - }, 10); - }; - - let pageComp: React.JSX.Element = null; - if (pageName === "welcome") { - pageComp = ( -
-
-
- -
-
Welcome to Wave v0.12!
-
- -
-
-
- - Wave AI -
-
-

- Wave AI is your new terminal assistant with full context. It can read your terminal - output, analyze widgets, access files, and help you solve problems faster. -

-

- Wave AI is in active beta with included AI credits while we refine the experience. - We're actively improving it and would love your feedback in{" "} - - Discord - - . -

-
-
- -
- -
-
Thanks for being an early Wave adopter! ⭐
-
- A GitHub star shows your support for Wave (and open-source) and helps us reach more - developers. -
-
-
-
-
-
- - - -
-
-
- ); - } else if (pageName === "features") { - pageComp = ; - } + if (semver.gte(lastVersion, "v0.12.1")) { + globalStore.set(modalsModel.upgradeOnboardingOpen, false); + } + }, [lastVersion]); - if (pageComp == null) { + if (semver.gte(lastVersion, "v0.12.1")) { return null; } - const paddingClass = isCompact ? "!py-3 !px-[30px]" : "!p-[30px]"; - const widthClass = pageName === "features" ? "w-[800px]" : "w-[560px]"; + if (semver.gte(lastVersion, "v0.12.0")) { + return ; + } - return ( - -
-
{pageComp}
- - ); + return ; }; UpgradeOnboardingModal.displayName = "UpgradeOnboardingModal"; diff --git a/frontend/app/view/preview/preview-model.tsx b/frontend/app/view/preview/preview-model.tsx index 2c53cd11c4..2ab8f0b29e 100644 --- a/frontend/app/view/preview/preview-model.tsx +++ b/frontend/app/view/preview/preview-model.tsx @@ -79,6 +79,13 @@ function isStreamingType(mimeType: string): boolean { ); } +function isMarkdownLike(mimeType: string): boolean { + if (mimeType == null) { + return false; + } + return mimeType.startsWith("text/markdown") || mimeType.startsWith("text/mdx"); +} + function iconForFile(mimeType: string): string { if (mimeType == null) { mimeType = "unknown"; @@ -91,7 +98,7 @@ function iconForFile(mimeType: string): string { return "film"; } else if (mimeType.startsWith("audio/")) { return "headphones"; - } else if (mimeType.startsWith("text/markdown")) { + } else if (isMarkdownLike(mimeType)) { return "file-lines"; } else if (mimeType == "text/csv") { return "file-csv"; @@ -333,7 +340,7 @@ export class PreviewModel implements ViewModel { click: () => this.refreshCallback?.(), }, ] as IconButtonDecl[]; - } else if (!isCeView && mimeType?.startsWith("text/markdown")) { + } else if (!isCeView && isMarkdownLike(mimeType)) { return [ { elemtype: "iconbutton", @@ -508,7 +515,7 @@ export class PreviewModel implements ViewModel { } return { specializedView: "csv" }; } - if (mimeType.startsWith("text/markdown")) { + if (isMarkdownLike(mimeType)) { if (editMode) { return { specializedView: "codeedit" }; }