Track bundled vendor runtime sources
Some checks failed
CI / main (push) Has been cancelled
CI / release-e2e (push) Has been cancelled

This commit is contained in:
2026-07-07 10:05:50 +08:00
parent fbe179ab53
commit 52636c91ae
2111 changed files with 1850012 additions and 14 deletions

31
vendor/aigcpanel/cli/cmd/model_list.go vendored Normal file
View File

@@ -0,0 +1,31 @@
package cmd
import (
"aigcpanel-cli/internal"
"github.com/spf13/cobra"
)
var modelListCmd = &cobra.Command{
Use: "model_list",
Short: "List installed AI models",
RunE: func(cmd *cobra.Command, args []string) error {
cfg, err := internal.LoadAuthConfig()
if err != nil {
return err
}
result, err := internal.DoRequest(cfg, "/api/model/list", map[string]any{})
if err != nil {
return err
}
// 只保留 name/title/version/functions去掉 id
if data, ok := result["data"].([]any); ok {
for _, item := range data {
if model, ok := item.(map[string]any); ok {
delete(model, "id")
}
}
}
return internal.PrintJSON(result)
},
}

29
vendor/aigcpanel/cli/cmd/root.go vendored Normal file
View File

@@ -0,0 +1,29 @@
package cmd
import (
"os"
"github.com/spf13/cobra"
)
var appVersion string
// Execute sets the version and runs the root command.
func Execute(version string) {
appVersion = version
if err := rootCmd.Execute(); err != nil {
os.Exit(1)
}
}
var rootCmd = &cobra.Command{
Use: "aigcpanel",
Short: "AIGCPanel CLI",
Long: "AIGCPanel command-line tool for interacting with the local AigcPanel service.",
}
func init() {
rootCmd.AddCommand(versionCmd)
rootCmd.AddCommand(modelListCmd)
rootCmd.AddCommand(taskCmd)
}

217
vendor/aigcpanel/cli/cmd/task.go vendored Normal file
View File

