@goodandready/dsh-image-gen 0.10.13 → 0.10.14
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 +8 -0
- package/README.ru.md +8 -0
- package/lib/client.js +1028 -1019
- package/lib/index.js +51 -10
- package/lib/providers.js +1 -1
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -274,6 +274,10 @@ export const Config = z.object({
|
|
|
274
274
|
.number()
|
|
275
275
|
.description('provider=local: CFG scale.')
|
|
276
276
|
.default(7),
|
|
277
|
+
seedreamBaseURL: z
|
|
278
|
+
.string()
|
|
279
|
+
.description('provider=seedream: base URL, e.g. https://api.bytedanceapi.com/v1 or Volcengine Ark.')
|
|
280
|
+
.default('https://api.bytedanceapi.com/v1'),
|
|
277
281
|
seedreamKeyEnv: z
|
|
278
282
|
.string()
|
|
279
283
|
.role('credential-ref')
|
|
@@ -1197,8 +1201,9 @@ export function apply(ctx, config) {
|
|
|
1197
1201
|
},
|
|
1198
1202
|
},
|
|
1199
1203
|
async execute(args, exec) {
|
|
1200
|
-
|
|
1201
|
-
|
|
1204
|
+
try {
|
|
1205
|
+
const source = await resolveSource(ctx, exec, args.image)
|
|
1206
|
+
if (!source || !source.bytes) throw new Error('Source image not found: ' + args.image)
|
|
1202
1207
|
const cfg = live()
|
|
1203
1208
|
const res = await removeBackgroundFal(
|
|
1204
1209
|
{ fetchImpl: fetch, resolveKey: (ref) => resolveApiKey(ctx, ref), cfg },
|
|
@@ -1236,6 +1241,9 @@ export function apply(ctx, config) {
|
|
|
1236
1241
|
format: 'png',
|
|
1237
1242
|
attachment,
|
|
1238
1243
|
})
|
|
1244
|
+
} catch (err) {
|
|
1245
|
+
throw new Error(sanitizeErrorAndLogs(err.message || err))
|
|
1246
|
+
}
|
|
1239
1247
|
},
|
|
1240
1248
|
}),
|
|
1241
1249
|
)
|
|
@@ -1266,8 +1274,9 @@ export function apply(ctx, config) {
|
|
|
1266
1274
|
},
|
|
1267
1275
|
},
|
|
1268
1276
|
async execute(args, exec) {
|
|
1269
|
-
|
|
1270
|
-
|
|
1277
|
+
try {
|
|
1278
|
+
const source = await resolveSource(ctx, exec, args.image)
|
|
1279
|
+
if (!source || !source.bytes) throw new Error('Source image not found: ' + args.image)
|
|
1271
1280
|
const cfg = live()
|
|
1272
1281
|
const res = await upscaleImageFal(
|
|
1273
1282
|
{ fetchImpl: fetch, resolveKey: (ref) => resolveApiKey(ctx, ref), cfg },
|
|
@@ -1305,6 +1314,9 @@ export function apply(ctx, config) {
|
|
|
1305
1314
|
height: res.height || attachment.height,
|
|
1306
1315
|
attachment,
|
|
1307
1316
|
})
|
|
1317
|
+
} catch (err) {
|
|
1318
|
+
throw new Error(sanitizeErrorAndLogs(err.message || err))
|
|
1319
|
+
}
|
|
1308
1320
|
},
|
|
1309
1321
|
}),
|
|
1310
1322
|
)
|
|
@@ -1378,14 +1390,17 @@ export function apply(ctx, config) {
|
|
|
1378
1390
|
},
|
|
1379
1391
|
},
|
|
1380
1392
|
async execute(args, exec) {
|
|
1381
|
-
|
|
1393
|
+
try {
|
|
1394
|
+
const cfg = live()
|
|
1395
|
+
trackAndAssertLoopGuard(exec?.agent?.session?.id || 'default', { limit: cfg.loopGuardLimit })
|
|
1396
|
+
assertBudgetAvailable(0.05, cfg.dailyBudgetUsd)
|
|
1397
|
+
const refs = Array.isArray(args.images) ? args.images : [args.images].filter(Boolean)
|
|
1382
1398
|
const sources = []
|
|
1383
1399
|
for (const r of refs) {
|
|
1384
1400
|
const s = await resolveSource(ctx, exec, r)
|
|
1385
1401
|
if (s && s.bytes) sources.push(s)
|
|
1386
1402
|
}
|
|
1387
1403
|
if (sources.length === 0) throw new Error('No valid images found to blend')
|
|
1388
|
-
const cfg = live()
|
|
1389
1404
|
const res = await blendImagesFal(
|
|
1390
1405
|
{ fetchImpl: fetch, resolveKey: (ref) => resolveApiKey(ctx, ref), cfg },
|
|
1391
1406
|
{ images: sources, weights: args.weights, prompt: args.prompt, signal: exec.signal }
|
|
@@ -1421,6 +1436,9 @@ export function apply(ctx, config) {
|
|
|
1421
1436
|
height: res.height || attachment.height,
|
|
1422
1437
|
attachment,
|
|
1423
1438
|
})
|
|
1439
|
+
} catch (err) {
|
|
1440
|
+
throw new Error(sanitizeErrorAndLogs(err.message || err))
|
|
1441
|
+
}
|
|
1424
1442
|
},
|
|
1425
1443
|
}),
|
|
1426
1444
|
)
|
|
@@ -1542,7 +1560,16 @@ export function apply(ctx, config) {
|
|
|
1542
1560
|
},
|
|
1543
1561
|
},
|
|
1544
1562
|
async execute(args, exec) {
|
|
1545
|
-
|
|
1563
|
+
try {
|
|
1564
|
+
trackAndAssertLoopGuard(exec?.agent?.session?.id || 'default', { limit: cfg.loopGuardLimit })
|
|
1565
|
+
const estimatedCostEdit = calculateGenerationCost({
|
|
1566
|
+
provider: cfg.provider || 'fal',
|
|
1567
|
+
model: cfg.model,
|
|
1568
|
+
size: cfg.defaultSize || 'square_hd',
|
|
1569
|
+
count: 1,
|
|
1570
|
+
})
|
|
1571
|
+
assertBudgetAvailable(estimatedCostEdit, cfg.dailyBudgetUsd)
|
|
1572
|
+
const source = await resolveConversationImage(ctx, exec, args.image)
|
|
1546
1573
|
const mask = args.mask ? await resolveSource(ctx, exec, args.mask) : undefined
|
|
1547
1574
|
const vision = await analyzeImageWithVision(ctx, exec, source)
|
|
1548
1575
|
|
|
@@ -1603,6 +1630,9 @@ export function apply(ctx, config) {
|
|
|
1603
1630
|
result.visionAnalysis = vision.summary
|
|
1604
1631
|
}
|
|
1605
1632
|
return toLosslessJson(result)
|
|
1633
|
+
} catch (err) {
|
|
1634
|
+
throw new Error(sanitizeErrorAndLogs(err.message || err))
|
|
1635
|
+
}
|
|
1606
1636
|
},
|
|
1607
1637
|
}),
|
|
1608
1638
|
)
|
|
@@ -1662,7 +1692,17 @@ export function apply(ctx, config) {
|
|
|
1662
1692
|
},
|
|
1663
1693
|
},
|
|
1664
1694
|
async execute(args, exec) {
|
|
1665
|
-
|
|
1695
|
+
try {
|
|
1696
|
+
trackAndAssertLoopGuard(exec?.agent?.session?.id || 'default', { limit: cfg.loopGuardLimit })
|
|
1697
|
+
const count = normalizeCount(args.count || 1)
|
|
1698
|
+
const estimatedCostVary = calculateGenerationCost({
|
|
1699
|
+
provider: cfg.provider || 'fal',
|
|
1700
|
+
model: cfg.model,
|
|
1701
|
+
size: cfg.defaultSize || 'square_hd',
|
|
1702
|
+
count,
|
|
1703
|
+
})
|
|
1704
|
+
assertBudgetAvailable(estimatedCostVary, cfg.dailyBudgetUsd)
|
|
1705
|
+
const source = await resolveConversationImage(ctx, exec, args.image)
|
|
1666
1706
|
const vision = await analyzeImageWithVision(ctx, exec, source)
|
|
1667
1707
|
|
|
1668
1708
|
const provider = cfg.provider || 'fal'
|
|
@@ -1671,8 +1711,6 @@ export function apply(ctx, config) {
|
|
|
1671
1711
|
resolveKey: (ref) => resolveApiKey(ctx, ref),
|
|
1672
1712
|
cfg,
|
|
1673
1713
|
}
|
|
1674
|
-
|
|
1675
|
-
const count = normalizeCount(args.count || 1)
|
|
1676
1714
|
const variationStrength = Math.max(0.05, Math.min(0.95, args.variation_strength ?? 0.35))
|
|
1677
1715
|
const baseSeed = Math.floor(Math.random() * 100000)
|
|
1678
1716
|
const format = cfg.defaultFormat || 'png'
|
|
@@ -1727,6 +1765,9 @@ export function apply(ctx, config) {
|
|
|
1727
1765
|
...first,
|
|
1728
1766
|
variations: results.map((r) => ({ path: r.path, attachmentId: r.attachment?.attachmentId, seed: r.seed })),
|
|
1729
1767
|
})
|
|
1768
|
+
} catch (err) {
|
|
1769
|
+
throw new Error(sanitizeErrorAndLogs(err.message || err))
|
|
1770
|
+
}
|
|
1730
1771
|
},
|
|
1731
1772
|
}),
|
|
1732
1773
|
)
|
package/lib/providers.js
CHANGED
|
@@ -749,7 +749,7 @@ export function makeProviders(deps, job) {
|
|
|
749
749
|
// Seedream (ByteDance): OpenAI-совместимый API картинок.
|
|
750
750
|
async function seedream(seedArg = seed, promptArg = prompt) {
|
|
751
751
|
const key = await resolveKey(cfg.seedreamKeyEnv)
|
|
752
|
-
const base = 'https://api.bytedanceapi.com/v1'
|
|
752
|
+
const base = (cfg.seedreamBaseURL || 'https://api.bytedanceapi.com/v1').replace(/\/+$/, '')
|
|
753
753
|
const res = await fetchImpl(`${base}/images/generations`, {
|
|
754
754
|
method: 'POST',
|
|
755
755
|
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${key}` },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@goodandready/dsh-image-gen",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.14",
|
|
4
4
|
"description": "Image generation for DeepSeek Harness: a generate_image tool with pluggable providers — the FAL queue, any OpenAI-compatible images API, or a ChatGPT/Grok subscription with no API key at all. The picture is shown inline in the conversation; the model receives either a link (works with any chat model) or the image itself (needs dsh-vision-bridge or a vision-capable model).",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"deepseek-harness",
|