@pippit-dev/cli 1.0.0 → 1.0.2

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.
@@ -9,7 +9,6 @@ import (
9
9
 
10
10
  "github.com/Pippit-dev/pippit-cli/internal/common"
11
11
  "github.com/Pippit-dev/pippit-cli/internal/short_drama"
12
- "github.com/bytedance/sonic"
13
12
  "github.com/spf13/cobra"
14
13
  )
15
14
 
@@ -24,9 +23,6 @@ func NewCommand(stdout, stderr io.Writer, runner *common.Runner) *cobra.Command
24
23
  cmd.SetErr(stderr)
25
24
  cmd.AddCommand(newShortDramaSubmitRunCommand(stdout, stderr, runner))
26
25
  cmd.AddCommand(newShortDramaUploadFileCommand(stdout, stderr, runner))
27
- cmd.AddCommand(newShortDramaDownloadResultCommand(stdout, stderr, runner))
28
- cmd.AddCommand(newShortDramaGetThreadCommand(stdout, stderr, runner))
29
- cmd.AddCommand(newShortDramaListThreadFileCommand(stdout, stderr, runner))
30
26
  return cmd
31
27
  }
32
28
 
@@ -47,14 +43,14 @@ func newShortDramaSubmitRunCommand(stdout, stderr io.Writer, runner *common.Runn
47
43
  opts.ThreadID = strings.TrimSpace(opts.ThreadID)
48
44
 
49
45
  if opts.Message == "" {
50
- return fmt.Errorf("--message is required")
46
+ return fmt.Errorf("缺少必填参数 --message")
51
47
  }
52
48
 
53
49
  result, err := short_drama.SubmitRun(cmd.Context(), &opts, runner)
54
50
  if err != nil {
55
51
  return err
56
52
  }
57
- return writeJSON(stdout, result)
53
+ return common.WriteJSON(stdout, result)
58
54
  }),
59
55
  }
60
56
  cmd.SetOut(stdout)
@@ -82,12 +78,15 @@ func newShortDramaUploadFileCommand(stdout, stderr io.Writer, runner *common.Run
82
78
  if opts.Path == "" {
83
79
  return fmt.Errorf("--path is required")
84
80
  }
81
+ if !isShortDramaUploadFile(opts.Path) {
82
+ return fmt.Errorf("短剧上传仅支持上传 .doc、.docx 和 .txt 文件")
83
+ }
85
84
 
86
85
  result, err := common.UploadFile(cmd.Context(), opts, runner)
87
86
  if err != nil {
88
87
  return err
89
88
  }
90
- return writeJSON(stdout, result)
89
+ return common.WriteJSON(stdout, result)
91
90
  }),
92
91
  }
93
92
  cmd.SetOut(stdout)
@@ -96,126 +95,6 @@ func newShortDramaUploadFileCommand(stdout, stderr io.Writer, runner *common.Run
96
95
  return cmd
97
96
  }
98
97
 
