multica/server/cmd/daemon/daemon_test.go
yushen bb45f17cf9 feat(daemon): unified agent SDK supporting Claude Code and Codex
Add a reusable Go agent package (server/pkg/agent/) that provides a
unified Backend interface for executing prompts via either Claude Code
or Codex. The daemon now auto-detects which CLIs are available at
startup, registers a runtime for each, and routes tasks to the correct
backend based on task.Context.Runtime.Provider.

Key changes:
- server/pkg/agent/agent.go: Backend interface, Message/Result types, factory
- server/pkg/agent/claude.go: Spawns claude CLI with stream-json, parses output
- server/pkg/agent/codex.go: Spawns codex app-server, JSON-RPC 2.0 protocol
- server/cmd/daemon/daemon.go: Multi-runtime registration, round-robin polling,
  provider-based backend selection. Removes old runCodexExec/codexResultSchema.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 14:05:03 +08:00

63 lines
1.5 KiB
Go

package main
import (
"os"
"path/filepath"
"strings"
"testing"
)
func TestNormalizeServerBaseURL(t *testing.T) {
t.Parallel()
got, err := normalizeServerBaseURL("ws://localhost:8080/ws")
if err != nil {
t.Fatalf("normalizeServerBaseURL returned error: %v", err)
}
if got != "http://localhost:8080" {
t.Fatalf("expected http://localhost:8080, got %s", got)
}
}
func TestResolveTaskWorkdirUsesRepoPathWhenPresent(t *testing.T) {
t.Parallel()
root := t.TempDir()
repoPath := filepath.Join(root, "repo")
if err := os.Mkdir(repoPath, 0o755); err != nil {
t.Fatalf("mkdir repo: %v", err)
}
got, err := resolveTaskWorkdir(root, &daemonRepoRef{Path: "repo"})
if err != nil {
t.Fatalf("resolveTaskWorkdir returned error: %v", err)
}
if got != repoPath {
t.Fatalf("expected %s, got %s", repoPath, got)
}
}
func TestBuildCodexPromptIncludesIssueAndSkills(t *testing.T) {
t.Parallel()
prompt := buildPrompt(daemonTask{
Context: daemonTaskContext{
Issue: daemonIssueContext{
Title: "Fix failing test",
Description: "Investigate and fix the test failure.",
AcceptanceCriteria: []string{"tests pass"},
ContextRefs: []string{"log snippet"},
},
Agent: daemonAgentContext{
Name: "Local Codex",
Skills: "Be concise.",
},
},
}, "/tmp/work")
for _, want := range []string{"Fix failing test", "Investigate and fix the test failure.", "tests pass", "log snippet", "Be concise."} {
if !strings.Contains(prompt, want) {
t.Fatalf("prompt missing %q", want)
}
}
}