@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
@@ -15,23 +15,23 @@
15
15
  * and both get the `position: relative` base in panel.module.css.
16
16
  */
17
17
 
18
- import type { ISessions } from '@deepseek-ai/dsh-client-runtime/client'
19
- import { createRoot, type Root } from 'react-dom/client'
18
+ import type { ISessions } from '@deepseek-ai/dsh-client-runtime/client'
19
+ import { createRoot, type Root } from 'react-dom/client'
20
20
  import type { ImageGenApi } from './api.ts'
21
21
  import type { ImageGenController } from './controller.ts'
22
22
  import { ImageGenPanel } from './ImageGenPanel.tsx'
23
- import type { ImageGenScope } from './settings-scope.ts'
24
- import type { ConversationService } from './conversation-sync.ts'
23
+ import type { ImageGenScope } from './settings-scope.ts'
24
+ import type { ConversationService } from './conversation-sync.ts'
25
25
  import css from './panel.module.css'
26
26
 
27
27
  /** The injected panel container (kept in the DOM, hidden when inactive). */
28
28
  export const PANEL_VIEW_SELECTOR = '[data-dsh-imagegen-view]'
29
29
 
30
- const CONVERSATION_COLUMN_SELECTOR = '[data-pane="conversation"], [class*="centerCol"]'
31
- const ACTIVE_ATTR = 'data-dsh-imagegen-active'
32
- const RESIZER_SELECTOR = '[data-dsh-imagegen-chat-resizer]'
33
- const CHAT_WIDTH_STORAGE_KEY = 'dsh-imagegen:chat-width'
34
- const CHAT_MIN_WIDTH = 320
30
+ const CONVERSATION_COLUMN_SELECTOR = '[data-pane="conversation"], [class*="centerCol"]'
31
+ const ACTIVE_ATTR = 'data-dsh-imagegen-active'
32
+ const RESIZER_SELECTOR = '[data-dsh-imagegen-chat-resizer]'
33
+ const CHAT_WIDTH_STORAGE_KEY = 'dsh-imagegen:chat-width'
34
+ const CHAT_MIN_WIDTH = 320
35
35
  /** Sibling panels' activation attributes, removed when this panel opens. */
36
36
  const OTHER_ACTIVE_ATTRS = ['data-dsh-taskboard-active', 'data-dsh-ssh-active']
37
37
  /** Cross-plugin activation event; detail is the activating panel name. */
@@ -39,82 +39,82 @@ const ACTIVATE_EVENT = 'dsh-panel-activate'
39
39
  const PANEL_NAME = 'imagegen'
40
40
 
41
41
  /** Find the center column, or undefined while the frame is not mounted. */
