koishi-plugin-p-draw 1.3.3 → 1.3.5

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/index.js CHANGED
@@ -139,10 +139,10 @@ exports.Config = Schema.object({
139
139
  // ------------------------------------------------------------------
140
140
  const {
141
141
  normalizeBaseUrl, escapeRe, parseGenerationSize, parseBatchCount, parseSeed, parseDenoise,
142
- stripRawPrefix, parseNameTags, parsePresetList, mergeTagText,
142
+ stripRawPrefix, splitPositiveNegativePrompt, parseNameTags, parsePresetList, mergeTagText,
143
143
  } = require('./lib/parse')
144
144
  const {
145
- splitTags, canonicalTagText, joinPromptParts, cleanContentTags, appendInlineProtectedTags,
145
+ splitTags, canonicalTagText, joinPromptParts, mergeNegativePrompts, cleanContentTags, appendInlineProtectedTags,
146
146
  NO_ARTIST_RE, NO_STYLE_RE,
147
147
  } = require('./lib/tags')
148
148
  const {
@@ -2231,10 +2231,12 @@ exports.apply = async function apply(ctx, cfg) {
2231
2231
  const pcheck = await precheckPoints(session, USERID, isAdmin, count * cfg.price)
2232
2232
  if (!pcheck.ok) return pcheck.message
2233
2233
 
2234
- // 原样模式
2235
- const stripped = stripRawPrefix(text)
2236
- const raw = stripped.raw
2237
- const userPrompt = stripped.prompt
2234
+ // 原样模式
2235
+ const stripped = stripRawPrefix(text)
2236
+ const raw = stripped.raw
2237
+ const promptSections = splitPositiveNegativePrompt(stripped.prompt)
2238
+ const userPrompt = promptSections.positive
2239
+ const userNegativePrompt = promptSections.negative
2238
2240
  if (!userPrompt) return session.text('.no-prompt')
2239
2241
 
2240
2242
  // ComfyUI 就绪
@@ -2315,9 +2317,15 @@ exports.apply = async function apply(ctx, cfg) {
2315
2317
  }
2316
2318
 
2317
2319
  // i2i 运行参数:模式(style/ootd/plain)、--denoise 覆盖值、检测到的能力
2318
- const i2iRun = i2iImage
2319
- ? { i2iImage, i2i: { mode: (i2iOpts && i2iOpts.mode) || 'plain', denoise: denoise != null ? denoise : null, caps: (i2iOpts && i2iOpts.caps) || null } }
2320
- : {}
2320
+ const i2iRun = i2iImage
2321
+ ? { i2iImage, i2i: { mode: (i2iOpts && i2iOpts.mode) || 'plain', denoise: denoise != null ? denoise : null, caps: (i2iOpts && i2iOpts.caps) || null } }
2322
+ : {}
2323
+ // 用户手写了 negative: 区块时,默认负面词仍保留;用户 tag 只补充未出现的部分。
2324
+ const generationOverrides = Object.assign(
2325
+ { unet, seed },
2326
+ i2iRun,
2327
+ userNegativePrompt ? { negativePrompt: mergeNegativePrompts(cfg.negativePrompt, userNegativePrompt) } : {},
2328
+ )
2321
2329
 
2322
2330
  // 性能:按张优化(perImageOptimize)时联网搜索只做一次,各图复用同一份结果
2323
2331
  const searchCache = perImageOptimize && wantsWebSearch(userPrompt) ? await webSearch(userPrompt) : null
@@ -2329,7 +2337,7 @@ exports.apply = async function apply(ctx, cfg) {
2329
2337
  const optimized = await optimizePrompt(session, userPrompt, true, i2iRule, searchCache)
2330
2338
  p = appendInlineProtectedTags(composePrompt(optimized.prompt || userPrompt, raw).prompt, userPrompt, raw)
2331
2339
  }
2332
- const generated = await runComfyGenerate(p, parsedSize.size, Object.assign({ unet, seed }, i2iRun))
2340
+ const generated = await runComfyGenerate(p, parsedSize.size, generationOverrides)
2333
2341
  return { ...generated, prompt: p }
2334
2342
  }, { USERID, isAdmin, totalPrice: count * cfg.price })
2335
2343
  if (!queued.ok) return queued.message
@@ -2369,7 +2377,7 @@ exports.apply = async function apply(ctx, cfg) {
2369
2377
  if (cfg.queueEnabled) {
2370
2378
  try { result = await queuedTasks[i] } catch (e) { result = { ok: false, message: `生成失败:${e.message}` } }
2371
2379
  } else {
2372
- try { result = await runComfyGenerate(p, parsedSize.size, Object.assign({ unet, seed }, i2iRun)) } catch (e) { result = { ok: false, message: `生成失败:${e.message}` } }
2380
+ try { result = await runComfyGenerate(p, parsedSize.size, generationOverrides) } catch (e) { result = { ok: false, message: `生成失败:${e.message}` } }
2373
2381
  }
2374
2382
  if (!result.prompt) result.prompt = p
2375
2383
  return result
package/lib/parse.js CHANGED
@@ -186,6 +186,19 @@ function stripRawPrefix(prompt) {
186
186
  return { raw: false, prompt: text }
187
187
  }
188
188
 
189
+ // 将用户手写的正负面区块拆开。只识别独立行标记,避免把普通 tag(如 negative space)误判为负面段。
190
+ const NEGATIVE_SECTION_RE = /(?:^|\r?\n)\s*(?:negative(?:\s*prompt)?|negative_prompt|负面(?:提示词|词)?)\s*[::]\s*/i
191
+
192
+ function splitPositiveNegativePrompt(prompt) {
193
+ const text = String(prompt || '').trim()
194
+ const match = NEGATIVE_SECTION_RE.exec(text)
195
+ if (!match) return { positive: text, negative: '' }
196
+ return {
197
+ positive: text.slice(0, match.index).trim(),
198
+ negative: text.slice(match.index + match[0].length).trim(),
199
+ }
200
+ }
201
+
189
202
  function mergeTagText(existing, addition) {
190
203
  const tags = []
191
204
  const seen = new Set()
@@ -259,6 +272,7 @@ module.exports = {
259
272
  parseDenoise,
260
273
  RAW_PREFIXES,
261
274
  stripRawPrefix,
275
+ splitPositiveNegativePrompt,
262
276
  mergeTagText,
263
277
  parseNameTags,
264
278
  parsePresetList,
package/lib/tags.js CHANGED
@@ -236,6 +236,11 @@ function joinPromptParts(parts) {
236
236
  return tags.join(', ')
237
237
  }
238
238
 
239
+ // 默认负面词始终保留,用户手写负面词只补充未出现的 tag。
240
+ function mergeNegativePrompts(defaultPrompt, userPrompt) {
241
+ return joinPromptParts([defaultPrompt, userPrompt])
242
+ }
243
+
239
244
  module.exports = {
240
245
  splitTags,
241
246
  normalizeTagKey,
@@ -258,4 +263,5 @@ module.exports = {
258
263
  isCharacterIdentityTag,
259
264
  cleanContentTags,
260
265
  joinPromptParts,
266
+ mergeNegativePrompts,
261
267
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-p-draw",
3
3
  "description": "p点-绘图,连接本地 ComfyUI 生图。支持自然语言优化、尺寸选择、画师组、固定角色、生成队列,需要配合 p-qiandao 使用",
4
- "version": "1.3.3",
4
+ "version": "1.3.5",
5
5
  "main": "index.js",
6
6
  "files": [
7
7
  "index.js",