Documentation
¶
Index ¶
- Constants
- func CLIList(stateDir string, limit int) error
- func CLIShow(stateDir string, id string) error
- func CleanupRecords()
- func FormatReportDescription(record *DiagnoseRecord, report string, language string) string
- func FormatToolArgsDisplay(name, rawArgs string) string
- func Init(registry *ToolRegistry)
- func ParseArgs(raw string) map[string]string
- func ParseToolArgs(raw string) map[string]string
- func RunSelfTest(registry *ToolRegistry, filter string, verbose bool) error
- func SeverityRank(status string) int
- func Shutdown()
- func TruncateForRecord(s string) string
- func TruncateOutput(s string) string
- func TruncateUTF8(s string, maxBytes int) string
- type AIRecord
- type AccessorFactory
- type AlertRecord
- type ChatStream
- type ChatStreamConfig
- type CheckSnapshot
- type DiagnoseAggregator
- type DiagnoseEngine
- func (e *DiagnoseEngine) Registry() *ToolRegistry
- func (e *DiagnoseEngine) ReleaseSem()
- func (e *DiagnoseEngine) RunDiagnose(req *DiagnoseRequest) *DiagnoseRecord
- func (e *DiagnoseEngine) RunDiagnoseStreaming(ctx context.Context, req *DiagnoseRequest, cb StreamCallback) (report string, err error)
- func (e *DiagnoseEngine) Shutdown()
- func (e *DiagnoseEngine) State() *DiagnoseState
- func (e *DiagnoseEngine) Submit(req *DiagnoseRequest)
- func (e *DiagnoseEngine) TrySem() bool
- type DiagnoseRecord
- type DiagnoseRequest
- type DiagnoseSession
- type DiagnoseState
- func (s *DiagnoseState) AddTokens(input, output int)
- func (s *DiagnoseState) FormatUsage() string
- func (s *DiagnoseState) IsCooldownActive(plugin, target string) bool
- func (s *DiagnoseState) IsDailyLimitReached(limit int) bool
- func (s *DiagnoseState) Load()
- func (s *DiagnoseState) Save()
- func (s *DiagnoseState) TotalTokens() int
- func (s *DiagnoseState) UpdateCooldown(plugin, target string, duration time.Duration)
- type DiagnoseTool
- type ProgressCallback
- type ProgressEvent
- type ProgressEventType
- type RoundRecord
- type SelfTestResult
- type ShellExecutor
- type StreamCallback
- type ToolCallRecord
- type ToolCategory
- type ToolParam
- type ToolRegistry
- func (r *ToolRegistry) ByPlugin(plugin string) []DiagnoseTool
- func (r *ToolRegistry) ByPluginForOS(plugin, goos string) []DiagnoseTool
- func (r *ToolRegistry) Categories() []string
- func (r *ToolRegistry) CategoriesWithTools() []ToolCategory
- func (r *ToolRegistry) CreateAccessor(ctx context.Context, plugin string, instanceRef any) (any, error)
- func (r *ToolRegistry) Get(name string) (*DiagnoseTool, bool)
- func (r *ToolRegistry) HasAccessorFactory(plugin string) bool
- func (r *ToolRegistry) ListAllTools() string
- func (r *ToolRegistry) ListCategories() string
- func (r *ToolRegistry) ListCategoriesForOS(goos string) string
- func (r *ToolRegistry) ListToolCatalogSmart() string
- func (r *ToolRegistry) ListToolCatalogSmartForOS(goos string) string
- func (r *ToolRegistry) ListTools(category string) string
- func (r *ToolRegistry) ListToolsForOS(category, goos string) string
- func (r *ToolRegistry) Register(category string, tool DiagnoseTool)
- func (r *ToolRegistry) RegisterAccessorFactory(plugin string, factory AccessorFactory)
- func (r *ToolRegistry) RegisterCategory(name, plugin, description string, scope ToolScope)
- func (r *ToolRegistry) ToolCount() int
- func (r *ToolRegistry) ToolSupportedOn(name, goos string) bool
- type ToolScope
Constants ¶
const ( ModeAlert = "alert" ModeInspect = "inspect" )
Variables ¶
This section is empty.
Functions ¶
func CleanupRecords ¶
func CleanupRecords()
CleanupRecords removes diagnosis records exceeding the retention period or the maximum count, whichever triggers first.
func FormatReportDescription ¶
func FormatReportDescription(record *DiagnoseRecord, report string, language string) string
FormatReportDescription builds a concise diagnosis report suitable for notification description fields (max 2048 bytes). It prioritizes:
- Header (plugin, target, time, status)
- AI summary/report body
- A footer with record ID and CLI hint
If the report exceeds 2048 bytes, the AI body is truncated.
func FormatToolArgsDisplay ¶
FormatToolArgsDisplay produces a human-friendly summary of tool arguments for terminal display. Returns "" when there is nothing meaningful to show.
func Init ¶
func Init(registry *ToolRegistry)
Init initializes the global diagnose engine and aggregator. Called once at startup from the agent package.
func ParseArgs ¶
ParseArgs parses the AI's function call arguments JSON into a flat string map. Returns a non-nil empty map for empty input so callers can safely read keys.
func ParseToolArgs ¶
ParseToolArgs parses the nested tool_args JSON string (from call_tool). Returns nil for empty input; callers should check for nil.
func RunSelfTest ¶
func RunSelfTest(registry *ToolRegistry, filter string, verbose bool) error
RunSelfTest executes all local tools in the registry and reports results. Returns a non-nil error if any tool FAILs, so the caller can decide the exit code.
func SeverityRank ¶
SeverityRank returns a numeric rank for severity comparison. Higher rank = more severe.
func TruncateForRecord ¶
TruncateForRecord truncates tool output for storage in DiagnoseRecord. Allows a larger budget than TruncateOutput since records are for audit.
func TruncateOutput ¶
TruncateOutput ensures a tool's output doesn't exceed the maximum size for sending to the AI. Uses UTF-8-safe truncation.
func TruncateUTF8 ¶
TruncateUTF8 truncates s to at most maxBytes bytes without breaking multi-byte UTF-8 characters. Exported for reuse across packages.
Types ¶
type AIRecord ¶
type AIRecord struct {
Model string `json:"model"`
TotalRounds int `json:"total_rounds"`
InputTokens int `json:"input_tokens"`
OutputTokens int `json:"output_tokens"`
}
AIRecord stores AI model usage info for this diagnosis.
type AccessorFactory ¶
AccessorFactory creates a shared Accessor for a remote plugin. The engine calls this once per DiagnoseSession.
type AlertRecord ¶
type AlertRecord struct {
Plugin string `json:"plugin"`
Target string `json:"target"`
Checks []CheckSnapshot `json:"checks"`
}
AlertRecord stores the alert context that triggered the diagnosis.
type ChatStream ¶ added in v0.1.2
type ChatStream struct {
// contains filtered or unexported fields
}
ChatStream manages a multi-turn chat conversation with history. Unlike DiagnoseEngine which processes single diagnosis requests, ChatStream maintains conversation state across multiple user messages.
func NewChatStream ¶ added in v0.1.2
func NewChatStream(cfg ChatStreamConfig) *ChatStream
NewChatStream creates a chat stream with the given configuration.
func (*ChatStream) HandleMessage ¶ added in v0.1.2
func (s *ChatStream) HandleMessage(ctx context.Context, input string) (reply string, usage aiclient.Usage, err error)
HandleMessage processes one user message through the conversation. On error, the user message is rolled back from history.
func (*ChatStream) Messages ¶ added in v0.1.2
func (s *ChatStream) Messages() []aiclient.Message
Messages returns the current message history. Useful for inspection or persistence.
func (*ChatStream) Reset ¶ added in v0.1.2
func (s *ChatStream) Reset()
Reset clears the conversation history except for the system prompt.
type ChatStreamConfig ¶ added in v0.1.2
type ChatStreamConfig struct {
FC *aiclient.FailoverClient
Registry *ToolRegistry
ToolTimeout time.Duration
SystemPrompt string
AllowShell bool
ShellExecutor ShellExecutor
ProgressCallback ProgressCallback
ContextWindowLimit int
GatewayMetadata aiclient.GatewayMetadata
}
ChatStreamConfig configures a new ChatStream.
type CheckSnapshot ¶
type CheckSnapshot struct {
Check string `json:"check"`
Status string `json:"status"`
CurrentValue string `json:"current_value"`
ThresholdDesc string `json:"threshold_desc,omitempty"`
Description string `json:"description"`
}
CheckSnapshot captures the current state of one alerting check at the moment the diagnosis is triggered. Produced by Gather(), consumed by the DiagnoseEngine.
func ExtractCheckSnapshot ¶
func ExtractCheckSnapshot(event *types.Event) CheckSnapshot
ExtractCheckSnapshot builds a CheckSnapshot from an event's labels.
type DiagnoseAggregator ¶
type DiagnoseAggregator struct {
// contains filtered or unexported fields
}
DiagnoseAggregator collects alerts for the same target within a short time window, then submits one aggregated DiagnoseRequest to the engine.
func GlobalAggregator ¶
func GlobalAggregator() *DiagnoseAggregator
GlobalAggregator returns the singleton aggregator, or nil if not initialized.
func NewDiagnoseAggregator ¶
func NewDiagnoseAggregator(engine *DiagnoseEngine, window time.Duration) *DiagnoseAggregator
NewDiagnoseAggregator creates an aggregator with the given window duration.
func (*DiagnoseAggregator) Shutdown ¶
func (a *DiagnoseAggregator) Shutdown()
Shutdown cancels all pending aggregation timers.
func (*DiagnoseAggregator) Submit ¶
func (a *DiagnoseAggregator) Submit(event *types.Event, snapshot CheckSnapshot, pluginName string, instanceRef any, diagnoseConfig config.DiagnoseConfig)
Submit is called from the alerting engine when an alert event is produced. It aggregates events for the same (plugin, target) within the time window.
type DiagnoseEngine ¶
type DiagnoseEngine struct {
// contains filtered or unexported fields
}
DiagnoseEngine is the central coordinator for AI-powered diagnosis.
func GlobalEngine ¶
func GlobalEngine() *DiagnoseEngine
GlobalEngine returns the singleton engine, or nil if not initialized.
func NewDiagnoseEngine ¶
func NewDiagnoseEngine(registry *ToolRegistry, cfg config.AIConfig) *DiagnoseEngine
NewDiagnoseEngine creates a new engine from global config.
func (*DiagnoseEngine) Registry ¶
func (e *DiagnoseEngine) Registry() *ToolRegistry
Registry returns the engine's tool registry.
func (*DiagnoseEngine) ReleaseSem ¶
func (e *DiagnoseEngine) ReleaseSem()
ReleaseSem releases one concurrency slot previously acquired via TrySem.
func (*DiagnoseEngine) RunDiagnose ¶
func (e *DiagnoseEngine) RunDiagnose(req *DiagnoseRequest) *DiagnoseRecord
RunDiagnose is the goroutine entry point. It includes panic recovery, session lifecycle, cooldown update, and state persistence. Returns the DiagnoseRecord so callers (e.g. inspect CLI) can inspect results.
func (*DiagnoseEngine) RunDiagnoseStreaming ¶
func (e *DiagnoseEngine) RunDiagnoseStreaming(ctx context.Context, req *DiagnoseRequest, cb StreamCallback) (report string, err error)
RunDiagnoseStreaming runs a diagnosis with streaming output via cb. Unlike RunDiagnose, it uses the caller-provided ctx (can be cancelled externally), does not manage sem/cooldown/state, and does not save records to disk. Intended for remote sessions where the server manages lifecycle.
func (*DiagnoseEngine) Shutdown ¶
func (e *DiagnoseEngine) Shutdown()
Shutdown cancels all in-flight diagnoses for graceful termination.
func (*DiagnoseEngine) State ¶
func (e *DiagnoseEngine) State() *DiagnoseState
State returns the engine's state for external inspection.
func (*DiagnoseEngine) Submit ¶
func (e *DiagnoseEngine) Submit(req *DiagnoseRequest)
Submit attempts to schedule a diagnosis. It respects cooldown, daily token limits, and concurrency bounds. Returns immediately; actual diagnosis runs in a goroutine.
func (*DiagnoseEngine) TrySem ¶
func (e *DiagnoseEngine) TrySem() bool
TrySem attempts to acquire a concurrency slot (shared with local diagnoses). Returns true if acquired, false if all slots are occupied.
type DiagnoseRecord ¶
type DiagnoseRecord struct {
ID string `json:"id"`
Mode string `json:"mode"` // "alert" or "inspect"
Status string `json:"status"` // success, failed, cancelled, timeout
Error string `json:"error,omitempty"`
CreatedAt time.Time `json:"created_at"`
DurationMs int64 `json:"duration_ms"`
Alert AlertRecord `json:"alert"`
AI AIRecord `json:"ai"`
Rounds []RoundRecord `json:"rounds"`
Report string `json:"report,omitempty"`
}
DiagnoseRecord stores the full trace of a single diagnosis run, written as a JSON file under state.d/diagnoses/.
func NewDiagnoseRecord ¶
func NewDiagnoseRecord(req *DiagnoseRequest) *DiagnoseRecord
NewDiagnoseRecord creates a DiagnoseRecord from a DiagnoseRequest, pre-populating the alert context and timestamp.
func (*DiagnoseRecord) FilePath ¶
func (r *DiagnoseRecord) FilePath() string
FilePath returns the absolute path where this record is (or will be) stored.
func (*DiagnoseRecord) Save ¶
func (r *DiagnoseRecord) Save() error
Save writes the DiagnoseRecord atomically (temp file + rename) to the diagnoses directory.
type DiagnoseRequest ¶
type DiagnoseRequest struct {
Mode string // "alert" (default) or "inspect"
Events []*types.Event
Plugin string
Target string
RuntimeOS string
Checks []CheckSnapshot
InstanceRef any
Timeout time.Duration
Cooldown time.Duration
Descriptions string // remote diagnose: textual alert descriptions for AI context
OnProgress ProgressCallback // optional; nil means no progress output
}
DiagnoseRequest is produced by the DiagnoseAggregator after collecting alerts for the same target within the aggregation window. For inspect mode, Events and Checks are nil.
type DiagnoseSession ¶
type DiagnoseSession struct {
Accessor any // shared remote Accessor, created by the plugin's factory
Record *DiagnoseRecord
StartTime time.Time
// contains filtered or unexported fields
}
DiagnoseSession manages the lifecycle of a single diagnosis run. All remote tool calls within the same diagnosis share one Accessor (TCP connection).
func (*DiagnoseSession) Close ¶
func (s *DiagnoseSession) Close()
Close releases the shared Accessor if it implements io.Closer.
type DiagnoseState ¶
type DiagnoseState struct {
Date string `json:"date"`
InputTokens int `json:"input_tokens"`
OutputTokens int `json:"output_tokens"`
Cooldowns map[string]int64 `json:"cooldowns"` // "plugin::target" → unix timestamp
// contains filtered or unexported fields
}
DiagnoseState tracks daily token usage and per-target cooldowns. Persisted to state.d/diagnose_state.json for restart resilience.
func NewDiagnoseState ¶
func NewDiagnoseState() *DiagnoseState
NewDiagnoseState creates a fresh state for today.
func (*DiagnoseState) AddTokens ¶
func (s *DiagnoseState) AddTokens(input, output int)
func (*DiagnoseState) FormatUsage ¶
func (s *DiagnoseState) FormatUsage() string
FormatUsage returns a human-readable summary of daily token usage.
func (*DiagnoseState) IsCooldownActive ¶
func (s *DiagnoseState) IsCooldownActive(plugin, target string) bool
func (*DiagnoseState) IsDailyLimitReached ¶
func (s *DiagnoseState) IsDailyLimitReached(limit int) bool
IsDailyLimitReached checks if the daily token budget has been exhausted.
func (*DiagnoseState) Load ¶
func (s *DiagnoseState) Load()
Load reads state from state.d/diagnose_state.json. Missing file is not an error.
func (*DiagnoseState) TotalTokens ¶
func (s *DiagnoseState) TotalTokens() int
func (*DiagnoseState) UpdateCooldown ¶
func (s *DiagnoseState) UpdateCooldown(plugin, target string, duration time.Duration)
type DiagnoseTool ¶
type DiagnoseTool struct {
Name string `json:"name"`
Description string `json:"description"`
Parameters []ToolParam `json:"parameters,omitempty"`
Scope ToolScope `json:"-"`
SupportedOS []string `json:"-"`
Execute func(ctx context.Context, args map[string]string) (string, error) `json:"-"`
RemoteExecute func(ctx context.Context, session *DiagnoseSession, args map[string]string) (string, error) `json:"-"`
}
DiagnoseTool defines a diagnostic tool that the AI can invoke.
func (DiagnoseTool) SupportsOS ¶
func (t DiagnoseTool) SupportsOS(goos string) bool
SupportsOS reports whether the tool should be exposed on the given OS. Empty SupportedOS means all operating systems are allowed.
type ProgressCallback ¶
type ProgressCallback func(event ProgressEvent)
ProgressCallback receives progress events during a diagnosis run. A nil callback is safe; the engine simply skips the call.
type ProgressEvent ¶
type ProgressEvent struct {
Type ProgressEventType
Round int
ToolName string
ToolArgs string
Reasoning string // non-empty on AIDone when the model emits reasoning
Duration time.Duration // set on AIDone / ToolDone
ResultLen int // set on ToolDone
IsError bool // set on ToolDone
ToolOutput string // set on ToolDone; the tool result content
}
ProgressEvent carries details about one progress milestone in a diagnosis run.
type ProgressEventType ¶
type ProgressEventType int
ProgressEventType identifies the kind of progress event fired by the engine.
const ( ProgressAIStart ProgressEventType = iota // AI call starting (spinner opportunity) ProgressAIDone // AI call completed ProgressToolStart // Tool invocation starting ProgressToolDone // Tool invocation completed )
type RoundRecord ¶
type RoundRecord struct {
Round int `json:"round"`
ToolCalls []ToolCallRecord `json:"tool_calls,omitempty"`
AIReasoning string `json:"ai_reasoning,omitempty"`
}
RoundRecord stores one round of AI interaction.
type SelfTestResult ¶
type SelfTestResult struct {
Category string
Tool string
Status string // PASS, FAIL, SKIP, WARN
Duration time.Duration
OutSize int
Message string
Args map[string]string
}
SelfTestResult holds the outcome of testing one tool.
type ShellExecutor ¶ added in v0.1.2
type ShellExecutor interface {
// ExecuteShell executes a shell command with approval flow.
// Returns (output, approved, error).
// approved=false indicates user rejected execution.
ExecuteShell(ctx context.Context, command string, timeout time.Duration) (string, bool, error)
}
ShellExecutor is an interface for executing shell commands during chat. Implementations must handle user approval and command editing.
type StreamCallback ¶
StreamCallback receives streaming output during a remote diagnosis run. Called with incremental deltas; done=true on the final call. A nil callback is safe; the engine simply skips the call.
type ToolCallRecord ¶
type ToolCallRecord struct {
Name string `json:"name"`
Args map[string]string `json:"args,omitempty"`
Result string `json:"result"`
DurationMs int64 `json:"duration_ms"`
}
ToolCallRecord stores one tool invocation within a round.
type ToolCategory ¶
type ToolCategory struct {
Name string // "redis", "disk", "cpu"
Plugin string // source plugin name
Description string // one-line description for AI
Scope ToolScope // local or remote
Tools []DiagnoseTool // tools in this category
}
ToolCategory groups related diagnostic tools under a plugin.
type ToolParam ¶
type ToolParam struct {
Name string `json:"name"`
Type string `json:"type"` // "string", "int"
Description string `json:"description"`
Required bool `json:"required"`
}
ToolParam describes a single parameter accepted by a DiagnoseTool.
type ToolRegistry ¶
type ToolRegistry struct {
// contains filtered or unexported fields
}
ToolRegistry manages all diagnostic tools registered by plugins. Thread-safe for concurrent reads; writes happen only at startup.
func NewToolRegistry ¶
func NewToolRegistry() *ToolRegistry
NewToolRegistry creates an empty registry.
func (*ToolRegistry) ByPlugin ¶
func (r *ToolRegistry) ByPlugin(plugin string) []DiagnoseTool
ByPlugin returns all tools registered under the given plugin/category name.
func (*ToolRegistry) ByPluginForOS ¶
func (r *ToolRegistry) ByPluginForOS(plugin, goos string) []DiagnoseTool
ByPluginForOS returns tools under the given plugin/category that are supported on the specified operating system.
func (*ToolRegistry) Categories ¶
func (r *ToolRegistry) Categories() []string
Categories returns a sorted snapshot of all category names.
func (*ToolRegistry) CategoriesWithTools ¶
func (r *ToolRegistry) CategoriesWithTools() []ToolCategory
CategoriesWithTools returns all categories with their tools, sorted by category name.
func (*ToolRegistry) CreateAccessor ¶
func (r *ToolRegistry) CreateAccessor(ctx context.Context, plugin string, instanceRef any) (any, error)
CreateAccessor calls the registered factory for the given plugin.
func (*ToolRegistry) Get ¶
func (r *ToolRegistry) Get(name string) (*DiagnoseTool, bool)
Get returns a tool by name.
func (*ToolRegistry) HasAccessorFactory ¶
func (r *ToolRegistry) HasAccessorFactory(plugin string) bool
HasAccessorFactory reports whether a plugin has a registered accessor factory.
func (*ToolRegistry) ListAllTools ¶
func (r *ToolRegistry) ListAllTools() string
ListAllTools returns a compact catalog of every registered tool, grouped by category and sorted alphabetically. Designed for injection into AI prompts so the model can call tools directly without a discovery round-trip.
func (*ToolRegistry) ListCategories ¶
func (r *ToolRegistry) ListCategories() string
ListCategories returns a formatted string of all categories for the AI, sorted alphabetically for deterministic output.
func (*ToolRegistry) ListCategoriesForOS ¶
func (r *ToolRegistry) ListCategoriesForOS(goos string) string
ListCategoriesForOS returns a formatted string of categories that support the specified operating system.
func (*ToolRegistry) ListToolCatalogSmart ¶
func (r *ToolRegistry) ListToolCatalogSmart() string
ListToolCatalogSmart returns a hybrid catalog for diagnose prompts:
- Built-in tool categories: full detail (name, params, description)
- MCP categories (prefix "mcp:"): summary only (name, tool count, description)
This keeps the prompt concise when many MCP tools are registered while still allowing zero-roundtrip access to built-in tools.
func (*ToolRegistry) ListToolCatalogSmartForOS ¶
func (r *ToolRegistry) ListToolCatalogSmartForOS(goos string) string
ListToolCatalogSmartForOS returns the tool catalog filtered by supported OS.
func (*ToolRegistry) ListTools ¶
func (r *ToolRegistry) ListTools(category string) string
ListTools returns a formatted string of tools in a category for the AI.
func (*ToolRegistry) ListToolsForOS ¶
func (r *ToolRegistry) ListToolsForOS(category, goos string) string
ListToolsForOS returns tools in a category filtered by supported OS.
func (*ToolRegistry) Register ¶
func (r *ToolRegistry) Register(category string, tool DiagnoseTool)
Register adds a tool under the given category. If the category doesn't exist, it is created with the provided scope and description. Duplicate tool names are logged and skipped (programming error, not runtime condition).
func (*ToolRegistry) RegisterAccessorFactory ¶
func (r *ToolRegistry) RegisterAccessorFactory(plugin string, factory AccessorFactory)
RegisterAccessorFactory registers a factory that creates a shared Accessor for remote plugin tools within a DiagnoseSession.
func (*ToolRegistry) RegisterCategory ¶
func (r *ToolRegistry) RegisterCategory(name, plugin, description string, scope ToolScope)
RegisterCategory registers or updates a category's metadata.
func (*ToolRegistry) ToolCount ¶
func (r *ToolRegistry) ToolCount() int
ToolCount returns the total number of registered tools.
func (*ToolRegistry) ToolSupportedOn ¶
func (r *ToolRegistry) ToolSupportedOn(name, goos string) bool
ToolSupportedOn reports whether the named tool should be available on the specified operating system.