needware-cli 1.2.9 → 1.3.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.
@@ -0,0 +1,350 @@
1
+ /**
2
+ * 图片转换功能使用示例
3
+ *
4
+ * 这个示例展示如何使用 prompt-parser 中的图片转换功能
5
+ */
6
+
7
+ import {
8
+ convertImageToBase64,
9
+ convertImagesToBase64,
10
+ convertRemoteImageToBase64,
11
+ convertRemoteImagesToBase64,
12
+ convertImageToBase64Smart,
13
+ convertImagesToBase64Smart,
14
+ isImageFile,
15
+ ImageContentBlock,
16
+ } from '../src/utils/prompt-parser.js';
17
+
18
+ /**
19
+ * 示例 1: 单个图片转换
20
+ */
21
+ async function example1_singleImage() {
22
+ console.log('示例 1: 转换单个图片文件');
23
+ console.log('================================\n');
24
+
25
+ try {
26
+ // 转换单个图片
27
+ const imageBlock = await convertImageToBase64('./path/to/image.jpg');
28
+
29
+ console.log('转换结果:');
30
+ console.log(JSON.stringify(imageBlock, null, 2));
31
+
32
+ // 输出格式:
33
+ // {
34
+ // "type": "image",
35
+ // "source": {
36
+ // "type": "base64",
37
+ // "media_type": "image/jpeg",
38
+ // "data": "/9j/4AAQSkZJRgABAQAAAQABAAD..."
39
+ // }
40
+ // }
41
+ } catch (error) {
42
+ console.error('转换失败:', error);
43
+ }
44
+ }
45
+
46
+ /**
47
+ * 示例 2: 批量图片转换
48
+ */
49
+ async function example2_multipleImages() {
50
+ console.log('\n示例 2: 批量转换多个图片');
51
+ console.log('================================\n');
52
+
53
+ try {
54
+ const imagePaths = [
55
+ './images/photo1.jpg',
56
+ './images/photo2.png',
57
+ './images/diagram.webp',
58
+ ];
59
+
60
+ const imageBlocks = await convertImagesToBase64(imagePaths);
61
+
62
+ console.log(`成功转换 ${imageBlocks.length} 个图片`);
63
+ imageBlocks.forEach((block, index) => {
64
+ console.log(`\n图片 ${index + 1}:`);
65
+ console.log(` 类型: ${block.source.media_type}`);
66
+ console.log(` 数据大小: ${block.source.data.length} 字符`);
67
+ });
68
+ } catch (error) {
69
+ console.error('批量转换失败:', error);
70
+ }
71
+ }
72
+
73
+ /**
74
+ * 示例 3: 检查文件是否为图片
75
+ */
76
+ function example3_checkImageFile() {
77
+ console.log('\n示例 3: 检查文件类型');
78
+ console.log('================================\n');
79
+
80
+ const files = [
81
+ 'photo.jpg',
82
+ 'document.pdf',
83
+ 'image.png',
84
+ 'video.mp4',
85
+ 'diagram.webp',
86
+ ];
87
+
88
+ files.forEach((file) => {
89
+ const isImage = isImageFile(file);
90
+ console.log(`${file}: ${isImage ? '✓ 是图片' : '✗ 不是图片'}`);
91
+ });
92
+ }
93
+
94
+ /**
95
+ * 示例 4: 创建带图片的消息
96
+ */
97
+ async function example4_createMessageWithImage() {
98
+ console.log('\n示例 4: 创建包含图片的消息');
99
+ console.log('================================\n');
100
+
101
+ try {
102
+ // 转换图片
103
+ const imageBlock = await convertImageToBase64('./chart.png');
104
+
105
+ // 创建包含文本和图片的消息
106
+ const message = {
107
+ type: 'user',
108
+ session_id: 'session-123',
109
+ message: {
110
+ role: 'user',
111
+ content: [
112
+ {
113
+ type: 'text',
114
+ text: '请分析这张图表',
115
+ },
116
+ imageBlock,
117
+ ],
118
+ },
119
+ parent_tool_use_id: null,
120
+ };
121
+
122
+ console.log('创建的消息结构:');
123
+ console.log(JSON.stringify(message, null, 2));
124
+ } catch (error) {
125
+ console.error('创建消息失败:', error);
126
+ }
127
+ }
128
+
129
+ /**
130
+ * 示例 5: 混合多个内容类型
131
+ */
132
+ async function example5_mixedContent() {
133
+ console.log('\n示例 5: 混合文本和多个图片');
134
+ console.log('================================\n');
135
+
136
+ try {
137
+ const image1 = await convertImageToBase64('./before.jpg');
138
+ const image2 = await convertImageToBase64('./after.jpg');
139
+
140
+ const message = {
141
+ type: 'user',
142
+ session_id: 'session-456',
143
+ message: {
144
+ role: 'user',
145
+ content: [
146
+ {
147
+ type: 'text',
148
+ text: '这是修改前的图片:',
149
+ },
150
+ image1,
151
+ {
152
+ type: 'text',
153
+ text: '这是修改后的图片:',
154
+ },
155
+ image2,
156
+ {
157
+ type: 'text',
158
+ text: '请比较这两张图片的差异',
159
+ },
160
+ ],
161
+ },
162
+ parent_tool_use_id: null,
163
+ };
164
+
165
+ console.log('创建的多模态消息:');
166
+ console.log(
167
+ JSON.stringify(
168
+ {
169
+ ...message,
170
+ message: {
171
+ ...message.message,
172
+ content: message.message.content.map((item) =>
173
+ item.type === 'image'
174
+ ? { ...item, source: { ...item.source, data: '[BASE64_DATA]' } }
175
+ : item
176
+ ),
177
+ },
178
+ },
179
+ null,
180
+ 2
181
+ )
182
+ );
183
+ } catch (error) {
184
+ console.error('创建混合内容失败:', error);
185
+ }
186
+ }
187
+
188
+ /**
189
+ * 示例 6: 转换远程URL图片
190
+ */
191
+ async function example6_remoteImage() {
192
+ console.log('\n示例 6: 转换远程URL图片');
193
+ console.log('================================\n');
194
+
195
+ try {
196
+ const imageUrl = 'https://example.com/photo.jpg';
197
+ const imageBlock = await convertRemoteImageToBase64(imageUrl);
198
+
199
+ console.log('远程图片转换成功:');
200
+ console.log(` 类型: ${imageBlock.source.media_type}`);
201
+ console.log(` 数据大小: ${imageBlock.source.data.length} 字符`);
202
+ } catch (error) {
203
+ console.error('转换远程图片失败:', error);
204
+ }
205
+ }
206
+
207
+ /**
208
+ * 示例 7: 批量转换远程图片
209
+ */
210
+ async function example7_multipleRemoteImages() {
211
+ console.log('\n示例 7: 批量转换远程图片');
212
+ console.log('================================\n');
213
+
214
+ try {
215
+ const imageUrls = [
216
+ 'https://example.com/photo1.jpg',
217
+ 'https://example.com/photo2.png',
218
+ 'https://example.com/diagram.webp',
219
+ ];
220
+
221
+ const imageBlocks = await convertRemoteImagesToBase64(imageUrls);
222
+
223
+ console.log(`成功转换 ${imageBlocks.length} 个远程图片`);
224
+ imageBlocks.forEach((block, index) => {
225
+ console.log(`\n图片 ${index + 1}:`);
226
+ console.log(` 类型: ${block.source.media_type}`);
227
+ console.log(` 数据大小: ${block.source.data.length} 字符`);
228
+ });
229
+ } catch (error) {
230
+ console.error('批量转换远程图片失败:', error);
231
+ }
232
+ }
233
+
234
+ /**
235
+ * 示例 8: 智能转换(自动检测本地或远程)
236
+ */
237
+ async function example8_smartConversion() {
238
+ console.log('\n示例 8: 智能转换(混合本地和远程)');
239
+ console.log('================================\n');
240
+
241
+ try {
242
+ // 混合本地文件和远程URL
243
+ const imagePaths = [
244
+ './local-photo.jpg', // 本地文件
245
+ 'https://example.com/remote-photo.jpg', // 远程URL
246
+ './another-local.png', // 本地文件
247
+ 'https://example.com/another-remote.png', // 远程URL
248
+ ];
249
+
250
+ const imageBlocks = await convertImagesToBase64Smart(imagePaths);
251
+
252
+ console.log(`成功转换 ${imageBlocks.length} 个图片(混合本地和远程)`);
253
+ imageBlocks.forEach((block, index) => {
254
+ const source = imagePaths[index].startsWith('http') ? '远程' : '本地';
255
+ console.log(`\n图片 ${index + 1} (${source}):`);
256
+ console.log(` 路径: ${imagePaths[index]}`);
257
+ console.log(` 类型: ${block.source.media_type}`);
258
+ console.log(` 数据大小: ${block.source.data.length} 字符`);
259
+ });
260
+ } catch (error) {
261
+ console.error('智能转换失败:', error);
262
+ }
263
+ }
264
+
265
+ /**
266
+ * 示例 9: 使用远程图片创建消息
267
+ */
268
+ async function example9_messageWithRemoteImage() {
269
+ console.log('\n示例 9: 使用远程图片创建消息');
270
+ console.log('================================\n');
271
+
272
+ try {
273
+ // 从远程URL转换图片
274
+ const imageBlock = await convertRemoteImageToBase64(
275
+ 'https://example.com/design-mockup.png'
276
+ );
277
+
278
+ // 创建包含远程图片的消息
279
+ const message = {
280
+ type: 'user',
281
+ session_id: 'session-789',
282
+ message: {
283
+ role: 'user',
284
+ content: [
285
+ {
286
+ type: 'text',
287
+ text: '请根据这个设计图一比一还原界面',
288
+ },
289
+ imageBlock,
290
+ ],
291
+ },
292
+ parent_tool_use_id: null,
293
+ };
294
+
295
+ console.log('创建的消息包含远程图片:');
296
+ console.log(
297
+ JSON.stringify(
298
+ {
299
+ ...message,
300
+ message: {
301
+ ...message.message,
302
+ content: message.message.content.map((item) =>
303
+ item.type === 'image'
304
+ ? { ...item, source: { ...item.source, data: '[BASE64_DATA]' } }
305
+ : item
306
+ ),
307
+ },
308
+ },
309
+ null,
310
+ 2
311
+ )
312
+ );
313
+ } catch (error) {
314
+ console.error('创建消息失败:', error);
315
+ }
316
+ }
317
+
318
+ // 运行所有示例
319
+ async function runAllExamples() {
320
+ console.log('图片转换功能示例\n');
321
+ console.log('注意:这些示例需要实际的图片文件或有效的图片URL才能运行');
322
+ console.log('请根据您的文件路径和URL调整示例中的参数\n');
323
+
324
+ // 本地图片示例
325
+ // example1_singleImage();
326
+ // example2_multipleImages();
327
+ example3_checkImageFile();
328
+ // example4_createMessageWithImage();
329
+ // example5_mixedContent();
330
+
331
+ // 远程图片示例
332
+ // example6_remoteImage();
333
+ // example7_multipleRemoteImages();
334
+ // example8_smartConversion();
335
+ // example9_messageWithRemoteImage();
336
+ }
337
+
338
+ // 如果直接运行此文件,执行示例
339
+ if (import.meta.url === `file://${process.argv[1]}`) {
340
+ runAllExamples().catch(console.error);
341
+ }
342
+
343
+ export {
344
+ example1_singleImage,
345
+ example2_multipleImages,
346
+ example3_checkImageFile,
347
+ example4_createMessageWithImage,
348
+ example5_mixedContent,
349
+ };
350
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "needware-cli",
3
- "version": "1.2.9",
3
+ "version": "1.3.1",
4
4
  "description": "一个功能强大的 Node.js 命令行工具",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -20,7 +20,7 @@