42
- function conversationColumn(): HTMLElement | undefined {
43
- return document.querySelector<HTMLElement>(CONVERSATION_COLUMN_SELECTOR) ?? undefined
44
- }
45
-
46
- function readChatWidth(): number | undefined {
47
- try {
48
- const raw = window.localStorage.getItem(CHAT_WIDTH_STORAGE_KEY)
49
- if (raw === null) return undefined
50
- const value = Number(raw)
51
- return Number.isFinite(value) && value >= CHAT_MIN_WIDTH ? value : undefined
52
- } catch {
53
- return undefined
54
- }
55
- }
56
-
57
- function writeChatWidth(value: number): void {
58
- try {
59
- window.localStorage.setItem(CHAT_WIDTH_STORAGE_KEY, String(Math.round(value)))
60
- } catch {
61
- // Private browsing and embedded shells may disable localStorage.
62
- }
63
- }
64
-
65
- function applyChatWidth(column: HTMLElement, clientX: number): void {
66
- const bounds = column.getBoundingClientRect()
67
- const max = Math.max(CHAT_MIN_WIDTH, bounds.width * 0.7)
68
- const width = Math.min(max, Math.max(CHAT_MIN_WIDTH, bounds.right - clientX))
69
- column.style.setProperty('--dsh-imagegen-chat-width', `${Math.round(width)}px`)
70
- writeChatWidth(width)
71
- }
72
-
73
- /** Create the visible handle that separates the image workspace and chat. */
74
- function createChatResizer(column: HTMLElement): HTMLDivElement {
75
- const resizer = document.createElement('div')
76
- resizer.dataset.dshImagegenChatResizer = ''
77
- resizer.className = css.chatResizer
78
- resizer.setAttribute('role', 'separator')
79
- resizer.setAttribute('aria-orientation', 'vertical')
80
- resizer.setAttribute('aria-label', '调整对话区域宽度')
81
- resizer.tabIndex = 0
82
-
83
- const saved = readChatWidth()
84
- if (saved !== undefined) column.style.setProperty('--dsh-imagegen-chat-width', `${saved}px`)
85
-
86
- const onPointerDown = (event: PointerEvent): void => {
87
- if (event.button !== 0) return
88
- event.preventDefault()
89
- resizer.setPointerCapture?.(event.pointerId)
90
- const onMove = (move: PointerEvent): void => { applyChatWidth(column, move.clientX) }
91
- const onUp = (): void => {
92
- window.removeEventListener('pointermove', onMove)
93
- window.removeEventListener('pointerup', onUp)
94
- window.removeEventListener('pointercancel', onUp)
95
- resizer.releasePointerCapture?.(event.pointerId)
96
- document.documentElement.style.removeProperty('cursor')
97
- document.documentElement.style.removeProperty('user-select')
98
- }
99
- window.addEventListener('pointermove', onMove)
100
- window.addEventListener('pointerup', onUp)
101
- window.addEventListener('pointercancel', onUp)
102
- document.documentElement.style.setProperty('cursor', 'col-resize')
103
- document.documentElement.style.setProperty('user-select', 'none')
104
- }
105
- const onKeyDown = (event: KeyboardEvent): void => {
106
- if (event.key !== 'ArrowLeft' && event.key !== 'ArrowRight') return
107
- event.preventDefault()
108
- const bounds = column.getBoundingClientRect()
109
- const current = column.style.getPropertyValue('--dsh-imagegen-chat-width')
110
- const currentWidth = Number.parseFloat(current) || bounds.width * 0.36
111
- const delta = event.key === 'ArrowLeft' ? -24 : 24
112
- applyChatWidth(column, bounds.right - currentWidth - delta)
113
- }
114
- resizer.addEventListener('pointerdown', onPointerDown)
115
- resizer.addEventListener('keydown', onKeyDown)
116
- return resizer
117
- }
42
+ function conversationColumn(): HTMLElement | undefined {
43
+ return document.querySelector<HTMLElement>(CONVERSATION_COLUMN_SELECTOR) ?? undefined
44
+ }
45
+
46
+ function readChatWidth(): number | undefined {
47
+ try {
48
+ const raw = window.localStorage.getItem(CHAT_WIDTH_STORAGE_KEY)
49
+ if (raw === null) return undefined
50
+ const value = Number(raw)
51
+ return Number.isFinite(value) && value >= CHAT_MIN_WIDTH ? value : undefined
52
+ } catch {
53
+ return undefined
54
+ }
55
+ }
56
+
57
+ function writeChatWidth(value: number): void {
58
+ try {
59
+ window.localStorage.setItem(CHAT_WIDTH_STORAGE_KEY, String(Math.round(value)))
60
+ } catch {
61
+ // Private browsing and embedded shells may disable localStorage.
62
+ }
63
+ }
64
+
65
+ function applyChatWidth(column: HTMLElement, clientX: number): void {
66
+ const bounds = column.getBoundingClientRect()
67
+ const max = Math.max(CHAT_MIN_WIDTH, bounds.width * 0.7)
68
+ const width = Math.min(max, Math.max(CHAT_MIN_WIDTH, bounds.right - clientX))
69
+ column.style.setProperty('--dsh-imagegen-chat-width', `${Math.round(width)}px`)
70
+ writeChatWidth(width)
71
+ }
72
+
73
+ /** Create the visible handle that separates the image workspace and chat. */
74
+ function createChatResizer(column: HTMLElement): HTMLDivElement {
75
+ const resizer = document.createElement('div')
76
+ resizer.dataset.dshImagegenChatResizer = ''
77
+ resizer.className = css.chatResizer
78
+ resizer.setAttribute('role', 'separator')
79
+ resizer.setAttribute('aria-orientation', 'vertical')
80
+ resizer.setAttribute('aria-label', '调整对话区域宽度')
81
+ resizer.tabIndex = 0
82
+
83
+ const saved = readChatWidth()
84
+ if (saved !== undefined) column.style.setProperty('--dsh-imagegen-chat-width', `${saved}px`)
85
+
86
+ const onPointerDown = (event: PointerEvent): void => {
87
+ if (event.button !== 0) return
88
+ event.preventDefault()
89
+ resizer.setPointerCapture?.(event.pointerId)
90
+ const onMove = (move: PointerEvent): void => { applyChatWidth(column, move.clientX) }
91
+ const onUp = (): void => {
92
+ window.removeEventListener('pointermove', onMove)
93
+ window.removeEventListener('pointerup', onUp)
94
+ window.removeEventListener('pointercancel', onUp)
95
+ resizer.releasePointerCapture?.(event.pointerId)
96
+ document.documentElement.style.removeProperty('cursor')
97
+ document.documentElement.style.removeProperty('user-select')
98
+ }
99
+ window.addEventListener('pointermove', onMove)
100
+ window.addEventListener('pointerup', onUp)
101
+ window.addEventListener('pointercancel', onUp)
102
+ document.documentElement.style.setProperty('cursor', 'col-resize')
103
+ document.documentElement.style.setProperty('user-select', 'none')
104
+ }
105
+ const onKeyDown = (event: KeyboardEvent): void => {
106
+ if (event.key !== 'ArrowLeft' && event.key !== 'ArrowRight') return
107
+ event.preventDefault()
108
+ const bounds = column.getBoundingClientRect()
109
+ const current = column.style.getPropertyValue('--dsh-imagegen-chat-width')
110
+ const currentWidth = Number.parseFloat(current) || bounds.width * 0.36
111
+ const delta = event.key === 'ArrowLeft' ? -24 : 24
112
+ applyChatWidth(column, bounds.right - currentWidth - delta)
113
+ }
114
+ resizer.addEventListener('pointerdown', onPointerDown)
115
+ resizer.addEventListener('keydown', onKeyDown)
116
+ return resizer
117
+ }
118
118
 
