package main import ( "log" "os" "path/filepath" ) func logf(format string, a ...any) { log.Printf(format, a...) } // The manual pause is a file next to the agent binary, so it survives restarts and can be // set from the machine itself (`wxch-agent -pause`) or from the web (owner.pause). func pauseFilePath() string { exe, err := os.Executable() if err != nil { return "/tmp/wxch-agent.PAUSED" } return filepath.Join(filepath.Dir(exe), "PAUSED") } func pausedFlag() bool { _, err := os.Stat(pauseFilePath()) return err == nil } func setPaused(on bool) error { p := pauseFilePath() if on { return os.WriteFile(p, []byte("paused by the owner\n"), 0644) } if err := os.Remove(p); err != nil && !os.IsNotExist(err) { return err } return nil } // ownerRPC implements owner.status / owner.pause / owner.resume. func (r *rpcCtx) ownerRPC() { switch r.m.Method { case "owner.pause": if err := setPaused(true); err != nil { r.fail("cannot pause: %v", err) return } case "owner.resume": if err := setPaused(false); err != nil { r.fail("cannot resume: %v", err) return } } // apply right away instead of waiting for the next telemetry tick lastSampleMu.Lock() idle, foreign := lastOwnerIdle, lastForeign lastSampleMu.Unlock() guardEvaluate(idle, foreign) mode, reason, paused := guardSnapshot() r.ok(map[string]any{"mode": mode, "reason": reason, "paused": paused}) }