99
- func newShortDramaDownloadResultCommand(stdout, stderr io.Writer, runner *common.Runner) *cobra.Command {
100
- var opts common.DownloadResultOptions
101
-
102
- cmd := &cobra.Command{
103
- Use: "+download-result",
104
- Short: "Download a generated result URL",
105
- Args: cobra.NoArgs,
106
- RunE: withErrorLog("short-drama +download-result", func() map[string]string {
107
- fields := map[string]string{
108
- "output_path": opts.OutputPath,
109
- "has_url": strconv.FormatBool(strings.TrimSpace(opts.URL) != ""),
110
- "workers": strconv.Itoa(opts.Workers),
111
- }
112
- if opts.UpdatedAt > 0 {
113
- fields["updated_at"] = strconv.FormatInt(opts.UpdatedAt, 10)
114
- }
115
- return fields
116
- }, func(cmd *cobra.Command, _ []string) error {
117
- opts.OutputPath = strings.TrimSpace(opts.OutputPath)
118
- if opts.OutputPath == "" {
119
- return fmt.Errorf("--output-path is required")
120
- }
121
- opts.URL = strings.TrimSpace(opts.URL)
122
- if opts.URL == "" {
123
- return fmt.Errorf("--url is required")
124
- }
125
- if opts.Workers <= 0 {
126
- return fmt.Errorf("--workers must be greater than 0")
127
- }
128
-
129
- result, err := common.DownloadResult(cmd.Context(), opts, runner)
130
- if err != nil {
131
- return err
132
- }
133
- return writeJSON(stdout, result)
134
- }),
135
- }
136
- cmd.SetOut(stdout)
137
- cmd.SetErr(stderr)
138
- cmd.Flags().StringVar(&opts.URL, "url", "", "URL to download")
139
- cmd.Flags().StringVar(&opts.OutputPath, "output-path", "", "local output file path")
140
- cmd.Flags().Int64Var(&opts.UpdatedAt, "updated-at", 0, "remote file update time as a Unix timestamp")
141
- cmd.Flags().IntVar(&opts.Workers, "workers", 5, "parallel download workers")
142
- return cmd
143
- }
144
-
145
- func newShortDramaGetThreadCommand(stdout, stderr io.Writer, runner *common.Runner) *cobra.Command {
146
- var opts common.GetThreadOptions
147
-
148
- cmd := &cobra.Command{
149
- Use: "+get-thread",
150
- Short: "Get a short drama thread detail",
151
- Args: cobra.NoArgs,
152
- RunE: withErrorLog("short-drama +get-thread", func() map[string]string {
153
- return map[string]string{
154
- "thread_id": opts.ThreadID,
155
- "run_id": opts.RunID,
156
- }
157
- }, func(cmd *cobra.Command, _ []string) error {
158
- opts.ThreadID = strings.TrimSpace(opts.ThreadID)
159
- if opts.ThreadID == "" {
160
- return fmt.Errorf("--thread-id is required")
161
- }
162
- opts.RunID = strings.TrimSpace(opts.RunID)
163
-
164
- result, err := common.GetThread(cmd.Context(), &opts, runner)
165
- if err != nil {
166
- return err
167
- }
168
- _, err = fmt.Fprintln(stdout, result.ReadableText)
169
- return err
170
- }),
171
- }
172
- cmd.SetOut(stdout)
173
- cmd.SetErr(stderr)
174
- cmd.Flags().StringVar(&opts.ThreadID, "thread-id", "", "thread ID to fetch")
175
- cmd.Flags().StringVar(&opts.RunID, "run-id", "", "run ID to fetch")
176
- return cmd
177
- }
178
-
179
- func newShortDramaListThreadFileCommand(stdout, stderr io.Writer, runner *common.Runner) *cobra.Command {
180
- var opts common.ListThreadFileOptions
181
-
182
- cmd := &cobra.Command{
183
- Use: "+list-thread-file",
184
- Short: "List files in a short drama thread",
185
- Args: cobra.NoArgs,
186
- RunE: withErrorLog("short-drama +list-thread-file", func() map[string]string {
187
- return map[string]string{
188
- "thread_id": opts.ThreadID,
189
- "page_num": strconv.Itoa(opts.PageNum),
190
- "page_size": strconv.Itoa(opts.PageSize),
191
- }
192
- }, func(cmd *cobra.Command, _ []string) error {
193
- opts.ThreadID = strings.TrimSpace(opts.ThreadID)
194
- if opts.ThreadID == "" {
195
- return fmt.Errorf("--thread-id is required")
196
- }
197
- if opts.PageSize <= 0 || opts.PageSize > common.MaxListThreadFilePageSize {
198
- return fmt.Errorf("--page-size must be between 1 and %d", common.MaxListThreadFilePageSize)
199
- }
200
- if opts.PageNum <= 0 {
201
- return fmt.Errorf("--page-num must be greater than 0")
202
- }
203
-
204
- result, err := common.ListThreadFile(cmd.Context(), &opts, runner)
205
- if err != nil {
206
- return err
207
- }
208
- return writeJSON(stdout, result)
209
- }),
210
- }
211
- cmd.SetOut(stdout)
212
- cmd.SetErr(stderr)
213
- cmd.Flags().StringVar(&opts.ThreadID, "thread-id", "", "thread ID to list files for")
214
- cmd.Flags().IntVar(&opts.PageNum, "page-num", 1, "page number (1-based)")
215
- cmd.Flags().IntVar(&opts.PageSize, "page-size", common.MaxListThreadFilePageSize, fmt.Sprintf("number of files per page (between 1 and %d)", common.MaxListThreadFilePageSize))
216
- return cmd
217
- }
218
-
219
98
  func withErrorLog(command string, fields func() map[string]string, run func(*cobra.Command, []string) error) func(*cobra.Command, []string) error {
220
99
  return func(cmd *cobra.Command, args []string) error {
221
100
  err := run(cmd, args)
@@ -238,11 +117,11 @@ func fileNameForLog(path string) string {
238
117
  return filepath.Base(path)
239
118
  }
240
119
 
241
- func writeJSON(w io.Writer, v any) error {
242
- data, err := sonic.Marshal(v)
243
- if err != nil {
244
- return err
120
+ func isShortDramaUploadFile(path string) bool {
121
+ switch strings.ToLower(filepath.Ext(path)) {
122
+ case ".doc", ".docx", ".txt":
123
+ return true
124
+ default:
125
+ return false
245
126
  }
246
- _, err = fmt.Fprintln(w, string(data))
247
- return err
248
127
  }
@@ -124,7 +124,12 @@ func TestRootHelpListsSupportedCommands(t *testing.T) {
124
124
  }
125
125
  got := stdout.String()
126
126
  for _, want := range []string{
127
- "Pippit CLI submits short-drama workflows",
127
+ "Pippit CLI generates videos",
128
+ "generate-video",
129
+ "download-result",
130
+ "get-thread",
131
+ "list-thread-file",
132
+ "query-result",
128
133
  "short-drama",
129
134
  "update",
130
135
  "--version",
@@ -140,6 +145,28 @@ func TestRootHelpListsSupportedCommands(t *testing.T) {
140
145
  }
141
146
  }
142
147
 
148
+ func TestShortDramaDoesNotIncludeCommonThreadCommands(t *testing.T) {
149
+ var stdout, stderr bytes.Buffer
150
+ root := NewRootCommand(&stdout, &stderr)
151
+ cmd, _, err := root.Find([]string{"short-drama"})
152
+ if err != nil {
153
+ t.Fatalf("Find(short-drama) error = %v", err)
154
+ }
155
+ if cmd.CommandPath() != "pippit-tool-cli short-drama" {
156
+ t.Fatalf("CommandPath() = %q, want short-drama command", cmd.CommandPath())
157
+ }
158
+ removedCommands := map[string]bool{
159
+ "+download-result": true,
160
+ "+get-thread": true,
161
+ "+list-thread-file": true,
162
+ }
163
+ for _, child := range cmd.Commands() {
164
+ if removedCommands[child.Name()] {
165
+ t.Fatalf("short-drama child %s = %#v, want nil", child.Name(), child)
166
+ }
167
+ }
168
+ }
169
+
143
170
  func TestVersionFlagPrintsVersion(t *testing.T) {
144
171
  var stdout, stderr bytes.Buffer
145
172
  root := NewRootCommand(&stdout, &stderr)
@@ -162,7 +189,7 @@ func TestShortDramaSubmitRunRequiresMessage(t *testing.T) {
162
189
  if err == nil {
163
190
  t.Fatal("Execute() error = nil, want validation error")
164
191
  }
165
- if !strings.Contains(err.Error(), "--message is required") {
192
+ if !strings.Contains(err.Error(), "缺少必填参数 --message") {
166
193
  t.Fatalf("error = %q, want message validation", err)
167
194
  }
168
195
  }
@@ -302,12 +329,12 @@ func TestShortDramaUploadFileRejectsUnsupportedFileType(t *testing.T) {
302
329
  if err == nil {
303
330
  t.Fatal("Execute() error = nil, want file type validation error")
304
331
  }
305
- if !strings.Contains(err.Error(), "only .doc, .docx, and .txt uploads are supported") {
332
+ if !strings.Contains(err.Error(), "仅支持上传 .doc、.docx .txt") {
306
333
  t.Fatalf("error = %q, want unsupported type validation", err)
307
334
  }
308
335
  }
309
336
 
310
- func TestShortDramaDownloadResult(t *testing.T) {
337
+ func TestDownloadResult(t *testing.T) {
311
338
  server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
312
339
  if r.Header.Get("User-Agent") != "Pippit-CLI/1.0" {
313
340
  t.Fatalf("User-Agent = %q, want Pippit-CLI/1.0", r.Header.Get("User-Agent"))
@@ -326,7 +353,7 @@ func TestShortDramaDownloadResult(t *testing.T) {
326
353
  root := NewRootCommand(&stdout, &stderr)
327
354
  outputPath := filepath.Join("results", "cover.jpeg")
328
355
  root.SetArgs([]string{
329
- "short-drama", "+download-result",
356
+ "download-result",
330
357
  "--output-path", outputPath,
331
358
  "--workers", "2",
332
359
  "--url", server.URL + "/image?filename=ignored.jpeg",
@@ -358,7 +385,7 @@ func TestShortDramaDownloadResult(t *testing.T) {
358
385
  assertFileContent(t, wantFiles[0], "image-data")
359
386
  }
360
387
 
361
- func TestShortDramaDownloadResultSkipsExistingFile(t *testing.T) {
388
+ func TestDownloadResultSkipsExistingFile(t *testing.T) {
362
389
  serverCalled := false
363
390
  server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
364
391
  serverCalled = true
@@ -378,7 +405,7 @@ func TestShortDramaDownloadResultSkipsExistingFile(t *testing.T) {
378
405
  var stdout, stderr bytes.Buffer
379
406
  root := NewRootCommand(&stdout, &stderr)
380
407
  root.SetArgs([]string{
381
- "short-drama", "+download-result",
408
+ "download-result",
382
409
  "--output-path", outputPath,
383
410
  "--url", server.URL + "/image",
384
411
  })
@@ -404,7 +431,7 @@ func TestShortDramaDownloadResultSkipsExistingFile(t *testing.T) {
404
431
  assertFileContent(t, outputPath, "existing-data")
405
432
  }
406
433
 
407
- func TestShortDramaDownloadResultSkipsExistingFileWhenLocalIsFresh(t *testing.T) {
434
+ func TestDownloadResultSkipsExistingFileWhenLocalIsFresh(t *testing.T) {
408
435
  serverCalled := false
409
436
  server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
410
437
  serverCalled = true
@@ -429,7 +456,7 @@ func TestShortDramaDownloadResultSkipsExistingFileWhenLocalIsFresh(t *testing.T)
429
456
  var stdout, stderr bytes.Buffer
430
457
  root := NewRootCommand(&stdout, &stderr)
431
458
  root.SetArgs([]string{
432
- "short-drama", "+download-result",
459
+ "download-result",
433
460
  "--output-path", outputPath,
434
461
  "--updated-at", "1779716734",
435
462
  "--url", server.URL + "/image",
@@ -450,7 +477,7 @@ func TestShortDramaDownloadResultSkipsExistingFileWhenLocalIsFresh(t *testing.T)
450
477
  assertFileContent(t, outputPath, "existing-data")
451
478
  }
452
479
 
453
- func TestShortDramaDownloadResultOverwritesStaleExistingFile(t *testing.T) {
480
+ func TestDownloadResultOverwritesStaleExistingFile(t *testing.T) {
454
481
  serverCalled := false
455
482
  server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
456
483
  serverCalled = true
@@ -478,7 +505,7 @@ func TestShortDramaDownloadResultOverwritesStaleExistingFile(t *testing.T) {
478
505
  var stdout, stderr bytes.Buffer
479
506
  root := NewRootCommand(&stdout, &stderr)
480
507
  root.SetArgs([]string{
481
- "short-drama", "+download-result",
508
+ "download-result",
482
509
  "--output-path", outputPath,
483
510
  "--updated-at", "1779716734",
484
511
  "--url", server.URL + "/image",
@@ -509,7 +536,7 @@ func TestShortDramaDownloadResultOverwritesStaleExistingFile(t *testing.T) {
509
536
  }
510
537
  }
511
538
 
512
- func TestShortDramaDownloadResultDownloadsMetaJSON(t *testing.T) {
539
+ func TestDownloadResultDownloadsMetaJSON(t *testing.T) {
513
540
  server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
514
541
  if r.URL.Path != "/meta.json" {
515
542
  t.Fatalf("path = %s, want meta.json", r.URL.Path)
@@ -524,7 +551,7 @@ func TestShortDramaDownloadResultDownloadsMetaJSON(t *testing.T) {
524
551
  var stdout, stderr bytes.Buffer
525
552
  root := NewRootCommand(&stdout, &stderr)
526
553
  root.SetArgs([]string{
527
- "short-drama", "+download-result",
554
+ "download-result",
528
555
  "--output-path", outputPath,
529
556
  "--url", server.URL + "/meta.json",
530
557
  })
@@ -547,10 +574,10 @@ func TestShortDramaDownloadResultDownloadsMetaJSON(t *testing.T) {
547
574
  assertFileContent(t, outputPath, `{"ok":true}`)
548
575
  }
549
576
 
550
- func TestShortDramaDownloadResultRequiresOutputPath(t *testing.T) {
577
+ func TestDownloadResultRequiresOutputPath(t *testing.T) {
551
578
  var stdout, stderr bytes.Buffer
552
579
  root := NewRootCommand(&stdout, &stderr)
553
- root.SetArgs([]string{"short-drama", "+download-result", "--url", "https://example.com/image.png"})
580
+ root.SetArgs([]string{"download-result", "--url", "https://example.com/image.png"})
554
581
 
555
582
  err := root.Execute()
556
583
  if err == nil {
@@ -561,11 +588,11 @@ func TestShortDramaDownloadResultRequiresOutputPath(t *testing.T) {
561
588
  }
562
589
  }
563
590
 
564
- func TestShortDramaDownloadResultRejectsOutputDirFlag(t *testing.T) {
591
+ func TestDownloadResultRejectsOutputDirFlag(t *testing.T) {
565
592
  var stdout, stderr bytes.Buffer
566
593
  root := NewRootCommand(&stdout, &stderr)
567
594
  root.SetArgs([]string{
568
- "short-drama", "+download-result",
595
+ "download-result",
569
596
  "--output-dir", filepath.Join("results", "image.png"),
570
597
  "--url", "https://example.com/image.png",
571
598
  })
@@ -574,15 +601,15 @@ func TestShortDramaDownloadResultRejectsOutputDirFlag(t *testing.T) {
574
601
  if err == nil {
575
602
  t.Fatal("Execute() error = nil, want unknown flag error")
576
603
  }
577
- if !strings.Contains(err.Error(), "unknown flag: --output-dir") {
604
+ if !strings.Contains(err.Error(), "未知参数: --output-dir") {
578
605
  t.Fatalf("error = %q, want output-dir rejection", err)
579
606
  }
580
607
  }
581
608
 
582
- func TestShortDramaDownloadResultRequiresURL(t *testing.T) {
609
+ func TestDownloadResultRequiresURL(t *testing.T) {
583
610
  var stdout, stderr bytes.Buffer
584
611
  root := NewRootCommand(&stdout, &stderr)
585
- root.SetArgs([]string{"short-drama", "+download-result", "--output-path", filepath.Join("results", "image.png")})
612
+ root.SetArgs([]string{"download-result", "--output-path", filepath.Join("results", "image.png")})
586
613
 
587
614
  err := root.Execute()
588
615
  if err == nil {
@@ -593,21 +620,21 @@ func TestShortDramaDownloadResultRequiresURL(t *testing.T) {
593
620
  }
594
621
  }
595
622
 
596
- func TestShortDramaDownloadResultRejectsInvalidScheme(t *testing.T) {
623
+ func TestDownloadResultRejectsInvalidScheme(t *testing.T) {
597
624
  var stdout, stderr bytes.Buffer
598
625
  root := NewRootCommand(&stdout, &stderr)
599
- root.SetArgs([]string{"short-drama", "+download-result", "--output-path", filepath.Join("results", "image.png"), "--url", "file:///etc/passwd"})
626
+ root.SetArgs([]string{"download-result", "--output-path", filepath.Join("results", "image.png"), "--url", "file:///etc/passwd"})
600
627
 
601
628
  err := root.Execute()
602
629
  if err == nil {
603
630
  t.Fatal("Execute() error = nil, want scheme validation error")
604
631
  }
605
- if !strings.Contains(err.Error(), "only http and https are allowed") {
632
+ if !strings.Contains(err.Error(), "仅支持 http https") {
606
633
  t.Fatalf("error = %q, want scheme validation", err)
607
634
  }
608
635
  }
609
636
 
610
- func TestShortDramaDownloadResultAllFailed(t *testing.T) {
637
+ func TestDownloadResultAllFailed(t *testing.T) {
611
638
  server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
612
639
  w.WriteHeader(http.StatusNotFound)
613
640
  }))
@@ -618,7 +645,7 @@ func TestShortDramaDownloadResultAllFailed(t *testing.T) {
618
645
  var stdout, stderr bytes.Buffer
619
646
  root := NewRootCommand(&stdout, &stderr)
620
647
  root.SetArgs([]string{
621
- "short-drama", "+download-result",
648
+ "download-result",
622
649
  "--output-path", filepath.Join("results", "missing.png"),
623
650
  "--url", server.URL + "/notfound",
624
651
  })
@@ -627,7 +654,7 @@ func TestShortDramaDownloadResultAllFailed(t *testing.T) {
627
654
  if err == nil {
628
655
  t.Fatal("Execute() error = nil, want all-failed error")
629
656
  }
630
- if !strings.Contains(err.Error(), "all 1 download(s) failed") {
657
+ if !strings.Contains(err.Error(), "全部 1 个下载任务失败") {
631
658
  t.Fatalf("error = %q, want all-failed message", err)
632
659
  }
633
660
  logs := readDailyErrorLog(t)
@@ -643,7 +670,7 @@ func TestShortDramaDownloadResultAllFailed(t *testing.T) {
643
670
  }
644
671
  }
645
672
 
646
- func TestShortDramaDownloadResultOutputPath(t *testing.T) {
673
+ func TestDownloadResultOutputPath(t *testing.T) {
647
674
  server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
648
675
  _, _ = w.Write([]byte("image-data"))
649
676
  }))
@@ -655,7 +682,7 @@ func TestShortDramaDownloadResultOutputPath(t *testing.T) {
655
682
  root := NewRootCommand(&stdout, &stderr)
656
683
  outputPath := filepath.Join("custom", "nested", "cover.png")
657
684
  root.SetArgs([]string{
658
- "short-drama", "+download-result",
685
+ "download-result",
659
686
  "--output-path", outputPath,
660
687
  "--url", server.URL + "/image.png",
661
688
  })
@@ -671,7 +698,7 @@ func TestShortDramaDownloadResultOutputPath(t *testing.T) {
671
698
  assertFileContent(t, outputPath, "image-data")
672
699
  }
673
700
 
674
- func TestShortDramaGetThread(t *testing.T) {
701
+ func TestGetThread(t *testing.T) {
675
702
  server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
676
703
  if r.Method != http.MethodPost {
677
704
  t.Fatalf("method = %s, want POST", r.Method)
@@ -709,7 +736,7 @@ func TestShortDramaGetThread(t *testing.T) {
709
736
  var stdout, stderr bytes.Buffer
710
737
  root := newTestRootCommand(t, &stdout, &stderr, server.URL)
711
738
  root.SetArgs([]string{
712
- "short-drama", "+get-thread",
739
+ "get-thread",
713
740
  "--thread-id", "thread_123",
714
741
  "--run-id", "run_456",
715
742
  })
@@ -723,12 +750,12 @@ func TestShortDramaGetThread(t *testing.T) {
723
750
  }
724
751
  }
725
752
 
726
- func TestShortDramaGetThreadRequiresThreadID(t *testing.T) {
753
+ func TestGetThreadRequiresThreadID(t *testing.T) {
727
754
  clearDailyErrorLog(t)
728
755
 
729
756
  var stdout, stderr bytes.Buffer
730
757
  root := NewRootCommand(&stdout, &stderr)
731
- root.SetArgs([]string{"short-drama", "+get-thread"})
758
+ root.SetArgs([]string{"get-thread"})
732
759
 
733
760
  err := root.Execute()
734
761
  if err == nil {
@@ -742,7 +769,7 @@ func TestShortDramaGetThreadRequiresThreadID(t *testing.T) {
742
769
  if len(entries) != 1 {
743
770
  t.Fatalf("log entries = %d, want 1: %#v", len(entries), entries)
744
771
  }
745
- if entries[0]["command"] != "short-drama +get-thread" {
772
+ if entries[0]["command"] != "get-thread" {
746
773
  t.Fatalf("command = %v, want get-thread", entries[0]["command"])
747
774
  }
748
775
  if entries[0]["error"] != "--thread-id is required" {
@@ -750,7 +777,7 @@ func TestShortDramaGetThreadRequiresThreadID(t *testing.T) {
750
777
  }
751
778
  }
752
779
 
753
- func TestShortDramaGetThreadRequiresAccessKey(t *testing.T) {
780
+ func TestGetThreadRequiresAccessKey(t *testing.T) {
754
781
  server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
755
782
  t.Fatal("server should not receive request without access key")
756
783
  }))
@@ -758,7 +785,7 @@ func TestShortDramaGetThreadRequiresAccessKey(t *testing.T) {
758
785
 
759
786
  var stdout, stderr bytes.Buffer
760
787
  root := newTestRootCommandWithAccessKey(t, &stdout, &stderr, server.URL, "")
761
- root.SetArgs([]string{"short-drama", "+get-thread", "--thread-id", "thread_123"})
788
+ root.SetArgs([]string{"get-thread", "--thread-id", "thread_123"})
762
789
 
763
790
  err := root.Execute()
764
791
  if err == nil {
@@ -767,7 +794,7 @@ func TestShortDramaGetThreadRequiresAccessKey(t *testing.T) {
767
794
  assertAccessKeyGuidance(t, err)
768
795
  }
769
796
 
770
- func TestShortDramaListThreadFile(t *testing.T) {
797
+ func TestListThreadFile(t *testing.T) {
771
798
  server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
772
799
  if r.Method != http.MethodPost {
773
800
  t.Fatalf("method = %s, want POST", r.Method)
@@ -802,7 +829,7 @@ func TestShortDramaListThreadFile(t *testing.T) {
802
829
  var stdout, stderr bytes.Buffer
803
830
  root := newTestRootCommand(t, &stdout, &stderr, server.URL)
804
831
  root.SetArgs([]string{
805
- "short-drama", "+list-thread-file",
832
+ "list-thread-file",
806
833
  "--thread-id", "thread_123",
807
834
  "--page-num", "2",
808
835
  "--page-size", "10",
@@ -816,7 +843,7 @@ func TestShortDramaListThreadFile(t *testing.T) {
816
843
  if got["total"] != float64(1) {
817
844
  t.Fatalf("total = %v, want 1", got["total"])
818
845
  }
819
- wantMessage := "<system-remind>\n- total is below 200; continue querying with current --page-num 2\n</system-remind>"
846
+ wantMessage := "<system-remind>\n- 文件总数小于 200;继续使用当前 --page-num 2 查询\n</system-remind>"
820
847
  if got["message"] != wantMessage {
821
848
  t.Fatalf("message = %v, want current page hint", got["message"])
822
849
  }
@@ -843,7 +870,7 @@ func TestShortDramaListThreadFile(t *testing.T) {
843
870
  }
844
871
  }
845
872
 
846
- func TestShortDramaListThreadFileMessageWhenPageFull(t *testing.T) {
873
+ func TestListThreadFileMessageWhenPageFull(t *testing.T) {
847
874
  server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
848
875
  if !strings.Contains(r.URL.Path, "list_thread_file") {
849
876
  t.Fatalf("path = %s, want list_thread_file path", r.URL.Path)
@@ -855,7 +882,7 @@ func TestShortDramaListThreadFileMessageWhenPageFull(t *testing.T) {
855
882
  var stdout, stderr bytes.Buffer
856
883
  root := newTestRootCommand(t, &stdout, &stderr, server.URL)
857
884
  root.SetArgs([]string{
858
- "short-drama", "+list-thread-file",
885
+ "list-thread-file",
859
886
  "--thread-id", "thread_123",
860
887
  "--page-num", "2",
861
888
  "--page-size", "200",
@@ -866,16 +893,16 @@ func TestShortDramaListThreadFileMessageWhenPageFull(t *testing.T) {
866
893
  }
867
894
 
868
895
  got := decodeJSON(t, stdout.Bytes())
869
- wantMessage := "<system-remind>\n- total reached 200; query the next page with --page-num 3\n</system-remind>"
896
+ wantMessage := "<system-remind>\n- 文件总数已达到 200;请使用 --page-num 3 查询下一页\n</system-remind>"
870
897
  if got["message"] != wantMessage {
871
898
  t.Fatalf("message = %v, want next page hint", got["message"])
872
899
  }
873
900
  }
874
901
 
875
- func TestShortDramaListThreadFileRequiresThreadID(t *testing.T) {
902
+ func TestListThreadFileRequiresThreadID(t *testing.T) {
876
903
  var stdout, stderr bytes.Buffer
877
904
  root := NewRootCommand(&stdout, &stderr)
878
- root.SetArgs([]string{"short-drama", "+list-thread-file"})
905
+ root.SetArgs([]string{"list-thread-file"})
879
906
 
880
907
  err := root.Execute()
881
908
  if err == nil {
@@ -886,7 +913,7 @@ func TestShortDramaListThreadFileRequiresThreadID(t *testing.T) {
886
913
  }
887
914
  }
888
915
 
889
- func TestShortDramaListThreadFileRequiresAccessKey(t *testing.T) {
916
+ func TestListThreadFileRequiresAccessKey(t *testing.T) {
890
917
  server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
891
918
  t.Fatal("server should not receive request without access key")
892
919
  }))
@@ -894,7 +921,7 @@ func TestShortDramaListThreadFileRequiresAccessKey(t *testing.T) {
894
921
 
895
922
  var stdout, stderr bytes.Buffer
896
923
  root := newTestRootCommandWithAccessKey(t, &stdout, &stderr, server.URL, "")
897
- root.SetArgs([]string{"short-drama", "+list-thread-file", "--thread-id", "thread_123"})
924
+ root.SetArgs([]string{"list-thread-file", "--thread-id", "thread_123"})
898
925
 
899
926
  err := root.Execute()
900
927
  if err == nil {
@@ -903,11 +930,11 @@ func TestShortDramaListThreadFileRequiresAccessKey(t *testing.T) {
903
930
  assertAccessKeyGuidance(t, err)
904
931
  }
905
932
 
906
- func TestShortDramaListThreadFileRejectsPageSizeAboveMax(t *testing.T) {
933
+ func TestListThreadFileRejectsPageSizeAboveMax(t *testing.T) {
907
934
  var stdout, stderr bytes.Buffer
908
935
  root := NewRootCommand(&stdout, &stderr)
909
936
  root.SetArgs([]string{
910
- "short-drama", "+list-thread-file",
937
+ "list-thread-file",
911
938
  "--thread-id", "thread_123",
912
939
  "--page-size", "201",
913
940
  })
@@ -942,13 +969,13 @@ func assertAccessKeyGuidance(t *testing.T, err error) {
942
969
  t.Fatal("error = nil, want access key guidance")
943
970
  }
944
971
  msg := err.Error()
945
- if !strings.Contains(msg, "XYQ_ACCESS_KEY is required") {
972
+ if !strings.Contains(msg, "XYQ_ACCESS_KEY 缺失") {
946
973
  t.Fatalf("error = %q, want access key guidance", err)
947
974
  }
948
975
  if !strings.Contains(msg, "https://xyq.jianying.com/home?tab_name=home") {
949
976
  t.Fatalf("error = %q, want access key settings URL", err)
950
977
  }
951
- if !strings.Contains(msg, `export XYQ_ACCESS_KEY="<access-key>"`) {
978
+ if !strings.Contains(msg, `export XYQ_ACCESS_KEY="<your-access-key>"`) {
952
979
  t.Fatalf("error = %q, want setup command guidance", err)
953
980
  }
954
981
  }
@@ -60,21 +60,21 @@ func runUpdate(stdout, stderr io.Writer) error {
60
60
  fmt.Fprintf(stderr, "Updating pippit-tool-cli via npm: %s\n", pkg)
61
61
  restore, err := prepareSelfReplace()
62
62
  if err != nil {
63
- return fmt.Errorf("prepare self replace: %w", err)
63
+ return fmt.Errorf("准备替换当前可执行文件失败: %w", err)
64
64
  }
65
65
  if err := runInheritEnv(stderr, []string{"PIPPIT_CLI_SKIP_SKILLS=1"}, "npm", "install", "-g", pkg); err != nil {
66
66
  restore()
67
- return fmt.Errorf("update pippit-tool-cli: %w", err)
67
+ return fmt.Errorf("更新 pippit-tool-cli 失败: %w", err)
68
68
  }
69
69
 
70
70
  root, err := globalPackageRoot(defaultPackage)
71
71
  if err != nil {
72
- return fmt.Errorf("locate global package: %w", err)
72
+ return fmt.Errorf("定位全局 npm 包失败: %w", err)
73
73
  }
74
74
 
75
75
  fmt.Fprintln(stderr, "Updating pippit-tool-cli skills...")
76
76
  if err := installSkills(root, stderr); err != nil {
77
- return fmt.Errorf("update pippit-tool-cli skills: %w", err)
77
+ return fmt.Errorf("更新 pippit-tool-cli skills 失败: %w", err)
78
78
  }
79
79
 
80
80
  reportBundledSkillTelemetry("update", "cli_update", stderr)
@@ -89,7 +89,7 @@ func globalPackageRoot(pkg string) (string, error) {
89
89
  }
90
90
  npmRoot := strings.TrimSpace(string(out))
91
91
  if npmRoot == "" {
92
- return "", fmt.Errorf("npm root -g returned empty output")
92
+ return "", fmt.Errorf("npm root -g 输出为空")
93
93
  }
94
94
  return filepath.Join(append([]string{npmRoot}, strings.Split(pkg, "/")...)...), nil
95
95
  }
@@ -98,7 +98,7 @@ func installSkills(root string, stderr io.Writer) error {
98
98
  if info, err := os.Stat(filepath.Join(root, "skills")); err != nil {
99
99
  return err
100
100
  } else if !info.IsDir() {
101
- return fmt.Errorf("%s is not a directory", filepath.Join(root, "skills"))
101
+ return fmt.Errorf("%s 不是目录", filepath.Join(root, "skills"))
102
102
  }
103
103
  if err := runInherit(stderr, "npx", "-y", "skills", "add", root, "-g", "-y", "--skill", "*"); err != nil {
104
104
  return err
@@ -153,7 +153,7 @@ func reportBundledSkillTelemetry(event string, source string, stderr io.Writer)
153
153
  go func(payload telemetryPayload) {
154
154
  defer wg.Done()
155
155
  if err := reportSkillTelemetry(payload); err != nil && os.Getenv("PIPPIT_CLI_DEBUG_TELEMETRY") == "1" {
156
- fmt.Fprintf(stderr, "[pippit-tool-cli] telemetry failed: %v\n", err)
156
+ fmt.Fprintf(stderr, "[pippit-tool-cli] 埋点上报失败: %v\n", err)
157
157
  }
158
158
  }(payload)
159
159
  }
@@ -188,7 +188,7 @@ func reportSkillTelemetry(payload telemetryPayload) error {
188
188
  defer resp.Body.Close()
189
189
  _, _ = io.Copy(io.Discard, resp.Body)
190
190
  if resp.StatusCode >= 400 {
191
- return fmt.Errorf("telemetry returned HTTP %d", resp.StatusCode)
191
+ return fmt.Errorf("埋点请求返回 HTTP %d", resp.StatusCode)
192
192
  }
193
193
  return nil
194
194
  }