diff --git a/emain/emain-activity.ts b/emain/emain-activity.ts index 58c12143fd..55861d7046 100644 --- a/emain/emain-activity.ts +++ b/emain/emain-activity.ts @@ -8,6 +8,7 @@ let globalIsQuitting = false; let globalIsStarting = true; let globalIsRelaunching = false; let forceQuit = false; +let termCommandsRun = 0; export function setWasActive(val: boolean) { wasActive = val; @@ -52,3 +53,13 @@ export function setForceQuit(val: boolean) { export function getForceQuit(): boolean { return forceQuit; } + +export function incrementTermCommandsRun() { + termCommandsRun++; +} + +export function getAndClearTermCommandsRun(): number { + const count = termCommandsRun; + termCommandsRun = 0; + return count; +} diff --git a/emain/emain-ipc.ts b/emain/emain-ipc.ts index ebc17363f9..88e4e24b32 100644 --- a/emain/emain-ipc.ts +++ b/emain/emain-ipc.ts @@ -18,6 +18,7 @@ import { getWaveTabViewByWebContentsId } from "./emain-tabview"; import { handleCtrlShiftState } from "./emain-util"; import { getWaveVersion } from "./emain-wavesrv"; import { createNewWaveWindow, focusedWaveWindow, getWaveWindowByWebContentsId } from "./emain-window"; +import { incrementTermCommandsRun } from "./emain-activity"; import { ElectronWshClient } from "./emain-wsh"; const electronApp = electron.app; @@ -395,6 +396,10 @@ export function initIpcHandlers() { console.log("fe-log", logStr); }); + electron.ipcMain.on("increment-term-commands", () => { + incrementTermCommandsRun(); + }); + electron.ipcMain.on("open-builder", (event, appId?: string) => { fireAndForget(() => createBuilderWindow(appId || "")); }); diff --git a/emain/emain.ts b/emain/emain.ts index 3f21e0552f..e4d44e8792 100644 --- a/emain/emain.ts +++ b/emain/emain.ts @@ -12,6 +12,7 @@ import { fireAndForget, sleep } from "../frontend/util/util"; import { AuthKey, configureAuthKeyRequestInjection } from "./authkey"; import { getActivityState, + getAndClearTermCommandsRun, getForceQuit, getGlobalIsRelaunching, setForceQuit, @@ -173,12 +174,19 @@ function logActiveState() { } activity.displays = getActivityDisplays(); + const termCmdCount = getAndClearTermCommandsRun(); + if (termCmdCount > 0) { + activity.termcommandsrun = termCmdCount; + } + const props: TEventProps = { "activity:activeminutes": activity.activeminutes, "activity:fgminutes": activity.fgminutes, "activity:openminutes": activity.openminutes, }; - + if (termCmdCount > 0) { + props["activity:termcommandsrun"] = termCmdCount; + } if (astate.wasActive && isWaveAIOpen) { props["activity:waveaiactiveminutes"] = 1; } diff --git a/emain/preload.ts b/emain/preload.ts index 587ed9a370..28e1b17808 100644 --- a/emain/preload.ts +++ b/emain/preload.ts @@ -3,6 +3,7 @@ import { contextBridge, ipcRenderer, Rectangle, WebviewTag } from "electron"; +// update type in custom.d.ts (ElectronApi type) contextBridge.exposeInMainWorld("api", { getAuthKey: () => ipcRenderer.sendSync("get-auth-key"), getIsDev: () => ipcRenderer.sendSync("get-is-dev"), @@ -60,6 +61,7 @@ contextBridge.exposeInMainWorld("api", { clearWebviewStorage: (webContentsId: number) => ipcRenderer.invoke("clear-webview-storage", webContentsId), setWaveAIOpen: (isOpen: boolean) => ipcRenderer.send("set-waveai-open", isOpen), closeBuilderWindow: () => ipcRenderer.send("close-builder-window"), + incrementTermCommands: () => ipcRenderer.send("increment-term-commands"), }); // Custom event for "new-window" diff --git a/frontend/app/view/term/termwrap.ts b/frontend/app/view/term/termwrap.ts index 7a58ac7e78..7f15cbcb69 100644 --- a/frontend/app/view/term/termwrap.ts +++ b/frontend/app/view/term/termwrap.ts @@ -5,7 +5,7 @@ import { getFileSubject } from "@/app/store/wps"; import { sendWSCommand } from "@/app/store/ws"; import { RpcApi } from "@/app/store/wshclientapi"; import { TabRpcClient } from "@/app/store/wshrpcutil"; -import { WOS, atoms, fetchWaveFile, getSettingsKeyAtom, globalStore, openLink } from "@/store/global"; +import { WOS, atoms, fetchWaveFile, getApi, getSettingsKeyAtom, globalStore, openLink } from "@/store/global"; import * as services from "@/store/services"; import { PLATFORM, PlatformMacOS } from "@/util/platformutil"; import { base64ToArray, base64ToString, fireAndForget } from "@/util/util"; @@ -252,6 +252,7 @@ function handleOsc16162Command(data: string, blockId: string, loaded: boolean, t case "C": rtInfo["shell:state"] = "running-command"; globalStore.set(termWrap.shellIntegrationStatusAtom, "running-command"); + getApi().incrementTermCommands(); if (cmd.data.cmd64) { const decodedLen = Math.ceil(cmd.data.cmd64.length * 0.75); if (decodedLen > 8192) { diff --git a/frontend/types/custom.d.ts b/frontend/types/custom.d.ts index 90b3bd9427..a5e24baae9 100644 --- a/frontend/types/custom.d.ts +++ b/frontend/types/custom.d.ts @@ -122,6 +122,7 @@ declare global { clearWebviewStorage: (webContentsId: number) => Promise; // clear-webview-storage setWaveAIOpen: (isOpen: boolean) => void; // set-waveai-open closeBuilderWindow: () => void; // close-builder-window + incrementTermCommands: () => void; // increment-term-commands }; type ElectronContextMenuItem = { diff --git a/frontend/types/gotypes.d.ts b/frontend/types/gotypes.d.ts index f132999b2b..1de284dee5 100644 --- a/frontend/types/gotypes.d.ts +++ b/frontend/types/gotypes.d.ts @@ -37,6 +37,7 @@ declare global { numsshconn?: number; numwslconn?: number; nummagnify?: number; + termcommandsrun?: number; numpanics?: number; numaireqs?: number; startup?: number; @@ -1061,6 +1062,7 @@ declare global { "activity:openminutes"?: number; "activity:waveaiactiveminutes"?: number; "activity:waveaifgminutes"?: number; + "activity:termcommandsrun"?: number; "app:firstday"?: boolean; "app:firstlaunch"?: boolean; "action:initiator"?: "keyboard" | "mouse"; diff --git a/pkg/telemetry/telemetry.go b/pkg/telemetry/telemetry.go index 7a14fc25c3..3a208055b9 100644 --- a/pkg/telemetry/telemetry.go +++ b/pkg/telemetry/telemetry.go @@ -153,6 +153,7 @@ func mergeActivity(curActivity *telemetrydata.TEventProps, newActivity telemetry curActivity.OpenMinutes += newActivity.OpenMinutes curActivity.WaveAIActiveMinutes += newActivity.WaveAIActiveMinutes curActivity.WaveAIFgMinutes += newActivity.WaveAIFgMinutes + curActivity.TermCommandsRun += newActivity.TermCommandsRun if newActivity.AppFirstDay { curActivity.AppFirstDay = true } diff --git a/pkg/telemetry/telemetrydata/telemetrydata.go b/pkg/telemetry/telemetrydata/telemetrydata.go index 1ff89679e0..a6ba026f79 100644 --- a/pkg/telemetry/telemetrydata/telemetrydata.go +++ b/pkg/telemetry/telemetrydata/telemetrydata.go @@ -85,6 +85,7 @@ type TEventProps struct { OpenMinutes int `json:"activity:openminutes,omitempty"` WaveAIActiveMinutes int `json:"activity:waveaiactiveminutes,omitempty"` WaveAIFgMinutes int `json:"activity:waveaifgminutes,omitempty"` + TermCommandsRun int `json:"activity:termcommandsrun,omitempty"` AppFirstDay bool `json:"app:firstday,omitempty"` AppFirstLaunch bool `json:"app:firstlaunch,omitempty"` diff --git a/pkg/wshrpc/wshrpctypes.go b/pkg/wshrpc/wshrpctypes.go index 9b6dd8d8d1..a53e0aa441 100644 --- a/pkg/wshrpc/wshrpctypes.go +++ b/pkg/wshrpc/wshrpctypes.go @@ -840,6 +840,7 @@ type ActivityUpdate struct { NumSSHConn int `json:"numsshconn,omitempty"` NumWSLConn int `json:"numwslconn,omitempty"` NumMagnify int `json:"nummagnify,omitempty"` + TermCommandsRun int `json:"termcommandsrun,omitempty"` NumPanics int `json:"numpanics,omitempty"` NumAIReqs int `json:"numaireqs,omitempty"` Startup int `json:"startup,omitempty"`