corago/codex-keep/main.go

85 lines
2.2 KiB
Go
Raw Normal View History

package main
import (
"context"
"errors"
"flag"
"fmt"
"io"
"os"
"os/signal"
"path/filepath"
"syscall"
"time"
)
type options struct {
socket string
state string
base time.Duration
cap time.Duration
poll time.Duration
}
func statePath() string {
root := os.Getenv("XDG_STATE_HOME")
if root == "" {
home, _ := os.UserHomeDir()
root = filepath.Join(home, ".local", "state")
}
return filepath.Join(root, "codex-keep", "state.json")
}
func socketPath() string {
home := os.Getenv("CODEX_HOME")
if home == "" {
root, _ := os.UserHomeDir()
home = filepath.Join(root, ".codex")
}
return filepath.Join(home, "app-server-control", "app-server-control.sock")
}
func parseOptions(args []string, output io.Writer) (options, error) {
var opts options
flags := flag.NewFlagSet("codex-keep", flag.ContinueOnError)
flags.SetOutput(output)
flags.StringVar(&opts.socket, "socket", socketPath(), "Codex daemon Unix socket")
flags.StringVar(&opts.state, "state", statePath(), "Recovery checkpoint")
flags.DurationVar(&opts.base, "base-delay", 5*time.Second, "Initial retry delay")
flags.DurationVar(&opts.cap, "max-delay", 5*time.Minute, "Retry delay ceiling")
flags.DurationVar(&opts.poll, "poll", 5*time.Second, "Reconciliation interval")
flags.Usage = func() {
_, _ = fmt.Fprintln(output, "Usage: codex-keep [options]")
_, _ = fmt.Fprintln(output, "Reconcile failed active goals through the shared Codex daemon.")
flags.PrintDefaults()
}
if err := flags.Parse(args); err != nil {
return opts, err
}
if len(flags.Args()) != 0 {
return opts, errors.New("unexpected positional arguments")
}
if opts.base <= 0 || opts.cap < opts.base || opts.poll <= 0 {
return opts, errors.New("delays must satisfy 0 < base-delay <= max-delay and poll > 0")
}
if opts.state == "" {
return opts, errors.New("state path is empty")
}
return opts, nil
}
func main() {
opts, err := parseOptions(os.Args[1:], os.Stderr)
if errors.Is(err, flag.ErrHelp) {
return
}
if err == nil {
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer stop()
err = run(ctx, opts, os.Stderr)
}
if err != nil {
fmt.Fprintln(os.Stderr, "codex-keep:", err)
os.Exit(1)
}
}