20
20
  "lint:fix": "eslint 'src/**/*.ts' --fix",
21
21
  "format": "prettier --write 'src/**/*.ts'",
22
22
  "prepare": "husky install",
23
- "prepublishOnly": "npm run lint && npm test && npm run build",
23
+ "prepublishOnly": "npm run build",
24
24
  "diagnose:container": "bash scripts/fix-container-permissions.sh"
25
25
  },
26
26
  "keywords": [
@@ -0,0 +1,69 @@
1
+ #!/bin/bash
2
+
3
+ # 多模态消息测试脚本
4
+ # 用于测试 needware-cli 的多模态消息支持
5
+
6
+ echo "======================================"
7
+ echo "多模态消息支持测试"
8
+ echo "======================================"
9
+ echo ""
10
+
11
+ # 检查是否提供了 API Key
12
+ if [ -z "$1" ]; then
13
+ echo "❌ 错误:请提供 API Key"
14
+ echo ""
15
+ echo "使用方法:"
16
+ echo " ./test-multimodal.sh YOUR_API_KEY [BASE_URL]"
17
+ echo ""
18
+ echo "示例:"
19
+ echo " ./test-multimodal.sh sk-ant-xxx https://api.openai-proxy.org/anthropic"
20
+ exit 1
21
+ fi
22
+
23
+ API_KEY="$1"
24
+ BASE_URL="${2:-}"
25
+
26
+ echo "✓ API Key: ${API_KEY:0:10}..."
27
+ if [ -n "$BASE_URL" ]; then
28
+ echo "✓ Base URL: $BASE_URL"
29
+ fi
30
+ echo ""
31
+
32
+ # 编译项目
33
+ echo "📦 编译项目..."
34
+ npm run build
35
+ if [ $? -ne 0 ]; then
36
+ echo "❌ 编译失败"
37
+ exit 1
38
+ fi
39
+ echo "✓ 编译成功"
40
+ echo ""
41
+
42
+ # 测试 1:使用示例文件
43
+ echo "======================================"
44
+ echo "测试 1: 从文件读取多模态消息"
45
+ echo "======================================"
46
+ echo ""
47
+ echo "命令:"
48
+ if [ -n "$BASE_URL" ]; then
49
+ echo " needware-cli agent examples/multimodal-message-example.json --api-key $API_KEY --base-url $BASE_URL"
50
+ echo ""
51
+ node bin/cli.js agent examples/multimodal-message-example.json --api-key "$API_KEY" --base-url "$BASE_URL"
52
+ else
53
+ echo " needware-cli agent examples/multimodal-message-example.json --api-key $API_KEY"
54
+ echo ""
55
+ node bin/cli.js agent examples/multimodal-message-example.json --api-key "$API_KEY"
56
+ fi
57
+
58
+ echo ""
59
+ echo "======================================"
60
+ echo "测试完成"
61
+ echo "======================================"
62
+ echo ""
63
+ echo "💡 提示:"
64
+ echo " - 如果看到 Agent 开始处理消息,说明功能正常"
65
+ echo " - 多模态消息会自动使用交互式模式"
66
+ echo " - 更多使用示例请查看 EXAMPLES.md"
67
+ echo ""
68
+
69
+
package/EXAMPLES.md DELETED
@@ -1,241 +0,0 @@
1
- # Agent 命令使用示例
2
-
3
- ## 📌 快速开始
4
-
5
- ### 1. 简单文本字符串
6
-
7
- 最简单的用法,直接提供文本:
8
-
9
- ```bash
10
- needware-cli agent "创建一个待办事项列表应用"
11
- ```
12
-
13
- ### 2. 从文件读取文本
14
-
15
- 创建文件 `prompt.txt`:
16
- ```
17
- 创建一个用户登录页面,包含:
18
- - 用户名输入框
19
- - 密码输入框
20
- - 记住我选项
21
- - 登录按钮
22
- - 忘记密码链接
23
- ```
24
-
25
- 使用命令:
26
- ```bash
27
- needware-cli agent ./prompt.txt
28
- ```
29
-
30
- ---
31
-
32
- ## 🔧 使用 SDKUserMessage JSON 格式
33
-
34
- ### 3. 直接使用 JSON 字符串
35
-
36
- ```bash
37
- needware-cli agent '{
38
- "type": "user",
39
- "session_id": "my-session-001",
40
- "message": {
41
- "role": "user",
42
- "content": "创建一个响应式的导航栏组件"
43
- },
44
- "parent_tool_use_id": null
45
- }'
46
- ```
47
-
48
- **注意:**
49
- - `type` 必须是 `"user"`
50
- - `session_id` 是会话标识符(可以自定义)
51
- - `message.role` 必须是 `"user"`
52
- - `parent_tool_use_id` 通常设置为 `null`
53
-
54
- ### 4. 从 JSON 文件读取
55
-
56
- 创建文件 `message.json`:
57
- ```json
58
- {
59
- "type": "user",
60
- "session_id": "my-session-001",
61
- "message": {
62
- "role": "user",
63
- "content": "创建一个简单的计数器组件,包含增加、减少和重置按钮"
64
- },
65
- "parent_tool_use_id": null
66
- }
67
- ```
68
-
69
- 使用命令:
70
- ```bash
71
- needware-cli agent ./message.json
72
- ```
73
-
74
- ### 5. 使用会话 ID 保持上下文
75
-
76
- 多次执行使用相同的 `session_id`,Agent 会记住之前的对话:
77
-
78
- **第一次执行:**
79
- ```bash
80
- needware-cli agent '{
81
- "type": "user",
82
- "session_id": "project-login-page",
83
- "message": {
84
- "role": "user",
85
- "content": "创建一个登录页面"
86
- },
87
- "parent_tool_use_id": null
88
- }'
89
- ```
90
-
91
- **第二次执行(使用相同的 session_id):**
92
- ```bash
93
- needware-cli agent '{
94
- "type": "user",
95
- "session_id": "project-login-page",
96
- "message": {
97
- "role": "user",
98
- "content": "添加表单验证和错误提示"
99
- },
100
- "parent_tool_use_id": null
101
- }'
102
- ```
103
-
104
- ---
105
-
106
- ## 🎯 实际应用场景
107
-
108
- ### 场景 1: 快速原型开发
109
-
110
- ```bash
111
- needware-cli agent "创建一个电商产品卡片组件,显示图片、标题、价格和购买按钮"
112
- ```
113
-
114
- ### 场景 2: 功能迭代(保持上下文)
115
-
116
- 使用 JSON 格式,通过 `session_id` 保持上下文:
117
-
118
- ```bash
119
- # 步骤 1: 创建基础功能
120
- needware-cli agent '{
121
- "type": "user",
122
- "session_id": "dashboard-project",
123
- "message": {"role": "user", "content": "创建一个仪表盘页面框架"},
124
- "parent_tool_use_id": null
125
- }'
126
-
127
- # 步骤 2: 添加图表
128
- needware-cli agent '{
129
- "type": "user",
130
- "session_id": "dashboard-project",
131
- "message": {"role": "user", "content": "在仪表盘中添加数据可视化图表"},
132
- "parent_tool_use_id": null
133
- }'
134
-
135
- # 步骤 3: 添加筛选功能
136
- needware-cli agent '{
137
- "type": "user",
138
- "session_id": "dashboard-project",
139
- "message": {"role": "user", "content": "添加日期范围筛选器"},
140
- "parent_tool_use_id": null
141
- }'
142
- ```
143
-
144
- ### 场景 3: 团队协作(使用文件)
145
-
146
- 创建 `tasks/feature-auth.json`:
147
- ```json
148
- {
149
- "type": "user",
150
- "session_id": "team-auth-feature",
151
- "message": {
152
- "role": "user",
153
- "content": "实现用户认证系统,包括登录、注册、密码重置功能"
154
- },
155
- "parent_tool_use_id": null
156
- }
157
- ```
158
-
159
- 团队成员可以直接使用:
160
- ```bash
161
- needware-cli agent ./tasks/feature-auth.json --working-dir ./my-project
162
- ```
163
-
164
- ---
165
-
166
- ## 💡 最佳实践
167
-
168
- ### 1. 文本字符串适用于:
169
- - ✅ 快速测试
170
- - ✅ 简单的一次性任务
171
- - ✅ 不需要保持上下文的场景
172
-
173
- ### 2. SDKUserMessage JSON 适用于:
174
- - ✅ 需要保持会话上下文
175
- - ✅ 复杂的多步骤任务
176
- - ✅ 团队协作和版本控制
177
- - ✅ 自动化脚本和 CI/CD 集成
178
-
179
- ### 3. 会话管理技巧
180
-
181
- 使用有意义的 `session_id` 命名:
182
- ```bash
183
- # 按功能命名
184
- session_id: "feature-user-auth"
185
- session_id: "feature-payment"
186
-
187
- # 按日期命名
188
- session_id: "dev-2025-01-15"
189
-
190
- # 按开发者命名
191
- session_id: "john-nav-component"
192
- ```
193
-
194
- ---
195
-
196
- ## 🔍 调试技巧
197
-
198
- 查看解析结果(使用你添加的调试日志):
199
- ```bash
200
- needware-cli agent '{
201
- "type": "user",
202
- "session_id": "debug-test",
203
- "message": {"role": "user", "content": "测试消息"},
204
- "parent_tool_use_id": null
205
- }'
206
- ```
207
-
208
- 输出会显示:
209
- ```
210
- parsedPrompt ************* {
211
- prompt: '测试消息',
212
- sessionId: 'debug-test',
213
- isInteractive: false
214
- }
215
- ```
216
-
217
- ---
218
-
219
- ## 📚 更多示例
220
-
221
- 查看 `examples/` 目录:
222
- - `examples/sdk-message-example.json` - 标准 SDKUserMessage 示例
223
- - `examples/prompt.txt` - 文本 prompt 示例
224
-
225
- ---
226
-
227
- ## ⚙️ 完整命令参数
228
-
229
- ```bash
230
- needware-cli agent <prompt> \
231
- --working-dir ./my-project \
232
- --additional-dirs ./shared,./utils \
233
- --api-key sk-xxx \
234
- --base-url https://api.anthropic.com
235
- ```
236
-
237
- 其中 `<prompt>` 可以是:
238
- 1. 文本字符串:`"创建组件"`
239
- 2. 文件路径:`./prompt.txt` 或 `./message.json`
240
- 3. JSON 字符串:`'{"type":"user",...}'`
241
-
@@ -1,10 +0,0 @@
1
- {
2
- "type": "user",
3
- "session_id": "my-session-123",
4
- "message": {
5
- "role": "user",
6
- "content": "创建一个简单的计数器组件,包含增加、减少和重置按钮"
7
- },
8
- "parent_tool_use_id": null
9
- }
10
-