fix(ax): align core-agent CLI bootstrap
Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
c77a9b93bc
commit
547f23a6f0
5 changed files with 60 additions and 111 deletions
|
|
@ -434,6 +434,7 @@ func (s *PrepSubsystem) gitCmd(ctx context.Context, dir string, args ...string)
|
|||
|
||||
## Changelog
|
||||
|
||||
- 2026-03-29: cmd/core-agent no longer rewrites `os.Args` before startup. The binary-owned commands now use named handlers, keeping the entrypoint on Core CLI primitives instead of repo-local argument mutation.
|
||||
- 2026-03-26: WIP — net/http consolidated to transport.go (ONE file). net/url + io/fs eliminated. RFC-025 updated with 3 new quality gates (net/http, net/url, io/fs). 1:1 test + example test coverage. Array[T].Deduplicate replaces custom helpers. Remaining: remove dead `client` field from test literals, brain/provider.go Gin handler.
|
||||
- 2026-03-25: Quality gates pass. Zero disallowed imports (all 10). encoding/json→Core JSON. path/filepath→Core Path. os→Core Env/Fs. io→Core ReadAll/WriteAll. go-process fully Result-native. ServiceRuntime on all subsystems. 22 named Actions + Task pipeline. ChannelNotifier→IPC. Reference docs synced.
|
||||
- 2026-03-25: Initial spec — written with full core/go v0.8.0 domain context.
|
||||
|
|
|
|||
|
|
@ -1,31 +1,13 @@
|
|||
// SPDX-License-Identifier: EUPL-1.2
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"dappco.re/go/core"
|
||||
)
|
||||
|
||||
// applyLogLevel scans os.Args for --quiet/-q/--debug before Core starts.
|
||||
// Must run before c.Run() so ServiceStartup logs respect the level.
|
||||
//
|
||||
// core-agent --quiet version → errors only
|
||||
// core-agent --debug mcp → full debug output
|
||||
// core-agent status → default (info)
|
||||
func applyLogLevel() {
|
||||
var cleaned []string
|
||||
cleaned = append(cleaned, os.Args[0])
|
||||
for _, arg := range os.Args[1:] {
|
||||
switch arg {
|
||||
case "--quiet", "-q":
|
||||
core.SetLevel(core.LevelError)
|
||||
case "--debug", "-d":
|
||||
core.SetLevel(core.LevelDebug)
|
||||
default:
|
||||
cleaned = append(cleaned, arg)
|
||||
}
|
||||
}
|
||||
os.Args = cleaned
|
||||
type appCommandSet struct {
|
||||
core *core.Core
|
||||
}
|
||||
|
||||
// registerAppCommands adds app-level CLI commands (version, check, env).
|
||||
|
|
@ -35,61 +17,69 @@ func applyLogLevel() {
|
|||
// core-agent check — health check
|
||||
// core-agent env — environment variables
|
||||
func registerAppCommands(c *core.Core) {
|
||||
commands := appCommandSet{core: c}
|
||||
|
||||
c.Command("version", core.Command{
|
||||
Description: "Print version and build info",
|
||||
Action: func(opts core.Options) core.Result {
|
||||
core.Print(nil, "core-agent %s", c.App().Version)
|
||||
core.Print(nil, " go: %s", core.Env("GO"))
|
||||
core.Print(nil, " os: %s/%s", core.Env("OS"), core.Env("ARCH"))
|
||||
core.Print(nil, " home: %s", core.Env("DIR_HOME"))
|
||||
core.Print(nil, " hostname: %s", core.Env("HOSTNAME"))
|
||||
core.Print(nil, " pid: %s", core.Env("PID"))
|
||||
core.Print(nil, " channel: %s", updateChannel())
|
||||
return core.Result{OK: true}
|
||||
},
|
||||
Action: commands.version,
|
||||
})
|
||||
|
||||
c.Command("check", core.Command{
|
||||
Description: "Verify workspace, deps, and config",
|
||||
Action: func(opts core.Options) core.Result {
|
||||
fs := c.Fs()
|
||||
core.Print(nil, "core-agent %s health check", c.App().Version)
|
||||
core.Print(nil, "")
|
||||
core.Print(nil, " binary: core-agent")
|
||||
|
||||
agentsPath := core.Path("Code", ".core", "agents.yaml")
|
||||
if fs.IsFile(agentsPath) {
|
||||
core.Print(nil, " agents: %s (ok)", agentsPath)
|
||||
} else {
|
||||
core.Print(nil, " agents: %s (MISSING)", agentsPath)
|
||||
}
|
||||
|
||||
wsRoot := core.Path("Code", ".core", "workspace")
|
||||
if fs.IsDir(wsRoot) {
|
||||
entries := core.PathGlob(core.JoinPath(wsRoot, "*"))
|
||||
core.Print(nil, " workspace: %s (%d entries)", wsRoot, len(entries))
|
||||
} else {
|
||||
core.Print(nil, " workspace: %s (MISSING)", wsRoot)
|
||||
}
|
||||
|
||||
core.Print(nil, " services: %d registered", len(c.Services()))
|
||||
core.Print(nil, " actions: %d registered", len(c.Actions()))
|
||||
core.Print(nil, " commands: %d registered", len(c.Commands()))
|
||||
core.Print(nil, " env keys: %d loaded", len(core.EnvKeys()))
|
||||
core.Print(nil, "")
|
||||
core.Print(nil, "ok")
|
||||
return core.Result{OK: true}
|
||||
},
|
||||
Action: commands.check,
|
||||
})
|
||||
|
||||
c.Command("env", core.Command{
|
||||
Description: "Show all core.Env() keys and values",
|
||||
Action: func(opts core.Options) core.Result {
|
||||
keys := core.EnvKeys()
|
||||
for _, k := range keys {
|
||||
core.Print(nil, " %-15s %s", k, core.Env(k))
|
||||
}
|
||||
return core.Result{OK: true}
|
||||
},
|
||||
Action: commands.env,
|
||||
})
|
||||
}
|
||||
|
||||
func (commands appCommandSet) version(_ core.Options) core.Result {
|
||||
core.Print(nil, "core-agent %s", commands.core.App().Version)
|
||||
core.Print(nil, " go: %s", core.Env("GO"))
|
||||
core.Print(nil, " os: %s/%s", core.Env("OS"), core.Env("ARCH"))
|
||||
core.Print(nil, " home: %s", core.Env("DIR_HOME"))
|
||||
core.Print(nil, " hostname: %s", core.Env("HOSTNAME"))
|
||||
core.Print(nil, " pid: %s", core.Env("PID"))
|
||||
core.Print(nil, " channel: %s", updateChannel())
|
||||
return core.Result{OK: true}
|
||||
}
|
||||
|
||||
func (commands appCommandSet) check(_ core.Options) core.Result {
|
||||
fs := commands.core.Fs()
|
||||
core.Print(nil, "core-agent %s health check", commands.core.App().Version)
|
||||
core.Print(nil, "")
|
||||
core.Print(nil, " binary: core-agent")
|
||||
|
||||
agentsPath := core.Path("Code", ".core", "agents.yaml")
|
||||
if fs.IsFile(agentsPath) {
|
||||
core.Print(nil, " agents: %s (ok)", agentsPath)
|
||||
} else {
|
||||
core.Print(nil, " agents: %s (MISSING)", agentsPath)
|
||||
}
|
||||
|
||||
wsRoot := core.Path("Code", ".core", "workspace")
|
||||
if fs.IsDir(wsRoot) {
|
||||
entries := core.PathGlob(core.JoinPath(wsRoot, "*"))
|
||||
core.Print(nil, " workspace: %s (%d entries)", wsRoot, len(entries))
|
||||
} else {
|
||||
core.Print(nil, " workspace: %s (MISSING)", wsRoot)
|
||||
}
|
||||
|
||||
core.Print(nil, " services: %d registered", len(commands.core.Services()))
|
||||
core.Print(nil, " actions: %d registered", len(commands.core.Actions()))
|
||||
core.Print(nil, " commands: %d registered", len(commands.core.Commands()))
|
||||
core.Print(nil, " env keys: %d loaded", len(core.EnvKeys()))
|
||||
core.Print(nil, "")
|
||||
core.Print(nil, "ok")
|
||||
return core.Result{OK: true}
|
||||
}
|
||||
|
||||
func (commands appCommandSet) env(_ core.Options) core.Result {
|
||||
keys := core.EnvKeys()
|
||||
for _, key := range keys {
|
||||
core.Print(nil, " %-15s %s", key, core.Env(key))
|
||||
}
|
||||
return core.Result{OK: true}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"dappco.re/go/core"
|
||||
|
|
@ -19,44 +18,6 @@ func newTestCore(t *testing.T) *core.Core {
|
|||
return c
|
||||
}
|
||||
|
||||
// --- applyLogLevel ---
|
||||
|
||||
func TestCommands_ApplyLogLevel_Good(t *testing.T) {
|
||||
original := os.Args
|
||||
defer func() { os.Args = original }()
|
||||
|
||||
os.Args = []string{"core-agent", "--quiet", "version"}
|
||||
applyLogLevel()
|
||||
assert.Equal(t, []string{"core-agent", "version"}, os.Args)
|
||||
}
|
||||
|
||||
func TestCommands_ApplyLogLevel_Good_Debug(t *testing.T) {
|
||||
original := os.Args
|
||||
defer func() { os.Args = original }()
|
||||
|
||||
os.Args = []string{"core-agent", "-d", "check"}
|
||||
applyLogLevel()
|
||||
assert.Equal(t, []string{"core-agent", "check"}, os.Args)
|
||||
}
|
||||
|
||||
func TestCommands_ApplyLogLevel_Bad_NoFlag(t *testing.T) {
|
||||
original := os.Args
|
||||
defer func() { os.Args = original }()
|
||||
|
||||
os.Args = []string{"core-agent", "status"}
|
||||
applyLogLevel()
|
||||
assert.Equal(t, []string{"core-agent", "status"}, os.Args)
|
||||
}
|
||||
|
||||
func TestCommands_ApplyLogLevel_Ugly_FlagAfterCommand(t *testing.T) {
|
||||
original := os.Args
|
||||
defer func() { os.Args = original }()
|
||||
|
||||
os.Args = []string{"core-agent", "version", "-q"}
|
||||
applyLogLevel()
|
||||
assert.Equal(t, []string{"core-agent", "version"}, os.Args)
|
||||
}
|
||||
|
||||
// --- registerAppCommands ---
|
||||
|
||||
func TestCommands_RegisterAppCommands_Good(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -12,10 +12,6 @@ import (
|
|||
)
|
||||
|
||||
func main() {
|
||||
// Set log level early — before ServiceStartup to suppress startup noise.
|
||||
// --quiet/-q reduces to errors only, --debug shows everything.
|
||||
applyLogLevel()
|
||||
|
||||
c := core.New(
|
||||
core.WithOption("name", "core-agent"),
|
||||
core.WithService(agentic.ProcessRegister),
|
||||
|
|
|
|||
|
|
@ -434,6 +434,7 @@ func (s *PrepSubsystem) gitCmd(ctx context.Context, dir string, args ...string)
|
|||
|
||||
## Changelog
|
||||
|
||||
- 2026-03-29: cmd/core-agent no longer rewrites `os.Args` before startup. The binary-owned commands now use named handlers, keeping the entrypoint on Core CLI primitives instead of repo-local argument mutation.
|
||||
- 2026-03-29: brain/provider.go no longer imports net/http for Gin handlers. Handler responses now use named status constants and shared response helpers. HTTP remains intentionally centralised in pkg/agentic/transport.go.
|
||||
- 2026-03-26: WIP — net/http consolidated to transport.go (ONE file). net/url + io/fs eliminated. RFC-025 updated with 3 new quality gates (net/http, net/url, io/fs). 1:1 test + example test coverage. Array[T].Deduplicate replaces custom helpers.
|
||||
- 2026-03-25: Quality gates pass. Zero disallowed imports (all 10). encoding/json→Core JSON. path/filepath→Core Path. os→Core Env/Fs. io→Core ReadAll/WriteAll. go-process fully Result-native. ServiceRuntime on all subsystems. 22 named Actions + Task pipeline. ChannelNotifier→IPC. Reference docs synced.
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue