@dickpy/dsh-imagegen 1.3.0 → 1.4.0
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/LICENSE +201 -201
- package/README.md +203 -182
- package/cordis.patch.yml +8 -8
- package/docs/images/multi-model-comparison.png +0 -0
- package/lib/client.js +1103 -837
- package/lib/client.js.map +1 -1
- package/lib/index.js +265 -135
- package/package.json +70 -68
- package/src/agent-image-tools.ts +418 -418
- package/src/client/ImageGenPanel.tsx +1699 -1508
- package/src/client/SettingsCard.tsx +936 -957
- package/src/client/TemplateLibrary.tsx +336 -336
- package/src/client/api.ts +193 -193
- package/src/client/channels-form.ts +263 -263
- package/src/client/controller.ts +46 -46
- package/src/client/conversation-sync.ts +14 -0
- package/src/client/css-modules.d.ts +5 -5
- package/src/client/helpers.ts +33 -33
- package/src/client/image-toolview.module.css +73 -73
- package/src/client/image-toolview.tsx +169 -158
- package/src/client/index.ts +32 -22
- package/src/client/locales.ts +610 -594
- package/src/client/mount.tsx +185 -96
- package/src/client/panel.module.css +1713 -1445
- package/src/client/settings-card.module.css +1023 -1023
- package/src/client/settings-form.ts +336 -336
- package/src/client/settings-scope.ts +298 -298
- package/src/client/sidebar-entry.ts +148 -102
- package/src/client/templates.module.css +453 -453
- package/src/engine.ts +520 -478
- package/src/gallery-store.ts +286 -286
- package/src/generation-runtime.ts +79 -75
- package/src/history-store.ts +250 -244
- package/src/image-format.ts +11 -11
- package/src/image-models.ts +19 -19
- package/src/index.ts +318 -318
- package/src/model-catalog.ts +115 -98
- package/src/presets.ts +71 -63
- package/src/prompt-enhancer.ts +137 -79
- package/src/protocol.ts +338 -326
- package/src/routes.ts +916 -906
- package/src/task-queue.ts +113 -103
- package/src/templates/cases.json +10196 -10196
- package/src/templates-store.ts +278 -278
- package/src/updater.ts +117 -117
package/src/task-queue.ts
CHANGED
|
@@ -1,103 +1,113 @@
|
|
|
1
|
-
/** In-memory, host-resident image generation queue. */
|
|
2
|
-
|
|
3
|
-
import { randomUUID } from 'node:crypto'
|
|
4
|
-
import type { GenerateRequest, GenerateResult, GenerationTask } from './protocol.ts'
|
|
5
|
-
|
|
6
|
-
export type GenerationTaskListener = (task: GenerationTask) => void
|
|
7
|
-
|
|
8
|
-
export class GenerationTaskQueue {
|
|
9
|
-
private readonly tasks: GenerationTask[] = []
|
|
10
|
-
private readonly controllers = new Map<string, AbortController>()
|
|
11
|
-
private readonly listeners = new Set<GenerationTaskListener>()
|
|
12
|
-
private running =
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
this.
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
return
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
this.
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
}
|
|
1
|
+
/** In-memory, host-resident image generation queue. */
|
|
2
|
+
|
|
3
|
+
import { randomUUID } from 'node:crypto'
|
|
4
|
+
import type { GenerateRequest, GenerateResult, GenerationTask } from './protocol.ts'
|
|
5
|
+
|
|
6
|
+
export type GenerationTaskListener = (task: GenerationTask) => void
|
|
7
|
+
|
|
8
|
+
export class GenerationTaskQueue {
|
|
9
|
+
private readonly tasks: GenerationTask[] = []
|
|
10
|
+
private readonly controllers = new Map<string, AbortController>()
|
|
11
|
+
private readonly listeners = new Set<GenerationTaskListener>()
|
|
12
|
+
private running = 0
|
|
13
|
+
private serialRunning = false
|
|
14
|
+
|
|
15
|
+
constructor(
|
|
16
|
+
private readonly run: (request: GenerateRequest, signal: AbortSignal) => Promise<GenerateResult>,
|
|
17
|
+
private readonly concurrency = 1,
|
|
18
|
+
) {}
|
|
19
|
+
|
|
20
|
+
list(): GenerationTask[] {
|
|
21
|
+
return this.tasks.map(task => this.snapshot(task))
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** Observe queue state changes. Listener failures never disrupt generation. */
|
|
25
|
+
subscribe(listener: GenerationTaskListener): () => void {
|
|
26
|
+
this.listeners.add(listener)
|
|
27
|
+
return () => { this.listeners.delete(listener) }
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
submit(request: GenerateRequest): GenerationTask {
|
|
31
|
+
const task: GenerationTask = { id: randomUUID(), request: { ...request }, status: 'queued', createdAt: Date.now() }
|
|
32
|
+
this.tasks.unshift(task)
|
|
33
|
+
this.publish(task)
|
|
34
|
+
this.drain()
|
|
35
|
+
return this.snapshot(task)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
cancel(id: string): GenerationTask | undefined {
|
|
39
|
+
const task = this.tasks.find(item => item.id === id)
|
|
40
|
+
if (task === undefined || task.status === 'completed' || task.status === 'failed' || task.status === 'cancelled') return task
|
|
41
|
+
task.status = 'cancelled'
|
|
42
|
+
task.finishedAt = Date.now()
|
|
43
|
+
this.controllers.get(id)?.abort()
|
|
44
|
+
this.publish(task)
|
|
45
|
+
this.drain()
|
|
46
|
+
return this.snapshot(task)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
retry(id: string): GenerationTask | undefined {
|
|
50
|
+
const previous = this.tasks.find(item => item.id === id)
|
|
51
|
+
return previous === undefined ? undefined : this.submit(previous.request)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
private drain(): void {
|
|
55
|
+
while (this.running < Math.max(1, this.concurrency)) {
|
|
56
|
+
const task = this.tasks.find(item => item.status === 'queued'
|
|
57
|
+
&& (this.running === 0 || (item.request.comparisonId !== undefined && !this.serialRunning)))
|
|
58
|
+
if (task === undefined) return
|
|
59
|
+
this.running += 1
|
|
60
|
+
if (task.request.comparisonId === undefined) this.serialRunning = true
|
|
61
|
+
void this.runTask(task).finally(() => {
|
|
62
|
+
this.running -= 1
|
|
63
|
+
if (task.request.comparisonId === undefined) this.serialRunning = false
|
|
64
|
+
this.drain()
|
|
65
|
+
})
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
private async runTask(task: GenerationTask): Promise<void> {
|
|
70
|
+
task.status = 'running'
|
|
71
|
+
task.startedAt = Date.now()
|
|
72
|
+
this.publish(task)
|
|
73
|
+
const controller = new AbortController()
|
|
74
|
+
this.controllers.set(task.id, controller)
|
|
75
|
+
try {
|
|
76
|
+
const result = await this.run(task.request, controller.signal)
|
|
77
|
+
if (this.tasks.find(item => item.id === task.id)?.status !== 'cancelled') {
|
|
78
|
+
task.status = 'completed'
|
|
79
|
+
task.result = result
|
|
80
|
+
task.finishedAt = Date.now()
|
|
81
|
+
this.publish(task)
|
|
82
|
+
}
|
|
83
|
+
} catch (error) {
|
|
84
|
+
if (this.tasks.find(item => item.id === task.id)?.status !== 'cancelled') {
|
|
85
|
+
task.status = 'failed'
|
|
86
|
+
task.error = error instanceof Error ? error.message : String(error)
|
|
87
|
+
task.finishedAt = Date.now()
|
|
88
|
+
this.publish(task)
|
|
89
|
+
}
|
|
90
|
+
} finally {
|
|
91
|
+
this.controllers.delete(task.id)
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
private publish(task: GenerationTask): void {
|
|
96
|
+
const snapshot = this.snapshot(task)
|
|
97
|
+
for (const listener of this.listeners) {
|
|
98
|
+
try {
|
|
99
|
+
listener(snapshot)
|
|
100
|
+
} catch {
|
|
101
|
+
// Observers must not be able to interrupt the queue pump.
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
private snapshot(task: GenerationTask): GenerationTask {
|
|
107
|
+
return {
|
|
108
|
+
...task,
|
|
109
|
+
request: { ...task.request },
|
|
110
|
+
...task.result === undefined ? {} : { result: task.result },
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|