refactor: remove fantasy dependency name leaks from SDK surface

- Rename ExtensionToolsAsFantasy -> ExtensionToolsAsLLMTools
- Rename convertKitMessagesToFantasy -> convertToLLMMessages
- Delete GetFantasyProviders, ToFantasyMessages, FromFantasyMessage
- Replace direct fantasy type usage with kit.LLM* aliases in app tests
- Scrub fantasy references from godoc comments across pkg/kit and internal
This commit is contained in:
Ed Zynda
2026-04-15 12:24:52 +03:00
parent e068487ff7
commit 26c9f009f9
13 changed files with 40 additions and 66 deletions
+3 -6
View File
@@ -3,24 +3,21 @@ package app
import (
"testing"
"charm.land/fantasy"
kit "github.com/mark3labs/kit/pkg/kit"
)
// makeTextMsg builds a minimal kit.LLMMessage using fantasy.NewUserMessage
// or constructing with the given role.
// makeTextMsg builds a minimal kit.LLMMessage with the given role and text.
func makeTextMsg(role, text string) kit.LLMMessage {
return kit.LLMMessage{
Role: kit.LLMMessageRole(role),
Content: []fantasy.MessagePart{fantasy.TextPart{Text: text}},
Content: []kit.LLMMessagePart{kit.LLMTextPart{Text: text}},
}
}
// textOf extracts the plain text from an LLMMessage for assertions.
func textOf(msg kit.LLMMessage) string {
for _, part := range msg.Content {
if tp, ok := part.(fantasy.TextPart); ok {
if tp, ok := part.(kit.LLMTextPart); ok {
return tp.Text
}
}
+1 -1
View File
@@ -918,7 +918,7 @@ type ExtensionEntry struct {
type ContextMessage struct {
// Index is the position of this message in the original context array
// (0-based). When returning messages from a ContextPrepareResult,
// messages with Index >= 0 reuse the original fantasy.Message at that
// messages with Index >= 0 reuse the original LLM message at that
// position (preserving tool calls, reasoning, and other complex parts).
// Set Index to -1 for newly injected messages (created from Role + Content).
Index int
+5 -5
View File
@@ -28,11 +28,11 @@ func WrapToolsWithExtensions(tools []fantasy.AgentTool, runner *Runner) []fantas
return wrapped
}
// ExtensionToolsAsFantasy converts ToolDef values registered by extensions
// into fantasy.AgentTool implementations so the LLM can invoke them.
// ExtensionToolsAsLLMTools converts ToolDef values registered by extensions
// into LLM agent tool implementations so the LLM can invoke them.
// The runner is optional; if provided, ToolContext.OnProgress routes
// progress messages through the runner's Print function.
func ExtensionToolsAsFantasy(defs []ToolDef, runner *Runner) []fantasy.AgentTool {
func ExtensionToolsAsLLMTools(defs []ToolDef, runner *Runner) []fantasy.AgentTool {
tools := make([]fantasy.AgentTool, 0, len(defs))
for _, def := range defs {
tools = append(tools, &extensionTool{def: def, runner: runner})
@@ -154,7 +154,7 @@ func (w *wrappedTool) Run(ctx context.Context, call fantasy.ToolCall) (fantasy.T
}
// ---------------------------------------------------------------------------
// extensionTool — wraps a ToolDef into a fantasy.AgentTool
// extensionTool — wraps a ToolDef into an LLM agent tool
// ---------------------------------------------------------------------------
type extensionTool struct {
@@ -182,7 +182,7 @@ func (t *extensionTool) Info() fantasy.ToolInfo {
info.Parameters = props
} else {
// Schema doesn't have "properties" — use as-is (may be
// a flat property map already matching fantasy's format).
// a flat property map already matching the expected format).
info.Parameters = schema
}
// Extract required fields if present.
+8 -8
View File
@@ -192,7 +192,7 @@ func TestWrappedTool_ExecutionStartEnd(t *testing.T) {
}
}
func TestExtensionToolsAsFantasy(t *testing.T) {
func TestExtensionToolsAsLLMTools(t *testing.T) {
defs := []ToolDef{
{
Name: "greet",
@@ -202,7 +202,7 @@ func TestExtensionToolsAsFantasy(t *testing.T) {
},
}
tools := ExtensionToolsAsFantasy(defs, nil)
tools := ExtensionToolsAsLLMTools(defs, nil)
if len(tools) != 1 {
t.Fatalf("expected 1 tool, got %d", len(tools))
}
@@ -232,7 +232,7 @@ func TestExtensionTool_Error(t *testing.T) {
},
}
tools := ExtensionToolsAsFantasy(defs, nil)
tools := ExtensionToolsAsLLMTools(defs, nil)
resp, err := tools[0].Run(context.Background(), fantasy.ToolCall{Input: "x"})
if err == nil {
t.Error("expected error")
@@ -259,7 +259,7 @@ func TestExtensionTool_ExecuteWithContext(t *testing.T) {
}
// Without runner, OnProgress is a no-op.
tools := ExtensionToolsAsFantasy(defs, nil)
tools := ExtensionToolsAsLLMTools(defs, nil)
resp, err := tools[0].Run(context.Background(), fantasy.ToolCall{Input: "test"})
if err != nil {
t.Fatalf("unexpected error: %v", err)
@@ -285,7 +285,7 @@ func TestExtensionTool_ExecuteWithContext(t *testing.T) {
},
},
}
tools2 := ExtensionToolsAsFantasy(defs2, runner)
tools2 := ExtensionToolsAsLLMTools(defs2, runner)
_, err = tools2[0].Run(context.Background(), fantasy.ToolCall{Input: ""})
if err != nil {
t.Fatalf("unexpected error: %v", err)
@@ -306,7 +306,7 @@ func TestExtensionTool_ExecuteWithContextPriority(t *testing.T) {
},
},
}
tools := ExtensionToolsAsFantasy(defs, nil)
tools := ExtensionToolsAsLLMTools(defs, nil)
resp, err := tools[0].Run(context.Background(), fantasy.ToolCall{Input: ""})
if err != nil {
t.Fatalf("unexpected error: %v", err)
@@ -330,7 +330,7 @@ func TestExtensionTool_CancelledContext(t *testing.T) {
},
},
}
tools := ExtensionToolsAsFantasy(defs, nil)
tools := ExtensionToolsAsLLMTools(defs, nil)
_, _ = tools[0].Run(ctx, fantasy.ToolCall{Input: ""})
if !sawCancelled {
t.Error("expected IsCancelled=true for cancelled context")
@@ -339,7 +339,7 @@ func TestExtensionTool_CancelledContext(t *testing.T) {
func TestExtensionTool_ProviderOptions(t *testing.T) {
defs := []ToolDef{{Name: "test", Execute: func(string) (string, error) { return "", nil }}}
tools := ExtensionToolsAsFantasy(defs, nil)
tools := ExtensionToolsAsLLMTools(defs, nil)
// Initially nil.
opts := tools[0].ProviderOptions()
+1 -1
View File
@@ -267,7 +267,7 @@ func loadExtensions() (*extensions.Runner, extensionCreationOpts, error) {
return extensions.WrapToolsWithExtensions(tools, runner)
}
extTools := extensions.ExtensionToolsAsFantasy(runner.RegisteredTools(), runner)
extTools := extensions.ExtensionToolsAsLLMTools(runner.RegisteredTools(), runner)
return runner, extensionCreationOpts{
toolWrapper: wrapper,
-13
View File
@@ -325,12 +325,6 @@ func UnmarshalParts(data []byte) ([]ContentPart, error) {
// mixed TextPart and ToolCallPart content. Tool-role messages produce
// ToolResultPart entries.
func (m *Message) ToLLMMessages() []fantasy.Message {
return m.ToFantasyMessages()
}
// Deprecated: Use ToLLMMessages instead.
// ToFantasyMessages converts a Message to one or more LLM message values.
func (m *Message) ToFantasyMessages() []fantasy.Message {
switch m.Role {
case RoleAssistant:
var parts []fantasy.MessagePart
@@ -431,13 +425,6 @@ func (m *Message) ToFantasyMessages() []fantasy.Message {
// FromLLMMessage converts an LLM message into our Message type,
// extracting all content parts into the appropriate block types.
func FromLLMMessage(msg fantasy.Message) Message {
return FromFantasyMessage(msg)
}
// Deprecated: Use FromLLMMessage instead.
// FromFantasyMessage converts an LLM message into our Message type,
// extracting all content parts into the appropriate block types.
func FromFantasyMessage(msg fantasy.Message) Message {
m := Message{
Role: MessageRole(msg.Role),
Parts: make([]ContentPart, 0),
-5
View File
@@ -379,11 +379,6 @@ func (r *ModelsRegistry) GetLLMProviders() []string {
return providers
}
// Deprecated: Use GetLLMProviders instead.
func (r *ModelsRegistry) GetFantasyProviders() []string {
return r.GetLLMProviders()
}
// isProviderLLMSupported checks if a provider can be used with the LLM layer.
func isProviderLLMSupported(providerID string, info *ProviderInfo) bool {
// Ollama and custom are always supported (model names are user-defined).
+5 -6
View File
@@ -22,13 +22,13 @@ func NewTreeManagerAdapter(tm *session.TreeManager) SessionManager {
// AppendMessage implements SessionManager.
func (a *treeManagerAdapter) AppendMessage(msg LLMMessage) (string, error) {
// LLMMessage is just an alias for fantasy.Message, so no conversion needed
// LLMMessage is a type alias, so no conversion needed.
return a.inner.AppendLLMMessage(msg)
}
// GetMessages implements SessionManager.
func (a *treeManagerAdapter) GetMessages() []LLMMessage {
// LLMMessage is just an alias for fantasy.Message
// LLMMessage is a type alias, so no conversion needed.
return a.inner.GetLLMMessages()
}
@@ -223,9 +223,8 @@ func (a *treeManagerAdapter) convertEntry(entry any) *BranchEntry {
}
}
// convertKitMessagesToFantasy converts kit LLM messages to fantasy messages.
// Since LLMMessage is an alias for fantasy.Message, this is a no-op.
func convertKitMessagesToFantasy(msgs []LLMMessage) []fantasy.Message {
// LLMMessage is just an alias for fantasy.Message, so we can type convert
// convertToLLMMessages converts kit LLM messages to the underlying provider
// message type. Since LLMMessage is a type alias, this is a no-op.
func convertToLLMMessages(msgs []LLMMessage) []fantasy.Message {
return msgs
}
+3 -3
View File
@@ -58,7 +58,7 @@ func (m *Kit) ShouldCompact() bool {
// Fall back to text-based heuristic before first turn completes.
messages := m.session.GetMessages()
return compaction.ShouldCompact(convertKitMessagesToFantasy(messages), info.Limit.Context, reserveTokens)
return compaction.ShouldCompact(convertToLLMMessages(messages), info.Limit.Context, reserveTokens)
}
// GetContextStats returns current context usage statistics including
@@ -203,9 +203,9 @@ func (m *Kit) compactInternal(ctx context.Context, opts *CompactionOptions, cust
// custom summary. It still determines the cut point and persists a
// CompactionEntry.
func (m *Kit) applyCustomCompaction(summary string, messages []LLMMessage, opts *CompactionOptions) (*CompactionResult, error) {
originalTokens := compaction.EstimateMessageTokens(convertKitMessagesToFantasy(messages))
originalTokens := compaction.EstimateMessageTokens(convertToLLMMessages(messages))
cutPoint := compaction.FindCutPoint(convertKitMessagesToFantasy(messages), opts.KeepRecentTokens)
cutPoint := compaction.FindCutPoint(convertToLLMMessages(messages), opts.KeepRecentTokens)
if cutPoint == 0 {
cutPoint = len(messages) - 1
if cutPoint < 1 {
+1 -1
View File
@@ -562,7 +562,7 @@ func (m *Kit) ReloadExtensions() error {
// Update extension tools on the agent so the LLM sees changes.
if m.agent != nil {
extTools := extensions.ExtensionToolsAsFantasy(m.extRunner.RegisteredTools(), m.extRunner)
extTools := extensions.ExtensionToolsAsLLMTools(m.extRunner.RegisteredTools(), m.extRunner)
m.agent.SetExtraTools(extTools)
}
-5
View File
@@ -22,11 +22,6 @@ func GetLLMProviders() []string {
return models.GetGlobalRegistry().GetLLMProviders()
}
// Deprecated: Use GetLLMProviders instead.
func GetFantasyProviders() []string {
return GetLLMProviders()
}
// GetModelsForProvider returns all known models for a provider.
func GetModelsForProvider(provider string) (map[string]ModelInfo, error) {
return models.GetGlobalRegistry().GetModelsForProvider(provider)
+6 -6
View File
@@ -129,9 +129,9 @@ type SpinnerFunc = agent.SpinnerFunc
// ==== LLM Types ====
//
// These are type aliases for the corresponding charm.land/fantasy types,
// giving them clean LLM-prefixed names without leaking the dependency name.
// SDK consumers can use these types without importing charm.land/fantasy directly.
// These are type aliases for the underlying LLM provider types, giving them
// clean LLM-prefixed names without leaking the dependency name. SDK consumers
// can use these types without importing the provider package directly.
// LLMMessage represents a message in an LLM conversation, carrying a role
// and a slice of typed content parts (text, tool calls, reasoning, etc.).
@@ -177,7 +177,7 @@ type LLMMessageRole = fantasy.MessageRole
// LLMFinishReason indicates why the LLM stopped generating.
type LLMFinishReason = fantasy.FinishReason
// LLM role constants mirror fantasy.MessageRole* values under clean LLM-prefixed names.
// LLM role constants mirror the provider's role values under clean LLM-prefixed names.
const (
// LLMRoleUser identifies a user message.
LLMRoleUser = fantasy.MessageRoleUser
@@ -190,11 +190,11 @@ const (
)
// NewLLMUserMessage constructs a user-role LLMMessage with optional file
// attachments. It is equivalent to fantasy.NewUserMessage.
// attachments.
var NewLLMUserMessage = fantasy.NewUserMessage
// NewLLMSystemMessage constructs a system-role LLMMessage from one or more
// prompt strings. It is equivalent to fantasy.NewSystemMessage.
// prompt strings.
var NewLLMSystemMessage = fantasy.NewSystemMessage
// ==== Compaction Types (internal/compaction/) ====
+7 -6
View File
@@ -77,8 +77,8 @@ func TestLLMRoleConstants(t *testing.T) {
}
}
// TestLLMMessageAlias verifies LLMMessage is a type alias for fantasy.Message
// and can be used interchangeably.
// TestLLMMessageAlias verifies LLMMessage is a type alias for the underlying
// LLM provider message type and can be used interchangeably.
func TestLLMMessageAlias(t *testing.T) {
// Construct an LLMMessage using alias types.
msg := kit.LLMMessage{
@@ -132,8 +132,8 @@ func TestNewLLMSystemMessage(t *testing.T) {
}
}
// TestLLMUsageAlias verifies LLMUsage is a type alias for fantasy.Usage
// and carries the correct fields.
// TestLLMUsageAlias verifies LLMUsage is a type alias for the underlying
// LLM provider usage type and carries the correct fields.
func TestLLMUsageAlias(t *testing.T) {
u := kit.LLMUsage{
InputTokens: 100,
@@ -150,7 +150,7 @@ func TestLLMUsageAlias(t *testing.T) {
t.Errorf("LLMUsage.TotalTokens = %d, want 150", u.TotalTokens)
}
// Verify JSON marshaling uses snake_case (inherited from fantasy.Usage tags).
// Verify JSON marshaling uses snake_case (inherited from the provider's tags).
data, err := json.Marshal(u)
if err != nil {
t.Fatalf("LLMUsage.MarshalJSON: %v", err)
@@ -165,7 +165,8 @@ func TestLLMUsageAlias(t *testing.T) {
}
}
// TestLLMFilePartAlias verifies LLMFilePart is a type alias for fantasy.FilePart.
// TestLLMFilePartAlias verifies LLMFilePart is a type alias for the underlying
// LLM provider file part type.
func TestLLMFilePartAlias(t *testing.T) {
fp := kit.LLMFilePart{
Filename: "screenshot.png",