@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/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
- const qProvider = u.searchParams.get('provider')
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
  }
@@ -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 в†’ Image generation)')
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) — use ComfyUI (IP-Adapter/InstantID) or FAL')
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 = {}
@@ -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.36",
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",