Mistral provider adapter with streaming, tool calls (single-chunk pattern), stop reason inference, model listing, capabilities, and JSON output support. Tool system: bash (7 security checks, shell alias harvesting for bash/zsh/fish), file ops (read, write, edit, glob, grep, ls). Alias harvesting collects 300+ aliases from user's shell config. Engine agentic loop: stream → tool execution → re-query → until done. Tool gating on model capabilities. Max turns safety limit. CLI pipe mode: echo "prompt" | gnoma streams response to stdout. Flags: --provider, --model, --system, --api-key, --max-turns, --verbose, --version. Provider interface expanded: Models(), DefaultModel(), Capabilities (ToolUse, JSONOutput, Vision, Thinking, ContextWindow, MaxOutput), ResponseFormat with JSON schema support. Live verified: text streaming + tool calling with devstral-small. 117 tests across 8 packages, 10MB binary.
78 lines
1.6 KiB
Go
78 lines
1.6 KiB
Go
package tool
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"sync"
|
|
)
|
|
|
|
// Definition is the provider-agnostic tool schema sent to the LLM.
|
|
type Definition struct {
|
|
Name string `json:"name"`
|
|
Description string `json:"description"`
|
|
Parameters json.RawMessage `json:"parameters"`
|
|
}
|
|
|
|
// Registry holds all available tools.
|
|
type Registry struct {
|
|
mu sync.RWMutex
|
|
tools map[string]Tool
|
|
}
|
|
|
|
func NewRegistry() *Registry {
|
|
return &Registry{
|
|
tools: make(map[string]Tool),
|
|
}
|
|
}
|
|
|
|
// Register adds a tool. Overwrites if name already exists.
|
|
func (r *Registry) Register(t Tool) {
|
|
r.mu.Lock()
|
|
defer r.mu.Unlock()
|
|
r.tools[t.Name()] = t
|
|
}
|
|
|
|
// Get returns a tool by name.
|
|
func (r *Registry) Get(name string) (Tool, bool) {
|
|
r.mu.RLock()
|
|
defer r.mu.RUnlock()
|
|
t, ok := r.tools[name]
|
|
return t, ok
|
|
}
|
|
|
|
// All returns all registered tools.
|
|
func (r *Registry) All() []Tool {
|
|
r.mu.RLock()
|
|
defer r.mu.RUnlock()
|
|
all := make([]Tool, 0, len(r.tools))
|
|
for _, t := range r.tools {
|
|
all = append(all, t)
|
|
}
|
|
return all
|
|
}
|
|
|
|
// Definitions returns tool definitions for all registered tools,
|
|
// suitable for sending to the LLM.
|
|
func (r *Registry) Definitions() []Definition {
|
|
r.mu.RLock()
|
|
defer r.mu.RUnlock()
|
|
defs := make([]Definition, 0, len(r.tools))
|
|
for _, t := range r.tools {
|
|
defs = append(defs, Definition{
|
|
Name: t.Name(),
|
|
Description: t.Description(),
|
|
Parameters: t.Parameters(),
|
|
})
|
|
}
|
|
return defs
|
|
}
|
|
|
|
// MustGet returns a tool by name or panics. For use in tests.
|
|
func (r *Registry) MustGet(name string) Tool {
|
|
t, ok := r.Get(name)
|
|
if !ok {
|
|
panic(fmt.Sprintf("tool not found: %q", name))
|
|
}
|
|
return t
|
|
}
|