--- /dev/null
+package main
+
+import (
+ "context"
+ "fmt"
+ "os"
+ "strings"
+)
+
+// usage is the help text of the command.
+const usage = `Usage: onechat [COMMAND]
+
+Commands:
+ backup FILE archive the running daemon data
+ restore FILE restore into an empty data directory
+ chat talk to the agent in this terminal (default)
+ daemon run the agent, Telegram, and WhatsApp
+ import [-n] [--agent NAME] ZIP...
+ import WhatsApp history (stop the daemon first)
+ -n print the plan without model calls
+ --agent NAME import into an existing direct child (default: root)
+ login log in to ChatGPT with a device code
+ probe LOG COUNT [BUILDS] measure the compactor on a log, with real calls
+ version show the build version
+ help show this help
+
+Chat needs a running daemon. ONECHAT_DIR sets the data directory.
+In chat, /image PATH [caption] sends a JPEG, PNG, or WebP image up to 20 MB.
+Quote PATH with single or double quotes when it contains spaces.
+`
+
+// version is set by the package build and stays dev for direct Go builds.
+var version = "dev"
+
+// parseCommand dispatches args with ctx and prints command output.
+func parseCommand(ctx context.Context, args []string) error {
+ switch {
+ case len(args) == 1 && (args[0] == "help" || args[0] == "--help" || args[0] == "-h"):
+ _, err := fmt.Print(usage)
+ if err != nil {
+ return fmt.Errorf("write command help: %w", err)
+ }
+ case len(args) == 1 && args[0] == "version":
+ _, err := fmt.Println(version)
+ if err != nil {
+ return fmt.Errorf("write build version: %w", err)
+ }
+ case len(args) == 1 && args[0] == "login":
+ err := chatgptLogin(ctx, os.Stdout)
+ if err != nil {
+ return err
+ }
+
+ // A signal is the normal stop of the daemon and the client, so their
+ // result does not include ctx.Err().
+ case len(args) == 1 && args[0] == "daemon":
+ return daemon(ctx, os.Stdout)
+ case len(args) == 0 || len(args) == 1 && args[0] == "chat":
+ return terminal(ctx, os.Stdin, os.Stdout)
+ case len(args) == 2 && args[0] == "backup":
+ return backup(ctx, args[1], os.Stdout)
+ case len(args) == 2 && args[0] == "restore":
+ return restore(ctx, args[1], os.Stdout)
+ case len(args) > 0 && args[0] == "import":
+ return whatsappImport(ctx, args[1:], os.Stdout)
+ case len(args) > 0 && args[0] == "probe":
+ err := probe(ctx, args[1:], os.Stdout)
+ if err != nil {
+ return err
+ }
+ default:
+ return fmt.Errorf("unknown command %q\n\n%s", strings.Join(args, " "), strings.TrimSuffix(usage, "\n"))
+ }
+
+ return ctx.Err()
+}
"fmt"
"os"
"os/signal"
- "strings"
"syscall"
)
-// usage is the help text of the command.
-const usage = `Usage: onechat [COMMAND]
-
-Commands:
- backup FILE archive the running daemon data
- restore FILE restore into an empty data directory
- chat talk to the agent in this terminal (default)
- daemon run the agent, Telegram, and WhatsApp
- import [-n] [--agent NAME] ZIP...
- import WhatsApp history (stop the daemon first)
- -n print the plan without model calls
- --agent NAME import into an existing direct child (default: root)
- login log in to ChatGPT with a device code
- probe LOG COUNT [BUILDS] measure the compactor on a log, with real calls
- version show the build version
- help show this help
-
-Chat needs a running daemon. ONECHAT_DIR sets the data directory.
-In chat, /image PATH [caption] sends a JPEG, PNG, or WebP image up to 20 MB.
-Quote PATH with single or double quotes when it contains spaces.
-`
-
-// version is set by the package build and stays dev for direct Go builds.
-var version = "dev"
-
func main() {
err := run()
if err != nil {
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer cancel()
- args := os.Args[1:]
- switch {
- case len(args) == 1 && (args[0] == "help" || args[0] == "--help" || args[0] == "-h"):
- _, err := fmt.Print(usage)
- if err != nil {
- return fmt.Errorf("write command help: %w", err)
- }
- case len(args) == 1 && args[0] == "version":
- _, err := fmt.Println(version)
- if err != nil {
- return fmt.Errorf("write build version: %w", err)
- }
- case len(args) == 1 && args[0] == "login":
- err := chatgptLogin(ctx, os.Stdout)
- if err != nil {
- return err
- }
-
- // A signal is the normal stop of the daemon and the client, so their
- // result does not include ctx.Err().
- case len(args) == 1 && args[0] == "daemon":
- return daemon(ctx, os.Stdout)
- case len(args) == 0 || len(args) == 1 && args[0] == "chat":
- return terminal(ctx, os.Stdin, os.Stdout)
- case len(args) == 2 && args[0] == "backup":
- return backup(ctx, args[1], os.Stdout)
- case len(args) == 2 && args[0] == "restore":
- return restore(ctx, args[1], os.Stdout)
- case len(args) > 0 && args[0] == "import":
- return whatsappImport(ctx, args[1:], os.Stdout)
- case len(args) > 0 && args[0] == "probe":
- err := probe(ctx, args[1:], os.Stdout)
- if err != nil {
- return err
- }
- default:
- return fmt.Errorf("unknown command %q\n\n%s", strings.Join(args, " "), strings.TrimSuffix(usage, "\n"))
- }
-
- return ctx.Err()
+ return parseCommand(ctx, os.Args[1:])
}