@dickpy/dsh-imagegen 1.2.3 → 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 -181
- package/cordis.patch.yml +8 -8
- package/docs/images/multi-model-comparison.png +0 -0
- package/lib/client.js +2711 -1318
- package/lib/client.js.map +1 -1
- package/lib/index.js +830 -155
- package/package.json +70 -68
- package/src/agent-image-tools.ts +418 -316
- package/src/client/ImageGenPanel.tsx +1703 -1476
- package/src/client/SettingsCard.tsx +936 -648
- package/src/client/TemplateLibrary.tsx +336 -336
- package/src/client/api.ts +193 -193
- package/src/client/channels-form.ts +263 -0
- 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 +170 -152
- package/src/client/index.ts +32 -22
- package/src/client/locales.ts +610 -484
- package/src/client/mount.tsx +185 -96
- package/src/client/panel.module.css +1713 -1445
- package/src/client/settings-card.module.css +1023 -536
- package/src/client/settings-form.ts +336 -336
- package/src/client/settings-scope.ts +298 -250
- package/src/client/sidebar-entry.ts +148 -102
- package/src/client/templates.module.css +453 -453
- package/src/engine.ts +520 -464
- package/src/gallery-store.ts +286 -280
- package/src/generation-runtime.ts +79 -48
- package/src/history-store.ts +250 -238
- package/src/image-format.ts +11 -0
- package/src/image-models.ts +19 -19
- package/src/index.ts +318 -212
- package/src/model-catalog.ts +115 -0
- package/src/presets.ts +71 -0
- package/src/prompt-enhancer.ts +137 -79
- package/src/protocol.ts +338 -253
- package/src/routes.ts +916 -738
- 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/updater.ts
CHANGED
|
@@ -1,117 +1,117 @@
|
|
|
1
|
-
/** GitHub Release discovery and explicit, user-triggered plugin updates. */
|
|
2
|
-
|
|
3
|
-
import { spawn, type ChildProcess } from 'node:child_process'
|
|
4
|
-
import { PLUGIN_VERSION } from './protocol.ts'
|
|
5
|
-
|
|
6
|
-
/** Keep this in sync with package.json for each published release. */
|
|
7
|
-
export const CURRENT_VERSION = PLUGIN_VERSION
|
|
8
|
-
export const PACKAGE_NAME = '@dickpy/dsh-imagegen'
|
|
9
|
-
export const RELEASES_URL = 'https://api.github.com/repos/dickpy/dsh-imagegen/releases/latest'
|
|
10
|
-
|
|
11
|
-
const CHECK_TIMEOUT_MS = 10_000
|
|
12
|
-
const CACHE_TTL_MS = 15 * 60_000
|
|
13
|
-
|
|
14
|
-
export interface UpdateInfo {
|
|
15
|
-
currentVersion: string
|
|
16
|
-
latestVersion: string
|
|
17
|
-
updateAvailable: boolean
|
|
18
|
-
releaseUrl: string
|
|
19
|
-
publishedAt?: string
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
interface GitHubRelease {
|
|
23
|
-
tag_name?: unknown
|
|
24
|
-
html_url?: unknown
|
|
25
|
-
published_at?: unknown
|
|
26
|
-
draft?: unknown
|
|
27
|
-
prerelease?: unknown
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
let cached: { expiresAt: number; value: UpdateInfo } | undefined
|
|
31
|
-
|
|
32
|
-
/** Compare stable semver triples; returns positive when `left` is newer. */
|
|
33
|
-
export function compareVersions(left: string, right: string): number {
|
|
34
|
-
const parse = (value: string): [number, number, number] => {
|
|
35
|
-
const match = /^v?(\d+)\.(\d+)\.(\d+)/.exec(value.trim())
|
|
36
|
-
if (match === null) return [0, 0, 0]
|
|
37
|
-
return [Number(match[1]), Number(match[2]), Number(match[3])]
|
|
38
|
-
}
|
|
39
|
-
const a = parse(left)
|
|
40
|
-
const b = parse(right)
|
|
41
|
-
return a[0] - b[0] || a[1] - b[1] || a[2] - b[2]
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function normalizedReleaseVersion(tag: unknown): string | undefined {
|
|
45
|
-
if (typeof tag !== 'string' || !/^v?\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(tag.trim())) return undefined
|
|
46
|
-
return tag.trim().replace(/^v/, '')
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/** Read the latest stable GitHub Release, with a short host-side cache. */
|
|
50
|
-
export async function checkForUpdate(fetchFn: typeof fetch = fetch, now = Date.now()): Promise<UpdateInfo> {
|
|
51
|
-
if (cached !== undefined && cached.expiresAt > now) return cached.value
|
|
52
|
-
const response = await fetchFn(RELEASES_URL, {
|
|
53
|
-
headers: {
|
|
54
|
-
accept: 'application/vnd.github+json',
|
|
55
|
-
'user-agent': 'dsh-imagegen-update-check',
|
|
56
|
-
},
|
|
57
|
-
signal: AbortSignal.timeout(CHECK_TIMEOUT_MS),
|
|
58
|
-
})
|
|
59
|
-
if (!response.ok) throw new Error(`GitHub Releases returned HTTP ${response.status}`)
|
|
60
|
-
const payload: unknown = await response.json()
|
|
61
|
-
if (payload === null || typeof payload !== 'object') throw new Error('GitHub Releases returned malformed JSON')
|
|
62
|
-
const release = payload as GitHubRelease
|
|
63
|
-
if (release.draft === true || release.prerelease === true) throw new Error('latest GitHub Release is not stable')
|
|
64
|
-
const latestVersion = normalizedReleaseVersion(release.tag_name)
|
|
65
|
-
if (latestVersion === undefined) throw new Error('latest GitHub Release has an invalid version tag')
|
|
66
|
-
const releaseUrl = typeof release.html_url === 'string' ? release.html_url : 'https://github.com/dickpy/dsh-imagegen/releases'
|
|
67
|
-
const value: UpdateInfo = {
|
|
68
|
-
currentVersion: CURRENT_VERSION,
|
|
69
|
-
latestVersion,
|
|
70
|
-
updateAvailable: compareVersions(latestVersion, CURRENT_VERSION) > 0,
|
|
71
|
-
releaseUrl,
|
|
72
|
-
...typeof release.published_at === 'string' ? { publishedAt: release.published_at } : {},
|
|
73
|
-
}
|
|
74
|
-
cached = { expiresAt: now + CACHE_TTL_MS, value }
|
|
75
|
-
return value
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/** Resolve the profile that launched the current DSH process. */
|
|
79
|
-
export function profileFromProcess(argv: readonly string[] = process.argv, env: NodeJS.ProcessEnv = process.env): string {
|
|
80
|
-
const envProfile = env.DSH_PROFILE?.trim()
|
|
81
|
-
if (envProfile !== undefined && /^[a-zA-Z0-9_-]+$/.test(envProfile)) return envProfile
|
|
82
|
-
const profileIndex = argv.indexOf('--profile')
|
|
83
|
-
const explicit = profileIndex >= 0 ? argv[profileIndex + 1]?.trim() : undefined
|
|
84
|
-
if (explicit !== undefined && /^[a-zA-Z0-9_-]+$/.test(explicit)) return explicit
|
|
85
|
-
if (argv.includes('web')) return 'web'
|
|
86
|
-
return 'web'
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/** Run the same official command documented for plugin installation. */
|
|
90
|
-
export function installUpdate(
|
|
91
|
-
version: string,
|
|
92
|
-
spawnFn: typeof spawn = spawn,
|
|
93
|
-
argv: readonly string[] = process.argv,
|
|
94
|
-
env: NodeJS.ProcessEnv = process.env,
|
|
95
|
-
): Promise<void> {
|
|
96
|
-
if (!/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(version)) {
|
|
97
|
-
return Promise.reject(new Error('invalid update version'))
|
|
98
|
-
}
|
|
99
|
-
const profile = profileFromProcess(argv, env)
|
|
100
|
-
const command = process.platform === 'win32' ? 'dsh.cmd' : 'dsh'
|
|
101
|
-
const child = spawnFn(command, ['plugin', '--profile', profile, 'add', `${PACKAGE_NAME}@${version}`], {
|
|
102
|
-
shell: process.platform === 'win32',
|
|
103
|
-
stdio: 'ignore',
|
|
104
|
-
}) as ChildProcess
|
|
105
|
-
return new Promise((resolve, reject) => {
|
|
106
|
-
child.once('error', reject)
|
|
107
|
-
child.once('exit', (code, signal) => {
|
|
108
|
-
if (code === 0) resolve()
|
|
109
|
-
else reject(new Error(signal === null ? `plugin update exited with code ${code ?? 'unknown'}` : `plugin update terminated by ${signal}`))
|
|
110
|
-
})
|
|
111
|
-
})
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/** Test helper: clear the host-side Release cache. */
|
|
115
|
-
export function clearUpdateCache(): void {
|
|
116
|
-
cached = undefined
|
|
117
|
-
}
|
|
1
|
+
/** GitHub Release discovery and explicit, user-triggered plugin updates. */
|
|
2
|
+
|
|
3
|
+
import { spawn, type ChildProcess } from 'node:child_process'
|
|
4
|
+
import { PLUGIN_VERSION } from './protocol.ts'
|
|
5
|
+
|
|
6
|
+
/** Keep this in sync with package.json for each published release. */
|
|
7
|
+
export const CURRENT_VERSION = PLUGIN_VERSION
|
|
8
|
+
export const PACKAGE_NAME = '@dickpy/dsh-imagegen'
|
|
9
|
+
export const RELEASES_URL = 'https://api.github.com/repos/dickpy/dsh-imagegen/releases/latest'
|
|
10
|
+
|
|
11
|
+
const CHECK_TIMEOUT_MS = 10_000
|
|
12
|
+
const CACHE_TTL_MS = 15 * 60_000
|
|
13
|
+
|
|
14
|
+
export interface UpdateInfo {
|
|
15
|
+
currentVersion: string
|
|
16
|
+
latestVersion: string
|
|
17
|
+
updateAvailable: boolean
|
|
18
|
+
releaseUrl: string
|
|
19
|
+
publishedAt?: string
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
interface GitHubRelease {
|
|
23
|
+
tag_name?: unknown
|
|
24
|
+
html_url?: unknown
|
|
25
|
+
published_at?: unknown
|
|
26
|
+
draft?: unknown
|
|
27
|
+
prerelease?: unknown
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
let cached: { expiresAt: number; value: UpdateInfo } | undefined
|
|
31
|
+
|
|
32
|
+
/** Compare stable semver triples; returns positive when `left` is newer. */
|
|
33
|
+
export function compareVersions(left: string, right: string): number {
|
|
34
|
+
const parse = (value: string): [number, number, number] => {
|
|
35
|
+
const match = /^v?(\d+)\.(\d+)\.(\d+)/.exec(value.trim())
|
|
36
|
+
if (match === null) return [0, 0, 0]
|
|
37
|
+
return [Number(match[1]), Number(match[2]), Number(match[3])]
|
|
38
|
+
}
|
|
39
|
+
const a = parse(left)
|
|
40
|
+
const b = parse(right)
|
|
41
|
+
return a[0] - b[0] || a[1] - b[1] || a[2] - b[2]
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function normalizedReleaseVersion(tag: unknown): string | undefined {
|
|
45
|
+
if (typeof tag !== 'string' || !/^v?\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(tag.trim())) return undefined
|
|
46
|
+
return tag.trim().replace(/^v/, '')
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** Read the latest stable GitHub Release, with a short host-side cache. */
|
|
50
|
+
export async function checkForUpdate(fetchFn: typeof fetch = fetch, now = Date.now()): Promise<UpdateInfo> {
|
|
51
|
+
if (cached !== undefined && cached.expiresAt > now) return cached.value
|
|
52
|
+
const response = await fetchFn(RELEASES_URL, {
|
|
53
|
+
headers: {
|
|
54
|
+
accept: 'application/vnd.github+json',
|
|
55
|
+
'user-agent': 'dsh-imagegen-update-check',
|
|
56
|
+
},
|
|
57
|
+
signal: AbortSignal.timeout(CHECK_TIMEOUT_MS),
|
|
58
|
+
})
|
|
59
|
+
if (!response.ok) throw new Error(`GitHub Releases returned HTTP ${response.status}`)
|
|
60
|
+
const payload: unknown = await response.json()
|
|
61
|
+
if (payload === null || typeof payload !== 'object') throw new Error('GitHub Releases returned malformed JSON')
|
|
62
|
+
const release = payload as GitHubRelease
|
|
63
|
+
if (release.draft === true || release.prerelease === true) throw new Error('latest GitHub Release is not stable')
|
|
64
|
+
const latestVersion = normalizedReleaseVersion(release.tag_name)
|
|
65
|
+
if (latestVersion === undefined) throw new Error('latest GitHub Release has an invalid version tag')
|
|
66
|
+
const releaseUrl = typeof release.html_url === 'string' ? release.html_url : 'https://github.com/dickpy/dsh-imagegen/releases'
|
|
67
|
+
const value: UpdateInfo = {
|
|
68
|
+
currentVersion: CURRENT_VERSION,
|
|
69
|
+
latestVersion,
|
|
70
|
+
updateAvailable: compareVersions(latestVersion, CURRENT_VERSION) > 0,
|
|
71
|
+
releaseUrl,
|
|
72
|
+
...typeof release.published_at === 'string' ? { publishedAt: release.published_at } : {},
|
|
73
|
+
}
|
|
74
|
+
cached = { expiresAt: now + CACHE_TTL_MS, value }
|
|
75
|
+
return value
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** Resolve the profile that launched the current DSH process. */
|
|
79
|
+
export function profileFromProcess(argv: readonly string[] = process.argv, env: NodeJS.ProcessEnv = process.env): string {
|
|
80
|
+
const envProfile = env.DSH_PROFILE?.trim()
|
|
81
|
+
if (envProfile !== undefined && /^[a-zA-Z0-9_-]+$/.test(envProfile)) return envProfile
|
|
82
|
+
const profileIndex = argv.indexOf('--profile')
|
|
83
|
+
const explicit = profileIndex >= 0 ? argv[profileIndex + 1]?.trim() : undefined
|
|
84
|
+
if (explicit !== undefined && /^[a-zA-Z0-9_-]+$/.test(explicit)) return explicit
|
|
85
|
+
if (argv.includes('web')) return 'web'
|
|
86
|
+
return 'web'
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** Run the same official command documented for plugin installation. */
|
|
90
|
+
export function installUpdate(
|
|
91
|
+
version: string,
|
|
92
|
+
spawnFn: typeof spawn = spawn,
|
|
93
|
+
argv: readonly string[] = process.argv,
|
|
94
|
+
env: NodeJS.ProcessEnv = process.env,
|
|
95
|
+
): Promise<void> {
|
|
96
|
+
if (!/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(version)) {
|
|
97
|
+
return Promise.reject(new Error('invalid update version'))
|
|
98
|
+
}
|
|
99
|
+
const profile = profileFromProcess(argv, env)
|
|
100
|
+
const command = process.platform === 'win32' ? 'dsh.cmd' : 'dsh'
|
|
101
|
+
const child = spawnFn(command, ['plugin', '--profile', profile, 'add', `${PACKAGE_NAME}@${version}`], {
|
|
102
|
+
shell: process.platform === 'win32',
|
|
103
|
+
stdio: 'ignore',
|
|
104
|
+
}) as ChildProcess
|
|
105
|
+
return new Promise((resolve, reject) => {
|
|
106
|
+
child.once('error', reject)
|
|
107
|
+
child.once('exit', (code, signal) => {
|
|
108
|
+
if (code === 0) resolve()
|
|
109
|
+
else reject(new Error(signal === null ? `plugin update exited with code ${code ?? 'unknown'}` : `plugin update terminated by ${signal}`))
|
|
110
|
+
})
|
|
111
|
+
})
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/** Test helper: clear the host-side Release cache. */
|
|
115
|
+
export function clearUpdateCache(): void {
|
|
116
|
+
cached = undefined
|
|
117
|
+
}
|