@dickpy/dsh-imagegen 1.4.0 → 1.5.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.
Files changed (53) hide show
  1. package/LICENSE +201 -201
  2. package/README.md +270 -124
  3. package/cordis.patch.yml +8 -8
  4. package/docs/images/ecommerce-mode.png +0 -0
  5. package/docs/images/image-generation-studio-three-column.png +0 -0
  6. package/docs/images/imagegen-overview.png +0 -0
  7. package/docs/videos/agent-chat-edit.gif +0 -0
  8. package/docs/videos/agent-chat-edit.mp4 +0 -0
  9. package/lib/client.js +1859 -420
  10. package/lib/client.js.map +1 -1
  11. package/lib/index.js +327 -112
  12. package/package.json +69 -68
  13. package/src/agent-image-tools.ts +447 -418
  14. package/src/client/ImageGenPanel.tsx +1242 -348
  15. package/src/client/SettingsCard.tsx +936 -936
  16. package/src/client/TemplateLibrary.tsx +336 -336
  17. package/src/client/api.ts +203 -193
  18. package/src/client/channels-form.ts +263 -263
  19. package/src/client/controller.ts +46 -46
  20. package/src/client/conversation-sync.ts +14 -14
  21. package/src/client/css-modules.d.ts +5 -5
  22. package/src/client/helpers.ts +33 -33
  23. package/src/client/image-toolview.module.css +73 -73
  24. package/src/client/image-toolview.tsx +18 -18
  25. package/src/client/index.ts +22 -22
  26. package/src/client/locales.ts +156 -28
  27. package/src/client/mount.tsx +117 -117
  28. package/src/client/panel.module.css +1243 -455
  29. package/src/client/settings-card.module.css +1023 -1023
  30. package/src/client/settings-form.ts +336 -336
  31. package/src/client/settings-scope.ts +298 -298
  32. package/src/client/sidebar-entry.ts +190 -190
  33. package/src/client/templates.module.css +453 -453
  34. package/src/edit-image-command.ts +110 -0
  35. package/src/engine.ts +520 -520
  36. package/src/gallery-store.ts +306 -286
  37. package/src/generation-runtime.ts +84 -79
  38. package/src/history-store.ts +270 -250
  39. package/src/image-format.ts +11 -11
  40. package/src/image-models.ts +19 -19
  41. package/src/index.ts +337 -318
  42. package/src/model-catalog.ts +115 -115
  43. package/src/presets.ts +71 -71
  44. package/src/prompt-enhancer.ts +137 -137
  45. package/src/protocol.ts +380 -338
  46. package/src/routes.ts +964 -916
  47. package/src/task-queue.ts +113 -113
  48. package/src/templates/cases.json +10196 -10196
  49. package/src/templates-store.ts +278 -278
  50. package/src/updater.ts +117 -117
  51. package/docs/images/agent-chat-edit.png +0 -0
  52. package/docs/images/agent-chat-generate.png +0 -0
  53. package/docs/images/agent-chat-poster-workflow.png +0 -0
package/src/task-queue.ts CHANGED
@@ -1,113 +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 = 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
- }
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
+ }