@goodandready/dsh-image-gen 0.11.0 → 0.11.2

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.
@@ -53,14 +53,12 @@ export function estimateSharpnessAndVariance(bytes) {
53
53
  if (!buf || buf.length < 64) {
54
54
  return { score: 0, passed: false, isBlank: true, reason: 'Empty or corrupt image buffer' }
55
55
  }
56
- let sum = 0
57
56
  let diffSum = 0
58
57
  const sampleStep = Math.max(1, Math.floor(buf.length / 4096))
59
58
  let count = 0
60
59
  for (let i = 8; i < buf.length - sampleStep; i += sampleStep) {
61
60
  const v = buf[i]
62
61
  const nextV = buf[i + sampleStep]
63
- sum += v
64
62
  diffSum += Math.abs(v - nextV)
65
63
  count++
66
64
  }
package/lib/providers.js CHANGED
@@ -4,28 +4,18 @@
4
4
 
5
5
  // Utilities and constants extracted to provider-utils.js (#239)
6
6
  import {
7
- resolveApiKeyCandidates,
8
- PROVIDER_MAX_COUNTS,
9
- clampProviderCount,
10
- buildEndpointUrl,
11
- createAbortError,
12
- estimateSharpnessAndVariance,
13
- quantizePalette,
14
- formatA1111Parameters,
15
- computeGenerationHash,
16
- PROVIDER_KEYS,
17
- fallbackOrder,
18
- calculateBackoff,
19
7
  isFatalClientError,
20
8
  formatErrorMessage,
21
- resolveSubscriptionSize,
22
- SUBSCRIPTION_SIZES,
23
- IMAGE_SIZES,
24
- OUTPUT_FORMATS,
25
- SIZE_PIXELS,
26
- normalizeCount,
9
+ formatA1111Parameters,
10
+ quantizePalette,
27
11
  } from './provider-utils.js'
28
12
 
13
+ import {
14
+ falAuthHeader,
15
+ submitJob,
16
+ pollStatus,
17
+ } from './providers/shared-helpers.js'
18
+
29
19
  // Per-backend factories (#218)
30
20
  import { createFalGenerator } from './providers/backends/fal.js'
31
21
  import { createCustomGenerator } from './providers/backends/custom.js'
@@ -49,18 +39,7 @@ export {
49
39
  extractComfyNodeErrors,
50
40
  } from './providers/shared-helpers.js'
51
41
 
52
- import {
53
- falAuthHeader,
54
- normalizeMediaType,
55
- submitJob,
56
- pollStatus,
57
- buildEditForm,
58
- estimateCost,
59
- pxSize,
60
- snapToMultipleOf64,
61
- snapDimensions,
62
- extractComfyNodeErrors,
63
- } from './providers/shared-helpers.js'
42
+
64
43
 
65
44
  // Re-export utilities so existing imports from './providers.js' continue to work
66
45
  export {
@@ -0,0 +1,112 @@
1
+ // lib/settings-route.js
2
+ // REST endpoints for plugin settings (/dsh-image-gen/config, /dsh-image-gen/status) (#295, #300).
3
+ // Provides HTTP read/write fallback when DSH core is accessed over network.
4
+
5
+ import { isTrustedLocalRequest } from './security.js'
6
+ import { publicConfig, plainConfig, Config } from './index.js'
7
+
8
+ export function registerSettingsRoutes(ctx, { live, getSettingsApi, setLiveConfig }) {
9
+ // 1. GET /dsh-image-gen/status
10
+ ctx.effect(() => ctx.webServer.register({
11
+ kind: 'exact',
12
+ path: '/dsh-image-gen/status',
13
+ handler: async (req, res) => {
14
+ if (req.method !== 'GET') {
15
+ res.writeHead(405, { 'Content-Type': 'application/json' })
16
+ res.end(JSON.stringify({ error: 'GET only' }))
17
+ return
18
+ }
19
+ if (!isTrustedLocalRequest(req)) {
20
+ res.writeHead(403, { 'Content-Type': 'application/json' })
21
+ res.end(JSON.stringify({ error: 'forbidden' }))
22
+ return
23
+ }
24
+ const cfg = publicConfig(live())
25
+ res.writeHead(200, { 'Content-Type': 'application/json' })
26
+ res.end(JSON.stringify({
27
+ ok: true,
28
+ provider: cfg.provider,
29
+ model: cfg.model,
30
+ enabled: cfg.enabled,
31
+ config: cfg,
32
+ }))
33
+ },
34
+ }), 'dsh-image-gen: status route')
35
+
36
+ // 2. GET & PUT /dsh-image-gen/config
37
+ ctx.effect(() => ctx.webServer.register({
38
+ kind: 'exact',
39
+ path: '/dsh-image-gen/config',
40
+ handler: async (req, res) => {
41
+ if (req.method === 'GET') {
42
+ if (!isTrustedLocalRequest(req)) {
43
+ res.writeHead(403, { 'Content-Type': 'application/json' })
44
+ res.end(JSON.stringify({ error: 'forbidden' }))
45
+ return
46
+ }
47
+ res.writeHead(200, { 'Content-Type': 'application/json' })
48
+ res.end(JSON.stringify({ ok: true, config: publicConfig(live()) }))
49
+ return
50
+ }
51
+
52
+ if (req.method !== 'PUT') {
53
+ res.writeHead(405, { 'Content-Type': 'application/json' })
54
+ res.end(JSON.stringify({ error: 'GET or PUT only' }))
55
+ return
56
+ }
57
+
58
+ if (!isTrustedLocalRequest(req)) {
59
+ res.writeHead(403, { 'Content-Type': 'application/json' })
60
+ res.end(JSON.stringify({ error: 'forbidden' }))
61
+ return
62
+ }
63
+
64
+ const chunks = []
65
+ req.on('data', (c) => chunks.push(c))
66
+ req.on('end', async () => {
67
+ let payload
68
+ try {
69
+ payload = JSON.parse(Buffer.concat(chunks).toString('utf8') || '{}')
70
+ } catch {
71
+ res.writeHead(400, { 'Content-Type': 'application/json' })
72
+ res.end(JSON.stringify({ ok: false, error: 'invalid JSON' }))
73
+ return
74
+ }
75
+
76
+ const raw = payload && typeof payload.config === 'object' && payload.config !== null ? payload.config : payload
77
+ if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {
78
+ res.writeHead(400, { 'Content-Type': 'application/json' })
79
+ res.end(JSON.stringify({ ok: false, error: 'body must be a JSON object' }))
80
+ return
81
+ }
82
+
83
+ const allowedKeys = new Set(Object.keys(Config.dict || {}))
84
+ for (const k of Object.keys(raw)) {
85
+ if (!allowedKeys.has(k)) {
86
+ res.writeHead(400, { 'Content-Type': 'application/json' })
87
+ res.end(JSON.stringify({ ok: false, error: `unknown config field: ${k}` }))
88
+ return
89
+ }
90
+ }
91
+
92
+ try {
93
+ const base = plainConfig(live()) || {}
94
+ const merged = Config({ ...base, ...raw })
95
+ const settingsApi = getSettingsApi ? getSettingsApi() : null
96
+ if (settingsApi && typeof settingsApi.replace === 'function') {
97
+ await settingsApi.replace(merged)
98
+ } else if (settingsApi && typeof settingsApi.update === 'function') {
99
+ await settingsApi.update(raw)
100
+ } else if (typeof setLiveConfig === 'function') {
101
+ setLiveConfig(merged)
102
+ }
103
+ res.writeHead(200, { 'Content-Type': 'application/json' })
104
+ res.end(JSON.stringify({ ok: true, config: publicConfig(merged) }))
105
+ } catch (err) {
106
+ res.writeHead(400, { 'Content-Type': 'application/json' })
107
+ res.end(JSON.stringify({ ok: false, error: String(err?.message || err) }))
108
+ }
109
+ })
110
+ },
111
+ }), 'dsh-image-gen: config route')
112
+ }
@@ -4,7 +4,6 @@
4
4
  import { defineTool } from '@deepseek-ai/dsh-tools'
5
5
  import {
6
6
  setSessionAnchor,
7
- getSessionAnchor,
8
7
  clearSessionAnchor,
9
8
  normalizeAnchorStrength,
10
9
  } from '../anchor-helpers.js'
@@ -102,7 +101,7 @@ export function registerAnchorTools(ctx, deps) {
102
101
  if (resolveSource && (imageRef.startsWith('sha256:') || !imageRef.startsWith('http'))) {
103
102
  try {
104
103
  await resolveSource(ctx, exec, imageRef)
105
- } catch (err) {
104
+ } catch {
106
105
  // Best effort check; non-blocking if remote URL or future attachment
107
106
  }
108
107
  }
@@ -3,49 +3,17 @@ import { renderToolOutput } from "../attachment-helper.js"
3
3
 
4
4
  import { defineTool } from '@deepseek-ai/dsh-tools'
5
5
  import { polishPrompt } from '../prompt-polisher.js'
6
- import path from 'node:path'
7
- import { mkdir, writeFile } from 'node:fs/promises'
8
6
  import {
9
- computeGenerationHash,
10
- IMAGE_SIZES,
11
- OUTPUT_FORMATS,
12
- PROVIDER_KEYS,
13
- buildSidecar,
14
7
  makeProviders,
15
- ASPECT_RATIOS,
16
- pixelDiff,
17
8
  normalizeCount,
18
- tryGenerate,
19
- fallbackOrder,
20
- embedPngMetadata,
21
- removeBackgroundFal,
22
- upscaleImageFal,
23
- traceToSvg,
24
- estimateCost,
25
- estimateSharpnessAndVariance,
26
- applyStylePreset,
27
- resolveStylePreset,
28
- blendImagesFal,
29
9
  toLosslessJson,
30
- saveAttachmentSafe,
31
10
  editImageDirect,
32
11
  varyImageDirect,
33
12
  } from '../providers.js'
34
- import { resolveConversationImage, analyzeImageWithVision, buildDualOutputMarkdown } from '../resolve-image.js'
35
- import { sanitizeNegativePrompt, supportsNegativePrompt } from '../negative-sanitizer.js'
36
- import { executeWithQualityGate } from '../quality-gate.js'
37
- import { calculateGenerationCost, recordSpend, assertBudgetAvailable } from '../cost-meter.js'
13
+ import { resolveConversationImage, analyzeImageWithVision } from '../resolve-image.js'
14
+ import { calculateGenerationCost, assertBudgetAvailable } from '../cost-meter.js'
38
15
  import { trackAndAssertLoopGuard } from '../loop-guard.js'
39
16
  import { sanitizeErrorAndLogs } from '../security.js'
40
- import { getCachedGeneration, setCachedGeneration } from '../generation-cache.js'
41
- import {
42
- extractDesignTokens,
43
- generateCssGradient,
44
- checkWcagContrast,
45
- optimizeSvgContent,
46
- generatePwaIconSuite,
47
- extractSampleColorsFromBuffer,
48
- } from '../frontend-assets.js'
49
17
 
50
18
 
51
19
  export function registerEditingTools(ctx, deps) {
@@ -2,51 +2,18 @@ import { renderToolOutput } from "../attachment-helper.js"
2
2
  // frontend — image-gen tools (extract_design_tokens, image_to_css_gradient, check_image_contrast, optimize_vector_svg, generate_pwa_icon_suite). Extracted from apply() (#216).
3
3
 
4
4
  import { defineTool } from '@deepseek-ai/dsh-tools'
5
- import path from 'node:path'
6
- import { mkdir, writeFile } from 'node:fs/promises'
7
- import {
8
- computeGenerationHash,
9
- IMAGE_SIZES,
10
- tryGenerate,
11
- fallbackOrder,
12
- embedPngMetadata,
13
- removeBackgroundFal,
14
- upscaleImageFal,
15
- traceToSvg,
16
- estimateCost,
17
- estimateSharpnessAndVariance,
18
- applyStylePreset,
19
- resolveStylePreset,
20
- blendImagesFal,
21
- toLosslessJson,
22
- saveAttachmentSafe,
23
- } from '../providers.js'
24
- import { resolveConversationImage, analyzeImageWithVision, buildDualOutputMarkdown } from '../resolve-image.js'
25
- import { sanitizeNegativePrompt, supportsNegativePrompt } from '../negative-sanitizer.js'
26
- import { executeWithQualityGate } from '../quality-gate.js'
27
- import { calculateGenerationCost, recordSpend, assertBudgetAvailable } from '../cost-meter.js'
28
- import { trackAndAssertLoopGuard } from '../loop-guard.js'
5
+ import { toLosslessJson } from '../providers.js'
29
6
  import { sanitizeErrorAndLogs } from '../security.js'
30
- import { getCachedGeneration, setCachedGeneration } from '../generation-cache.js'
31
7
  import {
32
8
  extractDesignTokens,
33
9
  generateCssGradient,
34
10
  checkWcagContrast,
35
11
  optimizeSvgContent,
36
12
  generatePwaIconSuite,
37
- extractSampleColorsFromBuffer,
38
13
  } from '../frontend-assets.js'
39
14
 
40
-
41
15
  export function registerFrontendTools(ctx, deps) {
42
- const {
43
- config,
44
- live,
45
- saveAndAttachResult,
46
- resolveSource,
47
- slugify,
48
- resolveApiKey,
49
- } = deps
16
+ const { resolveSource } = deps
50
17
  ctx.effect(() => {
51
18
  ctx.tools.register(
52
19
  defineTool({
@@ -4,8 +4,7 @@ import { toLosslessJson } from '../providers.js'
4
4
  import { slugify } from '../index.js'
5
5
 
6
6
  export function registerGenerationPackTool(ctx, deps) {
7
- const { live } = deps
8
-
7
+
9
8
  ctx.effect(() => {
10
9
  ctx.tools.register(
11
10
  defineTool({
@@ -30,8 +29,7 @@ export function registerGenerationPackTool(ctx, deps) {
30
29
  },
31
30
  async execute(args, exec) {
32
31
  const ratios = Array.isArray(args.aspect_ratios) && args.aspect_ratios.length ? args.aspect_ratios : ['1:1', '16:9', '9:16']
33
- const cfg = live()
34
- const generateTool = ctx.tools.get('generate_image')
32
+ const generateTool = ctx.tools.get('generate_image')
35
33
  const results = []
36
34
  const warnings = []
37
35
  const seedBase = Math.floor(Math.random() * 100000)
@@ -1,4 +1,3 @@
1
- import { polishPrompt } from '../prompt-polisher.js'
2
1
  import { registerGenerationPackTool } from './generation-pack.js'
3
2
 
4
3
  /** Run an array of async task functions with a concurrency cap */
@@ -29,46 +28,26 @@ import {
29
28
  buildSidecar,
30
29
  makeProviders,
31
30
  ASPECT_RATIOS,
32
- pixelDiff,
33
31
  normalizeCount,
34
- tryGenerate,
35
- fallbackOrder,
36
32
  embedPngMetadata,
37
- removeBackgroundFal,
38
- upscaleImageFal,
39
- traceToSvg,
40
- estimateCost,
41
- estimateSharpnessAndVariance,
42
- applyStylePreset,
43
33
  resolveStylePreset,
44
- blendImagesFal,
45
34
  toLosslessJson,
46
35
  saveAttachmentSafe,
47
36
  } from '../providers.js'
48
- import { resolveConversationImage, analyzeImageWithVision, buildDualOutputMarkdown } from '../resolve-image.js'
37
+ import { buildDualOutputMarkdown } from '../resolve-image.js'
49
38
  import { sanitizeNegativePrompt, supportsNegativePrompt } from '../negative-sanitizer.js'
50
39
  import { executeWithQualityGate } from '../quality-gate.js'
51
40
  import { calculateGenerationCost, recordSpend, assertBudgetAvailable } from '../cost-meter.js'
52
41
  import { trackAndAssertLoopGuard } from '../loop-guard.js'
53
- import { sanitizeErrorAndLogs } from '../security.js'
54
42
  import { getCachedGeneration, setCachedGeneration } from '../generation-cache.js'
55
43
  import { resolveFallbackChain, executeWithFallback } from '../fallback-router.js'
56
44
  import { getSessionAnchor, applyAnchorPromptHints } from '../anchor-helpers.js'
57
- import {
58
- extractDesignTokens,
59
- generateCssGradient,
60
- checkWcagContrast,
61
- optimizeSvgContent,
62
- generatePwaIconSuite,
63
- extractSampleColorsFromBuffer,
64
- } from '../frontend-assets.js'
65
45
 
66
46
 
67
47
  export function registerGenerationTools(ctx, deps) {
68
48
  const {
69
49
  config,
70
50
  live,
71
- saveAndAttachResult,
72
51
  resolveSource,
73
52
  slugify,
74
53
  resolveApiKey,
@@ -91,7 +70,7 @@ export function registerGenerationTools(ctx, deps) {
91
70
  },
92
71
  image_size: {
93
72
  type: 'string',
94
- description: `One of: ${IMAGE_SIZES.join(', ')}. Default: ${config.defaultSize}.`,
73
+ description: `One of: ${IMAGE_SIZES.join(', ')}. Default: ${config?.defaultSize || 'square_hd'}.`,
95
74
  },
96
75
  aspect_ratio: {
97
76
  type: 'string',
@@ -105,7 +84,7 @@ export function registerGenerationTools(ctx, deps) {
105
84
  output_format: {
106
85
  type: 'string',
107
86
  enum: OUTPUT_FORMATS,
108
- description: `Output format. Default: ${config.defaultFormat}.`,
87
+ description: `Output format. Default: ${config?.defaultFormat || 'png'}.`,
109
88
  },
110
89
  output_name: {
111
90
  type: 'string',
@@ -240,7 +219,7 @@ export function registerGenerationTools(ctx, deps) {
240
219
  },
241
220
  },
242
221
  isConcurrencySafe: () => false,
243
- timeoutMs: config.timeoutMs + 30000,
222
+ timeoutMs: (config?.timeoutMs || 180000) + 30000,
244
223
  async execute(args, exec) {
245
224
  const cfg = live()
246
225
 
@@ -269,7 +248,7 @@ export function registerGenerationTools(ctx, deps) {
269
248
  // Subscriptions service is optional: without it, subscription providers
270
249
  // gracefully decline while other providers continue functioning.
271
250
  let subscriptionImages
272
- try { subscriptionImages = ctx.get && ctx.get('subscriptionImages') } catch (noService) { subscriptionImages = undefined }
251
+ try { subscriptionImages = ctx.get && ctx.get('subscriptionImages') } catch { subscriptionImages = undefined }
273
252
 
274
253
  const source = args.source_image ? await resolveSource(ctx, exec, args.source_image) : undefined
275
254
  const mask = args.mask ? await resolveSource(ctx, exec, args.mask) : undefined
@@ -2,52 +2,13 @@ import { renderToolOutput } from "../attachment-helper.js"
2
2
  // inspect — image-gen tools (compare_images, inspect_image_quality). Extracted from apply() (#216).
3
3
 
4
4
  import { defineTool } from '@deepseek-ai/dsh-tools'
5
- import path from 'node:path'
6
- import { mkdir, writeFile } from 'node:fs/promises'
7
5
  import {
8
- computeGenerationHash,
9
- IMAGE_SIZES,
10
6
  pixelDiff,
11
- tryGenerate,
12
- fallbackOrder,
13
- embedPngMetadata,
14
- removeBackgroundFal,
15
- upscaleImageFal,
16
- traceToSvg,
17
- estimateCost,
18
7
  estimateSharpnessAndVariance,
19
- applyStylePreset,
20
- resolveStylePreset,
21
- blendImagesFal,
22
- toLosslessJson,
23
- saveAttachmentSafe,
24
8
  } from '../providers.js'
25
- import { resolveConversationImage, analyzeImageWithVision, buildDualOutputMarkdown } from '../resolve-image.js'
26
- import { sanitizeNegativePrompt, supportsNegativePrompt } from '../negative-sanitizer.js'
27
- import { executeWithQualityGate } from '../quality-gate.js'
28
- import { calculateGenerationCost, recordSpend, assertBudgetAvailable } from '../cost-meter.js'
29
- import { trackAndAssertLoopGuard } from '../loop-guard.js'
30
- import { sanitizeErrorAndLogs } from '../security.js'
31
- import { getCachedGeneration, setCachedGeneration } from '../generation-cache.js'
32
- import {
33
- extractDesignTokens,
34
- generateCssGradient,
35
- checkWcagContrast,
36
- optimizeSvgContent,
37
- generatePwaIconSuite,
38
- extractSampleColorsFromBuffer,
39
- } from '../frontend-assets.js'
40
-
41
9
 
42
10
  export function registerInspectTools(ctx, deps) {
43
- const {
44
- config,
45
- live,
46
- saveAndAttachResult,
47
- resolveSource,
48
- slugify,
49
- resolveApiKey,
50
- } = deps
11
+ const { resolveSource } = deps
51
12
  ctx.effect(() => {
52
13
  ctx.tools.register(
53
14
  defineTool({
@@ -58,8 +19,8 @@ export function registerInspectTools(ctx, deps) {
58
19
  image_b: { type: 'string', required: true, description: 'Path or attachment id of the second image.' },
59
20
  },
60
21
  output: {
61
- render: (_args, value) => renderToolOutput(value),
62
- schema: {
22
+ render: (_args, value) => renderToolOutput(value),
23
+ schema: {
63
24
  type: 'object',
64
25
  additionalProperties: false,
65
26
  properties: {
@@ -86,8 +47,8 @@ export function registerInspectTools(ctx, deps) {
86
47
  expected_elements: { type: 'string', description: 'What elements should be present and verified.' },
87
48
  },
88
49
  output: {
89
- render: (_args, value) => renderToolOutput(value),
90
- schema: {
50
+ render: (_args, value) => renderToolOutput(value),
51
+ schema: {
91
52
  type: 'object',
92
53
  additionalProperties: false,
93
54
  properties: {
@@ -109,6 +70,6 @@ export function registerInspectTools(ctx, deps) {
109
70
  }
110
71
  },
111
72
  }),
112
- )
73
+ )
113
74
  }, 'dsh-image-gen: tool inspect_image_quality')
114
75
  }
@@ -11,6 +11,8 @@ import {
11
11
  buildSeamlessPrompt,
12
12
  buildPatternCss,
13
13
  normalizeDensity,
14
+ scoreEdgeWrap,
15
+ tilePixels,
14
16
  } from '../pattern-helpers.js'
15
17
 
16
18
  export function registerPatternTools(ctx, deps) {
@@ -97,6 +99,14 @@ export function registerPatternTools(ctx, deps) {
97
99
  const filePath = path.join(outDir, name)
98
100
  await writeFile(filePath, gen.bytes)
99
101
 
102
+ if (gen.bytes && gen.width && gen.height) {
103
+ const seamScore = scoreEdgeWrap(new Uint8Array(gen.bytes), gen.width, gen.height)
104
+ const tiled = tilePixels(new Uint8Array(gen.bytes), gen.width, gen.height, 4, 2, 2)
105
+ if (exec?.logger?.debug) {
106
+ exec.logger.debug(`[dsh-image-gen] Pattern seam score: ${seamScore}, 2x2 width: ${tiled.width}`)
107
+ }
108
+ }
109
+
100
110
  const [tilePx] = sizeToPixels(size)
101
111
  const css = buildPatternCss({ className: stem, sizePx: tilePx, imagePath: `./${name}` })
102
112
  const cssPath = path.join(outDir, `${stem}.css`)
@@ -7,48 +7,16 @@ import { defineTool } from '@deepseek-ai/dsh-tools'
7
7
  import path from 'node:path'
8
8
  import { mkdir, writeFile } from 'node:fs/promises'
9
9
  import {
10
- computeGenerationHash,
11
- IMAGE_SIZES,
12
- tryGenerate,
13
- fallbackOrder,
14
- embedPngMetadata,
15
- removeBackgroundFal,
16
- upscaleImageFal,
17
- traceToSvg,
18
- estimateCost,
19
- estimateSharpnessAndVariance,
20
- applyStylePreset,
21
- resolveStylePreset,
22
- blendImagesFal,
23
10
  toLosslessJson,
24
11
  saveAttachmentSafe,
25
12
  } from '../providers.js'
26
- import { resolveConversationImage, analyzeImageWithVision, buildDualOutputMarkdown } from '../resolve-image.js'
27
- import { sanitizeNegativePrompt, supportsNegativePrompt } from '../negative-sanitizer.js'
28
- import { executeWithQualityGate } from '../quality-gate.js'
29
- import { calculateGenerationCost, recordSpend, assertBudgetAvailable } from '../cost-meter.js'
30
- import { trackAndAssertLoopGuard } from '../loop-guard.js'
31
13
  import { sanitizeErrorAndLogs } from '../security.js'
32
- import { getCachedGeneration, setCachedGeneration } from '../generation-cache.js'
33
- import {
34
- extractDesignTokens,
35
- generateCssGradient,
36
- checkWcagContrast,
37
- optimizeSvgContent,
38
- generatePwaIconSuite,
39
- extractSampleColorsFromBuffer,
40
- } from '../frontend-assets.js'
41
-
42
-
43
14
 
44
15
  export function registerProcessingAdvancedTools(ctx, deps) {
45
16
  const {
46
- config,
47
17
  live,
48
- saveAndAttachResult,
49
18
  resolveSource,
50
19
  slugify,
51
- resolveApiKey,
52
20
  } = deps
53
21
 
54
22
  ctx.effect(() => {
@@ -7,44 +7,21 @@ import { defineTool } from '@deepseek-ai/dsh-tools'
7
7
  import path from 'node:path'
8
8
  import { mkdir, writeFile } from 'node:fs/promises'
9
9
  import {
10
- computeGenerationHash,
11
- IMAGE_SIZES,
12
- tryGenerate,
13
- fallbackOrder,
14
- embedPngMetadata,
15
10
  removeBackgroundFal,
16
11
  upscaleImageFal,
17
12
  traceToSvg,
18
- estimateCost,
19
- estimateSharpnessAndVariance,
20
- applyStylePreset,
21
- resolveStylePreset,
22
13
  blendImagesFal,
23
14
  toLosslessJson,
24
15
  saveAttachmentSafe,
25
16
  } from '../providers.js'
26
- import { resolveConversationImage, analyzeImageWithVision, buildDualOutputMarkdown } from '../resolve-image.js'
27
- import { sanitizeNegativePrompt, supportsNegativePrompt } from '../negative-sanitizer.js'
28
- import { executeWithQualityGate } from '../quality-gate.js'
29
- import { calculateGenerationCost, recordSpend, assertBudgetAvailable } from '../cost-meter.js'
17
+ import { buildDualOutputMarkdown } from '../resolve-image.js'
18
+ import { assertBudgetAvailable } from '../cost-meter.js'
30
19
  import { trackAndAssertLoopGuard } from '../loop-guard.js'
31
20
  import { sanitizeErrorAndLogs } from '../security.js'
32
- import { getCachedGeneration, setCachedGeneration } from '../generation-cache.js'
33
- import {
34
- extractDesignTokens,
35
- generateCssGradient,
36
- checkWcagContrast,
37
- optimizeSvgContent,
38
- generatePwaIconSuite,
39
- extractSampleColorsFromBuffer,
40
- } from '../frontend-assets.js'
41
-
42
21
 
43
22
  export function registerProcessingTools(ctx, deps) {
44
23
  const {
45
- config,
46
24
  live,
47
- saveAndAttachResult,
48
25
  resolveSource,
49
26
  slugify,
50
27
  resolveApiKey,
@@ -14,7 +14,6 @@ import {
14
14
  } from '../providers.js'
15
15
  import { resolveFallbackChain, executeWithFallback } from '../fallback-router.js'
16
16
  import {
17
- DEFAULT_MATRIX_STYLES,
18
17
  normalizeMatrixStyles,
19
18
  buildMatrixCellPrompt,
20
19
  formatMatrixMarkdown,
@@ -127,7 +126,7 @@ export function registerStyleMatrixTools(ctx, deps) {
127
126
 
128
127
  const provider = PROVIDER_KEYS.includes(cfg.provider) ? cfg.provider : 'fal'
129
128
  let subscriptionImages
130
- try { subscriptionImages = ctx.get && ctx.get('subscriptionImages') } catch (_) { subscriptionImages = undefined }
129
+ try { subscriptionImages = ctx.get && ctx.get('subscriptionImages') } catch { subscriptionImages = undefined }
131
130
 
132
131
  const chain = resolveFallbackChain(provider, cfg.fallbackProviders, PROVIDER_KEYS)
133
132
  const quadrantIds = ['A', 'B', 'C', 'D']
@@ -6,7 +6,6 @@ import path from 'node:path'
6
6
  import { mkdir, writeFile } from 'node:fs/promises'
7
7
  import {
8
8
  ASPECT_RATIOS,
9
- PROVIDER_KEYS,
10
9
  buildSidecar,
11
10
  makeProviders,
12
11
  toLosslessJson,
@@ -123,7 +123,7 @@ export function registerUiAssetTools(ctx, deps) {
123
123
 
124
124
  const provider = PROVIDER_KEYS.includes(cfg.provider) ? cfg.provider : 'fal'
125
125
  let subscriptionImages
126
- try { subscriptionImages = ctx.get && ctx.get('subscriptionImages') } catch (_) { subscriptionImages = undefined }
126
+ try { subscriptionImages = ctx.get && ctx.get('subscriptionImages') } catch { subscriptionImages = undefined }
127
127
 
128
128
  const providers = makeProviders(
129
129
  { fetchImpl: fetch, resolveKey: (ref) => resolveApiKey(ctx, ref), cfg, subscriptionImages },
package/lib/updater.js CHANGED
@@ -3,7 +3,6 @@ import { existsSync, readFileSync } from 'node:fs'
3
3
  import { readFile } from 'node:fs/promises'
4
4
  import { homedir } from 'node:os'
5
5
  import { basename, dirname, isAbsolute, resolve } from 'node:path'
6
- import { fileURLToPath } from 'node:url'
7
6
  import { isLoopbackAddress, isPrivateLanAddress, extractHostName } from './security.js'
8
7
 
9
8
  /**
@@ -21,14 +20,6 @@ function header(request, name) {
21
20
  return Array.isArray(value) ? value[0] : value
22
21
  }
23
22
 
24
- function isLoopback(value) {
25
- return isLoopbackAddress(value)
26
- }
27
-
28
- function isPrivateLan(value) {
29
- return isPrivateLanAddress(value)
30
- }
31
-
32
23
  export function isTrustedUpdateRequest(request) {
33
24
  if (header(request, UPDATE_HEADER) !== '1') return false
34
25
  const remote = request.socket?.remoteAddress