skillfree 0.1.4 โ†’ 0.1.5

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": "skillfree",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "๐Ÿฆž ไธ€ไธช API๏ผŒๆปก่ถณๆ‰€ๆœ‰้พ™่™พๆŠ€่ƒฝ้œ€ๆฑ‚",
5
5
  "main": "bin/skillfree.js",
6
6
  "bin": {
@@ -75,8 +75,30 @@ async function pilot(flags) {
75
75
 
76
76
  // โ”€โ”€ IMAGE โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
77
77
  if (type === 'image') {
78
+ const imageModel = model || 'gemini-3.1-flash-image-preview'
79
+
80
+ // qwen-image-edit-plus๏ผšๅ›พ็‰‡็ผ–่พ‘๏ผŒ่ตฐ /v1/images/edits๏ผŒmultipart/form-data
81
+ if (imageModel.startsWith('qwen-image')) {
82
+ if (!flags.file) throw new Error('qwen-image-edit ้œ€่ฆ --file ๆŒ‡ๅฎšๅŽŸๅง‹ๅ›พ็‰‡่ทฏๅพ„')
83
+ const imgBuf = fs.readFileSync(path.resolve(flags.file))
84
+ const form = new FormData()
85
+ form.append('model', imageModel)
86
+ form.append('prompt', prompt)
87
+ form.append('size', flags.size || '1024x1024')
88
+ form.append('image', new Blob([imgBuf], { type: 'image/png' }), path.basename(flags.file))
89
+ const res = await request('/images/edits', { method: 'POST', body: form })
90
+ const data = await res.json()
91
+ if (data.error) throw new Error(data.error.message || JSON.stringify(data.error))
92
+ const url = data.data?.[0]?.url
93
+ if (!url) throw new Error('ๆœช่ฟ”ๅ›žๅ›พๅƒURL: ' + JSON.stringify(data).slice(0, 200))
94
+ if (output) await downloadAndSave(url, output)
95
+ else console.log('ๅ›พๅƒ URL:', url)
96
+ return
97
+ }
98
+
99
+ // doubao-seedream-5.0-lite / ๅ…ถไป–ๆ ‡ๅ‡†ๅ›พๅƒๆจกๅž‹
78
100
  const res = await post('/images/generations', {
79
- model: model || 'gemini-3.1-flash-image-preview',
101
+ model: imageModel,
80
102
  prompt,
81
103
  n: 1,
82
104
  size: flags.size || '1024x1024',
@@ -85,12 +107,8 @@ async function pilot(flags) {
85
107
  const url = res.data?.[0]?.url || res.data?.[0]?.b64_json
86
108
  if (!url) throw new Error('ๆœช่ฟ”ๅ›žๅ›พๅƒๆ•ฐๆฎ: ' + JSON.stringify(res).slice(0, 200))
87
109
  if (output) {
88
- if (url.startsWith('http')) {
89
- await downloadAndSave(url, output)
90
- } else {
91
- fs.writeFileSync(output, Buffer.from(url, 'base64'))
92
- console.log(`โœ… ๅทฒไฟๅญ˜ๅˆฐ ${output}`)
93
- }
110
+ if (url.startsWith('http')) await downloadAndSave(url, output)
111
+ else { fs.writeFileSync(output, Buffer.from(url, 'base64')); console.log(`โœ… ๅทฒไฟๅญ˜ๅˆฐ ${output}`) }
94
112
  } else {
95
113
  console.log('ๅ›พๅƒ URL:', url)
96
114
  }
@@ -216,8 +234,26 @@ async function pilot(flags) {
216
234
  throw new Error('Suno ็”Ÿๆˆ่ถ…ๆ—ถ๏ผˆ150s๏ผ‰๏ผŒ่ฏทๆ‰‹ๅŠจๆŸฅ่ฏข task_id: ' + taskId)
217
235
 
218
236
  } else {
219
- // music-2.5๏ผˆMiniMax๏ผ‰ๆš‚ไธๆ”ฏๆŒ๏ผˆ้œ€่ฆ lyrics ๅ‚ๆ•ฐ๏ผŒๅปบ่ฎฎ็›ดๆŽฅ่ฐƒ /v1/responses๏ผ‰
220
- throw new Error(`music-2.5 ้œ€่ฆ้€š่ฟ‡ /v1/responses ็›ดๆŽฅ่ฐƒ็”จ๏ผŒ่ฏทๅ‚่€ƒๆ–‡ๆกฃ`)
237
+ // music-2.5๏ผˆMiniMax๏ผ‰๏ผŒ่ตฐ /v1/responses๏ผŒ้œ€่ฆ lyrics
238
+ const res = await request('/responses', {
239
+ method: 'POST',
240
+ body: JSON.stringify({
241
+ model: 'music-2.5',
242
+ input: prompt,
243
+ lyrics: flags.lyrics || `[verse]\n${prompt}`,
244
+ audio_setting: { sample_rate: 44100, bitrate: 256000, format: 'mp3' },
245
+ output_format: 'url',
246
+ stream: false,
247
+ }),
248
+ })
249
+ const data = await res.json()
250
+ if (data.error) throw new Error(data.error.message || JSON.stringify(data.error))
251
+ const audioUrl = data.output?.[0]?.content?.[0]?.audio
252
+ if (!audioUrl) throw new Error('ๆœช่ฟ”ๅ›ž้Ÿณ้ข‘: ' + JSON.stringify(data).slice(0, 200))
253
+ const duration = ((data.extra_info?.music_duration || 0) / 1000).toFixed(1)
254
+ console.log(`โœ… music-2.5 ็”ŸๆˆๆˆๅŠŸ๏ผๆ—ถ้•ฟ็บฆ ${duration} ็ง’`)
255
+ console.log('้Ÿณ้ข‘ URL:', audioUrl)
256
+ if (output) await downloadAndSave(audioUrl, output)
221
257
  }
222
258
  }
223
259
 
@@ -265,7 +301,38 @@ async function pilot(flags) {
265
301
  return
266
302
  }
267
303
 
268
- throw new Error(`ไธๆ”ฏๆŒ็š„็ฑปๅž‹: ${type}๏ผŒๅฏ้€‰: chat | image | tts | stt | music | ocr | video`)
304
+ // โ”€โ”€ EMBEDDING โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
305
+ if (type === 'embedding') {
306
+ // doubao-embedding-vision๏ผš่ตฐ /v1/responses๏ผˆๅคšๆจกๆ€๏ผ‰๏ผŒinput ไธบๆ•ฐ็ป„
307
+ // ็ฎ€ๅ•ๆ–‡ๆœฌ embedding ไนŸๅฏ็”จ
308
+ const inputData = flags.file
309
+ ? [{ type: 'image_url', image_url: { url: 'data:image/png;base64,' + fs.readFileSync(path.resolve(flags.file)).toString('base64') } }]
310
+ : [{ type: 'text', text: prompt }]
311
+ const res = await request('/embeddings', {
312
+ method: 'POST',
313
+ body: JSON.stringify({
314
+ model: model || 'doubao-embedding-vision-251215',
315
+ input: inputData,
316
+ encoding_format: 'float',
317
+ dimensions: 1024,
318
+ sparse_embedding: { type: 'disabled' },
319
+ }),
320
+ })
321
+ const data = await res.json()
322
+ if (data.error) throw new Error(data.error.message || JSON.stringify(data.error))
323
+ const embedding = data.data?.[0]?.embedding
324
+ if (!embedding) throw new Error('ๆœช่ฟ”ๅ›žๅ‘้‡: ' + JSON.stringify(data).slice(0, 200))
325
+ console.log(`โœ… Embedding ๆˆๅŠŸ๏ผ็ปดๅบฆ: ${embedding.length}`)
326
+ if (output) {
327
+ fs.writeFileSync(output, JSON.stringify(embedding))
328
+ console.log(`ๅทฒไฟๅญ˜ๅˆฐ ${output}`)
329
+ } else {
330
+ console.log('ๅ‰5็ปด:', embedding.slice(0, 5))
331
+ }
332
+ return
333
+ }
334
+
335
+ throw new Error(`ไธๆ”ฏๆŒ็š„็ฑปๅž‹: ${type}๏ผŒๅฏ้€‰: chat | image | tts | stt | music | ocr | video | embedding`)
269
336
  }
270
337
 
271
338
  module.exports = { pilot }