@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.
- package/LICENSE +201 -201
- package/README.md +270 -124
- package/cordis.patch.yml +8 -8
- package/docs/images/ecommerce-mode.png +0 -0
- package/docs/images/image-generation-studio-three-column.png +0 -0
- package/docs/images/imagegen-overview.png +0 -0
- package/docs/videos/agent-chat-edit.gif +0 -0
- package/docs/videos/agent-chat-edit.mp4 +0 -0
- package/lib/client.js +1859 -420
- package/lib/client.js.map +1 -1
- package/lib/index.js +327 -112
- package/package.json +69 -68
- package/src/agent-image-tools.ts +447 -418
- package/src/client/ImageGenPanel.tsx +1242 -348
- package/src/client/SettingsCard.tsx +936 -936
- package/src/client/TemplateLibrary.tsx +336 -336
- package/src/client/api.ts +203 -193
- package/src/client/channels-form.ts +263 -263
- package/src/client/controller.ts +46 -46
- package/src/client/conversation-sync.ts +14 -14
- 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 +18 -18
- package/src/client/index.ts +22 -22
- package/src/client/locales.ts +156 -28
- package/src/client/mount.tsx +117 -117
- package/src/client/panel.module.css +1243 -455
- 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 +190 -190
- package/src/client/templates.module.css +453 -453
- package/src/edit-image-command.ts +110 -0
- package/src/engine.ts +520 -520
- package/src/gallery-store.ts +306 -286
- package/src/generation-runtime.ts +84 -79
- package/src/history-store.ts +270 -250
- package/src/image-format.ts +11 -11
- package/src/image-models.ts +19 -19
- package/src/index.ts +337 -318
- package/src/model-catalog.ts +115 -115
- package/src/presets.ts +71 -71
- package/src/prompt-enhancer.ts +137 -137
- package/src/protocol.ts +380 -338
- package/src/routes.ts +964 -916
- package/src/task-queue.ts +113 -113
- package/src/templates/cases.json +10196 -10196
- package/src/templates-store.ts +278 -278
- package/src/updater.ts +117 -117
- package/docs/images/agent-chat-edit.png +0 -0
- package/docs/images/agent-chat-generate.png +0 -0
- package/docs/images/agent-chat-poster-workflow.png +0 -0
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/** Direct `/edit_image` command for editing the latest image in the session. */
|
|
2
|
+
|
|
3
|
+
import type { Context } from '@deepseek-ai/cordis'
|
|
4
|
+
import type { CommandResult } from '@deepseek-ai/dsh-commands'
|
|
5
|
+
import type { AttachmentStore, ImageAttachmentRef } from '@deepseek-ai/dsh-attachment'
|
|
6
|
+
import type {} from '@deepseek-ai/dsh-commands'
|
|
7
|
+
import type {} from '@deepseek-ai/dsh-attachment'
|
|
8
|
+
import {
|
|
9
|
+
submitAgentImageEdit,
|
|
10
|
+
type AgentImageToolConfig,
|
|
11
|
+
} from './agent-image-tools.ts'
|
|
12
|
+
import type { ImageGenerationRuntime } from './generation-runtime.ts'
|
|
13
|
+
|
|
14
|
+
function isImageReference(value: unknown): value is ImageAttachmentRef {
|
|
15
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value)) return false
|
|
16
|
+
const ref = value as Record<string, unknown>
|
|
17
|
+
return typeof ref.attachmentId === 'string'
|
|
18
|
+
&& (ref.mediaType === 'image/png' || ref.mediaType === 'image/jpeg' || ref.mediaType === 'image/webp' || ref.mediaType === 'image/gif')
|
|
19
|
+
&& Number.isInteger(ref.bytes) && (ref.bytes as number) > 0
|
|
20
|
+
&& Number.isInteger(ref.width) && (ref.width as number) > 0
|
|
21
|
+
&& Number.isInteger(ref.height) && (ref.height as number) > 0
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function imageInContent(value: unknown): ImageAttachmentRef | undefined {
|
|
25
|
+
if (!Array.isArray(value)) return undefined
|
|
26
|
+
for (let index = value.length - 1; index >= 0; index -= 1) {
|
|
27
|
+
const block = value[index]
|
|
28
|
+
if (typeof block !== 'object' || block === null || Array.isArray(block)) continue
|
|
29
|
+
const raw = block as Record<string, unknown>
|
|
30
|
+
if (raw.type === 'image' && isImageReference(raw.attachment)) return raw.attachment
|
|
31
|
+
if (raw.type === 'tool-result') {
|
|
32
|
+
const nested = imageInContent(raw.content)
|
|
33
|
+
if (nested !== undefined) return nested
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return undefined
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Pick the newest image explicitly attached to this command invocation. */
|
|
40
|
+
function imageInInvocation(value: unknown): ImageAttachmentRef | undefined {
|
|
41
|
+
if (!Array.isArray(value)) return undefined
|
|
42
|
+
for (let index = value.length - 1; index >= 0; index -= 1) {
|
|
43
|
+
const block = value[index]
|
|
44
|
+
if (typeof block !== 'object' || block === null || Array.isArray(block)) continue
|
|
45
|
+
const raw = block as Record<string, unknown>
|
|
46
|
+
if (raw.type === 'image' && isImageReference(raw.attachment)) return raw.attachment
|
|
47
|
+
}
|
|
48
|
+
return undefined
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Find the newest durable image reference, including nested tool results. */
|
|
52
|
+
export function latestSessionImage(messages: readonly unknown[]): ImageAttachmentRef | undefined {
|
|
53
|
+
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
54
|
+
const message = messages[index]
|
|
55
|
+
if (typeof message !== 'object' || message === null || Array.isArray(message)) continue
|
|
56
|
+
const image = imageInContent((message as { content?: unknown }).content)
|
|
57
|
+
if (image !== undefined) return image
|
|
58
|
+
}
|
|
59
|
+
return undefined
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function commandError(error: unknown): CommandResult {
|
|
63
|
+
const text = error instanceof Error ? error.message : String(error)
|
|
64
|
+
return { kind: 'error', text: text.trim() === '' ? '图片编辑失败。' : text }
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** Register the host-side command; it never sends the command line to a chat model. */
|
|
68
|
+
export function registerEditImageCommand(
|
|
69
|
+
ctx: Context,
|
|
70
|
+
runtime: ImageGenerationRuntime,
|
|
71
|
+
resolve: () => AgentImageToolConfig,
|
|
72
|
+
pendingImages?: {
|
|
73
|
+
get: (sessionId: string) => ImageAttachmentRef | undefined
|
|
74
|
+
consume: (sessionId: string, ref: ImageAttachmentRef) => void
|
|
75
|
+
},
|
|
76
|
+
): () => void {
|
|
77
|
+
return ctx.commands.register({
|
|
78
|
+
name: 'edit_image',
|
|
79
|
+
description: 'Edit the latest image in this conversation with the plugin image model',
|
|
80
|
+
// `images` is understood by the newer host command protocol. Keep the
|
|
81
|
+
// source compatible with older development-only command typings.
|
|
82
|
+
input: { hint: 'Describe how to modify the latest image', images: true } as { hint: string; images: boolean },
|
|
83
|
+
async handler(invocation): Promise<CommandResult> {
|
|
84
|
+
const prompt = invocation.rawInput.trim()
|
|
85
|
+
if (prompt === '') return { kind: 'error', text: '请提供图片修改描述,例如:/edit_image 把背景改成夜景' }
|
|
86
|
+
const invocationImage = imageInInvocation((invocation as typeof invocation & { attachments?: readonly unknown[] }).attachments)
|
|
87
|
+
// A staged composer image is newer than anything already committed to
|
|
88
|
+
// the session, so it must win when the user explicitly adds a preview
|
|
89
|
+
// or gallery image before running the command.
|
|
90
|
+
const pendingImage = pendingImages?.get(String(invocation.agent.id))
|
|
91
|
+
const durableImage = latestSessionImage(invocation.agent.session.deriveMessages())
|
|
92
|
+
const sourceImage = invocationImage ?? pendingImage ?? durableImage
|
|
93
|
+
if (sourceImage === undefined) return { kind: 'error', text: '当前对话没有可用图片,请先上传图片或把画廊图片加入对话。' }
|
|
94
|
+
try {
|
|
95
|
+
const task = await submitAgentImageEdit(ctx.attachments as Pick<AttachmentStore, 'readImage'>, runtime, resolve, {
|
|
96
|
+
prompt,
|
|
97
|
+
sourceImage,
|
|
98
|
+
signal: invocation.signal,
|
|
99
|
+
})
|
|
100
|
+
if (task.status === 'completed') {
|
|
101
|
+
if (pendingImage !== undefined) pendingImages?.consume(String(invocation.agent.id), pendingImage)
|
|
102
|
+
return { kind: 'success', text: '图片编辑已完成,可在 AI 生图面板查看结果。' }
|
|
103
|
+
}
|
|
104
|
+
return { kind: 'error', text: task.error ?? `图片编辑${task.status === 'cancelled' ? '已取消' : '失败'}。` }
|
|
105
|
+
} catch (error) {
|
|
106
|
+
return commandError(error)
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
})
|
|
110
|
+
}
|