@dickpy/dsh-imagegen 1.0.5 → 1.0.7
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 +11 -5
- package/docs/images/image-generation-studio-four.png +0 -0
- package/docs/images/image-generation-studio-single.png +0 -0
- package/lib/client.js +102 -103
- package/lib/client.js.map +1 -1
- package/lib/index.js +1 -1
- package/package.json +11 -11
- package/src/client/index.ts +126 -127
- package/src/protocol.ts +1 -1
package/lib/index.js
CHANGED
|
@@ -14,7 +14,7 @@ import { spawn } from "node:child_process";
|
|
|
14
14
|
/** Settings namespace this plugin owns (host settings seam + bridge). */
|
|
15
15
|
const IMAGEGEN_SETTINGS_NAMESPACE = "dsh-imagegen";
|
|
16
16
|
/** Published package version shared by the host updater and the client UI. */
|
|
17
|
-
const PLUGIN_VERSION = "1.0.
|
|
17
|
+
const PLUGIN_VERSION = "1.0.7";
|
|
18
18
|
/** Same-origin route family (loopback-only, mirroring the dsh-ssh fence). */
|
|
19
19
|
const SETTINGS_API = {
|
|
20
20
|
describe: "/api/dsh-imagegen/settings/describe",
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dickpy/dsh-imagegen",
|
|
3
3
|
"description": "AI 生图 (image generation) plugin for the dsh web GUI: text-to-image and image-to-image through a configurable OpenAI-compatible endpoint (gpt-image-2 / gpt-image-1 / dall-e-3), with a settings card for api_url / api_key and a sidebar entry opening a split-pane generation studio.",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.7",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
7
7
|
"exports": {
|
|
@@ -27,15 +27,15 @@
|
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
30
|
-
"@deepseek-ai/dsh-client-connection": "
|
|
31
|
-
"@deepseek-ai/dsh-client-locale": "
|
|
32
|
-
"@deepseek-ai/dsh-client-runtime": "
|
|
33
|
-
"@deepseek-ai/dsh-client-ui-primitives": "
|
|
34
|
-
"@deepseek-ai/dsh-client-ui-settings": "
|
|
35
|
-
"@deepseek-ai/dsh-client-ui-slots": "
|
|
36
|
-
"@deepseek-ai/dsh-host-webserver": "
|
|
37
|
-
"@deepseek-ai/dsh-settings": "
|
|
38
|
-
"@deepseek-ai/dsh-system-prompt": "
|
|
30
|
+
"@deepseek-ai/dsh-client-connection": "0.1.0-rc.7",
|
|
31
|
+
"@deepseek-ai/dsh-client-locale": "0.1.0-rc.7",
|
|
32
|
+
"@deepseek-ai/dsh-client-runtime": "0.1.0-rc.7",
|
|
33
|
+
"@deepseek-ai/dsh-client-ui-primitives": "0.1.0-rc.7",
|
|
34
|
+
"@deepseek-ai/dsh-client-ui-settings": "0.1.0-rc.7",
|
|
35
|
+
"@deepseek-ai/dsh-client-ui-slots": "0.1.0-rc.7",
|
|
36
|
+
"@deepseek-ai/dsh-host-webserver": "0.1.0-rc.7",
|
|
37
|
+
"@deepseek-ai/dsh-settings": "0.1.0-rc.7",
|
|
38
|
+
"@deepseek-ai/dsh-system-prompt": "0.1.0-rc.7",
|
|
39
39
|
"@types/node": "^22.20.0",
|
|
40
40
|
"@types/react": "~18.3.1",
|
|
41
41
|
"@types/react-dom": "^18.3.5",
|
|
@@ -64,4 +64,4 @@
|
|
|
64
64
|
"watch": "tsdown --watch",
|
|
65
65
|
"typecheck": "tsc --noEmit"
|
|
66
66
|
}
|
|
67
|
-
}
|
|
67
|
+
}
|
package/src/client/index.ts
CHANGED
|
@@ -1,127 +1,126 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Browser-half entry for the dsh-imagegen plugin — runs inside the dsh web
|
|
3
|
-
* GUI.
|
|
4
|
-
*
|
|
5
|
-
* Registers the dsh-imagegen locale dictionaries, binds the plugin's own
|
|
6
|
-
* settings scope (its bridge routes serve the namespace the official rc.6
|
|
7
|
-
* allowlist would refuse), registers the settings card into the Web UI plugin
|
|
8
|
-
* group slot, and mounts the two DOM surfaces: the sidebar entry row (toggles
|
|
9
|
-
* the panel) and the generation studio in the center column. Failure policy:
|
|
10
|
-
* DOM mounting problems are logged, never thrown — the web shell fails the
|
|
11
|
-
* whole boot when a plugin apply throws, and an external plugin must not take
|
|
12
|
-
* the GUI down.
|
|
13
|
-
*/
|
|
14
|
-
import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client'
|
|
15
|
-
import type { ConnectionHandle } from '@deepseek-ai/dsh-client-connection/client'
|
|
16
|
-
// Type-only: pulls the locale plugin's Context merge (ctx.locale).
|
|
17
|
-
import type {} from '@deepseek-ai/dsh-client-locale/client'
|
|
18
|
-
// Type-only: pulls the LocaleNamespaceMap merge table.
|
|
19
|
-
import type {} from '@deepseek-ai/dsh-client-ui-slots'
|
|
20
|
-
import { ImageGenApi } from './api.ts'
|
|
21
|
-
import { ImageGenController } from './controller.ts'
|
|
22
|
-
import { tt } from './helpers.ts'
|
|
23
|
-
import { en, zh, type ImageGenKey } from './locales.ts'
|
|
24
|
-
import { mountPanel } from './mount.tsx'
|
|
25
|
-
import { mountSidebarEntry } from './sidebar-entry.ts'
|
|
26
|
-
import { ImageGenSettingsCard, ImageGenSettingsCardController } from './SettingsCard.tsx'
|
|
27
|
-
import { bindImageGenScope, type ImageGenScope } from './settings-scope.ts'
|
|
28
|
-
|
|
29
|
-
/** Locale namespace this plugin owns. */
|
|
30
|
-
const NS = 'dsh-imagegen'
|
|
31
|
-
|
|
32
|
-
declare module '@deepseek-ai/dsh-client-ui-slots' {
|
|
33
|
-
interface LocaleNamespaceMap {
|
|
34
|
-
/** dsh-imagegen surface copy. */
|
|
35
|
-
'dsh-imagegen': ImageGenKey
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
interface SlotMap {
|
|
39
|
-
/**
|
|
40
|
-
* The official plugin-configuration slot the Settings → Plugins →
|
|
41
|
-
* Configurable tab declares and renders. This card registers there as its
|
|
42
|
-
* own standalone card — independent of the dsh-web-ui family group — so
|
|
43
|
-
* this plugin never reads as part of that family. Spelled here with the
|
|
44
|
-
* same shape so this package can register without depending on the
|
|
45
|
-
* sibling UI package.
|
|
46
|
-
*/
|
|
47
|
-
'settings.plugin.item': { kind: '
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/** Owner share of a plugin card (the section supplies nothing). */
|
|
52
|
-
export interface ImageGenPluginItemOwnerProps {
|
|
53
|
-
/** Marker field: card owner props are intentionally empty. */
|
|
54
|
-
children?: never
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/** Required services (fiber inject waiting — the runtime must be up first). */
|
|
58
|
-
export const inject = ['slots', 'locale', 'connection']
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Mount the studio, its sidebar entry, and the settings card.
|
|
62
|
-
* @param ctx - client root context (services: slots, locale, connection).
|
|
63
|
-
*/
|
|
64
|
-
export function apply(ctx: ClientContext): void {
|
|
65
|
-
ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'dsh-imagegen: dictionaries')
|
|
66
|
-
|
|
67
|
-
const connection = ctx.get('connection') as ConnectionHandle | undefined
|
|
68
|
-
const loopback = connection?.isLoopback === true
|
|
69
|
-
// The bridge routes are loopback-fenced; remote browsers get an unavailable
|
|
70
|
-
// scope (the card explains the gap) instead of failing fetches.
|
|
71
|
-
const scope: ImageGenScope = bindImageGenScope(loopback
|
|
72
|
-
? (input, init) => fetch(input, init)
|
|
73
|
-
: () => { throw new Error('settings bridge is loopback-only') })
|
|
74
|
-
|
|
75
|
-
// Re-read the scope whenever the connection resets (same invalidation the
|
|
76
|
-
// official settings binder wires).
|
|
77
|
-
ctx.effect(() => {
|
|
78
|
-
const disposers = [
|
|
79
|
-
ctx.on('connection/reset', () => { void scope.load() }),
|
|
80
|
-
]
|
|
81
|
-
return () => { for (const dispose of disposers) dispose() }
|
|
82
|
-
}, 'dsh-imagegen: settings scope invalidation')
|
|
83
|
-
|
|
84
|
-
// Plugin configuration card: one staged form over the `dsh-imagegen` scope,
|
|
85
|
-
// registered into the official plugin-configuration slot (Settings →
|
|
86
|
-
// Plugins → Configurable) as a standalone card.
|
|
87
|
-
const settingsCard = new ImageGenSettingsCardController(scope)
|
|
88
|
-
ctx.slots.inject('settings.plugin.item', () => ctx.slots.register({
|
|
89
|
-
name: 'settings.plugin.item',
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
//
|
|
97
|
-
//
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
const
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
disposers.push(
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Browser-half entry for the dsh-imagegen plugin — runs inside the dsh web
|
|
3
|
+
* GUI.
|
|
4
|
+
*
|
|
5
|
+
* Registers the dsh-imagegen locale dictionaries, binds the plugin's own
|
|
6
|
+
* settings scope (its bridge routes serve the namespace the official rc.6
|
|
7
|
+
* allowlist would refuse), registers the settings card into the Web UI plugin
|
|
8
|
+
* group slot, and mounts the two DOM surfaces: the sidebar entry row (toggles
|
|
9
|
+
* the panel) and the generation studio in the center column. Failure policy:
|
|
10
|
+
* DOM mounting problems are logged, never thrown — the web shell fails the
|
|
11
|
+
* whole boot when a plugin apply throws, and an external plugin must not take
|
|
12
|
+
* the GUI down.
|
|
13
|
+
*/
|
|
14
|
+
import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client'
|
|
15
|
+
import type { ConnectionHandle } from '@deepseek-ai/dsh-client-connection/client'
|
|
16
|
+
// Type-only: pulls the locale plugin's Context merge (ctx.locale).
|
|
17
|
+
import type {} from '@deepseek-ai/dsh-client-locale/client'
|
|
18
|
+
// Type-only: pulls the LocaleNamespaceMap merge table.
|
|
19
|
+
import type {} from '@deepseek-ai/dsh-client-ui-slots'
|
|
20
|
+
import { ImageGenApi } from './api.ts'
|
|
21
|
+
import { ImageGenController } from './controller.ts'
|
|
22
|
+
import { tt } from './helpers.ts'
|
|
23
|
+
import { en, zh, type ImageGenKey } from './locales.ts'
|
|
24
|
+
import { mountPanel } from './mount.tsx'
|
|
25
|
+
import { mountSidebarEntry } from './sidebar-entry.ts'
|
|
26
|
+
import { ImageGenSettingsCard, ImageGenSettingsCardController } from './SettingsCard.tsx'
|
|
27
|
+
import { bindImageGenScope, type ImageGenScope } from './settings-scope.ts'
|
|
28
|
+
|
|
29
|
+
/** Locale namespace this plugin owns. */
|
|
30
|
+
const NS = 'dsh-imagegen'
|
|
31
|
+
|
|
32
|
+
declare module '@deepseek-ai/dsh-client-ui-slots' {
|
|
33
|
+
interface LocaleNamespaceMap {
|
|
34
|
+
/** dsh-imagegen surface copy. */
|
|
35
|
+
'dsh-imagegen': ImageGenKey
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
interface SlotMap {
|
|
39
|
+
/**
|
|
40
|
+
* The official plugin-configuration slot the Settings → Plugins →
|
|
41
|
+
* Configurable tab declares and renders. This card registers there as its
|
|
42
|
+
* own standalone card — independent of the dsh-web-ui family group — so
|
|
43
|
+
* this plugin never reads as part of that family. Spelled here with the
|
|
44
|
+
* same shape so this package can register without depending on the
|
|
45
|
+
* sibling UI package.
|
|
46
|
+
*/
|
|
47
|
+
'settings.plugin.item': { kind: 'keyed'; scope: 'root'; owner: ImageGenPluginItemOwnerProps }
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Owner share of a plugin card (the section supplies nothing). */
|
|
52
|
+
export interface ImageGenPluginItemOwnerProps {
|
|
53
|
+
/** Marker field: card owner props are intentionally empty. */
|
|
54
|
+
children?: never
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Required services (fiber inject waiting — the runtime must be up first). */
|
|
58
|
+
export const inject = ['slots', 'locale', 'connection']
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Mount the studio, its sidebar entry, and the settings card.
|
|
62
|
+
* @param ctx - client root context (services: slots, locale, connection).
|
|
63
|
+
*/
|
|
64
|
+
export function apply(ctx: ClientContext): void {
|
|
65
|
+
ctx.effect(() => ctx.locale.register(NS, { zh, en }), 'dsh-imagegen: dictionaries')
|
|
66
|
+
|
|
67
|
+
const connection = ctx.get('connection') as ConnectionHandle | undefined
|
|
68
|
+
const loopback = connection?.isLoopback === true
|
|
69
|
+
// The bridge routes are loopback-fenced; remote browsers get an unavailable
|
|
70
|
+
// scope (the card explains the gap) instead of failing fetches.
|
|
71
|
+
const scope: ImageGenScope = bindImageGenScope(loopback
|
|
72
|
+
? (input, init) => fetch(input, init)
|
|
73
|
+
: () => { throw new Error('settings bridge is loopback-only') })
|
|
74
|
+
|
|
75
|
+
// Re-read the scope whenever the connection resets (same invalidation the
|
|
76
|
+
// official settings binder wires).
|
|
77
|
+
ctx.effect(() => {
|
|
78
|
+
const disposers = [
|
|
79
|
+
ctx.on('connection/reset', () => { void scope.load() }),
|
|
80
|
+
]
|
|
81
|
+
return () => { for (const dispose of disposers) dispose() }
|
|
82
|
+
}, 'dsh-imagegen: settings scope invalidation')
|
|
83
|
+
|
|
84
|
+
// Plugin configuration card: one staged form over the `dsh-imagegen` scope,
|
|
85
|
+
// registered into the official plugin-configuration slot (Settings →
|
|
86
|
+
// Plugins → Configurable) as a standalone card.
|
|
87
|
+
const settingsCard = new ImageGenSettingsCardController(scope)
|
|
88
|
+
ctx.slots.inject('settings.plugin.item', () => ctx.slots.register({
|
|
89
|
+
name: 'settings.plugin.item',
|
|
90
|
+
key: 'dsh-imagegen',
|
|
91
|
+
locale: NS,
|
|
92
|
+
inject: () => settingsCard.inject(),
|
|
93
|
+
}, ImageGenSettingsCard))
|
|
94
|
+
|
|
95
|
+
// The sidebar entry and studio mount once the settings scope settles; while
|
|
96
|
+
// the scope is still loading, the composition default is unknown, so nothing
|
|
97
|
+
// mounts yet. Only an unavailable scope falls back to the default (enabled).
|
|
98
|
+
let uiDisposer: (() => void) | undefined
|
|
99
|
+
const mountUi = (): void => {
|
|
100
|
+
if (uiDisposer !== undefined) return
|
|
101
|
+
const controller = new ImageGenController()
|
|
102
|
+
const api = new ImageGenApi()
|
|
103
|
+
const disposers: Array<() => void> = []
|
|
104
|
+
try {
|
|
105
|
+
disposers.push(mountSidebarEntry(controller, tt('entry.label'), tt('entry.tooltip')))
|
|
106
|
+
disposers.push(mountPanel(controller, api, scope))
|
|
107
|
+
} catch (error) {
|
|
108
|
+
// DOM failures degrade the studio, never the GUI.
|
|
109
|
+
console.warn('[dsh-imagegen] mount failed:', error)
|
|
110
|
+
}
|
|
111
|
+
uiDisposer = () => {
|
|
112
|
+
for (const dispose of disposers.splice(0)) dispose()
|
|
113
|
+
uiDisposer = undefined
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
const syncEnabled = (): void => {
|
|
117
|
+
const snapshot = scope.getSnapshot()
|
|
118
|
+
const enabled = snapshot.status === 'ready'
|
|
119
|
+
? snapshot.value?.enabled ?? true
|
|
120
|
+
: snapshot.status === 'unavailable'
|
|
121
|
+
if (enabled) mountUi()
|
|
122
|
+
else uiDisposer?.()
|
|
123
|
+
}
|
|
124
|
+
scope.subscribe(syncEnabled)
|
|
125
|
+
syncEnabled()
|
|
126
|
+
}
|
package/src/protocol.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
export const IMAGEGEN_SETTINGS_NAMESPACE = 'dsh-imagegen'
|
|
9
9
|
|
|
10
10
|
/** Published package version shared by the host updater and the client UI. */
|
|
11
|
-
export const PLUGIN_VERSION = '1.0.
|
|
11
|
+
export const PLUGIN_VERSION = '1.0.7'
|
|
12
12
|
|
|
13
13
|
/** Same-origin route family (loopback-only, mirroring the dsh-ssh fence). */
|
|
14
14
|
export const SETTINGS_API = {
|