146 lines
4.3 KiB
Go
146 lines
4.3 KiB
Go
package agents
|
|
|
|
import (
|
|
"context"
|
|
_ "embed"
|
|
"time"
|
|
|
|
"github.com/kandev/kandev/pkg/agent"
|
|
)
|
|
|
|
//go:embed logos/mock_light.svg
|
|
var mockLogoLight []byte
|
|
|
|
//go:embed logos/mock_dark.svg
|
|
var mockLogoDark []byte
|
|
|
|
var (
|
|
_ Agent = (*MockAgent)(nil)
|
|
_ PassthroughAgent = (*MockAgent)(nil)
|
|
_ InferenceAgent = (*MockAgent)(nil)
|
|
)
|
|
|
|
type MockAgent struct {
|
|
StandardPassthrough
|
|
enabled bool
|
|
binaryPath string
|
|
supportsMCP bool
|
|
}
|
|
|
|
func NewMockAgent() *MockAgent {
|
|
return &MockAgent{
|
|
StandardPassthrough: StandardPassthrough{
|
|
Cfg: PassthroughConfig{
|
|
Supported: true,
|
|
Label: "TUI Passthrough",
|
|
Description: "Terminal UI mode for testing",
|
|
PassthroughCmd: NewCommand("mock-agent", "--tui"),
|
|
ModelFlag: NewParam("--model", "{model}"),
|
|
PromptFlag: NewParam("--prompt", "{prompt}"),
|
|
SessionResumeFlag: NewParam("--resume"),
|
|
ResumeFlag: NewParam("-c"),
|
|
IdleTimeout: 2 * time.Second,
|
|
BufferMaxBytes: DefaultBufferMaxBytes,
|
|
},
|
|
},
|
|
supportsMCP: true,
|
|
}
|
|
}
|
|
|
|
// SetEnabled enables or disables the mock agent at runtime.
|
|
func (a *MockAgent) SetEnabled(enabled bool) { a.enabled = enabled }
|
|
|
|
// SetBinaryPath overrides the mock-agent binary path.
|
|
// Also updates the passthrough command to use the same binary.
|
|
func (a *MockAgent) SetBinaryPath(path string) {
|
|
a.binaryPath = path
|
|
a.Cfg.PassthroughCmd = NewCommand(path, "--tui")
|
|
}
|
|
|
|
// SetSupportsMCP controls whether the mock agent reports MCP support.
|
|
// Defaults to true so plan mode workflow events work in E2E tests.
|
|
func (a *MockAgent) SetSupportsMCP(v bool) { a.supportsMCP = v }
|
|
|
|
// SupportsMCPEnabled reports the current MCP support setting.
|
|
func (a *MockAgent) SupportsMCPEnabled() bool { return a.supportsMCP }
|
|
|
|
func (a *MockAgent) ID() string { return "mock-agent" }
|
|
func (a *MockAgent) Name() string { return "Mock Agent" }
|
|
func (a *MockAgent) DisplayName() string { return "Mock" }
|
|
func (a *MockAgent) Description() string {
|
|
return "Mock agent for testing. Generates simulated responses with all message types."
|
|
}
|
|
func (a *MockAgent) Enabled() bool { return a.enabled }
|
|
func (a *MockAgent) DisplayOrder() int { return 99 }
|
|
|
|
func (a *MockAgent) Logo(v LogoVariant) []byte {
|
|
if v == LogoDark {
|
|
return mockLogoDark
|
|
}
|
|
return mockLogoLight
|
|
}
|
|
|
|
func (a *MockAgent) IsInstalled(ctx context.Context) (*DiscoveryResult, error) {
|
|
// Mock agent is always "available" when enabled (forced by settings controller).
|
|
return &DiscoveryResult{Available: true, SupportsMCP: a.supportsMCP}, nil
|
|
}
|
|
|
|
func (a *MockAgent) BuildCommand(opts CommandOptions) Command {
|
|
binary := "mock-agent"
|
|
if a.binaryPath != "" {
|
|
binary = a.binaryPath
|
|
}
|
|
return Cmd(binary).Build()
|
|
}
|
|
|
|
func (a *MockAgent) Runtime() *RuntimeConfig {
|
|
canRecover := true
|
|
return &RuntimeConfig{
|
|
Cmd: Cmd("mock-agent").Build(),
|
|
WorkingDir: "{workspace}",
|
|
Env: map[string]string{},
|
|
ResourceLimits: ResourceLimits{MemoryMB: 512, CPUCores: 0.5, Timeout: time.Hour},
|
|
Protocol: agent.ProtocolACP,
|
|
SessionConfig: SessionConfig{
|
|
CanRecover: &canRecover,
|
|
},
|
|
}
|
|
}
|
|
|
|
func (a *MockAgent) RemoteAuth() *RemoteAuth { return nil }
|
|
|
|
// InstallScript returns a deterministic short-lived shell script so e2e tests
|
|
// can exercise the install streaming endpoint without depending on npm.
|
|
func (a *MockAgent) InstallScript() string {
|
|
return "echo mock-install: step 1 && echo mock-install: step 2 && echo mock-install: done"
|
|
}
|
|
|
|
// LoginCommand exposes a deterministic interactive command for e2e PTY tests.
|
|
// `cat` echoes any input back to the user; tests send "exit\n" or kill the
|
|
// session to terminate.
|
|
func (a *MockAgent) LoginCommand() *LoginCommand {
|
|
return &LoginCommand{
|
|
Cmd: []string{"cat"},
|
|
Description: "Mock login (echoes input).",
|
|
}
|
|
}
|
|
|
|
func (a *MockAgent) PermissionSettings() map[string]PermissionSetting {
|
|
return emptyPermSettings
|
|
}
|
|
|
|
// InferenceConfig enables one-shot inference via ACP. The mock-agent binary
|
|
// advertises its available models in the session/new response, so the host
|
|
// utility capability probe populates them into the cache without any static
|
|
// model list here.
|
|
func (a *MockAgent) InferenceConfig() *InferenceConfig {
|
|
binary := "mock-agent"
|
|
if a.binaryPath != "" {
|
|
binary = a.binaryPath
|
|
}
|
|
return &InferenceConfig{
|
|
Supported: true,
|
|
Command: NewCommand(binary),
|
|
}
|
|
}
|