Skip to main content
Glama
data_injector.go9.04 kB
package aicoder import ( "fmt" "strings" "github.com/standardbeagle/brummer/internal/logs" "github.com/standardbeagle/brummer/internal/proxy" ) // DataInjectionType represents the type of data being injected type DataInjectionType string const ( DataInjectError DataInjectionType = "error" DataInjectLastError DataInjectionType = "last_error" DataInjectLogs DataInjectionType = "logs" DataInjectTestFailure DataInjectionType = "test_failure" DataInjectBuildOutput DataInjectionType = "build_output" DataInjectProcessInfo DataInjectionType = "process_info" DataInjectURLs DataInjectionType = "urls" DataInjectProxyReq DataInjectionType = "proxy_request" DataInjectSystemMsg DataInjectionType = "system_message" ) // DataInjector handles formatting and injecting Brummer data into AI sessions type DataInjector struct { // Configuration for data formatting maxLines int maxLength int includeColors bool } // NewDataInjector creates a new data injector func NewDataInjector() *DataInjector { return &DataInjector{ maxLines: 20, // Maximum lines to inject maxLength: 2000, // Maximum character length includeColors: false, // Disable colors for now } } // FormatData formats data based on its type for injection into terminal func (di *DataInjector) FormatData(dataType DataInjectionType, data interface{}) (string, error) { switch dataType { case DataInjectError, DataInjectLastError: return di.formatError(data) case DataInjectLogs: return di.formatLogs(data) case DataInjectTestFailure: return di.formatTestFailure(data) case DataInjectBuildOutput: return di.formatBuildOutput(data) case DataInjectProcessInfo: return di.formatProcessInfo(data) case DataInjectURLs: return di.formatURLs(data) case DataInjectProxyReq: return di.formatProxyRequest(data) case DataInjectSystemMsg: return di.formatSystemMessage(data) default: return fmt.Sprintf("Unknown data type: %v", data), nil } } // GetDataTypeLabel returns a human-readable label for the data type func (di *DataInjector) GetDataTypeLabel(dataType DataInjectionType) string { switch dataType { case DataInjectError: return "ERROR" case DataInjectLastError: return "LAST ERROR" case DataInjectLogs: return "RECENT LOGS" case DataInjectTestFailure: return "TEST FAILURE" case DataInjectBuildOutput: return "BUILD OUTPUT" case DataInjectProcessInfo: return "PROCESS INFO" case DataInjectURLs: return "DETECTED URLS" case DataInjectProxyReq: return "PROXY REQUEST" case DataInjectSystemMsg: return "SYSTEM MESSAGE" default: return "DATA" } } // formatError formats error context for injection func (di *DataInjector) formatError(data interface{}) (string, error) { switch v := data.(type) { case *logs.ErrorContext: var result strings.Builder result.WriteString(fmt.Sprintf("Type: %s\n", v.Type)) result.WriteString(fmt.Sprintf("Severity: %s\n", v.Severity)) result.WriteString(fmt.Sprintf("Process: %s\n", v.ProcessName)) result.WriteString(fmt.Sprintf("Time: %s\n", v.Timestamp.Format("15:04:05"))) result.WriteString(fmt.Sprintf("Message: %s\n", v.Message)) // ErrorContext doesn't have File/Line fields directly // Check if we can extract file info from context or stack if len(v.Stack) > 0 { result.WriteString("Stack trace:\n") for i, stackLine := range v.Stack { if i >= 5 { // Limit stack trace lines result.WriteString(" ... (truncated)\n") break } result.WriteString(fmt.Sprintf(" %s\n", stackLine)) } } if len(v.Context) > 0 { result.WriteString("Context:\n") for i, line := range v.Context { if i >= di.maxLines { result.WriteString("... (truncated)\n") break } result.WriteString(fmt.Sprintf(" %s\n", line)) } } return di.truncate(result.String()), nil case string: return di.truncate(v), nil default: return di.truncate(fmt.Sprintf("%v", data)), nil } } // formatLogs formats log entries for injection func (di *DataInjector) formatLogs(data interface{}) (string, error) { switch v := data.(type) { case []logs.LogEntry: var result strings.Builder for i, entry := range v { if i >= di.maxLines { result.WriteString("... (truncated)\n") break } result.WriteString(fmt.Sprintf("[%s] %s: %s\n", entry.Timestamp.Format("15:04:05"), entry.ProcessName, entry.Content)) } return di.truncate(result.String()), nil case string: return di.truncate(v), nil default: return di.truncate(fmt.Sprintf("%v", data)), nil } } // formatTestFailure formats test failure information func (di *DataInjector) formatTestFailure(data interface{}) (string, error) { // This would be expanded based on actual test failure data structure return di.truncate(fmt.Sprintf("Test Failure Details:\n%v", data)), nil } // formatBuildOutput formats build output func (di *DataInjector) formatBuildOutput(data interface{}) (string, error) { switch v := data.(type) { case string: lines := strings.Split(v, "\n") if len(lines) > di.maxLines { lines = lines[len(lines)-di.maxLines:] lines[0] = "... (showing last " + fmt.Sprintf("%d", di.maxLines) + " lines)" } return di.truncate(strings.Join(lines, "\n")), nil default: return di.truncate(fmt.Sprintf("%v", data)), nil } } // formatProcessInfo formats process information func (di *DataInjector) formatProcessInfo(data interface{}) (string, error) { // This would format process status, resource usage, etc. return di.truncate(fmt.Sprintf("Process Information:\n%v", data)), nil } // formatURLs formats detected URLs func (di *DataInjector) formatURLs(data interface{}) (string, error) { switch v := data.(type) { case []logs.URLEntry: var result strings.Builder for i, url := range v { if i >= di.maxLines { result.WriteString("... (truncated)\n") break } result.WriteString(fmt.Sprintf("%s", url.URL)) if url.ProxyURL != "" { result.WriteString(fmt.Sprintf(" → %s", url.ProxyURL)) } result.WriteString(fmt.Sprintf(" (%s)\n", url.ProcessName)) } return di.truncate(result.String()), nil case string: return di.truncate(v), nil default: return di.truncate(fmt.Sprintf("%v", data)), nil } } // formatProxyRequest formats proxy request information func (di *DataInjector) formatProxyRequest(data interface{}) (string, error) { switch v := data.(type) { case *proxy.Request: var result strings.Builder result.WriteString(fmt.Sprintf("Method: %s\n", v.Method)) result.WriteString(fmt.Sprintf("URL: %s\n", v.URL)) result.WriteString(fmt.Sprintf("Status: %d\n", v.StatusCode)) result.WriteString(fmt.Sprintf("Duration: %s\n", v.Duration)) result.WriteString(fmt.Sprintf("Time: %s\n", v.StartTime.Format("15:04:05"))) result.WriteString(fmt.Sprintf("Host: %s\n", v.Host)) result.WriteString(fmt.Sprintf("Path: %s\n", v.Path)) if v.Error != "" { result.WriteString(fmt.Sprintf("Error: %s\n", v.Error)) } if v.ProcessName != "" { result.WriteString(fmt.Sprintf("Process: %s\n", v.ProcessName)) } return di.truncate(result.String()), nil default: return di.truncate(fmt.Sprintf("%v", data)), nil } } // formatSystemMessage formats system messages func (di *DataInjector) formatSystemMessage(data interface{}) (string, error) { return di.truncate(fmt.Sprintf("%v", data)), nil } // truncate truncates text to maximum length func (di *DataInjector) truncate(text string) string { if len(text) <= di.maxLength { return text } return text[:di.maxLength-3] + "..." } // KeyBinding represents a key combination for data injection type KeyBinding struct { Key string Description string DataType DataInjectionType } // GetDefaultKeyBindings returns the default key bindings for data injection func GetDefaultKeyBindings() []KeyBinding { return []KeyBinding{ { Key: "ctrl+e", Description: "Inject last error message", DataType: DataInjectLastError, }, { Key: "ctrl+l", Description: "Inject recent log lines", DataType: DataInjectLogs, }, { Key: "ctrl+t", Description: "Inject test failure details", DataType: DataInjectTestFailure, }, { Key: "ctrl+b", Description: "Inject build output", DataType: DataInjectBuildOutput, }, { Key: "ctrl+p", Description: "Inject process information", DataType: DataInjectProcessInfo, }, { Key: "ctrl+u", Description: "Inject detected URLs", DataType: DataInjectURLs, }, { Key: "ctrl+r", Description: "Inject proxy request details", DataType: DataInjectProxyReq, }, } } // BrummerDataProvider interface for getting data from Brummer type BrummerDataProvider interface { GetLastError() *logs.ErrorContext GetRecentLogs(count int) []logs.LogEntry GetTestFailures() interface{} GetBuildOutput() string GetProcessInfo() interface{} GetDetectedURLs() []logs.URLEntry GetRecentProxyRequests(count int) []*proxy.Request }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/standardbeagle/brummer'

If you have feedback or need assistance with the MCP directory API, please join our Discord server