skill-market-cli 1.1.0 → 1.1.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skill-market-cli",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
4
4
  "description": "CLI tool for managing skills on Skill Market",
5
5
  "main": "src/index.js",
6
6
  "bin": {
package/src/api/client.js CHANGED
@@ -1,6 +1,6 @@
1
1
  const axios = require('axios');
2
2
  const chalk = require('chalk');
3
- const { getToken, isLoggedIn, getServerConfig } = require('../auth/token-store');
3
+ const { getToken, isLoggedIn, getServerConfig, getPersonalAccessToken } = require('../auth/token-store');
4
4
  const { refreshAccessToken } = require('../auth/oauth');
5
5
 
6
6
  class ApiClient {
@@ -23,12 +23,12 @@ class ApiClient {
23
23
  }
24
24
  });
25
25
 
26
- // 请求拦截器 - 添加 Token
26
+ // 请求拦截器 - 添加 Token(优先 OAuth Token,其次 Personal Access Token)
27
27
  this.client.interceptors.request.use(
28
28
  async (config) => {
29
29
  if (isLoggedIn()) {
30
30
  const { accessToken, expiresAt } = getToken();
31
-
31
+
32
32
  // 检查 Token 是否即将过期
33
33
  if (expiresAt && Date.now() > expiresAt - 60000) {
34
34
  // Token 即将过期,尝试刷新
@@ -42,6 +42,11 @@ class ApiClient {
42
42
  } else {
43
43
  config.headers['Authorization'] = `Bearer ${accessToken}`;
44
44
  }
45
+ } else {
46
+ const pat = getPersonalAccessToken();
47
+ if (pat) {
48
+ config.headers['Authorization'] = `Bearer ${pat}`;
49
+ }
45
50
  }
46
51
  return config;
47
52
  },
@@ -89,9 +94,9 @@ class ApiClient {
89
94
  const response = await this.client.get('/skill/list', {
90
95
  params: { page: 1, pageSize: 1000 }
91
96
  });
92
-
97
+
93
98
  const { user } = getToken();
94
- if (response.data && response.data.data && response.data.data.list) {
99
+ if (user && response.data && response.data.data && response.data.data.list) {
95
100
  response.data.data.list = response.data.data.list.filter(
96
101
  skill => skill.creator === user.name
97
102
  );
@@ -60,9 +60,28 @@ function clearToken() {
60
60
  saveConfig(config);
61
61
  }
62
62
 
63
- // 检查是否已登录
63
+ // Personal Access Token (PAT) 管理
64
+ function savePersonalAccessToken(token) {
65
+ const config = getConfig();
66
+ config.personalAccessToken = token;
67
+ saveConfig(config);
68
+ }
69
+
70
+ function getPersonalAccessToken() {
71
+ const config = getConfig();
72
+ return config.personalAccessToken || null;
73
+ }
74
+
75
+ function clearPersonalAccessToken() {
76
+ const config = getConfig();
77
+ delete config.personalAccessToken;
78
+ saveConfig(config);
79
+ }
80
+
81
+ // 检查是否已登录(OAuth 或 Personal Access Token)
64
82
  function isLoggedIn() {
65
83
  const config = getConfig();
84
+ if (config.personalAccessToken) return true;
66
85
  if (!config.accessToken) return false;
67
86
  if (config.expiresAt && Date.now() > config.expiresAt) {
68
87
  return false;
@@ -95,6 +114,9 @@ module.exports = {
95
114
  isLoggedIn,
96
115
  getServerConfig,
97
116
  setServerConfig,
117
+ savePersonalAccessToken,
118
+ getPersonalAccessToken,
119
+ clearPersonalAccessToken,
98
120
  CONFIG_DIR,
99
121
  CONFIG_FILE
100
122
  };
@@ -1,11 +1,13 @@
1
1
  const chalk = require('chalk');
2
2
  const inquirer = require('inquirer');
3
- const { isLoggedIn } = require('../auth/token-store');
3
+ const { isLoggedIn, getPersonalAccessToken } = require('../auth/token-store');
4
4
  const apiClient = require('../api/client');
5
5
 
6
6
  async function remove(skillId, options) {
7
- if (!isLoggedIn()) {
8
- console.error(chalk.red('❌ Please login first: skill-market-cli login\n'));
7
+ if (!isLoggedIn() && !getPersonalAccessToken()) {
8
+ console.error(chalk.red('❌ Please login first or set an access token:'));
9
+ console.error(chalk.gray(' skill-market-cli login'));
10
+ console.error(chalk.gray(' skill-market-cli token set <your-access-token>\n'));
9
11
  process.exit(1);
10
12
  }
11
13
 
@@ -1,5 +1,5 @@
1
1
  const chalk = require('chalk');
2
- const { clearToken, isLoggedIn } = require('../auth/token-store');
2
+ const { clearToken, clearPersonalAccessToken, isLoggedIn } = require('../auth/token-store');
3
3
  const apiClient = require('../api/client');
4
4
 
5
5
  async function logout() {
@@ -16,6 +16,7 @@ async function logout() {
16
16
  }
17
17
 
18
18
  clearToken();
19
+ clearPersonalAccessToken();
19
20
 
20
21
  console.log(chalk.green('已登出本地凭证'));
21
22
  console.log('');
@@ -0,0 +1,55 @@
1
+ const chalk = require('chalk');
2
+ const { getPersonalAccessToken, savePersonalAccessToken, clearPersonalAccessToken } = require('../auth/token-store');
3
+
4
+ function showHelp() {
5
+ console.log(`
6
+ 用法:skill-market-cli token <subcommand>
7
+
8
+ 子命令:
9
+ set <token> 保存 Personal Access Token 到本地配置
10
+ get 查看当前保存的 Personal Access Token
11
+ remove 删除本地保存的 Personal Access Token
12
+ `);
13
+ }
14
+
15
+ async function token(subcommand, value) {
16
+ switch (subcommand) {
17
+ case 'set': {
18
+ if (!value) {
19
+ console.error(chalk.red('错误:请提供 token 值'));
20
+ console.log(chalk.gray('示例:skill-market-cli token set pat_xxxxxxxxxx'));
21
+ process.exit(1);
22
+ }
23
+ savePersonalAccessToken(value);
24
+ console.log(chalk.green('✓ Personal Access Token 已保存'));
25
+ break;
26
+ }
27
+ case 'get': {
28
+ const pat = getPersonalAccessToken();
29
+ if (pat) {
30
+ console.log(chalk.cyan('当前 Personal Access Token:'));
31
+ console.log(pat);
32
+ } else {
33
+ console.log(chalk.yellow('尚未保存 Personal Access Token'));
34
+ console.log(chalk.gray('可通过以下命令设置:'));
35
+ console.log(chalk.gray(' skill-market-cli token set <your-token>'));
36
+ }
37
+ break;
38
+ }
39
+ case 'remove':
40
+ case 'rm': {
41
+ clearPersonalAccessToken();
42
+ console.log(chalk.green('✓ Personal Access Token 已删除'));
43
+ break;
44
+ }
45
+ default: {
46
+ showHelp();
47
+ if (subcommand) {
48
+ console.error(chalk.red(`未知子命令:${subcommand}`));
49
+ process.exit(1);
50
+ }
51
+ }
52
+ }
53
+ }
54
+
55
+ module.exports = token;
@@ -3,12 +3,14 @@ const path = require('path');
3
3
  const chalk = require('chalk');
4
4
  const inquirer = require('inquirer');
5
5
  const YAML = require('yaml');
6
- const { isLoggedIn } = require('../auth/token-store');
6
+ const { isLoggedIn, getPersonalAccessToken } = require('../auth/token-store');
7
7
  const apiClient = require('../api/client');
8
8
 
9
9
  async function update(skillId, options) {
10
- if (!isLoggedIn()) {
11
- console.error(chalk.red('❌ Please login first: skill-market-cli login\n'));
10
+ if (!isLoggedIn() && !getPersonalAccessToken()) {
11
+ console.error(chalk.red('❌ Please login first or set an access token:'));
12
+ console.error(chalk.gray(' skill-market-cli login'));
13
+ console.error(chalk.gray(' skill-market-cli token set <your-access-token>\n'));
12
14
  process.exit(1);
13
15
  }
14
16
 
@@ -2,7 +2,7 @@ const fs = require('fs-extra');
2
2
  const path = require('path');
3
3
  const chalk = require('chalk');
4
4
  const inquirer = require('inquirer');
5
- const { isLoggedIn } = require('../auth/token-store');
5
+ const { isLoggedIn, getPersonalAccessToken } = require('../auth/token-store');
6
6
  const apiClient = require('../api/client');
7
7
  const { runExampleAndCollect } = require('../lib/run-example-collect');
8
8
  const {
@@ -15,8 +15,10 @@ const {
15
15
  * 交互补全:名称、描述、标签、模型、rootUrl、用户案例 + 可选运行采集轨迹
16
16
  */
17
17
  async function upload(skillPath, options = {}) {
18
- if (!isLoggedIn()) {
19
- console.error(chalk.red('请先登录:skill-market-cli login\n'));
18
+ if (!isLoggedIn() && !getPersonalAccessToken()) {
19
+ console.error(chalk.red('请先登录或设置 Access Token:'));
20
+ console.error(chalk.gray(' skill-market-cli login'));
21
+ console.error(chalk.gray(' skill-market-cli token set <your-access-token>\n'));
20
22
  process.exit(1);
21
23
  }
22
24
 
package/src/index.js CHANGED
@@ -9,6 +9,7 @@ const upload = require('./commands/upload');
9
9
  const update = require('./commands/update');
10
10
  const remove = require('./commands/delete');
11
11
  const runExample = require('./commands/run-example');
12
+ const token = require('./commands/token');
12
13
  const { getConfig } = require('./auth/token-store');
13
14
  const { applyServerMode, getServerModesHelp } = require('./config/server-modes');
14
15
  const apiClient = require('./api/client');
@@ -67,6 +68,12 @@ program
67
68
  .description('清除本地登录状态并尝试撤销服务端令牌')
68
69
  .action(logout);
69
70
 
71
+ // Token command
72
+ program
73
+ .command('token [subcommand] [value]')
74
+ .description('管理 Personal Access Token(用于 CLI 免登录)')
75
+ .action(token);
76
+
70
77
  // List command
71
78
  program
72
79
  .command('list')
@@ -0,0 +1,26 @@
1
+ {
2
+ "model": "deepseek-chat",
3
+ "examples": [
4
+ {
5
+ "prompt": "请根据我仓库里的 SKILL.md 帮我执行上传,并告诉我你要确认哪些字段。",
6
+ "aiResponses": [
7
+ {
8
+ "type": "thinking",
9
+ "content": "用户要用 skill-market-cli 上传 SKILL。需先读 frontmatter,核对 name、描述、tags、model、rootUrl;至少一条用户案例与 thinking/toolcall/message 轨迹;再执行 upload 交互或脚本。"
10
+ },
11
+ {
12
+ "type": "toolcall",
13
+ "toolName": "read_file",
14
+ "toolInput": {
15
+ "path": "./SKILL.md"
16
+ }
17
+ },
18
+ {
19
+ "type": "message",
20
+ "content": "我会先读取 `SKILL.md` 的 frontmatter,列出缺失项;请你确认一条「最终用户会如何提问」的测试案例。然后运行 `skill-market-cli upload <skill 目录>`,在交互中补全字段并自动采集轨迹后提交到 Skill Market。"
21
+ }
22
+ ],
23
+ "model": "deepseek-chat"
24
+ }
25
+ ]
26
+ }
@@ -6,6 +6,7 @@ tags:
6
6
  - cli
7
7
  - upload
8
8
  model: deepseek-chat
9
+ rootUrl: https://raw.githubusercontent.com/LSTM-Kirigaya/skill-market-cli/refs/heads/main/src/skills/skill-market-upload/SKILL.md
9
10
  ---
10
11
 
11
12
  # Skill Market 上传助手(给 AI Agent 用)