@goodandready/dsh-image-gen 0.10.16 → 0.10.18

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 CHANGED
@@ -31,6 +31,21 @@
31
31
 
32
32
  ---
33
33
 
34
+ ## 🚀 Updates v0.10.18: Speed Acceleration & Quality Hardening (#222)
35
+ * **Parallel Batch & Pack Generation**: Multi-variation requests (`count > 1`, `prompts` array) and `generate_image_pack` multi-ratio workflows now execute concurrently with a concurrency limit (`concurrency: 3`) via `asyncPool`, reducing generation wait times by up to **3x**.
36
+ * **Zero-Delay Initial Polling**: Eliminated artificial initial delay in `pollStatus` and queue runners (Fal.ai, ComfyUI), inspecting generation status immediately on first attempt and shaving 1–1.5s off fast generative workflows.
37
+ * **Sub-Millisecond L1 In-Memory Cache**: Built-in 32-entry in-memory LRU cache atop disk cache L2 provides instantaneous (< 0.1 ms) cache hits without synchronous disk I/O.
38
+ * **Fast-Fail Quota Detection**: Added classification for HTTP 402 (Payment Required) and exhausted account quota/credits in `isFatalClientError`, enabling immediate, clean fallback transitions without fruitless retry loops.
39
+ * **Expanded Test Suite**: Added `test/batch5-speed-quality.test.mjs`, bringing total test coverage to **136 automated unit tests (100% pass)**.
40
+
41
+ ## 🚀 Updates v0.10.17: Modular Tool Lifecycle (#216, #217)
42
+ * **Tool modules extracted from `apply()`**: host lifecycle in `lib/index.js` is now a thin cordis entry (~650 lines). Tool definitions live in `lib/tools/{generation,processing,editing,inspect,frontend}.js` behind `lib/register-tools.js`.
43
+ * **Per-tool labeled `ctx.effect`**: each of the 15 tools registers in its own effect (`dsh-image-gen: tool <name>`) for clean unload/reload disposal.
44
+ * **Project meta**: `AGENTS.md` and `index.md` document architecture, constraints, and the test matrix (internal workflow files — not shipped in the npm package).
45
+ * **Design contract**: `docs/design/DESIGN.md` no longer advertises the removed HistoryGallery UI (#203).
46
+ * **Regression lock**: `test/lifecycle-structure.test.mjs` asserts modular layout, labeled effects, and meta files. Suite: **132 unit tests**.
47
+
48
+
34
49
  ## ⚡ Overview
35
50
 
36
51
  **`@goodandready/dsh-image-gen`** is a premier graphic generation and visual processing suite for DeepSeek Harness. It equips autonomous agents with an extensible set of tools for image generation, transformation, background removal, upscaling, vectorization, multi-reference blending, and quality inspection across 8 generative backends.
package/README.ru.md CHANGED
@@ -24,6 +24,21 @@
24
24
  </div>
25
25
 
26
26
  ---
27
+ ## 🚀 Обновления v0.10.18: Ускорение генерации и отказоустойчивость (#222)
28
+ * **Параллельная генерация вариаций и паков**: Запросы с `count > 1`, пакетные промпты `prompts` и инструмент `generate_image_pack` теперь выполняются параллельно с пулом задач (`concurrency: 3`), сокращая время ожидания пользователя до **3 раз**.
29
+ * **Мгновенный первый опрос очереди (Zero-Delay Initial Poll)**: Устранена искусственная задержка перед первым запросом статуса в `pollStatus` (Fal.ai, ComfyUI), экономя 1–1.5 с на быстрых генерациях.
30
+ * **Субмиллисекундный L1-кэш в памяти**: 32-позиционный оперативный LRU-кэш поверх дискового L2 обеспечивает мгновенную отдачу кэшированных генераций (< 0.1 мс) без синхронного чтения с диска.
31
+ * **Fast-Fail при исчерпании квоты**: Добавлено распознавание HTTP 402 (Payment Required) и ошибок баланса/кредитов в `isFatalClientError` для чистого и мгновенного переключения на запасного провайдера.
32
+ * **Расширение тестов**: Добавлен набор `test/batch5-speed-quality.test.mjs`, общее покрытие выросло до **136 юнит-тестов (100% pass)**.
33
+
34
+ ## 🚀 Обновления v0.10.17: модульный жизненный цикл тулов (#216, #217)
35
+ * **Тулы вынесены из `apply()`**: host `lib/index.js` — тонкая cordis-точка входа. Определения тулов — в `lib/tools/*` через `lib/register-tools.js`.
36
+ * **Свой labeled `ctx.effect` на каждый tool** (`dsh-image-gen: tool <name>`) для корректной выгрузки.
37
+ * **Meta-файлы проекта**: `AGENTS.md` и `index.md` (не попадают в npm-пакет).
38
+ * **DESIGN.md** больше не упоминает удалённую HistoryGallery (#203).
39
+ * **Тесты**: `lifecycle-structure` + полный suite — **132 unit tests**.
40
+
41
+
27
42
 
28
43
  ## ⚡ Обзор возможностей
29
44
 
@@ -7,6 +7,27 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync, statSync, unlinkSyn
7
7
 
8
8
  const DEFAULT_CACHE_MAX_BYTES = 500 * 1024 * 1024 // 500 MB
9
9
 
10
+ // In-Memory L1 LRU cache (up to 32 entries) for sub-millisecond retrieval
11
+ const L1_CACHE = new Map()
12
+ const L1_MAX_ENTRIES = 32
13
+
14
+ function getFromL1(hash) {
15
+ if (!L1_CACHE.has(hash)) return null
16
+ const entry = L1_CACHE.get(hash)
17
+ L1_CACHE.delete(hash)
18
+ L1_CACHE.set(hash, entry) // refresh LRU order
19
+ return entry
20
+ }
21
+
22
+ function setToL1(hash, entry) {
23
+ if (L1_CACHE.has(hash)) L1_CACHE.delete(hash)
24
+ else if (L1_CACHE.size >= L1_MAX_ENTRIES) {
25
+ const oldestKey = L1_CACHE.keys().next().value
26
+ if (oldestKey) L1_CACHE.delete(oldestKey)
27
+ }
28
+ L1_CACHE.set(hash, entry)
29
+ }
30
+
10
31
  function getCacheDir() {
11
32
  const base = process.env.DSH_HOME || join(homedir(), '.dsh')
12
33
  return join(base, 'cache', 'image-gen')
@@ -23,6 +44,9 @@ function getCacheDir() {
23
44
  export function getCachedGeneration(hash, { force = false } = {}) {
24
45
  if (force || !hash) return null
25
46
 
47
+ const l1Hit = getFromL1(hash)
48
+ if (l1Hit) return l1Hit
49
+
26
50
  const dir = getCacheDir()
27
51
  const metaPath = join(dir, `${hash}.json`)
28
52
  const dataPath = join(dir, `${hash}.bin`)
@@ -41,7 +65,7 @@ export function getCachedGeneration(hash, { force = false } = {}) {
41
65
  // Non-fatal touch failure: still return valid cache entry
42
66
  }
43
67
 
44
- return {
68
+ const cachedEntry = {
45
69
  bytes,
46
70
  mediaType: meta.mediaType || 'image/png',
47
71
  width: meta.width,
@@ -49,6 +73,8 @@ export function getCachedGeneration(hash, { force = false } = {}) {
49
73
  seed: meta.seed,
50
74
  meta,
51
75
  }
76
+ setToL1(hash, cachedEntry)
77
+ return cachedEntry
52
78
  } catch {
53
79
  return null
54
80
  }
@@ -79,7 +105,17 @@ export function setCachedGeneration(hash, { bytes, mediaType = 'image/png', widt
79
105
  }
80
106
 
81
107
  writeFileSync(metaPath, JSON.stringify(cacheMeta, null, 2), 'utf8')
82
- writeFileSync(dataPath, Buffer.isBuffer(bytes) ? bytes : Buffer.from(bytes))
108
+ const binBuf = Buffer.isBuffer(bytes) ? bytes : Buffer.from(bytes)
109
+ writeFileSync(dataPath, binBuf)
110
+
111
+ setToL1(hash, {
112
+ bytes: binBuf,
113
+ mediaType,
114
+ width,
115
+ height,
116
+ seed,
117
+ meta: cacheMeta,
118
+ })
83
119
 
84
120
  pruneCacheToLimit(maxBytes)
85
121
  } catch {