@@ -0,0 +1,217 @@
package cmd
import (
"encoding/json"
"fmt"
"os"
"strings"
"time"
"aigcpanel-cli/internal"
"github.com/spf13/cobra"
)
var taskCmd = &cobra.Command{
Use: "task",
Short: "Submit a task and wait for result",
Long: `Submit a task to AigcPanel and poll until completion.
Usage:
aigcpanel task --biz <biz> [--key value ...]
aigcpanel task --biz <biz> --task-id <id> --stage <stage> [--key value ...]
Flags:
--biz Required. Task type (e.g. VideoCompress, SoundGenerate)
--task-id Task ID of a paused task to continue (used with --stage)
--stage Stage name to continue (e.g. Config, Confirm)
For long parameter values, use --key-json /path/to/file.json to read from a JSON file.
Examples:
aigcpanel task --biz VideoCompress --file /path/to/video.mp4
aigcpanel task --biz SoundGenerate --text "Hello world"
aigcpanel task --biz VideoZoom --video /path/to/video.mp4
aigcpanel task --biz VideoZoom --task-id 123 --stage Config --times-json ./_temp/times.json`,
DisableFlagParsing: true,
RunE: func(cmd *cobra.Command, args []string) error {
biz, taskId, stage, stageData, modelConfig, helpRequested, err := parseTaskArgs(args)
if err != nil {
return err
}
if helpRequested {
return cmd.Help()
}
if biz == "" {
return fmt.Errorf("--biz is required")
}
cfg, err := internal.LoadAuthConfig()
if err != nil {
return err
}
// Continue a paused task
if taskId != "" && stage != "" {
continueResult, err := internal.DoRequest(cfg, "/api/task/continue", map[string]any{
"taskId": taskId,
"stage": stage,
"data": stageData,
})
if err != nil {
return err
}
cCode, _ := continueResult["code"].(float64)
if cCode != 0 {
return internal.PrintJSON(continueResult)
}
// Poll for result after continue
return pollTask(cfg, taskId)
}
// Submit new task
submitResult, err := internal.DoRequest(cfg, "/api/task/submit", map[string]any{
"biz": biz,
"modelConfig": modelConfig,
})
if err != nil {
return err
}
code, _ := submitResult["code"].(float64)
if code != 0 {
return internal.PrintJSON(submitResult)
}
dataMap, _ := submitResult["data"].(map[string]any)
newTaskId, _ := dataMap["taskId"].(string)
if newTaskId == "" {
return fmt.Errorf("no taskId returned from task submit")
}
return pollTask(cfg, newTaskId)
},
}
// pollTask polls /api/model/query until the task reaches a terminal state.
func pollTask(cfg *internal.AuthConfig, taskId string) error {
deadline := time.Now().Add(120 * time.Second)
for time.Now().Before(deadline) {
queryResult, err := internal.DoRequest(cfg, "/api/model/query", map[string]any{
"taskId": taskId,
})
if err != nil {
return err
}
qCode, _ := queryResult["code"].(float64)
if qCode != 0 {
return internal.PrintJSON(queryResult)
}
qData, _ := queryResult["data"].(map[string]any)
status, _ := qData["status"].(string)
switch status {
case "success", "pause":
return internal.PrintJSON(queryResult)
case "error", "fail":
return internal.PrintJSON(queryResult)
default:
time.Sleep(500 * time.Millisecond)
continue
}
}
return internal.PrintJSON(map[string]any{
"code": -1,
"msg": "timeout waiting for task result",
})
}
// parseTaskArgs manually parses --key value style arguments.
// Reserved flags: --biz, --task-id, --stage.
// Flags ending in -json are treated as JSON file paths.
// All other --key value pairs become either modelConfig or stageData entries
// depending on whether --stage is provided.
func parseTaskArgs(args []string) (biz, taskId, stage string, stageData map[string]any, modelConfig map[string]any, helpRequested bool, err error) {
modelConfig = map[string]any{}
stageData = map[string]any{}
// First pass: extract reserved flags
type kv struct{ key, value string }
var pairs []kv
i := 0
for i < len(args) {
arg := args[i]
if arg == "--help" || arg == "-h" {
return "", "", "", nil, nil, true, nil
}
if !strings.HasPrefix(arg, "--") {
i++
continue
}
key := strings.TrimPrefix(arg, "--")
if i+1 >= len(args) || strings.HasPrefix(args[i+1], "--") {
fmt.Fprintf(os.Stderr, "warning: flag --%s has no value, ignoring\n", key)
i++
continue
}
value := args[i+1]
i += 2
switch key {
case "biz":
biz = value
case "task-id":
taskId = value
case "stage":
stage = value
default:
pairs = append(pairs, kv{key, value})
}
}
// Second pass: distribute remaining flags to modelConfig or stageData
for _, p := range pairs {
key, value := p.key, p.value
// JSON file flag: --key-json /path/to/file.json
if strings.HasSuffix(key, "-json") {
realKey := strings.TrimSuffix(key, "-json")
fileBytes, readErr := os.ReadFile(value)
if readErr != nil {
err = fmt.Errorf("cannot read JSON file for --%s: %w", key, readErr)
return
}
var parsed any
if jsonErr := json.Unmarshal(fileBytes, &parsed); jsonErr != nil {
err = fmt.Errorf("invalid JSON in file for --%s: %w", key, jsonErr)
return
}
if stage != "" {
stageData[realKey] = parsed
} else {
modelConfig[realKey] = parsed
}
continue
}
// Regular flag: auto-parse JSON arrays/objects
trimmed := strings.TrimSpace(value)
var parsedValue any
if (strings.HasPrefix(trimmed, "[") && strings.HasSuffix(trimmed, "]")) ||
(strings.HasPrefix(trimmed, "{") && strings.HasSuffix(trimmed, "}")) {
var parsed any
if jsonErr := json.Unmarshal([]byte(trimmed), &parsed); jsonErr == nil {
parsedValue = parsed
} else {
parsedValue = value
}
} else {
parsedValue = value
}
if stage != "" {
stageData[key] = parsedValue
} else {
modelConfig[key] = parsedValue
}
}
return biz, taskId, stage, stageData, modelConfig, false, nil
}

17
vendor/aigcpanel/cli/cmd/version.go vendored Normal file
View File

@@ -0,0 +1,17 @@
package cmd
import (
"aigcpanel-cli/internal"
"github.com/spf13/cobra"
)
var versionCmd = &cobra.Command{
Use: "version",
Short: "Print version information",
RunE: func(cmd *cobra.Command, args []string) error {
return internal.PrintJSON(map[string]string{
"version": appVersion,
})
},
}

