beervid-app-cli 0.2.4 → 0.2.6

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.
Files changed (37) hide show
  1. package/README.md +30 -19
  2. package/dist/cli.mjs +1 -1
  3. package/package.json +6 -6
  4. package/{SKILL.md → skills/beervid-app-cli/SKILL.md} +6 -2
  5. package/{docs → skills/beervid-app-cli/docs}/oauth-callback.md +22 -19
  6. package/{example → skills/beervid-app-cli/example}/express/server.ts +8 -4
  7. package/{example → skills/beervid-app-cli/example}/nextjs/app/api/oauth/url/route.ts +3 -2
  8. package/{example → skills/beervid-app-cli/example}/standard/get-oauth-url.ts +3 -2
  9. package/agents/openai.yaml +0 -7
  10. /package/{docs → skills/beervid-app-cli/docs}/database-schema.md +0 -0
  11. /package/{docs → skills/beervid-app-cli/docs}/retry-and-idempotency.md +0 -0
  12. /package/{docs → skills/beervid-app-cli/docs}/tt-poll-task.md +0 -0
  13. /package/{docs → skills/beervid-app-cli/docs}/tts-product-cache.md +0 -0
  14. /package/{example → skills/beervid-app-cli/example}/express/README.md +0 -0
  15. /package/{example → skills/beervid-app-cli/example}/express/package.json +0 -0
  16. /package/{example → skills/beervid-app-cli/example}/express/tsconfig.json +0 -0
  17. /package/{example → skills/beervid-app-cli/example}/nextjs/.env.example +0 -0
  18. /package/{example → skills/beervid-app-cli/example}/nextjs/README.md +0 -0
  19. /package/{example → skills/beervid-app-cli/example}/nextjs/app/api/oauth/callback/route.ts +0 -0
  20. /package/{example → skills/beervid-app-cli/example}/nextjs/app/api/products/route.ts +0 -0
  21. /package/{example → skills/beervid-app-cli/example}/nextjs/app/api/publish/tt/route.ts +0 -0
  22. /package/{example → skills/beervid-app-cli/example}/nextjs/app/api/publish/tts/route.ts +0 -0
  23. /package/{example → skills/beervid-app-cli/example}/nextjs/app/api/status/[shareId]/route.ts +0 -0
  24. /package/{example → skills/beervid-app-cli/example}/nextjs/app/layout.tsx +0 -0
  25. /package/{example → skills/beervid-app-cli/example}/nextjs/app/page.tsx +0 -0
  26. /package/{example → skills/beervid-app-cli/example}/nextjs/lib/beervid-client.ts +0 -0
  27. /package/{example → skills/beervid-app-cli/example}/nextjs/next.config.ts +0 -0
  28. /package/{example → skills/beervid-app-cli/example}/nextjs/package.json +0 -0
  29. /package/{example → skills/beervid-app-cli/example}/nextjs/tsconfig.json +0 -0
  30. /package/{example → skills/beervid-app-cli/example}/standard/README.md +0 -0
  31. /package/{example → skills/beervid-app-cli/example}/standard/api-client.ts +0 -0
  32. /package/{example → skills/beervid-app-cli/example}/standard/package.json +0 -0
  33. /package/{example → skills/beervid-app-cli/example}/standard/query-products.ts +0 -0
  34. /package/{example → skills/beervid-app-cli/example}/standard/tsconfig.json +0 -0
  35. /package/{example → skills/beervid-app-cli/example}/standard/tt-publish-flow.ts +0 -0
  36. /package/{example → skills/beervid-app-cli/example}/standard/tts-publish-flow.ts +0 -0
  37. /package/{references → skills/beervid-app-cli/references}/api-reference.md +0 -0
package/README.md CHANGED
@@ -30,28 +30,39 @@ node dist/cli.mjs --help
30
30
  node dist/cli.mjs config --show
