Detailed changes
@@ -78,6 +78,28 @@ Crush can use LSPs for additional context to help inform its decisions, just lik
}
```
+### MCPs
+
+Crush can also use MCPs for additional context. Add LSPs to the config like so:
+
+```json
+{
+ "mcp": {
+ "context7": {
+ "url": "https://mcp.context7.com/mcp",
+ "type": "http"
+ },
+ "github": {
+ "type": "http",
+ "url": "https://api.githubcopilot.com/mcp/",
+ "headers": {
+ "Authorization": "$(echo Bearer $GH_MCP_TOKEN)"
+ }
+ }
+ }
+}
+```
+
### OpenAI-Compatible APIs
Crush supports all OpenAI-compatible APIs. Here's an example configuration for Deepseek, which uses an OpenAI-compatible API. Don't forget to set `DEEPSEEK_API_KEY` in your environment.
@@ -1,14 +1,13 @@
package cmd
import (
- "bufio"
+ "context"
"encoding/json"
"fmt"
"io"
"os"
"path/filepath"
"slices"
- "strings"
"time"
"github.com/charmbracelet/crush/internal/config"
@@ -17,6 +16,8 @@ import (
"github.com/spf13/cobra"
)
+const defaultTailLines = 1000
+
var logsCmd = &cobra.Command{
Use: "logs",
Short: "View crush logs",
@@ -38,7 +39,6 @@ var logsCmd = &cobra.Command{
}
log.SetLevel(log.DebugLevel)
- // Configure log to output to stdout instead of stderr
log.SetOutput(os.Stdout)
cfg, err := config.Load(cwd, false)
@@ -53,104 +53,114 @@ var logsCmd = &cobra.Command{
}
if follow {
- // Follow mode - tail the file continuously
- t, err := tail.TailFile(logsFile, tail.Config{Follow: true, ReOpen: true, Logger: tail.DiscardingLogger})
- if err != nil {
- return fmt.Errorf("failed to tail log file: %v", err)
- }
-
- // Print the text of each received line
- for line := range t.Lines {
- printLogLine(line.Text)
- }
- } else if tailLines > 0 {
- // Tail mode - show last N lines
- lines, err := readLastNLines(logsFile, tailLines)
- if err != nil {
- return fmt.Errorf("failed to read last %d lines: %v", tailLines, err)
- }
- for _, line := range lines {
- printLogLine(line)
- }
- } else {
- // Oneshot mode - read the entire file once
- file, err := os.Open(logsFile)
- if err != nil {
- return fmt.Errorf("failed to open log file: %v", err)
- }
- defer file.Close()
-
- reader := bufio.NewReader(file)
- for {
- line, err := reader.ReadString('\n')
- if err != nil {
- if err == io.EOF && line != "" {
- // Handle last line without newline
- printLogLine(line)
- }
- break
- }
- // Remove trailing newline
- line = strings.TrimSuffix(line, "\n")
- printLogLine(line)
- }
+ return followLogs(cmd.Context(), logsFile, tailLines)
}
- return nil
+ return showLogs(logsFile, tailLines)
},
}
func init() {
logsCmd.Flags().BoolP("follow", "f", false, "Follow log output")
- logsCmd.Flags().IntP("tail", "t", 0, "Show only the last N lines")
+ logsCmd.Flags().IntP("tail", "t", defaultTailLines, "Show only the last N lines default: 1000 for performance")
rootCmd.AddCommand(logsCmd)
}
-// readLastNLines reads the last N lines from a file using a simple circular buffer approach
-func readLastNLines(filename string, n int) ([]string, error) {
- file, err := os.Open(filename)
+func followLogs(ctx context.Context, logsFile string, tailLines int) error {
+ t, err := tail.TailFile(logsFile, tail.Config{
+ Follow: false,
+ ReOpen: false,
+ Logger: tail.DiscardingLogger,
+ })
if err != nil {
- return nil, err
+ return fmt.Errorf("failed to tail log file: %v", err)
}
- defer file.Close()
- // Use a circular buffer to keep only the last N lines
- lines := make([]string, n)
- count := 0
- index := 0
+ var lines []string
+ lineCount := 0
+ for line := range t.Lines {
+ if line.Err != nil {
+ continue
+ }
+ lines = append(lines, line.Text)
+ lineCount++
+ if lineCount >= tailLines {
+ if len(lines) > tailLines {
+ lines = lines[len(lines)-tailLines:]
+ }
+ }
+ }
+ t.Stop()
+
+ for _, line := range lines {
+ printLogLine(line)
+ }
+
+ if len(lines) == tailLines {
+ fmt.Fprintf(os.Stderr, "\nShowing last %d lines. Full logs available at: %s\n", tailLines, logsFile)
+ fmt.Fprintf(os.Stderr, "Following new log entries...\n\n")
+ }
+
+ t, err = tail.TailFile(logsFile, tail.Config{
+ Follow: true,
+ ReOpen: true,
+ Logger: tail.DiscardingLogger,
+ Location: &tail.SeekInfo{Offset: 0, Whence: io.SeekEnd},
+ })
+ if err != nil {
+ return fmt.Errorf("failed to tail log file: %v", err)
+ }
+ defer t.Stop()
- reader := bufio.NewReader(file)
for {
- line, err := reader.ReadString('\n')
- if err != nil {
- if err == io.EOF && line != "" {
- // Handle last line without newline
- line = strings.TrimSuffix(line, "\n")
- lines[index] = line
- count++
- index = (index + 1) % n
+ select {
+ case line := <-t.Lines:
+ if line.Err != nil {
+ continue
+ }
+ printLogLine(line.Text)
+ case <-ctx.Done():
+ return nil
+ }
+ }
+}
+
+func showLogs(logsFile string, tailLines int) error {
+ t, err := tail.TailFile(logsFile, tail.Config{
+ Follow: false,
+ ReOpen: false,
+ Logger: tail.DiscardingLogger,
+ MaxLineSize: 0,
+ })
+ if err != nil {
+ return fmt.Errorf("failed to tail log file: %v", err)
+ }
+ defer t.Stop()
+
+ var lines []string
+ lineCount := 0
+ for line := range t.Lines {
+ if line.Err != nil {
+ continue
+ }
+ lines = append(lines, line.Text)
+ lineCount++
+ if lineCount >= tailLines {
+ if len(lines) > tailLines {
+ lines = lines[len(lines)-tailLines:]
}
- break
}
- // Remove trailing newline
- line = strings.TrimSuffix(line, "\n")
- lines[index] = line
- count++
- index = (index + 1) % n
}
- // Extract the last N lines in correct order
- if count <= n {
- // We have fewer lines than requested, return them all
- return lines[:count], nil
+ for _, line := range lines {
+ printLogLine(line)
}
- // We have more lines than requested, extract from circular buffer
- result := make([]string, n)
- for i := range n {
- result[i] = lines[(index+i)%n]
+ if len(lines) == tailLines {
+ fmt.Fprintf(os.Stderr, "\nShowing last %d lines. Full logs available at: %s\n", tailLines, logsFile)
}
- return result, nil
+
+ return nil
}
func printLogLine(lineText string) {
@@ -6,14 +6,11 @@ import (
"io"
"log/slog"
"os"
- "time"
tea "github.com/charmbracelet/bubbletea/v2"
"github.com/charmbracelet/crush/internal/app"
"github.com/charmbracelet/crush/internal/config"
"github.com/charmbracelet/crush/internal/db"
- "github.com/charmbracelet/crush/internal/llm/agent"
- "github.com/charmbracelet/crush/internal/log"
"github.com/charmbracelet/crush/internal/tui"
"github.com/charmbracelet/crush/internal/version"
"github.com/charmbracelet/fang"
@@ -92,9 +89,6 @@ to assist developers in writing, debugging, and understanding code directly from
}
defer app.Shutdown()
- // Initialize MCP tools early for both modes
- initMCPTools(ctx, app, cfg)
-
prompt, err = maybePrependStdin(prompt)
if err != nil {
slog.Error(fmt.Sprintf("Failed to read from stdin: %v", err))
@@ -126,20 +120,6 @@ to assist developers in writing, debugging, and understanding code directly from
},
}
-func initMCPTools(ctx context.Context, app *app.App, cfg *config.Config) {
- go func() {
- defer log.RecoverPanic("MCP-goroutine", nil)
-
- // Create a context with timeout for the initial MCP tools fetch
- ctxWithTimeout, cancel := context.WithTimeout(ctx, 30*time.Second)
- defer cancel()
-
- // Set this up once with proper error handling
- agent.GetMcpTools(ctxWithTimeout, app.Permissions, cfg)
- slog.Info("MCP message handling goroutine exiting")
- }()
-}
-
func Execute() {
if err := fang.Execute(
context.Background(),
@@ -2,9 +2,9 @@ module github.com/charmbracelet/crush
go 1.24.3
-replace github.com/charmbracelet/bubbletea/v2 => github.com/charmbracelet/bubbletea-internal/v2 v2.0.0-20250710185017-3c0ffd25e595
+replace github.com/charmbracelet/bubbletea/v2 => github.com/charmbracelet/bubbletea-internal/v2 v2.0.0-20250716142813-5d1379f56ba2
-replace github.com/charmbracelet/lipgloss/v2 => github.com/charmbracelet/lipgloss-internal/v2 v2.0.0-20250710185058-03664cb9cecb
+replace github.com/charmbracelet/lipgloss/v2 => github.com/charmbracelet/lipgloss-internal/v2 v2.0.0-20250716143013-48f34cb75679
require (
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0
@@ -75,7 +75,7 @@ require (
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/aymerick/douceur v0.2.0 // indirect
github.com/charmbracelet/colorprofile v0.3.1 // indirect
- github.com/charmbracelet/ultraviolet v0.0.0-20250708152637-0fe0235c8db9 // indirect
+ github.com/charmbracelet/ultraviolet v0.0.0-20250716141307-2fae2b322afb // indirect
github.com/charmbracelet/x/cellbuf v0.0.14-0.20250516160309-24eee56f89fa // indirect
github.com/charmbracelet/x/exp/slice v0.0.0-20250611152503-f53cdd7e01ef
github.com/charmbracelet/x/term v0.2.1
@@ -133,8 +133,8 @@ require (
golang.org/x/crypto v0.37.0 // indirect
golang.org/x/image v0.26.0 // indirect
golang.org/x/net v0.39.0 // indirect
- golang.org/x/sync v0.15.0 // indirect
- golang.org/x/sys v0.33.0 // indirect
+ golang.org/x/sync v0.16.0 // indirect
+ golang.org/x/sys v0.34.0 // indirect
golang.org/x/term v0.31.0 // indirect
golang.org/x/text v0.24.0 // indirect
google.golang.org/genai v1.3.0
@@ -70,20 +70,20 @@ github.com/charlievieth/fastwalk v1.0.11 h1:5sLT/q9+d9xMdpKExawLppqvXFZCVKf6JHnr
github.com/charlievieth/fastwalk v1.0.11/go.mod h1:yGy1zbxog41ZVMcKA/i8ojXLFsuayX5VvwhQVoj9PBI=
github.com/charmbracelet/bubbles/v2 v2.0.0-beta.1.0.20250710161907-a4c42b579198 h1:CkMS9Ah9ac1Ego5JDC5NJyZyAAqu23Z+O0yDwsa3IxM=
github.com/charmbracelet/bubbles/v2 v2.0.0-beta.1.0.20250710161907-a4c42b579198/go.mod h1:6HamsBKWqEC/FVHuQMHgQL+knPyvHH55HwJDHl/adMw=
-github.com/charmbracelet/bubbletea-internal/v2 v2.0.0-20250710185017-3c0ffd25e595 h1:wLMjzOqrwoM7Em9UR9sGbn4375G8WuxcwFB3kjZiqHo=
-github.com/charmbracelet/bubbletea-internal/v2 v2.0.0-20250710185017-3c0ffd25e595/go.mod h1:+Tl7rePElw6OKt382t04zXwtPFoPXxAaJzNrYmtsLds=
+github.com/charmbracelet/bubbletea-internal/v2 v2.0.0-20250716142813-5d1379f56ba2 h1:Gj/vSk7h96TxUU/GSuwbYkr9H0ze+ElAQjcl25wB0+U=
+github.com/charmbracelet/bubbletea-internal/v2 v2.0.0-20250716142813-5d1379f56ba2/go.mod h1:m240IQxo1/eDQ7klblSzOCAUyc3LddHcV3Rc/YEGAgw=
github.com/charmbracelet/colorprofile v0.3.1 h1:k8dTHMd7fgw4bnFd7jXTLZrSU/CQrKnL3m+AxCzDz40=
github.com/charmbracelet/colorprofile v0.3.1/go.mod h1:/GkGusxNs8VB/RSOh3fu0TJmQ4ICMMPApIIVn0KszZ0=
github.com/charmbracelet/fang v0.3.1-0.20250711140230-d5ebb8c1d674 h1:+Cz+VfxD5DO+JT1LlswXWhre0HYLj6l2HW8HVGfMuC0=
github.com/charmbracelet/fang v0.3.1-0.20250711140230-d5ebb8c1d674/go.mod h1:9gCUAHmVx5BwSafeyNr3GI0GgvlB1WYjL21SkPp1jyU=
github.com/charmbracelet/glamour/v2 v2.0.0-20250516160903-6f1e2c8f9ebe h1:i6ce4CcAlPpTj2ER69m1DBeLZ3RRcHnKExuwhKa3GfY=
github.com/charmbracelet/glamour/v2 v2.0.0-20250516160903-6f1e2c8f9ebe/go.mod h1:p3Q+aN4eQKeM5jhrmXPMgPrlKbmc59rWSnMsSA3udhk=
-github.com/charmbracelet/lipgloss-internal/v2 v2.0.0-20250710185058-03664cb9cecb h1:lswj7CYZVYbLn2OhYJsXOMRQQGdRIfyuSnh5FdVSMr0=
-github.com/charmbracelet/lipgloss-internal/v2 v2.0.0-20250710185058-03664cb9cecb/go.mod h1:wEc/TRrTAIDJYjVCg3+y8WeKaN+F88gpYfGbUuP6W3A=
+github.com/charmbracelet/lipgloss-internal/v2 v2.0.0-20250716143013-48f34cb75679 h1:z0og40Sck650PjX51SmiTP8Div2OSugiZJBPZyJInOg=
+github.com/charmbracelet/lipgloss-internal/v2 v2.0.0-20250716143013-48f34cb75679/go.mod h1:BXY7j7rZgAprFwzNcO698++5KTd6GKI6lU83Pr4o0r0=
github.com/charmbracelet/log/v2 v2.0.0-20250226163916-c379e29ff706 h1:WkwO6Ks3mSIGnGuSdKl9qDSyfbYK50z2wc2gGMggegE=
github.com/charmbracelet/log/v2 v2.0.0-20250226163916-c379e29ff706/go.mod h1:mjJGp00cxcfvD5xdCa+bso251Jt4owrQvuimJtVmEmM=
-github.com/charmbracelet/ultraviolet v0.0.0-20250708152637-0fe0235c8db9 h1:+LLFCLxtb/sHegwY3zYdFAbaOgI/I9pv/pxdUlI1Q9s=
-github.com/charmbracelet/ultraviolet v0.0.0-20250708152637-0fe0235c8db9/go.mod h1:/O+B00+dYG6lqRAWIaNxSvywnDrIH6dmLYQAsH0LRTg=
+github.com/charmbracelet/ultraviolet v0.0.0-20250716141307-2fae2b322afb h1:fMyaSpuEyPP+uuTu98Wx2S/7OY52uhjF+kYfM5w7x+s=
+github.com/charmbracelet/ultraviolet v0.0.0-20250716141307-2fae2b322afb/go.mod h1:XrrgNFfXLrFAyd9DUmrqVc3yQFVv8Uk+okj4PsNNzpc=
github.com/charmbracelet/x/ansi v0.9.3 h1:BXt5DHS/MKF+LjuK4huWrC6NCvHtexww7dMayh6GXd0=
github.com/charmbracelet/x/ansi v0.9.3/go.mod h1:3RQDQ6lDnROptfpWuUVIUG64bD2g2BgntdxH0Ya5TeE=
github.com/charmbracelet/x/cellbuf v0.0.14-0.20250516160309-24eee56f89fa h1:lphz0Z3rsiOtMYiz8axkT24i9yFiueDhJbzyNUADmME=
@@ -309,8 +309,8 @@ golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8=
-golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
+golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
+golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -325,8 +325,8 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
-golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
+golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
+golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
@@ -6,8 +6,10 @@ import (
"slices"
"strings"
+ "github.com/charmbracelet/crush/internal/env"
"github.com/charmbracelet/crush/internal/fur/provider"
"github.com/tidwall/sjson"
+ "golang.org/x/exp/slog"
)
const (
@@ -90,12 +92,12 @@ const (
)
type MCPConfig struct {
- Command string `json:"command,omitempty" `
- Env []string `json:"env,omitempty"`
- Args []string `json:"args,omitempty"`
- Type MCPType `json:"type"`
- URL string `json:"url,omitempty"`
- Disabled bool `json:"disabled,omitempty"`
+ Command string `json:"command,omitempty" `
+ Env map[string]string `json:"env,omitempty"`
+ Args []string `json:"args,omitempty"`
+ Type MCPType `json:"type"`
+ URL string `json:"url,omitempty"`
+ Disabled bool `json:"disabled,omitempty"`
// TODO: maybe make it possible to get the value from the env
Headers map[string]string `json:"headers,omitempty"`
@@ -165,6 +167,37 @@ func (l LSPs) Sorted() []LSP {
return sorted
}
+func (m MCPConfig) ResolvedEnv() []string {
+ resolver := NewShellVariableResolver(env.New())
+ for e, v := range m.Env {
+ var err error
+ m.Env[e], err = resolver.ResolveValue(v)
+ if err != nil {
+ slog.Error("error resolving environment variable", "error", err, "variable", e, "value", v)
+ continue
+ }
+ }
+
+ env := make([]string, 0, len(m.Env))
+ for k, v := range m.Env {
+ env = append(env, fmt.Sprintf("%s=%s", k, v))
+ }
+ return env
+}
+
+func (m MCPConfig) ResolvedHeaders() map[string]string {
+ resolver := NewShellVariableResolver(env.New())
+ for e, v := range m.Headers {
+ var err error
+ m.Headers[e], err = resolver.ResolveValue(v)
+ if err != nil {
+ slog.Error("error resolving header variable", "error", err, "variable", e, "value", v)
+ continue
+ }
+ }
+ return m.Headers
+}
+
type Agent struct {
ID string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
@@ -94,7 +94,7 @@ func NewAgent(
) (Service, error) {
ctx := context.Background()
cfg := config.Get()
- otherTools := GetMcpTools(ctx, permissions, cfg)
+ otherTools := GetMCPTools(ctx, permissions, cfg)
if len(lspClients) > 0 {
otherTools = append(otherTools, tools.NewDiagnosticsTool(lspClients))
}
@@ -859,7 +859,7 @@ func (a *agent) UpdateModel() error {
// Get current provider configuration
currentProviderCfg := cfg.GetProviderForModel(a.agentCfg.Model)
- if currentProviderCfg.ID == "" {
+ if currentProviderCfg == nil || currentProviderCfg.ID == "" {
return fmt.Errorf("provider for agent %s not found in config", a.agentCfg.Name)
}
@@ -5,6 +5,7 @@ import (
"encoding/json"
"fmt"
"log/slog"
+ "sync"
"github.com/charmbracelet/crush/internal/config"
"github.com/charmbracelet/crush/internal/llm/tools"
@@ -36,7 +37,7 @@ type MCPClient interface {
}
func (b *mcpTool) Name() string {
- return fmt.Sprintf("%s_%s", b.mcpName, b.tool.Name)
+ return fmt.Sprintf("mcp_%s_%s", b.mcpName, b.tool.Name)
}
func (b *mcpTool) Info() tools.ToolInfo {
@@ -45,7 +46,7 @@ func (b *mcpTool) Info() tools.ToolInfo {
required = make([]string, 0)
}
return tools.ToolInfo{
- Name: fmt.Sprintf("%s_%s", b.mcpName, b.tool.Name),
+ Name: fmt.Sprintf("mcp_%s_%s", b.mcpName, b.tool.Name),
Description: b.tool.Description,
Parameters: b.tool.InputSchema.Properties,
Required: required,
@@ -107,14 +108,14 @@ func (b *mcpTool) Run(ctx context.Context, params tools.ToolCall) (tools.ToolRes
},
)
if !p {
- return tools.NewTextErrorResponse("permission denied"), nil
+ return tools.ToolResponse{}, permission.ErrorPermissionDenied
}
switch b.mcpConfig.Type {
case config.MCPStdio:
c, err := client.NewStdioMCPClient(
b.mcpConfig.Command,
- b.mcpConfig.Env,
+ b.mcpConfig.ResolvedEnv(),
b.mcpConfig.Args...,
)
if err != nil {
@@ -124,7 +125,7 @@ func (b *mcpTool) Run(ctx context.Context, params tools.ToolCall) (tools.ToolRes
case config.MCPHttp:
c, err := client.NewStreamableHttpClient(
b.mcpConfig.URL,
- transport.WithHTTPHeaders(b.mcpConfig.Headers),
+ transport.WithHTTPHeaders(b.mcpConfig.ResolvedHeaders()),
)
if err != nil {
return tools.NewTextErrorResponse(err.Error()), nil
@@ -133,7 +134,7 @@ func (b *mcpTool) Run(ctx context.Context, params tools.ToolCall) (tools.ToolRes
case config.MCPSse:
c, err := client.NewSSEMCPClient(
b.mcpConfig.URL,
- client.WithHeaders(b.mcpConfig.Headers),
+ client.WithHeaders(b.mcpConfig.ResolvedHeaders()),
)
if err != nil {
return tools.NewTextErrorResponse(err.Error()), nil
@@ -154,8 +155,6 @@ func NewMcpTool(name string, tool mcp.Tool, permissions permission.Service, mcpC
}
}
-var mcpTools []tools.BaseTool
-
func getTools(ctx context.Context, name string, m config.MCPConfig, permissions permission.Service, c MCPClient, workingDir string) []tools.BaseTool {
var stdioTools []tools.BaseTool
initRequest := mcp.InitializeRequest{}
@@ -183,50 +182,72 @@ func getTools(ctx context.Context, name string, m config.MCPConfig, permissions
return stdioTools
}
-func GetMcpTools(ctx context.Context, permissions permission.Service, cfg *config.Config) []tools.BaseTool {
- if len(mcpTools) > 0 {
- return mcpTools
- }
+var (
+ mcpToolsOnce sync.Once
+ mcpTools []tools.BaseTool
+)
+
+func GetMCPTools(ctx context.Context, permissions permission.Service, cfg *config.Config) []tools.BaseTool {
+ mcpToolsOnce.Do(func() {
+ mcpTools = doGetMCPTools(ctx, permissions, cfg)
+ })
+ return mcpTools
+}
+
+func doGetMCPTools(ctx context.Context, permissions permission.Service, cfg *config.Config) []tools.BaseTool {
+ var mu sync.Mutex
+ var wg sync.WaitGroup
+ var result []tools.BaseTool
for name, m := range cfg.MCP {
if m.Disabled {
slog.Debug("skipping disabled mcp", "name", name)
continue
}
- switch m.Type {
- case config.MCPStdio:
- c, err := client.NewStdioMCPClient(
- m.Command,
- m.Env,
- m.Args...,
- )
- if err != nil {
- slog.Error("error creating mcp client", "error", err)
- continue
+ wg.Add(1)
+ go func(name string, m config.MCPConfig) {
+ defer wg.Done()
+ switch m.Type {
+ case config.MCPStdio:
+ c, err := client.NewStdioMCPClient(
+ m.Command,
+ m.ResolvedEnv(),
+ m.Args...,
+ )
+ if err != nil {
+ slog.Error("error creating mcp client", "error", err)
+ return
+ }
+
+ mu.Lock()
+ result = append(result, getTools(ctx, name, m, permissions, c, cfg.WorkingDir())...)
+ mu.Unlock()
+ case config.MCPHttp:
+ c, err := client.NewStreamableHttpClient(
+ m.URL,
+ transport.WithHTTPHeaders(m.ResolvedHeaders()),
+ )
+ if err != nil {
+ slog.Error("error creating mcp client", "error", err)
+ return
+ }
+ mu.Lock()
+ result = append(result, getTools(ctx, name, m, permissions, c, cfg.WorkingDir())...)
+ mu.Unlock()
+ case config.MCPSse:
+ c, err := client.NewSSEMCPClient(
+ m.URL,
+ client.WithHeaders(m.ResolvedHeaders()),
+ )
+ if err != nil {
+ slog.Error("error creating mcp client", "error", err)
+ return
+ }
+ mu.Lock()
+ result = append(result, getTools(ctx, name, m, permissions, c, cfg.WorkingDir())...)
+ mu.Unlock()
}
-
- mcpTools = append(mcpTools, getTools(ctx, name, m, permissions, c, cfg.WorkingDir())...)
- case config.MCPHttp:
- c, err := client.NewStreamableHttpClient(
- m.URL,
- transport.WithHTTPHeaders(m.Headers),
- )
- if err != nil {
- slog.Error("error creating mcp client", "error", err)
- continue
- }
- mcpTools = append(mcpTools, getTools(ctx, name, m, permissions, c, cfg.WorkingDir())...)
- case config.MCPSse:
- c, err := client.NewSSEMCPClient(
- m.URL,
- client.WithHeaders(m.Headers),
- )
- if err != nil {
- slog.Error("error creating mcp client", "error", err)
- continue
- }
- mcpTools = append(mcpTools, getTools(ctx, name, m, permissions, c, cfg.WorkingDir())...)
- }
+ }(name, m)
}
-
- return mcpTools
+ wg.Wait()
+ return result
}
@@ -188,7 +188,7 @@ When the user asks you to create a new git commit, follow these steps carefully:
4. Create the commit with a message ending with:
💘 Generated with Crush
-Co-Authored-By: Crush <noreply@crush.charm.land>
+Co-Authored-By: Crush <crush@charm.land>
- In order to ensure good formatting, ALWAYS pass the commit message via a HEREDOC, a la this example:
<example>
@@ -196,7 +196,7 @@ git commit -m "$(cat <<'EOF'
Commit message here.
💘 Generated with Crush
- Co-Authored-By: 💘 Crush <noreply@crush.charm.land>
+ Co-Authored-By: 💘 Crush <crush@charm.land>
EOF
)"
</example>
@@ -655,6 +655,7 @@ func joinHeaderBody(header, body string) string {
func renderPlainContent(v *toolCallCmp, content string) string {
t := styles.CurrentTheme()
+ content = strings.ReplaceAll(content, "\r\n", "\n") // Normalize line endings
content = strings.TrimSpace(content)
lines := strings.Split(content, "\n")
@@ -664,6 +665,7 @@ func renderPlainContent(v *toolCallCmp, content string) string {
if i >= responseContextHeight {
break
}
+ ln = escapeContent(ln)
ln = " " + ln // left padding
if len(ln) > width {
ln = v.fit(ln, width)
@@ -680,6 +682,7 @@ func renderPlainContent(v *toolCallCmp, content string) string {
Width(width).
Render(fmt.Sprintf("… (%d lines)", len(lines)-responseContextHeight)))
}
+
return strings.Join(out, "\n")
}
@@ -694,10 +697,17 @@ func pad(v any, width int) string {
func renderCodeContent(v *toolCallCmp, path, content string, offset int) string {
t := styles.CurrentTheme()
+ content = strings.ReplaceAll(content, "\r\n", "\n") // Normalize line endings
+ content = strings.ReplaceAll(content, "\t", " ") // Replace tabs with spaces
truncated := truncateHeight(content, responseContextHeight)
- highlighted, _ := highlight.SyntaxHighlight(truncated, path, t.BgBase)
- lines := strings.Split(highlighted, "\n")
+ lines := strings.Split(truncated, "\n")
+ for i, ln := range lines {
+ lines[i] = escapeContent(ln)
+ }
+
+ highlighted, _ := highlight.SyntaxHighlight(strings.Join(lines, "\n"), path, t.BgBase)
+ lines = strings.Split(highlighted, "\n")
if len(strings.Split(content, "\n")) > responseContextHeight {
lines = append(lines, t.S().Muted.
@@ -721,6 +731,7 @@ func renderCodeContent(v *toolCallCmp, path, content string, offset int) string
PaddingLeft(1).
Render(v.fit(ln, w-1)))
}
+
return lipgloss.JoinVertical(lipgloss.Left, lines...)
}
@@ -766,3 +777,20 @@ func prettifyToolName(name string) string {
return name
}
}
+
+// escapeContent replaces control characters with their Unicode Control Picture
+// representations to ensure they are displayed correctly in the UI.
+func escapeContent(content string) string {
+ var sb strings.Builder
+ for _, r := range content {
+ switch {
+ case r >= 0 && r <= 0x1f: // Control characters 0x00-0x1F
+ sb.WriteRune('\u2400' + r)
+ case r == ansi.DEL:
+ sb.WriteRune('\u2421')
+ default:
+ sb.WriteRune(r)
+ }
+ }
+ return sb.String()
+}
@@ -40,6 +40,8 @@ type Completions interface {
Query() string // Returns the current filter query
KeyMap() KeyMap
Position() (int, int) // Returns the X and Y position of the completions popup
+ Width() int
+ Height() int
}
type completionsCmp struct {
@@ -54,6 +56,8 @@ type completionsCmp struct {
query string // The current filter query
}
+const maxCompletionsWidth = 80 // Maximum width for the completions popup
+
func New() Completions {
completionsKeyMap := DefaultKeyMap()
keyMap := list.DefaultKeyMap()
@@ -92,7 +96,7 @@ func (c *completionsCmp) Init() tea.Cmd {
func (c *completionsCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.WindowSizeMsg:
- c.width = min(msg.Width-c.x, 80)
+ c.width = min(msg.Width-c.x, maxCompletionsWidth)
c.height = min(msg.Height-c.y, 15)
return c, nil
case tea.KeyPressMsg:
@@ -118,10 +122,7 @@ func (c *completionsCmp) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
Value: selectedItem,
})
case key.Matches(msg, c.keyMap.Cancel):
- if c.open {
- c.open = false
- return c, util.CmdHandler(CompletionsClosedMsg{})
- }
+ return c, util.CmdHandler(CloseCompletionsMsg{})
}
case CloseCompletionsMsg:
c.open = false
@@ -197,3 +198,11 @@ func (c *completionsCmp) KeyMap() KeyMap {
func (c *completionsCmp) Position() (int, int) {
return c.x, c.y - c.height
}
+
+func (c *completionsCmp) Width() int {
+ return c.width
+}
+
+func (c *completionsCmp) Height() int {
+ return c.height
+}
@@ -323,18 +323,14 @@ func (p *permissionDialogCmp) generateBashContent() string {
content := pr.Command
t := styles.CurrentTheme()
content = strings.TrimSpace(content)
- content = "\n" + content + "\n"
lines := strings.Split(content, "\n")
width := p.width - 4
var out []string
for _, ln := range lines {
- ln = " " + ln // left padding
- if len(ln) > width {
- ln = ansi.Truncate(ln, width, "…")
- }
out = append(out, t.S().Muted.
Width(width).
+ Padding(0, 3).
Foreground(t.FgBase).
Background(t.BgSubtle).
Render(ln))
@@ -344,6 +340,7 @@ func (p *permissionDialogCmp) generateBashContent() string {
renderedContent := strings.Join(out, "\n")
finalContent := baseStyle.
Width(p.contentViewPort.Width()).
+ Padding(1, 0).
Render(renderedContent)
return finalContent
@@ -413,13 +410,26 @@ func (p *permissionDialogCmp) generateDefaultContent() string {
content := p.permission.Description
- // Use the cache for markdown rendering
- renderedContent := p.GetOrSetMarkdown(p.permission.ID, func() (string, error) {
- r := styles.GetMarkdownRenderer(p.width - 4)
- s, err := r.Render(content)
- return s, err
- })
+ content = strings.TrimSpace(content)
+ content = "\n" + content + "\n"
+ lines := strings.Split(content, "\n")
+
+ width := p.width - 4
+ var out []string
+ for _, ln := range lines {
+ ln = " " + ln // left padding
+ if len(ln) > width {
+ ln = ansi.Truncate(ln, width, "…")
+ }
+ out = append(out, t.S().Muted.
+ Width(width).
+ Foreground(t.FgBase).
+ Background(t.BgSubtle).
+ Render(ln))
+ }
+ // Use the cache for markdown rendering
+ renderedContent := strings.Join(out, "\n")
finalContent := baseStyle.
Width(p.contentViewPort.Width()).
Render(renderedContent)
@@ -459,7 +469,11 @@ func (p *permissionDialogCmp) render() string {
contentFinal := p.getOrGenerateContent()
// Always set viewport content (the caching is handled in getOrGenerateContent)
- contentHeight := min(p.height-9, lipgloss.Height(contentFinal))
+ const minContentHeight = 9
+ contentHeight := min(
+ max(minContentHeight, p.height-minContentHeight),
+ lipgloss.Height(contentFinal),
+ )
p.contentViewPort.SetHeight(contentHeight)
p.contentViewPort.SetContent(contentFinal)
@@ -529,6 +543,9 @@ func (p *permissionDialogCmp) SetSize() tea.Cmd {
// Default to diff split mode when dialog is wide enough.
p.defaultDiffSplitMode = p.width >= 140
+ // Set a maximum width for the dialog
+ p.width = min(p.width, 180)
+
// Mark content as dirty if size changed
if oldWidth != p.width || oldHeight != p.height {
p.contentDirty = true
@@ -275,7 +275,7 @@ func (p *chatPage) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return p, p.cancel()
}
case key.Matches(msg, p.keyMap.Details):
- p.showDetails()
+ p.toggleDetails()
return p, nil
}
@@ -382,7 +382,7 @@ func (p *chatPage) View() string {
Width(p.detailsWidth).
Border(lipgloss.RoundedBorder()).
BorderForeground(t.BorderFocus)
- version := t.S().Subtle.Width(p.detailsWidth - 2).AlignHorizontal(lipgloss.Right).Render(version.Version)
+ version := t.S().Base.Foreground(t.Border).Width(p.detailsWidth - 4).AlignHorizontal(lipgloss.Right).Render(version.Version)
details := style.Render(
lipgloss.JoinVertical(
lipgloss.Left,
@@ -446,12 +446,9 @@ func (p *chatPage) setCompactMode(compact bool) {
}
p.compact = compact
if compact {
- p.compact = true
p.sidebar.SetCompactMode(true)
} else {
- p.compact = false
- p.showingDetails = false
- p.sidebar.SetCompactMode(false)
+ p.setShowDetails(false)
}
}
@@ -558,12 +555,19 @@ func (p *chatPage) cancel() tea.Cmd {
return cancelTimerCmd()
}
-func (p *chatPage) showDetails() {
+func (p *chatPage) setShowDetails(show bool) {
+ p.showingDetails = show
+ p.header.SetDetailsOpen(p.showingDetails)
+ if !p.compact {
+ p.sidebar.SetCompactMode(false)
+ }
+}
+
+func (p *chatPage) toggleDetails() {
if p.session.ID == "" || !p.compact {
return
}
- p.showingDetails = !p.showingDetails
- p.header.SetDetailsOpen(p.showingDetails)
+ p.setShowDetails(!p.showingDetails)
}
func (p *chatPage) sendMessage(text string, attachments []message.Attachment) tea.Cmd {
@@ -116,6 +116,16 @@ func (a *appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
case completions.OpenCompletionsMsg, completions.FilterCompletionsMsg, completions.CloseCompletionsMsg:
u, completionCmd := a.completions.Update(msg)
a.completions = u.(completions.Completions)
+ switch msg := msg.(type) {
+ case completions.OpenCompletionsMsg:
+ x, _ := a.completions.Position()
+ if a.completions.Width()+x >= a.wWidth {
+ // Adjust X position to fit in the window.
+ msg.X = a.wWidth - a.completions.Width() - 1
+ u, completionCmd = a.completions.Update(msg)
+ a.completions = u.(completions.Completions)
+ }
+ }
return a, completionCmd
// Dialog messages
@@ -1,246 +0,0 @@
-// Copyright 2019 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package myers implements the Myers diff algorithm.
-package myers
-
-import (
- "strings"
-
- diff "github.com/aymanbagabas/go-udiff"
-)
-
-// Sources:
-// https://blog.jcoglan.com/2017/02/17/the-myers-diff-algorithm-part-3/
-// https://www.codeproject.com/Articles/42279/%2FArticles%2F42279%2FInvestigating-Myers-diff-algorithm-Part-1-of-2
-
-// ComputeEdits returns the diffs of two strings using a simple
-// line-based implementation, like [diff.Strings].
-//
-// Deprecated: this implementation is moribund. However, when diffs
-// appear in marker test expectations, they are the particular diffs
-// produced by this implementation. The marker test framework
-// asserts diff(orig, got)==wantDiff, but ideally it would compute
-// got==apply(orig, wantDiff) so that the notation of the diff
-// is immaterial.
-func ComputeEdits(before, after string) []diff.Edit {
- beforeLines := splitLines(before)
- ops := operations(beforeLines, splitLines(after))
-
- // Build a table mapping line number to offset.
- lineOffsets := make([]int, 0, len(beforeLines)+1)
- total := 0
- for i := range beforeLines {
- lineOffsets = append(lineOffsets, total)
- total += len(beforeLines[i])
- }
- lineOffsets = append(lineOffsets, total) // EOF
-
- edits := make([]diff.Edit, 0, len(ops))
- for _, op := range ops {
- start, end := lineOffsets[op.I1], lineOffsets[op.I2]
- switch op.Kind {
- case opDelete:
- // Delete: before[I1:I2] is deleted.
- edits = append(edits, diff.Edit{Start: start, End: end})
- case opInsert:
- // Insert: after[J1:J2] is inserted at before[I1:I1].
- if content := strings.Join(op.Content, ""); content != "" {
- edits = append(edits, diff.Edit{Start: start, End: end, New: content})
- }
- }
- }
- return edits
-}
-
-// opKind is used to denote the type of operation a line represents.
-type opKind int
-
-const (
- opDelete opKind = iota // line deleted from input (-)
- opInsert // line inserted into output (+)
- opEqual // line present in input and output
-)
-
-func (kind opKind) String() string {
- switch kind {
- case opDelete:
- return "delete"
- case opInsert:
- return "insert"
- case opEqual:
- return "equal"
- default:
- panic("unknown opKind")
- }
-}
-
-type operation struct {
- Kind opKind
- Content []string // content from b
- I1, I2 int // indices of the line in a
- J1 int // indices of the line in b, J2 implied by len(Content)
-}
-
-// operations returns the list of operations to convert a into b, consolidating
-// operations for multiple lines and not including equal lines.
-func operations(a, b []string) []*operation {
- if len(a) == 0 && len(b) == 0 {
- return nil
- }
-
- trace, offset := shortestEditSequence(a, b)
- snakes := backtrack(trace, len(a), len(b), offset)
-
- M, N := len(a), len(b)
-
- var i int
- solution := make([]*operation, len(a)+len(b))
-
- add := func(op *operation, i2, j2 int) {
- if op == nil {
- return
- }
- op.I2 = i2
- if op.Kind == opInsert {
- op.Content = b[op.J1:j2]
- }
- solution[i] = op
- i++
- }
- x, y := 0, 0
- for _, snake := range snakes {
- if len(snake) < 2 {
- continue
- }
- var op *operation
- // delete (horizontal)
- for snake[0]-snake[1] > x-y {
- if op == nil {
- op = &operation{
- Kind: opDelete,
- I1: x,
- J1: y,
- }
- }
- x++
- if x == M {
- break
- }
- }
- add(op, x, y)
- op = nil
- // insert (vertical)
- for snake[0]-snake[1] < x-y {
- if op == nil {
- op = &operation{
- Kind: opInsert,
- I1: x,
- J1: y,
- }
- }
- y++
- }
- add(op, x, y)
- op = nil
- // equal (diagonal)
- for x < snake[0] {
- x++
- y++
- }
- if x >= M && y >= N {
- break
- }
- }
- return solution[:i]
-}
-
-// backtrack uses the trace for the edit sequence computation and returns the
-// "snakes" that make up the solution. A "snake" is a single deletion or
-// insertion followed by zero or diagonals.
-func backtrack(trace [][]int, x, y, offset int) [][]int {
- snakes := make([][]int, len(trace))
- d := len(trace) - 1
- for ; x > 0 && y > 0 && d > 0; d-- {
- V := trace[d]
- if len(V) == 0 {
- continue
- }
- snakes[d] = []int{x, y}
-
- k := x - y
-
- var kPrev int
- if k == -d || (k != d && V[k-1+offset] < V[k+1+offset]) {
- kPrev = k + 1
- } else {
- kPrev = k - 1
- }
-
- x = V[kPrev+offset]
- y = x - kPrev
- }
- if x < 0 || y < 0 {
- return snakes
- }
- snakes[d] = []int{x, y}
- return snakes
-}
-
-// shortestEditSequence returns the shortest edit sequence that converts a into b.
-func shortestEditSequence(a, b []string) ([][]int, int) {
- M, N := len(a), len(b)
- V := make([]int, 2*(N+M)+1)
- offset := N + M
- trace := make([][]int, N+M+1)
-
- // Iterate through the maximum possible length of the SES (N+M).
- for d := 0; d <= N+M; d++ {
- copyV := make([]int, len(V))
- // k lines are represented by the equation y = x - k. We move in
- // increments of 2 because end points for even d are on even k lines.
- for k := -d; k <= d; k += 2 {
- // At each point, we either go down or to the right. We go down if
- // k == -d, and we go to the right if k == d. We also prioritize
- // the maximum x value, because we prefer deletions to insertions.
- var x int
- if k == -d || (k != d && V[k-1+offset] < V[k+1+offset]) {
- x = V[k+1+offset] // down
- } else {
- x = V[k-1+offset] + 1 // right
- }
-
- y := x - k
-
- // Diagonal moves while we have equal contents.
- for x < M && y < N && a[x] == b[y] {
- x++
- y++
- }
-
- V[k+offset] = x
-
- // Return if we've exceeded the maximum values.
- if x == M && y == N {
- // Makes sure to save the state of the array before returning.
- copy(copyV, V)
- trace[d] = copyV
- return trace, offset
- }
- }
-
- // Save the state of the array.
- copy(copyV, V)
- trace[d] = copyV
- }
- return nil, 0
-}
-
-func splitLines(text string) []string {
- lines := strings.SplitAfter(text, "\n")
- if lines[len(lines)-1] == "" {
- lines = lines[:len(lines)-1]
- }
- return lines
-}
@@ -320,12 +320,10 @@ type Program struct {
// where to read inputs from, this will usually be os.Stdin.
input io.Reader
- mu sync.Mutex
// ttyInput is null if input is not a TTY.
ttyInput term.File
previousTtyInputState *term.State
inputReader *uv.TerminalReader
- traceInput bool // true if input should be traced
readLoopDone chan struct{}
mouseMode bool // indicates whether we should enable mouse on Windows
@@ -1,6 +1,7 @@
package lipgloss
import (
+ "fmt"
"image"
"sort"
@@ -94,17 +95,14 @@ type Layer struct {
zIndex int
children []*Layer
id string
- content string
+ content uv.Drawable
}
// NewLayer creates a new Layer with the given content. It calculates the size
// based on the widest line and the number of lines in the content.
-func NewLayer(content string) (l *Layer) {
+func NewLayer(content any) (l *Layer) {
l = new(Layer)
- l.content = content
- height := Height(content)
- width := Width(content)
- l.rect = image.Rect(0, 0, width, height)
+ l.SetContent(content)
return l
}
@@ -216,23 +214,56 @@ func (l *Layer) AddLayers(layers ...*Layer) *Layer {
}
// SetContent sets the content of the Layer.
-func (l *Layer) SetContent(content string) *Layer {
- l.content = content
+func (l *Layer) SetContent(content any) *Layer {
+ var drawable uv.Drawable
+ var rect image.Rectangle
+ switch c := content.(type) {
+ case uv.Drawable:
+ drawable = c
+ switch c := c.(type) {
+ case interface{ Bounds() image.Rectangle }:
+ rect.Max.X = c.Bounds().Dx()
+ rect.Max.Y = c.Bounds().Dy()
+ case interface {
+ Width() int
+ Height() int
+ }:
+ rect.Max.X = c.Width()
+ rect.Max.Y = c.Height()
+ }
+ case fmt.Stringer:
+ s := c.String()
+ drawable = uv.NewStyledString(s)
+ rect = image.Rect(0, 0, Width(s), Height(s))
+ case string:
+ drawable = uv.NewStyledString(c)
+ rect = image.Rect(0, 0, Width(c), Height(c))
+ default:
+ s := fmt.Sprint(content)
+ drawable = uv.NewStyledString(s)
+ rect = image.Rect(0, 0, Width(s), Height(s))
+ }
+ l.content = drawable
+ l.rect = rect
return l
}
// Content returns the content of the Layer.
-func (l *Layer) Content() string {
+func (l *Layer) Content() any {
return l.content
}
// Draw draws the Layer onto the given screen buffer.
-func (l *Layer) Draw(scr uv.Screen, _ image.Rectangle) {
- ss := uv.NewStyledString(l.content)
- ss.Draw(scr, l.Bounds())
+func (l *Layer) Draw(scr uv.Screen, area image.Rectangle) {
+ if l.content == nil {
+ return
+ }
+ l.content.Draw(scr, area.Intersect(l.Bounds()))
for _, child := range l.children {
- ss := uv.NewStyledString(child.content)
- ss.Draw(scr, child.Bounds())
+ if child.content == nil {
+ continue
+ }
+ child.content.Draw(scr, area.Intersect(child.Bounds()))
}
}
@@ -1,5 +1,7 @@
# Ultraviolet
+<img width="400" alt="Charm Ultraviolet" src="https://github.com/user-attachments/assets/3484e4b0-3741-4e8c-bebf-9ea51f5bb49c" />
+
<p>
<a href="https://github.com/charmbracelet/ultraviolet/releases"><img src="https://img.shields.io/github/release/charmbracelet/ultraviolet.svg" alt="Latest Release"></a>
<a href="https://pkg.go.dev/github.com/charmbracelet/ultraviolet?tab=doc"><img src="https://godoc.org/github.com/charmbracelet/ultraviolet?status.svg" alt="GoDoc"></a>
@@ -3,6 +3,7 @@ package uv
import (
"context"
+ "github.com/charmbracelet/x/term"
"golang.org/x/sync/errgroup"
)
@@ -59,3 +60,30 @@ func (im *InputManager) ReceiveEvents(ctx context.Context, events chan<- Event)
// Wait for all receivers to finish
return errg.Wait()
}
+
+// InitialSizeReceiver query the initial size of the terminal window and sends
+// it to the given event channel.
+type InitialSizeReceiver struct {
+ File term.File
+}
+
+// ReceiveEvents queries the initial size of the terminal window and sends it
+// to the given event channel. It stops when event is sent, the context is done
+// or an error occurs.
+func (r *InitialSizeReceiver) ReceiveEvents(ctx context.Context, events chan<- Event) error {
+ if r.File == nil {
+ return nil // No file set, nothing to do.
+ }
+
+ w, h, err := term.GetSize(r.File.Fd())
+ if err != nil {
+ return err
+ }
+
+ select {
+ case <-ctx.Done():
+ return ctx.Err()
+ case events <- WindowSizeEvent{Width: w, Height: h}:
+ return nil
+ }
+}
@@ -20,6 +20,8 @@ import (
"github.com/muesli/cancelreader"
)
+const isWindows = "windows"
+
var (
// ErrNotTerminal is returned when one of the I/O streams is not a terminal.
ErrNotTerminal = fmt.Errorf("not a terminal")
@@ -42,8 +44,7 @@ type Terminal struct {
inTtyState *term.State
outTty term.File
outTtyState *term.State
- winchTty term.File // The terminal to receive window size changes from.
- started bool // Indicates if the terminal has been started.
+ started bool // Indicates if the terminal has been started.
// Terminal type, screen and buffer.
termtype string // The $TERM type.
@@ -123,7 +124,7 @@ func NewTerminal(in io.Reader, out io.Writer, env []string) *Terminal {
// Handle debugging I/O.
debug, ok := os.LookupEnv("UV_DEBUG")
if ok && len(debug) > 0 {
- f, err := os.OpenFile(debug, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0o666)
+ f, err := os.OpenFile(debug, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0o600)
if err != nil {
panic("failed to open debug file: " + err.Error())
}
@@ -346,7 +347,7 @@ func (t *Terminal) EnableMode(modes ...ansi.Mode) {
for _, m := range modes {
t.modes[m] = ansi.ModeSet
}
- t.scr.WriteString(ansi.SetMode(modes...)) //nolint:errcheck
+ t.scr.WriteString(ansi.SetMode(modes...)) //nolint:errcheck,gosec
}
// DisableMode disables the given modes on the terminal. This is typically
@@ -362,7 +363,7 @@ func (t *Terminal) DisableMode(modes ...ansi.Mode) {
for _, m := range modes {
t.modes[m] = ansi.ModeReset
}
- t.scr.WriteString(ansi.ResetMode(modes...)) //nolint:errcheck
+ t.scr.WriteString(ansi.ResetMode(modes...)) //nolint:errcheck,gosec
}
// RequestMode requests the current state of the given modes from the terminal.
@@ -372,7 +373,7 @@ func (t *Terminal) DisableMode(modes ...ansi.Mode) {
// Note that this won't take any effect until the next [Terminal.Display] or
// [Terminal.Flush] call.
func (t *Terminal) RequestMode(mode ansi.Mode) {
- t.scr.WriteString(ansi.RequestMode(mode)) //nolint:errcheck
+ t.scr.WriteString(ansi.RequestMode(mode)) //nolint:errcheck,gosec
}
// MouseMode represents the mouse mode for the terminal. It is used to enable
@@ -399,7 +400,7 @@ func (t *Terminal) SetForegroundColor(c color.Color) {
t.setFg = c
col, ok := colorful.MakeColor(c)
if ok {
- t.scr.WriteString(ansi.SetForegroundColor(col.Hex())) //nolint:errcheck
+ t.scr.WriteString(ansi.SetForegroundColor(col.Hex())) //nolint:errcheck,gosec
}
}
@@ -408,7 +409,7 @@ func (t *Terminal) SetForegroundColor(c color.Color) {
// Note that this won't take any effect until the next [Terminal.Display] or
// [Terminal.Flush] call.
func (t *Terminal) RequestForegroundColor() {
- t.scr.WriteString(ansi.RequestForegroundColor) //nolint:errcheck
+ t.scr.WriteString(ansi.RequestForegroundColor) //nolint:errcheck,gosec
}
// ResetForegroundColor resets the terminal foreground color to the
@@ -418,7 +419,7 @@ func (t *Terminal) RequestForegroundColor() {
// [Terminal.Flush] call.
func (t *Terminal) ResetForegroundColor() {
t.setFg = nil
- t.scr.WriteString(ansi.ResetForegroundColor) //nolint:errcheck
+ t.scr.WriteString(ansi.ResetForegroundColor) //nolint:errcheck,gosec
}
// SetBackgroundColor sets the terminal default background color.
@@ -429,7 +430,7 @@ func (t *Terminal) SetBackgroundColor(c color.Color) {
t.setBg = c
col, ok := colorful.MakeColor(c)
if ok {
- t.scr.WriteString(ansi.SetBackgroundColor(col.Hex())) //nolint:errcheck
+ t.scr.WriteString(ansi.SetBackgroundColor(col.Hex())) //nolint:errcheck,gosec
}
}
@@ -438,7 +439,7 @@ func (t *Terminal) SetBackgroundColor(c color.Color) {
// Note that this won't take any effect until the next [Terminal.Display] or
// [Terminal.Flush] call.
func (t *Terminal) RequestBackgroundColor() {
- t.scr.WriteString(ansi.RequestBackgroundColor) //nolint:errcheck
+ t.scr.WriteString(ansi.RequestBackgroundColor) //nolint:errcheck,gosec
}
// ResetBackgroundColor resets the terminal background color to the
@@ -448,7 +449,7 @@ func (t *Terminal) RequestBackgroundColor() {
// [Terminal.Flush] call.
func (t *Terminal) ResetBackgroundColor() {
t.setBg = nil
- t.scr.WriteString(ansi.ResetBackgroundColor) //nolint:errcheck
+ t.scr.WriteString(ansi.ResetBackgroundColor) //nolint:errcheck,gosec
}
// SetCursorColor sets the terminal cursor color.
@@ -459,7 +460,7 @@ func (t *Terminal) SetCursorColor(c color.Color) {
t.setCc = c
col, ok := colorful.MakeColor(c)
if ok {
- t.scr.WriteString(ansi.SetCursorColor(col.Hex())) //nolint:errcheck
+ t.scr.WriteString(ansi.SetCursorColor(col.Hex())) //nolint:errcheck,gosec
}
}
@@ -468,7 +469,7 @@ func (t *Terminal) SetCursorColor(c color.Color) {
// Note that this won't take any effect until the next [Terminal.Display] or
// [Terminal.Flush] call.
func (t *Terminal) RequestCursorColor() {
- t.scr.WriteString(ansi.RequestCursorColor) //nolint:errcheck
+ t.scr.WriteString(ansi.RequestCursorColor) //nolint:errcheck,gosec
}
// ResetCursorColor resets the terminal cursor color to the
@@ -478,7 +479,7 @@ func (t *Terminal) RequestCursorColor() {
// [Terminal.Flush] call.
func (t *Terminal) ResetCursorColor() {
t.setCc = nil
- t.scr.WriteString(ansi.ResetCursorColor) //nolint:errcheck
+ t.scr.WriteString(ansi.ResetCursorColor) //nolint:errcheck,gosec
}
// SetCursorShape sets the terminal cursor shape and blinking style.
@@ -488,7 +489,7 @@ func (t *Terminal) ResetCursorColor() {
func (t *Terminal) SetCursorShape(shape CursorShape, blink bool) {
style := shape.Encode(blink)
t.curStyle = style
- t.scr.WriteString(ansi.SetCursorStyle(style)) //nolint:errcheck
+ t.scr.WriteString(ansi.SetCursorStyle(style)) //nolint:errcheck,gosec
}
// EnableMouse enables mouse support on the terminal.
@@ -520,7 +521,7 @@ func (t *Terminal) EnableMouse(modes ...MouseMode) {
mode = ButtonMouseMode | DragMouseMode | AllMouseMode
}
t.mouseMode = mode
- if runtime.GOOS != "windows" {
+ if runtime.GOOS != isWindows {
modes := []ansi.Mode{}
if t.mouseMode&AllMouseMode != 0 {
modes = append(modes, ansi.AnyEventMouseMode)
@@ -532,7 +533,7 @@ func (t *Terminal) EnableMouse(modes ...MouseMode) {
modes = append(modes, ansi.SgrExtMouseMode)
t.EnableMode(modes...)
}
- t.enableWindowsMouse() //nolint:errcheck
+ t.enableWindowsMouse() //nolint:errcheck,gosec
}
// DisableMouse disables mouse support on the terminal. This will disable mouse
@@ -542,7 +543,7 @@ func (t *Terminal) EnableMouse(modes ...MouseMode) {
// [Terminal.Display] or [Terminal.Flush] call.
func (t *Terminal) DisableMouse() {
t.mouseMode = 0
- if runtime.GOOS != "windows" {
+ if runtime.GOOS != isWindows {
var modes []ansi.Mode
if t.modes.Get(ansi.AnyEventMouseMode).IsSet() {
modes = append(modes, ansi.AnyEventMouseMode)
@@ -558,7 +559,7 @@ func (t *Terminal) DisableMouse() {
}
t.DisableMode(modes...)
}
- t.disableWindowsMouse() //nolint:errcheck
+ t.disableWindowsMouse() //nolint:errcheck,gosec
}
// EnableBracketedPaste enables bracketed paste mode on the terminal. This is
@@ -608,9 +609,9 @@ func (t *Terminal) enterAltScreen(cursor bool) {
t.scr.EnterAltScreen()
if cursor && !altscreen {
if t.scr.CursorHidden() {
- t.scr.WriteString(ansi.HideCursor) //nolint:errcheck
+ t.scr.WriteString(ansi.HideCursor) //nolint:errcheck,gosec
} else {
- t.scr.WriteString(ansi.ShowCursor) //nolint:errcheck
+ t.scr.WriteString(ansi.ShowCursor) //nolint:errcheck,gosec
}
}
t.scr.SetRelativeCursor(false)
@@ -639,9 +640,9 @@ func (t *Terminal) exitAltScreen(cursor bool) {
t.scr.ExitAltScreen()
if cursor && altscreen {
if t.scr.CursorHidden() {
- t.scr.WriteString(ansi.HideCursor) //nolint:errcheck
+ t.scr.WriteString(ansi.HideCursor) //nolint:errcheck,gosec
} else {
- t.scr.WriteString(ansi.ShowCursor) //nolint:errcheck
+ t.scr.WriteString(ansi.ShowCursor) //nolint:errcheck,gosec
}
}
t.scr.SetRelativeCursor(true)
@@ -725,11 +726,6 @@ func (t *Terminal) Start() error {
return ErrNotTerminal
}
- t.winchTty = t.inTty
- if t.winchTty == nil {
- t.winchTty = t.outTty
- }
-
// Get the initial terminal size.
var err error
t.size.Width, t.size.Height, err = t.GetSize()
@@ -749,11 +745,11 @@ func (t *Terminal) Start() error {
t.configureRenderer()
if t.modes.Get(ansi.AltScreenSaveCursorMode).IsSet() {
- t.enterAltScreen(false) //nolint:errcheck
+ t.enterAltScreen(false)
}
if t.cursorHidden == t.modes.Get(ansi.TextCursorEnableMode).IsReset() {
// We always hide the cursor when we start.
- t.hideCursor() //nolint:errcheck
+ t.hideCursor()
}
// Restore terminal modes.
for m, s := range t.modes {
@@ -763,7 +759,7 @@ func (t *Terminal) Start() error {
continue
default:
if s.IsSet() {
- t.scr.WriteString(ansi.SetMode(m)) //nolint:errcheck
+ t.scr.WriteString(ansi.SetMode(m)) //nolint:errcheck,gosec
}
}
}
@@ -779,21 +775,32 @@ func (t *Terminal) Start() error {
if c.colorp != nil && *c.colorp != nil {
col, ok := colorful.MakeColor(*c.colorp)
if ok {
- t.scr.WriteString(c.setter(col.Hex())) //nolint:errcheck
+ t.scr.WriteString(c.setter(col.Hex())) //nolint:errcheck,gosec
}
}
}
if t.curStyle > 1 {
- t.scr.WriteString(ansi.SetCursorStyle(t.curStyle)) //nolint:errcheck
+ t.scr.WriteString(ansi.SetCursorStyle(t.curStyle)) //nolint:errcheck,gosec
}
if err := t.rd.Start(); err != nil {
return fmt.Errorf("error starting terminal: %w", err)
}
- recvs := []InputReceiver{t.rd}
- if runtime.GOOS != "windows" {
- t.wrdr = &WinChReceiver{t.winchTty}
+ var winchTty term.File
+ if runtime.GOOS == isWindows {
+ // On Windows, we need to use the console output buffer to get the
+ // window size.
+ winchTty = t.outTty
+ } else {
+ winchTty = t.inTty
+ if winchTty == nil {
+ winchTty = t.outTty
+ }
+ }
+ recvs := []InputReceiver{t.rd, &InitialSizeReceiver{winchTty}}
+ if runtime.GOOS != isWindows {
+ t.wrdr = &WinChReceiver{winchTty}
if err := t.wrdr.Start(); err != nil {
return fmt.Errorf("error starting window size receiver: %w", err)
}
@@ -818,13 +825,13 @@ func (t *Terminal) Start() error {
func (t *Terminal) Restore() error {
if t.inTtyState != nil {
if err := term.Restore(t.inTty.Fd(), t.inTtyState); err != nil {
- return err
+ return fmt.Errorf("error restoring input terminal state: %w", err)
}
t.inTtyState = nil
}
if t.outTtyState != nil {
if err := term.Restore(t.outTty.Fd(), t.outTtyState); err != nil {
- return err
+ return fmt.Errorf("error restoring output terminal state: %w", err)
}
t.outTtyState = nil
}
@@ -835,10 +842,10 @@ func (t *Terminal) Restore() error {
t.scr.MoveTo(0, t.buf.Height()-1)
}
if altscreen {
- t.exitAltScreen(false) //nolint:errcheck
+ t.exitAltScreen(false)
}
if cursorHidden {
- t.showCursor() //nolint:errcheck
+ t.showCursor()
// Override the cursor hidden state so that we can auto hide it again
// when the terminal resumes using [Terminal.Start].
t.cursorHidden = false
@@ -259,17 +259,22 @@ func (d *TerminalReader) run() {
// - "\x1b^" (alt+^ key press)
esc := n > 0 && n <= 2 && readBuf[0] == ansi.ESC
if esc {
- d.esc.Store(true)
- d.timeout.Reset(d.EscTimeout)
+ d.resetEsc()
}
d.notify <- readBuf[:n]
}
}
+func (d *TerminalReader) resetEsc() {
+ // Reset the escape sequence state and timer.
+ d.esc.Store(true)
+ d.timeout.Reset(d.EscTimeout)
+}
+
func (d *TerminalReader) sendEvents(events chan<- Event) {
// Lookup table first
- if d.lookup && d.timedout.Load() && len(d.buf) > 0 && d.buf[0] == ansi.ESC {
+ if d.lookup && d.timedout.Load() && len(d.buf) > 2 && d.buf[0] == ansi.ESC {
if k, ok := d.table[string(d.buf)]; ok {
events <- KeyPressEvent(k)
d.buf = d.buf[:0]
@@ -309,8 +314,7 @@ LOOP:
if slices.Contains([]byte{
ansi.ESC, ansi.CSI, ansi.OSC, ansi.DCS, ansi.APC, ansi.SOS, ansi.PM,
}, d.buf[0]) {
- d.esc.Store(true)
- d.timeout.Reset(d.EscTimeout)
+ d.resetEsc()
}
}
// If this is the entire buffer, we can break and assume this
@@ -18,6 +18,8 @@ func (l *WinChReceiver) receiveEvents(ctx context.Context, f term.File, evch cha
sig := make(chan os.Signal, 1)
signal.Notify(sig, syscall.SIGWINCH)
+ defer signal.Stop(sig)
+
sendWinSize := func(w, h int) {
select {
case <-ctx.Done():
@@ -32,31 +34,8 @@ func (l *WinChReceiver) receiveEvents(ctx context.Context, f term.File, evch cha
}
}
- defer signal.Stop(sig)
-
- // Send the initial window size.
- winsize, err := termios.GetWinsize(int(f.Fd()))
- if err != nil {
- return err
- }
-
- var wg sync.WaitGroup
- wg.Add(1)
- go func() {
- defer wg.Done()
- sendWinSize(int(winsize.Col), int(winsize.Row))
- }()
-
- wg.Add(1)
- go func() {
- defer wg.Done()
- sendPixelSize(int(winsize.Xpixel), int(winsize.Ypixel))
- }()
-
- // Wait for all goroutines to finish before continuing.
- wg.Wait()
-
// Listen for window size changes.
+ var wg sync.WaitGroup
for {
select {
case <-ctx.Done():
@@ -12,8 +12,6 @@ package errgroup
import (
"context"
"fmt"
- "runtime"
- "runtime/debug"
"sync"
)
@@ -33,10 +31,6 @@ type Group struct {
errOnce sync.Once
err error
-
- mu sync.Mutex
- panicValue any // = PanicError | PanicValue; non-nil if some Group.Go goroutine panicked.
- abnormal bool // some Group.Go goroutine terminated abnormally (panic or goexit).
}
func (g *Group) done() {
@@ -56,22 +50,13 @@ func WithContext(ctx context.Context) (*Group, context.Context) {
return &Group{cancel: cancel}, ctx
}
-// Wait blocks until all function calls from the Go method have returned
-// normally, then returns the first non-nil error (if any) from them.
-//
-// If any of the calls panics, Wait panics with a [PanicValue];
-// and if any of them calls [runtime.Goexit], Wait calls runtime.Goexit.
+// Wait blocks until all function calls from the Go method have returned, then
+// returns the first non-nil error (if any) from them.
func (g *Group) Wait() error {
g.wg.Wait()
if g.cancel != nil {
g.cancel(g.err)
}
- if g.panicValue != nil {
- panic(g.panicValue)
- }
- if g.abnormal {
- runtime.Goexit()
- }
return g.err
}
@@ -81,53 +66,31 @@ func (g *Group) Wait() error {
// It blocks until the new goroutine can be added without the number of
// goroutines in the group exceeding the configured limit.
//
-// The first goroutine in the group that returns a non-nil error, panics, or
-// invokes [runtime.Goexit] will cancel the associated Context, if any.
+// The first goroutine in the group that returns a non-nil error will
+// cancel the associated Context, if any. The error will be returned
+// by Wait.
func (g *Group) Go(f func() error) {
if g.sem != nil {
g.sem <- token{}
}
- g.add(f)
-}
-
-func (g *Group) add(f func() error) {
g.wg.Add(1)
go func() {
defer g.done()
- normalReturn := false
- defer func() {
- if normalReturn {
- return
- }
- v := recover()
- g.mu.Lock()
- defer g.mu.Unlock()
- if !g.abnormal {
- if g.cancel != nil {
- g.cancel(g.err)
- }
- g.abnormal = true
- }
- if v != nil && g.panicValue == nil {
- switch v := v.(type) {
- case error:
- g.panicValue = PanicError{
- Recovered: v,
- Stack: debug.Stack(),
- }
- default:
- g.panicValue = PanicValue{
- Recovered: v,
- Stack: debug.Stack(),
- }
- }
- }
- }()
- err := f()
- normalReturn = true
- if err != nil {
+ // It is tempting to propagate panics from f()
+ // up to the goroutine that calls Wait, but
+ // it creates more problems than it solves:
+ // - it delays panics arbitrarily,
+ // making bugs harder to detect;
+ // - it turns f's panic stack into a mere value,
+ // hiding it from crash-monitoring tools;
+ // - it risks deadlocks that hide the panic entirely,
+ // if f's panic leaves the program in a state
+ // that prevents the Wait call from being reached.
+ // See #53757, #74275, #74304, #74306.
+
+ if err := f(); err != nil {
g.errOnce.Do(func() {
g.err = err
if g.cancel != nil {
@@ -152,7 +115,19 @@ func (g *Group) TryGo(f func() error) bool {
}
}
- g.add(f)
+ g.wg.Add(1)
+ go func() {
+ defer g.done()
+
+ if err := f(); err != nil {
+ g.errOnce.Do(func() {
+ g.err = err
+ if g.cancel != nil {
+ g.cancel(g.err)
+ }
+ })
+ }
+ }()
return true
}
@@ -174,34 +149,3 @@ func (g *Group) SetLimit(n int) {
}
g.sem = make(chan token, n)
}
-
-// PanicError wraps an error recovered from an unhandled panic
-// when calling a function passed to Go or TryGo.
-type PanicError struct {
- Recovered error
- Stack []byte // result of call to [debug.Stack]
-}
-
-func (p PanicError) Error() string {
- if len(p.Stack) > 0 {
- return fmt.Sprintf("recovered from errgroup.Group: %v\n%s", p.Recovered, p.Stack)
- }
- return fmt.Sprintf("recovered from errgroup.Group: %v", p.Recovered)
-}
-
-func (p PanicError) Unwrap() error { return p.Recovered }
-
-// PanicValue wraps a value that does not implement the error interface,
-// recovered from an unhandled panic when calling a function passed to Go or
-// TryGo.
-type PanicValue struct {
- Recovered any
- Stack []byte // result of call to [debug.Stack]
-}
-
-func (p PanicValue) String() string {
- if len(p.Stack) > 0 {
- return fmt.Sprintf("recovered from errgroup.Group: %v\n%s", p.Recovered, p.Stack)
- }
- return fmt.Sprintf("recovered from errgroup.Group: %v", p.Recovered)
-}
@@ -319,6 +319,7 @@ const (
AUDIT_INTEGRITY_POLICY_RULE = 0x70f
AUDIT_INTEGRITY_RULE = 0x70d
AUDIT_INTEGRITY_STATUS = 0x70a
+ AUDIT_INTEGRITY_USERSPACE = 0x710
AUDIT_IPC = 0x517
AUDIT_IPC_SET_PERM = 0x51f
AUDIT_IPE_ACCESS = 0x58c
@@ -843,9 +844,9 @@ const (
DM_UUID_FLAG = 0x4000
DM_UUID_LEN = 0x81
DM_VERSION = 0xc138fd00
- DM_VERSION_EXTRA = "-ioctl (2023-03-01)"
+ DM_VERSION_EXTRA = "-ioctl (2025-01-17)"
DM_VERSION_MAJOR = 0x4
- DM_VERSION_MINOR = 0x30
+ DM_VERSION_MINOR = 0x31
DM_VERSION_PATCHLEVEL = 0x0
DT_BLK = 0x6
DT_CHR = 0x2
@@ -941,6 +942,8 @@ const (
ETHER_FLOW = 0x12
ETHTOOL_BUSINFO_LEN = 0x20
ETHTOOL_EROMVERS_LEN = 0x20
+ ETHTOOL_FAMILY_NAME = "ethtool"
+ ETHTOOL_FAMILY_VERSION = 0x1
ETHTOOL_FEC_AUTO = 0x2
ETHTOOL_FEC_BASER = 0x10
ETHTOOL_FEC_LLRS = 0x20
@@ -1203,6 +1206,9 @@ const (
FAN_DENY = 0x2
FAN_ENABLE_AUDIT = 0x40
FAN_EPIDFD = -0x2
+ FAN_ERRNO_BITS = 0x8
+ FAN_ERRNO_MASK = 0xff
+ FAN_ERRNO_SHIFT = 0x18
FAN_EVENT_INFO_TYPE_DFID = 0x3
FAN_EVENT_INFO_TYPE_DFID_NAME = 0x2
FAN_EVENT_INFO_TYPE_ERROR = 0x5
@@ -1210,6 +1216,7 @@ const (
FAN_EVENT_INFO_TYPE_NEW_DFID_NAME = 0xc
FAN_EVENT_INFO_TYPE_OLD_DFID_NAME = 0xa
FAN_EVENT_INFO_TYPE_PIDFD = 0x4
+ FAN_EVENT_INFO_TYPE_RANGE = 0x6
FAN_EVENT_METADATA_LEN = 0x18
FAN_EVENT_ON_CHILD = 0x8000000
FAN_FS_ERROR = 0x8000
@@ -1240,6 +1247,7 @@ const (
FAN_OPEN_EXEC = 0x1000
FAN_OPEN_EXEC_PERM = 0x40000
FAN_OPEN_PERM = 0x10000
+ FAN_PRE_ACCESS = 0x100000
FAN_Q_OVERFLOW = 0x4000
FAN_RENAME = 0x10000000
FAN_REPORT_DFID_NAME = 0xc00
@@ -2787,7 +2795,7 @@ const (
RTAX_UNSPEC = 0x0
RTAX_WINDOW = 0x3
RTA_ALIGNTO = 0x4
- RTA_MAX = 0x1e
+ RTA_MAX = 0x1f
RTCF_DIRECTSRC = 0x4000000
RTCF_DOREDIRECT = 0x1000000
RTCF_LOG = 0x2000000
@@ -2864,10 +2872,12 @@ const (
RTM_DELACTION = 0x31
RTM_DELADDR = 0x15
RTM_DELADDRLABEL = 0x49
+ RTM_DELANYCAST = 0x3d
RTM_DELCHAIN = 0x65
RTM_DELLINK = 0x11
RTM_DELLINKPROP = 0x6d
RTM_DELMDB = 0x55
+ RTM_DELMULTICAST = 0x39
RTM_DELNEIGH = 0x1d
RTM_DELNETCONF = 0x51
RTM_DELNEXTHOP = 0x69
@@ -2917,11 +2927,13 @@ const (
RTM_NEWACTION = 0x30
RTM_NEWADDR = 0x14
RTM_NEWADDRLABEL = 0x48
+ RTM_NEWANYCAST = 0x3c
RTM_NEWCACHEREPORT = 0x60
RTM_NEWCHAIN = 0x64
RTM_NEWLINK = 0x10
RTM_NEWLINKPROP = 0x6c
RTM_NEWMDB = 0x54
+ RTM_NEWMULTICAST = 0x38
RTM_NEWNDUSEROPT = 0x44
RTM_NEWNEIGH = 0x1c
RTM_NEWNEIGHTBL = 0x40
@@ -2987,11 +2999,12 @@ const (
RUSAGE_THREAD = 0x1
RWF_APPEND = 0x10
RWF_ATOMIC = 0x40
+ RWF_DONTCACHE = 0x80
RWF_DSYNC = 0x2
RWF_HIPRI = 0x1
RWF_NOAPPEND = 0x20
RWF_NOWAIT = 0x8
- RWF_SUPPORTED = 0x7f
+ RWF_SUPPORTED = 0xff
RWF_SYNC = 0x4
RWF_WRITE_LIFE_NOT_SET = 0x0
SCHED_BATCH = 0x3
@@ -3271,6 +3284,7 @@ const (
STATX_BTIME = 0x800
STATX_CTIME = 0x80
STATX_DIOALIGN = 0x2000
+ STATX_DIO_READ_ALIGN = 0x20000
STATX_GID = 0x10
STATX_INO = 0x100
STATX_MNT_ID = 0x1000
@@ -3322,7 +3336,7 @@ const (
TASKSTATS_GENL_NAME = "TASKSTATS"
TASKSTATS_GENL_VERSION = 0x1
TASKSTATS_TYPE_MAX = 0x6
- TASKSTATS_VERSION = 0xe
+ TASKSTATS_VERSION = 0xf
TCIFLUSH = 0x0
TCIOFF = 0x2
TCIOFLUSH = 0x2
@@ -3503,6 +3517,7 @@ const (
TP_STATUS_WRONG_FORMAT = 0x4
TRACEFS_MAGIC = 0x74726163
TS_COMM_LEN = 0x20
+ UBI_IOCECNFO = 0xc01c6f06
UDF_SUPER_MAGIC = 0x15013346
UDP_CORK = 0x1
UDP_ENCAP = 0x64
@@ -372,6 +372,7 @@ const (
SO_RCVBUFFORCE = 0x21
SO_RCVLOWAT = 0x12
SO_RCVMARK = 0x4b
+ SO_RCVPRIORITY = 0x52
SO_RCVTIMEO = 0x14
SO_RCVTIMEO_NEW = 0x42
SO_RCVTIMEO_OLD = 0x14
@@ -373,6 +373,7 @@ const (
SO_RCVBUFFORCE = 0x21
SO_RCVLOWAT = 0x12
SO_RCVMARK = 0x4b
+ SO_RCVPRIORITY = 0x52
SO_RCVTIMEO = 0x14
SO_RCVTIMEO_NEW = 0x42
SO_RCVTIMEO_OLD = 0x14
@@ -378,6 +378,7 @@ const (
SO_RCVBUFFORCE = 0x21
SO_RCVLOWAT = 0x12
SO_RCVMARK = 0x4b
+ SO_RCVPRIORITY = 0x52
SO_RCVTIMEO = 0x14
SO_RCVTIMEO_NEW = 0x42
SO_RCVTIMEO_OLD = 0x14
@@ -371,6 +371,7 @@ const (
SO_RCVBUFFORCE = 0x21
SO_RCVLOWAT = 0x12
SO_RCVMARK = 0x4b
+ SO_RCVPRIORITY = 0x52
SO_RCVTIMEO = 0x14
SO_RCVTIMEO_NEW = 0x42
SO_RCVTIMEO_OLD = 0x14
@@ -365,6 +365,7 @@ const (
SO_RCVBUFFORCE = 0x21
SO_RCVLOWAT = 0x12
SO_RCVMARK = 0x4b
+ SO_RCVPRIORITY = 0x52
SO_RCVTIMEO = 0x14
SO_RCVTIMEO_NEW = 0x42
SO_RCVTIMEO_OLD = 0x14
@@ -371,6 +371,7 @@ const (
SO_RCVBUFFORCE = 0x21
SO_RCVLOWAT = 0x1004
SO_RCVMARK = 0x4b
+ SO_RCVPRIORITY = 0x52
SO_RCVTIMEO = 0x1006
SO_RCVTIMEO_NEW = 0x42
SO_RCVTIMEO_OLD = 0x1006
@@ -371,6 +371,7 @@ const (
SO_RCVBUFFORCE = 0x21
SO_RCVLOWAT = 0x1004
SO_RCVMARK = 0x4b
+ SO_RCVPRIORITY = 0x52
SO_RCVTIMEO = 0x1006
SO_RCVTIMEO_NEW = 0x42
SO_RCVTIMEO_OLD = 0x1006
@@ -371,6 +371,7 @@ const (
SO_RCVBUFFORCE = 0x21
SO_RCVLOWAT = 0x1004
SO_RCVMARK = 0x4b
+ SO_RCVPRIORITY = 0x52
SO_RCVTIMEO = 0x1006
SO_RCVTIMEO_NEW = 0x42
SO_RCVTIMEO_OLD = 0x1006
@@ -371,6 +371,7 @@ const (
SO_RCVBUFFORCE = 0x21
SO_RCVLOWAT = 0x1004
SO_RCVMARK = 0x4b
+ SO_RCVPRIORITY = 0x52
SO_RCVTIMEO = 0x1006
SO_RCVTIMEO_NEW = 0x42
SO_RCVTIMEO_OLD = 0x1006
@@ -426,6 +426,7 @@ const (
SO_RCVBUFFORCE = 0x21
SO_RCVLOWAT = 0x10
SO_RCVMARK = 0x4b
+ SO_RCVPRIORITY = 0x52
SO_RCVTIMEO = 0x12
SO_RCVTIMEO_NEW = 0x42
SO_RCVTIMEO_OLD = 0x12
@@ -430,6 +430,7 @@ const (
SO_RCVBUFFORCE = 0x21
SO_RCVLOWAT = 0x10
SO_RCVMARK = 0x4b
+ SO_RCVPRIORITY = 0x52
SO_RCVTIMEO = 0x12
SO_RCVTIMEO_NEW = 0x42
SO_RCVTIMEO_OLD = 0x12
@@ -430,6 +430,7 @@ const (
SO_RCVBUFFORCE = 0x21
SO_RCVLOWAT = 0x10
SO_RCVMARK = 0x4b
+ SO_RCVPRIORITY = 0x52
SO_RCVTIMEO = 0x12
SO_RCVTIMEO_NEW = 0x42
SO_RCVTIMEO_OLD = 0x12
@@ -362,6 +362,7 @@ const (
SO_RCVBUFFORCE = 0x21
SO_RCVLOWAT = 0x12
SO_RCVMARK = 0x4b
+ SO_RCVPRIORITY = 0x52
SO_RCVTIMEO = 0x14
SO_RCVTIMEO_NEW = 0x42
SO_RCVTIMEO_OLD = 0x14
@@ -434,6 +434,7 @@ const (
SO_RCVBUFFORCE = 0x21
SO_RCVLOWAT = 0x12
SO_RCVMARK = 0x4b
+ SO_RCVPRIORITY = 0x52
SO_RCVTIMEO = 0x14
SO_RCVTIMEO_NEW = 0x42
SO_RCVTIMEO_OLD = 0x14
@@ -473,6 +473,7 @@ const (
SO_RCVBUFFORCE = 0x100b
SO_RCVLOWAT = 0x800
SO_RCVMARK = 0x54
+ SO_RCVPRIORITY = 0x5b
SO_RCVTIMEO = 0x2000
SO_RCVTIMEO_NEW = 0x44
SO_RCVTIMEO_OLD = 0x2000
@@ -114,7 +114,7 @@ type Statx_t struct {
Atomic_write_unit_min uint32
Atomic_write_unit_max uint32
Atomic_write_segments_max uint32
- _ [1]uint32
+ Dio_read_offset_align uint32
_ [9]uint64
}
@@ -2226,8 +2226,11 @@ const (
NFT_PAYLOAD_LL_HEADER = 0x0
NFT_PAYLOAD_NETWORK_HEADER = 0x1
NFT_PAYLOAD_TRANSPORT_HEADER = 0x2
+ NFT_PAYLOAD_INNER_HEADER = 0x3
+ NFT_PAYLOAD_TUN_HEADER = 0x4
NFT_PAYLOAD_CSUM_NONE = 0x0
NFT_PAYLOAD_CSUM_INET = 0x1
+ NFT_PAYLOAD_CSUM_SCTP = 0x2
NFT_PAYLOAD_L4CSUM_PSEUDOHDR = 0x1
NFTA_PAYLOAD_UNSPEC = 0x0
NFTA_PAYLOAD_DREG = 0x1
@@ -3802,7 +3805,16 @@ const (
ETHTOOL_MSG_PSE_GET = 0x24
ETHTOOL_MSG_PSE_SET = 0x25
ETHTOOL_MSG_RSS_GET = 0x26
- ETHTOOL_MSG_USER_MAX = 0x2d
+ ETHTOOL_MSG_PLCA_GET_CFG = 0x27
+ ETHTOOL_MSG_PLCA_SET_CFG = 0x28
+ ETHTOOL_MSG_PLCA_GET_STATUS = 0x29
+ ETHTOOL_MSG_MM_GET = 0x2a
+ ETHTOOL_MSG_MM_SET = 0x2b
+ ETHTOOL_MSG_MODULE_FW_FLASH_ACT = 0x2c
+ ETHTOOL_MSG_PHY_GET = 0x2d
+ ETHTOOL_MSG_TSCONFIG_GET = 0x2e
+ ETHTOOL_MSG_TSCONFIG_SET = 0x2f
+ ETHTOOL_MSG_USER_MAX = 0x2f
ETHTOOL_MSG_KERNEL_NONE = 0x0
ETHTOOL_MSG_STRSET_GET_REPLY = 0x1
ETHTOOL_MSG_LINKINFO_GET_REPLY = 0x2
@@ -3842,7 +3854,17 @@ const (
ETHTOOL_MSG_MODULE_NTF = 0x24
ETHTOOL_MSG_PSE_GET_REPLY = 0x25
ETHTOOL_MSG_RSS_GET_REPLY = 0x26
- ETHTOOL_MSG_KERNEL_MAX = 0x2e
+ ETHTOOL_MSG_PLCA_GET_CFG_REPLY = 0x27
+ ETHTOOL_MSG_PLCA_GET_STATUS_REPLY = 0x28
+ ETHTOOL_MSG_PLCA_NTF = 0x29
+ ETHTOOL_MSG_MM_GET_REPLY = 0x2a
+ ETHTOOL_MSG_MM_NTF = 0x2b
+ ETHTOOL_MSG_MODULE_FW_FLASH_NTF = 0x2c
+ ETHTOOL_MSG_PHY_GET_REPLY = 0x2d
+ ETHTOOL_MSG_PHY_NTF = 0x2e
+ ETHTOOL_MSG_TSCONFIG_GET_REPLY = 0x2f
+ ETHTOOL_MSG_TSCONFIG_SET_REPLY = 0x30
+ ETHTOOL_MSG_KERNEL_MAX = 0x30
ETHTOOL_FLAG_COMPACT_BITSETS = 0x1
ETHTOOL_FLAG_OMIT_REPLY = 0x2
ETHTOOL_FLAG_STATS = 0x4
@@ -3949,7 +3971,12 @@ const (
ETHTOOL_A_RINGS_TCP_DATA_SPLIT = 0xb
ETHTOOL_A_RINGS_CQE_SIZE = 0xc
ETHTOOL_A_RINGS_TX_PUSH = 0xd
- ETHTOOL_A_RINGS_MAX = 0x10
+ ETHTOOL_A_RINGS_RX_PUSH = 0xe
+ ETHTOOL_A_RINGS_TX_PUSH_BUF_LEN = 0xf
+ ETHTOOL_A_RINGS_TX_PUSH_BUF_LEN_MAX = 0x10
+ ETHTOOL_A_RINGS_HDS_THRESH = 0x11
+ ETHTOOL_A_RINGS_HDS_THRESH_MAX = 0x12
+ ETHTOOL_A_RINGS_MAX = 0x12
ETHTOOL_A_CHANNELS_UNSPEC = 0x0
ETHTOOL_A_CHANNELS_HEADER = 0x1
ETHTOOL_A_CHANNELS_RX_MAX = 0x2
@@ -4015,7 +4042,9 @@ const (
ETHTOOL_A_TSINFO_TX_TYPES = 0x3
ETHTOOL_A_TSINFO_RX_FILTERS = 0x4
ETHTOOL_A_TSINFO_PHC_INDEX = 0x5
- ETHTOOL_A_TSINFO_MAX = 0x6
+ ETHTOOL_A_TSINFO_STATS = 0x6
+ ETHTOOL_A_TSINFO_HWTSTAMP_PROVIDER = 0x7
+ ETHTOOL_A_TSINFO_MAX = 0x7
ETHTOOL_A_CABLE_TEST_UNSPEC = 0x0
ETHTOOL_A_CABLE_TEST_HEADER = 0x1
ETHTOOL_A_CABLE_TEST_MAX = 0x1
@@ -4613,6 +4642,7 @@ const (
NL80211_ATTR_AKM_SUITES = 0x4c
NL80211_ATTR_AP_ISOLATE = 0x60
NL80211_ATTR_AP_SETTINGS_FLAGS = 0x135
+ NL80211_ATTR_ASSOC_SPP_AMSDU = 0x14a
NL80211_ATTR_AUTH_DATA = 0x9c
NL80211_ATTR_AUTH_TYPE = 0x35
NL80211_ATTR_BANDS = 0xef
@@ -4623,6 +4653,7 @@ const (
NL80211_ATTR_BSS_BASIC_RATES = 0x24
NL80211_ATTR_BSS = 0x2f
NL80211_ATTR_BSS_CTS_PROT = 0x1c
+ NL80211_ATTR_BSS_DUMP_INCLUDE_USE_DATA = 0x147
NL80211_ATTR_BSS_HT_OPMODE = 0x6d
NL80211_ATTR_BSSID = 0xf5
NL80211_ATTR_BSS_SELECT = 0xe3
@@ -4682,6 +4713,7 @@ const (
NL80211_ATTR_DTIM_PERIOD = 0xd
NL80211_ATTR_DURATION = 0x57
NL80211_ATTR_EHT_CAPABILITY = 0x136
+ NL80211_ATTR_EMA_RNR_ELEMS = 0x145
NL80211_ATTR_EML_CAPABILITY = 0x13d
NL80211_ATTR_EXT_CAPA = 0xa9
NL80211_ATTR_EXT_CAPA_MASK = 0xaa
@@ -4717,6 +4749,7 @@ const (
NL80211_ATTR_HIDDEN_SSID = 0x7e
NL80211_ATTR_HT_CAPABILITY = 0x1f
NL80211_ATTR_HT_CAPABILITY_MASK = 0x94
+ NL80211_ATTR_HW_TIMESTAMP_ENABLED = 0x144
NL80211_ATTR_IE_ASSOC_RESP = 0x80
NL80211_ATTR_IE = 0x2a
NL80211_ATTR_IE_PROBE_RESP = 0x7f
@@ -4747,9 +4780,10 @@ const (
NL80211_ATTR_MAC_HINT = 0xc8
NL80211_ATTR_MAC_MASK = 0xd7
NL80211_ATTR_MAX_AP_ASSOC_STA = 0xca
- NL80211_ATTR_MAX = 0x14d
+ NL80211_ATTR_MAX = 0x150
NL80211_ATTR_MAX_CRIT_PROT_DURATION = 0xb4
NL80211_ATTR_MAX_CSA_COUNTERS = 0xce
+ NL80211_ATTR_MAX_HW_TIMESTAMP_PEERS = 0x143
NL80211_ATTR_MAX_MATCH_SETS = 0x85
NL80211_ATTR_MAX_NUM_AKM_SUITES = 0x13c
NL80211_ATTR_MAX_NUM_PMKIDS = 0x56
@@ -4774,9 +4808,12 @@ const (
NL80211_ATTR_MGMT_SUBTYPE = 0x29
NL80211_ATTR_MLD_ADDR = 0x13a
NL80211_ATTR_MLD_CAPA_AND_OPS = 0x13e
+ NL80211_ATTR_MLO_LINK_DISABLED = 0x146
NL80211_ATTR_MLO_LINK_ID = 0x139
NL80211_ATTR_MLO_LINKS = 0x138
NL80211_ATTR_MLO_SUPPORT = 0x13b
+ NL80211_ATTR_MLO_TTLM_DLINK = 0x148
+ NL80211_ATTR_MLO_TTLM_ULINK = 0x149
NL80211_ATTR_MNTR_FLAGS = 0x17
NL80211_ATTR_MPATH_INFO = 0x1b
NL80211_ATTR_MPATH_NEXT_HOP = 0x1a
@@ -4809,12 +4846,14 @@ const (
NL80211_ATTR_PORT_AUTHORIZED = 0x103
NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN = 0x5
NL80211_ATTR_POWER_RULE_MAX_EIRP = 0x6
+ NL80211_ATTR_POWER_RULE_PSD = 0x8
NL80211_ATTR_PREV_BSSID = 0x4f
NL80211_ATTR_PRIVACY = 0x46
NL80211_ATTR_PROBE_RESP = 0x91
NL80211_ATTR_PROBE_RESP_OFFLOAD = 0x90
NL80211_ATTR_PROTOCOL_FEATURES = 0xad
NL80211_ATTR_PS_STATE = 0x5d
+ NL80211_ATTR_PUNCT_BITMAP = 0x142
NL80211_ATTR_QOS_MAP = 0xc7
NL80211_ATTR_RADAR_BACKGROUND = 0x134
NL80211_ATTR_RADAR_EVENT = 0xa8
@@ -4943,7 +4982,9 @@ const (
NL80211_ATTR_WIPHY_FREQ = 0x26
NL80211_ATTR_WIPHY_FREQ_HINT = 0xc9
NL80211_ATTR_WIPHY_FREQ_OFFSET = 0x122
+ NL80211_ATTR_WIPHY_INTERFACE_COMBINATIONS = 0x14c
NL80211_ATTR_WIPHY_NAME = 0x2
+ NL80211_ATTR_WIPHY_RADIOS = 0x14b
NL80211_ATTR_WIPHY_RETRY_LONG = 0x3e
NL80211_ATTR_WIPHY_RETRY_SHORT = 0x3d
NL80211_ATTR_WIPHY_RTS_THRESHOLD = 0x40
@@ -4978,6 +5019,8 @@ const (
NL80211_BAND_ATTR_IFTYPE_DATA = 0x9
NL80211_BAND_ATTR_MAX = 0xd
NL80211_BAND_ATTR_RATES = 0x2
+ NL80211_BAND_ATTR_S1G_CAPA = 0xd
+ NL80211_BAND_ATTR_S1G_MCS_NSS_SET = 0xc
NL80211_BAND_ATTR_VHT_CAPA = 0x8
NL80211_BAND_ATTR_VHT_MCS_SET = 0x7
NL80211_BAND_IFTYPE_ATTR_EHT_CAP_MAC = 0x8
@@ -5001,6 +5044,10 @@ const (
NL80211_BSS_BEACON_INTERVAL = 0x4
NL80211_BSS_BEACON_TSF = 0xd
NL80211_BSS_BSSID = 0x1
+ NL80211_BSS_CANNOT_USE_6GHZ_PWR_MISMATCH = 0x2
+ NL80211_BSS_CANNOT_USE_NSTR_NONPRIMARY = 0x1
+ NL80211_BSS_CANNOT_USE_REASONS = 0x18
+ NL80211_BSS_CANNOT_USE_UHB_PWR_MISMATCH = 0x2
NL80211_BSS_CAPABILITY = 0x5
NL80211_BSS_CHAIN_SIGNAL = 0x13
NL80211_BSS_CHAN_WIDTH_10 = 0x1
@@ -5032,6 +5079,9 @@ const (
NL80211_BSS_STATUS = 0x9
NL80211_BSS_STATUS_IBSS_JOINED = 0x2
NL80211_BSS_TSF = 0x3
+ NL80211_BSS_USE_FOR = 0x17
+ NL80211_BSS_USE_FOR_MLD_LINK = 0x2
+ NL80211_BSS_USE_FOR_NORMAL = 0x1
NL80211_CHAN_HT20 = 0x1
NL80211_CHAN_HT40MINUS = 0x2
NL80211_CHAN_HT40PLUS = 0x3
@@ -5117,7 +5167,8 @@ const (
NL80211_CMD_LEAVE_IBSS = 0x2c
NL80211_CMD_LEAVE_MESH = 0x45
NL80211_CMD_LEAVE_OCB = 0x6d
- NL80211_CMD_MAX = 0x9b
+ NL80211_CMD_LINKS_REMOVED = 0x9a
+ NL80211_CMD_MAX = 0x9d
NL80211_CMD_MICHAEL_MIC_FAILURE = 0x29
NL80211_CMD_MODIFY_LINK_STA = 0x97
NL80211_CMD_NAN_MATCH = 0x78
@@ -5161,6 +5212,7 @@ const (
NL80211_CMD_SET_COALESCE = 0x65
NL80211_CMD_SET_CQM = 0x3f
NL80211_CMD_SET_FILS_AAD = 0x92
+ NL80211_CMD_SET_HW_TIMESTAMP = 0x99
NL80211_CMD_SET_INTERFACE = 0x6
NL80211_CMD_SET_KEY = 0xa
NL80211_CMD_SET_MAC_ACL = 0x5d
@@ -5180,6 +5232,7 @@ const (
NL80211_CMD_SET_SAR_SPECS = 0x8c
NL80211_CMD_SET_STATION = 0x12
NL80211_CMD_SET_TID_CONFIG = 0x89
+ NL80211_CMD_SET_TID_TO_LINK_MAPPING = 0x9b
NL80211_CMD_SET_TX_BITRATE_MASK = 0x39
NL80211_CMD_SET_WDS_PEER = 0x42
NL80211_CMD_SET_WIPHY = 0x2
@@ -5247,6 +5300,7 @@ const (
NL80211_EXT_FEATURE_AIRTIME_FAIRNESS = 0x21
NL80211_EXT_FEATURE_AP_PMKSA_CACHING = 0x22
NL80211_EXT_FEATURE_AQL = 0x28
+ NL80211_EXT_FEATURE_AUTH_AND_DEAUTH_RANDOM_TA = 0x40
NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT = 0x2e
NL80211_EXT_FEATURE_BEACON_PROTECTION = 0x29
NL80211_EXT_FEATURE_BEACON_RATE_HE = 0x36
@@ -5262,6 +5316,7 @@ const (
NL80211_EXT_FEATURE_CQM_RSSI_LIST = 0xd
NL80211_EXT_FEATURE_DATA_ACK_SIGNAL_SUPPORT = 0x1b
NL80211_EXT_FEATURE_DEL_IBSS_STA = 0x2c
+ NL80211_EXT_FEATURE_DFS_CONCURRENT = 0x43
NL80211_EXT_FEATURE_DFS_OFFLOAD = 0x19
NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER = 0x20
NL80211_EXT_FEATURE_EXT_KEY_ID = 0x24
@@ -5281,9 +5336,12 @@ const (
NL80211_EXT_FEATURE_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION = 0x14
NL80211_EXT_FEATURE_OCE_PROBE_REQ_HIGH_TX_RATE = 0x13
NL80211_EXT_FEATURE_OPERATING_CHANNEL_VALIDATION = 0x31
+ NL80211_EXT_FEATURE_OWE_OFFLOAD_AP = 0x42
+ NL80211_EXT_FEATURE_OWE_OFFLOAD = 0x41
NL80211_EXT_FEATURE_POWERED_ADDR_CHANGE = 0x3d
NL80211_EXT_FEATURE_PROTECTED_TWT = 0x2b
NL80211_EXT_FEATURE_PROT_RANGE_NEGO_AND_MEASURE = 0x39
+ NL80211_EXT_FEATURE_PUNCT = 0x3e
NL80211_EXT_FEATURE_RADAR_BACKGROUND = 0x3c
NL80211_EXT_FEATURE_RRM = 0x1
NL80211_EXT_FEATURE_SAE_OFFLOAD_AP = 0x33
@@ -5295,8 +5353,10 @@ const (
NL80211_EXT_FEATURE_SCHED_SCAN_BAND_SPECIFIC_RSSI_THOLD = 0x23
NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI = 0xc
NL80211_EXT_FEATURE_SECURE_LTF = 0x37
+ NL80211_EXT_FEATURE_SECURE_NAN = 0x3f
NL80211_EXT_FEATURE_SECURE_RTT = 0x38
NL80211_EXT_FEATURE_SET_SCAN_DWELL = 0x5
+ NL80211_EXT_FEATURE_SPP_AMSDU_SUPPORT = 0x44
NL80211_EXT_FEATURE_STA_TX_PWR = 0x25
NL80211_EXT_FEATURE_TXQS = 0x1c
NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP = 0x35
@@ -5343,7 +5403,10 @@ const (
NL80211_FREQUENCY_ATTR_2MHZ = 0x16
NL80211_FREQUENCY_ATTR_4MHZ = 0x17
NL80211_FREQUENCY_ATTR_8MHZ = 0x18
+ NL80211_FREQUENCY_ATTR_ALLOW_6GHZ_VLP_AP = 0x21
+ NL80211_FREQUENCY_ATTR_CAN_MONITOR = 0x20
NL80211_FREQUENCY_ATTR_DFS_CAC_TIME = 0xd
+ NL80211_FREQUENCY_ATTR_DFS_CONCURRENT = 0x1d
NL80211_FREQUENCY_ATTR_DFS_STATE = 0x7
NL80211_FREQUENCY_ATTR_DFS_TIME = 0x8
NL80211_FREQUENCY_ATTR_DISABLED = 0x2
@@ -5357,6 +5420,8 @@ const (
NL80211_FREQUENCY_ATTR_NO_160MHZ = 0xc
NL80211_FREQUENCY_ATTR_NO_20MHZ = 0x10
NL80211_FREQUENCY_ATTR_NO_320MHZ = 0x1a
+ NL80211_FREQUENCY_ATTR_NO_6GHZ_AFC_CLIENT = 0x1f
+ NL80211_FREQUENCY_ATTR_NO_6GHZ_VLP_CLIENT = 0x1e
NL80211_FREQUENCY_ATTR_NO_80MHZ = 0xb
NL80211_FREQUENCY_ATTR_NO_EHT = 0x1b
NL80211_FREQUENCY_ATTR_NO_HE = 0x13
@@ -5364,8 +5429,11 @@ const (
NL80211_FREQUENCY_ATTR_NO_HT40_PLUS = 0xa
NL80211_FREQUENCY_ATTR_NO_IBSS = 0x3
NL80211_FREQUENCY_ATTR_NO_IR = 0x3
+ NL80211_FREQUENCY_ATTR_NO_UHB_AFC_CLIENT = 0x1f
+ NL80211_FREQUENCY_ATTR_NO_UHB_VLP_CLIENT = 0x1e
NL80211_FREQUENCY_ATTR_OFFSET = 0x14
NL80211_FREQUENCY_ATTR_PASSIVE_SCAN = 0x3
+ NL80211_FREQUENCY_ATTR_PSD = 0x1c
NL80211_FREQUENCY_ATTR_RADAR = 0x5
NL80211_FREQUENCY_ATTR_WMM = 0x12
NL80211_FTM_RESP_ATTR_CIVICLOC = 0x3
@@ -5430,6 +5498,7 @@ const (
NL80211_IFTYPE_STATION = 0x2
NL80211_IFTYPE_UNSPECIFIED = 0x0
NL80211_IFTYPE_WDS = 0x5
+ NL80211_KCK_EXT_LEN_32 = 0x20
NL80211_KCK_EXT_LEN = 0x18
NL80211_KCK_LEN = 0x10
NL80211_KEK_EXT_LEN = 0x20
@@ -5458,6 +5527,7 @@ const (
NL80211_MAX_SUPP_HT_RATES = 0x4d
NL80211_MAX_SUPP_RATES = 0x20
NL80211_MAX_SUPP_REG_RULES = 0x80
+ NL80211_MAX_SUPP_SELECTORS = 0x80
NL80211_MBSSID_CONFIG_ATTR_EMA = 0x5
NL80211_MBSSID_CONFIG_ATTR_INDEX = 0x3
NL80211_MBSSID_CONFIG_ATTR_MAX = 0x5
@@ -5703,11 +5773,16 @@ const (
NL80211_RADAR_PRE_CAC_EXPIRED = 0x4
NL80211_RATE_INFO_10_MHZ_WIDTH = 0xb
NL80211_RATE_INFO_160_MHZ_WIDTH = 0xa
+ NL80211_RATE_INFO_16_MHZ_WIDTH = 0x1d
+ NL80211_RATE_INFO_1_MHZ_WIDTH = 0x19
+ NL80211_RATE_INFO_2_MHZ_WIDTH = 0x1a
NL80211_RATE_INFO_320_MHZ_WIDTH = 0x12
NL80211_RATE_INFO_40_MHZ_WIDTH = 0x3
+ NL80211_RATE_INFO_4_MHZ_WIDTH = 0x1b
NL80211_RATE_INFO_5_MHZ_WIDTH = 0xc
NL80211_RATE_INFO_80_MHZ_WIDTH = 0x8
NL80211_RATE_INFO_80P80_MHZ_WIDTH = 0x9
+ NL80211_RATE_INFO_8_MHZ_WIDTH = 0x1c
NL80211_RATE_INFO_BITRATE32 = 0x5
NL80211_RATE_INFO_BITRATE = 0x1
NL80211_RATE_INFO_EHT_GI_0_8 = 0x0
@@ -5753,6 +5828,8 @@ const (
NL80211_RATE_INFO_HE_RU_ALLOC = 0x11
NL80211_RATE_INFO_MAX = 0x1d
NL80211_RATE_INFO_MCS = 0x2
+ NL80211_RATE_INFO_S1G_MCS = 0x17
+ NL80211_RATE_INFO_S1G_NSS = 0x18
NL80211_RATE_INFO_SHORT_GI = 0x4
NL80211_RATE_INFO_VHT_MCS = 0x6
NL80211_RATE_INFO_VHT_NSS = 0x7
@@ -5770,14 +5847,19 @@ const (
NL80211_REKEY_DATA_KEK = 0x1
NL80211_REKEY_DATA_REPLAY_CTR = 0x3
NL80211_REPLAY_CTR_LEN = 0x8
+ NL80211_RRF_ALLOW_6GHZ_VLP_AP = 0x1000000
NL80211_RRF_AUTO_BW = 0x800
NL80211_RRF_DFS = 0x10
+ NL80211_RRF_DFS_CONCURRENT = 0x200000
NL80211_RRF_GO_CONCURRENT = 0x1000
NL80211_RRF_IR_CONCURRENT = 0x1000
NL80211_RRF_NO_160MHZ = 0x10000
NL80211_RRF_NO_320MHZ = 0x40000
+ NL80211_RRF_NO_6GHZ_AFC_CLIENT = 0x800000
+ NL80211_RRF_NO_6GHZ_VLP_CLIENT = 0x400000
NL80211_RRF_NO_80MHZ = 0x8000
NL80211_RRF_NO_CCK = 0x2
+ NL80211_RRF_NO_EHT = 0x80000
NL80211_RRF_NO_HE = 0x20000
NL80211_RRF_NO_HT40 = 0x6000
NL80211_RRF_NO_HT40MINUS = 0x2000
@@ -5788,7 +5870,10 @@ const (
NL80211_RRF_NO_IR = 0x80
NL80211_RRF_NO_OFDM = 0x1
NL80211_RRF_NO_OUTDOOR = 0x8
+ NL80211_RRF_NO_UHB_AFC_CLIENT = 0x800000
+ NL80211_RRF_NO_UHB_VLP_CLIENT = 0x400000
NL80211_RRF_PASSIVE_SCAN = 0x80
+ NL80211_RRF_PSD = 0x100000
NL80211_RRF_PTMP_ONLY = 0x40
NL80211_RRF_PTP_ONLY = 0x20
NL80211_RXMGMT_FLAG_ANSWERED = 0x1
@@ -5849,6 +5934,7 @@ const (
NL80211_STA_FLAG_MAX_OLD_API = 0x6
NL80211_STA_FLAG_MFP = 0x4
NL80211_STA_FLAG_SHORT_PREAMBLE = 0x2
+ NL80211_STA_FLAG_SPP_AMSDU = 0x8
NL80211_STA_FLAG_TDLS_PEER = 0x6
NL80211_STA_FLAG_WME = 0x3
NL80211_STA_INFO_ACK_SIGNAL_AVG = 0x23
@@ -6007,6 +6093,13 @@ const (
NL80211_VHT_CAPABILITY_LEN = 0xc
NL80211_VHT_NSS_MAX = 0x8
NL80211_WIPHY_NAME_MAXLEN = 0x40
+ NL80211_WIPHY_RADIO_ATTR_FREQ_RANGE = 0x2
+ NL80211_WIPHY_RADIO_ATTR_INDEX = 0x1
+ NL80211_WIPHY_RADIO_ATTR_INTERFACE_COMBINATION = 0x3
+ NL80211_WIPHY_RADIO_ATTR_MAX = 0x4
+ NL80211_WIPHY_RADIO_FREQ_ATTR_END = 0x2
+ NL80211_WIPHY_RADIO_FREQ_ATTR_MAX = 0x2
+ NL80211_WIPHY_RADIO_FREQ_ATTR_START = 0x1
NL80211_WMMR_AIFSN = 0x3
NL80211_WMMR_CW_MAX = 0x2
NL80211_WMMR_CW_MIN = 0x1
@@ -6038,6 +6131,7 @@ const (
NL80211_WOWLAN_TRIG_PKT_PATTERN = 0x4
NL80211_WOWLAN_TRIG_RFKILL_RELEASE = 0x9
NL80211_WOWLAN_TRIG_TCP_CONNECTION = 0xe
+ NL80211_WOWLAN_TRIG_UNPROTECTED_DEAUTH_DISASSOC = 0x14
NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211 = 0xa
NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211_LEN = 0xb
NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023 = 0xc
@@ -285,10 +285,16 @@ type Taskstats struct {
_ [4]byte
Cpu_count uint64
Cpu_delay_total uint64
+ Cpu_delay_max uint64
+ Cpu_delay_min uint64
Blkio_count uint64
Blkio_delay_total uint64
+ Blkio_delay_max uint64
+ Blkio_delay_min uint64
Swapin_count uint64
Swapin_delay_total uint64
+ Swapin_delay_max uint64
+ Swapin_delay_min uint64
Cpu_run_real_total uint64
Cpu_run_virtual_total uint64
Ac_comm [32]int8
@@ -324,11 +330,17 @@ type Taskstats struct {
Cpu_scaled_run_real_total uint64
Freepages_count uint64
Freepages_delay_total uint64
+ Freepages_delay_max uint64
+ Freepages_delay_min uint64
Thrashing_count uint64
Thrashing_delay_total uint64
+ Thrashing_delay_max uint64
+ Thrashing_delay_min uint64
Ac_btime64 uint64
Compact_count uint64
Compact_delay_total uint64
+ Compact_delay_max uint64
+ Compact_delay_min uint64
Ac_tgid uint32
_ [4]byte
Ac_tgetime uint64
@@ -336,8 +348,12 @@ type Taskstats struct {
Ac_exe_inode uint64
Wpcopy_count uint64
Wpcopy_delay_total uint64
+ Wpcopy_delay_max uint64
+ Wpcopy_delay_min uint64
Irq_count uint64
Irq_delay_total uint64
+ Irq_delay_max uint64
+ Irq_delay_min uint64
}
type cpuMask uint32
@@ -300,10 +300,16 @@ type Taskstats struct {
Ac_nice uint8
Cpu_count uint64
Cpu_delay_total uint64
+ Cpu_delay_max uint64
+ Cpu_delay_min uint64
Blkio_count uint64
Blkio_delay_total uint64
+ Blkio_delay_max uint64
+ Blkio_delay_min uint64
Swapin_count uint64
Swapin_delay_total uint64
+ Swapin_delay_max uint64
+ Swapin_delay_min uint64
Cpu_run_real_total uint64
Cpu_run_virtual_total uint64
Ac_comm [32]int8
@@ -338,19 +344,29 @@ type Taskstats struct {
Cpu_scaled_run_real_total uint64
Freepages_count uint64
Freepages_delay_total uint64
+ Freepages_delay_max uint64
+ Freepages_delay_min uint64
Thrashing_count uint64
Thrashing_delay_total uint64
+ Thrashing_delay_max uint64
+ Thrashing_delay_min uint64
Ac_btime64 uint64
Compact_count uint64
Compact_delay_total uint64
+ Compact_delay_max uint64
+ Compact_delay_min uint64
Ac_tgid uint32
Ac_tgetime uint64
Ac_exe_dev uint64
Ac_exe_inode uint64
Wpcopy_count uint64
Wpcopy_delay_total uint64
+ Wpcopy_delay_max uint64
+ Wpcopy_delay_min uint64
Irq_count uint64
Irq_delay_total uint64
+ Irq_delay_max uint64
+ Irq_delay_min uint64
}
type cpuMask uint64
@@ -276,10 +276,16 @@ type Taskstats struct {
_ [4]byte
Cpu_count uint64
Cpu_delay_total uint64
+ Cpu_delay_max uint64
+ Cpu_delay_min uint64
Blkio_count uint64
Blkio_delay_total uint64
+ Blkio_delay_max uint64
+ Blkio_delay_min uint64
Swapin_count uint64
Swapin_delay_total uint64
+ Swapin_delay_max uint64
+ Swapin_delay_min uint64
Cpu_run_real_total uint64
Cpu_run_virtual_total uint64
Ac_comm [32]uint8
@@ -315,11 +321,17 @@ type Taskstats struct {
Cpu_scaled_run_real_total uint64
Freepages_count uint64
Freepages_delay_total uint64
+ Freepages_delay_max uint64
+ Freepages_delay_min uint64
Thrashing_count uint64
Thrashing_delay_total uint64
+ Thrashing_delay_max uint64
+ Thrashing_delay_min uint64
Ac_btime64 uint64
Compact_count uint64
Compact_delay_total uint64
+ Compact_delay_max uint64
+ Compact_delay_min uint64
Ac_tgid uint32
_ [4]byte
Ac_tgetime uint64
@@ -327,8 +339,12 @@ type Taskstats struct {
Ac_exe_inode uint64
Wpcopy_count uint64
Wpcopy_delay_total uint64
+ Wpcopy_delay_max uint64
+ Wpcopy_delay_min uint64
Irq_count uint64
Irq_delay_total uint64
+ Irq_delay_max uint64
+ Irq_delay_min uint64
}
type cpuMask uint32
@@ -279,10 +279,16 @@ type Taskstats struct {
Ac_nice uint8
Cpu_count uint64
Cpu_delay_total uint64
+ Cpu_delay_max uint64
+ Cpu_delay_min uint64
Blkio_count uint64
Blkio_delay_total uint64
+ Blkio_delay_max uint64
+ Blkio_delay_min uint64
Swapin_count uint64
Swapin_delay_total uint64
+ Swapin_delay_max uint64
+ Swapin_delay_min uint64
Cpu_run_real_total uint64
Cpu_run_virtual_total uint64
Ac_comm [32]int8
@@ -317,19 +323,29 @@ type Taskstats struct {
Cpu_scaled_run_real_total uint64
Freepages_count uint64
Freepages_delay_total uint64
+ Freepages_delay_max uint64
+ Freepages_delay_min uint64
Thrashing_count uint64
Thrashing_delay_total uint64
+ Thrashing_delay_max uint64
+ Thrashing_delay_min uint64
Ac_btime64 uint64
Compact_count uint64
Compact_delay_total uint64
+ Compact_delay_max uint64
+ Compact_delay_min uint64
Ac_tgid uint32
Ac_tgetime uint64
Ac_exe_dev uint64
Ac_exe_inode uint64
Wpcopy_count uint64
Wpcopy_delay_total uint64
+ Wpcopy_delay_max uint64
+ Wpcopy_delay_min uint64
Irq_count uint64
Irq_delay_total uint64
+ Irq_delay_max uint64
+ Irq_delay_min uint64
}
type cpuMask uint64
@@ -280,10 +280,16 @@ type Taskstats struct {
Ac_nice uint8
Cpu_count uint64
Cpu_delay_total uint64
+ Cpu_delay_max uint64
+ Cpu_delay_min uint64
Blkio_count uint64
Blkio_delay_total uint64
+ Blkio_delay_max uint64
+ Blkio_delay_min uint64
Swapin_count uint64
Swapin_delay_total uint64
+ Swapin_delay_max uint64
+ Swapin_delay_min uint64
Cpu_run_real_total uint64
Cpu_run_virtual_total uint64
Ac_comm [32]int8
@@ -318,19 +324,29 @@ type Taskstats struct {
Cpu_scaled_run_real_total uint64
Freepages_count uint64
Freepages_delay_total uint64
+ Freepages_delay_max uint64
+ Freepages_delay_min uint64
Thrashing_count uint64
Thrashing_delay_total uint64
+ Thrashing_delay_max uint64
+ Thrashing_delay_min uint64
Ac_btime64 uint64
Compact_count uint64
Compact_delay_total uint64
+ Compact_delay_max uint64
+ Compact_delay_min uint64
Ac_tgid uint32
Ac_tgetime uint64
Ac_exe_dev uint64
Ac_exe_inode uint64
Wpcopy_count uint64
Wpcopy_delay_total uint64
+ Wpcopy_delay_max uint64
+ Wpcopy_delay_min uint64
Irq_count uint64
Irq_delay_total uint64
+ Irq_delay_max uint64
+ Irq_delay_min uint64
}
type cpuMask uint64
@@ -281,10 +281,16 @@ type Taskstats struct {
_ [4]byte
Cpu_count uint64
Cpu_delay_total uint64
+ Cpu_delay_max uint64
+ Cpu_delay_min uint64
Blkio_count uint64
Blkio_delay_total uint64
+ Blkio_delay_max uint64
+ Blkio_delay_min uint64
Swapin_count uint64
Swapin_delay_total uint64
+ Swapin_delay_max uint64
+ Swapin_delay_min uint64
Cpu_run_real_total uint64
Cpu_run_virtual_total uint64
Ac_comm [32]int8
@@ -320,11 +326,17 @@ type Taskstats struct {
Cpu_scaled_run_real_total uint64
Freepages_count uint64
Freepages_delay_total uint64
+ Freepages_delay_max uint64
+ Freepages_delay_min uint64
Thrashing_count uint64
Thrashing_delay_total uint64
+ Thrashing_delay_max uint64
+ Thrashing_delay_min uint64
Ac_btime64 uint64
Compact_count uint64
Compact_delay_total uint64
+ Compact_delay_max uint64
+ Compact_delay_min uint64
Ac_tgid uint32
_ [4]byte
Ac_tgetime uint64
@@ -332,8 +344,12 @@ type Taskstats struct {
Ac_exe_inode uint64
Wpcopy_count uint64
Wpcopy_delay_total uint64
+ Wpcopy_delay_max uint64
+ Wpcopy_delay_min uint64
Irq_count uint64
Irq_delay_total uint64
+ Irq_delay_max uint64
+ Irq_delay_min uint64
}
type cpuMask uint32
@@ -282,10 +282,16 @@ type Taskstats struct {
Ac_nice uint8
Cpu_count uint64
Cpu_delay_total uint64
+ Cpu_delay_max uint64
+ Cpu_delay_min uint64
Blkio_count uint64
Blkio_delay_total uint64
+ Blkio_delay_max uint64
+ Blkio_delay_min uint64
Swapin_count uint64
Swapin_delay_total uint64
+ Swapin_delay_max uint64
+ Swapin_delay_min uint64
Cpu_run_real_total uint64
Cpu_run_virtual_total uint64
Ac_comm [32]int8
@@ -320,19 +326,29 @@ type Taskstats struct {
Cpu_scaled_run_real_total uint64
Freepages_count uint64
Freepages_delay_total uint64
+ Freepages_delay_max uint64
+ Freepages_delay_min uint64
Thrashing_count uint64
Thrashing_delay_total uint64
+ Thrashing_delay_max uint64
+ Thrashing_delay_min uint64
Ac_btime64 uint64
Compact_count uint64
Compact_delay_total uint64
+ Compact_delay_max uint64
+ Compact_delay_min uint64
Ac_tgid uint32
Ac_tgetime uint64
Ac_exe_dev uint64
Ac_exe_inode uint64
Wpcopy_count uint64
Wpcopy_delay_total uint64
+ Wpcopy_delay_max uint64
+ Wpcopy_delay_min uint64
Irq_count uint64
Irq_delay_total uint64
+ Irq_delay_max uint64
+ Irq_delay_min uint64
}
type cpuMask uint64
@@ -282,10 +282,16 @@ type Taskstats struct {
Ac_nice uint8
Cpu_count uint64
Cpu_delay_total uint64
+ Cpu_delay_max uint64
+ Cpu_delay_min uint64
Blkio_count uint64
Blkio_delay_total uint64
+ Blkio_delay_max uint64
+ Blkio_delay_min uint64
Swapin_count uint64
Swapin_delay_total uint64
+ Swapin_delay_max uint64
+ Swapin_delay_min uint64
Cpu_run_real_total uint64
Cpu_run_virtual_total uint64
Ac_comm [32]int8
@@ -320,19 +326,29 @@ type Taskstats struct {
Cpu_scaled_run_real_total uint64
Freepages_count uint64
Freepages_delay_total uint64
+ Freepages_delay_max uint64
+ Freepages_delay_min uint64
Thrashing_count uint64
Thrashing_delay_total uint64
+ Thrashing_delay_max uint64
+ Thrashing_delay_min uint64
Ac_btime64 uint64
Compact_count uint64
Compact_delay_total uint64
+ Compact_delay_max uint64
+ Compact_delay_min uint64
Ac_tgid uint32
Ac_tgetime uint64
Ac_exe_dev uint64
Ac_exe_inode uint64
Wpcopy_count uint64
Wpcopy_delay_total uint64
+ Wpcopy_delay_max uint64
+ Wpcopy_delay_min uint64
Irq_count uint64
Irq_delay_total uint64
+ Irq_delay_max uint64
+ Irq_delay_min uint64
}
type cpuMask uint64
@@ -281,10 +281,16 @@ type Taskstats struct {
_ [4]byte
Cpu_count uint64
Cpu_delay_total uint64
+ Cpu_delay_max uint64
+ Cpu_delay_min uint64
Blkio_count uint64
Blkio_delay_total uint64
+ Blkio_delay_max uint64
+ Blkio_delay_min uint64
Swapin_count uint64
Swapin_delay_total uint64
+ Swapin_delay_max uint64
+ Swapin_delay_min uint64
Cpu_run_real_total uint64
Cpu_run_virtual_total uint64
Ac_comm [32]int8
@@ -320,11 +326,17 @@ type Taskstats struct {
Cpu_scaled_run_real_total uint64
Freepages_count uint64
Freepages_delay_total uint64
+ Freepages_delay_max uint64
+ Freepages_delay_min uint64
Thrashing_count uint64
Thrashing_delay_total uint64
+ Thrashing_delay_max uint64
+ Thrashing_delay_min uint64
Ac_btime64 uint64
Compact_count uint64
Compact_delay_total uint64
+ Compact_delay_max uint64
+ Compact_delay_min uint64
Ac_tgid uint32
_ [4]byte
Ac_tgetime uint64
@@ -332,8 +344,12 @@ type Taskstats struct {
Ac_exe_inode uint64
Wpcopy_count uint64
Wpcopy_delay_total uint64
+ Wpcopy_delay_max uint64
+ Wpcopy_delay_min uint64
Irq_count uint64
Irq_delay_total uint64
+ Irq_delay_max uint64
+ Irq_delay_min uint64
}
type cpuMask uint32
@@ -288,10 +288,16 @@ type Taskstats struct {
_ [4]byte
Cpu_count uint64
Cpu_delay_total uint64
+ Cpu_delay_max uint64
+ Cpu_delay_min uint64
Blkio_count uint64
Blkio_delay_total uint64
+ Blkio_delay_max uint64
+ Blkio_delay_min uint64
Swapin_count uint64
Swapin_delay_total uint64
+ Swapin_delay_max uint64
+ Swapin_delay_min uint64
Cpu_run_real_total uint64
Cpu_run_virtual_total uint64
Ac_comm [32]uint8
@@ -327,11 +333,17 @@ type Taskstats struct {
Cpu_scaled_run_real_total uint64
Freepages_count uint64
Freepages_delay_total uint64
+ Freepages_delay_max uint64
+ Freepages_delay_min uint64
Thrashing_count uint64
Thrashing_delay_total uint64
+ Thrashing_delay_max uint64
+ Thrashing_delay_min uint64
Ac_btime64 uint64
Compact_count uint64
Compact_delay_total uint64
+ Compact_delay_max uint64
+ Compact_delay_min uint64
Ac_tgid uint32
_ [4]byte
Ac_tgetime uint64
@@ -339,8 +351,12 @@ type Taskstats struct {
Ac_exe_inode uint64
Wpcopy_count uint64
Wpcopy_delay_total uint64
+ Wpcopy_delay_max uint64
+ Wpcopy_delay_min uint64
Irq_count uint64
Irq_delay_total uint64
+ Irq_delay_max uint64
+ Irq_delay_min uint64
}
type cpuMask uint32
@@ -289,10 +289,16 @@ type Taskstats struct {
Ac_nice uint8
Cpu_count uint64
Cpu_delay_total uint64
+ Cpu_delay_max uint64
+ Cpu_delay_min uint64
Blkio_count uint64
Blkio_delay_total uint64
+ Blkio_delay_max uint64
+ Blkio_delay_min uint64
Swapin_count uint64
Swapin_delay_total uint64
+ Swapin_delay_max uint64
+ Swapin_delay_min uint64
Cpu_run_real_total uint64
Cpu_run_virtual_total uint64
Ac_comm [32]uint8
@@ -327,19 +333,29 @@ type Taskstats struct {
Cpu_scaled_run_real_total uint64
Freepages_count uint64
Freepages_delay_total uint64
+ Freepages_delay_max uint64
+ Freepages_delay_min uint64
Thrashing_count uint64
Thrashing_delay_total uint64
+ Thrashing_delay_max uint64
+ Thrashing_delay_min uint64
Ac_btime64 uint64
Compact_count uint64
Compact_delay_total uint64
+ Compact_delay_max uint64
+ Compact_delay_min uint64
Ac_tgid uint32
Ac_tgetime uint64
Ac_exe_dev uint64
Ac_exe_inode uint64
Wpcopy_count uint64
Wpcopy_delay_total uint64
+ Wpcopy_delay_max uint64
+ Wpcopy_delay_min uint64
Irq_count uint64
Irq_delay_total uint64
+ Irq_delay_max uint64
+ Irq_delay_min uint64
}
type cpuMask uint64
@@ -289,10 +289,16 @@ type Taskstats struct {
Ac_nice uint8
Cpu_count uint64
Cpu_delay_total uint64
+ Cpu_delay_max uint64
+ Cpu_delay_min uint64
Blkio_count uint64
Blkio_delay_total uint64
+ Blkio_delay_max uint64
+ Blkio_delay_min uint64
Swapin_count uint64
Swapin_delay_total uint64
+ Swapin_delay_max uint64
+ Swapin_delay_min uint64
Cpu_run_real_total uint64
Cpu_run_virtual_total uint64
Ac_comm [32]uint8
@@ -327,19 +333,29 @@ type Taskstats struct {
Cpu_scaled_run_real_total uint64
Freepages_count uint64
Freepages_delay_total uint64
+ Freepages_delay_max uint64
+ Freepages_delay_min uint64
Thrashing_count uint64
Thrashing_delay_total uint64
+ Thrashing_delay_max uint64
+ Thrashing_delay_min uint64
Ac_btime64 uint64
Compact_count uint64
Compact_delay_total uint64
+ Compact_delay_max uint64
+ Compact_delay_min uint64
Ac_tgid uint32
Ac_tgetime uint64
Ac_exe_dev uint64
Ac_exe_inode uint64
Wpcopy_count uint64
Wpcopy_delay_total uint64
+ Wpcopy_delay_max uint64
+ Wpcopy_delay_min uint64
Irq_count uint64
Irq_delay_total uint64
+ Irq_delay_max uint64
+ Irq_delay_min uint64
}
type cpuMask uint64
@@ -307,10 +307,16 @@ type Taskstats struct {
Ac_nice uint8
Cpu_count uint64
Cpu_delay_total uint64
+ Cpu_delay_max uint64
+ Cpu_delay_min uint64
Blkio_count uint64
Blkio_delay_total uint64
+ Blkio_delay_max uint64
+ Blkio_delay_min uint64
Swapin_count uint64
Swapin_delay_total uint64
+ Swapin_delay_max uint64
+ Swapin_delay_min uint64
Cpu_run_real_total uint64
Cpu_run_virtual_total uint64
Ac_comm [32]uint8
@@ -345,19 +351,29 @@ type Taskstats struct {
Cpu_scaled_run_real_total uint64
Freepages_count uint64
Freepages_delay_total uint64
+ Freepages_delay_max uint64
+ Freepages_delay_min uint64
Thrashing_count uint64
Thrashing_delay_total uint64
+ Thrashing_delay_max uint64
+ Thrashing_delay_min uint64
Ac_btime64 uint64
Compact_count uint64
Compact_delay_total uint64
+ Compact_delay_max uint64
+ Compact_delay_min uint64
Ac_tgid uint32
Ac_tgetime uint64
Ac_exe_dev uint64
Ac_exe_inode uint64
Wpcopy_count uint64
Wpcopy_delay_total uint64
+ Wpcopy_delay_max uint64
+ Wpcopy_delay_min uint64
Irq_count uint64
Irq_delay_total uint64
+ Irq_delay_max uint64
+ Irq_delay_min uint64
}
type cpuMask uint64
@@ -302,10 +302,16 @@ type Taskstats struct {
Ac_nice uint8
Cpu_count uint64
Cpu_delay_total uint64
+ Cpu_delay_max uint64
+ Cpu_delay_min uint64
Blkio_count uint64
Blkio_delay_total uint64
+ Blkio_delay_max uint64
+ Blkio_delay_min uint64
Swapin_count uint64
Swapin_delay_total uint64
+ Swapin_delay_max uint64
+ Swapin_delay_min uint64
Cpu_run_real_total uint64
Cpu_run_virtual_total uint64
Ac_comm [32]int8
@@ -340,19 +346,29 @@ type Taskstats struct {
Cpu_scaled_run_real_total uint64
Freepages_count uint64
Freepages_delay_total uint64
+ Freepages_delay_max uint64
+ Freepages_delay_min uint64
Thrashing_count uint64
Thrashing_delay_total uint64
+ Thrashing_delay_max uint64
+ Thrashing_delay_min uint64
Ac_btime64 uint64
Compact_count uint64
Compact_delay_total uint64
+ Compact_delay_max uint64
+ Compact_delay_min uint64
Ac_tgid uint32
Ac_tgetime uint64
Ac_exe_dev uint64
Ac_exe_inode uint64
Wpcopy_count uint64
Wpcopy_delay_total uint64
+ Wpcopy_delay_max uint64
+ Wpcopy_delay_min uint64
Irq_count uint64
Irq_delay_total uint64
+ Irq_delay_max uint64
+ Irq_delay_min uint64
}
type cpuMask uint64
@@ -284,10 +284,16 @@ type Taskstats struct {
Ac_nice uint8
Cpu_count uint64
Cpu_delay_total uint64
+ Cpu_delay_max uint64
+ Cpu_delay_min uint64
Blkio_count uint64
Blkio_delay_total uint64
+ Blkio_delay_max uint64
+ Blkio_delay_min uint64
Swapin_count uint64
Swapin_delay_total uint64
+ Swapin_delay_max uint64
+ Swapin_delay_min uint64
Cpu_run_real_total uint64
Cpu_run_virtual_total uint64
Ac_comm [32]int8
@@ -322,19 +328,29 @@ type Taskstats struct {
Cpu_scaled_run_real_total uint64
Freepages_count uint64
Freepages_delay_total uint64
+ Freepages_delay_max uint64
+ Freepages_delay_min uint64
Thrashing_count uint64
Thrashing_delay_total uint64
+ Thrashing_delay_max uint64
+ Thrashing_delay_min uint64
Ac_btime64 uint64
Compact_count uint64
Compact_delay_total uint64
+ Compact_delay_max uint64
+ Compact_delay_min uint64
Ac_tgid uint32
Ac_tgetime uint64
Ac_exe_dev uint64
Ac_exe_inode uint64
Wpcopy_count uint64
Wpcopy_delay_total uint64
+ Wpcopy_delay_max uint64
+ Wpcopy_delay_min uint64
Irq_count uint64
Irq_delay_total uint64
+ Irq_delay_max uint64
+ Irq_delay_min uint64
}
type cpuMask uint64
@@ -229,7 +229,6 @@ github.com/aymanbagabas/go-osc52/v2
## explicit; go 1.23
github.com/aymanbagabas/go-udiff
github.com/aymanbagabas/go-udiff/lcs
-github.com/aymanbagabas/go-udiff/myers
# github.com/aymerick/douceur v0.2.0
## explicit
github.com/aymerick/douceur/css
@@ -254,7 +253,7 @@ github.com/charmbracelet/bubbles/v2/spinner
github.com/charmbracelet/bubbles/v2/textarea
github.com/charmbracelet/bubbles/v2/textinput
github.com/charmbracelet/bubbles/v2/viewport
-# github.com/charmbracelet/bubbletea/v2 v2.0.0-beta.1 => github.com/charmbracelet/bubbletea-internal/v2 v2.0.0-20250710185017-3c0ffd25e595
+# github.com/charmbracelet/bubbletea/v2 v2.0.0-beta.1 => github.com/charmbracelet/bubbletea-internal/v2 v2.0.0-20250716142813-5d1379f56ba2
## explicit; go 1.24.0
github.com/charmbracelet/bubbletea/v2
# github.com/charmbracelet/colorprofile v0.3.1
@@ -269,7 +268,7 @@ github.com/charmbracelet/glamour/v2
github.com/charmbracelet/glamour/v2/ansi
github.com/charmbracelet/glamour/v2/internal/autolink
github.com/charmbracelet/glamour/v2/styles
-# github.com/charmbracelet/lipgloss/v2 v2.0.0-beta.3 => github.com/charmbracelet/lipgloss-internal/v2 v2.0.0-20250710185058-03664cb9cecb
+# github.com/charmbracelet/lipgloss/v2 v2.0.0-beta.3 => github.com/charmbracelet/lipgloss-internal/v2 v2.0.0-20250716143013-48f34cb75679
## explicit; go 1.24.2
github.com/charmbracelet/lipgloss/v2
github.com/charmbracelet/lipgloss/v2/table
@@ -277,7 +276,7 @@ github.com/charmbracelet/lipgloss/v2/tree
# github.com/charmbracelet/log/v2 v2.0.0-20250226163916-c379e29ff706
## explicit; go 1.19
github.com/charmbracelet/log/v2
-# github.com/charmbracelet/ultraviolet v0.0.0-20250708152637-0fe0235c8db9
+# github.com/charmbracelet/ultraviolet v0.0.0-20250716141307-2fae2b322afb
## explicit; go 1.24.0
github.com/charmbracelet/ultraviolet
# github.com/charmbracelet/x/ansi v0.9.3
@@ -682,10 +681,10 @@ golang.org/x/net/idna
golang.org/x/net/internal/httpcommon
golang.org/x/net/internal/timeseries
golang.org/x/net/trace
-# golang.org/x/sync v0.15.0
+# golang.org/x/sync v0.16.0
## explicit; go 1.23.0
golang.org/x/sync/errgroup
-# golang.org/x/sys v0.33.0
+# golang.org/x/sys v0.34.0
## explicit; go 1.23.0
golang.org/x/sys/cpu
golang.org/x/sys/plan9
@@ -838,5 +837,5 @@ mvdan.cc/sh/v3/fileutil
mvdan.cc/sh/v3/interp
mvdan.cc/sh/v3/pattern
mvdan.cc/sh/v3/syntax
-# github.com/charmbracelet/bubbletea/v2 => github.com/charmbracelet/bubbletea-internal/v2 v2.0.0-20250710185017-3c0ffd25e595
-# github.com/charmbracelet/lipgloss/v2 => github.com/charmbracelet/lipgloss-internal/v2 v2.0.0-20250710185058-03664cb9cecb
+# github.com/charmbracelet/bubbletea/v2 => github.com/charmbracelet/bubbletea-internal/v2 v2.0.0-20250716142813-5d1379f56ba2
+# github.com/charmbracelet/lipgloss/v2 => github.com/charmbracelet/lipgloss-internal/v2 v2.0.0-20250716143013-48f34cb75679