@pippit-dev/cli 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +50 -0
- package/cmd/auth/auth.go +144 -0
- package/cmd/root.go +42 -0
- package/cmd/short_drama/short_drama.go +196 -0
- package/cmd/short_drama_test.go +587 -0
- package/cmd/update/update.go +124 -0
- package/internal/auth/manager.go +146 -0
- package/internal/common/access_key.go +29 -0
- package/internal/common/client.go +137 -0
- package/internal/common/download_results.go +243 -0
- package/internal/common/list_thread_file.go +104 -0
- package/internal/common/runner.go +21 -0
- package/internal/common/upload_file.go +49 -0
- package/internal/config/config.go +72 -0
- package/internal/config/config_test.go +49 -0
- package/internal/short_drama/get_thread.go +137 -0
- package/internal/short_drama/mock.go +47 -0
- package/internal/short_drama/submit_run.go +81 -0
- package/package.json +45 -0
- package/scripts/install-wizard.js +71 -0
- package/scripts/install.js +170 -0
- package/scripts/platform.js +28 -0
- package/scripts/run.js +62 -0
- package/scripts/skills.js +32 -0
- package/skills/short-drama/SKILL.md +280 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Pippit-dev
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# pippit-cli
|
|
2
|
+
|
|
3
|
+
Minimal demo CLI for Pippit workflows.
|
|
4
|
+
|
|
5
|
+
## Short Drama Run Demo
|
|
6
|
+
|
|
7
|
+
Install from npm after the package is published. The installer downloads the
|
|
8
|
+
matching prebuilt binary for macOS, Linux, or Windows:
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
npx @pippit-dev/cli@latest install
|
|
12
|
+
export XYQ_ACCESS_KEY="<access-key>"
|
|
13
|
+
pippit-cli short-drama +submit-run --message "写一个赛博朋克短剧开头"
|
|
14
|
+
pippit-cli short-drama +upload-file --path ./story.md
|
|
15
|
+
pippit-cli short-drama +get-thread --thread-id thread_123 --run-id run_456 --after-seq 0
|
|
16
|
+
pippit-cli short-drama +download-result --output-dir ./thread_123/results/result.mp4 --url URL
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
NPM package names must be lowercase, so the publishable package name is
|
|
20
|
+
`@pippit-dev/cli` rather than `@Pippit-dev/cli`.
|
|
21
|
+
|
|
22
|
+
Submit a Run task for the short drama scene:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
export XYQ_ACCESS_KEY="<access-key>"
|
|
26
|
+
go run . short-drama +submit-run --message "写一个赛博朋克短剧开头"
|
|
27
|
+
go run . short-drama +upload-file --path ./story.md
|
|
28
|
+
go run . short-drama +get-thread --thread-id thread_123 --run-id run_456 --after-seq 0
|
|
29
|
+
go run . short-drama +download-result --output-dir ./thread_123/results/result.mp4 --url URL
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
`+submit-run` calls `/api/biz/v1/skill/submit_run` and prints `thread_id`,
|
|
33
|
+
`run_id`, and `web_thread_link`; `--message` is required.
|
|
34
|
+
`+get-thread` calls
|
|
35
|
+
`/api/biz/v1/skill/get_thread` and prints extracted `messages`.
|
|
36
|
+
`+download-result` downloads the result URL to
|
|
37
|
+
the `--output-dir` file path. `+upload-file` is still mocked while
|
|
38
|
+
its real service contract is wired.
|
|
39
|
+
|
|
40
|
+
## HTTP Client
|
|
41
|
+
|
|
42
|
+
Command modules should receive `common.Runner` for service calls. Runtime
|
|
43
|
+
settings such as base URL, HTTP timeout, and API paths are loaded by
|
|
44
|
+
`internal/config` and paired with `common.Client` in the runner.
|
|
45
|
+
|
|
46
|
+
## Auth
|
|
47
|
+
|
|
48
|
+
`short-drama +submit-run` and `short-drama +get-thread` authenticate with
|
|
49
|
+
`Authorization: Bearer <XYQ_ACCESS_KEY>`. OAuth command code remains available,
|
|
50
|
+
but runtime short drama requests do not use it.
|
package/cmd/auth/auth.go
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
package authcmd
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"fmt"
|
|
5
|
+
"io"
|
|
6
|
+
"strings"
|
|
7
|
+
"time"
|
|
8
|
+
|
|
9
|
+
"github.com/Pippit-dev/pippit-cli/internal/auth"
|
|
10
|
+
"github.com/Pippit-dev/pippit-cli/internal/common"
|
|
11
|
+
"github.com/bytedance/sonic"
|
|
12
|
+
"github.com/spf13/cobra"
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
type checkResult struct {
|
|
16
|
+
Pending bool `json:"pending"`
|
|
17
|
+
State any `json:"state,omitempty"`
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
func NewCommand(stdout, stderr io.Writer, runner *common.Runner) *cobra.Command {
|
|
21
|
+
cmd := &cobra.Command{
|
|
22
|
+
Use: "auth",
|
|
23
|
+
Short: "Manage Pippit OAuth login state",
|
|
24
|
+
}
|
|
25
|
+
cmd.SetOut(stdout)
|
|
26
|
+
cmd.SetErr(stderr)
|
|
27
|
+
cmd.AddCommand(newLoginCommand(stdout, stderr, runner))
|
|
28
|
+
cmd.AddCommand(newCheckCommand(stdout, stderr, runner))
|
|
29
|
+
cmd.AddCommand(newStatusCommand(stdout, stderr, runner))
|
|
30
|
+
cmd.AddCommand(newLogoutCommand(stdout, stderr, runner))
|
|
31
|
+
return cmd
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
func newLoginCommand(stdout, stderr io.Writer, runner *common.Runner) *cobra.Command {
|
|
35
|
+
cmd := &cobra.Command{
|
|
36
|
+
Use: "login",
|
|
37
|
+
Short: "Start an OAuth device login flow",
|
|
38
|
+
Args: cobra.NoArgs,
|
|
39
|
+
RunE: func(cmd *cobra.Command, _ []string) error {
|
|
40
|
+
if runner == nil || runner.AuthAuthorizer == nil {
|
|
41
|
+
return fmt.Errorf("auth manager is required")
|
|
42
|
+
}
|
|
43
|
+
flow, err := runner.AuthAuthorizer.NewLoginFlow(cmd.Context())
|
|
44
|
+
if err != nil {
|
|
45
|
+
return err
|
|
46
|
+
}
|
|
47
|
+
return writeJSON(stdout, flow)
|
|
48
|
+
},
|
|
49
|
+
}
|
|
50
|
+
cmd.SetOut(stdout)
|
|
51
|
+
cmd.SetErr(stderr)
|
|
52
|
+
return cmd
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
func newCheckCommand(stdout, stderr io.Writer, runner *common.Runner) *cobra.Command {
|
|
56
|
+
var deviceCode string
|
|
57
|
+
cmd := &cobra.Command{
|
|
58
|
+
Use: "check",
|
|
59
|
+
Short: "Check whether an OAuth device login has completed",
|
|
60
|
+
Args: cobra.NoArgs,
|
|
61
|
+
RunE: func(cmd *cobra.Command, _ []string) error {
|
|
62
|
+
deviceCode = strings.TrimSpace(deviceCode)
|
|
63
|
+
if deviceCode == "" {
|
|
64
|
+
return fmt.Errorf("--device-code is required")
|
|
65
|
+
}
|
|
66
|
+
if runner == nil || runner.AuthAuthorizer == nil {
|
|
67
|
+
return fmt.Errorf("auth manager is required")
|
|
68
|
+
}
|
|
69
|
+
state, err := runner.AuthAuthorizer.CheckLogin(cmd.Context(), deviceCode)
|
|
70
|
+
if auth.IsLoginPending(err) {
|
|
71
|
+
return writeJSON(stdout, checkResult{Pending: true})
|
|
72
|
+
}
|
|
73
|
+
if err != nil {
|
|
74
|
+
return err
|
|
75
|
+
}
|
|
76
|
+
v := map[string]any{
|
|
77
|
+
"logged_in": state.LoggedIn,
|
|
78
|
+
"expires_at": state.ExpiresAt.Format(time.RFC3339),
|
|
79
|
+
}
|
|
80
|
+
return writeJSON(stdout, checkResult{State: v})
|
|
81
|
+
},
|
|
82
|
+
}
|
|
83
|
+
cmd.SetOut(stdout)
|
|
84
|
+
cmd.SetErr(stderr)
|
|
85
|
+
cmd.Flags().StringVar(&deviceCode, "device-code", "", "device code returned by auth login")
|
|
86
|
+
return cmd
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
func newStatusCommand(stdout, stderr io.Writer, runner *common.Runner) *cobra.Command {
|
|
90
|
+
cmd := &cobra.Command{
|
|
91
|
+
Use: "status",
|
|
92
|
+
Short: "Show current OAuth login state",
|
|
93
|
+
Args: cobra.NoArgs,
|
|
94
|
+
RunE: func(cmd *cobra.Command, _ []string) error {
|
|
95
|
+
if runner == nil || runner.AuthAuthorizer == nil {
|
|
96
|
+
return fmt.Errorf("auth manager is required")
|
|
97
|
+
}
|
|
98
|
+
state, err := runner.AuthAuthorizer.State(cmd.Context())
|
|
99
|
+
if err != nil {
|
|
100
|
+
return err
|
|
101
|
+
}
|
|
102
|
+
if !state.LoggedIn {
|
|
103
|
+
return fmt.Errorf("not logged in")
|
|
104
|
+
}
|
|
105
|
+
v := map[string]any{
|
|
106
|
+
"logged_in": state.LoggedIn,
|
|
107
|
+
"expires_at": state.ExpiresAt.Format(time.RFC3339),
|
|
108
|
+
}
|
|
109
|
+
return writeJSON(stdout, v)
|
|
110
|
+
},
|
|
111
|
+
}
|
|
112
|
+
cmd.SetOut(stdout)
|
|
113
|
+
cmd.SetErr(stderr)
|
|
114
|
+
return cmd
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
func newLogoutCommand(stdout, stderr io.Writer, runner *common.Runner) *cobra.Command {
|
|
118
|
+
cmd := &cobra.Command{
|
|
119
|
+
Use: "logout",
|
|
120
|
+
Short: "Clear local OAuth login state",
|
|
121
|
+
Args: cobra.NoArgs,
|
|
122
|
+
RunE: func(cmd *cobra.Command, _ []string) error {
|
|
123
|
+
if runner == nil || runner.AuthAuthorizer == nil {
|
|
124
|
+
return fmt.Errorf("auth manager is required")
|
|
125
|
+
}
|
|
126
|
+
if err := runner.AuthAuthorizer.Logout(cmd.Context()); err != nil {
|
|
127
|
+
return err
|
|
128
|
+
}
|
|
129
|
+
return writeJSON(stdout, map[string]bool{"logged_out": true})
|
|
130
|
+
},
|
|
131
|
+
}
|
|
132
|
+
cmd.SetOut(stdout)
|
|
133
|
+
cmd.SetErr(stderr)
|
|
134
|
+
return cmd
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
func writeJSON(w io.Writer, v any) error {
|
|
138
|
+
data, err := sonic.Marshal(v)
|
|
139
|
+
if err != nil {
|
|
140
|
+
return err
|
|
141
|
+
}
|
|
142
|
+
_, err = fmt.Fprintln(w, string(data))
|
|
143
|
+
return err
|
|
144
|
+
}
|
package/cmd/root.go
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
package cmd
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"io"
|
|
5
|
+
"os"
|
|
6
|
+
|
|
7
|
+
// authcmd "github.com/Pippit-dev/pippit-cli/cmd/auth"
|
|
8
|
+
"github.com/Pippit-dev/pippit-cli/cmd/short_drama"
|
|
9
|
+
updatecmd "github.com/Pippit-dev/pippit-cli/cmd/update"
|
|
10
|
+
"github.com/Pippit-dev/pippit-cli/internal/auth"
|
|
11
|
+
"github.com/Pippit-dev/pippit-cli/internal/common"
|
|
12
|
+
"github.com/Pippit-dev/pippit-cli/internal/config"
|
|
13
|
+
"github.com/spf13/cobra"
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
// Execute runs the pippit-cli command tree.
|
|
17
|
+
func Execute() error {
|
|
18
|
+
return NewRootCommand(os.Stdout, os.Stderr).Execute()
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
func NewRootCommand(stdout, stderr io.Writer) *cobra.Command {
|
|
22
|
+
cfg := config.Load()
|
|
23
|
+
authManager := auth.NewManager(cfg)
|
|
24
|
+
client := common.NewHTTPClient(cfg.BaseURL, cfg.HTTPTimeout, common.NewAccessKeyAuthorizer(cfg.AccessKey))
|
|
25
|
+
runner := common.NewRunner(cfg, client, authManager)
|
|
26
|
+
return newRootCommand(stdout, stderr, runner)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
func newRootCommand(stdout, stderr io.Writer, runner *common.Runner) *cobra.Command {
|
|
30
|
+
root := &cobra.Command{
|
|
31
|
+
Use: "pippit-cli",
|
|
32
|
+
Short: "Pippit CLI",
|
|
33
|
+
SilenceUsage: true,
|
|
34
|
+
SilenceErrors: true,
|
|
35
|
+
}
|
|
36
|
+
root.SetOut(stdout)
|
|
37
|
+
root.SetErr(stderr)
|
|
38
|
+
// root.AddCommand(authcmd.NewCommand(stdout, stderr, runner)) // temporarily disabled; auth is via access key injection
|
|
39
|
+
root.AddCommand(short_drama.NewCommand(stdout, stderr, runner))
|
|
40
|
+
root.AddCommand(updatecmd.NewCommand(stdout, stderr))
|
|
41
|
+
return root
|
|
42
|
+
}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
package short_drama
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"fmt"
|
|
5
|
+
"io"
|
|
6
|
+
"path/filepath"
|
|
7
|
+
"strings"
|
|
8
|
+
|
|
9
|
+
"github.com/Pippit-dev/pippit-cli/internal/common"
|
|
10
|
+
"github.com/Pippit-dev/pippit-cli/internal/short_drama"
|
|
11
|
+
"github.com/bytedance/sonic"
|
|
12
|
+
"github.com/spf13/cobra"
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
// NewCommand builds the short_drama scene command tree.
|
|
16
|
+
func NewCommand(stdout, stderr io.Writer, runner *common.Runner) *cobra.Command {
|
|
17
|
+
cmd := &cobra.Command{
|
|
18
|
+
Use: "short-drama",
|
|
19
|
+
Short: "Short drama generation workflows",
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
cmd.SetOut(stdout)
|
|
23
|
+
cmd.SetErr(stderr)
|
|
24
|
+
cmd.AddCommand(newShortDramaSubmitRunCommand(stdout, stderr, runner))
|
|
25
|
+
cmd.AddCommand(newShortDramaUploadFileCommand(stdout, stderr, runner))
|
|
26
|
+
cmd.AddCommand(newShortDramaDownloadResultCommand(stdout, stderr, runner))
|
|
27
|
+
cmd.AddCommand(newShortDramaGetThreadCommand(stdout, stderr, runner))
|
|
28
|
+
cmd.AddCommand(newShortDramaListThreadFileCommand(stdout, stderr, runner))
|
|
29
|
+
return cmd
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
func newShortDramaSubmitRunCommand(stdout, stderr io.Writer, runner *common.Runner) *cobra.Command {
|
|
33
|
+
var opts short_drama.SubmitRunOptions
|
|
34
|
+
|
|
35
|
+
cmd := &cobra.Command{
|
|
36
|
+
Use: "+submit-run",
|
|
37
|
+
Short: "Submit a Run task for the short drama scene",
|
|
38
|
+
Args: cobra.NoArgs,
|
|
39
|
+
RunE: func(cmd *cobra.Command, _ []string) error {
|
|
40
|
+
opts.Message = strings.TrimSpace(opts.Message)
|
|
41
|
+
opts.ThreadID = strings.TrimSpace(opts.ThreadID)
|
|
42
|
+
|
|
43
|
+
if opts.Message == "" {
|
|
44
|
+
return fmt.Errorf("--message is required")
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
result, err := short_drama.SubmitRun(cmd.Context(), &opts, runner)
|
|
48
|
+
if err != nil {
|
|
49
|
+
return err
|
|
50
|
+
}
|
|
51
|
+
return writeJSON(stdout, result)
|
|
52
|
+
},
|
|
53
|
+
}
|
|
54
|
+
cmd.SetOut(stdout)
|
|
55
|
+
cmd.SetErr(stderr)
|
|
56
|
+
cmd.Flags().StringVar(&opts.Message, "message", "", "message to send to the short drama agent")
|
|
57
|
+
cmd.Flags().StringVar(&opts.ThreadID, "thread-id", "", "existing thread ID; omit to create a new thread")
|
|
58
|
+
cmd.Flags().StringArrayVar(&opts.AssetIDs, "asset-ids", nil, "asset ID to attach; repeat for multiple assets")
|
|
59
|
+
return cmd
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
func newShortDramaUploadFileCommand(stdout, stderr io.Writer, runner *common.Runner) *cobra.Command {
|
|
63
|
+
var opts common.UploadFileOptions
|
|
64
|
+
|
|
65
|
+
cmd := &cobra.Command{
|
|
66
|
+
Use: "+upload-file",
|
|
67
|
+
Short: "Upload a file for the short drama scene",
|
|
68
|
+
Args: cobra.NoArgs,
|
|
69
|
+
RunE: func(cmd *cobra.Command, _ []string) error {
|
|
70
|
+
opts.Path = strings.TrimSpace(opts.Path)
|
|
71
|
+
|
|
72
|
+
if opts.Path == "" {
|
|
73
|
+
return fmt.Errorf("--path is required")
|
|
74
|
+
}
|
|
75
|
+
opts.FileName = filepath.Base(opts.Path)
|
|
76
|
+
opts.Mock = true
|
|
77
|
+
|
|
78
|
+
result, err := common.UploadFile(cmd.Context(), opts, runner)
|
|
79
|
+
if err != nil {
|
|
80
|
+
return err
|
|
81
|
+
}
|
|
82
|
+
return writeJSON(stdout, result)
|
|
83
|
+
},
|
|
84
|
+
}
|
|
85
|
+
cmd.SetOut(stdout)
|
|
86
|
+
cmd.SetErr(stderr)
|
|
87
|
+
cmd.Flags().StringVar(&opts.Path, "path", "", "local file path to upload")
|
|
88
|
+
return cmd
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
func newShortDramaDownloadResultCommand(stdout, stderr io.Writer, runner *common.Runner) *cobra.Command {
|
|
92
|
+
var opts common.DownloadResultOptions
|
|
93
|
+
|
|
94
|
+
cmd := &cobra.Command{
|
|
95
|
+
Use: "+download-result",
|
|
96
|
+
Short: "Download a generated result URL",
|
|
97
|
+
Args: cobra.NoArgs,
|
|
98
|
+
RunE: func(cmd *cobra.Command, _ []string) error {
|
|
99
|
+
opts.OutputDir = strings.TrimSpace(opts.OutputDir)
|
|
100
|
+
if opts.OutputDir == "" {
|
|
101
|
+
return fmt.Errorf("--output-dir is required")
|
|
102
|
+
}
|
|
103
|
+
opts.URL = strings.TrimSpace(opts.URL)
|
|
104
|
+
if opts.URL == "" {
|
|
105
|
+
return fmt.Errorf("--url is required")
|
|
106
|
+
}
|
|
107
|
+
if opts.Workers <= 0 {
|
|
108
|
+
return fmt.Errorf("--workers must be greater than 0")
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
result, err := common.DownloadResult(cmd.Context(), opts, runner)
|
|
112
|
+
if err != nil {
|
|
113
|
+
return err
|
|
114
|
+
}
|
|
115
|
+
return writeJSON(stdout, result)
|
|
116
|
+
},
|
|
117
|
+
}
|
|
118
|
+
cmd.SetOut(stdout)
|
|
119
|
+
cmd.SetErr(stderr)
|
|
120
|
+
cmd.Flags().StringVar(&opts.URL, "url", "", "URL to download")
|
|
121
|
+
cmd.Flags().StringVar(&opts.OutputDir, "output-dir", "", "output file path")
|
|
122
|
+
cmd.Flags().IntVar(&opts.Workers, "workers", 5, "parallel download workers")
|
|
123
|
+
return cmd
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
func newShortDramaGetThreadCommand(stdout, stderr io.Writer, runner *common.Runner) *cobra.Command {
|
|
127
|
+
var opts short_drama.GetThreadOptions
|
|
128
|
+
|
|
129
|
+
cmd := &cobra.Command{
|
|
130
|
+
Use: "+get-thread",
|
|
131
|
+
Short: "Get a short drama thread detail",
|
|
132
|
+
Args: cobra.NoArgs,
|
|
133
|
+
RunE: func(cmd *cobra.Command, _ []string) error {
|
|
134
|
+
opts.ThreadID = strings.TrimSpace(opts.ThreadID)
|
|
135
|
+
if opts.ThreadID == "" {
|
|
136
|
+
return fmt.Errorf("--thread-id is required")
|
|
137
|
+
}
|
|
138
|
+
opts.RunID = strings.TrimSpace(opts.RunID)
|
|
139
|
+
|
|
140
|
+
result, err := short_drama.GetThread(cmd.Context(), &opts, runner)
|
|
141
|
+
if err != nil {
|
|
142
|
+
return err
|
|
143
|
+
}
|
|
144
|
+
return writeJSON(stdout, result)
|
|
145
|
+
},
|
|
146
|
+
}
|
|
147
|
+
cmd.SetOut(stdout)
|
|
148
|
+
cmd.SetErr(stderr)
|
|
149
|
+
cmd.Flags().StringVar(&opts.ThreadID, "thread-id", "", "thread ID to fetch")
|
|
150
|
+
cmd.Flags().StringVar(&opts.RunID, "run-id", "", "run ID to fetch")
|
|
151
|
+
cmd.Flags().IntVar(&opts.AfterSeq, "after-seq", 0, "return messages whose sequence is greater than or equal to this value")
|
|
152
|
+
return cmd
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
func newShortDramaListThreadFileCommand(stdout, stderr io.Writer, runner *common.Runner) *cobra.Command {
|
|
156
|
+
var opts common.ListThreadFileOptions
|
|
157
|
+
|
|
158
|
+
cmd := &cobra.Command{
|
|
159
|
+
Use: "+list-thread-file",
|
|
160
|
+
Short: "List files in a short drama thread",
|
|
161
|
+
Args: cobra.NoArgs,
|
|
162
|
+
RunE: func(cmd *cobra.Command, _ []string) error {
|
|
163
|
+
opts.ThreadID = strings.TrimSpace(opts.ThreadID)
|
|
164
|
+
if opts.ThreadID == "" {
|
|
165
|
+
return fmt.Errorf("--thread-id is required")
|
|
166
|
+
}
|
|
167
|
+
if opts.PageSize <= 0 || opts.PageSize > 100 {
|
|
168
|
+
return fmt.Errorf("--page-size must be between 1 and 100")
|
|
169
|
+
}
|
|
170
|
+
if opts.PageNum <= 0 {
|
|
171
|
+
return fmt.Errorf("--page-num must be greater than 0")
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
result, err := common.ListThreadFile(cmd.Context(), &opts, runner)
|
|
175
|
+
if err != nil {
|
|
176
|
+
return err
|
|
177
|
+
}
|
|
178
|
+
return writeJSON(stdout, result)
|
|
179
|
+
},
|
|
180
|
+
}
|
|
181
|
+
cmd.SetOut(stdout)
|
|
182
|
+
cmd.SetErr(stderr)
|
|
183
|
+
cmd.Flags().StringVar(&opts.ThreadID, "thread-id", "", "thread ID to list files for")
|
|
184
|
+
cmd.Flags().IntVar(&opts.PageNum, "page-num", 1, "page number (1-based)")
|
|
185
|
+
cmd.Flags().IntVar(&opts.PageSize, "page-size", 100, "number of files per page (between 1 and 100)")
|
|
186
|
+
return cmd
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
func writeJSON(w io.Writer, v any) error {
|
|
190
|
+
data, err := sonic.Marshal(v)
|
|
191
|
+
if err != nil {
|
|
192
|
+
return err
|
|
193
|
+
}
|
|
194
|
+
_, err = fmt.Fprintln(w, string(data))
|
|
195
|
+
return err
|
|
196
|
+
}
|