docs(ax): align workspace reference usage examples
Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
620f702591
commit
f32720b692
7 changed files with 135 additions and 1 deletions
|
|
@ -342,6 +342,58 @@ func TestLib_ExtractWorkspace_Good_ReferenceHeaders(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestLib_ExtractWorkspace_Good_ReferenceUsageExamples(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
data := &WorkspaceData{Repo: "test-repo", Task: "carry AX usage examples into workspace references"}
|
||||
|
||||
if err := ExtractWorkspace("default", dir, data); err != nil {
|
||||
t.Fatalf("ExtractWorkspace failed: %v", err)
|
||||
}
|
||||
|
||||
cases := map[string][]string{
|
||||
core.JoinPath(dir, ".core", "reference", "array.go"): {
|
||||
`arr := core.NewArray("prep", "dispatch")`,
|
||||
`arr.Add("verify", "merge")`,
|
||||
`arr.AddUnique("verify", "verify", "merge")`,
|
||||
},
|
||||
core.JoinPath(dir, ".core", "reference", "config.go"): {
|
||||
`timeout := core.ConfigGet[int](c.Config(), "agent.timeout")`,
|
||||
},
|
||||
core.JoinPath(dir, ".core", "reference", "embed.go"): {
|
||||
`core.AddAsset("docs", "RFC.md", packed)`,
|
||||
`r := core.GeneratePack(pkg)`,
|
||||
},
|
||||
core.JoinPath(dir, ".core", "reference", "error.go"): {
|
||||
`if core.Is(err, context.Canceled) { return }`,
|
||||
`stack := core.FormatStackTrace(err)`,
|
||||
`r := c.Error().Reports(10)`,
|
||||
},
|
||||
core.JoinPath(dir, ".core", "reference", "log.go"): {
|
||||
`log := core.NewLog(core.LogOptions{Level: core.LevelDebug, Output: os.Stdout})`,
|
||||
`core.SetRedactKeys("token", "password")`,
|
||||
`core.Security("entitlement.denied", "action", "process.run")`,
|
||||
},
|
||||
core.JoinPath(dir, ".core", "reference", "runtime.go"): {
|
||||
`r := c.ServiceStartup(context.Background(), nil)`,
|
||||
`r := core.NewRuntime(app)`,
|
||||
`name := runtime.ServiceName()`,
|
||||
},
|
||||
}
|
||||
|
||||
for path, snippets := range cases {
|
||||
r := testFs.Read(path)
|
||||
if !r.OK {
|
||||
t.Fatalf("failed to read %s", path)
|
||||
}
|
||||
text := r.Value.(string)
|
||||
for _, snippet := range snippets {
|
||||
if !core.Contains(text, snippet) {
|
||||
t.Errorf("%s missing usage example snippet %q", path, snippet)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestLib_MountEmbed_Bad(t *testing.T) {
|
||||
result := mountEmbed(promptFiles, "missing-dir")
|
||||
if result.OK {
|
||||
|
|
|
|||
|
|
@ -10,17 +10,23 @@ type Array[T comparable] struct {
|
|||
items []T
|
||||
}
|
||||
|
||||
// NewArray creates an empty Array.
|
||||
// NewArray creates an Array with the provided items.
|
||||
//
|
||||
// arr := core.NewArray("prep", "dispatch")
|
||||
func NewArray[T comparable](items ...T) *Array[T] {
|
||||
return &Array[T]{items: items}
|
||||
}
|
||||
|
||||
// Add appends values.
|
||||
//
|
||||
// arr.Add("verify", "merge")
|
||||
func (s *Array[T]) Add(values ...T) {
|
||||
s.items = append(s.items, values...)
|
||||
}
|
||||
|
||||
// AddUnique appends values only if not already present.
|
||||
//
|
||||
// arr.AddUnique("verify", "verify", "merge")
|
||||
func (s *Array[T]) AddUnique(values ...T) {
|
||||
for _, v := range values {
|
||||
if !s.Contains(v) {
|
||||
|
|
@ -40,6 +46,8 @@ func (s *Array[T]) Contains(val T) bool {
|
|||
}
|
||||
|
||||
// Filter returns a new Array with elements matching the predicate.
|
||||
//
|
||||
// r := arr.Filter(func(step string) bool { return core.Contains(step, "prep") })
|
||||
func (s *Array[T]) Filter(fn func(T) bool) Result {
|
||||
filtered := &Array[T]{}
|
||||
for _, v := range s.items {
|
||||
|
|
@ -68,6 +76,8 @@ func (s *Array[T]) Remove(val T) {
|
|||
}
|
||||
|
||||
// Deduplicate removes duplicate values, preserving order.
|
||||
//
|
||||
// arr.Deduplicate()
|
||||
func (s *Array[T]) Deduplicate() {
|
||||
seen := make(map[T]struct{})
|
||||
result := make([]T, 0, len(s.items))
|
||||
|
|
@ -91,6 +101,8 @@ func (s *Array[T]) Clear() {
|
|||
}
|
||||
|
||||
// AsSlice returns a copy of the underlying slice.
|
||||
//
|
||||
// items := arr.AsSlice()
|
||||
func (s *Array[T]) AsSlice() []T {
|
||||
if s.items == nil {
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -117,6 +117,8 @@ func (e *Config) Int(key string) int { return ConfigGet[int](e, key) }
|
|||
func (e *Config) Bool(key string) bool { return ConfigGet[bool](e, key) }
|
||||
|
||||
// ConfigGet retrieves a typed configuration value.
|
||||
//
|
||||
// timeout := core.ConfigGet[int](c.Config(), "agent.timeout")
|
||||
func ConfigGet[T any](e *Config, key string) T {
|
||||
r := e.Get(key)
|
||||
if !r.OK {
|
||||
|
|
|
|||
|
|
@ -51,6 +51,8 @@ var (
|
|||
)
|
||||
|
||||
// AddAsset registers a packed asset at runtime (called from generated init()).
|
||||
//
|
||||
// core.AddAsset("docs", "RFC.md", packed)
|
||||
func AddAsset(group, name, data string) {
|
||||
assetGroupsMu.Lock()
|
||||
defer assetGroupsMu.Unlock()
|
||||
|
|
@ -214,6 +216,8 @@ func ScanAssets(filenames []string) Result {
|
|||
}
|
||||
|
||||
// GeneratePack creates Go source code that embeds the scanned assets.
|
||||
//
|
||||
// r := core.GeneratePack(pkg)
|
||||
func GeneratePack(pkg ScannedPackage) Result {
|
||||
b := NewBuilder()
|
||||
|
||||
|
|
|
|||
|
|
@ -120,18 +120,25 @@ func NewCode(code, msg string) error {
|
|||
|
||||
// Is reports whether any error in err's tree matches target.
|
||||
// Wrapper around errors.Is for convenience.
|
||||
//
|
||||
// if core.Is(err, context.Canceled) { return }
|
||||
func Is(err, target error) bool {
|
||||
return errors.Is(err, target)
|
||||
}
|
||||
|
||||
// As finds the first error in err's tree that matches target.
|
||||
// Wrapper around errors.As for convenience.
|
||||
//
|
||||
// var typed *core.Err
|
||||
// if core.As(err, &typed) { core.Println(typed.Operation) }
|
||||
func As(err error, target any) bool {
|
||||
return errors.As(err, target)
|
||||
}
|
||||
|
||||
// NewError creates a simple error with the given text.
|
||||
// Wrapper around errors.New for convenience.
|
||||
//
|
||||
// err := core.NewError("workspace not found")
|
||||
func NewError(text string) error {
|
||||
return errors.New(text)
|
||||
}
|
||||
|
|
@ -147,6 +154,8 @@ func ErrorJoin(errs ...error) error {
|
|||
|
||||
// Operation extracts the operation name from an error.
|
||||
// Returns empty string if the error is not an *Err.
|
||||
//
|
||||
// op := core.Operation(err)
|
||||
func Operation(err error) string {
|
||||
var e *Err
|
||||
if As(err, &e) {
|
||||
|
|
@ -157,6 +166,8 @@ func Operation(err error) string {
|
|||
|
||||
// ErrorCode extracts the error code from an error.
|
||||
// Returns empty string if the error is not an *Err or has no code.
|
||||
//
|
||||
// code := core.ErrorCode(err)
|
||||
func ErrorCode(err error) string {
|
||||
var e *Err
|
||||
if As(err, &e) {
|
||||
|
|
@ -180,6 +191,8 @@ func ErrorMessage(err error) string {
|
|||
|
||||
// Root returns the root cause of an error chain.
|
||||
// Unwraps until no more wrapped errors are found.
|
||||
//
|
||||
// cause := core.Root(err)
|
||||
func Root(err error) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
|
|
@ -212,6 +225,8 @@ func AllOperations(err error) iter.Seq[string] {
|
|||
|
||||
// StackTrace returns the logical stack trace (chain of operations) from an error.
|
||||
// It returns an empty slice if no operational context is found.
|
||||
//
|
||||
// trace := core.StackTrace(err)
|
||||
func StackTrace(err error) []string {
|
||||
var stack []string
|
||||
for op := range AllOperations(err) {
|
||||
|
|
@ -221,6 +236,8 @@ func StackTrace(err error) []string {
|
|||
}
|
||||
|
||||
// FormatStackTrace returns a pretty-printed logical stack trace.
|
||||
//
|
||||
// stack := core.FormatStackTrace(err)
|
||||
func FormatStackTrace(err error) string {
|
||||
var ops []string
|
||||
for op := range AllOperations(err) {
|
||||
|
|
@ -338,6 +355,8 @@ func (h *ErrorPanic) Recover() {
|
|||
}
|
||||
|
||||
// SafeGo runs a function in a goroutine with panic recovery.
|
||||
//
|
||||
// c.Error().SafeGo(func() { runWorker() })
|
||||
func (h *ErrorPanic) SafeGo(fn func()) {
|
||||
go func() {
|
||||
defer h.Recover()
|
||||
|
|
@ -346,6 +365,8 @@ func (h *ErrorPanic) SafeGo(fn func()) {
|
|||
}
|
||||
|
||||
// Reports returns the last n crash reports from the file.
|
||||
//
|
||||
// r := c.Error().Reports(10)
|
||||
func (h *ErrorPanic) Reports(n int) Result {
|
||||
if h.filePath == "" {
|
||||
return Result{}
|
||||
|
|
|
|||
|
|
@ -110,6 +110,8 @@ type LogOptions struct {
|
|||
var RotationWriterFactory func(RotationLogOptions) goio.WriteCloser
|
||||
|
||||
// New creates a new Log with the given options.
|
||||
//
|
||||
// log := core.NewLog(core.LogOptions{Level: core.LevelDebug, Output: os.Stdout})
|
||||
func NewLog(opts LogOptions) *Log {
|
||||
output := opts.Output
|
||||
if opts.Rotation != nil && opts.Rotation.Filename != "" && RotationWriterFactory != nil {
|
||||
|
|
@ -286,6 +288,8 @@ func (l *Log) Security(msg string, keyvals ...any) {
|
|||
|
||||
// Username returns the current system username.
|
||||
// It uses os/user for reliability and falls back to environment variables.
|
||||
//
|
||||
// user := core.Username()
|
||||
func Username() string {
|
||||
if u, err := user.Current(); err == nil {
|
||||
return u.Username
|
||||
|
|
@ -307,46 +311,64 @@ func init() {
|
|||
}
|
||||
|
||||
// Default returns the default logger.
|
||||
//
|
||||
// log := core.Default()
|
||||
func Default() *Log {
|
||||
return defaultLogPtr.Load()
|
||||
}
|
||||
|
||||
// SetDefault sets the default logger.
|
||||
//
|
||||
// core.SetDefault(core.NewLog(core.LogOptions{Level: core.LevelWarn}))
|
||||
func SetDefault(l *Log) {
|
||||
defaultLogPtr.Store(l)
|
||||
}
|
||||
|
||||
// SetLevel sets the default logger's level.
|
||||
//
|
||||
// core.SetLevel(core.LevelDebug)
|
||||
func SetLevel(level Level) {
|
||||
Default().SetLevel(level)
|
||||
}
|
||||
|
||||
// SetRedactKeys sets the default logger's redaction keys.
|
||||
//
|
||||
// core.SetRedactKeys("token", "password")
|
||||
func SetRedactKeys(keys ...string) {
|
||||
Default().SetRedactKeys(keys...)
|
||||
}
|
||||
|
||||
// Debug logs to the default logger.
|
||||
//
|
||||
// core.Debug("agent dispatched", "repo", "core/agent")
|
||||
func Debug(msg string, keyvals ...any) {
|
||||
Default().Debug(msg, keyvals...)
|
||||
}
|
||||
|
||||
// Info logs to the default logger.
|
||||
//
|
||||
// core.Info("workspace ready", "path", "/srv/ws-42")
|
||||
func Info(msg string, keyvals ...any) {
|
||||
Default().Info(msg, keyvals...)
|
||||
}
|
||||
|
||||
// Warn logs to the default logger.
|
||||
//
|
||||
// core.Warn("queue delay increased", "seconds", 30)
|
||||
func Warn(msg string, keyvals ...any) {
|
||||
Default().Warn(msg, keyvals...)
|
||||
}
|
||||
|
||||
// Error logs to the default logger.
|
||||
//
|
||||
// core.Error("dispatch failed", "err", err)
|
||||
func Error(msg string, keyvals ...any) {
|
||||
Default().Error(msg, keyvals...)
|
||||
}
|
||||
|
||||
// Security logs to the default logger.
|
||||
//
|
||||
// core.Security("entitlement.denied", "action", "process.run")
|
||||
func Security(msg string, keyvals ...any) {
|
||||
Default().Security(msg, keyvals...)
|
||||
}
|
||||
|
|
@ -360,6 +382,8 @@ type LogErr struct {
|
|||
}
|
||||
|
||||
// NewLogErr creates a LogErr bound to the given logger.
|
||||
//
|
||||
// logErr := core.NewLogErr(core.Default())
|
||||
func NewLogErr(log *Log) *LogErr {
|
||||
return &LogErr{log: log}
|
||||
}
|
||||
|
|
@ -381,6 +405,8 @@ type LogPanic struct {
|
|||
}
|
||||
|
||||
// NewLogPanic creates a LogPanic bound to the given logger.
|
||||
//
|
||||
// panicLog := core.NewLogPanic(core.Default())
|
||||
func NewLogPanic(log *Log) *LogPanic {
|
||||
return &LogPanic{log: log}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@ type ServiceRuntime[T any] struct {
|
|||
}
|
||||
|
||||
// NewServiceRuntime creates a ServiceRuntime for a service constructor.
|
||||
//
|
||||
// svc.ServiceRuntime = core.NewServiceRuntime(c, ServiceOptions{Queue: "default"})
|
||||
func NewServiceRuntime[T any](c *Core, opts T) *ServiceRuntime[T] {
|
||||
return &ServiceRuntime[T]{core: c, opts: opts}
|
||||
}
|
||||
|
|
@ -43,6 +45,8 @@ func (r *ServiceRuntime[T]) Config() *Config { return r.core.Config() }
|
|||
// --- Lifecycle ---
|
||||
|
||||
// ServiceStartup runs OnStart for all registered services that have one.
|
||||
//
|
||||
// r := c.ServiceStartup(context.Background(), nil)
|
||||
func (c *Core) ServiceStartup(ctx context.Context, options any) Result {
|
||||
c.shutdown.Store(false)
|
||||
c.context, c.cancel = context.WithCancel(ctx)
|
||||
|
|
@ -63,6 +67,8 @@ func (c *Core) ServiceStartup(ctx context.Context, options any) Result {
|
|||
}
|
||||
|
||||
// ServiceShutdown drains background tasks, then stops all registered services.
|
||||
//
|
||||
// r := c.ServiceShutdown(context.Background())
|
||||
func (c *Core) ServiceShutdown(ctx context.Context) Result {
|
||||
c.shutdown.Store(true)
|
||||
c.cancel() // signal all context-aware tasks to stop
|
||||
|
|
@ -116,6 +122,8 @@ type Runtime struct {
|
|||
type ServiceFactory func() Result
|
||||
|
||||
// NewWithFactories creates a Runtime with the provided service factories.
|
||||
//
|
||||
// r := core.NewWithFactories(app, map[string]core.ServiceFactory{"brain": newBrainService})
|
||||
func NewWithFactories(app any, factories map[string]ServiceFactory) Result {
|
||||
c := New(WithOptions(NewOptions(Option{Key: "name", Value: "core"})))
|
||||
c.app.Runtime = app
|
||||
|
|
@ -144,18 +152,27 @@ func NewWithFactories(app any, factories map[string]ServiceFactory) Result {
|
|||
}
|
||||
|
||||
// NewRuntime creates a Runtime with no custom services.
|
||||
//
|
||||
// r := core.NewRuntime(app)
|
||||
func NewRuntime(app any) Result {
|
||||
return NewWithFactories(app, map[string]ServiceFactory{})
|
||||
}
|
||||
|
||||
// ServiceName returns "Core" — the Runtime's service identity.
|
||||
//
|
||||
// name := runtime.ServiceName()
|
||||
func (r *Runtime) ServiceName() string { return "Core" }
|
||||
|
||||
// ServiceStartup starts all services via the embedded Core.
|
||||
//
|
||||
// runtime.ServiceStartup(context.Background(), nil)
|
||||
func (r *Runtime) ServiceStartup(ctx context.Context, options any) Result {
|
||||
return r.Core.ServiceStartup(ctx, options)
|
||||
}
|
||||
|
||||
// ServiceShutdown stops all services via the embedded Core.
|
||||
//
|
||||
// runtime.ServiceShutdown(context.Background())
|
||||
func (r *Runtime) ServiceShutdown(ctx context.Context) Result {
|
||||
if r.Core != nil {
|
||||
return r.Core.ServiceShutdown(ctx)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue