Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -691,10 +691,10 @@ host, err := kit.NewAgent(ctx,

Available options: `WithModel`, `WithSystemPrompt`, `WithStreaming`,
`WithMaxTokens`, `WithThinkingLevel`, `WithTools`, `WithExtraTools`,
`WithProviderAPIKey`, `WithProviderURL`, `WithConfigFile`, `WithDebug`, and
`Ephemeral`. For advanced configuration not covered by the helpers (custom MCP
config, in-process MCP servers, session backends, MCP task tuning) construct an
`Options` value explicitly and call `kit.New`.
`WithProviderAPIKey`, `WithProviderURL`, `WithConfigFile`, `WithDebug`,
`WithDebugLogger`, and `Ephemeral`. For advanced configuration not covered by
the helpers (custom MCP config, in-process MCP servers, session backends, MCP
task tuning) construct an `Options` value explicitly and call `kit.New`.

### Per-instance config isolation

Expand Down
12 changes: 11 additions & 1 deletion internal/kitsetup/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ type AgentSetupOptions struct {
// Debug enables debug logging. When zero-value, viper is consulted.
// Only meaningful when ProviderConfig is also set.
Debug bool
// DebugLogger, if non-nil, is used directly as the engine/MCP debug
// logger — overriding the built-in SimpleDebugLogger / BufferedDebugLogger
// selected by Debug + UseBufferedLogger. Callers supply this when they
// want to route debug output into their own logging system.
DebugLogger tools.DebugLogger
// NoExtensions skips extension loading. When false, viper is consulted.
// Only meaningful when ProviderConfig is also set.
NoExtensions bool
Expand Down Expand Up @@ -192,7 +197,12 @@ func SetupAgent(ctx context.Context, opts AgentSetupOptions) (*AgentSetupResult,
// Create the appropriate debug logger.
var debugLogger tools.DebugLogger
var bufferedLogger *tools.BufferedDebugLogger
if debugEnabled {
switch {
case opts.DebugLogger != nil:
// Caller-supplied logger wins unconditionally. Its IsDebugEnabled()
// is the source of truth for whether downstream code emits messages.
debugLogger = opts.DebugLogger
case debugEnabled:
if opts.UseBufferedLogger {
bufferedLogger = tools.NewBufferedDebugLogger(true)
debugLogger = bufferedLogger
Expand Down
7 changes: 4 additions & 3 deletions pkg/kit/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ host, err := kit.NewAgent(ctx,

Helpers: `WithModel`, `WithSystemPrompt`, `WithStreaming`, `WithMaxTokens`,
`WithThinkingLevel`, `WithTools`, `WithExtraTools`, `WithProviderAPIKey`,
`WithProviderURL`, `WithConfigFile`, `WithDebug`, and `Ephemeral`. `Option` is
`WithProviderURL`, `WithConfigFile`, `WithDebug`, `WithDebugLogger`, and
`Ephemeral`. `Option` is
a plain `func(*Options)`, so you can define your own. For fields without a
`With*` helper (`MCPConfig`, `InProcessMCPServers`, `SessionManager`, MCP task
tuning) construct an `Options` value and call `kit.New`.
Expand Down Expand Up @@ -329,7 +330,6 @@ kit.LLMFilePart // {Filename, Data []byte, MediaType}
// Agent configuration — concrete Kit-owned structs and function types.
// All fields use SDK types (e.g. `[]kit.Tool`), so consumers can construct
// these without importing any LLM-provider package.
kit.AgentConfig // Lower-level agent config — prefer Options unless you need direct control
kit.DebugLogger // Interface: LogDebug(string) / IsDebugEnabled() bool
kit.MCPTaskConfig // Task-aware MCP tools/call config (modes, polling, progress)
kit.ToolCallHandler // func(toolCallID, toolName, toolArgs string)
Expand Down Expand Up @@ -403,7 +403,8 @@ Key `Options` fields for SDK usage:
| `SessionPath` | Open specific session file |
| `Continue` | Resume most recent session |
| `InProcessMCPServers` | Map of name → `*kit.MCPServer` for in-process MCP servers |
| `Debug` | Enable debug logging |
| `Debug` | Enable debug logging via the built-in console logger (ignored when `DebugLogger` is set) |
| `DebugLogger` | Custom `DebugLogger` implementation — routes engine + MCP debug output into your own logging system |

## Environment Variables

Expand Down
208 changes: 0 additions & 208 deletions pkg/kit/agent_config_internal_test.go

This file was deleted.

19 changes: 18 additions & 1 deletion pkg/kit/kit.go
Original file line number Diff line number Diff line change
Expand Up @@ -1047,9 +1047,25 @@ type Options struct {
AutoCompact bool // Auto-compact when near context limit
CompactionOptions *CompactionOptions // Config for auto-compaction (nil = defaults)

// Debug enables debug logging for the SDK.
// Debug enables debug logging for the SDK. When DebugLogger is nil this
// flag selects between the default no-op SimpleDebugLogger (Debug=false)
// and the built-in console/buffered logger (Debug=true). When DebugLogger
// is non-nil this flag is ignored — the supplied logger's
// IsDebugEnabled() controls whether downstream code emits messages.
Debug bool

// DebugLogger, if non-nil, routes low-level debug output from the engine
// and the MCP tool plumbing to a caller-supplied implementation. This is
// the SDK escape hatch for embedders that want to forward debug output
// into their own logging system (zap, slog, log/charm, an in-app TUI
// panel, etc.) instead of the built-in console logger.
//
// When nil (default) the Debug bool controls whether the built-in logger
// is installed. When non-nil this logger is used unconditionally and the
// Debug bool is ignored; the supplied logger's IsDebugEnabled() reports
// whether downstream code should bother formatting messages.
DebugLogger DebugLogger

// MCPAuthHandler handles OAuth authorization for remote MCP servers.
// When set, remote transports (streamable HTTP, SSE) are configured
// with OAuth support. If the server returns a 401, the handler is
Expand Down Expand Up @@ -1514,6 +1530,7 @@ func New(ctx context.Context, opts *Options) (*Kit, error) {
ToolWrapper: hookToolWrapper(beforeToolCall, afterToolResult),
ProviderConfig: providerConfig,
Debug: debug,
DebugLogger: opts.DebugLogger,
NoExtensions: noExtensions,
MaxSteps: maxSteps,
StreamingEnabled: streaming,
Expand Down
38 changes: 5 additions & 33 deletions pkg/kit/mcp_tasks.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,11 @@ type MCPTaskProgressHandler func(MCPTaskProgress)
// are optional; the zero value disables progress callbacks and applies
// sensible polling defaults inside the engine.
//
// For most consumers, the flat [Options] fields (`MCPTaskMode`,
// `MCPTaskTTL`, `MCPTaskPollInterval`, `MCPTaskMaxPollInterval`,
// `MCPTaskTimeout`, `MCPTaskProgress`) are the preferred entry point.
// MCPTaskConfig is exposed for the low-level [AgentConfig] path.
// Most consumers configure these via the flat [Options] fields
// (`MCPTaskMode`, `MCPTaskTTL`, `MCPTaskPollInterval`,
// `MCPTaskMaxPollInterval`, `MCPTaskTimeout`, `MCPTaskProgress`). The
// MCPTaskConfig type itself is retained for downstream consumers that
// receive it on engine-facing call sites.
type MCPTaskConfig struct {
// PerServerMode overrides the per-server task mode resolved from
// [MCPServerConfig]. Keys are server names. Missing entries fall back
Expand Down Expand Up @@ -133,35 +134,6 @@ type MCPTaskConfig struct {
Progress MCPTaskProgressHandler
}

// toToolsConfig converts the SDK-level [MCPTaskConfig] to the internal
// tools-package representation. Keeps the dependency arrow internal-only.
func (c MCPTaskConfig) toToolsConfig() tools.MCPTaskConfig {
cfg := tools.MCPTaskConfig{
DefaultTTL: c.DefaultTTL,
PollInterval: c.PollInterval,
MaxPollInterval: c.MaxPollInterval,
Timeout: c.Timeout,
}
if len(c.PerServerMode) > 0 {
cfg.PerServerMode = make(map[string]tools.MCPTaskMode, len(c.PerServerMode))
for k, v := range c.PerServerMode {
cfg.PerServerMode[k] = tools.MCPTaskMode(v)
}
}
if c.Progress != nil {
h := c.Progress
cfg.Progress = func(p tools.MCPTaskProgress) {
h(MCPTaskProgress{
Server: p.Server,
TaskID: p.TaskID,
Status: MCPTaskStatus(p.Status),
Message: p.Message,
})
}
}
return cfg
}

// mcpTaskOptions carries SDK consumer configuration into the agent setup.
// Stored on Options as a single value so the public surface stays compact;
// individual fields are exposed via WithMCP* builder functions.
Expand Down
11 changes: 11 additions & 0 deletions pkg/kit/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,17 @@ func WithConfigFile(path string) Option { return func(o *Options) { o.ConfigFile
// WithDebug enables SDK debug logging.
func WithDebug() Option { return func(o *Options) { o.Debug = true } }

// WithDebugLogger installs a caller-supplied [DebugLogger] for low-level
// engine and MCP tool plumbing output. When set this overrides the built-in
// logger selected by [WithDebug] — messages flow into the supplied logger
// unconditionally, and the logger's IsDebugEnabled reports whether downstream
// code should bother formatting them. Use this to forward Kit's debug output
// into your application's logging system (slog, zap, charm/log, an in-app
// panel, etc.).
func WithDebugLogger(l DebugLogger) Option {
return func(o *Options) { o.DebugLogger = l }
}

// Ephemeral configures an in-memory session with no persistence (equivalent to
// Options.NoSession = true).
func Ephemeral() Option { return func(o *Options) { o.NoSession = true } }
Loading
Loading