@pippit-dev/cli 0.0.22 → 0.0.24

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/README.md CHANGED
@@ -8,12 +8,12 @@
8
8
 
9
9
  | 技能 | 说明 | 路径 |
10
10
  |-------|-------------|------|
11
- | `pippit-short-drama-skill` | 短剧工作流技能,支持提交创作任务、上传参考文件、查询进度、列出会话文件和下载产物。 | `skills/short-drama/` |
12
- | `xyq-nest-skill` | 通用 NestAgent 技能,支持图片/视频生成、编辑、文件上传、进度查询和结果下载。 | `skills/xyq-nest-skill/` |
11
+ | `xyq-short-drama-skill` | 短剧工作流技能,支持提交创作任务、上传参考文件、查询进度、列出会话文件和下载产物。 | `skills/short-drama/` |
12
+ | `xyq-skill` | 通用 NestAgent 技能,支持图片/视频生成、编辑、文件上传、进度查询和结果下载。 | `skills/xyq-nest-skill/` |
13
13
 
14
14
  ## 通用 NestAgent 技能
15
15
 
16
- `xyq-nest-skill` 通过接入小云雀 NestAgent 的综合创作能力,实现 AI 图片/视频生成、编辑、风格转换、文件上传、进度查询和结果下载。
16
+ `xyq-skill` 通过接入小云雀 NestAgent 的综合创作能力,实现 AI 图片/视频生成、编辑、风格转换、文件上传、进度查询和结果下载。
17
17
 
18
18
  ### 功能特性
19
19
 
@@ -32,7 +32,7 @@
32
32
 
33
33
  ### 配置
34
34
 
35
- 所有 `xyq-nest-skill` 脚本都使用 Bearer 令牌鉴权:
35
+ 所有 `xyq-skill` 脚本都使用 Bearer 令牌鉴权:
36
36
 