10
vendor/aigcpanel/cli/go.mod vendored Normal file
View File

@@ -0,0 +1,10 @@
module aigcpanel-cli
go 1.21
require github.com/spf13/cobra v1.8.0
require (
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
)

10
vendor/aigcpanel/cli/go.sum vendored Normal file
View File

@@ -0,0 +1,10 @@
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

60
vendor/aigcpanel/cli/internal/client.go vendored Normal file
View File

@@ -0,0 +1,60 @@
package internal
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
)
// DoRequest sends a POST request to the local AigcPanel HTTP server.
func DoRequest(cfg *AuthConfig, urlPath string, body any) (map[string]any, error) {
var reqBody io.Reader
if body != nil {
b, err := json.Marshal(body)
if err != nil {
return nil, fmt.Errorf("marshal request body: %w", err)
}
reqBody = bytes.NewReader(b)
}
url := fmt.Sprintf("http://127.0.0.1:%d%s", cfg.Port, urlPath)
req, err := http.NewRequest(http.MethodPost, url, reqBody)
if err != nil {
return nil, fmt.Errorf("create request: %w", err)
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer "+cfg.Token)
resp, err := http.DefaultClient.Do(req)
if err != nil {
return nil, fmt.Errorf("request failed: %w (is AigcPanel running?)", err)
}
defer resp.Body.Close()
respBytes, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("read response: %w", err)
}
if resp.StatusCode == http.StatusUnauthorized {
return nil, fmt.Errorf("unauthorized: token mismatch, restart AigcPanel and try again")
}
var result map[string]any
if err := json.Unmarshal(respBytes, &result); err != nil {
return nil, fmt.Errorf("parse response: %w", err)
}
return result, nil
}
// PrintJSON outputs a value as indented JSON to stdout.
func PrintJSON(v any) error {
b, err := json.MarshalIndent(v, "", " ")
if err != nil {
return err
}
fmt.Println(string(b))
return nil
}

66
vendor/aigcpanel/cli/internal/config.go vendored Normal file
View File

@@ -0,0 +1,66 @@
package internal
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"runtime"
)
// AuthConfig holds the port and token read from cli-auth.json
type AuthConfig struct {
Port int `json:"port"`
Token string `json:"token"`
}
// userDataDir returns the Electron userData directory path matching app.getPath('userData')
// which uses the app name "aigcpanel".
func userDataDir() (string, error) {
switch runtime.GOOS {
case "darwin":
home, err := os.UserHomeDir()
if err != nil {
return "", err
}
return filepath.Join(home, "Library", "Application Support", "aigcpanel"), nil
case "windows":
appData := os.Getenv("APPDATA")
if appData == "" {
return "", fmt.Errorf("APPDATA environment variable not set")
}
return filepath.Join(appData, "aigcpanel"), nil
default:
// Linux: XDG_CONFIG_HOME or ~/.config
configDir := os.Getenv("XDG_CONFIG_HOME")
if configDir == "" {
home, err := os.UserHomeDir()
if err != nil {
return "", err
}
configDir = filepath.Join(home, ".config")
}
return filepath.Join(configDir, "aigcpanel"), nil
}
}
// LoadAuthConfig reads cli-auth.json from the aigcpanel userData directory.
func LoadAuthConfig() (*AuthConfig, error) {
dir, err := userDataDir()
if err != nil {
return nil, fmt.Errorf("cannot determine userData directory: %w", err)
}
filePath := filepath.Join(dir, "cli-auth.json")
data, err := os.ReadFile(filePath)
if err != nil {
return nil, fmt.Errorf("cannot read %s: %w (is AigcPanel running?)", filePath, err)
}
var cfg AuthConfig
if err := json.Unmarshal(data, &cfg); err != nil {
return nil, fmt.Errorf("invalid cli-auth.json: %w", err)
}
if cfg.Port == 0 || cfg.Token == "" {
return nil, fmt.Errorf("cli-auth.json is incomplete (port=%d, token empty=%v)", cfg.Port, cfg.Token == "")
}
return &cfg, nil
}

10
vendor/aigcpanel/cli/main.go vendored Normal file
View File

@@ -0,0 +1,10 @@
package main
import "aigcpanel-cli/cmd"
// Version is injected at build time via ldflags: -X main.Version=x.x.x
var Version = "dev"
func main() {
cmd.Execute(Version)
}