diff options
| author | adamdottv <[email protected]> | 2025-07-09 08:16:10 -0500 |
|---|---|---|
| committer | adamdottv <[email protected]> | 2025-07-09 08:16:10 -0500 |
| commit | ca8ce88354fa2f8e7cc8f0a911197a2550ebc269 (patch) | |
| tree | 07902e77aadb66113897c8363488d0b3a90ebf5d /packages/tui/internal | |
| parent | 37a86439c426bc735e3b3e76767ddd4c321fbe1a (diff) | |
| download | opencode-ca8ce88354fa2f8e7cc8f0a911197a2550ebc269.tar.gz opencode-ca8ce88354fa2f8e7cc8f0a911197a2550ebc269.zip | |
feat(tui): move logging to server logs
Diffstat (limited to 'packages/tui/internal')
| -rw-r--r-- | packages/tui/internal/completions/files-folders.go | 4 | ||||
| -rw-r--r-- | packages/tui/internal/util/apilogger.go | 131 |
2 files changed, 133 insertions, 2 deletions
diff --git a/packages/tui/internal/completions/files-folders.go b/packages/tui/internal/completions/files-folders.go index ec298af9e..55e0c1a1b 100644 --- a/packages/tui/internal/completions/files-folders.go +++ b/packages/tui/internal/completions/files-folders.go @@ -42,7 +42,7 @@ func (cg *filesAndFoldersContextGroup) getGitFiles() []dialog.CompletionItemI { }) for _, file := range files { - title := file.File + title := file.Path if file.Added > 0 { title += green(" +" + strconv.Itoa(int(file.Added))) } @@ -51,7 +51,7 @@ func (cg *filesAndFoldersContextGroup) getGitFiles() []dialog.CompletionItemI { } item := dialog.NewCompletionItem(dialog.CompletionItem{ Title: title, - Value: file.File, + Value: file.Path, }) items = append(items, item) } diff --git a/packages/tui/internal/util/apilogger.go b/packages/tui/internal/util/apilogger.go new file mode 100644 index 000000000..11eb21722 --- /dev/null +++ b/packages/tui/internal/util/apilogger.go @@ -0,0 +1,131 @@ +package util + +import ( + "context" + "log/slog" + "sync" + + opencode "github.com/sst/opencode-sdk-go" +) + +// APILogHandler is a slog.Handler that sends logs to the opencode API +type APILogHandler struct { + client *opencode.Client + service string + level slog.Level + attrs []slog.Attr + groups []string + mu sync.Mutex +} + +// NewAPILogHandler creates a new APILogHandler +func NewAPILogHandler(client *opencode.Client, service string, level slog.Level) *APILogHandler { + return &APILogHandler{ + client: client, + service: service, + level: level, + attrs: make([]slog.Attr, 0), + groups: make([]string, 0), + } +} + +// Enabled reports whether the handler handles records at the given level. +func (h *APILogHandler) Enabled(_ context.Context, level slog.Level) bool { + return level >= h.level +} + +// Handle handles the Record. +func (h *APILogHandler) Handle(ctx context.Context, r slog.Record) error { + // Convert slog level to API level + var apiLevel opencode.AppLogParamsLevel + switch r.Level { + case slog.LevelDebug, slog.LevelInfo: + apiLevel = opencode.AppLogParamsLevelInfo + case slog.LevelWarn: + apiLevel = opencode.AppLogParamsLevelWarn + case slog.LevelError: + apiLevel = opencode.AppLogParamsLevelError + default: + apiLevel = opencode.AppLogParamsLevelInfo + } + + // Build extra fields + extra := make(map[string]any) + + // Add handler attributes + h.mu.Lock() + for _, attr := range h.attrs { + extra[attr.Key] = attr.Value.Any() + } + h.mu.Unlock() + + // Add record attributes + r.Attrs(func(attr slog.Attr) bool { + extra[attr.Key] = attr.Value.Any() + return true + }) + + // Send log to API + params := opencode.AppLogParams{ + Service: opencode.F(h.service), + Level: opencode.F(apiLevel), + Message: opencode.F(r.Message), + } + + if len(extra) > 0 { + params.Extra = opencode.F(extra) + } + + // Use a goroutine to avoid blocking the logger + go func() { + _, err := h.client.App.Log(context.Background(), params) + if err != nil { + // Fallback: we can't log the error using slog as it would create a loop + // TODO: fallback file? + } + }() + + return nil +} + +// WithAttrs returns a new Handler whose attributes consist of +// both the receiver's attributes and the arguments. +func (h *APILogHandler) WithAttrs(attrs []slog.Attr) slog.Handler { + h.mu.Lock() + defer h.mu.Unlock() + + newHandler := &APILogHandler{ + client: h.client, + service: h.service, + level: h.level, + attrs: make([]slog.Attr, len(h.attrs)+len(attrs)), + groups: make([]string, len(h.groups)), + } + + copy(newHandler.attrs, h.attrs) + copy(newHandler.attrs[len(h.attrs):], attrs) + copy(newHandler.groups, h.groups) + + return newHandler +} + +// WithGroup returns a new Handler with the given group appended to +// the receiver's existing groups. +func (h *APILogHandler) WithGroup(name string) slog.Handler { + h.mu.Lock() + defer h.mu.Unlock() + + newHandler := &APILogHandler{ + client: h.client, + service: h.service, + level: h.level, + attrs: make([]slog.Attr, len(h.attrs)), + groups: make([]string, len(h.groups)+1), + } + + copy(newHandler.attrs, h.attrs) + copy(newHandler.groups, h.groups) + newHandler.groups[len(h.groups)] = name + + return newHandler +} |
