feat: add cli contract and local browser events

This commit is contained in:
QiuSW
2026-07-22 15:19:11 +08:00
parent 82f3c1be0e
commit 26cfa8b921
8 changed files with 210 additions and 6 deletions
+68
View File
@@ -2,8 +2,12 @@ package main
import (
"context"
"encoding/json"
"fmt"
"io"
"log/slog"
"os"
"strings"
"chub/internal/platform/config"
"chub/internal/platform/logging"
@@ -18,6 +22,9 @@ import (
const version = "0.1.0-dev"
func main() {
if len(os.Args) > 1 {
os.Exit(runCLI(os.Args[1:], os.Stdout, os.Stderr))
}
ctx := context.Background()
logger := logging.New(os.Stderr)
logger.InfoContext(ctx, "chub starting", "version", version)
@@ -25,6 +32,67 @@ func main() {
app.Main()
}
type cliError struct {
Code string `json:"code"`
Message string `json:"message"`
}
func runCLI(args []string, out, errout io.Writer) int {
if len(args) == 0 {
return 2
}
command := args[0]
if command == "--help" || command == "-h" {
fmt.Fprintln(out, "chub [start|list|stop|restart|events]")
return 0
}
path, err := config.DefaultPath()
if err != nil {
writeCLIError(errout, "system_error", err.Error())
return 6
}
store, err := config.New(path)
if err != nil {
writeCLIError(errout, "system_error", err.Error())
return 6
}
switch command {
case "list":
value, err := store.Load()
if err != nil {
writeCLIError(errout, "system_error", err.Error())
return 6
}
return writeJSON(out, map[string]any{"instances": value.Instances})
case "events":
// T-203 exposes a local JSON-lines snapshot; the live in-process bus is
// consumed by the UI and will be connected to a loopback transport later.
value, err := store.Load()
if err != nil {
writeCLIError(errout, "system_error", err.Error())
return 6
}
return writeJSON(out, map[string]any{"event": "browser.snapshot", "instances": value.Instances})
case "start", "stop", "restart":
writeCLIError(errout, "service_unavailable", strings.TrimSpace(command)+" requires the BrowserManager adapter")
return 6
default:
writeCLIError(errout, "invalid_argument", "unknown command: "+command)
return 2
}
}
func writeJSON(out io.Writer, value any) int {
if err := json.NewEncoder(out).Encode(value); err != nil {
return 6
}
return 0
}
func writeCLIError(out io.Writer, code, message string) {
_ = json.NewEncoder(out).Encode(cliError{Code: code, Message: message})
}
func runWindow(logger *slog.Logger) {
window := new(app.Window)
window.Option(app.Title("Chub 浏览器管理"), app.Size(unit.Dp(1100), unit.Dp(720)))
+14
View File
@@ -0,0 +1,14 @@
package main
import (
"bytes"
"strings"
"testing"
)
func TestRunCLIRejectsUnknownCommandWithStableCode(t *testing.T) {
var out bytes.Buffer
if code := runCLI([]string{"wat"}, &out, &out); code != 2 || !strings.Contains(out.String(), `"invalid_argument"`) {
t.Fatalf("code=%d output=%s", code, out.String())
}
}