diff --git a/.golangci.yml b/.golangci.yml index e0e8418e1..34fc8995b 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -12,6 +12,7 @@ linters: - depguard - dogsled - durationcheck + - embeddedstructfieldcheck - errcheck - errname - errorlint @@ -20,6 +21,7 @@ linters: - forbidigo - ginkgolinter - gocheckcompilerdirectives + - godoclint - gochecknoinits - gochecksumtype - gocritic diff --git a/cmd/root/eval.go b/cmd/root/eval.go index d364deaf8..8a81eb99d 100644 --- a/cmd/root/eval.go +++ b/cmd/root/eval.go @@ -21,6 +21,7 @@ const defaultJudgeModel = "anthropic/claude-opus-4-5-20251101" type evalFlags struct { evaluation.Config + runConfig config.RuntimeConfig outputDir string } diff --git a/pkg/acp/filesystem.go b/pkg/acp/filesystem.go index 756a1188f..0346824c4 100644 --- a/pkg/acp/filesystem.go +++ b/pkg/acp/filesystem.go @@ -32,6 +32,7 @@ func getSessionID(ctx context.Context) (string, bool) { // and edit_file to use the ACP connection for file operations type FilesystemToolset struct { *builtin.FilesystemTool + agent *Agent workingDir string } diff --git a/pkg/app/app.go b/pkg/app/app.go index cdc0bd388..869132bc6 100644 --- a/pkg/app/app.go +++ b/pkg/app/app.go @@ -1038,11 +1038,11 @@ func (a *App) ExportHTML(ctx context.Context, filename string) (string, error) { return export.SessionToFile(a.session, agentInfo.Description, filename) } -// UpdateSessionTitle updates the current session's title and persists it. -// It works with both local and remote runtimes. // ErrTitleGenerating is returned when attempting to set a title while generation is in progress. var ErrTitleGenerating = errors.New("title generation in progress, please wait") +// UpdateSessionTitle updates the current session's title and persists it. +// It works with both local and remote runtimes. func (a *App) UpdateSessionTitle(ctx context.Context, title string) error { if a.session == nil { return errors.New("no active session") diff --git a/pkg/content/artifact.go b/pkg/content/artifact.go index 07d20464b..cb19ccb83 100644 --- a/pkg/content/artifact.go +++ b/pkg/content/artifact.go @@ -19,6 +19,7 @@ import ( // See https://github.com/opencontainers/image-spec/blob/v1.1.1/manifest.md#guidelines-for-artifact-usage type artifactImage struct { v1.Image + artifactType string } diff --git a/pkg/evaluation/eval.go b/pkg/evaluation/eval.go index a55bc301c..43c904879 100644 --- a/pkg/evaluation/eval.go +++ b/pkg/evaluation/eval.go @@ -32,6 +32,7 @@ import ( // Runner runs evaluations against an agent. type Runner struct { Config + agentSource config.Source judge *Judge runConfig *config.RuntimeConfig diff --git a/pkg/evaluation/types.go b/pkg/evaluation/types.go index fbe0c9bdb..5b6483987 100644 --- a/pkg/evaluation/types.go +++ b/pkg/evaluation/types.go @@ -10,6 +10,7 @@ import ( // InputSession wraps a session with its source path for evaluation loading. type InputSession struct { *session.Session + SourcePath string // Path to the source eval file (not serialized) } diff --git a/pkg/fake/proxy_test.go b/pkg/fake/proxy_test.go index 34fc7dd0c..a0bb90c91 100644 --- a/pkg/fake/proxy_test.go +++ b/pkg/fake/proxy_test.go @@ -303,6 +303,7 @@ func TestSimulatedStreamCopy_SSEEvents(t *testing.T) { // notifyWriter wraps an http.ResponseWriter and signals on first Write. type notifyWriter struct { http.ResponseWriter + notify chan struct{} notified bool } diff --git a/pkg/hooks/types.go b/pkg/hooks/types.go index e32e84744..b72eb0350 100644 --- a/pkg/hooks/types.go +++ b/pkg/hooks/types.go @@ -13,32 +13,32 @@ import ( type EventType string const ( - // PreToolUse is triggered before a tool call executes. + // EventPreToolUse is triggered before a tool call executes. // Can allow/deny/modify tool calls; can block with feedback. EventPreToolUse EventType = "pre_tool_use" - // PostToolUse is triggered after a tool completes successfully. + // EventPostToolUse is triggered after a tool completes successfully. // Can provide validation, feedback, or additional processing. EventPostToolUse EventType = "post_tool_use" - // SessionStart is triggered when a session begins or resumes. + // EventSessionStart is triggered when a session begins or resumes. // Can load context, setup environment, install dependencies. EventSessionStart EventType = "session_start" - // SessionEnd is triggered when a session terminates. + // EventSessionEnd is triggered when a session terminates. // Can perform cleanup, logging, persist session state. EventSessionEnd EventType = "session_end" - // OnUserInput is triggered when the agent needs input from the user. + // EventOnUserInput is triggered when the agent needs input from the user. // Can log, notify, or perform actions before user interaction. EventOnUserInput EventType = "on_user_input" - // Stop is triggered when the model finishes its response and is about + // EventStop is triggered when the model finishes its response and is about // to hand control back to the user. Can perform post-response validation, // logging, or cleanup. EventStop EventType = "stop" - // Notification is triggered when the agent emits a notification to the user, + // EventNotification is triggered when the agent emits a notification to the user, // such as errors or warnings. Can send external notifications or log events. EventNotification EventType = "notification" ) diff --git a/pkg/model/provider/anthropic/adapter.go b/pkg/model/provider/anthropic/adapter.go index 3f561dddf..b5fb83ce3 100644 --- a/pkg/model/provider/anthropic/adapter.go +++ b/pkg/model/provider/anthropic/adapter.go @@ -19,6 +19,7 @@ import ( // streamAdapter adapts the Anthropic stream to our interface type streamAdapter struct { retryableStream[anthropic.MessageStreamEventUnion] + trackUsage bool toolCall bool toolID string diff --git a/pkg/model/provider/anthropic/beta_adapter.go b/pkg/model/provider/anthropic/beta_adapter.go index 2a87f6f41..319ce404d 100644 --- a/pkg/model/provider/anthropic/beta_adapter.go +++ b/pkg/model/provider/anthropic/beta_adapter.go @@ -15,6 +15,7 @@ import ( // betaStreamAdapter adapts the Anthropic Beta stream to our interface type betaStreamAdapter struct { retryableStream[anthropic.BetaRawMessageStreamEventUnion] + trackUsage bool toolCall bool toolID string diff --git a/pkg/model/provider/anthropic/client.go b/pkg/model/provider/anthropic/client.go index ac1d01a31..b171e9563 100644 --- a/pkg/model/provider/anthropic/client.go +++ b/pkg/model/provider/anthropic/client.go @@ -31,6 +31,7 @@ import ( // It holds the anthropic client and model config type Client struct { base.Config + clientFn func(context.Context) (anthropic.Client, error) lastHTTPResponse *http.Response fileManager *FileManager diff --git a/pkg/model/provider/bedrock/client.go b/pkg/model/provider/bedrock/client.go index 8086d41de..a29fd7363 100644 --- a/pkg/model/provider/bedrock/client.go +++ b/pkg/model/provider/bedrock/client.go @@ -27,6 +27,7 @@ import ( // Client represents a Bedrock client wrapper implementing provider.Provider type Client struct { base.Config + bedrockClient *bedrockruntime.Client cachingSupported bool // Cached at init time for efficiency } diff --git a/pkg/model/provider/dmr/client.go b/pkg/model/provider/dmr/client.go index d4ee17957..439e31918 100644 --- a/pkg/model/provider/dmr/client.go +++ b/pkg/model/provider/dmr/client.go @@ -50,6 +50,7 @@ const ( // It implements the provider.Provider interface type Client struct { base.Config + client openai.Client baseURL string httpClient *http.Client diff --git a/pkg/model/provider/gemini/client.go b/pkg/model/provider/gemini/client.go index 1f36f8b39..0178e5d74 100644 --- a/pkg/model/provider/gemini/client.go +++ b/pkg/model/provider/gemini/client.go @@ -30,6 +30,7 @@ import ( // It implements the provider.Provider interface type Client struct { base.Config + clientFn func(context.Context) (*genai.Client, error) } diff --git a/pkg/model/provider/openai/client.go b/pkg/model/provider/openai/client.go index d3ad07eff..e9956f08c 100644 --- a/pkg/model/provider/openai/client.go +++ b/pkg/model/provider/openai/client.go @@ -33,6 +33,7 @@ import ( // It implements the provider.Provider interface type Client struct { base.Config + clientFn func(context.Context) (*openai.Client, error) } diff --git a/pkg/model/provider/rulebased/client.go b/pkg/model/provider/rulebased/client.go index 5894de2b5..6647a0b9f 100644 --- a/pkg/model/provider/rulebased/client.go +++ b/pkg/model/provider/rulebased/client.go @@ -41,6 +41,7 @@ type ProviderFactory func(ctx context.Context, modelSpec string, models map[stri // Client implements the Provider interface for rule-based model routing. type Client struct { base.Config + routes []Provider fallback Provider index bleve.Index diff --git a/pkg/rag/rerank/rerank_test.go b/pkg/rag/rerank/rerank_test.go index 223b135ab..0a514fae3 100644 --- a/pkg/rag/rerank/rerank_test.go +++ b/pkg/rag/rerank/rerank_test.go @@ -18,6 +18,7 @@ import ( // fakeRerankingProvider implements provider.RerankingProvider for testing. type fakeRerankingProvider struct { base.Config + scores []float64 err error } diff --git a/pkg/rag/strategy/vector_store.go b/pkg/rag/strategy/vector_store.go index dd036851f..ad04623ac 100644 --- a/pkg/rag/strategy/vector_store.go +++ b/pkg/rag/strategy/vector_store.go @@ -38,6 +38,7 @@ type vectorStoreDB interface { // It contains base document data plus similarity score. type VectorSearchResultData struct { database.Document + Embedding []float64 EmbeddingInput string // Only populated for semantic-embeddings Similarity float64 diff --git a/pkg/runtime/event.go b/pkg/runtime/event.go index 568bc4f03..4254e2b61 100644 --- a/pkg/runtime/event.go +++ b/pkg/runtime/event.go @@ -37,12 +37,13 @@ func newAgentContext(agentName string) AgentContext { // UserMessageEvent is sent when a user message is received type UserMessageEvent struct { + AgentContext + Type string `json:"type"` Message string `json:"message"` MultiContent []chat.MessagePart `json:"multi_content,omitempty"` SessionID string `json:"session_id"` SessionPosition int `json:"session_position"` // Index in session.Messages, -1 if unknown - AgentContext } func UserMessage(message, sessionID string, multiContent []chat.MessagePart, sessionPos ...int) Event { @@ -62,10 +63,11 @@ func UserMessage(message, sessionID string, multiContent []chat.MessagePart, ses // PartialToolCallEvent is sent when a tool call is first received (partial/complete) type PartialToolCallEvent struct { + AgentContext + Type string `json:"type"` ToolCall tools.ToolCall `json:"tool_call"` ToolDefinition *tools.Tool `json:"tool_definition,omitempty"` - AgentContext } func PartialToolCall(toolCall tools.ToolCall, toolDefinition tools.Tool, agentName string) Event { @@ -84,10 +86,11 @@ func PartialToolCall(toolCall tools.ToolCall, toolDefinition tools.Tool, agentNa // ToolCallEvent is sent when a tool call is received type ToolCallEvent struct { + AgentContext + Type string `json:"type"` ToolCall tools.ToolCall `json:"tool_call"` ToolDefinition tools.Tool `json:"tool_definition"` - AgentContext } func ToolCall(toolCall tools.ToolCall, toolDefinition tools.Tool, agentName string) Event { @@ -100,10 +103,11 @@ func ToolCall(toolCall tools.ToolCall, toolDefinition tools.Tool, agentName stri } type ToolCallConfirmationEvent struct { + AgentContext + Type string `json:"type"` ToolCall tools.ToolCall `json:"tool_call"` ToolDefinition tools.Tool `json:"tool_definition"` - AgentContext } func ToolCallConfirmation(toolCall tools.ToolCall, toolDefinition tools.Tool, agentName string) Event { @@ -116,12 +120,13 @@ func ToolCallConfirmation(toolCall tools.ToolCall, toolDefinition tools.Tool, ag } type ToolCallResponseEvent struct { + AgentContext + Type string `json:"type"` ToolCallID string `json:"tool_call_id"` ToolDefinition tools.Tool `json:"tool_definition"` Response string `json:"response"` Result *tools.ToolCallResult `json:"result,omitempty"` - AgentContext } func ToolCallResponse(toolCallID string, toolDefinition tools.Tool, result *tools.ToolCallResult, response, agentName string) Event { @@ -136,9 +141,10 @@ func ToolCallResponse(toolCallID string, toolDefinition tools.Tool, result *tool } type StreamStartedEvent struct { + AgentContext + Type string `json:"type"` SessionID string `json:"session_id,omitempty"` - AgentContext } func StreamStarted(sessionID, agentName string) Event { @@ -150,10 +156,11 @@ func StreamStarted(sessionID, agentName string) Event { } type AgentChoiceEvent struct { + AgentContext + Type string `json:"type"` Content string `json:"content"` SessionID string `json:"session_id,omitempty"` - AgentContext } func (e *AgentChoiceEvent) GetSessionID() string { return e.SessionID } @@ -168,10 +175,11 @@ func AgentChoice(agentName, sessionID, content string) Event { } type AgentChoiceReasoningEvent struct { + AgentContext + Type string `json:"type"` Content string `json:"content"` SessionID string `json:"session_id,omitempty"` - AgentContext } func (e *AgentChoiceReasoningEvent) GetSessionID() string { return e.SessionID } @@ -186,9 +194,10 @@ func AgentChoiceReasoning(agentName, sessionID, content string) Event { } type ErrorEvent struct { + AgentContext + Type string `json:"type"` Error string `json:"error"` - AgentContext } func Error(msg string) Event { @@ -199,9 +208,10 @@ func Error(msg string) Event { } type ShellOutputEvent struct { + AgentContext + Type string `json:"type"` Output string `json:"output"` - AgentContext } func ShellOutput(output string) Event { @@ -213,9 +223,10 @@ func ShellOutput(output string) Event { } type WarningEvent struct { + AgentContext + Type string `json:"type"` Message string `json:"message"` - AgentContext } func Warning(message, agentName string) Event { @@ -231,13 +242,14 @@ func Warning(message, agentName string) Event { // - Retryable errors (5xx, timeouts) after exhausting retries // - Non-retryable errors (429, 4xx) which skip retries and move immediately to fallback type ModelFallbackEvent struct { + AgentContext + Type string `json:"type"` FailedModel string `json:"failed_model"` FallbackModel string `json:"fallback_model"` Reason string `json:"reason"` Attempt int `json:"attempt"` // Current attempt number (1-indexed) MaxAttempts int `json:"max_attempts"` // Total attempts allowed for this model - AgentContext } // ModelFallback creates a new ModelFallbackEvent. @@ -254,10 +266,11 @@ func ModelFallback(agentName, failedModel, fallbackModel, reason string, attempt } type TokenUsageEvent struct { + AgentContext + Type string `json:"type"` SessionID string `json:"session_id"` Usage *Usage `json:"usage"` - AgentContext } type Usage struct { @@ -274,6 +287,7 @@ type Usage struct { type MessageUsage struct { chat.Usage chat.RateLimit + Cost float64 Model string } @@ -301,10 +315,11 @@ func SessionUsage(sess *session.Session, contextLimit int64) *Usage { } type SessionTitleEvent struct { + AgentContext + Type string `json:"type"` SessionID string `json:"session_id"` Title string `json:"title"` - AgentContext } func SessionTitle(sessionID, title string) Event { @@ -316,10 +331,11 @@ func SessionTitle(sessionID, title string) Event { } type SessionSummaryEvent struct { + AgentContext + Type string `json:"type"` SessionID string `json:"session_id"` Summary string `json:"summary"` - AgentContext } func SessionSummary(sessionID, summary, agentName string) Event { @@ -332,10 +348,11 @@ func SessionSummary(sessionID, summary, agentName string) Event { } type SessionCompactionEvent struct { + AgentContext + Type string `json:"type"` SessionID string `json:"session_id"` Status string `json:"status"` - AgentContext } func SessionCompaction(sessionID, status, agentName string) Event { @@ -348,9 +365,10 @@ func SessionCompaction(sessionID, status, agentName string) Event { } type StreamStoppedEvent struct { + AgentContext + Type string `json:"type"` SessionID string `json:"session_id,omitempty"` - AgentContext } func StreamStopped(sessionID, agentName string) Event { @@ -363,6 +381,8 @@ func StreamStopped(sessionID, agentName string) Event { // ElicitationRequestEvent is sent when an elicitation request is received from an MCP server type ElicitationRequestEvent struct { + AgentContext + Type string `json:"type"` Message string `json:"message"` Mode string `json:"mode,omitempty"` // "form" or "url" @@ -370,7 +390,6 @@ type ElicitationRequestEvent struct { URL string `json:"url,omitempty"` ElicitationID string `json:"elicitation_id,omitempty"` Meta map[string]any `json:"meta,omitempty"` - AgentContext } func ElicitationRequest(message, mode string, schema any, url, elicitationID string, meta map[string]any, agentName string) Event { @@ -387,9 +406,10 @@ func ElicitationRequest(message, mode string, schema any, url, elicitationID str } type AuthorizationEvent struct { + AgentContext + Type string `json:"type"` Confirmation tools.ElicitationAction `json:"confirmation"` - AgentContext } func Authorization(confirmation tools.ElicitationAction, agentName string) Event { @@ -401,9 +421,10 @@ func Authorization(confirmation tools.ElicitationAction, agentName string) Event } type MaxIterationsReachedEvent struct { + AgentContext + Type string `json:"type"` MaxIterations int `json:"max_iterations"` - AgentContext } func MaxIterationsReached(maxIterations int) Event { @@ -415,8 +436,9 @@ func MaxIterationsReached(maxIterations int) Event { // MCPInitStartedEvent is for MCP initialization lifecycle events type MCPInitStartedEvent struct { - Type string `json:"type"` AgentContext + + Type string `json:"type"` } func MCPInitStarted(agentName string) Event { @@ -427,8 +449,9 @@ func MCPInitStarted(agentName string) Event { } type MCPInitFinishedEvent struct { - Type string `json:"type"` AgentContext + + Type string `json:"type"` } func MCPInitFinished(agentName string) Event { @@ -440,12 +463,13 @@ func MCPInitFinished(agentName string) Event { // AgentInfoEvent is sent when agent information is available or changes type AgentInfoEvent struct { + AgentContext + Type string `json:"type"` AgentName string `json:"agent_name"` Model string `json:"model"` // this is in provider/model format (e.g., "openai/gpt-4o") Description string `json:"description"` WelcomeMessage string `json:"welcome_message,omitempty"` - AgentContext } func AgentInfo(agentName, model, description, welcomeMessage string) Event { @@ -470,10 +494,11 @@ type AgentDetails struct { // TeamInfoEvent is sent when team information is available type TeamInfoEvent struct { + AgentContext + Type string `json:"type"` AvailableAgents []AgentDetails `json:"available_agents"` CurrentAgent string `json:"current_agent"` - AgentContext } func TeamInfo(availableAgents []AgentDetails, currentAgent string) Event { @@ -487,11 +512,12 @@ func TeamInfo(availableAgents []AgentDetails, currentAgent string) Event { // AgentSwitchingEvent is sent when agent switching starts or stops type AgentSwitchingEvent struct { + AgentContext + Type string `json:"type"` Switching bool `json:"switching"` FromAgent string `json:"from_agent,omitempty"` ToAgent string `json:"to_agent,omitempty"` - AgentContext } func AgentSwitching(switching bool, fromAgent, toAgent string) Event { @@ -507,10 +533,11 @@ func AgentSwitching(switching bool, fromAgent, toAgent string) Event { // ToolsetInfoEvent is sent when toolset information is available // When Loading is true, more tools may still be loading (e.g., MCP servers starting) type ToolsetInfoEvent struct { + AgentContext + Type string `json:"type"` AvailableTools int `json:"available_tools"` Loading bool `json:"loading"` - AgentContext } func ToolsetInfo(availableTools int, loading bool, agentName string) Event { @@ -524,10 +551,11 @@ func ToolsetInfo(availableTools int, loading bool, agentName string) Event { // RAGIndexingStartedEvent is for RAG lifecycle events type RAGIndexingStartedEvent struct { + AgentContext + Type string `json:"type"` RAGName string `json:"rag_name"` StrategyName string `json:"strategy_name"` - AgentContext } func RAGIndexingStarted(ragName, strategyName, agentName string) Event { @@ -540,12 +568,13 @@ func RAGIndexingStarted(ragName, strategyName, agentName string) Event { } type RAGIndexingProgressEvent struct { + AgentContext + Type string `json:"type"` RAGName string `json:"rag_name"` StrategyName string `json:"strategy_name"` Current int `json:"current"` Total int `json:"total"` - AgentContext } func RAGIndexingProgress(ragName, strategyName string, current, total int, agentName string) Event { @@ -560,10 +589,11 @@ func RAGIndexingProgress(ragName, strategyName string, current, total int, agent } type RAGIndexingCompletedEvent struct { + AgentContext + Type string `json:"type"` RAGName string `json:"rag_name"` StrategyName string `json:"strategy_name"` - AgentContext } func RAGIndexingCompleted(ragName, strategyName, agentName string) Event { @@ -577,11 +607,12 @@ func RAGIndexingCompleted(ragName, strategyName, agentName string) Event { // HookBlockedEvent is sent when a pre-tool hook blocks a tool call type HookBlockedEvent struct { + AgentContext + Type string `json:"type"` ToolCall tools.ToolCall `json:"tool_call"` ToolDefinition tools.Tool `json:"tool_definition"` Message string `json:"message"` - AgentContext } func HookBlocked(toolCall tools.ToolCall, toolDefinition tools.Tool, message, agentName string) Event { @@ -597,10 +628,11 @@ func HookBlocked(toolCall tools.ToolCall, toolDefinition tools.Tool, message, ag // MessageAddedEvent is emitted when a message is added to the session. // This event is used by the PersistentRuntime wrapper to persist messages. type MessageAddedEvent struct { + AgentContext + Type string `json:"type"` SessionID string `json:"session_id"` Message *session.Message `json:"-"` - AgentContext } func (e *MessageAddedEvent) GetAgentName() string { return e.AgentName } @@ -618,10 +650,11 @@ func MessageAdded(sessionID string, msg *session.Message, agentName string) Even // SubSessionCompletedEvent is emitted when a sub-session completes and is added to parent. // This event is used by the PersistentRuntime wrapper to persist sub-sessions. type SubSessionCompletedEvent struct { + AgentContext + Type string `json:"type"` ParentSessionID string `json:"parent_session_id"` SubSession any `json:"sub_session"` // *session.Session - AgentContext } func (e *SubSessionCompletedEvent) GetAgentName() string { return e.AgentName } diff --git a/pkg/runtime/model_switcher_test.go b/pkg/runtime/model_switcher_test.go index 5f9d74e02..1ca002d3d 100644 --- a/pkg/runtime/model_switcher_test.go +++ b/pkg/runtime/model_switcher_test.go @@ -15,6 +15,7 @@ import ( // mockCatalogStore implements ModelStore for testing type mockCatalogStore struct { ModelStore + db *modelsdev.Database } diff --git a/pkg/runtime/runtime_test.go b/pkg/runtime/runtime_test.go index 216e66985..5587b2d8e 100644 --- a/pkg/runtime/runtime_test.go +++ b/pkg/runtime/runtime_test.go @@ -681,6 +681,7 @@ func (p *queueProvider) MaxTokens() int { return 0 } type mockModelStoreWithLimit struct { ModelStore + limit int } diff --git a/pkg/teamloader/filter.go b/pkg/teamloader/filter.go index fdbc717b7..9426db70d 100644 --- a/pkg/teamloader/filter.go +++ b/pkg/teamloader/filter.go @@ -38,6 +38,7 @@ func WithToolsExcludeFilter(inner tools.ToolSet, toolNames ...string) tools.Tool type filterTools struct { tools.ToolSet + toolNames []string exclude bool } diff --git a/pkg/teamloader/filter_test.go b/pkg/teamloader/filter_test.go index 8e2727ea0..8a7a11510 100644 --- a/pkg/teamloader/filter_test.go +++ b/pkg/teamloader/filter_test.go @@ -13,6 +13,7 @@ import ( type mockToolSet struct { tools.ToolSet + toolsFunc func(ctx context.Context) ([]tools.Tool, error) } @@ -122,6 +123,7 @@ func TestWithToolsFilter_CaseSensitive(t *testing.T) { type instructableToolSet struct { mockToolSet + instructions string } diff --git a/pkg/teamloader/instructions.go b/pkg/teamloader/instructions.go index 0bb396536..2d4387334 100644 --- a/pkg/teamloader/instructions.go +++ b/pkg/teamloader/instructions.go @@ -19,6 +19,7 @@ func WithInstructions(inner tools.ToolSet, instruction string) tools.ToolSet { type replaceInstruction struct { tools.ToolSet + instruction string } diff --git a/pkg/teamloader/instructions_test.go b/pkg/teamloader/instructions_test.go index 5c8e04e37..ae3ae9d5a 100644 --- a/pkg/teamloader/instructions_test.go +++ b/pkg/teamloader/instructions_test.go @@ -10,6 +10,7 @@ import ( type toolSet struct { tools.ToolSet + instruction string } diff --git a/pkg/teamloader/model_override.go b/pkg/teamloader/model_override.go index 33de47900..8c4370f4f 100644 --- a/pkg/teamloader/model_override.go +++ b/pkg/teamloader/model_override.go @@ -21,6 +21,7 @@ func WithModelOverride(inner tools.ToolSet, model string) tools.ToolSet { type modelOverrideToolset struct { tools.ToolSet + model string } diff --git a/pkg/teamloader/toon.go b/pkg/teamloader/toon.go index ec949cf0c..820e3bebd 100644 --- a/pkg/teamloader/toon.go +++ b/pkg/teamloader/toon.go @@ -13,6 +13,7 @@ import ( type toonTools struct { tools.ToolSet + toolRegexps []*regexp.Regexp } diff --git a/pkg/telemetry/telemetry_test.go b/pkg/telemetry/telemetry_test.go index 58fbd118f..c636c04a3 100644 --- a/pkg/telemetry/telemetry_test.go +++ b/pkg/telemetry/telemetry_test.go @@ -19,6 +19,7 @@ import ( // MockHTTPClient captures HTTP requests for testing type MockHTTPClient struct { *http.Client + mu sync.Mutex requests []*http.Request bodies [][]byte diff --git a/pkg/tools/builtin/lsp.go b/pkg/tools/builtin/lsp.go index ff2d5f6fc..28a4a3998 100644 --- a/pkg/tools/builtin/lsp.go +++ b/pkg/tools/builtin/lsp.go @@ -145,6 +145,7 @@ type PositionArgs struct { // ReferencesArgs extends PositionArgs with an include_declaration option. type ReferencesArgs struct { PositionArgs + IncludeDeclaration *bool `json:"include_declaration,omitempty" jsonschema:"Include the declaration in results (default: true)"` } @@ -161,6 +162,7 @@ type WorkspaceSymbolsArgs struct { // RenameArgs extends PositionArgs with the new name. type RenameArgs struct { PositionArgs + NewName string `json:"new_name" jsonschema:"The new name for the symbol"` } @@ -174,12 +176,14 @@ type CodeActionsArgs struct { // CallHierarchyArgs for getting call hierarchy. type CallHierarchyArgs struct { PositionArgs + Direction string `json:"direction" jsonschema:"Direction: 'incoming' (who calls this) or 'outgoing' (what this calls)"` } // TypeHierarchyArgs for getting type hierarchy. type TypeHierarchyArgs struct { PositionArgs + Direction string `json:"direction" jsonschema:"Direction: 'supertypes' (parent types) or 'subtypes' (child types)"` } diff --git a/pkg/tools/builtin/tasks.go b/pkg/tools/builtin/tasks.go index 00804fda8..9f7cb1047 100644 --- a/pkg/tools/builtin/tasks.go +++ b/pkg/tools/builtin/tasks.go @@ -80,6 +80,7 @@ type Task struct { type taskWithEffective struct { Task + EffectiveStatus TaskStatus `json:"effectiveStatus"` } diff --git a/pkg/tools/mcp/gateway.go b/pkg/tools/mcp/gateway.go index 2d914de89..b2be14610 100644 --- a/pkg/tools/mcp/gateway.go +++ b/pkg/tools/mcp/gateway.go @@ -17,6 +17,7 @@ import ( type GatewayToolset struct { *Toolset + cleanUp func() error } diff --git a/pkg/tools/mcp/remote.go b/pkg/tools/mcp/remote.go index 9683ae90c..83269883e 100644 --- a/pkg/tools/mcp/remote.go +++ b/pkg/tools/mcp/remote.go @@ -13,6 +13,7 @@ import ( type remoteMCPClient struct { sessionClient + url string transportType string headers map[string]string diff --git a/pkg/tools/mcp/stdio.go b/pkg/tools/mcp/stdio.go index 39b2c35a9..01e3fab25 100644 --- a/pkg/tools/mcp/stdio.go +++ b/pkg/tools/mcp/stdio.go @@ -13,6 +13,7 @@ import ( type stdioMCPClient struct { sessionClient + command string args []string env []string diff --git a/pkg/tui/dialog/attachment_preview.go b/pkg/tui/dialog/attachment_preview.go index e88c7a8c0..61d638c26 100644 --- a/pkg/tui/dialog/attachment_preview.go +++ b/pkg/tui/dialog/attachment_preview.go @@ -29,6 +29,7 @@ const ( type attachmentPreviewDialog struct { BaseDialog + preview editor.AttachmentPreview viewport viewport.Model diff --git a/pkg/tui/dialog/command_palette.go b/pkg/tui/dialog/command_palette.go index 8467695cb..1154f00b9 100644 --- a/pkg/tui/dialog/command_palette.go +++ b/pkg/tui/dialog/command_palette.go @@ -25,6 +25,7 @@ type CommandExecuteMsg struct { // commandPaletteDialog implements Dialog for the command palette type commandPaletteDialog struct { BaseDialog + textInput textinput.Model categories []commands.Category filtered []commands.Item diff --git a/pkg/tui/dialog/cost.go b/pkg/tui/dialog/cost.go index efbc6fa70..a16fcad1b 100644 --- a/pkg/tui/dialog/cost.go +++ b/pkg/tui/dialog/cost.go @@ -28,6 +28,7 @@ import ( type costDialog struct { BaseDialog + session *session.Session keyMap costDialogKeyMap scrollview *scrollview.Model @@ -97,6 +98,7 @@ func (d *costDialog) View() string { type totalUsage struct { chat.Usage + label string model string // model name (only set for per-message entries) cost float64 diff --git a/pkg/tui/dialog/elicitation.go b/pkg/tui/dialog/elicitation.go index a14d9d789..755ce9e5a 100644 --- a/pkg/tui/dialog/elicitation.go +++ b/pkg/tui/dialog/elicitation.go @@ -43,6 +43,7 @@ type ElicitationField struct { // is shown so the user can type an answer. type ElicitationDialog struct { BaseDialog + title string message string fields []ElicitationField diff --git a/pkg/tui/dialog/exit_confirmation.go b/pkg/tui/dialog/exit_confirmation.go index 28ff96973..ec589e30b 100644 --- a/pkg/tui/dialog/exit_confirmation.go +++ b/pkg/tui/dialog/exit_confirmation.go @@ -37,6 +37,7 @@ func defaultExitConfirmationKeyMap() exitConfirmationKeyMap { type exitConfirmationDialog struct { BaseDialog + keyMap exitConfirmationKeyMap } diff --git a/pkg/tui/dialog/file_picker.go b/pkg/tui/dialog/file_picker.go index 1048d81e8..fe92a8107 100644 --- a/pkg/tui/dialog/file_picker.go +++ b/pkg/tui/dialog/file_picker.go @@ -33,6 +33,7 @@ const ( type filePickerDialog struct { BaseDialog + textInput textinput.Model currentDir string entries []fileEntry diff --git a/pkg/tui/dialog/max_iterations.go b/pkg/tui/dialog/max_iterations.go index b0369d529..2d455baba 100644 --- a/pkg/tui/dialog/max_iterations.go +++ b/pkg/tui/dialog/max_iterations.go @@ -23,6 +23,7 @@ const ( type maxIterationsDialog struct { BaseDialog + maxIterations int app *app.App keyMap ConfirmKeyMap diff --git a/pkg/tui/dialog/mcp_prompt_input.go b/pkg/tui/dialog/mcp_prompt_input.go index 111877080..494193225 100644 --- a/pkg/tui/dialog/mcp_prompt_input.go +++ b/pkg/tui/dialog/mcp_prompt_input.go @@ -18,6 +18,7 @@ import ( // MCPPromptInputDialog implements Dialog for collecting MCP prompt parameters type MCPPromptInputDialog struct { BaseDialog + promptName string promptInfo mcptools.PromptInfo inputs []textinput.Model diff --git a/pkg/tui/dialog/model_picker.go b/pkg/tui/dialog/model_picker.go index 3b1f199fb..3b089ddc5 100644 --- a/pkg/tui/dialog/model_picker.go +++ b/pkg/tui/dialog/model_picker.go @@ -26,6 +26,7 @@ import ( // modelPickerDialog is a dialog for selecting a model for the current agent. type modelPickerDialog struct { BaseDialog + textInput textinput.Model models []runtime.ModelChoice filtered []runtime.ModelChoice diff --git a/pkg/tui/dialog/multi_choice.go b/pkg/tui/dialog/multi_choice.go index ba7368d32..6e9ad8d8f 100644 --- a/pkg/tui/dialog/multi_choice.go +++ b/pkg/tui/dialog/multi_choice.go @@ -98,6 +98,7 @@ type clickableRange struct { // multiChoiceDialog implements a reusable multi-choice selection dialog. type multiChoiceDialog struct { BaseDialog + config MultiChoiceConfig selected selection // Currently selected item (-1 = none) customInput textinput.Model // Text input for custom response diff --git a/pkg/tui/dialog/oauth_authorization.go b/pkg/tui/dialog/oauth_authorization.go index 62e740495..b669ca7a2 100644 --- a/pkg/tui/dialog/oauth_authorization.go +++ b/pkg/tui/dialog/oauth_authorization.go @@ -15,6 +15,7 @@ import ( type oauthAuthorizationDialog struct { BaseDialog + serverURL string app *app.App keyMap ConfirmKeyMap diff --git a/pkg/tui/dialog/permissions.go b/pkg/tui/dialog/permissions.go index 5f6709424..c035636a7 100644 --- a/pkg/tui/dialog/permissions.go +++ b/pkg/tui/dialog/permissions.go @@ -15,6 +15,7 @@ import ( // permissionsDialog displays the configured tool permissions (allow/deny patterns). type permissionsDialog struct { BaseDialog + permissions *runtime.PermissionsInfo yoloEnabled bool closeKey key.Binding diff --git a/pkg/tui/dialog/session_browser.go b/pkg/tui/dialog/session_browser.go index 3170ca6ad..bef156b7d 100644 --- a/pkg/tui/dialog/session_browser.go +++ b/pkg/tui/dialog/session_browser.go @@ -39,6 +39,7 @@ const ( type sessionBrowserDialog struct { BaseDialog + textInput textinput.Model sessions []session.Summary filtered []session.Summary diff --git a/pkg/tui/dialog/theme_picker.go b/pkg/tui/dialog/theme_picker.go index 79522e262..4db3662ff 100644 --- a/pkg/tui/dialog/theme_picker.go +++ b/pkg/tui/dialog/theme_picker.go @@ -31,6 +31,7 @@ type ThemeChoice struct { // themePickerDialog is a dialog for selecting a theme. type themePickerDialog struct { BaseDialog + textInput textinput.Model themes []ThemeChoice filtered []ThemeChoice diff --git a/pkg/tui/dialog/tool_confirmation.go b/pkg/tui/dialog/tool_confirmation.go index a3bcf58e3..1bb2ba6e5 100644 --- a/pkg/tui/dialog/tool_confirmation.go +++ b/pkg/tui/dialog/tool_confirmation.go @@ -42,6 +42,7 @@ type ToolConfirmationResponse struct { type toolConfirmationDialog struct { BaseDialog + msg *runtime.ToolCallConfirmationEvent keyMap toolConfirmationKeyMap sessionState *service.SessionState diff --git a/pkg/tui/dialog/url_elicitation.go b/pkg/tui/dialog/url_elicitation.go index 600514ce3..d7535c715 100644 --- a/pkg/tui/dialog/url_elicitation.go +++ b/pkg/tui/dialog/url_elicitation.go @@ -17,6 +17,7 @@ import ( // It displays a URL for the user to visit and waits for confirmation. type URLElicitationDialog struct { BaseDialog + message string url string keyMap ConfirmKeyMap diff --git a/pkg/tui/dialog/working_dir_picker.go b/pkg/tui/dialog/working_dir_picker.go index d434b42d3..4773d9ed3 100644 --- a/pkg/tui/dialog/working_dir_picker.go +++ b/pkg/tui/dialog/working_dir_picker.go @@ -111,6 +111,7 @@ type tabRegion struct { type workingDirPickerDialog struct { BaseDialog + textInput textinput.Model section dirSection diff --git a/pkg/tui/messages/session.go b/pkg/tui/messages/session.go index 8d048c082..fbce752ce 100644 --- a/pkg/tui/messages/session.go +++ b/pkg/tui/messages/session.go @@ -1,4 +1,3 @@ -// Package messages defines all TUI message types organized by domain. package messages import "github.com/docker/docker-agent/pkg/session" diff --git a/pkg/tui/messages/tabs.go b/pkg/tui/messages/tabs.go index d54b19ab1..f65ef6828 100644 --- a/pkg/tui/messages/tabs.go +++ b/pkg/tui/messages/tabs.go @@ -1,4 +1,3 @@ -// Package messages defines all TUI message types organized by domain. package messages import tea "charm.land/bubbletea/v2" diff --git a/pkg/tui/styles/agent_colors.go b/pkg/tui/styles/agent_colors.go index 2f3fe6f8d..3a95ecae0 100644 --- a/pkg/tui/styles/agent_colors.go +++ b/pkg/tui/styles/agent_colors.go @@ -33,6 +33,7 @@ type cachedBadgeStyle struct { // precomputed styles for each palette entry. var agentRegistry struct { sync.RWMutex + indices map[string]int badgeStyles []cachedBadgeStyle accentStyles []lipgloss.Style diff --git a/pkg/tui/styles/styles.go b/pkg/tui/styles/styles.go index 61087f1bf..51f653547 100644 --- a/pkg/tui/styles/styles.go +++ b/pkg/tui/styles/styles.go @@ -25,11 +25,13 @@ var ( BackgroundAlt color.Color // Primary accent colors + White color.Color MobyBlue color.Color Accent color.Color // Status colors + Success color.Color Error color.Color Warning color.Color @@ -37,33 +39,39 @@ var ( Highlight color.Color // Text hierarchy + TextPrimary color.Color TextSecondary color.Color TextMuted color.Color TextMutedGray color.Color // Border colors + BorderPrimary color.Color BorderSecondary color.Color BorderMuted color.Color BorderWarning color.Color // Diff colors + DiffAddBg color.Color DiffRemoveBg color.Color DiffAddFg color.Color DiffRemoveFg color.Color // UI element colors + LineNumber color.Color Separator color.Color // Interactive element colors + Selected color.Color SelectedFg color.Color PlaceholderColor color.Color // Badge colors + AgentBadgeFg color.Color AgentBadgeBg color.Color BadgePurple color.Color @@ -71,13 +79,16 @@ var ( BadgeGreen color.Color // Error colors (extended) + ErrorStrong color.Color ErrorDark color.Color // Additional muted colors + FadedGray color.Color // Tabs + TabBg color.Color TabPrimaryFg color.Color TabAccentFg color.Color @@ -248,6 +259,7 @@ var ( Foreground(White) // Badge styles for model picker - use color vars set by ApplyTheme() + BadgeAlloyStyle = BaseStyle. Foreground(BadgePurple) @@ -373,6 +385,7 @@ var ( SuggestionCursorStyle = BaseStyle.Background(Accent).Foreground(TextMutedGray) // Attachment banner styles - polished look with subtle border + AttachmentBannerStyle = BaseStyle. Foreground(TextSecondary)