redskillhub-upload 1.0.0-alpha.5 → 1.0.0-alpha.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.
package/README.md CHANGED
@@ -16,7 +16,7 @@ Publish input can be a local Skill directory or a `.zip` file. User-provided zip
16
16
 
17
17
  ## API Endpoints
18
18
 
19
- All paths and hosts are centralized in `cli/config.mjs` (`PATHS` + `DEFAULT_API_BASE` / `DEFAULT_OAS_BASE`).
19
+ All paths and hosts are centralized in `cli/config.mjs` (`PATHS` + `DEFAULT_API_BASE` / `BETA_API_BASE`).
20
20
 
21
21
  | Path Key | Path | Host | Description |
22
22
  |----------|------|------|-------------|
@@ -24,16 +24,15 @@ All paths and hosts are centralized in `cli/config.mjs` (`PATHS` + `DEFAULT_API_
24
24
  | `SUBMIT_SKILL_VERSION` | `/api/sns/v1/openapi/skillhub/submit_skill_version` | `DEFAULT_API_BASE` | 提交 skill 版本 |
25
25
  | `CREATE_CLI_OAUTH_DEVICE_CODE` | `/api/sns/v1/creator/red_skill/create_cli_oauth_device_code` | `DEFAULT_API_BASE` | 创建 CLI OAuth 设备码 |
26
26
  | `POLL_CLI_OAUTH_DEVICE_TOKEN` | `/api/sns/v1/creator/red_skill/poll_cli_oauth_device_token` | `DEFAULT_API_BASE` | 轮询 CLI OAuth 授权状态 |
27
- | `OAS_ACCESS_TOKEN` | `/api/sns/v1/oauth2/access_token` | `DEFAULT_OAS_BASE` | 用授权码换取 access_token |
28
- | `OAS_REFRESH_TOKEN` | `/api/sns/v1/oauth2/refresh_token` | `DEFAULT_OAS_BASE` | 用 refresh_token 续期 access_token |
27
+ | `EXCHANGE_CLI_OAUTH_TOKEN` | `/api/sns/v1/creator/red_skill/exchange_cli_oauth_token` | `DEFAULT_API_BASE` / `BETA_API_BASE` | 通过 SkillHub 服务端换取 access_token |
28
+ | `REFRESH_CLI_OAUTH_TOKEN` | `/api/sns/v1/creator/red_skill/refresh_cli_oauth_token` | `DEFAULT_API_BASE` / `BETA_API_BASE` | 通过 SkillHub 服务端续期 access_token |
29
29
 
30
30
  - `DEFAULT_API_BASE` = `https://edith.xiaohongshu.com` — 生产业务接口
31
31
  - `BETA_API_BASE` = `https://edith.beta.xiaohongshu.com` — beta 业务接口
32
- - `DEFAULT_OAS_BASE` = `https://openaccount.xiaohongshu.com` — OAuth2 开放平台接口
33
32
  - 所有命令都支持 `--env prod|beta`,默认 `prod`;`--env beta` 时业务接口使用 `BETA_API_BASE`
34
33
  - prod 沿用 `~/.skillhub-upload`,beta 使用 `~/.skillhub-upload/beta`,凭证、待授权、二维码、标签缓存和临时包相互隔离
35
34
  - 业务接口 host 可通过 `--api-base` 参数或 `SKILLHUB_UPLOAD_API_BASE` 环境变量覆盖
36
- - OAS 换 token 默认使用内置应用凭证;可通过 `SKILLHUB_UPLOAD_APP_SECRET` 覆盖
35
+ - OAuth token 换取与刷新统一走 SkillHub 服务端 broker,CLI 不保存 appSecret
37
36
 
38
37
  ## Auth Flow
39
38
 
package/cli/auth.mjs CHANGED
@@ -3,9 +3,6 @@ import fs from 'node:fs/promises';
3
3
  import path from 'node:path';
4
4
  import {
5
5
  DEFAULT_API_BASE,
6
- DEFAULT_APP_ID,
7
- DEFAULT_APP_SECRET,
8
- DEFAULT_OAS_BASE,
9
6
  DEFAULT_SCOPE,
10
7
  DEFAULT_SCOPES,
11
8
  PATHS,
@@ -108,34 +105,17 @@ function unwrapResponseBody(body) {
108
105
  return body?.data && typeof body.data === 'object' ? body.data : body;
109
106
  }
110
107
 
111
- function resolveAppSecret(flags = {}, env = process.env) {
112
- return flags.appSecret
113
- || flags['app-secret']
114
- || env.SKILLHUB_UPLOAD_APP_SECRET
115
- || DEFAULT_APP_SECRET;
116
- }
117
-
118
108
  function buildTokenRequestBody(fields = {}) {
119
- const body = {
120
- app_id: fields.appId,
121
- code: fields.authorizationCode,
109
+ return {
110
+ authorization_code: fields.authorizationCode,
122
111
  code_verifier: fields.codeVerifier
123
112
  };
124
- if (fields.appSecret) {
125
- body.app_secret = fields.appSecret;
126
- }
127
- return body;
128
113
  }
129
114
 
130
115
  function buildRefreshRequestBody(fields = {}) {
131
- const body = {
132
- app_id: fields.appId,
116
+ return {
133
117
  refresh_token: fields.refreshToken
134
118
  };
135
- if (fields.appSecret) {
136
- body.app_secret = fields.appSecret;
137
- }
138
- return body;
139
119
  }
140
120
 
141
121
  function getRejectMessage(body, fallback) {
@@ -231,14 +211,12 @@ export async function pollDeviceToken({ apiBase, deviceCode, fetchImpl = compati
231
211
  }
232
212
 
233
213
  export async function exchangeToken({
234
- tokenUrl = `${DEFAULT_OAS_BASE}${PATHS.OAS_ACCESS_TOKEN}`,
235
- appId = DEFAULT_APP_ID,
236
- appSecret = '',
214
+ tokenUrl = `${DEFAULT_API_BASE}${PATHS.EXCHANGE_CLI_OAUTH_TOKEN}`,
237
215
  authorizationCode,
238
216
  codeVerifier,
239
217
  fetchImpl = compatibleFetch
240
218
  }) {
241
- const body = buildTokenRequestBody({ appId, appSecret, authorizationCode, codeVerifier });
219
+ const body = buildTokenRequestBody({ authorizationCode, codeVerifier });
242
220
  const response = await fetchImpl(tokenUrl, {
243
221
  method: 'POST',
244
222
  headers: { 'content-type': 'application/json' },
@@ -257,13 +235,11 @@ export async function exchangeToken({
257
235
  }
258
236
 
259
237
  export async function refreshToken({
260
- tokenUrl = `${DEFAULT_OAS_BASE}${PATHS.OAS_REFRESH_TOKEN}`,
261
- appId = DEFAULT_APP_ID,
262
- appSecret = '',
238
+ tokenUrl = `${DEFAULT_API_BASE}${PATHS.REFRESH_CLI_OAUTH_TOKEN}`,
263
239
  refreshToken: rt,
264
240
  fetchImpl = compatibleFetch
265
241
  }) {
266
- const body = buildRefreshRequestBody({ appId, appSecret, refreshToken: rt });
242
+ const body = buildRefreshRequestBody({ refreshToken: rt });
267
243
  const response = await fetchImpl(tokenUrl, {
268
244
  method: 'POST',
269
245
  headers: { 'content-type': 'application/json' },
@@ -283,7 +259,6 @@ export async function refreshToken({
283
259
 
284
260
  function buildCredentialsFromToken(token, nowMs, errorCode) {
285
261
  const credentials = {
286
- appId: token.app_id || token.appId || DEFAULT_APP_ID,
287
262
  accessToken: token.access_token || token.accessToken || '',
288
263
  refreshToken: token.refresh_token || token.refreshToken || '',
289
264
  expireTimeMs: String(token.expire_time_ms || token.expireTimeMs || nowMs + Number(token.expires_in || 7200) * 1000),
@@ -349,6 +324,7 @@ export async function login({
349
324
  now = () => Date.now(),
350
325
  promptStream = process.stdout
351
326
  } = {}) {
327
+ const apiBase = resolveApiBase(flags, env);
352
328
  const cachedCredentials = await readCredentials(env, flags);
353
329
  if (isValidCredentials(cachedCredentials, now())) {
354
330
  return maskCredentials(cachedCredentials);
@@ -357,12 +333,9 @@ export async function login({
357
333
  // access_token 过期但 refresh_token 仍有效,静默续期
358
334
  if (canRefreshCredentials(cachedCredentials, now())) {
359
335
  try {
360
- const appSecret = resolveAppSecret(flags, env);
361
336
  const token = await refreshToken({
362
- appId: cachedCredentials.appId || DEFAULT_APP_ID,
363
- appSecret,
364
337
  refreshToken: cachedCredentials.refreshToken,
365
- tokenUrl: flags.tokenUrl || `${DEFAULT_OAS_BASE}${PATHS.OAS_REFRESH_TOKEN}`,
338
+ tokenUrl: `${apiBase}${PATHS.REFRESH_CLI_OAUTH_TOKEN}`,
366
339
  fetchImpl
367
340
  });
368
341
  await writeCredentials(buildCredentialsFromToken(token, now(), 'OAS_TOKEN_REFRESH_INVALID_RESPONSE'), env, flags);
@@ -376,8 +349,6 @@ export async function login({
376
349
  }
377
350
  }
378
351
 
379
- const apiBase = resolveApiBase(flags, env);
380
-
381
352
  // 从磁盘恢复未完成的授权状态,避免进程重启后要求用户重新授权
382
353
  let pending = await readPendingAuth(env, flags, now);
383
354
  let codeVerifier;
@@ -457,11 +428,9 @@ export async function login({
457
428
  }
458
429
 
459
430
  const token = await exchangeToken({
460
- appId: DEFAULT_APP_ID,
461
- appSecret: resolveAppSecret(flags, env),
462
431
  authorizationCode,
463
432
  codeVerifier,
464
- tokenUrl: flags.tokenUrl || `${DEFAULT_OAS_BASE}${PATHS.OAS_ACCESS_TOKEN}`,
433
+ tokenUrl: `${apiBase}${PATHS.EXCHANGE_CLI_OAUTH_TOKEN}`,
465
434
  fetchImpl
466
435
  });
467
436
  await writeCredentials(buildCredentialsFromToken(token, now(), 'OAS_TOKEN_EXCHANGE_INVALID_RESPONSE'), env, flags);
package/cli/config.mjs CHANGED
@@ -3,9 +3,6 @@ import path from 'node:path';
3
3
 
4
4
  export const DEFAULT_API_BASE = 'https://edith.xiaohongshu.com';
5
5
  export const BETA_API_BASE = 'https://edith-redskill.sl.beta.xiaohongshu.com';
6
- export const DEFAULT_OAS_BASE = 'https://openaccount.xiaohongshu.com';
7
- export const DEFAULT_APP_ID = 'xhsyfHfmZQAQ24o';
8
- export const DEFAULT_APP_SECRET = 'skHlFZ8BTk2bVmsSt1aYjv1NxcJjuOwhSev4oraniDa6eyn8L9oqBWvCtsEBnmCmWG';
9
6
  export const DEFAULT_SCOPES = ['base_info', 'skill_publish'];
10
7
  export const DEFAULT_SCOPE = DEFAULT_SCOPES.join(',');
11
8
 
@@ -14,8 +11,8 @@ export const PATHS = {
14
11
  SUBMIT_SKILL_VERSION: '/api/sns/v1/creator/red_skill/cli_submit_skill_version',
15
12
  CREATE_CLI_OAUTH_DEVICE_CODE: '/api/sns/v1/creator/red_skill/create_cli_oauth_device_code',
16
13
  POLL_CLI_OAUTH_DEVICE_TOKEN: '/api/sns/v1/creator/red_skill/poll_cli_oauth_device_token',
17
- OAS_ACCESS_TOKEN: '/api/sns/v1/oauth2/access_token',
18
- OAS_REFRESH_TOKEN: '/api/sns/v1/oauth2/refresh_token',
14
+ EXCHANGE_CLI_OAUTH_TOKEN: '/api/sns/v1/creator/red_skill/exchange_cli_oauth_token',
15
+ REFRESH_CLI_OAUTH_TOKEN: '/api/sns/v1/creator/red_skill/refresh_cli_oauth_token',
19
16
  QUERY_CONTENT_TAG_CONFIG: '/api/sns/v1/activity_platform/config/query_config'
20
17
  };
21
18
  export const TOKEN_REFRESH_BUFFER_MS = 5 * 60 * 1000;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "redskillhub-upload",
3
- "version": "1.0.0-alpha.5",
3
+ "version": "1.0.0-alpha.6",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public",