@dsh-plus/image-studio 0.1.17 → 0.1.19
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/lib/client.js +1 -1
- package/lib/index.js +6 -10
- package/package.json +11 -11
- package/src/client/client.ts +1 -1
- package/src/client/panel/controller.ts +1 -1
- package/src/client/styles.ts +1 -1
- package/src/gallery/store.ts +7 -9
- package/src/uploads/store.ts +6 -8
package/lib/client.js
CHANGED
|
@@ -3444,7 +3444,7 @@ ${extra}
|
|
|
3444
3444
|
* 图像工作室前端样式:侧栏入口 + 工作台(官方 Modal 承载)+ 配置卡片附加件。
|
|
3445
3445
|
* 设计令牌仅用 dsh-client-ui-theme 实测存在的 --dsw-alias-*(深浅色自适应);
|
|
3446
3446
|
* 模态骨架(遮罩/Escape/portal 层叠)由官方 Modal 原语承载,本表只覆写尺寸
|
|
3447
|
-
* 与内部布局(.ims-modal 等,模式同 web-files
|
|
3447
|
+
* 与内部布局(.ims-modal 等,模式同 web-files 的 wf-modal)。
|
|
3448
3448
|
* 响应式断点 767px 与 @dsh-plus/ui-mobile-fit 对齐(移动端全屏、单列、44px 热区)。
|
|
3449
3449
|
* @module image-studio/client/styles
|
|
3450
3450
|
*/
|
package/lib/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { Service } from "@deepseek-ai/cordis";
|
|
2
2
|
import { credentialRef } from "@deepseek-ai/dsh-credentials";
|
|
3
|
-
import { pluginDataPath, unwrapVolatile } from "@dsh-plus/shared";
|
|
3
|
+
import { atomicWriteFile, commitTmpFile, pluginDataPath, unwrapVolatile } from "@dsh-plus/shared";
|
|
4
4
|
import { request } from "node:http";
|
|
5
5
|
import { request as request$1 } from "node:https";
|
|
6
6
|
import { HttpsProxyAgent } from "https-proxy-agent";
|
|
7
7
|
import { randomUUID } from "node:crypto";
|
|
8
|
-
import { appendFile, mkdir, readFile, readdir,
|
|
8
|
+
import { appendFile, mkdir, readFile, readdir, rm, writeFile } from "node:fs/promises";
|
|
9
9
|
import { join } from "node:path";
|
|
10
10
|
import z from "@deepseek-ai/schemastery";
|
|
11
11
|
//#region src/errors.ts
|
|
@@ -1068,7 +1068,7 @@ async function saveGalleryItem(input) {
|
|
|
1068
1068
|
const target = imagePathOf(imageId, extOfMime(image.mime));
|
|
1069
1069
|
const tmp = `${target}.tmp-${process.pid}-${Date.now()}`;
|
|
1070
1070
|
await writeFile(tmp, image.data);
|
|
1071
|
-
await
|
|
1071
|
+
await commitTmpFile(tmp, target);
|
|
1072
1072
|
imageIds.push(imageId);
|
|
1073
1073
|
}
|
|
1074
1074
|
const item = {
|
|
@@ -1091,9 +1091,7 @@ async function deleteGalleryItem(itemId) {
|
|
|
1091
1091
|
for (const name of files) if (name.startsWith(`${imageId}.`)) await rm(join(imagesDir(), name), { force: true });
|
|
1092
1092
|
}
|
|
1093
1093
|
const kept = items.filter((item) => item.id !== itemId);
|
|
1094
|
-
|
|
1095
|
-
await writeFile(tmp, kept.map((item) => JSON.stringify(item)).join("\n") + (kept.length > 0 ? "\n" : ""), "utf8");
|
|
1096
|
-
await rename(tmp, indexFile$1());
|
|
1094
|
+
await atomicWriteFile(indexFile$1(), kept.map((item) => JSON.stringify(item)).join("\n") + (kept.length > 0 ? "\n" : ""));
|
|
1097
1095
|
return true;
|
|
1098
1096
|
}
|
|
1099
1097
|
//#endregion
|
|
@@ -1296,7 +1294,7 @@ async function saveUpload(input) {
|
|
|
1296
1294
|
const target = blobPathOf(id, ext);
|
|
1297
1295
|
const tmp = `${target}.tmp-${process.pid}-${Date.now()}`;
|
|
1298
1296
|
await writeFile(tmp, input.data);
|
|
1299
|
-
await
|
|
1297
|
+
await commitTmpFile(tmp, target);
|
|
1300
1298
|
const entry = {
|
|
1301
1299
|
id,
|
|
1302
1300
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -1325,9 +1323,7 @@ async function removeUpload(entry) {
|
|
|
1325
1323
|
}
|
|
1326
1324
|
/** 索引导出为 JSONL(重写式删除的公共收尾)。 */
|
|
1327
1325
|
async function rewriteIndex(kept) {
|
|
1328
|
-
|
|
1329
|
-
await writeFile(tmp, kept.map((item) => JSON.stringify(item)).join("\n") + (kept.length > 0 ? "\n" : ""), "utf8");
|
|
1330
|
-
await rename(tmp, indexFile());
|
|
1326
|
+
await atomicWriteFile(indexFile(), kept.map((item) => JSON.stringify(item)).join("\n") + (kept.length > 0 ? "\n" : ""));
|
|
1331
1327
|
}
|
|
1332
1328
|
/**
|
|
1333
1329
|
* 回收孤儿上传:未被 keepIds 引用且创建时间早于 ttlMs 的条目删除。
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dsh-plus/image-studio",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.19",
|
|
4
4
|
"description": "dsh-plus service+ui plugin: 图像工作室——OpenAI Images 协议文生图/图生图,全参数开关化,双预设体系,并发生图任务与可二次编辑画廊",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
@@ -20,23 +20,23 @@
|
|
|
20
20
|
],
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"https-proxy-agent": "^9.1.0",
|
|
23
|
-
"@dsh-plus/shared": "0.1.
|
|
23
|
+
"@dsh-plus/shared": "0.1.27"
|
|
24
24
|
},
|
|
25
25
|
"peerDependencies": {
|
|
26
26
|
"@deepseek-ai/cordis": "^4.0.4",
|
|
27
|
-
"@deepseek-ai/dsh-client-ui-primitives": "^0.
|
|
28
|
-
"@deepseek-ai/dsh-credentials": "^0.
|
|
29
|
-
"@deepseek-ai/dsh-host-webserver": "^0.
|
|
30
|
-
"@deepseek-ai/dsh-settings": "^0.
|
|
27
|
+
"@deepseek-ai/dsh-client-ui-primitives": "^0.2.0-rc.1",
|
|
28
|
+
"@deepseek-ai/dsh-credentials": "^0.2.0-rc.1",
|
|
29
|
+
"@deepseek-ai/dsh-host-webserver": "^0.2.0-rc.1",
|
|
30
|
+
"@deepseek-ai/dsh-settings": "^0.2.0-rc.1",
|
|
31
31
|
"@deepseek-ai/schemastery": "^3.18.4"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@deepseek-ai/cordis": "4.0.4",
|
|
35
|
-
"@deepseek-ai/dsh-client-ui-primitives": "0.
|
|
36
|
-
"@deepseek-ai/dsh-credentials": "0.
|
|
37
|
-
"@deepseek-ai/dsh-host-webserver": "0.
|
|
38
|
-
"@deepseek-ai/dsh-session": "0.
|
|
39
|
-
"@deepseek-ai/dsh-settings": "0.
|
|
35
|
+
"@deepseek-ai/dsh-client-ui-primitives": "0.2.0-rc.1",
|
|
36
|
+
"@deepseek-ai/dsh-credentials": "0.2.0-rc.1",
|
|
37
|
+
"@deepseek-ai/dsh-host-webserver": "0.2.0-rc.1",
|
|
38
|
+
"@deepseek-ai/dsh-session": "0.2.0-rc.1",
|
|
39
|
+
"@deepseek-ai/dsh-settings": "0.2.0-rc.1",
|
|
40
40
|
"@deepseek-ai/schemastery": "3.18.4",
|
|
41
41
|
"@types/node": "26.4.0",
|
|
42
42
|
"@types/react": "~18.3.31",
|
package/src/client/client.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* - shell.overlay:图像工作室面板(文生图/图生图/画廊 + 任务条);
|
|
5
5
|
* - 配置卡片:injectPluginConfigCard 三槽位(三组预设 + 凭据 + 高级项;
|
|
6
6
|
* legacy settings.plugin.item 与 0.1.6-alpha.2 插件页 row/bundle config)。
|
|
7
|
-
* 模式与 web-files
|
|
7
|
+
* 模式与 web-files 一致:CJS factory 产物、data-plugin-css 样式
|
|
8
8
|
* 约定、slot 失配静默降级;配置读写经 ctx.remote.settings 直连(远程域名可用)。
|
|
9
9
|
* @module @dsh-plus/image-studio/client
|
|
10
10
|
*/
|
package/src/client/styles.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* 图像工作室前端样式:侧栏入口 + 工作台(官方 Modal 承载)+ 配置卡片附加件。
|
|
3
3
|
* 设计令牌仅用 dsh-client-ui-theme 实测存在的 --dsw-alias-*(深浅色自适应);
|
|
4
4
|
* 模态骨架(遮罩/Escape/portal 层叠)由官方 Modal 原语承载,本表只覆写尺寸
|
|
5
|
-
* 与内部布局(.ims-modal 等,模式同 web-files
|
|
5
|
+
* 与内部布局(.ims-modal 等,模式同 web-files 的 wf-modal)。
|
|
6
6
|
* 响应式断点 767px 与 @dsh-plus/ui-mobile-fit 对齐(移动端全屏、单列、44px 热区)。
|
|
7
7
|
* @module image-studio/client/styles
|
|
8
8
|
*/
|
package/src/gallery/store.ts
CHANGED
|
@@ -7,10 +7,10 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { randomUUID } from 'node:crypto'
|
|
10
|
-
import { appendFile, mkdir, readdir, readFile,
|
|
10
|
+
import { appendFile, mkdir, readdir, readFile, rm, writeFile } from 'node:fs/promises'
|
|
11
11
|
import { join } from 'node:path'
|
|
12
12
|
|
|
13
|
-
import { pluginDataPath } from '@dsh-plus/shared'
|
|
13
|
+
import { atomicWriteFile, commitTmpFile, pluginDataPath } from '@dsh-plus/shared'
|
|
14
14
|
import { isImageId } from '../images/id.ts'
|
|
15
15
|
import { extOfMime } from '../images/mime.ts'
|
|
16
16
|
import type { ImageEndpoint } from '../provider/types.ts'
|
|
@@ -121,11 +121,12 @@ export async function saveGalleryItem(input: {
|
|
|
121
121
|
for (const image of input.images) {
|
|
122
122
|
const imageId = randomUUID()
|
|
123
123
|
const ext = extOfMime(image.mime)
|
|
124
|
-
//
|
|
124
|
+
// 图片是字节(官方 writeFileAtomic 仅收字符串):tmp 落盘 + commitTmpFile
|
|
125
|
+
// rename 提交,rename 被占用时回退复制,中断不留半截图片。
|
|
125
126
|
const target = imagePathOf(imageId, ext)
|
|
126
127
|
const tmp = `${target}.tmp-${process.pid}-${Date.now()}`
|
|
127
128
|
await writeFile(tmp, image.data)
|
|
128
|
-
await
|
|
129
|
+
await commitTmpFile(tmp, target)
|
|
129
130
|
imageIds.push(imageId)
|
|
130
131
|
}
|
|
131
132
|
const item: GalleryItem = {
|
|
@@ -153,13 +154,10 @@ export async function deleteGalleryItem(itemId: string): Promise<boolean> {
|
|
|
153
154
|
}
|
|
154
155
|
}
|
|
155
156
|
const kept = items.filter((item) => item.id !== itemId)
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
tmp,
|
|
157
|
+
await atomicWriteFile(
|
|
158
|
+
indexFile(),
|
|
159
159
|
kept.map((item) => JSON.stringify(item)).join('\n') + (kept.length > 0 ? '\n' : ''),
|
|
160
|
-
'utf8',
|
|
161
160
|
)
|
|
162
|
-
await rename(tmp, indexFile())
|
|
163
161
|
return true
|
|
164
162
|
}
|
|
165
163
|
|
package/src/uploads/store.ts
CHANGED
|
@@ -8,10 +8,10 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { randomUUID } from 'node:crypto'
|
|
11
|
-
import { appendFile, mkdir, readdir, readFile,
|
|
11
|
+
import { appendFile, mkdir, readdir, readFile, rm, writeFile } from 'node:fs/promises'
|
|
12
12
|
import { join } from 'node:path'
|
|
13
13
|
|
|
14
|
-
import { pluginDataPath } from '@dsh-plus/shared'
|
|
14
|
+
import { atomicWriteFile, commitTmpFile, pluginDataPath } from '@dsh-plus/shared'
|
|
15
15
|
import { isImageId } from '../images/id.ts'
|
|
16
16
|
import { extOfMime } from '../images/mime.ts'
|
|
17
17
|
|
|
@@ -96,9 +96,10 @@ export async function saveUpload(input: {
|
|
|
96
96
|
const id = randomUUID()
|
|
97
97
|
const ext = extOfMime(input.mime)
|
|
98
98
|
const target = blobPathOf(id, ext)
|
|
99
|
+
// 字节走 tmp + commitTmpFile(官方 writeFileAtomic 仅收字符串)。
|
|
99
100
|
const tmp = `${target}.tmp-${process.pid}-${Date.now()}`
|
|
100
101
|
await writeFile(tmp, input.data)
|
|
101
|
-
await
|
|
102
|
+
await commitTmpFile(tmp, target)
|
|
102
103
|
const entry: UploadEntry = {
|
|
103
104
|
id,
|
|
104
105
|
createdAt: new Date().toISOString(),
|
|
@@ -128,13 +129,10 @@ async function removeUpload(entry: UploadEntry): Promise<void> {
|
|
|
128
129
|
|
|
129
130
|
/** 索引导出为 JSONL(重写式删除的公共收尾)。 */
|
|
130
131
|
async function rewriteIndex(kept: UploadEntry[]): Promise<void> {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
tmp,
|
|
132
|
+
await atomicWriteFile(
|
|
133
|
+
indexFile(),
|
|
134
134
|
kept.map((item) => JSON.stringify(item)).join('\n') + (kept.length > 0 ? '\n' : ''),
|
|
135
|
-
'utf8',
|
|
136
135
|
)
|
|
137
|
-
await rename(tmp, indexFile())
|
|
138
136
|
}
|
|
139
137
|
|
|
140
138
|
/**
|