mirror of
https://github.com/mark3labs/kit.git
synced 2026-06-13 19:20:06 +00:00
refactor(models): decouple TUI progress from SDK dependency tree
- Remove direct internal/ui/progress import from internal/models/providers.go - Add ProgressReaderFunc callback to ProviderConfig for dependency inversion - Wire Bubble Tea progress reader via CLIOptions in cmd/root.go - Add NewProgressReadCloser convenience wrapper in progress package - SDK consumers (pkg/kit) no longer transitively pull bubbletea, lipgloss v2, or bubbles - Update embedded_models.json from models.dev (110 providers, 4172 models)
This commit is contained in:
+6
-4
@@ -19,6 +19,7 @@ import (
|
||||
"github.com/mark3labs/kit/internal/prompts"
|
||||
"github.com/mark3labs/kit/internal/ui"
|
||||
"github.com/mark3labs/kit/internal/ui/commands"
|
||||
"github.com/mark3labs/kit/internal/ui/progress"
|
||||
"github.com/mark3labs/kit/internal/watcher"
|
||||
kit "github.com/mark3labs/kit/pkg/kit"
|
||||
"github.com/spf13/cobra"
|
||||
@@ -753,10 +754,11 @@ func runNormalMode(ctx context.Context) error {
|
||||
}
|
||||
},
|
||||
CLI: &kit.CLIOptions{
|
||||
MCPConfig: mcpConfig,
|
||||
ShowSpinner: true,
|
||||
SpinnerFunc: spinnerFunc,
|
||||
UseBufferedLogger: true,
|
||||
MCPConfig: mcpConfig,
|
||||
ShowSpinner: true,
|
||||
SpinnerFunc: spinnerFunc,
|
||||
UseBufferedLogger: true,
|
||||
ProgressReaderFunc: progress.NewProgressReadCloser,
|
||||
},
|
||||
}
|
||||
if resumeFlag {
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -25,7 +25,6 @@ import (
|
||||
openaisdk "github.com/charmbracelet/openai-go"
|
||||
|
||||
"github.com/mark3labs/kit/internal/auth"
|
||||
"github.com/mark3labs/kit/internal/ui/progress"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -159,6 +158,12 @@ type ProviderConfig struct {
|
||||
TLSSkipVerify bool
|
||||
ThinkingLevel ThinkingLevel
|
||||
DisableCaching bool // Opt-out: set to true to disable automatic prompt caching
|
||||
|
||||
// ProgressReaderFunc, when set, wraps an io.Reader with progress display
|
||||
// for long operations like Ollama model pulls. The returned io.ReadCloser
|
||||
// must be closed when done. When nil, the raw reader is consumed directly
|
||||
// with no progress UI.
|
||||
ProgressReaderFunc func(io.Reader) io.ReadCloser
|
||||
}
|
||||
|
||||
// ProviderResult contains the result of provider creation.
|
||||
@@ -1128,7 +1133,7 @@ func loadOllamaModelWithFallback(ctx context.Context, baseURL, modelName string,
|
||||
// Phase 1: Check if model exists locally
|
||||
if err := checkOllamaModelExists(client, baseURL, modelName); err != nil {
|
||||
// Phase 2: Pull model if not found
|
||||
if err := pullOllamaModel(ctx, client, baseURL, modelName); err != nil {
|
||||
if err := pullOllamaModel(ctx, client, baseURL, modelName, config.ProgressReaderFunc); err != nil {
|
||||
return nil, fmt.Errorf("failed to pull model %s: %v", modelName, err)
|
||||
}
|
||||
}
|
||||
@@ -1217,11 +1222,7 @@ func checkOllamaModelExists(client *http.Client, baseURL, modelName string) erro
|
||||
return nil
|
||||
}
|
||||
|
||||
func pullOllamaModel(ctx context.Context, client *http.Client, baseURL, modelName string) error {
|
||||
return pullOllamaModelWithProgress(ctx, client, baseURL, modelName, true)
|
||||
}
|
||||
|
||||
func pullOllamaModelWithProgress(ctx context.Context, client *http.Client, baseURL, modelName string, showProgress bool) error {
|
||||
func pullOllamaModel(ctx context.Context, client *http.Client, baseURL, modelName string, progressFn func(io.Reader) io.ReadCloser) error {
|
||||
reqBody := map[string]string{"name": modelName}
|
||||
jsonBody, _ := json.Marshal(reqBody)
|
||||
|
||||
@@ -1245,10 +1246,10 @@ func pullOllamaModelWithProgress(ctx context.Context, client *http.Client, baseU
|
||||
return fmt.Errorf("failed to pull model (status %d): %s", resp.StatusCode, string(body))
|
||||
}
|
||||
|
||||
if showProgress {
|
||||
progressReader := progress.NewProgressReader(resp.Body)
|
||||
defer func() { _ = progressReader.Close() }()
|
||||
_, err = io.ReadAll(progressReader)
|
||||
if progressFn != nil {
|
||||
pr := progressFn(resp.Body)
|
||||
defer func() { _ = pr.Close() }()
|
||||
_, err = io.ReadAll(pr)
|
||||
} else {
|
||||
_, err = io.ReadAll(resp.Body)
|
||||
}
|
||||
|
||||
@@ -288,3 +288,9 @@ func (pr *ProgressReader) Close() error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewProgressReadCloser is a convenience wrapper around NewProgressReader that
|
||||
// returns an io.ReadCloser, suitable for use as a ProgressReaderFunc callback.
|
||||
func NewProgressReadCloser(r io.Reader) io.ReadCloser {
|
||||
return NewProgressReader(r)
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -684,6 +685,11 @@ type CLIOptions struct {
|
||||
SpinnerFunc SpinnerFunc
|
||||
// UseBufferedLogger buffers debug messages for later display.
|
||||
UseBufferedLogger bool
|
||||
// ProgressReaderFunc wraps an io.Reader with a progress display for
|
||||
// long-running operations such as Ollama model pulls. The returned
|
||||
// io.ReadCloser must be closed when done. When nil, progress is not
|
||||
// displayed.
|
||||
ProgressReaderFunc func(io.Reader) io.ReadCloser
|
||||
}
|
||||
|
||||
// InitTreeSession creates or opens a tree session based on the given options.
|
||||
@@ -953,6 +959,9 @@ func New(ctx context.Context, opts *Options) (*Kit, error) {
|
||||
setupOpts.ShowSpinner = opts.CLI.ShowSpinner
|
||||
setupOpts.SpinnerFunc = opts.CLI.SpinnerFunc
|
||||
setupOpts.UseBufferedLogger = opts.CLI.UseBufferedLogger
|
||||
if opts.CLI.ProgressReaderFunc != nil {
|
||||
providerConfig.ProgressReaderFunc = opts.CLI.ProgressReaderFunc
|
||||
}
|
||||
}
|
||||
|
||||
// Create agent using shared setup with the hook tool wrapper.
|
||||
|
||||
Reference in New Issue
Block a user