diff --git a/cmd/test/test-main.go b/cmd/test/test-main.go index 215989539d..bb16343da8 100644 --- a/cmd/test/test-main.go +++ b/cmd/test/test-main.go @@ -3,53 +3,6 @@ package main -import ( - "context" - "fmt" - "log" - - "github.com/wavetermdev/waveterm/pkg/vdom" - "github.com/wavetermdev/waveterm/pkg/wshutil" -) - -func Page(ctx context.Context, props map[string]any) any { - clicked, setClicked := vdom.UseState(ctx, false) - var clickedDiv *vdom.VDomElem - if clicked { - clickedDiv = vdom.Bind(`
clicked
`, nil) - } - clickFn := func() { - log.Printf("run clickFn\n") - setClicked(true) - } - return vdom.Bind( - ` -
-

hello world

- - -
-`, - map[string]any{"clickFn": clickFn, "clickedDiv": clickedDiv}, - ) -} - -func Button(ctx context.Context, props map[string]any) any { - ref := vdom.UseVDomRef(ctx) - clName, setClName := vdom.UseState(ctx, "button") - vdom.UseEffect(ctx, func() func() { - fmt.Printf("Button useEffect\n") - setClName("button mounted") - return nil - }, nil) - return vdom.Bind(` -
- -
- `, map[string]any{"clName": clName, "ref": ref, "onClick": props["onClick"], "children": props["children"]}) -} - func main() { - wshutil.SetTermRawModeAndInstallShutdownHandlers(true) - defer wshutil.RestoreTermState() + } diff --git a/cmd/wsh/cmd/wshcmd-root.go b/cmd/wsh/cmd/wshcmd-root.go index 0edbcea79c..48a568d69c 100644 --- a/cmd/wsh/cmd/wshcmd-root.go +++ b/cmd/wsh/cmd/wshcmd-root.go @@ -84,10 +84,7 @@ func OutputHelpMessage(cmd *cobra.Command) { func preRunSetupRpcClient(cmd *cobra.Command, args []string) error { jwtToken := os.Getenv(wshutil.WaveJwtTokenVarName) if jwtToken == "" { - wshutil.SetTermRawModeAndInstallShutdownHandlers(true) - UsingTermWshMode = true - RpcClient, WrappedStdin = wshutil.SetupTerminalRpcClient(nil, "wshcmd-termclient") - return nil + return fmt.Errorf("wsh must be run inside a Wave-managed SSH session (WAVETERM_JWT not found)") } err := setupRpcClient(nil, jwtToken) if err != nil { diff --git a/frontend/app/view/term/termwrap.ts b/frontend/app/view/term/termwrap.ts index b676a98361..6393b2165a 100644 --- a/frontend/app/view/term/termwrap.ts +++ b/frontend/app/view/term/termwrap.ts @@ -52,68 +52,6 @@ type TermWrapOptions = { nodeModel?: BlockNodeModel; }; -function handleOscWaveCommand(data: string, blockId: string, loaded: boolean): boolean { - if (!loaded) { - return true; - } - if (!data || data.length === 0) { - console.log("Invalid Wave OSC command received (empty)"); - return true; - } - - // Expected formats: - // "setmeta;{JSONDATA}" - // "setmeta;[wave-id];{JSONDATA}" - const parts = data.split(";"); - if (parts[0] !== "setmeta") { - console.log("Invalid Wave OSC command received (bad command)", data); - return true; - } - let jsonPayload: string; - let waveId: string | undefined; - if (parts.length === 2) { - jsonPayload = parts[1]; - } else if (parts.length >= 3) { - waveId = parts[1]; - jsonPayload = parts.slice(2).join(";"); - } else { - console.log("Invalid Wave OSC command received (1 part)", data); - return true; - } - - let meta: any; - try { - meta = JSON.parse(jsonPayload); - } catch (e) { - console.error("Invalid JSON in Wave OSC command:", e); - return true; - } - - if (waveId) { - // Resolve the wave id to an ORef using our ResolveIdsCommand. - fireAndForget(() => { - return RpcApi.ResolveIdsCommand(TabRpcClient, { blockid: blockId, ids: [waveId] }) - .then((response: { resolvedids: { [key: string]: any } }) => { - const oref = response.resolvedids[waveId]; - if (!oref) { - console.error("Failed to resolve wave id:", waveId); - return; - } - services.ObjectService.UpdateObjectMeta(oref, meta); - }) - .catch((err: any) => { - console.error("Error resolving wave id", waveId, err); - }); - }); - } else { - // No wave id provided; update using the current block id. - fireAndForget(() => { - return services.ObjectService.UpdateObjectMeta(WOS.makeORef("block", blockId), meta); - }); - } - return true; -} - // for xterm OSC handlers, we return true always because we "own" the OSC number. // even if data is invalid we don't want to propagate to other handlers. function handleOsc52Command(data: string, blockId: string, loaded: boolean, termWrap: TermWrap): boolean { @@ -538,9 +476,6 @@ export class TermWrap { this.terminal.parser.registerOscHandler(52, (data: string) => { return handleOsc52Command(data, this.blockId, this.loaded, this); }); - this.terminal.parser.registerOscHandler(9283, (data: string) => { - return handleOscWaveCommand(data, this.blockId, this.loaded); - }); this.terminal.parser.registerOscHandler(16162, (data: string) => { return handleOsc16162Command(data, this.blockId, this.loaded, this); }); diff --git a/pkg/blockcontroller/shellcontroller.go b/pkg/blockcontroller/shellcontroller.go index bbdf38295d..040a245745 100644 --- a/pkg/blockcontroller/shellcontroller.go +++ b/pkg/blockcontroller/shellcontroller.go @@ -513,14 +513,6 @@ func (bc *ShellController) manageRunningShellProcess(shellProc *shellexec.ShellP shellInputCh := make(chan *BlockInputUnion, 32) bc.ShellInputCh = shellInputCh - // make esc sequence wshclient wshProxy - // we don't need to authenticate this wshProxy since it is coming direct - wshProxy := wshutil.MakeRpcProxy(fmt.Sprintf("controller:%s", bc.BlockId)) - controllerLinkId, err := wshutil.DefaultRouter.RegisterTrustedLeaf(wshProxy, wshutil.MakeControllerRouteId(bc.BlockId)) - if err != nil { - return fmt.Errorf("cannot register controller route: %w", err) - } - ptyBuffer := wshutil.MakePtyBuffer(wshutil.WaveOSCPrefix, shellProc.Cmd, wshProxy.FromRemoteCh) go func() { // handles regular output from the pty (goes to the blockfile and xterm) defer func() { @@ -546,7 +538,7 @@ func (bc *ShellController) manageRunningShellProcess(shellProc *shellexec.ShellP }() buf := make([]byte, 4096) for { - nr, err := ptyBuffer.Read(buf) + nr, err := shellProc.Cmd.Read(buf) if nr > 0 { err := HandleAppendBlockFile(bc.BlockId, wavebase.BlockFile_Term, buf[:nr]) if err != nil { @@ -577,19 +569,6 @@ func (bc *ShellController) manageRunningShellProcess(shellProc *shellexec.ShellP } } }() - go func() { - defer func() { - panichandler.PanicHandler("blockcontroller:shellproc-output-loop", recover()) - }() - // handles outputCh -> shellInputCh - for msg := range wshProxy.ToRemoteCh { - encodedMsg, err := wshutil.EncodeWaveOSCBytes(wshutil.WaveServerOSC, msg) - if err != nil { - log.Printf("error encoding OSC message: %v\n", err) - } - shellInputCh <- &BlockInputUnion{InputData: encodedMsg} - } - }() go func() { defer func() { panichandler.PanicHandler("blockcontroller:shellproc-wait-loop", recover()) @@ -597,7 +576,6 @@ func (bc *ShellController) manageRunningShellProcess(shellProc *shellexec.ShellP // wait for the shell to finish var exitCode int defer func() { - wshutil.DefaultRouter.UnregisterLink(controllerLinkId) bc.UpdateControllerAndSendUpdate(func() bool { if bc.ProcStatus == Status_Running { bc.ProcStatus = Status_Done diff --git a/pkg/wshutil/wshutil.go b/pkg/wshutil/wshutil.go index 28e3db8a77..b5e938839c 100644 --- a/pkg/wshutil/wshutil.go +++ b/pkg/wshutil/wshutil.go @@ -11,13 +11,11 @@ import ( "log" "net" "os" - "os/signal" "path/filepath" "runtime" "strings" "sync" "sync/atomic" - "syscall" "github.com/golang-jwt/jwt/v5" "github.com/wavetermdev/waveterm/pkg/baseds" @@ -28,7 +26,6 @@ import ( "github.com/wavetermdev/waveterm/pkg/wavebase" "github.com/wavetermdev/waveterm/pkg/wavejwt" "github.com/wavetermdev/waveterm/pkg/wshrpc" - "golang.org/x/term" ) // these should both be 5 characters @@ -126,102 +123,17 @@ func EncodeWaveOSCMessageEx(oscNum string, msg *RpcMessage) ([]byte, error) { return EncodeWaveOSCBytes(oscNum, barr) } -var termModeLock = sync.Mutex{} -var termIsRaw bool -var origTermState *term.State -var shutdownSignalHandlersInstalled bool var shutdownOnce sync.Once -var extraShutdownFunc atomic.Pointer[func()] func DoShutdown(reason string, exitCode int, quiet bool) { shutdownOnce.Do(func() { defer os.Exit(exitCode) - RestoreTermState() - extraFn := extraShutdownFunc.Load() - if extraFn != nil { - (*extraFn)() - } if !quiet && reason != "" { - log.Printf("shutting down: %s\r\n", reason) + log.Printf("shutting down: %s\n", reason) } }) } -func installShutdownSignalHandlers(quiet bool) { - termModeLock.Lock() - defer termModeLock.Unlock() - if shutdownSignalHandlersInstalled { - return - } - sigCh := make(chan os.Signal, 1) - signal.Notify(sigCh, syscall.SIGHUP, syscall.SIGTERM, syscall.SIGINT) - go func() { - defer func() { - panichandler.PanicHandlerNoTelemetry("installShutdownSignalHandlers", recover()) - }() - for sig := range sigCh { - DoShutdown(fmt.Sprintf("got signal %v", sig), 1, quiet) - break - } - }() -} - -func SetTermRawModeAndInstallShutdownHandlers(quietShutdown bool) { - SetTermRawMode() - installShutdownSignalHandlers(quietShutdown) -} - -func SetExtraShutdownFunc(fn func()) { - extraShutdownFunc.Store(&fn) -} - -func SetTermRawMode() { - termModeLock.Lock() - defer termModeLock.Unlock() - if termIsRaw { - return - } - origState, err := term.MakeRaw(int(os.Stdin.Fd())) - if err != nil { - fmt.Fprintf(os.Stderr, "Error setting raw mode: %v\n", err) - return - } - origTermState = origState - termIsRaw = true -} - -func RestoreTermState() { - termModeLock.Lock() - defer termModeLock.Unlock() - if !termIsRaw || origTermState == nil { - return - } - term.Restore(int(os.Stdin.Fd()), origTermState) - termIsRaw = false -} - -// returns (wshRpc, wrappedStdin) -func SetupTerminalRpcClient(serverImpl ServerImpl, debugStr string) (*WshRpc, io.Reader) { - messageCh := make(chan baseds.RpcInputChType, DefaultInputChSize) - outputCh := make(chan []byte, DefaultOutputChSize) - ptyBuf := MakePtyBuffer(WaveServerOSCPrefix, os.Stdin, messageCh) - rpcClient := MakeWshRpcWithChannels(messageCh, outputCh, wshrpc.RpcContext{}, serverImpl, debugStr) - go func() { - defer func() { - panichandler.PanicHandler("SetupTerminalRpcClient", recover()) - }() - for msg := range outputCh { - barr, err := EncodeWaveOSCBytes(WaveOSC, msg) - if err != nil { - fmt.Fprintf(os.Stderr, "Error encoding OSC message: %v\n", err) - continue - } - os.Stdout.Write(barr) - } - }() - return rpcClient, ptyBuf -} - func SetupPacketRpcClient(input io.Reader, output io.Writer, serverImpl ServerImpl, debugStr string) (*WshRpc, chan []byte) { messageCh := make(chan baseds.RpcInputChType, DefaultInputChSize) outputCh := make(chan []byte, DefaultOutputChSize)