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
49 changes: 28 additions & 21 deletions cmd/server/main-server.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
"fmt"
"log"
"os"
"strconv"

"runtime"
"sync"
Expand Down Expand Up @@ -247,6 +246,21 @@ func startupActivityUpdate(firstLaunch bool) {
shellType = "error"
shellVersion = ""
}
userSetOnce := &telemetrydata.TEventUserProps{
ClientInitialVersion: "v" + WaveVersion,
}
tosTs := telemetry.GetTosAgreedTs()
var cohortTime time.Time
if tosTs > 0 {
cohortTime = time.UnixMilli(tosTs)
} else {
cohortTime = time.Now()
}
cohortMonth := cohortTime.Format("2006-01")
year, week := cohortTime.ISOWeek()
cohortISOWeek := fmt.Sprintf("%04d-W%02d", year, week)
userSetOnce.CohortMonth = cohortMonth
userSetOnce.CohortISOWeek = cohortISOWeek
props := telemetrydata.TEventProps{
UserSet: &telemetrydata.TEventUserProps{
ClientVersion: "v" + WaveVersion,
Expand All @@ -259,9 +273,7 @@ func startupActivityUpdate(firstLaunch bool) {
LocalShellType: shellType,
LocalShellVersion: shellVersion,
},
UserSetOnce: &telemetrydata.TEventUserProps{
ClientInitialVersion: "v" + WaveVersion,
},
UserSetOnce: userSetOnce,
}
if firstLaunch {
props.AppFirstLaunch = true
Expand Down Expand Up @@ -339,18 +351,19 @@ func clearTempFiles() error {
return nil
}

func maybeStartPprofServer() error {
pprofPortStr := os.Getenv("WAVETERM_PPROFPORT")
if pprofPortStr == "" {
return nil
func maybeStartPprofServer() {
settings := wconfig.GetWatcher().GetFullConfig().Settings
if settings.DebugPprofMemProfileRate != nil {
runtime.MemProfileRate = *settings.DebugPprofMemProfileRate
log.Printf("set runtime.MemProfileRate to %d\n", runtime.MemProfileRate)
}
defer os.Unsetenv("WAVETERM_PPROFPORT")
pprofPort, err := strconv.Atoi(pprofPortStr)
if err != nil {
return fmt.Errorf("invalid WAVETERM_PPROFPORT value '%s': %v", pprofPortStr, err)
if settings.DebugPprofPort == nil {
return
}
pprofPort := *settings.DebugPprofPort
if pprofPort < 1 || pprofPort > 65535 {
return fmt.Errorf("WAVETERM_PPROFPORT must be between 1 and 65535, got %d", pprofPort)
log.Printf("[error] debug:pprofport must be between 1 and 65535, got %d\n", pprofPort)
return
}
go func() {
addr := fmt.Sprintf("localhost:%d", pprofPort)
Expand All @@ -359,22 +372,15 @@ func maybeStartPprofServer() error {
log.Printf("[error] pprof server failed: %v\n", err)
}
}()
return nil
}

func main() {
err := maybeStartPprofServer()
if err != nil {
log.Printf("[error] %v\n", err)
return
}

log.SetFlags(log.LstdFlags | log.Lmicroseconds)
log.SetPrefix("[wavesrv] ")
wavebase.WaveVersion = WaveVersion
wavebase.BuildTime = BuildTime

err = grabAndRemoveEnvVars()
err := grabAndRemoveEnvVars()
if err != nil {
log.Printf("[error] %v\n", err)
return
Expand Down Expand Up @@ -463,6 +469,7 @@ func main() {
sigutil.InstallShutdownSignalHandlers(doShutdown)
sigutil.InstallSIGUSR1Handler()
startConfigWatcher()
maybeStartPprofServer()
go stdinReadWatch()
go telemetryLoop()
go updateTelemetryCountsLoop()
Expand Down
12 changes: 6 additions & 6 deletions frontend/app/store/keymodel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,16 +152,16 @@ function uxCloseBlock(blockId: string) {
return;
}
}

const blockAtom = WOS.getWaveObjectAtom<Block>(WOS.makeORef("block", blockId));
const blockData = globalStore.get(blockAtom);
const isAIFileDiff = blockData?.meta?.view === "aifilediff";

const layoutModel = getLayoutModelForStaticTab();
const node = layoutModel.getNodeByBlockId(blockId);
if (node) {
fireAndForget(() => layoutModel.closeNode(node.id));

if (isAIFileDiff && isAIPanelOpen) {
setTimeout(() => WaveAIModel.getInstance().focusInput(), 50);
}
Expand Down Expand Up @@ -199,16 +199,16 @@ function genericClose() {
simpleCloseStaticTab();
return;
}

const layoutModel = getLayoutModelForStaticTab();
const focusedNode = globalStore.get(layoutModel.focusedNode);
const blockId = focusedNode?.data?.blockId;
const blockAtom = blockId ? WOS.getWaveObjectAtom<Block>(WOS.makeORef("block", blockId)) : null;
const blockData = blockAtom ? globalStore.get(blockAtom) : null;
const isAIFileDiff = blockData?.meta?.view === "aifilediff";

fireAndForget(layoutModel.closeFocusedNode.bind(layoutModel));

if (isAIFileDiff && isAIPanelOpen) {
setTimeout(() => WaveAIModel.getInstance().focusInput(), 50);
}
Expand Down
20 changes: 16 additions & 4 deletions frontend/app/view/preview/preview-directory.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ function DirectoryTable({
newFile,
newDirectory,
}: DirectoryTableProps) {
const searchActive = useAtomValue(model.directorySearchActive);
const fullConfig = useAtomValue(atoms.fullConfigAtom);
const setErrorMsg = useSetAtom(model.errorMsgAtom);
const getIconFromMimeType = useCallback(
Expand Down Expand Up @@ -346,6 +347,7 @@ function TableBody({
setRefreshVersion,
osRef,
}: TableBodyProps) {
const searchActive = useAtomValue(model.directorySearchActive);
const dummyLineRef = useRef<HTMLDivElement>(null);
const warningBoxRef = useRef<HTMLDivElement>(null);
const conn = useAtomValue(model.connection);
Expand Down Expand Up @@ -447,12 +449,15 @@ function TableBody({

return (
<div className="dir-table-body" ref={bodyRef}>
{search !== "" && (
<div className="flex rounded-[3px] py-1 px-2 bg-warning" ref={warningBoxRef}>
<span>Searching for "{search}"</span>
{(searchActive || search !== "") && (
<div className="flex rounded-[3px] py-1 px-2 bg-warning text-black" ref={warningBoxRef}>
<span>{search === "" ? "Type to search (Esc to cancel)" : `Searching for "${search}"`}</span>
<div
className="ml-auto bg-transparent flex justify-center items-center flex-col p-0.5 rounded-md hover:bg-hoverbg focus:bg-hoverbg focus-within:bg-hoverbg cursor-pointer"
onClick={() => setSearch("")}
onClick={() => {
setSearch("");
globalStore.set(model.directorySearchActive, false);
}}
>
<i className="fa-solid fa-xmark" />
<input
Expand Down Expand Up @@ -549,6 +554,7 @@ const TableRow = React.forwardRef(function ({
const newFileName = row.getValue("path") as string;
model.goHistory(newFileName);
setSearch("");
globalStore.set(model.directorySearchActive, false);
}}
onClick={() => setFocusIndex(idx)}
onContextMenu={(e) => handleFileContextMenu(e, row.original)}
Expand Down Expand Up @@ -650,8 +656,13 @@ function DirectoryPreview({ model }: DirectoryPreviewProps) {

useEffect(() => {
model.directoryKeyDownHandler = (waveEvent: WaveKeyboardEvent): boolean => {
if (checkKeyPressed(waveEvent, "Cmd:f")) {
globalStore.set(model.directorySearchActive, true);
return true;
}
if (checkKeyPressed(waveEvent, "Escape")) {
setSearchText("");
globalStore.set(model.directorySearchActive, false);
return;
}
if (checkKeyPressed(waveEvent, "ArrowUp")) {
Expand All @@ -676,6 +687,7 @@ function DirectoryPreview({ model }: DirectoryPreviewProps) {
}
model.goHistory(selectedPath);
setSearchText("");
globalStore.set(model.directorySearchActive, false);
return true;
}
if (checkKeyPressed(waveEvent, "Backspace")) {
Expand Down
2 changes: 2 additions & 0 deletions frontend/app/view/preview/preview-model.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ export class PreviewModel implements ViewModel {

showHiddenFiles: PrimitiveAtom<boolean>;
refreshVersion: PrimitiveAtom<number>;
directorySearchActive: PrimitiveAtom<boolean>;
refreshCallback: () => void;
directoryKeyDownHandler: (waveEvent: WaveKeyboardEvent) => boolean;
codeEditKeyDownHandler: (waveEvent: WaveKeyboardEvent) => boolean;
Expand All @@ -173,6 +174,7 @@ export class PreviewModel implements ViewModel {
let showHiddenFiles = globalStore.get(getSettingsKeyAtom("preview:showhiddenfiles")) ?? true;
this.showHiddenFiles = atom<boolean>(showHiddenFiles);
this.refreshVersion = atom(0);
this.directorySearchActive = atom(false);
this.previewTextRef = createRef();
this.openFileModal = atom(false);
this.openFileModalDelay = atom(false);
Expand Down
7 changes: 7 additions & 0 deletions frontend/app/view/term/term-model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@


import { BlockNodeModel } from "@/app/block/blocktypes";
import { appHandleKeyDown } from "@/app/store/keymodel";
import { waveEventSubscribe } from "@/app/store/wps";
import { RpcApi } from "@/app/store/wshclientapi";
import { makeFeBlockRouteId } from "@/app/store/wshrouter";
Expand Down Expand Up @@ -528,6 +529,12 @@ export class TermViewModel implements ViewModel {
this.forceRestartController();
return false;
}
const appHandled = appHandleKeyDown(waveEvent);
if (appHandled) {
event.preventDefault();
event.stopPropagation();
return false;
}
return true;
}

Expand Down
7 changes: 7 additions & 0 deletions frontend/types/gotypes.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -977,6 +977,9 @@ declare global {
"conn:*"?: boolean;
"conn:askbeforewshinstall"?: boolean;
"conn:wshenabled"?: boolean;
"debug:*"?: boolean;
"debug:pprofport"?: number;
"debug:pprofmemprofilerate"?: number;
};

// waveobj.StickerClickOptsType
Expand Down Expand Up @@ -1042,6 +1045,8 @@ declare global {
"client:buildtime"?: string;
"client:osrelease"?: string;
"client:isdev"?: boolean;
"cohort:month"?: string;
"cohort:isoweek"?: string;
"autoupdate:channel"?: string;
"autoupdate:enabled"?: boolean;
"localshell:type"?: string;
Expand Down Expand Up @@ -1113,6 +1118,8 @@ declare global {
"client:buildtime"?: string;
"client:osrelease"?: string;
"client:isdev"?: boolean;
"cohort:month"?: string;
"cohort:isoweek"?: string;
"autoupdate:channel"?: string;
"autoupdate:enabled"?: boolean;
"localshell:type"?: string;
Expand Down
3 changes: 3 additions & 0 deletions pkg/telemetry/telemetry.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,9 @@ func mergeActivity(curActivity *telemetrydata.TEventProps, newActivity telemetry
curActivity.OpenMinutes += newActivity.OpenMinutes
curActivity.WaveAIActiveMinutes += newActivity.WaveAIActiveMinutes
curActivity.WaveAIFgMinutes += newActivity.WaveAIFgMinutes
if newActivity.AppFirstDay {
curActivity.AppFirstDay = true
}
}

// ignores the timestamp in tevent, and uses the current time
Expand Down
3 changes: 3 additions & 0 deletions pkg/telemetry/telemetrydata/telemetrydata.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ type TEventUserProps struct {
ClientOSRelease string `json:"client:osrelease,omitempty"`
ClientIsDev bool `json:"client:isdev,omitempty"`

CohortMonth string `json:"cohort:month,omitempty"`
CohortISOWeek string `json:"cohort:isoweek,omitempty"`

AutoUpdateChannel string `json:"autoupdate:channel,omitempty"`
AutoUpdateEnabled bool `json:"autoupdate:enabled,omitempty"`

Expand Down
4 changes: 4 additions & 0 deletions pkg/wconfig/metaconsts.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,5 +97,9 @@ const (
ConfigKey_ConnClear = "conn:*"
ConfigKey_ConnAskBeforeWshInstall = "conn:askbeforewshinstall"
ConfigKey_ConnWshEnabled = "conn:wshenabled"

ConfigKey_DebugClear = "debug:*"
ConfigKey_DebugPprofPort = "debug:pprofport"
ConfigKey_DebugPprofMemProfileRate = "debug:pprofmemprofilerate"
)

16 changes: 10 additions & 6 deletions pkg/wconfig/settingsconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,10 @@ type SettingsType struct {
ConnClear bool `json:"conn:*,omitempty"`
ConnAskBeforeWshInstall *bool `json:"conn:askbeforewshinstall,omitempty"`
ConnWshEnabled bool `json:"conn:wshenabled,omitempty"`

DebugClear bool `json:"debug:*,omitempty"`
DebugPprofPort *int `json:"debug:pprofport,omitempty"`
DebugPprofMemProfileRate *int `json:"debug:pprofmemprofilerate,omitempty"`
}

func (s *SettingsType) GetAiSettings() *AiSettingsType {
Expand Down Expand Up @@ -333,7 +337,7 @@ func resolveEnvReplacements(m waveobj.MetaMapType) {
if m == nil {
return
}

for key, value := range m {
switch v := value.(type) {
case string:
Expand Down Expand Up @@ -367,20 +371,20 @@ func resolveEnvValue(value string) (string, bool) {
if !strings.HasPrefix(value, "$ENV:") {
return "", false
}

envSpec := value[5:] // Remove "$ENV:" prefix
parts := strings.SplitN(envSpec, ":", 2)
envVar := parts[0]
var fallback string
if len(parts) > 1 {
fallback = parts[1]
}

// Get the environment variable value
if envValue, exists := os.LookupEnv(envVar); exists {
return envValue, true
}

// Return fallback if provided, otherwise return empty string
if fallback != "" {
return fallback, true
Expand Down Expand Up @@ -414,12 +418,12 @@ func readConfigHelper(fileName string, barr []byte, readErr error) (waveobj.Meta
}
cerrs = append(cerrs, ConfigError{File: fileName, Err: err.Error()})
}

// Resolve environment variable replacements
if rtn != nil {
resolveEnvReplacements(rtn)
}

return rtn, cerrs
}

Expand Down
9 changes: 9 additions & 0 deletions schema/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,15 @@
},
"conn:wshenabled": {
"type": "boolean"
},
"debug:*": {
"type": "boolean"
},
"debug:pprofport": {
"type": "integer"
},
"debug:pprofmemprofilerate": {
"type": "integer"
}
},
"additionalProperties": false,
Expand Down
Loading