37
37
  ```bash
38
38
  export XYQ_ACCESS_KEY="<access-key>"
@@ -214,4 +214,4 @@ pippit-tool-cli short-drama +download-result --output-path ./thread_123/results/
214
214
 
215
215
  ## 鉴权
216
216
 
217
- `short-drama +submit-run`、`short-drama +get-thread`、`short-drama +upload-file` 以及 `xyq-nest-skill` Python 脚本都使用 `Authorization: Bearer <XYQ_ACCESS_KEY>` 鉴权。OAuth 命令代码仍保留在仓库中,但短剧运行时请求不使用 OAuth。
217
+ `short-drama +submit-run`、`short-drama +get-thread`、`short-drama +upload-file` 以及 `xyq-skill` Python 脚本都使用 `Authorization: Bearer <XYQ_ACCESS_KEY>` 鉴权。OAuth 命令代码仍保留在仓库中,但短剧运行时请求不使用 OAuth。
package/checksums.txt CHANGED
@@ -1,6 +1,6 @@
1
- 2de4679cc459fe3c4d674fb25f00c8df8fa84e98f80a2fd01f5357d07c663c3e pippit-tool-cli-0.0.22-darwin-amd64.tar.gz
2
- 9a63d12f5f0534994c01f57caba16ec0d31a141afbe342cf8f42f7e954270633 pippit-tool-cli-0.0.22-darwin-arm64.tar.gz
3
- 61d20c1df72d556b0bd7157c77cdfe3e4c91bc0d85d8924efb0d49c4d6b36ef2 pippit-tool-cli-0.0.22-linux-amd64.tar.gz
4
- 76407ca98a7f885e06cab745eb09a8e5225bbeaae2226ad4c63c3c403bbdec5d pippit-tool-cli-0.0.22-linux-arm64.tar.gz
5
- 3db90d5c2b5a6a0ba964dd51424ffbc0eaf6dffb3497b5be226d16534504e8e6 pippit-tool-cli-0.0.22-windows-amd64.zip
6
- b3a69cb5e43a21c037e30e5f6af53c1806de5f24e0724ddbbcbd005255cd20ce pippit-tool-cli-0.0.22-windows-arm64.zip
1
+ 489fab9b2e6334ea206ada098598bf60a63d7930b17e646598414fda2685d0cb pippit-tool-cli-0.0.24-darwin-amd64.tar.gz
2
+ da482045b41ccd8ba12291ba589a38ad4ad72dc20a1b71413d73b8c49ebe8609 pippit-tool-cli-0.0.24-darwin-arm64.tar.gz
3
+ d3720a47492cc73f1118e3f8521e6344b50b5d9405185718a95de7b3df048f94 pippit-tool-cli-0.0.24-linux-amd64.tar.gz
4
+ 98bab626d1f985e9a4039e93e96f089da72292e5df98f567dee387b663818d6e pippit-tool-cli-0.0.24-linux-arm64.tar.gz
5
+ 81c026da8883962fa74d8f59749cb4987f85911d30cc1df12fdf9811e85d526c pippit-tool-cli-0.0.24-windows-amd64.zip
6
+ cb27d671c861089bb432461d1ec3dab9dca862665f4f0b26351b78b68ae0a211 pippit-tool-cli-0.0.24-windows-arm64.zip
@@ -184,9 +184,7 @@ func TestShortDramaSubmitRunRequiresAccessKey(t *testing.T) {
184
184
  if err == nil {
185
185
  t.Fatal("Execute() error = nil, want access key error")
186
186
  }
187
- if !strings.Contains(err.Error(), "XYQ_ACCESS_KEY is required") {
188
- t.Fatalf("error = %q, want access key guidance", err)
189
- }
187
+ assertAccessKeyGuidance(t, err)
190
188
  }
191
189
 
192
190
  func TestShortDramaUploadFile(t *testing.T) {
@@ -286,9 +284,7 @@ func TestShortDramaUploadFileRequiresAccessKey(t *testing.T) {
286
284
  if err == nil {
287
285
  t.Fatal("Execute() error = nil, want access key error")
288
286
  }
289
- if !strings.Contains(err.Error(), "XYQ_ACCESS_KEY is required") {
290
- t.Fatalf("error = %q, want access key guidance", err)
291
- }
287
+ assertAccessKeyGuidance(t, err)
292
288
  }
293
289
 
294
290
  func TestShortDramaUploadFileRejectsUnsupportedFileType(t *testing.T) {
@@ -768,9 +764,7 @@ func TestShortDramaGetThreadRequiresAccessKey(t *testing.T) {
768
764
  if err == nil {
769
765
  t.Fatal("Execute() error = nil, want access key error")
770
766
  }
771
- if !strings.Contains(err.Error(), "XYQ_ACCESS_KEY is required") {
772
- t.Fatalf("error = %q, want access key guidance", err)
773
- }
767
+ assertAccessKeyGuidance(t, err)
774
768
  }
775
769
 
776
770
  func TestShortDramaListThreadFile(t *testing.T) {
@@ -892,6 +886,23 @@ func TestShortDramaListThreadFileRequiresThreadID(t *testing.T) {
892
886
  }
893
887
  }
894
888
 
889
+ func TestShortDramaListThreadFileRequiresAccessKey(t *testing.T) {
890
+ server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
891
+ t.Fatal("server should not receive request without access key")
892
+ }))
893
+ defer server.Close()
894
+
895
+ var stdout, stderr bytes.Buffer
896
+ root := newTestRootCommandWithAccessKey(t, &stdout, &stderr, server.URL, "")
897
+ root.SetArgs([]string{"short-drama", "+list-thread-file", "--thread-id", "thread_123"})
898
+
899
+ err := root.Execute()
900
+ if err == nil {
901
+ t.Fatal("Execute() error = nil, want access key error")
902
+ }
903
+ assertAccessKeyGuidance(t, err)
904
+ }
905
+
895
906
  func TestShortDramaListThreadFileRejectsPageSizeAboveMax(t *testing.T) {
896
907
  var stdout, stderr bytes.Buffer
897
908
  root := NewRootCommand(&stdout, &stderr)
@@ -925,6 +936,23 @@ func newTestRootCommandWithAccessKey(t *testing.T, stdout, stderr io.Writer, bas
925
936
  return newRootCommand(stdout, stderr, runner)
926
937
  }
927
938
 
939
+ func assertAccessKeyGuidance(t *testing.T, err error) {
940
+ t.Helper()
941
+ if err == nil {
942
+ t.Fatal("error = nil, want access key guidance")
943
+ }
944
+ msg := err.Error()
945
+ if !strings.Contains(msg, "XYQ_ACCESS_KEY is required") {
946
+ t.Fatalf("error = %q, want access key guidance", err)
947
+ }
948
+ if !strings.Contains(msg, "https://xyq.jianying.com/home?tab_name=home") {
949
+ t.Fatalf("error = %q, want access key settings URL", err)
950
+ }
951
+ if !strings.Contains(msg, `export XYQ_ACCESS_KEY="<access-key>"`) {
952
+ t.Fatalf("error = %q, want setup command guidance", err)
953
+ }
954
+ }
955
+
928
956
  func decodeJSON(t *testing.T, data []byte) map[string]any {
929
957
  t.Helper()
930
958
  var got map[string]any
@@ -14,6 +14,11 @@ import (
14
14
 
15
15
  const defaultPackage = "@pippit-dev/cli"
16
16
 
17
+ var legacyGlobalSkills = []string{
18
+ "pippit-short-drama-skill",
19
+ "xyq-nest-skill",
20
+ }
21
+
17
22
  // NewCommand builds the update command.
18
23
  func NewCommand(stdout, stderr io.Writer) *cobra.Command {
19
24
  cmd := &cobra.Command{
@@ -74,7 +79,30 @@ func installSkills(root string, stderr io.Writer) error {
74
79
  } else if !info.IsDir() {
75
80
  return fmt.Errorf("%s is not a directory", filepath.Join(root, "skills"))
76
81
  }
77
- return runInherit(stderr, "npx", "-y", "skills", "add", root, "-g", "-y", "--skill", "*")
82
+ if err := runInherit(stderr, "npx", "-y", "skills", "add", root, "-g", "-y", "--skill", "*"); err != nil {
83
+ return err
84
+ }
85
+ return cleanupLegacyGlobalSkills(defaultGlobalSkillsDir())
86
+ }
87
+
88
+ func defaultGlobalSkillsDir() string {
89
+ home, err := os.UserHomeDir()
90
+ if err != nil {
91
+ return ""
92
+ }
93
+ return filepath.Join(home, ".agents", "skills")
94
+ }
95
+
96
+ func cleanupLegacyGlobalSkills(globalSkillsDir string) error {
97
+ if globalSkillsDir == "" {
98
+ return nil
99
+ }
100
+ for _, skillName := range legacyGlobalSkills {
101
+ if err := os.RemoveAll(filepath.Join(globalSkillsDir, skillName)); err != nil {
102
+ return err
103
+ }
104
+ }
105
+ return nil
78
106
  }
79
107
 
80
108
  func runInherit(stderr io.Writer, name string, args ...string) error {
@@ -29,6 +29,7 @@ func TestInstallSkillsInstallsAllBundledSkills(t *testing.T) {
29
29
 
30
30
  t.Setenv("PATH", binDir+string(os.PathListSeparator)+os.Getenv("PATH"))
31
31
  t.Setenv("CAPTURE_ARGS", capturePath)
32
+ t.Setenv("HOME", t.TempDir())
32
33
 
33
34
  var stderr bytes.Buffer
34
35
  if err := installSkills(root, &stderr); err != nil {
@@ -45,3 +46,27 @@ func TestInstallSkillsInstallsAllBundledSkills(t *testing.T) {
45
46
  t.Fatalf("npx args mismatch\ngot: %#v\nwant: %#v", got, want)
46
47
  }
47
48
  }
49
+
50
+ func TestCleanupLegacyGlobalSkills(t *testing.T) {
51
+ globalSkillsDir := t.TempDir()
52
+ for _, skillName := range []string{"pippit-short-drama-skill", "xyq-nest-skill", "xyq-short-drama-skill", "xyq-skill"} {
53
+ if err := os.Mkdir(filepath.Join(globalSkillsDir, skillName), 0o755); err != nil {
54
+ t.Fatal(err)
55
+ }
56
+ }
57
+
58
+ if err := cleanupLegacyGlobalSkills(globalSkillsDir); err != nil {
59
+ t.Fatalf("cleanupLegacyGlobalSkills() error = %v", err)
60
+ }
61
+
62
+ for _, skillName := range []string{"pippit-short-drama-skill", "xyq-nest-skill"} {
63
+ if _, err := os.Stat(filepath.Join(globalSkillsDir, skillName)); !os.IsNotExist(err) {
64
+ t.Fatalf("legacy skill %s still exists or stat failed: %v", skillName, err)
65
+ }
66
+ }
67
+ for _, skillName := range []string{"xyq-short-drama-skill", "xyq-skill"} {
68
+ if _, err := os.Stat(filepath.Join(globalSkillsDir, skillName)); err != nil {
69
+ t.Fatalf("new skill %s was not preserved: %v", skillName, err)
70
+ }
71
+ }
72
+ }
@@ -22,7 +22,7 @@ func (a *accessKeyAuthorizer) Inject(ctx context.Context, req *http.Request) err
22
22
  return err
23
23
  }
24
24
  if a.accessKey == "" && req.Method == http.MethodPost {
25
- return fmt.Errorf("%s is required for authenticated requests", config.EnvXYQAccessKey)
25
+ return fmt.Errorf("%s 缺失. 请前往小云雀官网个人设置页创建 Access Key,地址:https://xyq.jianying.com/home?tab_name=home\n配置后重试:\n export %s=\"<your-access-key>\"", config.EnvXYQAccessKey, config.EnvXYQAccessKey)
26
26
  }
27
27
  if a.accessKey != "" {
28
28
  req.Header.Set("Authorization", "Bearer "+a.accessKey)
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@pippit-dev/cli",
3
- "version": "0.0.22",
3
+ "version": "0.0.24",
4
4
  "description": "Pippit CLI",
5
5
  "bin": {
6
6
  "pippit-tool-cli": "scripts/run.js"
7
7
  },
8
8
  "scripts": {
9
9
  "postinstall": "node scripts/install.js",
10
- "test": "node scripts/version-check.test.js && go test ./... && go vet ./..."
10
+ "test": "node scripts/version-check.test.js && node scripts/skills.test.js && go test ./... && go vet ./..."
11
11
  },
12
12
  "os": [
13
13
  "darwin",
package/scripts/skills.js CHANGED
@@ -1,8 +1,26 @@
1
1
  const fs = require("fs");
2
+ const os = require("os");
2
3
  const path = require("path");
3
4
  const { run, runSilent } = require("./platform");
4
5
 
5
6
  const DEFAULT_PKG = "@pippit-dev/cli";
7
+ const LEGACY_GLOBAL_SKILLS = [
8
+ "pippit-short-drama-skill",
9
+ "xyq-nest-skill",
10
+ ];
11
+
12
+ function defaultGlobalSkillsDir() {
13
+ return path.join(os.homedir(), ".agents", "skills");
14
+ }
15
+
16
+ function cleanupLegacyGlobalSkills(globalSkillsDir = defaultGlobalSkillsDir()) {
17
+ for (const skillName of LEGACY_GLOBAL_SKILLS) {
18
+ fs.rmSync(path.join(globalSkillsDir, skillName), {
19
+ force: true,
20
+ recursive: true,
21
+ });
22
+ }
23
+ }
6
24
 
7
25
  function installSkillsFromRoot(root, opts = {}) {
8
26
  const source = path.resolve(root);
@@ -13,6 +31,7 @@ function installSkillsFromRoot(root, opts = {}) {
13
31
  run("npx", ["-y", "skills", "add", source, "-g", "-y", "--skill", "*"], {
14
32
  timeout: opts.timeout || 120000,
15
33
  });
34
+ cleanupLegacyGlobalSkills(opts.globalSkillsDir);
16
35
  }
17
36
 
18
37
  function globalPackageRoot(pkg = DEFAULT_PKG) {
@@ -26,6 +45,9 @@ function installGlobalPackageSkills(pkg = DEFAULT_PKG, opts = {}) {
26
45
 
27
46
  module.exports = {
28
47
  DEFAULT_PKG,
48
+ LEGACY_GLOBAL_SKILLS,
49
+ cleanupLegacyGlobalSkills,
50
+ defaultGlobalSkillsDir,
29
51
  globalPackageRoot,
30
52
  installGlobalPackageSkills,
31
53
  installSkillsFromRoot,
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: pippit-short-drama-skill
2
+ name: xyq-short-drama-skill
3
3
  description: 使用 pippit-tool-cli 的短剧场景能力提交和查询短剧创作任务。覆盖短剧生成、续写、改写、剧情扩展、人物设定、分集草稿、世界观设定、会话文件获取、文件资源下载等创作场景。当用户要求创作短剧、写短剧剧本、续写故事、修改剧情、补充角色设定、查询短剧任务进展、获取短剧会话文件或下载短剧文件资源,或提到 pippit-tool-cli short-drama / 小云雀短剧时触发。
4
4
  user-invocable: true
5
5
  metadata:
@@ -67,6 +67,14 @@ metadata:
67
67
  npx @pippit-dev/cli@latest install
68
68
  ```
