@goodandready/dsh-image-gen 0.11.36 → 0.11.38
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/lib/client.js +570 -495
- package/lib/index.js +20 -5
- package/lib/live-progress.js +9 -0
- package/lib/providers/backends/custom.js +2 -2
- package/lib/tools/frontend.js +1 -0
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -43,10 +43,11 @@ import { resolveConversationImage, analyzeImageWithVision, validateImageSignatur
|
|
|
43
43
|
import { registerImageCommand } from './commands.js'
|
|
44
44
|
import { registerAllTools } from './register-tools.js'
|
|
45
45
|
import { registerPluginUpdater } from './updater.js'
|
|
46
|
-
import { registerVaultRoutes } from './vault.js'
|
|
46
|
+
import { registerVaultRoutes, readBoundedRequestBody } from './vault.js'
|
|
47
47
|
import { registerLiveProgressRoutes } from './live-progress.js'
|
|
48
48
|
import { registerSettingsRoutes } from './settings-route.js'
|
|
49
49
|
import { clearAllAnchors } from './anchor-helpers.js'
|
|
50
|
+
import { clearSpendReservations } from './cost-meter.js'
|
|
50
51
|
import { resetLoopGuard, getLoopGuardState } from './loop-guard.js'
|
|
51
52
|
import { Config, plainConfig, volatileConfig, publicConfig, ensureConfig } from './config-schema.js'
|
|
52
53
|
import { resolveSource } from './resolve-source.js'
|
|
@@ -349,14 +350,14 @@ export function apply(ctx, rawConfig) {
|
|
|
349
350
|
manifestUrl: new URL('../package.json', import.meta.url),
|
|
350
351
|
}), 'dsh-image-gen: plugin updater route')
|
|
351
352
|
|
|
352
|
-
// Provider connection diagnostics probe
|
|
353
|
+
// Provider connection diagnostics probe (#419)
|
|
353
354
|
ctx.effect(() => ctx.webServer.register({
|
|
354
355
|
kind: 'exact',
|
|
355
356
|
path: '/dsh-image-gen/diagnostics/test',
|
|
356
357
|
handler: async (req, res) => {
|
|
357
|
-
if (req.method !== 'GET') {
|
|
358
|
+
if (req.method !== 'GET' && req.method !== 'POST') {
|
|
358
359
|
res.writeHead(405, { 'Content-Type': 'application/json' })
|
|
359
|
-
res.end(JSON.stringify({ error: 'GET only' }))
|
|
360
|
+
res.end(JSON.stringify({ error: 'GET or POST only' }))
|
|
360
361
|
return
|
|
361
362
|
}
|
|
362
363
|
if (!isTrustedLocalRequest(req)) {
|
|
@@ -366,7 +367,20 @@ export function apply(ctx, rawConfig) {
|
|
|
366
367
|
}
|
|
367
368
|
try {
|
|
368
369
|
const u = new URL(req.url, 'http://localhost')
|
|
369
|
-
|
|
370
|
+
let qProvider = u.searchParams.get('provider')
|
|
371
|
+
if (!qProvider && req.method === 'POST') {
|
|
372
|
+
try {
|
|
373
|
+
const buf = await readBoundedRequestBody(req, 16 * 1024)
|
|
374
|
+
if (buf && buf.length > 0) {
|
|
375
|
+
const body = JSON.parse(buf.toString('utf8'))
|
|
376
|
+
if (body && typeof body.provider === 'string') {
|
|
377
|
+
qProvider = body.provider
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
} catch (_err) {
|
|
381
|
+
/* ignore JSON body parse errors, fallback to URL query or live config */
|
|
382
|
+
}
|
|
383
|
+
}
|
|
370
384
|
const effectiveCfg = live()
|
|
371
385
|
const provider = (typeof qProvider === 'string' && qProvider.trim())
|
|
372
386
|
|| (typeof effectiveCfg?.provider === 'string' && effectiveCfg.provider.trim())
|
|
@@ -461,5 +475,6 @@ export function apply(ctx, rawConfig) {
|
|
|
461
475
|
|
|
462
476
|
ctx.effect(() => () => {
|
|
463
477
|
toolController?.dispose?.()
|
|
478
|
+
clearSpendReservations()
|
|
464
479
|
}, 'dsh-image-gen: tool registration cleanup')
|
|
465
480
|
}
|
package/lib/live-progress.js
CHANGED
|
@@ -255,6 +255,15 @@ export function registerLiveProgressRoutes(ctx) {
|
|
|
255
255
|
|
|
256
256
|
res.write(': connected\n\n')
|
|
257
257
|
|
|
258
|
+
const current = getLiveProgress(callId)
|
|
259
|
+
if (current) {
|
|
260
|
+
try {
|
|
261
|
+
res.write(`data: ${JSON.stringify(current)}\n\n`)
|
|
262
|
+
} catch (_err) {
|
|
263
|
+
// Ignore stream write failure on initial snapshot replay (#429)
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
258
267
|
const unsubscribe = subscribeLiveProgress(callId, (data) => {
|
|
259
268
|
try {
|
|
260
269
|
res.write(`data: ${JSON.stringify(data)}\n\n`)
|
|
@@ -23,13 +23,13 @@ export function createCustomGenerator(deps, job) {
|
|
|
23
23
|
throw new Error('Custom provider (OpenAI-compatible) does not support facial identity references (FaceID) — use ComfyUI (IP-Adapter/InstantID) or FAL')
|
|
24
24
|
}
|
|
25
25
|
const base = String(cfg.customBaseURL || '').replace(/\/+$/, '')
|
|
26
|
-
if (!base) throw new Error('Custom image provider: base URL is not configured (Settings
|
|
26
|
+
if (!base) throw new Error('Custom image provider: base URL is not configured (Settings -> Image generation)')
|
|
27
27
|
if (!cfg.customModel) throw new Error('Custom image provider: model is not configured')
|
|
28
28
|
|
|
29
29
|
// Empty key reference indicates unauthenticated gateway.
|
|
30
30
|
const key = cfg.customKeyEnv ? await resolveKey(cfg.customKeyEnv) : ''
|
|
31
31
|
if (job.faceReference && !source) {
|
|
32
|
-
throw new Error('Custom provider (OpenAI-compatible) does not support facial identity references (FaceID)
|
|
32
|
+
throw new Error('Custom provider (OpenAI-compatible) does not support facial identity references (FaceID) — use ComfyUI (IP-Adapter/InstantID) or FAL')
|
|
33
33
|
}
|
|
34
34
|
const isEdit = Boolean(source && source.bytes)
|
|
35
35
|
const headers = {}
|
package/lib/tools/frontend.js
CHANGED
|
@@ -192,6 +192,7 @@ export function registerFrontendTools(ctx, deps) {
|
|
|
192
192
|
theme_color: { type: 'string', description: 'Theme color hex (e.g. #0f172a).' },
|
|
193
193
|
background_color: { type: 'string', description: 'Background color hex (e.g. #ffffff).' },
|
|
194
194
|
icons_dir: { type: 'string', description: 'Directory for icons relative to webroot (default: icons).' },
|
|
195
|
+
out_dir: { type: 'string', description: 'Output root directory to write manifest.json and icons into (defaults to current directory).' },
|
|
195
196
|
},
|
|
196
197
|
output: {
|
|
197
198
|
render: (_args, value) => renderToolOutput(value),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@goodandready/dsh-image-gen",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.38",
|
|
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",
|