31
31
  ```
32
32
 
33
- ### 在 Claude Code / Codex / Antigravity 中使用
33
+ ### 在 Claude Code / Codex / Antigravity 中使用(以下说明面向 AI Agent)
34
34
 
35
- 如果你希望在 Claude Code、Codex 等支持 Skill 的工具中直接调用本项目,除了通过 npm 安装 CLI 之外,还需要把 Skill 相关文件复制到你自己的 skills 目录下。
35
+ #### 方式一:通过 `npx skills add` 安装(推荐)
36
36
 
37
- 需要复制的内容:
37
+ ```bash
38
+ npx skills add Lupeiwen0/beervid-app-cli
39
+ ```
40
+
41
+ 安装后 Skill 会自动注册到你的 skills 目录中,Claude Code 等 Agent 即可发现和调用。
42
+
43
+ #### 方式二:手动安装
38
44
 
39
- - `SKILL.md`
40
- - `references/`
41
- - `docs/`
42
- - `example/`
45
+ 如果你是 Claude Code、Codex、Antigravity,或任何支持 Skill 的 AI Agent,请严格按下面规则执行:
43
46
 
44
- 建议在你的 skills 目录中保持如下结构:
47
+ - 用户把 GitHub 仓库链接发给你,**不等于**这个 Skill 已经安装到你的 skills 目录中。
48
+ - 只有当 `skills/beervid-app-cli/` 目录被完整安装到你的 skills 目录后,才算这个 Skill 可用。
49
+
50
+ 你必须先把以下目录复制到你自己的 skills 目录中:
45
51
 
46
52
  ```text
47
- beervid-app-cli/
53
+ skills/beervid-app-cli/
48
54
  SKILL.md
49
55
  references/
50
56
  docs/
51
57
  example/
52
58
  ```
53
59
 
54
- 这样工具在加载 `SKILL.md` 时,才能继续访问本项目附带的 API 参考、落地文档和示例工程。
60
+ 安装完成后,你应从 skills 目录中的 `SKILL.md` 加载本 Skill,而不是只读取仓库根目录里的 `README.md` 或 `package.json`。
61
+
62
+ 对 AI Agent 来说,应这样区分:
63
+
64
+ - 目标是使用 CLI:安装 npm 包即可。
65
+ - 目标是使用 Skill:必须额外安装 Skill 文件;仓库链接本身不完成这一步。
55
66
 
56
67
  ## 配置
57
68
 
@@ -106,7 +117,7 @@ beervid publish-tts-flow --creator-id open_user_abc --file ./video.mp4 --interac
106
117
  beervid publish-tts-flow --creator-id open_user_abc --file ./video.mp4 --product-id prod_123 --product-title "Widget"
107
118
  ```
108
119
 
109
- 详细用法见 [SKILL.md](./SKILL.md)。完整 API 参考见 [references/api-reference.md](./references/api-reference.md)。
120
+ 详细用法见 [SKILL.md](./skills/beervid-app-cli/SKILL.md)。完整 API 参考见 [references/api-reference.md](./skills/beervid-app-cli/references/api-reference.md)。
110
121
 
111
122
  ## 落地文档
112
123
 
@@ -114,11 +125,11 @@ beervid publish-tts-flow --creator-id open_user_abc --file ./video.mp4 --product
114
125
 
115
126
  | 文档 | 内容 |
116
127
  |------|------|
117
- | [数据表字段建议](./docs/database-schema.md) | accounts/videos/products 表结构设计 |
118
- | [OAuth 回调存储建议](./docs/oauth-callback.md) | State Token 防 CSRF、回调持久化、异步头像同步 |
119
- | [TT 轮询任务建议](./docs/tt-poll-task.md) | 阶梯递增轮询间隔、Cron/队列三层保障 |
120
- | [TTS 商品缓存建议](./docs/tts-product-cache.md) | 全量拉取、缓存过期、图片 URL 解析 |
121
- | [失败重试与幂等建议](./docs/retry-and-idempotency.md) | 各 API 幂等性分析、指数退避、幂等键设计 |
128
+ | [数据表字段建议](./skills/beervid-app-cli/docs/database-schema.md) | accounts/videos/products 表结构设计 |
129
+ | [OAuth 回调存储建议](./skills/beervid-app-cli/docs/oauth-callback.md) | State Token 防 CSRF、回调持久化、异步头像同步 |
130
+ | [TT 轮询任务建议](./skills/beervid-app-cli/docs/tt-poll-task.md) | 阶梯递增轮询间隔、Cron/队列三层保障 |
131
+ | [TTS 商品缓存建议](./skills/beervid-app-cli/docs/tts-product-cache.md) | 全量拉取、缓存过期、图片 URL 解析 |
132
+ | [失败重试与幂等建议](./skills/beervid-app-cli/docs/retry-and-idempotency.md) | 各 API 幂等性分析、指数退避、幂等键设计 |
122
133
 
