diff --git a/AGENTS.md b/AGENTS.md index c3767d6..39adff6 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -66,6 +66,14 @@ - 数据库结构写到 `docs/backend-database.md`。 - 文档不要写过期日期;除非用户明确要求记录具体时间。 +## 发版本流程 + +- 发版本时,先把 `CHANGELOG.md` 的 `Unreleased` 变更整理成新的版本记录,并保留空的 `Unreleased` 标题。 +- 按当前版本号提升一个版本,更新根目录 `VERSION`。 +- 将当前未提交的代码全部提交到 Git。 +- 提交完成后,给当前提交打最新版本号对应的 tag,例如 `v0.0.5`。 +- 发版本流程中不要执行编译、测试或构建,除非用户明确要求。 + ## 项目注意事项 - 当前画布项目和“我的素材”主要保存在浏览器本地,不要在文档中误写成已支持云同步。 diff --git a/CHANGELOG.md b/CHANGELOG.md index ef5fc30..1d4fe27 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,10 @@ ## Unreleased +## v0.0.5 - 2026-05-20 + + [新增] 右上角版本号支持点击查看版本更新弹窗,展示当前版本、最新版本和按时间线整理的更新日志。 ++ [新增] 设置弹窗支持配置系统提示词,AI 生图、编辑图和文本请求会自动携带。 ## v0.0.4 - 2026-05-20 diff --git a/VERSION b/VERSION index a92e827..5c314e5 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v0.0.4 \ No newline at end of file +v0.0.5 diff --git a/docs/pending-test.md b/docs/pending-test.md index 9749ed7..47b5d27 100644 --- a/docs/pending-test.md +++ b/docs/pending-test.md @@ -1,3 +1,4 @@ # 待测试 - 点击右上角版本号时,应弹出版本更新弹窗,并展示当前版本、最新版本、检查更新入口和可滚动的版本时间线。 +- 设置弹窗中填写系统提示词后,生图、编辑图和画布助手文本请求应携带该提示词。 diff --git a/web/src/components/app-top-nav.tsx b/web/src/components/app-top-nav.tsx index 7d5c640..d5b1af5 100644 --- a/web/src/components/app-top-nav.tsx +++ b/web/src/components/app-top-nav.tsx @@ -227,6 +227,9 @@ export function AppTopNav({ activeToolSlug, config, onConfigChange, hideHeader = onConfigChange("textModel", model)} fullWidth /> + + onConfigChange("systemPrompt", event.target.value)} /> + diff --git a/web/src/lib/ai-config.ts b/web/src/lib/ai-config.ts index 3a2b9ad..bde9edf 100644 --- a/web/src/lib/ai-config.ts +++ b/web/src/lib/ai-config.ts @@ -4,6 +4,7 @@ export type AiConfig = { model: string; imageModel: string; textModel: string; + systemPrompt: string; models: string[]; quality: string; size: string; @@ -18,6 +19,7 @@ export const defaultConfig: AiConfig = { model: "gpt-image-2", imageModel: "gpt-image-2", textModel: "gpt-5.5", + systemPrompt: "", models: [], quality: "auto", size: "1:1", diff --git a/web/src/services/api/image.ts b/web/src/services/api/image.ts index fb5699a..70276a5 100644 --- a/web/src/services/api/image.ts +++ b/web/src/services/api/image.ts @@ -7,7 +7,7 @@ import { imageToDataUrl } from "@/services/image-storage"; import type { ReferenceImage } from "@/types/image"; export type ChatCompletionMessage = { - role: "user" | "assistant"; + role: "system" | "user" | "assistant"; content: string | Array<{ type: "text"; text: string } | { type: "image_url"; image_url: { url: string } }>; }; @@ -58,6 +58,16 @@ function parseStreamChunk(chunk: string, onDelta: (value: string) => void) { if (deltaText) onDelta(deltaText); } +function withSystemPrompt(config: AiConfig, prompt: string) { + const systemPrompt = config.systemPrompt.trim(); + return systemPrompt ? `${systemPrompt}\n\n${prompt}` : prompt; +} + +function withSystemMessage(config: AiConfig, messages: ChatCompletionMessage[]) { + const systemPrompt = config.systemPrompt.trim(); + return systemPrompt ? [{ role: "system" as const, content: systemPrompt }, ...messages] : messages; +} + export async function requestGeneration(config: AiConfig, prompt: string) { const n = Math.max(1, Math.min(15, Math.floor(Math.abs(Number(config.count)) || 1))); try { @@ -65,7 +75,7 @@ export async function requestGeneration(config: AiConfig, prompt: string) { buildApiUrl(config.baseUrl, "/images/generations"), { model: config.model, - prompt, + prompt: withSystemPrompt(config, prompt), n, quality: config.quality || undefined, size: config.size || undefined, @@ -88,7 +98,7 @@ export async function requestEdit(config: AiConfig, prompt: string, references: const n = Math.max(1, Math.min(15, Math.floor(Math.abs(Number(config.count)) || 1))); const formData = new FormData(); formData.set("model", config.model); - formData.set("prompt", prompt); + formData.set("prompt", withSystemPrompt(config, prompt)); formData.set("n", String(n)); formData.set("response_format", "b64_json"); if (config.quality) { @@ -122,7 +132,7 @@ export async function requestImageQuestion(config: AiConfig, messages: ChatCompl buildApiUrl(config.baseUrl, "/chat/completions"), { model: config.model, - messages, + messages: withSystemMessage(config, messages), stream: true, }, {