Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ anna is a self-hosted AI assistant with lossless context management (LCM). Nativ

All Go packages live under `internal/` (app-private) except public interfaces in `pkg/`.

`cmd/anna/` → `internal/agent/` (pool, session) → `internal/agent/runner/` (GoRunner) → `internal/agent/engine/` (loop, tool execution) → `pkg/ai/` (types, events, transforms) → `pkg/providers/` (ProviderAdapter, Registry, stream dispatch)
`cmd/anna/` → `internal/agent/` (pool, session) → `internal/agent/runner/` (GoRunner) → `pkg/agent/` (Runner, loop, tool execution) → `pkg/ai/` (types, events, transforms) → `pkg/providers/` (ProviderAdapter, Registry, stream dispatch)

Side packages: `internal/channel/` (cli, telegram, qq, feishu, notifier) → `internal/scheduler/` → `internal/memory/` → `pkg/tools/` (Tool interface, registry, built-in tools) → `pkg/hooks/` (Hook interface, HookSet) → `internal/db/` → `internal/config/`

Expand Down
1 change: 1 addition & 0 deletions cmd/anna/plugins_imports.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ import (

// Plugin hooks.
_ "github.com/vaayne/anna/plugins/hooks/rtk"
_ "github.com/vaayne/anna/plugins/hooks/trace"
)
34 changes: 33 additions & 1 deletion internal/admin/ui/pages/plugins.templ
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import "github.com/vaayne/anna/internal/admin/ui"

templ PluginsPage() {
<div x-data="pluginsPage()">
@ui.PageHeader("Plugins", "Manage built-in tools and channel integrations.")
@ui.PageHeader("Plugins", "Manage built-in tools, hooks, and channel integrations.")
<div class="space-y-8">
<!-- Tools -->
<div>
Expand Down Expand Up @@ -38,6 +38,38 @@ templ PluginsPage() {
</template>
</div>
</div>
<!-- Hooks -->
<div>
<h3 class="text-base font-medium mb-3">Hooks</h3>
<div class="border border-base-300 rounded-lg divide-y divide-base-300">
<template x-for="p in hookPlugins" :key="p.id">
<div class="flex items-center justify-between px-4 py-3">
<div class="flex items-center gap-3">
<span class="font-mono font-medium text-sm" x-text="p.name"></span>
<span class="badge badge-warning badge-sm">hook</span>
<template x-if="p.enabled">
<span class="badge badge-success badge-sm">enabled</span>
</template>
<template x-if="!p.enabled">
<span class="badge badge-error badge-sm">disabled</span>
</template>
</div>
<div class="flex items-center gap-4">
<span class="text-xs text-secondary hidden sm:inline" x-text="descriptionFor(p.name)"></span>
<input
type="checkbox"
:checked="p.enabled"
@change="togglePlugin(p.id, $event.target.checked)"
class="toggle toggle-primary toggle-sm"
/>
</div>
</div>
</template>
<template x-if="hookPlugins.length === 0">
<div class="px-4 py-8 text-center text-base-content/50 text-sm">No hook plugins</div>
</template>
</div>
</div>
<!-- Channels -->
<div>
<h3 class="text-base font-medium mb-3">Channels</h3>
Expand Down
4 changes: 2 additions & 2 deletions internal/admin/ui/pages/plugins_templ.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions internal/admin/ui/static/js/pages/plugins.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ export function register(Alpine) {
return this.plugins.filter(p => p.kind === 'channel')
},

get hookPlugins() {
return this.plugins.filter(p => p.kind === 'hook')
},

async init() {
await this.loadPlugins()
},
Expand Down Expand Up @@ -46,6 +50,8 @@ export function register(Alpine) {
qq: 'QQ bot integration',
feishu: 'Feishu (Lark) bot integration',
weixin: 'WeChat bot integration',
trace: 'Trace LLM calls and tool executions',
rtk: 'Rewrite bash commands via rtk',
}
return descriptions[name] || ''
},
Expand Down
23 changes: 0 additions & 23 deletions internal/agent/engine/continue.go

This file was deleted.

23 changes: 13 additions & 10 deletions internal/agent/integration_tool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"testing"
"time"

"github.com/vaayne/anna/internal/agent/engine"
"github.com/vaayne/anna/pkg/agent"
"github.com/vaayne/anna/pkg/ai"
providerapi "github.com/vaayne/anna/pkg/providers"
pluginproviders "github.com/vaayne/anna/plugins/providers"
Expand Down Expand Up @@ -71,12 +71,10 @@ func TestIntegrationToolUseAllProviders(t *testing.T) {
reg := providerapi.NewRegistry()
reg.Register(adapter)

eng := &engine.Engine{Providers: reg}

var toolCalled atomic.Bool
var capturedCity string

tools := engine.ToolSet{
tools := agent.ToolSet{
"get_weather": func(ctx context.Context, call ai.ToolCall) (ai.TextContent, error) {
toolCalled.Store(true)
city, _ := call.Arguments["city"].(string)
Expand All @@ -85,13 +83,18 @@ func TestIntegrationToolUseAllProviders(t *testing.T) {
},
}

cfg := engine.LoopConfig{
runner, err := agent.NewRunner(agent.RunnerConfig{
Providers: reg,
Model: ai.Model{API: p.name, Name: model},
StreamOptions: ai.StreamOptions{APIKey: apiKey},
MaxTurns: 5,
Tools: tools,
ToolDefinitions: []ai.ToolDefinition{toolDef},
System: "You are a helpful assistant. When asked about weather, always use the get_weather tool. Be concise.",
},
agent.WithStreamOptions(ai.StreamOptions{APIKey: apiKey}),
agent.WithMaxTurns(5),
agent.WithSystem("You are a helpful assistant. When asked about weather, always use the get_weather tool. Be concise."),
)
if err != nil {
t.Fatalf("NewRunner error: %v", err)
}

ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
Expand All @@ -101,9 +104,9 @@ func TestIntegrationToolUseAllProviders(t *testing.T) {
ai.UserMessage{Content: "What's the weather in Tokyo?"},
}

history, err := eng.Run(ctx, cfg, messages, nil)
history, err := runner.Run(ctx, messages, nil)
if err != nil {
t.Fatalf("engine.Run error: %v", err)
t.Fatalf("runner.Run error: %v", err)
}

// Verify tool was called.
Expand Down
Loading
Loading