Skip to content

feat(sdk): add Options.DebugLogger and WithDebugLogger option#66

Closed
ezynda3 wants to merge 1 commit into
masterfrom
feat/sdk-with-debug-logger
Closed

feat(sdk): add Options.DebugLogger and WithDebugLogger option#66
ezynda3 wants to merge 1 commit into
masterfrom
feat/sdk-with-debug-logger

Conversation

@ezynda3

@ezynda3 ezynda3 commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Summary

The SDK exposes a DebugLogger interface (pkg/kit/types.go) but no public path to install one. The only consumer of the field is the unexported kit.AgentConfig.toInternal() method, which itself is not reachable from outside the package. Embedders that want to forward Kit's low-level engine + MCP debug output into their own logging system (slog, zap, charm/log, an in-app TUI panel, etc.) currently have no option but the on/off Debug bool, which always installs the built-in SimpleDebugLogger / BufferedDebugLogger.

This PR closes that gap on the supported Options / functional-option construction path.

Changes

  • pkg/kit/kit.go: add Options.DebugLogger DebugLogger. When non-nil it is used directly and the Debug bool is ignored; the supplied logger's IsDebugEnabled() controls whether downstream code emits messages.
  • pkg/kit/options.go: add WithDebugLogger(l DebugLogger) Option.
  • internal/kitsetup/setup.go: add AgentSetupOptions.DebugLogger and switch SetupAgent's logger selection so the caller-supplied logger wins unconditionally; otherwise the existing Debug + UseBufferedLogger branch picks the built-in implementation. No behaviour change when DebugLogger is nil.
  • pkg/kit/kit.go: wire opts.DebugLogger into setupOpts so the New() path threads it through.
  • pkg/kit/viper_isolation_test.go: add TestWithDebugLoggerPlumbing and TestWithDebugLoggerNilClears covering the option-to-field contract and later-options-override semantics consistent with the other With* helpers.
  • pkg/kit/README.md: list WithDebugLogger in the helper inventory.

Usage

type myLogger struct{ /* slog/zap/charm-log wrapper */ }

func (l *myLogger) LogDebug(msg string)    { /* forward */ }
func (l *myLogger) IsDebugEnabled() bool   { return true }

k, err := kit.NewAgent(ctx,
    kit.WithModel("anthropic/claude-sonnet-4-5-20250929"),
    kit.WithDebugLogger(&myLogger{}),
)

Notes

  • kit.DebugLogger and tools.DebugLogger are structurally identical (LogDebug(string) / IsDebugEnabled() bool), so the SDK value flows into the internal field without a conversion.
  • This is purely additive on the SDK surface and does not touch kit.AgentConfig — that field already carried a DebugLogger, but the AgentConfig path is unreachable from outside the package today.
  • A discussion thread suggested removing the unreachable kit.AgentConfig entirely; this PR is intentionally scoped to the "keep DebugLogger, add the missing wiring" option only. Removal of AgentConfig (if desired) belongs in a separate change.

Verification

  • go build ./pkg/... ./internal/... ./cmd/... — clean
  • go vet ./... — clean (modulo the pre-existing examples/extensions Yaegi source not being a main package)
  • go test -race ./pkg/kit/... ./internal/kitsetup/... ./internal/agent/... ./internal/tools/... — passing

Summary by CodeRabbit

Release Notes

  • New Features
    • Introduced WithDebugLogger option to supply custom debug logger implementations, allowing users to route and control debug output
    • Custom-supplied loggers override built-in debug logging when configured, providing full control over debug output handling
    • Debug state reporting now determined by the configured logger instance

Today the SDK exposes a DebugLogger interface (pkg/kit/types.go) but no
public path to install one — the only consumer of the field is the
unexported kit.AgentConfig.toInternal() method, which itself is not
reachable from outside the package. As a result, embedders that want to
forward Kit's low-level engine + MCP tool plumbing debug output into
their own logging system (slog, zap, charm/log, an in-app TUI panel,
etc.) have no option but the on/off Debug bool, which always installs
the built-in SimpleDebugLogger / BufferedDebugLogger.

