summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2025-08-16 15:58:40 +0300
committerPaul Buetow <paul@buetow.org>2025-08-16 15:58:40 +0300
commit02cc0e3ac6c08f422f11b668c729102fcf0c7f38 (patch)
tree3910b94e08239c3a7f0a47cdf7f092c7de58008d
parent2caaae5863c2fd31803a6d944ced4b8b0a7b5e36 (diff)
logging: add -log-preview-limit flag with HEXAI_LOG_PREVIEW_LIMIT env; wire through llm.SetLogPreviewLimit; document in README
-rw-r--r--README.md1
-rw-r--r--internal/llm/openai.go8
-rw-r--r--internal/llm/provider.go36
3 files changed, 30 insertions, 15 deletions
diff --git a/README.md b/README.md
index a671729..ea6a670 100644
--- a/README.md
+++ b/README.md
@@ -46,3 +46,4 @@ Notes:
| `-context-mode` | `file-on-new-func` | `HEXAI_CONTEXT_MODE` | `minimal` `window` `file-on-new-func` `always-full` |
| `-context-window-lines` | `120` | `HEXAI_CONTEXT_WINDOW_LINES` | Lines around cursor when using `window` mode. |
| `-max-context-tokens` | `2000` | `HEXAI_MAX_CONTEXT_TOKENS` | Token budget for additional context. |
+| `-log-preview-limit` | `0` (unlimited) | `HEXAI_LOG_PREVIEW_LIMIT` | Limit characters shown in LLM preview logs. |
diff --git a/internal/llm/openai.go b/internal/llm/openai.go
index 45cb1b8..7cfabc1 100644
--- a/internal/llm/openai.go
+++ b/internal/llm/openai.go
@@ -95,8 +95,8 @@ func (c *openAIClient) Chat(ctx context.Context, messages []Message, opts ...Req
start := time.Now()
c.logf("chat start model=%s temp=%.2f max_tokens=%d stop=%d messages=%d", o.Model, o.Temperature, o.MaxTokens, len(o.Stop), len(messages))
for i, m := range messages {
- // Sending context (cyan) — log full content with real newlines
- c.logf("msg[%d] role=%s size=%d preview=%s%s%s", i, m.Role, len(m.Content), ansiCyan, m.Content, ansiNormal)
+ // Sending context (cyan)
+ c.logf("msg[%d] role=%s size=%d preview=%s%s%s", i, m.Role, len(m.Content), ansiCyan, previewForLog(m.Content), ansiNormal)
}
req := oaChatRequest{Model: o.Model}
req.Messages = make([]oaMessage, len(messages))
@@ -154,8 +154,8 @@ func (c *openAIClient) Chat(ctx context.Context, messages []Message, opts ...Req
return "", errors.New("openai: no choices returned")
}
content := out.Choices[0].Message.Content
- // Received context (green) — log full content with real newlines
- c.logf("success choice=0 finish=%s size=%d preview=%s%s%s duration=%s", out.Choices[0].FinishReason, len(content), ansiGreen, content, ansiNormal, time.Since(start))
+ // Received context (green)
+ c.logf("success choice=0 finish=%s size=%d preview=%s%s%s duration=%s", out.Choices[0].FinishReason, len(content), ansiGreen, previewForLog(content), ansiNormal, time.Since(start))
return content, nil
}
diff --git a/internal/llm/provider.go b/internal/llm/provider.go
index fd9d4d3..a80b1c1 100644
--- a/internal/llm/provider.go
+++ b/internal/llm/provider.go
@@ -1,10 +1,10 @@
package llm
import (
- "context"
- "errors"
- "log"
- "os"
+ "context"
+ "errors"
+ "log"
+ "os"
)
// Message represents a chat-style prompt message.
@@ -16,8 +16,8 @@ type Message struct {
// Client is a minimal LLM provider interface.
// Future providers (Ollama, etc.) should implement this.
type Client interface {
- // Chat sends chat messages and returns the assistant text.
- Chat(ctx context.Context, messages []Message, opts ...RequestOption) (string, error)
+ // Chat sends chat messages and returns the assistant text.
+ Chat(ctx context.Context, messages []Message, opts ...RequestOption) (string, error)
}
// Options for a request. Providers may ignore unsupported fields.
@@ -41,9 +41,23 @@ func WithStop(stop ...string) RequestOption {
// NewDefault returns the default provider using environment configuration.
// Currently this is the OpenAI provider using OPENAI_API_KEY.
func NewDefault(logger *log.Logger) (Client, error) {
- apiKey := os.Getenv("OPENAI_API_KEY")
- if apiKey == "" {
- return nil, errors.New("OPENAI_API_KEY is not set")
- }
- return newOpenAIFromEnv(apiKey, logger), nil
+ apiKey := os.Getenv("OPENAI_API_KEY")
+ if apiKey == "" {
+ return nil, errors.New("OPENAI_API_KEY is not set")
+ }
+ return newOpenAIFromEnv(apiKey, logger), nil
+}
+
+// Logging configuration for previews
+var logPreviewLimit int // 0 means unlimited
+
+// SetLogPreviewLimit sets the maximum number of characters to log for
+// request/response previews. Set to 0 for unlimited.
+func SetLogPreviewLimit(n int) { logPreviewLimit = n }
+
+func previewForLog(s string) string {
+ if logPreviewLimit > 0 {
+ return trimPreview(s, logPreviewLimit)
+ }
+ return s
}