119
119
  /**
120
120
  * Mount the panel React tree into the center column and bind its visibility
@@ -124,40 +124,40 @@ function createChatResizer(column: HTMLElement): HTMLDivElement {
124
124
  * @param scope - the settings scope (config status banner).
125
125
  * @returns disposer unmounting the tree and restoring the column.
126
126
  */
127
- export function mountPanel(
128
- controller: ImageGenController,
129
- api: ImageGenApi,
130
- scope: ImageGenScope,
131
- services: {
132
- sessions?: ISessions
133
- conversation?: ConversationService
134
- } = {},
135
- ): () => void {
136
- let root: Root | undefined
137
- let container: HTMLDivElement | undefined
138
- let resizer: HTMLDivElement | undefined
127
+ export function mountPanel(
128
+ controller: ImageGenController,
129
+ api: ImageGenApi,
130
+ scope: ImageGenScope,
131
+ services: {
132
+ sessions?: ISessions
133
+ conversation?: ConversationService
134
+ } = {},
135
+ ): () => void {
136
+ let root: Root | undefined
137
+ let container: HTMLDivElement | undefined
138
+ let resizer: HTMLDivElement | undefined
139
139
 
140
140
  const ensure = (): void => {
141
141
  if (container !== undefined) {
142
142
  if (container.isConnected) return
143
143
  // The conversation pane was replaced; drop the stale tree and remount.
144
- root?.unmount()
145
- root = undefined
146
- container.remove()
147
- container = undefined
148
- resizer?.remove()
149
- resizer = undefined
144
+ root?.unmount()
145
+ root = undefined
146
+ container.remove()
147
+ container = undefined
148
+ resizer?.remove()
149
+ resizer = undefined
150
150
  }
151
151
  const column = conversationColumn()
152
152
  if (column === undefined) return
153
153
  container = document.createElement('div')
154
154
  container.dataset.dshImagegenView = ''
155
- container.className = css.view
156
- column.appendChild(container)
157
- root = createRoot(container)
158
- root.render(<ImageGenPanel api={api} scope={scope} {...services} />)
159
- resizer = column.querySelector<HTMLDivElement>(RESIZER_SELECTOR) ?? createChatResizer(column)
160
- if (resizer.parentElement !== column) column.appendChild(resizer)
155
+ container.className = css.view
156
+ column.appendChild(container)
157
+ root = createRoot(container)
158
+ root.render(<ImageGenPanel api={api} scope={scope} {...services} />)
159
+ resizer = column.querySelector<HTMLDivElement>(RESIZER_SELECTOR) ?? createChatResizer(column)
160
+ if (resizer.parentElement !== column) column.appendChild(resizer)
161
161
  }
162
162
 
163
163
  // The frame mounts after boot settlement; watch for the column's arrival.
@@ -203,11 +203,11 @@ export function mountPanel(
203
203
  waitObserver.disconnect()
204
204
  unsubscribe()
205
205
  document.documentElement.removeAttribute(ACTIVE_ATTR)
206
- root?.unmount()
207
- root = undefined
208
- container?.remove()
209
- container = undefined
210
- resizer?.remove()
211
- resizer = undefined
212
- }
213
- }
206
+ root?.unmount()
207
+ root = undefined
208
+ container?.remove()
209
+ container = undefined
210
+ resizer?.remove()
211
+ resizer = undefined
212
+ }
213
+ }