123
134
  ## 示例工程
124
135
 
@@ -126,6 +137,6 @@ beervid publish-tts-flow --creator-id open_user_abc --file ./video.mp4 --product
126
137
 
127
138
  | 示例 | 场景 | 入口 |
128
139
  |------|------|------|
129
- | [Standard](./example/standard/) | 纯 Node.js 脚本,快速验证 | `npx tsx tt-publish-flow.ts` |
130
- | [Express](./example/express/) | Express 后端服务,含 OAuth 回调 | `npx tsx server.ts` |
131
- | [Next.js](./example/nextjs/) | Next.js App Router API Route | `npm run dev` |
140
+ | [Standard](./skills/beervid-app-cli/example/standard/) | 纯 Node.js 脚本,快速验证 | `npx tsx tt-publish-flow.ts` |
141
+ | [Express](./skills/beervid-app-cli/example/express/) | Express 后端服务,含 OAuth 回调 | `npx tsx server.ts` |
142
+ | [Next.js](./skills/beervid-app-cli/example/nextjs/) | Next.js App Router API Route | `npm run dev` |
package/dist/cli.mjs CHANGED
@@ -1130,7 +1130,7 @@ function register10(cli2) {
1130
1130
 
1131
1131
  // src/cli.ts
1132
1132
  var cli = cac("beervid");
1133
- var cliVersion = true ? "0.2.4" : pkg.version;
1133
+ var cliVersion = true ? "0.2.6" : pkg.version;
1134
1134
  register10(cli);
1135
1135
  register(cli);
1136
1136
  register2(cli);
package/package.json CHANGED
@@ -1,7 +1,11 @@
1
1
  {
2
2
  "name": "beervid-app-cli",
3
- "version": "0.2.4",
3
+ "version": "0.2.6",
4
4
  "description": "BEERVID App CLI — TikTok video publish, account auth, and data query",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "https://github.com/Lupeiwen0/beervid-app-cli"
8
+ },
5
9
  "type": "module",
6
10
  "engines": {
7
11
  "node": ">=20.0.0"
@@ -11,11 +15,7 @@
11
15
  },
12
16
  "files": [
13
17
  "dist/",
14
- "agents/",
15
- "references/",
16
- "docs/",
17
- "example/",
18
- "SKILL.md",
18
+ "skills/",
19
19
  "README.md"
20
20
  ],
21
21
  "scripts": {
@@ -184,9 +184,13 @@ creatorUserOpenId -> upload-tts-video -> fileId -> shoppable-publish -> videoId
184
184
  - 上传请求头使用 `X-UPLOAD-TOKEN`
185
185
  - 如需上传进度与取消能力,优先用 XHR 而非裸 `fetch`
186
186
 
187
- ## CLI 使用原则
187
+ ## CLI 工具
188
188
 
189
- 本仓库已经提供 `beervid` CLI;如果用户要“直接操作 API”或“快速验证链路”,优先复用 CLI 能力,不必手写一遍完整流程。
189
+ Skill 配套提供 `beervid` CLI;可直接在终端调用所有 Open API 能力。如需使用 CLI,请先安装:
190
+
191
+ ```bash
192
+ npm install -g beervid-app-cli
193
+ ```
190
194
 
191
195
  ### CLI 前置
192
196
 
@@ -16,8 +16,9 @@
16
16
  2. **用户跳转授权**:将用户重定向到返回的 URL
17
17
  3. **接收回调**:用户授权后,TikTok 回调你的服务器
18
18
 
19
- > **说明**:获取到的授权链接中通常已经包含 `state` 参数。
20
- > 如果你需要附加自定义安全字段,做法不是新增一个 `state` 参数,而是解析现有 `state`,在其 JSON 中追加字段后再写回授权链接。
19
+ > **说明**:获取到的授权链接中**不一定**携带 `state` 参数。
20
+ > - 如果链接中已经包含 `state`,它的值一定是一个 JSON 字符串。你可以解析该 JSON,在其中追加自定义字段后再写回。
21
+ > - 如果链接中没有 `state`,而你需要透传参数(例如防 CSRF 的安全 token),应自行构造一个 JSON 对象作为 `state` 的值追加到授权链接上。
21
22
 
22
23
  ---
23
24
 
@@ -35,9 +36,11 @@ OAuth 授权完成后,回调 URL 会携带以下关键参数:
35
36
 
36
37
  ---
37
38
 
38
- ## 获取授权链接后如何向已有 State 追加自定义字段
39
+ ## 获取授权链接后如何设置或追加 State
39
40
 
40
- 如果获取到的授权链接里已经自带 `state`,并且它的值是一个 JSON 字符串,可以在拿到 OAuth URL 后解析这个 JSON,再把你方的安全 token 追加进去:
41
+ 授权链接中**可能包含也可能不包含** `state` 参数:
42
+ - 如果已包含 `state`,其值是一个 JSON 字符串,可以解析后追加字段再写回。
43
+ - 如果未包含 `state`,而你需要透传参数,应自行构造一个 JSON 对象设置为 `state`。
41
44
 
42
45
  ```typescript
43
46
  function tryParseJsonObject(value: string): Record<string, unknown> | null {
@@ -52,25 +55,25 @@ function tryParseJsonObject(value: string): Record<string, unknown> | null {
52
55
  }
53
56
  }
54
57
 
55
- function appendTokenToOAuthUrlState(
58
+ function setOrAppendStateToken(
56
59
  rawUrl: string,
57
60
  customStateToken: string
58
61
  ): string {
59
62
  const url = new URL(rawUrl)
60
63
  const rawState = url.searchParams.get('state')
61
64
 
62
- if (!rawState) {
63
- throw new Error('授权链接中缺少 state 参数')
64
- }
65
-
66
- const parsedState = tryParseJsonObject(rawState)
67
- if (!parsedState) {
68
- throw new Error('授权链接中的 state 不是可追加字段的 JSON 对象')
69
- }
65
+ let nextState: Record<string, unknown>
70
66
 
71
- const nextState = {
72
- ...parsedState,
73
- customStateToken,
67
+ if (rawState) {
68
+ // 链接中已有 state,解析后追加字段
69
+ const parsedState = tryParseJsonObject(rawState)
70
+ if (!parsedState) {
71
+ throw new Error('授权链接中的 state 不是可追加字段的 JSON 对象')
72
+ }
73
+ nextState = { ...parsedState, customStateToken }
74
+ } else {
75
+ // 链接中没有 state,自行构造 JSON
76
+ nextState = { customStateToken }
74
77
  }
75
78
 
76
79
  url.searchParams.set('state', JSON.stringify(nextState))
@@ -80,7 +83,7 @@ function appendTokenToOAuthUrlState(
80
83
  async function getTtOAuthUrlWithState(userId: string): Promise<string> {
81
84
  const customStateToken = generateStateToken(userId)
82
85
  const rawUrl = await openApiGet<string>('/api/v1/open/thirdparty-auth/tt-url')
83
- return appendTokenToOAuthUrlState(rawUrl, customStateToken)
86
+ return setOrAppendStateToken(rawUrl, customStateToken)
84
87
  }
85
88
 
86
89
  async function getTtsOAuthUrlWithState(userId: string): Promise<string> {
@@ -88,7 +91,7 @@ async function getTtsOAuthUrlWithState(userId: string): Promise<string> {
88
91
  const data = await openApiGet<{ crossBorderUrl: string }>(
89
92
  '/api/v1/open/thirdparty-auth/tts-url'
90
93
  )
91
- return appendTokenToOAuthUrlState(data.crossBorderUrl, customStateToken)
94
+ return setOrAppendStateToken(data.crossBorderUrl, customStateToken)
92
95
  }
93
96
  ```
94
97
 
@@ -108,7 +111,7 @@ function parseCustomStateToken(state: string): string {
108
111
  ```
109
112
 
110
113
  > **说明**:字段名 `customStateToken` 只是示例,你也可以改成 `token`、`nonce`、`appState` 等业务上更合适的名字。
111
- > 如果授权链接里的 `state` 不是 JSON 对象,就不要按这个示例直接 `JSON.parse`;应改为使用平台允许的编码方式,或采用你当前链路已有的透传机制。
114
+ > 无论链接中原先是否携带 `state`,你设置的 `state` 值都应该是一个 JSON 对象。
112
115
 
113
116
  ---
114
117
 
@@ -154,8 +154,10 @@ async function pollVideoStatusInBackground(record: VideoRecord): Promise<void> {
154
154
  app.get('/oauth/tt', async (_req, res) => {
155
155
  try {
156
156
  const url = await openApiGet<string>('/api/v1/open/thirdparty-auth/tt-url')
157
- // 生产环境:先判断授权链接中的 state 是否为 JSON 对象;
158
- // 若是,再在该 JSON 中追加你方自定义安全字段,详见 docs/oauth-callback.md
157
+ // 生产环境:授权链接中不一定携带 state 参数。
158
+ // 如果已有 state,其值为 JSON,可解析后追加自定义字段;
159
+ // 如果没有 state,需透传参数时应自行构造 JSON 设置为 state。
160
+ // 详见 docs/oauth-callback.md
159
161
  res.redirect(url)
160
162
  } catch (err) {
161
163
  res.status(500).json({ error: (err as Error).message })
@@ -168,8 +170,10 @@ app.get('/oauth/tts', async (_req, res) => {
168
170
  const data = await openApiGet<{ crossBorderUrl: string }>(
169
171
  '/api/v1/open/thirdparty-auth/tts-url'
170
172
  )
171
- // 生产环境:先判断授权链接中的 state 是否为 JSON 对象;
172
- // 若是,再在该 JSON 中追加你方自定义安全字段,详见 docs/oauth-callback.md
173
+ // 生产环境:授权链接中不一定携带 state 参数。
174
+ // 如果已有 state,其值为 JSON,可解析后追加自定义字段;
175
+ // 如果没有 state,需透传参数时应自行构造 JSON 设置为 state。
176
+ // 详见 docs/oauth-callback.md
173
177
  res.redirect(data.crossBorderUrl)
174
178
  } catch (err) {
175
179
  res.status(500).json({ error: (err as Error).message })
@@ -2,8 +2,9 @@
2
2
  * GET /api/oauth/url?type=tt|tts
3
3
  * 获取 OAuth 授权 URL
4
4
  *
5
- * 生产环境:如果要往授权链接里追加你方自定义安全字段,
6
- * 先判断现有 state 是否为 JSON 对象;若是,再在该 JSON 中追加字段。
5
+ * 生产环境:授权链接中不一定携带 state 参数。
6
+ * 如果已有 state,其值为 JSON,可解析后追加自定义字段;
7
+ * 如果没有 state,需透传参数时应自行构造 JSON 设置为 state。
7
8
  * 详见 docs/oauth-callback.md
8
9
  */
9
10
  import { NextRequest, NextResponse } from 'next/server'
@@ -5,8 +5,9 @@
5
5
  * npx tsx get-oauth-url.ts --type tt
6
6
  * npx tsx get-oauth-url.ts --type tts
7
7
  *
8
- * 生产环境:如果要往授权链接里追加你方自定义安全字段,
9
- * 先判断现有 state 是否为 JSON 对象;若是,再在该 JSON 中追加字段。
8
+ * 生产环境:授权链接中不一定携带 state 参数。
9
+ * 如果已有 state,其值为 JSON,可解析后追加自定义字段;
10
+ * 如果没有 state,需透传参数时应自行构造 JSON 设置为 state。
10
11
  * 详见 docs/oauth-callback.md
11
12
  */
12
13
 
@@ -1,7 +0,0 @@
1
- interface:
2
- display_name: "BEERVID App CLI"
3
- short_description: "BEERVID third-party Open API CLI skill"
4
- default_prompt: "Use $beervid-app-cli to implement or troubleshoot BEERVID third-party Open API flows for OAuth, TikTok publishing, status polling, and product queries."
5
-
6
- policy:
7
- allow_implicit_invocation: true