69
69
 
70
+ 部分功能需要先配置 `XYQ_ACCESS_KEY`。缺失时 CLI 会直接提示用户先创建 Access Key,此时请等待用户给与Access Key后再继续运行。
71
+
72
+ Access Key 创建地址:https://xyq.jianying.com/home?tab_name=home
73
+
74
+ ```bash
75
+ export XYQ_ACCESS_KEY="<access-key>"
76
+ ```
77
+
70
78
  ## 使用方法
71
79
 
72
80
  ### 1. 提交短剧任务
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: xyq-nest-skill
2
+ name: xyq-skill
3
3
  description: 通过小云雀的 AI 能力进行综合创作,支持生成和编辑图片/视频。覆盖场景包括:生成(文生图、文生视频、图生视频、做动画、画一个xxx、来段xxx)、编辑修改(把xxx换成yyy、去掉xxx、加上xxx、改成xxx、调整xxx、局部修改、改镜头)、风格转换(风格迁移、转绘、换风格)、视频续写延长、复刻视频/TVC/宣传片、短剧/短漫剧生成、音乐MV生成、产品广告/展示片制作、分镜/故事板设计、教育视频/短视频制作。当用户提到小云雀、xyq、上传参考图/视频、查看生成进度时也应触发。关键判断:只要用户的请求涉及 AI 视频的创作、生成、编辑、修改,无论措辞如何(如"画只猫"、"做个海报"、"做个视频"、"这个视频帮我改一下"、"帮我复刻这段视频"、"用这首歌做个MV"、"一句话生成短剧"),都必须触发此技能。
4
4
  user-invocable: true
5
5
  metadata: