skill-market-cli 1.0.0 → 1.1.0

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.
@@ -0,0 +1,78 @@
1
+ ---
2
+ name: code-reviewer
3
+ purpose: Review code changes and provide constructive feedback on quality, style, and potential issues
4
+ rootUrl: https://raw.githubusercontent.com/LSTM-Kirigaya/jinhui-skills/main/skills/code-reviewer/SKILL.md
5
+ tags: ["code-review", "development", "quality"]
6
+ model: claude-3-5-sonnet
7
+ ---
8
+
9
+ # Code Reviewer Skill
10
+
11
+ This skill helps review code changes and provide detailed feedback.
12
+
13
+ ## Usage Examples
14
+
15
+ ### Review a pull request
16
+
17
+ Please review this pull request for code quality and potential issues:
18
+
19
+ ```diff
20
+ + function calculateTotal(items) {
21
+ + let total = 0;
22
+ + for (let i = 0; i < items.length; i++) {
23
+ + total += items[i].price;
24
+ + }
25
+ + return total;
26
+ + }
27
+ ```
28
+
29
+ ### Check for security issues
30
+
31
+ Review this code for potential security vulnerabilities:
32
+
33
+ ```javascript
34
+ app.post('/login', (req, res) => {
35
+ const { username, password } = req.body;
36
+ const query = `SELECT * FROM users WHERE username = '${username}'`;
37
+ db.query(query, (err, results) => {
38
+ // ...
39
+ });
40
+ });
41
+ ```
42
+
43
+ ## AI Execution Output Format
44
+
45
+ When reviewing code, provide output in this structured format:
46
+
47
+ 1. **Summary** - Brief overview of the code changes
48
+ 2. **Quality Assessment** - Code quality rating (1-5 stars)
49
+ 3. **Issues Found** - List of specific issues with:
50
+ - Severity (Critical/High/Medium/Low)
51
+ - Location (line numbers)
52
+ - Description
53
+ - Suggested fix
54
+ 4. **Positive Aspects** - What was done well
55
+ 5. **Recommendations** - Actionable improvement suggestions
56
+
57
+ ## Required Fields
58
+
59
+ Based on the skill format, the following fields are required when uploading:
60
+
61
+ | Field | Type | Description |
62
+ |-------|------|-------------|
63
+ | name | string | Unique skill identifier (e.g., "code-reviewer") |
64
+ | purpose | string | What this skill does |
65
+ | rootUrl | string | GitHub raw URL to the SKILL.md file |
66
+ | tags | array | Categories for the skill |
67
+ | usageExamples | array | Example prompts with AI responses |
68
+ | model | string | Recommended AI model (optional) |
69
+
70
+ ## Usage Example Structure
71
+
72
+ Each usage example should include:
73
+ - `prompt`: The user's input/query
74
+ - `aiResponses`: Array of AI response items with:
75
+ - `type`: "thinking", "toolcall", or "message"
76
+ - `content`: The response content
77
+ - `toolName`: For toolcall type, the tool name
78
+ - `toolInput`: For toolcall type, the input parameters
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "skill-market-cli",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "CLI tool for managing skills on Skill Market",
5
5
  "main": "src/index.js",
6
6
  "bin": {
7
- "skill-market-cli": "./bin/skill-market-cli.js",
8
- "smcli": "./bin/skill-market-cli.js"
7
+ "skill-market-cli": "bin/skill-market-cli.js",
8
+ "smcli": "bin/skill-market-cli.js"
9
9
  },
10
10
  "scripts": {
11
11
  "test": "echo \"Error: no test specified\" && exit 1"
@@ -35,10 +35,10 @@
35
35
  },
36
36
  "repository": {
37
37
  "type": "git",
38
- "url": "https://github.com/yourusername/skill-market-cli.git"
38
+ "url": "git+https://github.com/LSTM-Kirigaya/skill-market-cli.git"
39
39
  },
40
40
  "homepage": "https://kirigaya.cn/ktools/skillmanager",
41
41
  "bugs": {
42
- "url": "https://github.com/yourusername/skill-market-cli/issues"
42
+ "url": "https://github.com/LSTM-Kirigaya/skill-market-cli/issues"
43
43
  }
44
44
  }
package/src/api/client.js CHANGED
@@ -9,6 +9,10 @@ class ApiClient {
9
9
  this.init();
10
10
  }
11
11
 
12
+ reinit() {
13
+ this.init();
14
+ }
15
+
12
16
  init() {
13
17
  const serverConfig = getServerConfig();
14
18
  this.client = axios.create({
@@ -101,12 +105,12 @@ class ApiClient {
101
105
  }
102
106
 
103
107
  async uploadSkill(data) {
104
- const response = await this.client.post('/skill/upload', data);
108
+ const response = await this.client.post('/skill/ai/upload', data);
105
109
  return response.data;
106
110
  }
107
111
 
108
112
  async updateSkill(id, data) {
109
- const response = await this.client.post(`/skill/update/${id}`, data);
113
+ const response = await this.client.post(`/skill/ai/update/${id}`, data);
110
114
  return response.data;
111
115
  }
112
116
 
package/src/auth/oauth.js CHANGED
@@ -1,155 +1,196 @@
1
1
  const http = require('http');
2
- const url = require('url');
3
2
  const chalk = require('chalk');
4
3
  const open = require('open');
5
4
  const axios = require('axios');
6
- const { saveToken, getServerConfig, setServerConfig } = require('./token-store');
5
+ const { saveToken, getServerConfig } = require('./token-store');
7
6
 
8
- const DEFAULT_SERVER_URL = 'https://kirigaya.cn';
9
7
  const CLIENT_ID = 'skill-market-cli';
10
8
 
11
- // 获取 OAuth 配置
9
+ function getApiRoot() {
10
+ const serverConfig = getServerConfig();
11
+ return serverConfig.apiBase || `${serverConfig.baseURL}/api`;
12
+ }
13
+
12
14
  async function getOAuthConfig() {
15
+ const serverConfig = getServerConfig();
16
+ const apiRoot = getApiRoot();
17
+
13
18
  try {
14
- const serverConfig = getServerConfig();
15
- const response = await axios.get(`${serverConfig.baseURL}/oauth/config`);
19
+ const response = await axios.get(`${apiRoot}/oauth/config`);
16
20
  if (response.data && response.data.code === 200) {
17
- return response.data.data;
21
+ const data = response.data.data || {};
22
+ return {
23
+ ...data,
24
+ authorizeURL: `${serverConfig.baseURL}/oauth/authorize`,
25
+ tokenURL: `${apiRoot}/oauth/token`,
26
+ userinfoURL: `${apiRoot}/oauth/userinfo`
27
+ };
18
28
  }
19
29
  } catch (e) {
20
- // 使用默认配置
30
+ // 使用下方默认配置
21
31
  }
32
+
22
33
  return {
23
34
  clientId: CLIENT_ID,
24
35
  redirectUri: 'http://localhost:0/callback',
25
- authorizeURL: `${DEFAULT_SERVER_URL}/oauth/authorize`,
26
- tokenURL: `${DEFAULT_SERVER_URL}/oauth/token`,
36
+ authorizeURL: `${serverConfig.baseURL}/oauth/authorize`,
37
+ tokenURL: `${apiRoot}/oauth/token`,
38
+ userinfoURL: `${apiRoot}/oauth/userinfo`,
27
39
  scopes: ['skill:read', 'skill:write', 'user:read']
28
40
  };
29
41
  }
30
42
 
31
- // 启动本地回调服务器
32
- function startCallbackServer(port = 0) {
33
- return new Promise((resolve, reject) => {
34
- const server = http.createServer((req, res) => {
35
- const parsedUrl = url.parse(req.url, true);
36
- const { code, error, error_description } = parsedUrl.query;
37
-
38
- if (error) {
39
- res.writeHead(400, { 'Content-Type': 'text/html; charset=utf-8' });
40
- res.end(`
41
- <!DOCTYPE html>
42
- <html>
43
- <head><title>授权失败</title></head>
44
- <body style="text-align:center;padding:50px;font-family:sans-serif;">
45
- <h1 style="color:#f44336;">❌ 授权失败</h1>
46
- <p>${error_description || error}</p>
47
- <p>请关闭此窗口并返回命令行</p>
48
- </body>
49
- </html>
50
- `);
51
- server.close();
52
- reject(new Error(error_description || error));
53
- return;
54
- }
43
+ function startCallbackServer() {
44
+ let resolveCode;
45
+ let rejectCode;
55
46
 
56
- if (code) {
57
- res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
58
- res.end(`
59
- <!DOCTYPE html>
60
- <html>
61
- <head><title>授权成功</title></head>
62
- <body style="text-align:center;padding:50px;font-family:sans-serif;background:linear-gradient(135deg,#667eea,#764ba2);">
63
- <div style="background:white;padding:40px;border-radius:12px;box-shadow:0 10px 40px rgba(0,0,0,0.2);display:inline-block;">
64
- <div style="font-size:64px;color:#4CAF50;">✓</div>
65
- <h1 style="color:#333;">授权成功</h1>
66
- <p style="color:#666;">您已成功授权 Skill Market CLI</p>
67
- <p style="color:#999;font-size:14px;">请关闭此窗口并返回命令行</p>
68
- </div>
69
- </body>
70
- </html>
71
- `);
72
- server.close();
73
- resolve(code);
74
- }
75
- });
47
+ const codePromise = new Promise((resolve, reject) => {
48
+ resolveCode = resolve;
49
+ rejectCode = reject;
50
+ });
51
+
52
+ const server = http.createServer((req, res) => {
53
+ let pathname;
54
+ let code;
55
+ let error;
56
+ let error_description;
57
+ try {
58
+ const base = `http://127.0.0.1:${server.address().port}`;
59
+ const u = new URL(req.url || '/', base);
60
+ pathname = u.pathname;
61
+ code = u.searchParams.get('code');
62
+ error = u.searchParams.get('error');
63
+ error_description = u.searchParams.get('error_description');
64
+ } catch {
65
+ res.writeHead(400, { 'Content-Type': 'text/plain; charset=utf-8' });
66
+ res.end('Bad request');
67
+ return;
68
+ }
69
+
70
+ if (pathname === '/favicon.ico') {
71
+ res.writeHead(204);
72
+ res.end();
73
+ return;
74
+ }
75
+
76
+ if (error) {
77
+ res.writeHead(400, { 'Content-Type': 'text/html; charset=utf-8' });
78
+ res.end(`<!DOCTYPE html><html><head><meta charset="utf-8"><title>授权未通过</title></head>
79
+ <body style="font-family:sans-serif;text-align:center;padding:48px;">
80
+ <h1>授权未通过</h1><p>${error_description || error}</p><p>请关闭此窗口,回到终端继续操作。</p>
81
+ </body></html>`);
82
+ server.close();
83
+ rejectCode(new Error(error_description || error));
84
+ return;
85
+ }
76
86
 
77
- server.listen(port, () => {
87
+ if (code) {
88
+ res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
89
+ res.end(`<!DOCTYPE html><html><head><meta charset="utf-8"><title>授权完成</title></head>
90
+ <body style="font-family:sans-serif;text-align:center;padding:48px;">
91
+ <h1>授权完成</h1><p>本窗口可关闭,请回到终端查看登录结果。</p>
92
+ </body></html>`);
93
+ server.close();
94
+ resolveCode(code);
95
+ return;
96
+ }
97
+
98
+ res.writeHead(404, { 'Content-Type': 'text/plain' });
99
+ res.end('Not found');
100
+ });
101
+
102
+ return new Promise((resolve, reject) => {
103
+ server.listen(0, () => {
78
104
  const actualPort = server.address().port;
79
- console.log(chalk.gray(`Callback server listening on port ${actualPort}`));
105
+ console.log(chalk.gray(`本地回调服务已启动,端口:${actualPort}`));
106
+ resolve({ port: actualPort, codePromise });
80
107
  });
81
108
 
82
109
  server.on('error', reject);
83
110
  });
84
111
  }
85
112
 
86
- // 执行 OAuth 登录流程
113
+ function formatApiError(err) {
114
+ const d = err.response && err.response.data;
115
+ if (!d) return err.message || String(err);
116
+ if (typeof d === 'string') return d;
117
+ if (d.error_description) return d.error_description;
118
+ if (d.error) return d.error;
119
+ try {
120
+ return JSON.stringify(d);
121
+ } catch {
122
+ return err.message;
123
+ }
124
+ }
125
+
87
126
  async function login(options = {}) {
88
- console.log(chalk.blue('🔐 Starting OAuth login flow...\n'));
127
+ const serverConfig = getServerConfig();
128
+
129
+ console.log(chalk.bold('Skill Market 登录'));
130
+ console.log(chalk.gray(`站点地址:${serverConfig.baseURL}`));
89
131
 
90
- // 获取 OAuth 配置
91
132
  const oauthConfig = await getOAuthConfig();
92
- console.log(chalk.gray(`Server: ${oauthConfig.authorizeURL}`));
93
133
 
94
- // 启动本地回调服务器
95
- let callbackPort = 0;
96
- const callbackPromise = startCallbackServer(callbackPort);
134
+ const { port, codePromise } = await startCallbackServer();
135
+ const redirectUri = `http://localhost:${port}/callback`;
97
136
 
98
- // 构造授权 URL
99
137
  const state = generateRandomString(16);
100
- const redirectUri = `http://localhost:${callbackPort}/callback`;
101
-
102
- const authUrl = new URL(oauthConfig.authorizeURL);
138
+ const authorizeURL = oauthConfig.authorizeURL || `${serverConfig.baseURL}/oauth/authorize`;
139
+ const authUrl = new URL(authorizeURL);
103
140
  authUrl.searchParams.set('response_type', 'code');
104
141
  authUrl.searchParams.set('client_id', oauthConfig.clientId);
105
142
  authUrl.searchParams.set('redirect_uri', redirectUri);
106
- authUrl.searchParams.set('scope', oauthConfig.scopes.join(' '));
143
+ const scopeVal = oauthConfig.scopes;
144
+ const scopeStr = Array.isArray(scopeVal)
145
+ ? scopeVal.join(' ')
146
+ : (scopeVal || 'skill:read skill:write user:read');
147
+ authUrl.searchParams.set('scope', scopeStr);
107
148
  authUrl.searchParams.set('state', state);
108
149
 
109
- console.log(chalk.cyan('\n📱 Please authorize the CLI in your browser.\n'));
110
- console.log(chalk.gray('Authorization URL:'));
111
- console.log(chalk.underline(authUrl.toString()));
112
- console.log();
150
+ console.log('');
151
+ console.log('请在浏览器中完成授权(将自动打开页面;若未打开,请复制下方链接到浏览器):');
152
+ console.log(chalk.cyan(authUrl.toString()));
153
+ console.log('');
113
154
 
114
- // 自动打开浏览器
115
155
  if (options.open !== false) {
116
156
  try {
117
157
  await open(authUrl.toString());
118
- console.log(chalk.gray('Browser opened automatically.\n'));
158
+ console.log(chalk.gray('已尝试打开系统默认浏览器。'));
119
159
  } catch (e) {
120
- console.log(chalk.yellow('Could not open browser automatically.'));
121
- console.log(chalk.yellow('Please open the URL manually.\n'));
160
+ console.log(chalk.yellow('无法自动打开浏览器,请手动访问上方链接。'));
122
161
  }
123
162
  }
124
163
 
125
- // 等待回调
126
164
  try {
127
- const code = await callbackPromise;
128
- console.log(chalk.green('✅ Authorization code received'));
129
-
130
- // 交换 Token
131
- console.log(chalk.gray('Exchanging code for token...'));
132
-
133
- const tokenResponse = await axios.post(oauthConfig.tokenURL, {
134
- grant_type: 'authorization_code',
135
- code: code,
136
- redirect_uri: redirectUri,
137
- client_id: oauthConfig.clientId,
138
- client_secret: 'dummy-secret' // 实际使用时需要从安全的地方获取
139
- });
165
+ const code = await codePromise;
166
+ console.log(chalk.gray('已收到授权码,正在换取访问令牌…'));
167
+
168
+ const tokenURL = oauthConfig.tokenURL;
169
+ const tokenResponse = await axios.post(
170
+ tokenURL,
171
+ {
172
+ grant_type: 'authorization_code',
173
+ code: code,
174
+ redirect_uri: redirectUri,
175
+ client_id: oauthConfig.clientId,
176
+ client_secret: 'dummy-secret'
177
+ },
178
+ {
179
+ headers: { 'Content-Type': 'application/json' }
180
+ }
181
+ );
140
182
 
141
183
  const { access_token, refresh_token, expires_in } = tokenResponse.data;
142
184
 
143
- // 获取用户信息
144
- const userResponse = await axios.get(`${oauthConfig.authorizeURL.replace('/authorize', '/userinfo')}`, {
185
+ const userinfoURL = oauthConfig.userinfoURL;
186
+ const userResponse = await axios.get(userinfoURL, {
145
187
  headers: {
146
- 'Authorization': `Bearer ${access_token}`
188
+ Authorization: `Bearer ${access_token}`
147
189
  }
148
190
  });
149
191
 
150
192
  const user = userResponse.data;
151
193
 
152
- // 保存 Token
153
194
  const expiresAt = Date.now() + (expires_in * 1000);
154
195
  saveToken(access_token, refresh_token, expiresAt, {
155
196
  name: user.name,
@@ -157,38 +198,46 @@ async function login(options = {}) {
157
198
  picture: user.picture
158
199
  });
159
200
 
160
- console.log();
161
- console.log(chalk.green('✅ Login successful!'));
162
- console.log(chalk.cyan(`👤 Welcome, ${user.name}!`));
163
- console.log();
201
+ console.log('');
202
+ console.log(chalk.green('登录成功'));
203
+ console.log(chalk.gray(`当前用户:${user.name || user.sub || '(未返回名称)'}`));
204
+ console.log('');
164
205
 
165
206
  return true;
166
207
  } catch (error) {
167
- console.error();
168
- console.error(chalk.red('❌ Login failed:'), error.message);
169
- if (error.response) {
170
- console.error(chalk.red('Server response:'), error.response.data);
208
+ console.log('');
209
+ console.log(chalk.red('登录失败'));
210
+ console.log(chalk.red(formatApiError(error)));
211
+ if (error.response && error.response.data && process.env.DEBUG) {
212
+ console.log(chalk.gray(JSON.stringify(error.response.data, null, 2)));
171
213
  }
214
+ console.log('');
172
215
  return false;
173
216
  }
174
217
  }
175
218
 
176
- // 刷新 Token
177
219
  async function refreshAccessToken() {
178
220
  const { refreshToken } = require('./token-store').getToken();
179
221
  if (!refreshToken) {
180
- throw new Error('No refresh token available');
222
+ throw new Error('无刷新令牌,请重新登录');
181
223
  }
182
224
 
183
225
  const oauthConfig = await getOAuthConfig();
184
-
226
+ const tokenURL = oauthConfig.tokenURL;
227
+
185
228
  try {
186
- const response = await axios.post(oauthConfig.tokenURL, {
187
- grant_type: 'refresh_token',
188
- refresh_token: refreshToken,
189
- client_id: oauthConfig.clientId,
190
- client_secret: 'dummy-secret'
191
- });
229
+ const response = await axios.post(
230
+ tokenURL,
231
+ {
232
+ grant_type: 'refresh_token',
233
+ refresh_token: refreshToken,
234
+ client_id: oauthConfig.clientId,
235
+ client_secret: 'dummy-secret'
236
+ },
237
+ {
238
+ headers: { 'Content-Type': 'application/json' }
239
+ }
240
+ );
192
241
 
193
242
  const { access_token, refresh_token, expires_in } = response.data;
194
243
  const expiresAt = Date.now() + (expires_in * 1000);
@@ -198,11 +247,10 @@ async function refreshAccessToken() {
198
247
 
199
248
  return access_token;
200
249
  } catch (error) {
201
- throw new Error('Failed to refresh token: ' + error.message);
250
+ throw new Error('刷新令牌失败:' + formatApiError(error));
202
251
  }
203
252
  }
204
253
 
205
- // 生成随机字符串
206
254
  function generateRandomString(length) {
207
255
  const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
208
256
  let result = '';
@@ -70,7 +70,7 @@ function isLoggedIn() {
70
70
  return true;
71
71
  }
72
72
 
73
- // 获取服务器配置
73
+ // 获取服务器配置(默认与 --mode production 一致)
74
74
  function getServerConfig() {
75
75
  const config = getConfig();
76
76
  return config.server || {
@@ -3,16 +3,15 @@ const { isLoggedIn } = require('../auth/token-store');
3
3
  const { login: oauthLogin } = require('../auth/oauth');
4
4
 
5
5
  async function login(options) {
6
- // 检查是否已登录
7
6
  if (isLoggedIn()) {
8
- console.log(chalk.yellow('⚠️ You are already logged in.'));
9
- console.log(chalk.gray('Use "skill-market-cli logout" to logout first.\n'));
7
+ console.log(chalk.yellow('当前已处于登录状态。'));
8
+ console.log(chalk.gray('如需重新登录,请先执行:skill-market-cli logout'));
9
+ console.log('');
10
10
  return;
11
11
  }
12
12
 
13
- // 执行登录
14
13
  const success = await oauthLogin(options);
15
-
14
+
16
15
  if (!success) {
17
16
  process.exit(1);
18
17
  }
@@ -4,21 +4,21 @@ const apiClient = require('../api/client');
4
4
 
5
5
  async function logout() {
6
6
  if (!isLoggedIn()) {
7
- console.log(chalk.yellow('⚠️ You are not logged in.\n'));
7
+ console.log(chalk.yellow('当前未登录,无需登出。'));
8
+ console.log('');
8
9
  return;
9
10
  }
10
11
 
11
12
  try {
12
- // 通知服务器登出(撤销 Token)
13
13
  await apiClient.client.post('/oauth/logout');
14
14
  } catch (e) {
15
- // 忽略错误
15
+ // 忽略网络错误,仍清除本地凭证
16
16
  }
17
17
 
18
- // 清除本地 Token
19
18
  clearToken();
20
19
 
21
- console.log(chalk.green('✅ Logged out successfully.\n'));
20
+ console.log(chalk.green('已登出本地凭证'));
21
+ console.log('');
22
22
  }
23
23
 
24
24
  module.exports = logout;
@@ -3,6 +3,7 @@ const path = require('path');
3
3
  const chalk = require('chalk');
4
4
  const inquirer = require('inquirer');
5
5
  const YAML = require('yaml');
6
+ const { runExampleAndCollect } = require('../lib/run-example-collect');
6
7
 
7
8
  /**
8
9
  * Run user examples and collect AI responses
@@ -213,60 +214,4 @@ async function addExampleInteractively(skillFilePath, skillContent, model) {
213
214
  }
214
215
  }
215
216
 
216
- /**
217
- * 运行示例并收集 AI 响应
218
- * 这里需要集成 AI API,目前使用模拟数据
219
- */
220
- async function runExampleAndCollect(prompt, model) {
221
- console.log(chalk.blue('\n🤖 Running example with AI...'));
222
- console.log(chalk.gray(`Model: ${model}\n`));
223
-
224
- // 这里应该调用实际的 AI API
225
- // 目前模拟一个典型的 AI 响应流程
226
-
227
- console.log(chalk.gray('Simulating AI response collection...'));
228
- console.log(chalk.gray('In production, this would call the AI API and capture:'));
229
- console.log(chalk.gray(' 1. Thinking steps'));
230
- console.log(chalk.gray(' 2. Tool calls'));
231
- console.log(chalk.gray(' 3. Final message\n'));
232
-
233
- // 模拟 AI 响应
234
- const simulatedResponses = [
235
- {
236
- type: 'thinking',
237
- content: `Let me analyze this request: "${prompt}". The user wants me to help them with a specific task. I'll break this down into steps and execute the appropriate tools.`
238
- },
239
- {
240
- type: 'toolcall',
241
- toolName: 'read_file',
242
- toolInput: { path: './README.md' }
243
- },
244
- {
245
- type: 'toolcall',
246
- toolName: 'write_file',
247
- toolInput: {
248
- path: './output.txt',
249
- content: `Processed: ${prompt}`
250
- }
251
- },
252
- {
253
- type: 'message',
254
- content: `I've processed your request: "${prompt}". Here's what I did:\n\n1. Analyzed the requirements\n2. Read the relevant files\n3. Generated the output\n\nThe task is now complete!`
255
- }
256
- ];
257
-
258
- // 模拟处理时间
259
- await new Promise(resolve => setTimeout(resolve, 1000));
260
-
261
- console.log(chalk.gray('Collected responses:'));
262
- simulatedResponses.forEach((resp, i) => {
263
- const icon = resp.type === 'thinking' ? '💭' :
264
- resp.type === 'toolcall' ? '🔧' : '💬';
265
- console.log(chalk.gray(` ${icon} [${resp.type}]`));
266
- });
267
- console.log();
268
-
269
- return simulatedResponses;
270
- }
271
-
272
217
  module.exports = runExample;