Documentation
¶
Overview ¶
Package heimdall provides Heimdall - the cognitive guardian for NornicDB.
Package heimdall provides the Heimdall cognitive guardian for NornicDB. This file provides the CGO-enabled generator using localllm.
Package heimdall - Ollama-backed Generator for chat completions. When Heimdall provider is "ollama", NewManager uses this implementation.
Package heimdall - OpenAI-backed Generator for chat completions. When Heimdall provider is "openai", NewManager uses this implementation.
Package heimdall provides comprehensive metrics collection for the cognitive guardian.
Package heimdall provides Heimdall - the cognitive guardian for NornicDB.
Heimdall is named after the all-seeing Norse god who guards Bifröst. Like its namesake, Heimdall watches over NornicDB's cognitive subsystems, providing SLM (Small Language Model) management and plugin architecture.
Heimdall Plugins are a DISTINCT plugin type from regular NornicDB plugins. They specifically enable cognitive database features that the SLM manages.
Plugin Type: HeimdallPlugin
Unlike regular plugins (which provide Cypher functions), Heimdall plugins provide actions that the SLM can invoke based on user chat requests.
How it works:
- User sends chat message: "Check for graph anomalies"
- SLM interprets intent and maps to registered action: "heimdall_anomaly_detect"
- Action handler is invoked with context
- Results returned to user via chat
Plugin Loading:
Heimdall plugins are loaded from NORNICDB_HEIMDALL_PLUGINS_DIR (separate from regular plugins). Each .so plugin must export a "Plugin" variable of type HeimdallPlugin.
Built-in Heimdall Plugins:
Core Heimdall plugins ship with NornicDB:
- watcher: SLM management (heimdall_watcher_*) - the core guardian
- anomaly: Graph anomaly detection (heimdall_anomaly_*)
- health: Runtime health diagnosis (heimdall_health_*)
- curator: Memory curation (heimdall_curator_*)
- optimizer: Query optimization (heimdall_optimizer_*)
Custom Heimdall Plugins:
Example implementing HeimdallPlugin interface:
package main
import "github.com/orneryd/nornicdb/pkg/heimdall"
// MySubsystem implements heimdall.HeimdallPlugin
type MySubsystem struct{}
func (p *MySubsystem) Name() string { return "mysubsystem" }
func (p *MySubsystem) Version() string { return "1.0.0" }
func (p *MySubsystem) Type() string { return "heimdall" } // MUST return "heimdall"
func (p *MySubsystem) Actions() map[string]heimdall.ActionFunc {
return map[string]heimdall.ActionFunc{
"analyze": {
Handler: p.Analyze,
Description: "Analyze custom metrics",
Category: "analysis",
},
}
}
func (p *MySubsystem) Analyze(ctx heimdall.ActionContext) (*heimdall.ActionResult, error) {
// Your implementation
return &heimdall.ActionResult{Success: true, Message: "Done"}, nil
}
// Export as HeimdallPlugin type
var Plugin heimdall.HeimdallPlugin = &MySubsystem{}
Package heimdall provides RBAC context helpers for Bifrost request context. The server attaches RBAC via auth.WithRequest*; heimdall reads via these helpers which delegate to auth.Request*FromContext so the same context works for Bifrost and GraphQL.
Package heimdall provides Heimdall - the cognitive guardian for NornicDB.
Heimdall enables NornicDB to run reasoning SLMs alongside embedding models for cognitive database capabilities including anomaly detection, runtime diagnosis, and memory curation.
The Heimdall subsystem uses standard protocols:
- WebSocket (WSS) for real-time streaming chat
- Server-Sent Events (SSE) as fallback
- JSON message format (OpenAI-compatible)
- JWT authentication from existing auth system
Index ¶
- Constants
- Variables
- func ActionCatalog() map[string][]ActionFunc
- func ActionPrompt() string
- func BuildPrompt(messages []ChatMessage) string
- func CallPostExecuteHooks(ctx *PostExecuteContext)
- func CallPrePromptHooks(ctx *PromptContext)
- func CallSynthesisHooks(ctx *SynthesisContext) string
- func DatabaseAccessModeFromContext(ctx context.Context) auth.DatabaseAccessMode
- func EmitDatabaseEvent(event *DatabaseEvent)
- func EmitNodeEvent(eventType DatabaseEventType, nodeID string, labels []string, ...)
- func EmitQueryEvent(eventType DatabaseEventType, query string, params map[string]interface{}, ...)
- func EmitRelationshipEvent(eventType DatabaseEventType, relID, relType, sourceID, targetID string, ...)
- func EstimateTokens(text string) int
- func EstimateToolRoundMessagesTokens(messages []ToolRoundMessage) int
- func FormatActionResultForModel(result *ActionResult) string
- func FormatInMemoryToolResult(raw interface{}, err error) string
- func HeimdallPluginsInitialized() bool
- func ListHeimdallActions() []string
- func LoadHeimdallPluginsFromDir(dir string, ctx SubsystemContext) error
- func MaxContextTokens() int
- func MaxSystemPromptTokens() int
- func MaxUserMessageTokens() int
- func PrincipalRolesFromContext(ctx context.Context) []string
- func RegisterBuiltinAction(action ActionFunc)
- func RegisterHeimdallProvider(name string, factory func(Config) (Generator, error))
- func ResetSubsystemManagerForTests()
- func ResolvedAccessResolverFromContext(ctx context.Context) func(string) auth.ResolvedAccess
- func SetTokenBudget(flags FeatureFlagsSource)
- func StartEventDispatcher()
- func StopEventDispatcher()
- type ActionContext
- type ActionFunc
- type ActionInvoker
- type ActionOpcode
- type ActionResponse
- type ActionResult
- type AsyncEngineStats
- type Bifrost
- func (b *Bifrost) Broadcast(msg string) error
- func (b *Bifrost) ConnectionCount() int
- func (b *Bifrost) IsConnected() bool
- func (b *Bifrost) RegisterClient(id string, w http.ResponseWriter, f http.Flusher)
- func (b *Bifrost) RequestConfirmation(action string) (bool, error)
- func (b *Bifrost) SendMessage(msg string) error
- func (b *Bifrost) SendNotification(notifType, title, message string) error
- func (b *Bifrost) Stats() map[string]interface{}
- func (b *Bifrost) UnregisterClient(id string)
- type BifrostBridge
- type BifrostClient
- type BifrostMessage
- type CacheMetrics
- type CancellationInfo
- type ChatChoice
- type ChatMessage
- type ChatRequest
- type ChatResponse
- type ChatToolCallWire
- type ChatToolDefinition
- type ChatToolDefinitionFunction
- type ChatToolFunctionWire
- type ChatUsage
- type ClusterStats
- type Config
- type DatabaseEvent
- type DatabaseEventHook
- type DatabaseEventType
- type DatabaseMetrics
- type DatabaseMetricsSource
- type DatabaseRouter
- type DatabaseStats
- type DefaultLogger
- type DiscoverResult
- type Embedder
- type EmbeddingMetrics
- type FeatureFlags
- type FeatureFlagsSource
- type FullLifecycleHook
- type GPUManagerStats
- type GPUMetrics
- type GenerateParams
- type Generator
- type GeneratorLoader
- type GeneratorWithTools
- type GraphEdge
- type Handler
- type HeimdallInvoker
- type HeimdallPlugin
- type InMemoryToolRunner
- type LiveHeimdallInvoker
- func (h *LiveHeimdallInvoker) InvokeAction(ctx context.Context, action string, params map[string]interface{}) (*ActionResult, error)
- func (h *LiveHeimdallInvoker) InvokeActionAsync(action string, params map[string]interface{})
- func (h *LiveHeimdallInvoker) SendPrompt(ctx context.Context, prompt string) (*ActionResult, error)
- func (h *LiveHeimdallInvoker) SendPromptAsync(prompt string)
- func (h *LiveHeimdallInvoker) SendRawPrompt(ctx context.Context, prompt string) (*ActionResult, error)
- type LoadedHeimdallPlugin
- type MCPTool
- type Manager
- func (m *Manager) Chat(ctx context.Context, req ChatRequest) (*ChatResponse, error)
- func (m *Manager) Close() error
- func (m *Manager) Generate(ctx context.Context, prompt string, params GenerateParams) (string, error)
- func (m *Manager) GenerateStream(ctx context.Context, prompt string, params GenerateParams, ...) error
- func (m *Manager) GenerateWithTools(ctx context.Context, messages []ToolRoundMessage, tools []MCPTool, ...) (content string, toolCalls []ParsedToolCall, err error)
- func (m *Manager) ModelPath() string
- func (m *Manager) Stats() ManagerStats
- func (m *Manager) SupportsTools() bool
- type ManagerStats
- type MetricsCollector
- type MetricsReader
- type ModelInfo
- type ModelType
- type NoOpBifrost
- func (n *NoOpBifrost) Broadcast(msg string) error
- func (n *NoOpBifrost) ConnectionCount() int
- func (n *NoOpBifrost) IsConnected() bool
- func (n *NoOpBifrost) RequestConfirmation(action string) (bool, error)
- func (n *NoOpBifrost) SendMessage(msg string) error
- func (n *NoOpBifrost) SendNotification(t, title, msg string) error
- type NoOpHeimdallInvoker
- func (n *NoOpHeimdallInvoker) InvokeAction(ctx context.Context, action string, params map[string]interface{}) (*ActionResult, error)
- func (n *NoOpHeimdallInvoker) InvokeActionAsync(action string, params map[string]interface{})
- func (n *NoOpHeimdallInvoker) SendPrompt(ctx context.Context, prompt string) (*ActionResult, error)
- func (n *NoOpHeimdallInvoker) SendPromptAsync(prompt string)
- func (n *NoOpHeimdallInvoker) SendRawPrompt(ctx context.Context, prompt string) (*ActionResult, error)
- type NodeData
- type NornicDBMetrics
- type ParsedAction
- type ParsedToolCall
- type PluginOrdering
- type PostExecuteContext
- func (p *PostExecuteContext) DrainNotifications() []QueuedNotification
- func (p *PostExecuteContext) Notify(notificationType, title, message string)
- func (p *PostExecuteContext) NotifyError(title, message string)
- func (p *PostExecuteContext) NotifyInfo(title, message string)
- func (p *PostExecuteContext) NotifySuccess(title, message string)
- func (p *PostExecuteContext) NotifyWarning(title, message string)
- type PostExecuteHook
- type PreExecuteContext
- func (p *PreExecuteContext) Cancel(reason string, cancelledBy string)
- func (p *PreExecuteContext) CancelReason() string
- func (p *PreExecuteContext) Cancelled() bool
- func (p *PreExecuteContext) CancelledBy() string
- func (p *PreExecuteContext) DrainNotifications() []QueuedNotification
- func (p *PreExecuteContext) Notify(notificationType, title, message string)
- func (p *PreExecuteContext) NotifyError(title, message string)
- func (p *PreExecuteContext) NotifyInfo(title, message string)
- func (p *PreExecuteContext) NotifyProgress(title, message string)
- func (p *PreExecuteContext) NotifyWarning(title, message string)
- func (p *PreExecuteContext) SetBifrost(b BifrostBridge)
- type PreExecuteHook
- type PreExecuteResult
- type PrePromptHook
- type PromptBudgetInfo
- type PromptContext
- func (p *PromptContext) Broadcast(message string)
- func (p *PromptContext) BuildFinalPrompt() string
- func (p *PromptContext) BuildFinalPromptForTools() string
- func (p *PromptContext) Cancel(reason string, cancelledBy string)
- func (p *PromptContext) CancelReason() string
- func (p *PromptContext) Cancelled() bool
- func (p *PromptContext) CancelledBy() string
- func (p *PromptContext) DrainNotifications() []QueuedNotification
- func (p *PromptContext) EstimatedSystemTokens() int
- func (p *PromptContext) GetBudgetInfo() PromptBudgetInfo
- func (p *PromptContext) Notify(notificationType, title, message string)
- func (p *PromptContext) NotifyError(title, message string)
- func (p *PromptContext) NotifyInfo(title, message string)
- func (p *PromptContext) NotifyProgress(title, message string)
- func (p *PromptContext) NotifyWarning(title, message string)
- func (p *PromptContext) SendMessage(message string)
- func (p *PromptContext) SetBifrost(b BifrostBridge)
- func (p *PromptContext) ValidateTokenBudget() error
- type PromptExample
- type QueryCacheStats
- type QueryDatabase
- type QueryExecutor
- func (e *QueryExecutor) Discover(ctx context.Context, query string, nodeTypes []string, limit int, depth int) (*DiscoverResult, error)
- func (e *QueryExecutor) Query(ctx context.Context, cypher string, params map[string]interface{}) ([]map[string]interface{}, error)
- func (e *QueryExecutor) Stats() DatabaseStats
- type QueryMetrics
- type QueuedNotification
- type RealMetricsReader
- type RelatedNode
- type RuntimeMetrics
- type SchemaManagerStats
- type SearchResult
- type SemanticSearchResult
- type SemanticSearcher
- type ServerMetrics
- type ServerMetricsSource
- type StorageMetrics
- type StreamEvent
- type SubsystemContext
- type SubsystemEvent
- type SubsystemHealth
- type SubsystemLogger
- type SubsystemManager
- func (m *SubsystemManager) AllHealth() map[string]SubsystemHealth
- func (m *SubsystemManager) AllSummaries() map[string]string
- func (m *SubsystemManager) GetAction(name string) (ActionFunc, bool)
- func (m *SubsystemManager) GetPlugin(name string) (HeimdallPlugin, bool)
- func (m *SubsystemManager) RegisterPlugin(p HeimdallPlugin, path string, builtin bool) error
- func (m *SubsystemManager) SetContext(ctx SubsystemContext)
- func (m *SubsystemManager) ShutdownAll() error
- func (m *SubsystemManager) StartAll() error
- func (m *SubsystemManager) StopAll() error
- type SubsystemStatus
- type SynthesisContext
- type SynthesisHook
- type TokenBudget
- type ToolRoundMessage
- type WALStats
Constants ¶
const ( // DefaultMaxContextTokens is the default context window (8K for memory efficiency) DefaultMaxContextTokens = 8192 // DefaultMaxSystemPromptTokens is the default system prompt budget DefaultMaxSystemPromptTokens = 6000 // DefaultMaxUserMessageTokens is the default user message budget DefaultMaxUserMessageTokens = 2000 // TokensPerChar is a rough estimate (~4 chars per token for English) TokensPerChar = 0.25 )
Token budget constants for Heimdall - DEFAULT values (can be overridden via config) These are used when config values are 0 or not provided. Configure via environment variables:
- NORNICDB_HEIMDALL_MAX_CONTEXT_TOKENS (default: 8192)
- NORNICDB_HEIMDALL_MAX_SYSTEM_TOKENS (default: 6000)
- NORNICDB_HEIMDALL_MAX_USER_TOKENS (default: 2000)
const AgenticSystemPromptTools = `` /* 584-byte string literal not displayed */
AgenticSystemPromptTools is the short system prompt when using native tools (OpenAI/Ollama). The model receives tools via the API; no need to list actions in the prompt.
const CypherPrimer = `` /* 1948-byte string literal not displayed */
CypherPrimer is a comprehensive Cypher query reference for Heimdall.
const MaxAgenticRounds = 10
MaxAgenticRounds is the maximum number of tool-call rounds in the agentic loop. Prevents runaway when the model keeps requesting tools.
const PluginTypeHeimdall = "heimdall"
PluginType identifies the type of plugin.
Variables ¶
var DefaultActionInputSchema = []byte(`{"type":"object","properties":{},"additionalProperties":true}`)
DefaultActionInputSchema is the MCP-compatible JSON Schema when an action does not declare parameters (type "object" with no required properties).
Functions ¶
func ActionCatalog ¶
func ActionCatalog() map[string][]ActionFunc
ActionCatalog returns all actions grouped by category for display.
func BuildPrompt ¶
func BuildPrompt(messages []ChatMessage) string
BuildPrompt converts chat messages to a prompt string. Uses ChatML format for instruction-tuned models.
func CallPostExecuteHooks ¶
func CallPostExecuteHooks(ctx *PostExecuteContext)
CallPostExecuteHooks calls PostExecute on all plugins that implement PostExecuteHook. Plugins that don't implement the hook are silently skipped. This is fire-and-forget - runs asynchronously using a bounded worker pool.
func CallPrePromptHooks ¶
func CallPrePromptHooks(ctx *PromptContext)
CallPrePromptHooks calls PrePrompt on all plugins that implement PrePromptHook. Plugins that don't implement the hook are silently skipped. Returns the first cancellation encountered, or nil if no cancellations.
func CallSynthesisHooks ¶
func CallSynthesisHooks(ctx *SynthesisContext) string
CallSynthesisHooks calls Synthesize on all plugins that implement SynthesisHook. The first plugin to return a non-empty response wins. If no plugin provides a response, returns empty string (caller should use default synthesis). This is synchronous with a timeout to ensure responsive UX.
func DatabaseAccessModeFromContext ¶
func DatabaseAccessModeFromContext(ctx context.Context) auth.DatabaseAccessMode
DatabaseAccessModeFromContext returns the principal's DatabaseAccessMode from context, or nil.
func EmitDatabaseEvent ¶
func EmitDatabaseEvent(event *DatabaseEvent)
EmitDatabaseEvent sends a database event to all registered plugins. This is non-blocking - events are queued for async delivery. If the queue is full, the event is dropped (with a warning).
func EmitNodeEvent ¶
func EmitNodeEvent(eventType DatabaseEventType, nodeID string, labels []string, props map[string]interface{})
EmitNodeEvent is a convenience function for emitting node-related events.
func EmitQueryEvent ¶
func EmitQueryEvent(eventType DatabaseEventType, query string, params map[string]interface{}, duration time.Duration, rowsAffected int64, err error)
EmitQueryEvent is a convenience function for emitting query-related events.
func EmitRelationshipEvent ¶
func EmitRelationshipEvent(eventType DatabaseEventType, relID, relType, sourceID, targetID string, props map[string]interface{})
EmitRelationshipEvent is a convenience function for emitting relationship-related events.
func EstimateTokens ¶
EstimateTokens provides a rough token count estimate for a string. Uses ~4 chars per token which is typical for English text. For exact counts, use the actual tokenizer.
func EstimateToolRoundMessagesTokens ¶
func EstimateToolRoundMessagesTokens(messages []ToolRoundMessage) int
EstimateToolRoundMessagesTokens returns a rough token count for a slice of tool-round messages. Used to stay within model context limits (e.g. OpenAI 128K) before sending.
func FormatActionResultForModel ¶
func FormatActionResultForModel(result *ActionResult) string
FormatActionResultForModel formats an action result for the LLM to read (any provider). Used in the agentic loop so the model can infer and format the final response.
func FormatInMemoryToolResult ¶
FormatInMemoryToolResult formats a raw tool result or error for the LLM (tool message content).
func HeimdallPluginsInitialized ¶
func HeimdallPluginsInitialized() bool
HeimdallPluginsInitialized returns true if SLM plugins have been loaded.
func ListHeimdallActions ¶
func ListHeimdallActions() []string
ListHeimdallActions returns all registered SLM action names.
func LoadHeimdallPluginsFromDir ¶
func LoadHeimdallPluginsFromDir(dir string, ctx SubsystemContext) error
LoadHeimdallPluginsFromDir scans a directory for .so files and loads them. Called at startup if NORNICDB_HEIMDALL_PLUGINS_DIR is set.
func MaxContextTokens ¶
func MaxContextTokens() int
MaxContextTokens returns the configured max context tokens.
func MaxSystemPromptTokens ¶
func MaxSystemPromptTokens() int
MaxSystemPromptTokens returns the configured max system prompt tokens.
func MaxUserMessageTokens ¶
func MaxUserMessageTokens() int
MaxUserMessageTokens returns the configured max user message tokens.
func PrincipalRolesFromContext ¶
PrincipalRolesFromContext returns the principal's roles from the request context, or nil.
func RegisterBuiltinAction ¶
func RegisterBuiltinAction(action ActionFunc)
RegisterBuiltinAction registers a built-in action (not from .so plugin). Used to register core actions without requiring external plugins.
func RegisterHeimdallProvider ¶
RegisterHeimdallProvider registers a remote provider (openai, ollama). Called from generator_* init().
func ResetSubsystemManagerForTests ¶
func ResetSubsystemManagerForTests()
ResetSubsystemManagerForTests clears the global subsystem manager singleton. It is intended for test isolation when separate test cases need a fresh registration state for Heimdall plugins.
func ResolvedAccessResolverFromContext ¶
func ResolvedAccessResolverFromContext(ctx context.Context) func(string) auth.ResolvedAccess
ResolvedAccessResolverFromContext returns the ResolvedAccess resolver from context, or nil.
func SetTokenBudget ¶
func SetTokenBudget(flags FeatureFlagsSource)
SetTokenBudget configures the token budget from feature flags. Call this during initialization to apply config values.
func StartEventDispatcher ¶
func StartEventDispatcher()
StartEventDispatcher starts the background event dispatcher. This should be called when Heimdall is initialized.
func StopEventDispatcher ¶
func StopEventDispatcher()
StopEventDispatcher stops the background event dispatcher.
Types ¶
type ActionContext ¶
type ActionContext struct {
context.Context
// UserMessage is what the user said to trigger this action
UserMessage string
// Params extracted from user message by SLM
Params map[string]interface{}
// Database routes Cypher/search operations across logical databases.
Database DatabaseRouter
// Metrics provides runtime metrics
Metrics MetricsReader
// Bifrost provides communication bridge to the user
// Use this to send progress updates, request confirmation, etc.
Bifrost BifrostBridge
// PrincipalRoles are the authenticated principal's role names (from request context).
// Plugins can use this with DatabaseAccessMode and ResolvedAccess to enforce per-DB access.
PrincipalRoles []string
// DatabaseAccessMode is the principal's per-database see/access mode (from request context).
// Use CanAccessDatabase(dbName) before running Cypher against a database.
DatabaseAccessMode auth.DatabaseAccessMode
// ResolvedAccess returns per-database read/write for the principal (from request context).
// Use for mutation checks: ResolvedAccess(dbName).Write before CREATE/DELETE/SET/etc.
ResolvedAccess func(dbName string) auth.ResolvedAccess
}
ActionContext provides context for action execution. Passed to handlers when actions are invoked.
type ActionFunc ¶
type ActionFunc struct {
Name string // Full name: heimdall.{plugin}.{action} (MCP tool "name")
Handler func(ctx ActionContext) (*ActionResult, error) // The action handler
Description string // Human-readable description (MCP "description")
Category string // Grouping: monitoring, optimization, curation
// InputSchema is optional JSON Schema for parameters (MCP "inputSchema").
// When nil or empty, ActionsAsMCPTools() uses DefaultActionInputSchema.
InputSchema json.RawMessage
}
ActionFunc represents an action function provided by an SLM plugin. Aligned with MCP (Model Context Protocol) tool format: name, description, inputSchema. Invocation uses the same shape as MCP tools/call: action name + params (arguments).
func GetHeimdallAction ¶
func GetHeimdallAction(name string) (ActionFunc, bool)
GetHeimdallAction returns an action by full name (e.g., "heimdall_anomaly_detect").
type ActionInvoker ¶
type ActionInvoker struct {
// contains filtered or unexported fields
}
ActionInvoker handles action invocation from SLM responses.
func NewActionInvoker ¶
func NewActionInvoker(db DatabaseRouter, metrics MetricsReader) *ActionInvoker
NewActionInvoker creates an action invoker with database/metrics access.
func (*ActionInvoker) Invoke ¶
func (i *ActionInvoker) Invoke(ctx context.Context, parsed ParsedAction, userMessage string) (*ActionResult, error)
Invoke executes a parsed action.
type ActionOpcode ¶
type ActionOpcode int
ActionOpcode represents bounded actions the SLM can recommend. All SLM outputs map to these predefined actions for safety.
const ( ActionNone ActionOpcode = iota ActionLogInfo ActionLogWarning ActionLogError ActionThrottleQuery ActionSuggestIndex ActionMergeNodes ActionRestartWorkerPool ActionClearQueue ActionTriggerGC ActionReduceConcurrency )
type ActionResponse ¶
type ActionResponse struct {
Action ActionOpcode `json:"action"`
Confidence float64 `json:"confidence"`
Reasoning string `json:"reasoning"`
Params map[string]any `json:"params,omitempty"`
}
ActionResponse is the structured output format for SLM recommendations.
type ActionResult ¶
type ActionResult struct {
Success bool `json:"success"`
Message string `json:"message"`
Data map[string]interface{} `json:"data,omitempty"`
}
ActionResult is the outcome of action execution.
func ExecuteAction ¶
func ExecuteAction(name string, ctx ActionContext) (*ActionResult, error)
ExecuteAction executes an action by name with the given context.
type AsyncEngineStats ¶
type AsyncEngineStats interface {
Stats() (pendingWrites, totalFlushes int64)
}
AsyncEngineStats is the interface for async storage metrics.
type Bifrost ¶
type Bifrost struct {
// contains filtered or unexported fields
}
Bifrost implements BifrostBridge for real-time communication with clients. Named after the rainbow bridge that connects Asgard to other realms. Bifrost is the communication layer between Heimdall and connected UI clients.
func NewBifrost ¶
NewBifrost creates a new Bifrost bridge. Returns nil if Bifrost is not enabled in config.
func (*Bifrost) Broadcast ¶
Broadcast sends a message to all connected clients. Useful for system-wide announcements.
func (*Bifrost) ConnectionCount ¶
ConnectionCount returns the number of active Bifrost connections.
func (*Bifrost) IsConnected ¶
IsConnected returns true if there are active Bifrost connections.
func (*Bifrost) RegisterClient ¶
RegisterClient adds a new connected client.
func (*Bifrost) RequestConfirmation ¶
RequestConfirmation asks the user to confirm an action. Returns true if user confirms, false if they decline or timeout. Note: This is a simplified implementation - real implementation would need WebSocket for bidirectional communication.
func (*Bifrost) SendMessage ¶
SendMessage sends a message to all connected Bifrost clients. The message appears as a system message in the chat.
func (*Bifrost) SendNotification ¶
SendNotification sends a notification with a specific type. Types: "info", "warning", "error", "success"
func (*Bifrost) UnregisterClient ¶
UnregisterClient removes a disconnected client.
type BifrostBridge ¶
type BifrostBridge interface {
// SendMessage sends a message to connected Bifrost clients.
// The message appears as a system message in the chat.
SendMessage(msg string) error
// SendNotification sends a notification with a specific type.
// Types: "info", "warning", "error", "success"
SendNotification(notifType, title, message string) error
// Broadcast sends a message to all connected clients.
// Useful for system-wide announcements.
Broadcast(msg string) error
// RequestConfirmation asks the user to confirm an action.
// Returns true if user confirms, false if they decline or timeout.
// The action parameter describes what needs confirmation.
RequestConfirmation(action string) (bool, error)
// IsConnected returns true if there are active Bifrost connections.
IsConnected() bool
// ConnectionCount returns the number of active Bifrost connections.
ConnectionCount() int
}
BifrostBridge is the interface for plugins to communicate via Bifrost. Named after the rainbow bridge connecting Asgard to other realms.
type BifrostClient ¶
type BifrostClient struct {
ID string
Flusher http.Flusher
Writer http.ResponseWriter
ConnectedAt time.Time
LastPing time.Time
}
BifrostClient represents a connected client.
type BifrostMessage ¶
type BifrostMessage struct {
Type string `json:"type"` // "message", "notification", "confirmation"
Timestamp int64 `json:"timestamp"` // Unix timestamp
Content string `json:"content,omitempty"`
Title string `json:"title,omitempty"`
Level string `json:"level,omitempty"` // "info", "warning", "error", "success"
Data map[string]interface{} `json:"data,omitempty"`
}
BifrostMessage is a message sent through Bifrost.
type CacheMetrics ¶
type CacheMetrics struct {
Size int `json:"size"`
MaxSize int `json:"max_size"`
Hits uint64 `json:"hits"`
Misses uint64 `json:"misses"`
HitRate float64 `json:"hit_rate"`
Evictions uint64 `json:"evictions"`
TTL string `json:"ttl"`
}
CacheMetrics contains query cache statistics.
type CancellationInfo ¶
type CancellationInfo struct {
Reason string `json:"reason"`
CancelledBy string `json:"cancelled_by"`
Phase string `json:"phase"` // "PrePrompt" or "PreExecute"
}
CancellationInfo contains details about a cancelled request.
type ChatChoice ¶
type ChatChoice struct {
Index int `json:"index"`
Message *ChatMessage `json:"message,omitempty"`
Delta *ChatMessage `json:"delta,omitempty"` // For streaming
FinishReason string `json:"finish_reason,omitempty"`
}
ChatChoice represents a single completion choice.
type ChatMessage ¶
type ChatMessage struct {
Role string `json:"role"` // "system", "user", "assistant"
Content string `json:"content"`
ToolCalls []ChatToolCallWire `json:"tool_calls,omitempty"`
}
ChatMessage represents a message in the chat format (OpenAI-compatible).
type ChatRequest ¶
type ChatRequest struct {
Model string `json:"model"`
Messages []ChatMessage `json:"messages"`
Tools []ChatToolDefinition `json:"tools,omitempty"`
Stream bool `json:"stream,omitempty"`
MaxTokens int `json:"max_tokens,omitempty"`
Temperature float32 `json:"temperature,omitempty"`
TopP float32 `json:"top_p,omitempty"`
}
ChatRequest is the request format for chat completions. Compatible with OpenAI/Ollama API format.
type ChatResponse ¶
type ChatResponse struct {
ID string `json:"id"`
Object string `json:"object"` // "chat.completion" or "chat.completion.chunk"
Model string `json:"model"`
Created int64 `json:"created"`
Choices []ChatChoice `json:"choices"`
Usage *ChatUsage `json:"usage,omitempty"`
}
ChatResponse is the response format for chat completions. Fully OpenAI API compatible.
type ChatToolCallWire ¶ added in v1.0.42
type ChatToolCallWire struct {
ID string `json:"id"`
Type string `json:"type"`
Function ChatToolFunctionWire `json:"function"`
}
type ChatToolDefinition ¶ added in v1.0.42
type ChatToolDefinition struct {
Type string `json:"type,omitempty"`
Function ChatToolDefinitionFunction `json:"function"`
}
type ChatToolDefinitionFunction ¶ added in v1.0.42
type ChatToolDefinitionFunction struct {
Name string `json:"name"`
Description string `json:"description,omitempty"`
Parameters json.RawMessage `json:"parameters,omitempty"`
}
type ChatToolFunctionWire ¶ added in v1.0.42
type ChatUsage ¶
type ChatUsage struct {
PromptTokens int `json:"prompt_tokens"`
CompletionTokens int `json:"completion_tokens"`
TotalTokens int `json:"total_tokens"`
}
ChatUsage tracks token usage.
type ClusterStats ¶
type ClusterStats struct {
NumClusters int `json:"num_clusters"`
EmbeddingCount int `json:"embedding_count"`
IsClustered bool `json:"is_clustered"`
AvgClusterSize float64 `json:"avg_cluster_size,omitempty"`
Iterations int `json:"iterations,omitempty"`
}
ClusterStats contains k-means clustering statistics.
type Config ¶
type Config struct {
// Enabled controls whether Heimdall (the cognitive guardian) is active.
// When enabled, Bifrost (the chat interface) is automatically enabled.
// Default: false (opt-in feature)
Enabled bool `json:"enabled"`
// BifrostEnabled controls the Bifrost chat interface.
// Automatically set to true when Heimdall is enabled.
// Cannot be enabled independently - Bifrost requires Heimdall.
BifrostEnabled bool `json:"bifrost_enabled"`
ModelsDir string `json:"models_dir"`
Model string `json:"model"`
Provider string `json:"provider"` // local, ollama, openai, vllm
APIURL string `json:"api_url"` // for ollama/openai
APIKey string `json:"api_key"` // for openai
ContextSize int `json:"context_size"` // Context window size (single-shot, max out)
BatchSize int `json:"batch_size"` // Batch size (match context for single-shot)
MaxTokens int `json:"max_tokens"`
Temperature float32 `json:"temperature"`
GPULayers int `json:"gpu_layers"`
// Feature toggles
AnomalyDetection bool `json:"anomaly_detection"`
AnomalyInterval time.Duration `json:"anomaly_interval"`
RuntimeDiagnosis bool `json:"runtime_diagnosis"`
RuntimeInterval time.Duration `json:"runtime_interval"`
MemoryCuration bool `json:"memory_curation"`
CurationInterval time.Duration `json:"curation_interval"`
}
Config holds SLM subsystem configuration.
func ConfigFromFeatureFlags ¶
func ConfigFromFeatureFlags(flags FeatureFlagsSource) Config
ConfigFromFeatureFlags creates Heimdall config from feature flags. This is the preferred way to create Config - respects BYOM settings.
Key behavior:
- When Heimdall is enabled, Bifrost is automatically enabled
- Bifrost cannot be enabled independently (requires Heimdall)
- Heimdall is disabled by default (opt-in feature)
- Uses NORNICDB_MODELS_DIR for model location (same as embedder)
func DefaultConfig ¶
func DefaultConfig() Config
DefaultConfig returns sensible defaults. Heimdall is disabled by default (opt-in feature). When Heimdall is enabled, Bifrost is automatically enabled.
type DatabaseEvent ¶
type DatabaseEvent struct {
// Type identifies what kind of event occurred
Type DatabaseEventType `json:"type"`
// Timestamp when the event occurred
Timestamp time.Time `json:"timestamp"`
// RequestID links to the originating request (if applicable)
RequestID string `json:"request_id,omitempty"`
// NodeID for node events
NodeID string `json:"node_id,omitempty"`
// NodeLabels for node events
NodeLabels []string `json:"node_labels,omitempty"`
// RelationshipID for relationship events
RelationshipID string `json:"relationship_id,omitempty"`
// RelationshipType for relationship events
RelationshipType string `json:"relationship_type,omitempty"`
// SourceNodeID for relationship events
SourceNodeID string `json:"source_node_id,omitempty"`
// TargetNodeID for relationship events
TargetNodeID string `json:"target_node_id,omitempty"`
// Properties that were set/changed
Properties map[string]interface{} `json:"properties,omitempty"`
// OldProperties for update events (what was there before)
OldProperties map[string]interface{} `json:"old_properties,omitempty"`
// Query is the Cypher query that was executed
Query string `json:"query,omitempty"`
// QueryParams are the parameters passed to the query
QueryParams map[string]interface{} `json:"query_params,omitempty"`
// Duration of query execution
Duration time.Duration `json:"duration,omitempty"`
// RowsAffected by the query
RowsAffected int64 `json:"rows_affected,omitempty"`
// Error message if the query failed
Error string `json:"error,omitempty"`
// IndexName for index events
IndexName string `json:"index_name,omitempty"`
// IndexLabel for index events
IndexLabel string `json:"index_label,omitempty"`
// IndexProperty for index events
IndexProperty string `json:"index_property,omitempty"`
// UserID who triggered the event (if authenticated)
UserID string `json:"user_id,omitempty"`
// Source identifies where the event came from (e.g., "bolt", "http", "internal")
Source string `json:"source,omitempty"`
// Metadata for any additional event-specific data
Metadata map[string]interface{} `json:"metadata,omitempty"`
}
DatabaseEvent represents a database event that plugins can react to. This provides a unified interface for all database operations.
func (*DatabaseEvent) IsNodeEvent ¶
func (e *DatabaseEvent) IsNodeEvent() bool
IsNodeEvent returns true if this is a node-related event.
func (*DatabaseEvent) IsQueryEvent ¶
func (e *DatabaseEvent) IsQueryEvent() bool
IsQueryEvent returns true if this is a query-related event.
func (*DatabaseEvent) IsRelationshipEvent ¶
func (e *DatabaseEvent) IsRelationshipEvent() bool
IsRelationshipEvent returns true if this is a relationship-related event.
func (*DatabaseEvent) IsTransactionEvent ¶
func (e *DatabaseEvent) IsTransactionEvent() bool
IsTransactionEvent returns true if this is a transaction-related event.
type DatabaseEventHook ¶
type DatabaseEventHook interface {
// OnDatabaseEvent is called when a database event occurs.
// This is fire-and-forget (does not block database operations).
// The plugin should handle errors internally and not panic.
//
// Events are delivered asynchronously - the database operation
// has already completed by the time this is called.
//
// Plugins can use this to:
// - Build audit logs
// - Track usage patterns
// - Trigger alerts on specific events
// - Update caches
// - Collect metrics
OnDatabaseEvent(event *DatabaseEvent)
}
DatabaseEventHook is an optional interface for plugins that want to react to database events. This enables plugins to monitor database activity without modifying the database layer.
type DatabaseEventType ¶
type DatabaseEventType string
DatabaseEventType categorizes database events.
const ( // Node events EventNodeCreated DatabaseEventType = "node.created" EventNodeUpdated DatabaseEventType = "node.updated" EventNodeDeleted DatabaseEventType = "node.deleted" EventNodeRead DatabaseEventType = "node.read" // Relationship events EventRelationshipCreated DatabaseEventType = "relationship.created" EventRelationshipUpdated DatabaseEventType = "relationship.updated" EventRelationshipDeleted DatabaseEventType = "relationship.deleted" // Query events EventQueryExecuted DatabaseEventType = "query.executed" EventQueryFailed DatabaseEventType = "query.failed" // Index events EventIndexCreated DatabaseEventType = "index.created" EventIndexDropped DatabaseEventType = "index.dropped" // Transaction events EventTransactionCommit DatabaseEventType = "transaction.commit" EventTransactionRollback DatabaseEventType = "transaction.rollback" // System events EventDatabaseStarted DatabaseEventType = "database.started" EventDatabaseShutdown DatabaseEventType = "database.shutdown" EventBackupStarted DatabaseEventType = "backup.started" EventBackupCompleted DatabaseEventType = "backup.completed" )
type DatabaseMetrics ¶
type DatabaseMetrics struct {
NodeCount int64 `json:"node_count"`
EdgeCount int64 `json:"edge_count"`
LabelCounts map[string]int64 `json:"label_counts,omitempty"`
IndexCount int `json:"index_count"`
PropertyIndexes int `json:"property_indexes"`
CompositeIndexes int `json:"composite_indexes"`
MVCCLifecycle map[string]interface{} `json:"mvcc_lifecycle,omitempty"`
}
DatabaseMetrics contains core database statistics.
type DatabaseMetricsSource ¶
type DatabaseMetricsSource interface {
// Core stats
Stats() interface{} // Returns DBStats or similar
// Node/Edge counts
NodeCount() (int64, error)
EdgeCount() (int64, error)
// Embed queue
EmbedQueueStats() interface{}
// Storage engine
GetAsyncEngine() AsyncEngineStats
GetWAL() WALStats
GetSchemaManager() SchemaManagerStats
// Query cache
GetQueryCache() QueryCacheStats
// GPU
GetGPUManager() GPUManagerStats
// Encryption
EncryptionStats() map[string]interface{}
}
DatabaseMetricsSource is the interface for collecting database metrics.
type DatabaseRouter ¶
type DatabaseRouter interface {
// DefaultDatabaseName returns the configured default database name.
DefaultDatabaseName() string
// ResolveDatabase resolves a database alias or name to the underlying database name.
ResolveDatabase(nameOrAlias string) (string, error)
// ListDatabases returns the known logical database names.
ListDatabases() []string
// Query executes a Cypher query against the specified logical database.
//
// NOTE: Despite the historical "read-only" naming, this method may execute write
// queries depending on the underlying Cypher engine. Treat it as a general Cypher
// execution entrypoint unless your implementation enforces read-only semantics.
Query(ctx context.Context, database string, cypher string, params map[string]interface{}) ([]map[string]interface{}, error)
// Stats returns database statistics for the specified logical database.
Stats(database string) (DatabaseStats, error)
// Discover performs semantic search with graph traversal in the specified database.
// Returns search results with related nodes up to the specified depth.
Discover(ctx context.Context, database string, query string, nodeTypes []string, limit int, depth int) (*DiscoverResult, error)
}
DatabaseRouter provides multi-database access for Heimdall actions and plugins.
IMPORTANT:
- The `database` parameter is a logical database name (or alias) as used by the Neo4j-compatible multi-database layer.
- If `database` is empty, implementations must route to the configured default database.
This interface is intentionally database-name aware so plugins can maintain strict tenant isolation by routing each operation to the correct logical database.
type DatabaseStats ¶
type DatabaseStats struct {
NodeCount int64 `json:"node_count"`
RelationshipCount int64 `json:"relationship_count"`
LabelCounts map[string]int64 `json:"label_counts"`
ClusterStats *ClusterStats `json:"cluster_stats,omitempty"`
FeatureFlags *FeatureFlags `json:"feature_flags,omitempty"`
}
DatabaseStats contains database statistics.
type DefaultLogger ¶
type DefaultLogger struct {
// contains filtered or unexported fields
}
DefaultLogger is a simple logger implementation.
func NewDefaultLogger ¶
func NewDefaultLogger(prefix string) *DefaultLogger
NewDefaultLogger creates a logger with the given prefix.
func (*DefaultLogger) Debug ¶
func (l *DefaultLogger) Debug(msg string, args ...interface{})
func (*DefaultLogger) Error ¶
func (l *DefaultLogger) Error(msg string, args ...interface{})
func (*DefaultLogger) Info ¶
func (l *DefaultLogger) Info(msg string, args ...interface{})
func (*DefaultLogger) Warn ¶
func (l *DefaultLogger) Warn(msg string, args ...interface{})
type DiscoverResult ¶
type DiscoverResult struct {
Results []SearchResult `json:"results"`
Method string `json:"method"` // "vector" or "keyword"
Total int `json:"total"`
}
DiscoverResult contains semantic search results with related nodes.
type Embedder ¶
type Embedder interface {
Embed(ctx context.Context, text string) ([]float32, error)
ChunkText(text string, maxTokens, overlap int) ([]string, error)
}
Embedder generates embeddings for text.
type EmbeddingMetrics ¶
type EmbeddingMetrics struct {
WorkerRunning bool `json:"worker_running"`
Processed int `json:"processed"`
Failed int `json:"failed"`
QueueLength int `json:"queue_length"`
NodesWithEmbed int64 `json:"nodes_with_embeddings"`
NodesWithoutEmbed int64 `json:"nodes_without_embeddings"`
EmbedRate float64 `json:"embed_rate"`
Provider string `json:"provider"`
Model string `json:"model"`
Dimensions int `json:"dimensions"`
}
EmbeddingMetrics contains embedding worker statistics.
type FeatureFlags ¶
type FeatureFlags struct {
// Core Heimdall flags
HeimdallEnabled bool `json:"heimdall_enabled"`
HeimdallAnomalyDetection bool `json:"heimdall_anomaly_detection"`
HeimdallRuntimeDiagnosis bool `json:"heimdall_runtime_diagnosis"`
HeimdallMemoryCuration bool `json:"heimdall_memory_curation"`
// Clustering (derived from search stats)
ClusteringEnabled bool `json:"clustering_enabled"`
// Topology/prediction flags
TopologyEnabled bool `json:"topology_enabled"`
KalmanEnabled bool `json:"kalman_enabled"`
// Runtime flags (derived from DB state)
AsyncWritesEnabled bool `json:"async_writes_enabled"`
}
FeatureFlags contains enabled/disabled feature status.
type FeatureFlagsSource ¶
type FeatureFlagsSource interface {
GetHeimdallEnabled() bool
GetHeimdallModel() string
GetHeimdallProvider() string
GetHeimdallAPIURL() string
GetHeimdallAPIKey() string
GetHeimdallGPULayers() int
GetHeimdallContextSize() int
GetHeimdallBatchSize() int
GetHeimdallMaxTokens() int
GetHeimdallTemperature() float32
GetHeimdallAnomalyDetection() bool
GetHeimdallRuntimeDiagnosis() bool
GetHeimdallMemoryCuration() bool
GetHeimdallMaxContextTokens() int
GetHeimdallMaxSystemTokens() int
GetHeimdallMaxUserTokens() int
}
FeatureFlagsSource is the interface for getting Heimdall config from feature flags. This avoids import cycles with the config package.
type FullLifecycleHook ¶
type FullLifecycleHook interface {
PrePromptHook
PreExecuteHook
PostExecuteHook
SynthesisHook
DatabaseEventHook
}
FullLifecycleHook is a convenience interface for plugins that implement all hooks. Plugins are NOT required to implement this - they can pick and choose.
Hook execution order:
- PrePromptHook - Modify prompt context before SLM processes it
- PreExecuteHook - Validate/modify params before action runs
- (Action executes)
- PostExecuteHook - Log, update state after action completes
- SynthesisHook - Transform action results into user-friendly prose
- (Response sent to user)
DatabaseEventHook runs asynchronously on database operations.
type GPUManagerStats ¶
type GPUManagerStats interface {
IsEnabled() bool
Device() interface{}
Stats() interface{}
AllocatedMemoryMB() int
}
GPUManagerStats is the interface for GPU metrics.
type GPUMetrics ¶
type GPUMetrics struct {
Available bool `json:"available"`
Enabled bool `json:"enabled"`
DeviceName string `json:"device_name,omitempty"`
Backend string `json:"backend,omitempty"`
MemoryMB int `json:"memory_mb,omitempty"`
AllocatedMB int `json:"allocated_mb"`
OperationsGPU int64 `json:"operations_gpu"`
OperationsCPU int64 `json:"operations_cpu"`
FallbackCount int64 `json:"fallback_count"`
}
GPUMetrics contains GPU acceleration statistics.
type GenerateParams ¶
type GenerateParams struct {
MaxTokens int
Temperature float32
TopP float32
TopK int
StopTokens []string
}
GenerateParams configures text generation.
func DefaultGenerateParams ¶
func DefaultGenerateParams() GenerateParams
DefaultGenerateParams returns sensible defaults for chat (Qwen3-aligned). Qwen3 0.6B instruct best practices: temperature 0.5–0.7, top_p 0.8, top_k 20 to reduce repetition.
type Generator ¶
type Generator interface {
// Generate produces a complete response.
Generate(ctx context.Context, prompt string, params GenerateParams) (string, error)
// GenerateStream produces tokens via callback.
GenerateStream(ctx context.Context, prompt string, params GenerateParams, callback func(token string) error) error
// Close releases model resources.
Close() error
// ModelPath returns the loaded model path.
ModelPath() string
}
Generator is the interface for text generation models.
type GeneratorLoader ¶
type GeneratorLoader func(modelPath string, gpuLayers, contextSize, batchSize int) (Generator, error)
GeneratorLoader is a function type for loading generators. This can be replaced for testing or by CGO implementation. Parameters:
- modelPath: Path to the GGUF model file
- gpuLayers: GPU layer offload (-1=auto, 0=CPU only)
- contextSize: Context window size (single-shot = 8192)
- batchSize: Batch processing size (match context for single-shot)
var DefaultGeneratorLoader GeneratorLoader = func(modelPath string, gpuLayers, contextSize, batchSize int) (Generator, error) { return nil, fmt.Errorf("SLM generation requires CGO build with localllm tag") }
DefaultGeneratorLoader is the default loader (stub without CGO).
func SetGeneratorLoader ¶
func SetGeneratorLoader(loader GeneratorLoader) GeneratorLoader
SetGeneratorLoader allows overriding the generator loader for testing. Returns the previous loader so it can be restored.
type GeneratorWithTools ¶
type GeneratorWithTools interface {
Generator
// GenerateWithTools runs one round of chat with tools. messages is the full conversation
// so far (system, user, optional assistant+tool_calls, tool results, ...). Returns content
// (text reply) and/or toolCalls. Handler executes toolCalls, appends messages, and calls
// again until toolCalls is empty (agentic loop).
GenerateWithTools(ctx context.Context, messages []ToolRoundMessage, tools []MCPTool, params GenerateParams) (content string, toolCalls []ParsedToolCall, err error)
}
GeneratorWithTools is implemented by generators that support native tool/function calling. When used, the handler runs an agentic loop: call GenerateWithTools, execute any toolCalls, append assistant + tool result messages, call again until the model returns content only. Used for OpenAI and Ollama; local GGUF uses prompt-based agentic loop (same loop, prompt-based).
type GraphEdge ¶
type GraphEdge struct {
ID string
Type string
SourceID string
TargetID string
Properties map[string]interface{}
}
GraphEdge represents an edge in the graph.
type Handler ¶
type Handler struct {
// contains filtered or unexported fields
}
Handler provides HTTP endpoints for Bifrost chat. Uses standard HTTP/SSE - no external dependencies required. Bifrost is the rainbow bridge that connects to Heimdall.
Endpoints:
- GET /api/bifrost/status - Heimdall and Bifrost status
- POST /api/bifrost/chat/completions - Chat with Heimdall
- GET /v1/models - OpenAI-compatible single-model list
- POST /v1/chat/completions - OpenAI-compatible alias for Bifrost chat
- GET /api/bifrost/events - SSE stream for real-time events
func NewHandler ¶
func NewHandler(manager *Manager, cfg Config, db DatabaseRouter, metrics MetricsReader) *Handler
NewHandler creates a Bifrost HTTP handler. Returns nil if Heimdall is disabled (manager is nil). Automatically creates Bifrost bridge when Heimdall is enabled.
func (*Handler) Bifrost ¶
func (h *Handler) Bifrost() BifrostBridge
Bifrost returns the BifrostBridge for plugin communication. Returns NoOpBifrost if Bifrost is not available.
func (*Handler) ServeHTTP ¶
func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request)
ServeHTTP routes requests to appropriate handlers.
func (*Handler) SetInMemoryToolRunner ¶
func (h *Handler) SetInMemoryToolRunner(runner InMemoryToolRunner)
SetInMemoryToolRunner sets the runner for MCP-style tools (store, recall, discover, etc.) so the agentic loop can call them in process. When set, tools from the runner are merged into the tool list and execution is dispatched in memory instead of via HTTP.
type HeimdallInvoker ¶
type HeimdallInvoker interface {
// InvokeAction directly invokes a registered action by name.
// The action must be registered (e.g., "heimdall_watcher_status").
// Results are returned synchronously.
//
// Example:
// result, err := ctx.Heimdall.InvokeAction("heimdall_anomaly_detect", map[string]interface{}{
// "threshold": 0.8,
// })
InvokeAction(ctx context.Context, action string, params map[string]interface{}) (*ActionResult, error)
// SendPrompt sends a natural language prompt to the SLM for processing.
// The SLM will interpret the prompt and may invoke registered actions.
// Results are returned after the SLM processes the request.
//
// Example:
// result, err := ctx.Heimdall.SendPrompt("Analyze recent error patterns")
SendPrompt(ctx context.Context, prompt string) (*ActionResult, error)
// InvokeActionAsync invokes an action without waiting for result.
// Use this for fire-and-forget scenarios where you don't need the result.
// Results will be broadcast via Bifrost to connected clients.
InvokeActionAsync(action string, params map[string]interface{})
// SendPromptAsync sends a prompt without waiting for result.
// Results will be broadcast via Bifrost to connected clients.
SendPromptAsync(prompt string)
// SendRawPrompt sends a prompt directly to the LLM without action routing context.
// Use this for synthesis or direct question-answering where you don't want
// the SLM to try parsing actions from the response.
//
// Example:
// result, err := ctx.Heimdall.SendRawPrompt("Answer this question: How many nodes?")
SendRawPrompt(ctx context.Context, prompt string) (*ActionResult, error)
}
HeimdallInvoker allows plugins to autonomously trigger SLM actions. This enables event-driven automation where plugins can analyze accumulated events and trigger appropriate responses.
Example: A security plugin monitors failed auth events and after N failures triggers "heimdall_security_analyze" to investigate.
type HeimdallPlugin ¶
type HeimdallPlugin interface {
// Name returns the plugin/subsystem identifier (e.g., "anomaly", "health", "curator")
Name() string
// Version returns the plugin version (semver format)
Version() string
// Type must return "heimdall" to identify this as a Heimdall plugin
Type() string
// Description returns human-readable description of what this subsystem does
Description() string
// Initialize is called when the subsystem is loaded
// Receives context for accessing database, config, etc.
Initialize(ctx SubsystemContext) error
// Start begins the subsystem's background operations (if any)
Start() error
// Stop halts the subsystem's background operations
Stop() error
// Shutdown is called when the subsystem is being unloaded
Shutdown() error
// Status returns current subsystem status
Status() SubsystemStatus
// Health returns detailed health information
Health() SubsystemHealth
// Metrics returns subsystem-specific metrics for the SLM to analyze
Metrics() map[string]interface{}
// Config returns current configuration
Config() map[string]interface{}
// Configure updates subsystem configuration
// The SLM can use this to tune subsystem behavior
Configure(settings map[string]interface{}) error
// Schema returns the configuration schema (for validation)
ConfigSchema() map[string]interface{}
// Actions returns all actions this subsystem provides
// Map key is the action name (e.g., "detect"), will be prefixed as slm.{name}.{action}
Actions() map[string]ActionFunc
// Summary returns a text summary of current subsystem state
// Used by SLM to understand what the subsystem is doing
Summary() string
// RecentEvents returns recent notable events from this subsystem
// Used by SLM for contextual awareness
RecentEvents(limit int) []SubsystemEvent
}
HeimdallPlugin is the interface that all Heimdall plugins must implement. This is a DISTINCT plugin type from regular NornicDB plugins.
Regular plugins provide Cypher functions (apoc.*). Heimdall plugins provide SUBSYSTEM MANAGEMENT for cognitive database features.
Heimdall (the guardian) uses this interface to:
- Query subsystem state and health
- Configure subsystem behavior
- Control subsystem lifecycle
- Execute subsystem actions
- Collect subsystem metrics
type InMemoryToolRunner ¶
type InMemoryToolRunner interface {
// ToolDefinitions returns tool definitions for the LLM (name, description, inputSchema).
ToolDefinitions() []MCPTool
// ToolNames returns the list of tool names this runner handles (for dispatch).
ToolNames() []string
// CallTool executes the named tool with the given arguments in the given database context.
// dbName is the logical database name (e.g. from DefaultDatabaseName()); use "" for default.
CallTool(ctx context.Context, name string, args map[string]interface{}, dbName string) (interface{}, error)
}
InMemoryToolRunner provides MCP-style tools (e.g. store, recall, discover) that the agentic loop can call in process instead of via HTTP. Used to expose pkg/mcp memory tools to the LLM so it can manage memories through the same tool list.
type LiveHeimdallInvoker ¶
type LiveHeimdallInvoker struct {
// contains filtered or unexported fields
}
LiveHeimdallInvoker is the production implementation of HeimdallInvoker. It uses the SubsystemManager to invoke actions and can optionally use a Generator for SLM prompt processing.
func NewLiveHeimdallInvoker ¶
func NewLiveHeimdallInvoker(manager *SubsystemManager, generator Generator, bifrost BifrostBridge, database DatabaseRouter, metrics MetricsReader) *LiveHeimdallInvoker
NewLiveHeimdallInvoker creates a new invoker with the required dependencies.
func (*LiveHeimdallInvoker) InvokeAction ¶
func (h *LiveHeimdallInvoker) InvokeAction(ctx context.Context, action string, params map[string]interface{}) (*ActionResult, error)
InvokeAction directly invokes a registered action.
func (*LiveHeimdallInvoker) InvokeActionAsync ¶
func (h *LiveHeimdallInvoker) InvokeActionAsync(action string, params map[string]interface{})
InvokeActionAsync invokes an action asynchronously, broadcasting results via Bifrost.
func (*LiveHeimdallInvoker) SendPrompt ¶
func (h *LiveHeimdallInvoker) SendPrompt(ctx context.Context, prompt string) (*ActionResult, error)
SendPrompt sends a prompt to the SLM and processes the response.
func (*LiveHeimdallInvoker) SendPromptAsync ¶
func (h *LiveHeimdallInvoker) SendPromptAsync(prompt string)
SendPromptAsync sends a prompt asynchronously, broadcasting results via Bifrost.
func (*LiveHeimdallInvoker) SendRawPrompt ¶
func (h *LiveHeimdallInvoker) SendRawPrompt(ctx context.Context, prompt string) (*ActionResult, error)
SendRawPrompt sends a prompt directly to the SLM without action routing context. This is used for synthesis where we just want the LLM to answer a question, not try to parse and route actions.
type LoadedHeimdallPlugin ¶
type LoadedHeimdallPlugin struct {
Plugin HeimdallPlugin // The actual plugin implementing full interface
Path string // Path to .so file (empty for built-in)
Builtin bool // True if this is a built-in plugin
}
LoadedHeimdallPlugin represents a loaded SLM plugin with full subsystem management.
func ListHeimdallPlugins ¶
func ListHeimdallPlugins() []*LoadedHeimdallPlugin
ListHeimdallPlugins returns information about all loaded SLM plugins.
type MCPTool ¶
type MCPTool struct {
Name string `json:"name"`
Description string `json:"description"`
InputSchema json.RawMessage `json:"inputSchema"`
}
MCPTool is the MCP (Model Context Protocol) tool definition shape. Use ActionsAsMCPTools() to export Heimdall actions as MCP tools. Same fields as MCP Tool: name, description, inputSchema (JSON Schema).
func ActionsAsMCPTools ¶
func ActionsAsMCPTools() []MCPTool
ActionsAsMCPTools returns all registered Heimdall actions in MCP tool format. Use this to expose Heimdall actions to MCP clients or to merge with pkg/mcp tool list. Each tool has name, description, and inputSchema (JSON Schema); when an action has no InputSchema set, DefaultActionInputSchema is used.
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
Manager handles Heimdall SLM model loading and inference. Follows the same BYOM pattern as the embedding subsystem.
Environment variables:
- NORNICDB_MODELS_DIR: Directory for .gguf files (default: /data/models)
- NORNICDB_HEIMDALL_MODEL: Model name (default: qwen2.5-1.5b-instruct-q4_k_m)
- NORNICDB_HEIMDALL_GPU_LAYERS: GPU layer offload (-1=auto, 0=CPU only)
- NORNICDB_HEIMDALL_ENABLED: Feature flag (default: false)
func NewManager ¶
NewManager creates an SLM manager using BYOM configuration. Returns nil if SLM feature is disabled.
Provider selection (matches embeddings: local / ollama / openai / vllm):
- openai: Use OpenAI (or compatible) chat API; requires NORNICDB_HEIMDALL_API_KEY.
- ollama: Use Ollama /api/chat; NORNICDB_HEIMDALL_API_URL defaults to http://localhost:11434.
- vllm: Use vLLM's OpenAI-compatible API; NORNICDB_HEIMDALL_API_URL defaults to http://localhost:8000.
- local or empty: Load GGUF from NORNICDB_MODELS_DIR (BYOM).
func (*Manager) Chat ¶
func (m *Manager) Chat(ctx context.Context, req ChatRequest) (*ChatResponse, error)
Chat handles chat completion requests.
func (*Manager) Generate ¶
func (m *Manager) Generate(ctx context.Context, prompt string, params GenerateParams) (string, error)
Generate produces a response for the given prompt.
func (*Manager) GenerateStream ¶
func (m *Manager) GenerateStream(ctx context.Context, prompt string, params GenerateParams, callback func(token string) error) error
GenerateStream produces tokens via callback.
func (*Manager) GenerateWithTools ¶
func (m *Manager) GenerateWithTools(ctx context.Context, messages []ToolRoundMessage, tools []MCPTool, params GenerateParams) (content string, toolCalls []ParsedToolCall, err error)
GenerateWithTools runs one round of chat with tools (agentic loop). Only valid when SupportsTools() is true. Returns content and/or toolCalls; caller executes tools and calls again until no toolCalls.
func (*Manager) ModelPath ¶
ModelPath returns the path to the loaded model. This allows Manager to implement the Generator interface.
func (*Manager) Stats ¶
func (m *Manager) Stats() ManagerStats
func (*Manager) SupportsTools ¶
SupportsTools returns true if the generator supports native tool/function calling (e.g. OpenAI, Ollama). When true, the handler uses GenerateWithTools and an agentic loop.
type ManagerStats ¶
type ManagerStats struct {
ModelPath string `json:"model_path"`
RequestCount int64 `json:"request_count"`
ErrorCount int64 `json:"error_count"`
LastUsed time.Time `json:"last_used"`
Enabled bool `json:"enabled"`
}
Stats returns current manager statistics.
type MetricsCollector ¶
type MetricsCollector struct {
// contains filtered or unexported fields
}
MetricsCollector collects metrics from all NornicDB subsystems.
func NewMetricsCollector ¶
func NewMetricsCollector(db DatabaseMetricsSource, server ServerMetricsSource) *MetricsCollector
NewMetricsCollector creates a new metrics collector.
func (*MetricsCollector) Collect ¶
func (c *MetricsCollector) Collect() *NornicDBMetrics
Collect gathers all metrics from the database.
func (*MetricsCollector) Runtime ¶
func (c *MetricsCollector) Runtime() RuntimeMetrics
Runtime returns current runtime metrics (always cheap to collect).
type MetricsReader ¶
type MetricsReader interface {
// Runtime returns current runtime metrics
Runtime() RuntimeMetrics
}
MetricsReader provides runtime metrics access for actions.
type ModelInfo ¶
type ModelInfo struct {
Name string `json:"name"`
Path string `json:"path"`
Type ModelType `json:"type"`
SizeBytes int64 `json:"size_bytes"`
Quantization string `json:"quantization,omitempty"`
Loaded bool `json:"loaded"`
LastUsed time.Time `json:"last_used,omitempty"`
VRAMEstimate int64 `json:"vram_estimate_bytes"`
}
ModelInfo describes an available model in the registry.
type NoOpBifrost ¶
type NoOpBifrost struct{}
NoOpBifrost is a no-op implementation for when Bifrost is not available.
func (*NoOpBifrost) Broadcast ¶
func (n *NoOpBifrost) Broadcast(msg string) error
func (*NoOpBifrost) ConnectionCount ¶
func (n *NoOpBifrost) ConnectionCount() int
func (*NoOpBifrost) IsConnected ¶
func (n *NoOpBifrost) IsConnected() bool
func (*NoOpBifrost) RequestConfirmation ¶
func (n *NoOpBifrost) RequestConfirmation(action string) (bool, error)
func (*NoOpBifrost) SendMessage ¶
func (n *NoOpBifrost) SendMessage(msg string) error
func (*NoOpBifrost) SendNotification ¶
func (n *NoOpBifrost) SendNotification(t, title, msg string) error
type NoOpHeimdallInvoker ¶
type NoOpHeimdallInvoker struct{}
NoOpHeimdallInvoker is a no-op implementation when Heimdall is not available.
func (*NoOpHeimdallInvoker) InvokeAction ¶
func (n *NoOpHeimdallInvoker) InvokeAction(ctx context.Context, action string, params map[string]interface{}) (*ActionResult, error)
func (*NoOpHeimdallInvoker) InvokeActionAsync ¶
func (n *NoOpHeimdallInvoker) InvokeActionAsync(action string, params map[string]interface{})
func (*NoOpHeimdallInvoker) SendPrompt ¶
func (n *NoOpHeimdallInvoker) SendPrompt(ctx context.Context, prompt string) (*ActionResult, error)
func (*NoOpHeimdallInvoker) SendPromptAsync ¶
func (n *NoOpHeimdallInvoker) SendPromptAsync(prompt string)
func (*NoOpHeimdallInvoker) SendRawPrompt ¶
func (n *NoOpHeimdallInvoker) SendRawPrompt(ctx context.Context, prompt string) (*ActionResult, error)
type NornicDBMetrics ¶
type NornicDBMetrics struct {
// Server metrics
Server ServerMetrics `json:"server"`
// Database metrics
Database DatabaseMetrics `json:"database"`
// Storage engine metrics
Storage StorageMetrics `json:"storage"`
// Cache metrics
Cache CacheMetrics `json:"cache"`
// Embedding metrics
Embedding EmbeddingMetrics `json:"embedding"`
// GPU metrics
GPU GPUMetrics `json:"gpu"`
// Query metrics
Query QueryMetrics `json:"query"`
// Runtime metrics
Runtime RuntimeMetrics `json:"runtime"`
// Timestamp
CollectedAt time.Time `json:"collected_at"`
}
NornicDBMetrics aggregates ALL database metrics for the SLM. This is the single source of truth for database observability.
type ParsedAction ¶
type ParsedAction struct {
Action string `json:"action"`
Params map[string]interface{} `json:"params"`
}
ParseActionResponse parses an SLM response to extract action requests.
type ParsedToolCall ¶
ParsedToolCall is a single tool invocation from a remote provider (OpenAI/Ollama). Arguments is the JSON string of parameters (e.g. "{\"cypher\": \"MATCH (n) RETURN n\"}"). Id is set by the provider (e.g. OpenAI) and must be sent back with the tool result for that call.
type PluginOrdering ¶
type PluginOrdering interface {
// Priority controls ordering when there are no explicit dependencies.
// Higher values run earlier.
Priority() int
// Before lists plugin names that must run after this plugin.
Before() []string
// After lists plugin names that must run before this plugin.
After() []string
}
PluginOrdering is an optional interface for plugins that want deterministic ordering. Higher priority runs earlier. Before/After define ordering constraints by plugin name.
type PostExecuteContext ¶
type PostExecuteContext struct {
// Context carries request cancellation and deadlines.
Context context.Context
// RequestID for tracking
RequestID string
// Action that was executed
Action string
// Params that were passed
Params map[string]interface{}
// Result from the action execution
Result *ActionResult
// Duration of action execution
Duration time.Duration
// PluginData from earlier phases
PluginData map[string]interface{}
// WasCancelled indicates if the request was cancelled in an earlier phase
WasCancelled bool
// CancellationInfo contains details if cancelled
CancellationInfo *CancellationInfo
// contains filtered or unexported fields
}
PostExecuteContext contains execution results for logging/state updates.
Notifications from PostExecute are queued and sent inline after the action result, ensuring proper ordering in the streaming response.
func (*PostExecuteContext) DrainNotifications ¶
func (p *PostExecuteContext) DrainNotifications() []QueuedNotification
DrainNotifications returns and clears all queued notifications.
func (*PostExecuteContext) Notify ¶
func (p *PostExecuteContext) Notify(notificationType, title, message string)
Notify queues a notification to be sent inline after the action result.
func (*PostExecuteContext) NotifyError ¶
func (p *PostExecuteContext) NotifyError(title, message string)
NotifyError queues an error notification.
func (*PostExecuteContext) NotifyInfo ¶
func (p *PostExecuteContext) NotifyInfo(title, message string)
NotifyInfo queues an info notification.
func (*PostExecuteContext) NotifySuccess ¶
func (p *PostExecuteContext) NotifySuccess(title, message string)
NotifySuccess queues a success notification.
func (*PostExecuteContext) NotifyWarning ¶
func (p *PostExecuteContext) NotifyWarning(title, message string)
NotifyWarning queues a warning notification.
type PostExecuteHook ¶
type PostExecuteHook interface {
// PostExecute is called AFTER action execution completes.
// Plugins can:
// - Log execution metrics
// - Update internal state
// - Cache results
// - Trigger side effects
// This is fire-and-forget (does not block response).
PostExecute(ctx *PostExecuteContext)
}
PostExecuteHook is an optional interface for plugins that want to react to action results. If a plugin implements this, PostExecute will be called after each action completes.
type PreExecuteContext ¶
type PreExecuteContext struct {
// Context carries request cancellation and deadlines.
Context context.Context
// RequestID for tracking
RequestID string
// RequestTime when the request started
RequestTime time.Time
// Action is the parsed action name (e.g., "heimdall_watcher_status")
Action string
// Params are the parsed action parameters
Params map[string]interface{}
// RawResponse is the raw SLM response (for inspection if needed)
RawResponse string
// PluginData from the PrePrompt phase
PluginData map[string]interface{}
// Database routes Cypher/search operations across logical databases.
Database DatabaseRouter
// Metrics provides runtime metrics
Metrics MetricsReader
// PrincipalRoles are the authenticated principal's role names (from request context).
PrincipalRoles []string
// DatabaseAccessMode is the principal's per-database see/access mode (from request context).
DatabaseAccessMode auth.DatabaseAccessMode
// ResolvedAccess returns per-database read/write for the principal (from request context).
ResolvedAccess func(dbName string) auth.ResolvedAccess
// contains filtered or unexported fields
}
PreExecuteContext contains the parsed action before execution.
Cancellation: Call ctx.Cancel("reason", "hook:plugin") to abort execution. The reason will be logged and sent to the user via Bifrost.
Notifications: Plugins can send non-blocking SSE messages to the UI via ctx.Notify() - these are fire-and-forget and won't block the request.
func (*PreExecuteContext) Cancel ¶
func (p *PreExecuteContext) Cancel(reason string, cancelledBy string)
Cancel aborts the action execution with a reason.
func (*PreExecuteContext) CancelReason ¶
func (p *PreExecuteContext) CancelReason() string
CancelReason returns the reason for cancellation.
func (*PreExecuteContext) Cancelled ¶
func (p *PreExecuteContext) Cancelled() bool
Cancelled returns true if the request has been cancelled.
func (*PreExecuteContext) CancelledBy ¶
func (p *PreExecuteContext) CancelledBy() string
CancelledBy returns which hook/plugin cancelled.
func (*PreExecuteContext) DrainNotifications ¶
func (p *PreExecuteContext) DrainNotifications() []QueuedNotification
DrainNotifications returns and clears all queued notifications.
func (*PreExecuteContext) Notify ¶
func (p *PreExecuteContext) Notify(notificationType, title, message string)
Notify queues a notification to be sent inline after the AI response. This ensures proper ordering with the streaming content.
func (*PreExecuteContext) NotifyError ¶
func (p *PreExecuteContext) NotifyError(title, message string)
NotifyError queues an error notification.
func (*PreExecuteContext) NotifyInfo ¶
func (p *PreExecuteContext) NotifyInfo(title, message string)
NotifyInfo queues an info notification.
func (*PreExecuteContext) NotifyProgress ¶
func (p *PreExecuteContext) NotifyProgress(title, message string)
NotifyProgress queues a progress notification.
func (*PreExecuteContext) NotifyWarning ¶
func (p *PreExecuteContext) NotifyWarning(title, message string)
NotifyWarning queues a warning notification.
func (*PreExecuteContext) SetBifrost ¶
func (p *PreExecuteContext) SetBifrost(b BifrostBridge)
SetBifrost sets the Bifrost bridge for notifications (called by handler).
type PreExecuteHook ¶
type PreExecuteHook interface {
// PreExecute is called AFTER Heimdall responds, BEFORE action execution.
// Plugins can perform async operations:
// - Fetch additional data from external services
// - Validate/modify params
// - Abort execution by setting Continue=false
// The done callback MUST be called when complete.
PreExecute(ctx *PreExecuteContext, done func(PreExecuteResult))
}
PreExecuteHook is an optional interface for plugins that want to validate/modify actions. If a plugin implements this, PreExecute will be called after SLM responds but before action runs.
type PreExecuteResult ¶
type PreExecuteResult struct {
// Continue indicates whether to proceed with execution.
// Set to false to abort the action.
Continue bool
// ModifiedParams replaces the original params if non-nil.
ModifiedParams map[string]interface{}
// AdditionalContext is merged into ActionContext.
AdditionalContext map[string]interface{}
// AbortMessage is returned to user if Continue=false.
AbortMessage string
// Error if something went wrong during pre-execute.
Error error
}
PreExecuteResult is returned via callback after async operations complete.
func CallPreExecuteHooks ¶
func CallPreExecuteHooks(ctx *PreExecuteContext) PreExecuteResult
CallPreExecuteHooks calls PreExecute on all plugins that implement PreExecuteHook. Plugins that don't implement the hook are silently skipped. This is synchronous - waits for each plugin with a timeout.
type PrePromptHook ¶
type PrePromptHook interface {
// PrePrompt is called BEFORE sending the prompt to Heimdall.
// The ActionPrompt field is IMMUTABLE (already set, read-only).
// Plugins can modify mutable fields:
// - AdditionalInstructions: Add context, constraints, guidance
// - Examples: Add domain-specific examples
// - PluginData: Store state for later phases
// Return error to log warning (does not abort request).
PrePrompt(ctx *PromptContext) error
}
PrePromptHook is an optional interface for plugins that want to modify prompts. If a plugin implements this, PrePrompt will be called before each SLM request.
type PromptBudgetInfo ¶
type PromptBudgetInfo struct {
SystemTokens int `json:"system_tokens"`
UserTokens int `json:"user_tokens"`
TotalTokens int `json:"total_tokens"`
MaxSystem int `json:"max_system"`
MaxUser int `json:"max_user"`
MaxTotal int `json:"max_total"`
SystemAvailable int `json:"system_available"`
UserAvailable int `json:"user_available"`
}
PromptBudgetInfo returns token budget information for debugging.
type PromptContext ¶
type PromptContext struct {
// Context carries request cancellation and deadlines.
Context context.Context
// RequestID for tracking through the lifecycle
RequestID string
// RequestTime when the request started
RequestTime time.Time
// ActionPrompt contains all registered actions formatted for the SLM.
// This is always injected at the start of the system prompt.
// Plugins CANNOT modify this field.
ActionPrompt string
// UserMessage is the current user input
UserMessage string
// Messages is the full conversation history
Messages []ChatMessage
// ExternalTools are tool definitions provided by the client (e.g. Continue/OpenAI tools).
// These are exposed to the underlying model in addition to Heimdall's built-in actions.
ExternalTools []MCPTool
// AdditionalInstructions are appended after ActionPrompt.
// Plugins add context, constraints, or guidance here.
AdditionalInstructions string
// Examples help Heimdall understand user intent.
// Plugins can add domain-specific examples.
Examples []PromptExample
// PluginData persists through the request lifecycle.
// Plugins can store state here for use in PreExecute/PostExecute.
PluginData map[string]interface{}
// contains filtered or unexported fields
}
PromptContext contains the prompt being built for Heimdall. ActionPrompt is immutable (always injected first). Plugins can modify the mutable fields to add context.
Cancellation: Any lifecycle hook can cancel the request by calling ctx.Cancel("reason"). The request will be aborted and the reason sent to the user via Bifrost.
Notifications: Plugins can send non-blocking SSE messages to the UI via ctx.Notify() - these are fire-and-forget and won't block the request.
func (*PromptContext) Broadcast ¶
func (p *PromptContext) Broadcast(message string)
Broadcast sends a message to all connected clients (fire-and-forget).
func (*PromptContext) BuildFinalPrompt ¶
func (p *PromptContext) BuildFinalPrompt() string
BuildFinalPrompt constructs the complete prompt for Heimdall (prompt-based flow: model outputs JSON actions). ActionPrompt is ALWAYS first and immutable. Falls back to minimal prompt if full prompt exceeds budget.
func (*PromptContext) BuildFinalPromptForTools ¶
func (p *PromptContext) BuildFinalPromptForTools() string
BuildFinalPromptForTools constructs the system prompt when the provider uses native tool calling. Same as BuildFinalPrompt but with tools-friendly instructions: answer in natural language when the context contains the answer; use tools only when an action is needed. Plugins inject context via AdditionalInstructions (e.g. order status); the model should use it and reply in plain text.
func (*PromptContext) Cancel ¶
func (p *PromptContext) Cancel(reason string, cancelledBy string)
Cancel aborts the request with a reason. The reason will be logged and sent to the user via Bifrost. cancelledBy should identify which plugin/hook is cancelling (e.g., "PrePrompt:myplugin").
func (*PromptContext) CancelReason ¶
func (p *PromptContext) CancelReason() string
CancelReason returns the reason for cancellation (empty if not cancelled).
func (*PromptContext) Cancelled ¶
func (p *PromptContext) Cancelled() bool
Cancelled returns true if the request has been cancelled.
func (*PromptContext) CancelledBy ¶
func (p *PromptContext) CancelledBy() string
CancelledBy returns which hook/plugin cancelled the request.
func (*PromptContext) DrainNotifications ¶
func (p *PromptContext) DrainNotifications() []QueuedNotification
DrainNotifications returns and clears all queued notifications. Called by the handler to send them inline with the streaming response.
func (*PromptContext) EstimatedSystemTokens ¶
func (p *PromptContext) EstimatedSystemTokens() int
EstimatedSystemTokens returns estimated token count for the system prompt.
func (*PromptContext) GetBudgetInfo ¶
func (p *PromptContext) GetBudgetInfo() PromptBudgetInfo
GetBudgetInfo returns current token budget information.
func (*PromptContext) Notify ¶
func (p *PromptContext) Notify(notificationType, title, message string)
Notify queues a notification to be sent inline with the streaming response. This ensures proper ordering - notifications appear at the correct point in the chat. Use this to send progress updates, warnings, or informational messages.
func (*PromptContext) NotifyError ¶
func (p *PromptContext) NotifyError(title, message string)
NotifyError sends an error notification (fire-and-forget).
func (*PromptContext) NotifyInfo ¶
func (p *PromptContext) NotifyInfo(title, message string)
NotifyInfo sends an info notification (fire-and-forget).
func (*PromptContext) NotifyProgress ¶
func (p *PromptContext) NotifyProgress(title, message string)
NotifyProgress sends a progress notification (fire-and-forget).
func (*PromptContext) NotifyWarning ¶
func (p *PromptContext) NotifyWarning(title, message string)
NotifyWarning sends a warning notification (fire-and-forget).
func (*PromptContext) SendMessage ¶
func (p *PromptContext) SendMessage(message string)
SendMessage sends a raw message to the UI (fire-and-forget).
func (*PromptContext) SetBifrost ¶
func (p *PromptContext) SetBifrost(b BifrostBridge)
SetBifrost sets the Bifrost bridge for notifications (called by handler).
func (*PromptContext) ValidateTokenBudget ¶
func (p *PromptContext) ValidateTokenBudget() error
ValidateTokenBudget checks if the prompt fits within the token budget. Returns an error if the system prompt is too large.
type PromptExample ¶
type PromptExample struct {
UserSays string // What the user might say
ActionJSON string // The JSON action Heimdall should output
}
PromptExample is a user→action mapping example for Heimdall.
type QueryCacheStats ¶
type QueryCacheStats interface {
Stats() interface{}
}
QueryCacheStats is the interface for cache metrics.
type QueryDatabase ¶
type QueryDatabase interface {
// Query executes a read-only Cypher query
Query(ctx context.Context, cypher string, params map[string]interface{}) ([]map[string]interface{}, error)
// Stats returns basic database stats
Stats() interface{}
// NodeCount returns total nodes
NodeCount() (int64, error)
// EdgeCount returns total edges
EdgeCount() (int64, error)
}
QueryDatabase is the interface for executing Cypher queries.
type QueryExecutor ¶
type QueryExecutor struct {
// contains filtered or unexported fields
}
QueryExecutor provides read-only database access for Heimdall actions.
func NewQueryExecutor ¶
func NewQueryExecutor(db QueryDatabase, timeout time.Duration) *QueryExecutor
NewQueryExecutor creates a query executor with the given database.
func NewQueryExecutorWithSearch ¶
func NewQueryExecutorWithSearch(db QueryDatabase, searcher SemanticSearcher, embedder Embedder, timeout time.Duration) *QueryExecutor
NewQueryExecutorWithSearch creates a query executor with semantic search support.
func (*QueryExecutor) Discover ¶
func (e *QueryExecutor) Discover(ctx context.Context, query string, nodeTypes []string, limit int, depth int) (*DiscoverResult, error)
Discover implements DatabaseReader.Discover for semantic search.
func (*QueryExecutor) Query ¶
func (e *QueryExecutor) Query(ctx context.Context, cypher string, params map[string]interface{}) ([]map[string]interface{}, error)
Query implements DatabaseReader.Query
func (*QueryExecutor) Stats ¶
func (e *QueryExecutor) Stats() DatabaseStats
Stats implements DatabaseReader.Stats
type QueryMetrics ¶
type QueryMetrics struct {
TotalQueries int64 `json:"total_queries"`
SlowQueries int64 `json:"slow_queries"`
AvgExecutionTime time.Duration `json:"avg_execution_time"`
CacheHitRate float64 `json:"cache_hit_rate"`
ThresholdMs int64 `json:"threshold_ms"`
}
QueryMetrics contains Cypher query statistics.
type QueuedNotification ¶
type QueuedNotification struct {
Type string `json:"type"` // "info", "warning", "error", "success", "progress"
Title string `json:"title"`
Message string `json:"message"`
}
QueuedNotification represents a notification waiting to be sent inline.
type RealMetricsReader ¶
type RealMetricsReader struct{}
RealMetricsReader provides actual runtime metrics.
func (*RealMetricsReader) Runtime ¶
func (r *RealMetricsReader) Runtime() RuntimeMetrics
Runtime returns current runtime metrics.
type RelatedNode ¶
type RelatedNode struct {
ID string `json:"id"`
Type string `json:"type,omitempty"`
Title string `json:"title,omitempty"`
Distance int `json:"distance"` // Hops from the source node
Relationship string `json:"relationship"` // Relationship type
Direction string `json:"direction,omitempty"` // "incoming", "outgoing", or ""
Path string `json:"path,omitempty"` // Path description
}
RelatedNode represents a node connected to a search result.
type RuntimeMetrics ¶
type RuntimeMetrics struct {
GoroutineCount int `json:"goroutine_count"`
MemoryAllocMB uint64 `json:"memory_alloc_mb"`
NumGC uint32 `json:"num_gc"`
}
RuntimeMetrics contains runtime statistics.
type SchemaManagerStats ¶
type SchemaManagerStats interface {
GetIndexStats() interface{}
}
SchemaManagerStats is the interface for schema/index metrics.
type SearchResult ¶
type SearchResult struct {
ID string `json:"id"`
Type string `json:"type"`
Title string `json:"title,omitempty"`
ContentPreview string `json:"content_preview,omitempty"`
Similarity float64 `json:"similarity"`
Properties map[string]interface{} `json:"properties,omitempty"`
Related []RelatedNode `json:"related,omitempty"`
}
SearchResult represents a single search result with similarity and related nodes.
type SemanticSearchResult ¶
type SemanticSearchResult struct {
ID string
Labels []string
Properties map[string]interface{}
Score float64
}
SemanticSearchResult is the result of a semantic search operation.
type SemanticSearcher ¶
type SemanticSearcher interface {
// HybridSearch performs vector + text search with pre-computed embedding
HybridSearch(ctx context.Context, query string, queryEmbedding []float32, labels []string, limit int) ([]*SemanticSearchResult, error)
// Search performs full-text BM25 search
Search(ctx context.Context, query string, labels []string, limit int) ([]*SemanticSearchResult, error)
// Neighbors returns connected node IDs
Neighbors(ctx context.Context, nodeID string) ([]string, error)
// GetEdgesForNode returns edges for a node
GetEdgesForNode(ctx context.Context, nodeID string) ([]*GraphEdge, error)
// GetNode retrieves a node by ID
GetNode(ctx context.Context, nodeID string) (*NodeData, error)
}
SemanticSearcher is an optional interface for databases that support semantic search. QueryDatabase implementations may optionally implement this for vector search.
type ServerMetrics ¶
type ServerMetrics struct {
Uptime time.Duration `json:"uptime"`
RequestsTotal int64 `json:"requests_total"`
ErrorsTotal int64 `json:"errors_total"`
ActiveRequests int64 `json:"active_requests"`
SlowQueryCount int64 `json:"slow_query_count"`
RequestsPerSec float64 `json:"requests_per_sec"`
}
ServerMetrics contains HTTP server statistics.
type ServerMetricsSource ¶
type ServerMetricsSource interface {
Stats() interface{}
SlowQueryCount() int64
}
ServerMetricsSource is the interface for collecting server metrics.
type StorageMetrics ¶
type StorageMetrics struct {
// Async engine stats
PendingWrites int64 `json:"pending_writes"`
TotalFlushes int64 `json:"total_flushes"`
// WAL stats
WALSequence uint64 `json:"wal_sequence"`
WALEntries uint64 `json:"wal_entries"`
WALBytes uint64 `json:"wal_bytes"`
WALTotalWrites uint64 `json:"wal_total_writes"`
WALTotalSyncs uint64 `json:"wal_total_syncs"`
WALLastSync time.Time `json:"wal_last_sync"`
// Node config stats
NodeConfigs int64 `json:"node_configs"`
ConfigChecks int64 `json:"config_checks"`
ConfigsBlocked int64 `json:"configs_blocked"`
BlockRate float64 `json:"block_rate"`
// Edge meta stats
EdgeMetaRecords int64 `json:"edge_meta_records"`
EdgeMetaMaterialized int64 `json:"edge_meta_materialized"`
EdgeMetaBySignal map[string]int64 `json:"edge_meta_by_signal,omitempty"`
}
StorageMetrics contains storage engine statistics.
type StreamEvent ¶
type StreamEvent struct {
Event string `json:"event,omitempty"` // "message", "done", "error"
Data string `json:"data"`
}
StreamEvent represents a Server-Sent Event for streaming.
type SubsystemContext ¶
type SubsystemContext struct {
// Config is the Heimdall configuration
Config Config
// Database routes Cypher/search operations across logical databases.
// This is multi-database aware (Neo4j 4.x style) and should be used instead of
// relying on a single default database.
Database DatabaseRouter
// Metrics provides runtime metrics
Metrics MetricsReader
// Logger for subsystem logging
Logger SubsystemLogger
// Bifrost provides the communication bridge to connected clients
// Plugins can use this to send messages, notifications, and request input
Bifrost BifrostBridge
// Heimdall provides autonomous action invocation for plugins.
// Plugins can use this to trigger actions or send prompts to the SLM
// based on accumulated events or other triggers.
Heimdall HeimdallInvoker
}
SubsystemContext is provided to plugins during initialization.
type SubsystemEvent ¶
type SubsystemEvent struct {
Time time.Time `json:"time"`
Type string `json:"type"` // "info", "warning", "error", "action"
Message string `json:"message"`
Data map[string]interface{} `json:"data,omitempty"`
}
SubsystemEvent represents a notable event from a subsystem.
type SubsystemHealth ¶
type SubsystemHealth struct {
Status SubsystemStatus `json:"status"`
Healthy bool `json:"healthy"`
Message string `json:"message,omitempty"`
LastCheck time.Time `json:"last_check"`
Details map[string]interface{} `json:"details,omitempty"`
}
SubsystemHealth contains detailed health information.
type SubsystemLogger ¶
type SubsystemLogger interface {
Debug(msg string, args ...interface{})
Info(msg string, args ...interface{})
Warn(msg string, args ...interface{})
Error(msg string, args ...interface{})
}
SubsystemLogger is the logging interface for subsystems.
type SubsystemManager ¶
type SubsystemManager struct {
// contains filtered or unexported fields
}
SubsystemManager manages all SLM plugins/subsystems. Provides the SLM with full control over registered subsystems.
func GetSubsystemManager ¶
func GetSubsystemManager() *SubsystemManager
GetSubsystemManager returns the global subsystem manager (creates if needed).
func (*SubsystemManager) AllHealth ¶
func (m *SubsystemManager) AllHealth() map[string]SubsystemHealth
AllHealth returns health status of all subsystems.
func (*SubsystemManager) AllSummaries ¶
func (m *SubsystemManager) AllSummaries() map[string]string
AllSummaries returns summaries of all subsystems (for SLM context).
func (*SubsystemManager) GetAction ¶
func (m *SubsystemManager) GetAction(name string) (ActionFunc, bool)
GetAction returns an action by full name (e.g., "heimdall_plugin_action").
func (*SubsystemManager) GetPlugin ¶
func (m *SubsystemManager) GetPlugin(name string) (HeimdallPlugin, bool)
GetPlugin returns a plugin by name.
func (*SubsystemManager) RegisterPlugin ¶
func (m *SubsystemManager) RegisterPlugin(p HeimdallPlugin, path string, builtin bool) error
RegisterPlugin registers an SLM plugin and initializes it.
func (*SubsystemManager) SetContext ¶
func (m *SubsystemManager) SetContext(ctx SubsystemContext)
SetContext configures the shared context for all subsystems.
func (*SubsystemManager) ShutdownAll ¶
func (m *SubsystemManager) ShutdownAll() error
ShutdownAll shuts down all registered subsystems.
func (*SubsystemManager) StartAll ¶
func (m *SubsystemManager) StartAll() error
StartAll starts all registered subsystems.
func (*SubsystemManager) StopAll ¶
func (m *SubsystemManager) StopAll() error
StopAll stops all registered subsystems.
type SubsystemStatus ¶
type SubsystemStatus string
SubsystemStatus represents the current state of a subsystem.
const ( StatusUninitialized SubsystemStatus = "uninitialized" StatusInitializing SubsystemStatus = "initializing" StatusReady SubsystemStatus = "ready" StatusRunning SubsystemStatus = "running" StatusStopping SubsystemStatus = "stopping" StatusStopped SubsystemStatus = "stopped" StatusError SubsystemStatus = "error" )
type SynthesisContext ¶
type SynthesisContext struct {
// Context carries request cancellation and deadlines.
Context context.Context
// RequestID for tracking
RequestID string
// UserQuestion is the original user message
UserQuestion string
// Action that was executed
Action string
// Result from the action execution
Result *ActionResult
// PluginData from earlier phases
PluginData map[string]interface{}
// Database routes Cypher/search operations across logical databases.
Database DatabaseRouter
}
SynthesisContext provides context for response synthesis.
type SynthesisHook ¶
type SynthesisHook interface {
// Synthesize transforms action results into a user-friendly response.
//
// Return values:
// - Non-empty string: Use this as the final response (skips default synthesis)
// - Empty string: Continue with default LLM-based synthesis
//
// The done callback MUST be called when complete.
Synthesize(ctx *SynthesisContext, done func(response string))
}
SynthesisHook is an optional interface for plugins that want to customize how action results are presented to users. This is called AFTER PostExecute but BEFORE the response is sent to the user.
Plugins can use this to:
- Provide domain-specific formatting (e.g., format POC data nicely)
- Add custom context or explanations
- Transform data into more user-friendly formats
- Skip synthesis entirely and return raw data
type TokenBudget ¶
type TokenBudget struct {
MaxContext int // Total context window
MaxSystem int // System prompt budget
MaxUser int // User message budget
}
TokenBudget holds the configurable token limits for prompt construction. Use GetTokenBudget() to get the current budget from config.
func GetTokenBudget ¶
func GetTokenBudget() TokenBudget
GetTokenBudget returns the current token budget.
type ToolRoundMessage ¶
type ToolRoundMessage struct {
Role string // "system", "user", "assistant", "tool"
Content string // For tool role: the result content (e.g. JSON or text)
ToolCalls []ParsedToolCall // For assistant: tool invocations from the model
ToolCallID string // For tool role: which call this result is for (OpenAI id)
}
ToolRoundMessage is one message in an agentic conversation (system, user, assistant, or tool result). Used for the tool-calling loop: after executing tools, handler appends assistant message (with ToolCalls) and tool result messages (Role "tool", ToolCallID, Content), then calls again.