feat: import agents_and_robots platform as unibots (Matrix-out, unibus transport)
Reemplaza el scaffold del echobot por la plataforma completa de bots traida desde ~/DataProyects/Github/agents_and_robots tras la operacion Matrix-out: los bots ya no hablan por Matrix sino por el bus unibus (modelo todo-rooms + E2E via shell/transportunibus sobre github.com/enmanuel/unibus/pkg/client). - go.mod: replace de unibus -> ../unibus y de fn-registry -> ../../../.. (paths relativos reajustados a la nueva ubicacion dentro de fn_registry). - app.md: bump a 0.2.0, descripcion + arquitectura + comandos + gotchas reales. - modulo Go conservado como github.com/enmanuel/agents (sin reescribir imports). agents_and_robots queda archivado como museo de la era Matrix.
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
package llm
|
||||
|
||||
import "strings"
|
||||
|
||||
// Route maps a model string to its provider. Pure function.
|
||||
func Route(model string) ProviderID {
|
||||
switch {
|
||||
case model == "claude-code" || strings.HasPrefix(model, "claude-code/"):
|
||||
return ProviderClaudeCode
|
||||
case strings.HasPrefix(model, "claude"):
|
||||
return ProviderAnthropic
|
||||
case strings.HasPrefix(model, "gpt"), strings.HasPrefix(model, "o1"), strings.HasPrefix(model, "o3"):
|
||||
return ProviderOpenAI
|
||||
case strings.HasPrefix(model, "ollama/"):
|
||||
return ProviderOllama
|
||||
default:
|
||||
return ProviderOpenAI
|
||||
}
|
||||
}
|
||||
|
||||
// ModelName strips the provider prefix from a model string.
|
||||
func ModelName(model string) string {
|
||||
if after, ok := strings.CutPrefix(model, "ollama/"); ok {
|
||||
return after
|
||||
}
|
||||
return model
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package llm
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestRoute(t *testing.T) {
|
||||
tests := []struct {
|
||||
model string
|
||||
want ProviderID
|
||||
}{
|
||||
{"claude-code", ProviderClaudeCode},
|
||||
{"claude-code/custom", ProviderClaudeCode},
|
||||
{"claude-sonnet-4-5-20250929", ProviderAnthropic},
|
||||
{"claude-opus-4", ProviderAnthropic},
|
||||
{"gpt-4o", ProviderOpenAI},
|
||||
{"o1-preview", ProviderOpenAI},
|
||||
{"o3-mini", ProviderOpenAI},
|
||||
{"ollama/mistral", ProviderOllama},
|
||||
{"unknown-model", ProviderOpenAI}, // default
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.model, func(t *testing.T) {
|
||||
got := Route(tt.model)
|
||||
if got != tt.want {
|
||||
t.Errorf("Route(%q) = %q, want %q", tt.model, got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestModelName(t *testing.T) {
|
||||
tests := []struct {
|
||||
input, want string
|
||||
}{
|
||||
{"ollama/mistral", "mistral"},
|
||||
{"gpt-4o", "gpt-4o"},
|
||||
{"claude-sonnet-4-5-20250929", "claude-sonnet-4-5-20250929"},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.input, func(t *testing.T) {
|
||||
got := ModelName(tt.input)
|
||||
if got != tt.want {
|
||||
t.Errorf("ModelName(%q) = %q, want %q", tt.input, got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
// Package llm defines pure types for LLM provider communication.
|
||||
// No side effects — only data and transformations.
|
||||
package llm
|
||||
|
||||
import "context"
|
||||
|
||||
type Role string
|
||||
|
||||
const (
|
||||
RoleSystem Role = "system"
|
||||
RoleUser Role = "user"
|
||||
RoleAssistant Role = "assistant"
|
||||
RoleTool Role = "tool"
|
||||
)
|
||||
|
||||
type ProviderID string
|
||||
|
||||
const (
|
||||
ProviderAnthropic ProviderID = "anthropic"
|
||||
ProviderOpenAI ProviderID = "openai"
|
||||
ProviderOllama ProviderID = "ollama"
|
||||
ProviderClaudeCode ProviderID = "claude-code"
|
||||
)
|
||||
|
||||
type Message struct {
|
||||
Role Role
|
||||
Content string
|
||||
ToolCallID string
|
||||
ToolCalls []ToolCall
|
||||
}
|
||||
|
||||
type ToolCall struct {
|
||||
ID string
|
||||
Name string
|
||||
Arguments string // JSON-encoded
|
||||
}
|
||||
|
||||
type ToolSpec struct {
|
||||
Name string
|
||||
Description string
|
||||
InputSchema map[string]any
|
||||
}
|
||||
|
||||
type CompletionRequest struct {
|
||||
Model string
|
||||
Messages []Message
|
||||
Tools []ToolSpec
|
||||
MaxTokens int
|
||||
Temperature float64
|
||||
Stream bool
|
||||
SystemPrompt string
|
||||
}
|
||||
|
||||
type TokenUsage struct {
|
||||
InputTokens int
|
||||
OutputTokens int
|
||||
TotalTokens int
|
||||
}
|
||||
|
||||
type CompletionResponse struct {
|
||||
Content string
|
||||
ToolCalls []ToolCall
|
||||
Usage TokenUsage
|
||||
FinishReason string
|
||||
}
|
||||
|
||||
// CompleteFunc is the single contract for LLM providers.
|
||||
// Implementations live in shell/llm/.
|
||||
type CompleteFunc func(ctx context.Context, req CompletionRequest) (CompletionResponse, error)
|
||||
Reference in New Issue
Block a user