Major additions: - core-agent serve: persistent HTTP daemon with PID file, health check, registry - agentic_dispatch_remote: dispatch tasks to remote agents (Charon) over MCP HTTP - agentic_status_remote: check remote agent workspace status - agentic_mirror: sync Forge repos to GitHub mirrors with file count limits - agentic_review_queue: CodeRabbit/Codex review queue with rate-limit awareness - verify.go: auto-verify (run tests) + auto-merge + retry with rebase + needs-review label - monitor sync: checkin API integration for cross-agent repo sync - PostToolUse inbox notification hook (check-notify.sh) Dispatch improvements: - --dangerously-skip-permissions (CLI flag changed) - proc.CloseStdin() after spawn (Claude CLI stdin pipe fix) - GOWORK=off in agent env and verify - Exit code / BLOCKED.md / failure detection - Monitor poke for instant notifications New agent types: - coderabbit: CodeRabbit CLI review (--plain --base) - codex:review: OpenAI Codex review mode Integrations: - CODEX.md: OpenAI Codex conventions file - Gemini extension: points at core-agent MCP (not Node server) - Codex config: core-agent MCP server added - GitHub webhook handler + CodeRabbit KPI tables (PHP) - Forgejo provider for uptelligence webhooks - Agent checkin endpoint for repo sync Co-Authored-By: Virgil <virgil@lethean.io>
123 lines
3 KiB
Go
123 lines
3 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"forge.lthn.ai/core/agent/pkg/agentic"
|
|
"forge.lthn.ai/core/agent/pkg/brain"
|
|
"forge.lthn.ai/core/agent/pkg/monitor"
|
|
"forge.lthn.ai/core/cli/pkg/cli"
|
|
"forge.lthn.ai/core/go-process"
|
|
"forge.lthn.ai/core/go/pkg/core"
|
|
"forge.lthn.ai/core/mcp/pkg/mcp"
|
|
)
|
|
|
|
func main() {
|
|
if err := cli.Init(cli.Options{
|
|
AppName: "core-agent",
|
|
Version: "0.2.0",
|
|
}); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// Shared setup for both mcp and serve commands
|
|
initServices := func() (*mcp.Service, *monitor.Subsystem, error) {
|
|
c, err := core.New(core.WithName("process", process.NewService(process.Options{})))
|
|
if err != nil {
|
|
return nil, nil, cli.Wrap(err, "init core")
|
|
}
|
|
procSvc, err := core.ServiceFor[*process.Service](c, "process")
|
|
if err != nil {
|
|
return nil, nil, cli.Wrap(err, "get process service")
|
|
}
|
|
process.SetDefault(procSvc)
|
|
|
|
mon := monitor.New()
|
|
prep := agentic.NewPrep()
|
|
prep.SetCompletionNotifier(mon)
|
|
|
|
mcpSvc, err := mcp.New(
|
|
mcp.WithSubsystem(brain.NewDirect()),
|
|
mcp.WithSubsystem(prep),
|
|
mcp.WithSubsystem(mon),
|
|
)
|
|
if err != nil {
|
|
return nil, nil, cli.Wrap(err, "create MCP service")
|
|
}
|
|
|
|
return mcpSvc, mon, nil
|
|
}
|
|
|
|
// mcp — stdio transport (Claude Code integration)
|
|
mcpCmd := cli.NewCommand("mcp", "Start the MCP server on stdio", "", func(cmd *cli.Command, args []string) error {
|
|
mcpSvc, mon, err := initServices()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
mon.Start(cmd.Context())
|
|
return mcpSvc.Run(cmd.Context())
|
|
})
|
|
|
|
// serve — persistent HTTP daemon (Charon, CI, cross-agent)
|
|
serveCmd := cli.NewCommand("serve", "Start as a persistent HTTP daemon", "", func(cmd *cli.Command, args []string) error {
|
|
mcpSvc, mon, err := initServices()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Determine address
|
|
addr := os.Getenv("MCP_HTTP_ADDR")
|
|
if addr == "" {
|
|
addr = "0.0.0.0:9101"
|
|
}
|
|
|
|
// Determine health address
|
|
healthAddr := os.Getenv("HEALTH_ADDR")
|
|
if healthAddr == "" {
|
|
healthAddr = "0.0.0.0:9102"
|
|
}
|
|
|
|
// Set up daemon with PID file, health check, and registry
|
|
home, _ := os.UserHomeDir()
|
|
pidFile := filepath.Join(home, ".core", "core-agent.pid")
|
|
|
|
daemon := process.NewDaemon(process.DaemonOptions{
|
|
PIDFile: pidFile,
|
|
HealthAddr: healthAddr,
|
|
Registry: process.DefaultRegistry(),
|
|
RegistryEntry: process.DaemonEntry{
|
|
Code: "core",
|
|
Daemon: "agent",
|
|
Project: "core-agent",
|
|
Binary: "core-agent",
|
|
},
|
|
})
|
|
|
|
if err := daemon.Start(); err != nil {
|
|
return cli.Wrap(err, "daemon start")
|
|
}
|
|
|
|
// Start monitor
|
|
mon.Start(cmd.Context())
|
|
|
|
// Mark ready
|
|
daemon.SetReady(true)
|
|
fmt.Fprintf(os.Stderr, "core-agent serving on %s (health: %s, pid: %s)\n", addr, healthAddr, pidFile)
|
|
|
|
// Set env so mcp.Run picks HTTP transport
|
|
os.Setenv("MCP_HTTP_ADDR", addr)
|
|
|
|
// Run MCP server (blocks until context cancelled)
|
|
return mcpSvc.Run(cmd.Context())
|
|
})
|
|
|
|
cli.RootCmd().AddCommand(mcpCmd)
|
|
cli.RootCmd().AddCommand(serveCmd)
|
|
|
|
if err := cli.Execute(); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|