]> git.giacomolli.uk - onechat/blob - command.go
e62c4b6edabb2b97813ceb1bc308195036917c3d
[onechat] / command.go
1 package main
2
3 import (
4 "context"
5 "fmt"
6 "os"
7 "strings"
8 )
9
10 // usage is the help text of the command.
11 const usage = `Usage: onechat [COMMAND]
12
13 Commands:
14 backup FILE archive the running daemon data
15 restore FILE restore into an empty data directory
16 chat talk to the agent in this terminal (default)
17 daemon run the agent, Telegram, and WhatsApp
18 import [-n] [--agent NAME] ZIP...
19 import WhatsApp history (stop the daemon first)
20 -n print the plan without model calls
21 --agent NAME import into an existing direct child (default: root)
22 notify --source SOURCE --id ID --text TEXT
23 send an external event to the root
24 login log in to ChatGPT with a device code
25 probe LOG COUNT [BUILDS] measure the compactor on a log, with real calls
26 version show the build version
27 help show this help
28
29 Chat needs a running daemon. ONECHAT_DIR sets the data directory.
30 In chat, /image PATH [caption] sends a JPEG, PNG, or WebP image up to 20 MB.
31 Quote PATH with single or double quotes when it contains spaces.
32 `
33
34 // version is set by the package build and stays dev for direct Go builds.
35 var version = "dev"
36
37 // parseCommand dispatches args with ctx and prints command output.
38 func parseCommand(ctx context.Context, args []string) error {
39 switch {
40 case len(args) == 1 && (args[0] == "help" || args[0] == "--help" || args[0] == "-h"):
41 _, err := fmt.Print(usage)
42 if err != nil {
43 return fmt.Errorf("write command help: %w", err)
44 }
45 case len(args) == 1 && args[0] == "version":
46 _, err := fmt.Println(version)
47 if err != nil {
48 return fmt.Errorf("write build version: %w", err)
49 }
50 case len(args) == 1 && args[0] == "login":
51 err := chatgptLogin(ctx, os.Stdout)
52 if err != nil {
53 return fmt.Errorf("log in: %w", err)
54 }
55
56 // A signal is the normal stop of the daemon and the client, so their
57 // result does not include ctx.Err().
58 case len(args) == 1 && args[0] == "daemon":
59 err := daemon(ctx, os.Stdout)
60 if err != nil {
61 return fmt.Errorf("run daemon: %w", err)
62 }
63
64 return nil
65 case len(args) == 0 || len(args) == 1 && args[0] == "chat":
66 err := terminal(ctx, os.Stdin, os.Stdout)
67 if err != nil {
68 return fmt.Errorf("run terminal: %w", err)
69 }
70
71 return nil
72 case len(args) == 2 && args[0] == "backup":
73 err := backup(ctx, args[1], os.Stdout)
74 if err != nil {
75 return fmt.Errorf("run backup: %w", err)
76 }
77
78 return nil
79 case len(args) == 2 && args[0] == "restore":
80 err := restore(ctx, args[1], os.Stdout)
81 if err != nil {
82 return fmt.Errorf("run restore: %w", err)
83 }
84
85 return nil
86 case len(args) > 0 && args[0] == "notify":
87 err := notify(ctx, args[1:], os.Stdout)
88 if err != nil {
89 return fmt.Errorf("submit external event: %w", err)
90 }
91
92 return nil
93 case len(args) > 0 && args[0] == "import":
94 err := whatsappImport(ctx, args[1:], os.Stdout)
95 if err != nil {
96 return fmt.Errorf("import WhatsApp history: %w", err)
97 }
98
99 return nil
100 case len(args) > 0 && args[0] == "probe":
101 err := probe(ctx, args[1:], os.Stdout)
102 if err != nil {
103 return fmt.Errorf("run probe: %w", err)
104 }
105 default:
106 return fmt.Errorf("unknown command %q\n\n%s", strings.Join(args, " "), strings.TrimSuffix(usage, "\n"))
107 }
108
109 return ctx.Err()
110 }