This change closes that gap on the supported Options / functional-option
construction path:

- pkg/kit/kit.go: add Options.DebugLogger DebugLogger. When non-nil it
  is used directly and the Debug bool is ignored; the supplied logger's
  IsDebugEnabled() controls whether downstream code emits messages.
- pkg/kit/options.go: add WithDebugLogger(l DebugLogger) Option.
- internal/kitsetup/setup.go: add AgentSetupOptions.DebugLogger and
  switch SetupAgent's logger selection so the caller-supplied logger
  wins unconditionally; otherwise the existing Debug + UseBufferedLogger
  branch picks the built-in implementation. No behaviour change when
  DebugLogger is nil.
- pkg/kit/kit.go: wire opts.DebugLogger into setupOpts so the New()
  path threads it through.
- pkg/kit/viper_isolation_test.go: add TestWithDebugLoggerPlumbing and
  TestWithDebugLoggerNilClears covering the option-to-field contract
  and later-options-override semantics consistent with the other With*
  helpers.
- pkg/kit/README.md: list WithDebugLogger in the helper inventory.

Notes:
- kit.DebugLogger and tools.DebugLogger are structurally identical
  (LogDebug(string) / IsDebugEnabled() bool), so the SDK value flows
  into the internal field without a conversion.
- This is purely additive on the SDK surface and does not touch
  kit.AgentConfig — that field already carried a DebugLogger, but the
  AgentConfig path is unreachable from outside the package today.
@mark-iii-labs-huly

Copy link
Copy Markdown

Connected to Huly®: KIT-67

@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f9f4bda5-07b6-43c2-877d-543805275db8

📥 Commits

Reviewing files that changed from the base of the PR and between 888c6c7 and dddf10b.

📒 Files selected for processing (5)
  • internal/kitsetup/setup.go
  • pkg/kit/README.md
  • pkg/kit/kit.go
  • pkg/kit/options.go
  • pkg/kit/viper_isolation_test.go

📝 Walkthrough

Walkthrough

Adds a WithDebugLogger functional option to the kit package that accepts a DebugLogger and stores it on Options.DebugLogger. This field propagates through New() into AgentSetupOptions.DebugLogger, where SetupAgent now uses a switch to prefer the caller-supplied logger over the built-in debug/buffered logger selection.

Changes

WithDebugLogger Custom Debug Logger

Layer / File(s) Summary
DebugLogger contract, option, and wiring
pkg/kit/kit.go, internal/kitsetup/setup.go, pkg/kit/options.go
Adds DebugLogger field to Options with precedence docs, adds DebugLogger field to AgentSetupOptions, implements WithDebugLogger functional option, wires opts.DebugLogger into setupOpts.DebugLogger in New(), and changes SetupAgent logger initialization to a switch that uses the caller-supplied logger when non-nil.
Tests and README
pkg/kit/viper_isolation_test.go, pkg/kit/README.md
Adds recordingDebugLogger test helper, TestWithDebugLoggerPlumbing, TestWithDebugLoggerNilClears, and updates the README functional options list to include WithDebugLogger.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

A new field appears, a logger to pass,
No more hard-coded paths through the grass.
WithDebugLogger hops onto the stack,
Your custom log lines come hopping right back.
🐇 The rabbit approves — now debug in style!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely describes the main change: adding a DebugLogger field and WithDebugLogger option to the SDK's Options struct, which is the core feature implemented across all modified files.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/sdk-with-debug-logger

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@ezynda3

ezynda3 commented Jun 18, 2026

Copy link
Copy Markdown
Contributor Author

Closing in favour of #67, which bundles this additive WithDebugLogger wiring with the actual kit.AgentConfig removal. They're tightly coupled (the wiring exists precisely to make the removal lossless) so reviewers benefit from seeing them together.

@ezynda3 ezynda3 closed this Jun 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant