dsh-plugin-prompt-tool 0.6.0 → 0.6.1

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.
@@ -7,8 +7,9 @@
7
7
  *
8
8
  * 插值规则:
9
9
  * - {{key}}:配置 variables 有值 → 替换;否则 ST 运行时宏(lastusermessage /
10
- * lastcharmessage 等,大小写不敏感)→ 会话事件提取;否则内置变量(DSH_HOME /
11
- * WORKSPACE / CWD)→ 替换;否则保留字面(宽容,未注册变量不抛错)。
10
+ * lastcharmessage 等,大小写不敏感)→ 会话事件提取;否则动态宏(roll/random/
11
+ * pick/chance/time/date 等,支持 {{name::arg}} 参数)→ 运行时计算;否则内置
12
+ * 变量(DSH_HOME / WORKSPACE / CWD)→ 替换;否则保留字面(宽容)。
12
13
  * - 键字符集:字母数字、下划线、点、中文、连字符(与 ST setvar/getvar 一致)。
13
14
  */
14
15
 
@@ -30,13 +31,62 @@ function lastMessageOf(session, type) {
30
31
  return ''
31
32
  }
32
33
 
33
- /** ST 运行时宏(会话上下文,大小写不敏感;无会话上下文时为空串——不残留字面)。 */
34
+ /** 逗号分隔随机选一个({{random::a,b,c}} / {{pick::a,b,c}})。 */
35
+ function pickRandom(arg) {
36
+ const items = String(arg ?? '').split(',').map((item) => item.trim()).filter((item) => item.length > 0)
37
+ if (items.length === 0) return ''
38
+ return items[Math.floor(Math.random() * items.length)]
39
+ }
40
+
41
+ /** 骰子表达式({{roll::2d6+3}} / {{roll::1d20}};非法表达式原样返回)。 */
42
+ function rollDice(arg) {
43
+ const text = String(arg ?? '').replace(/\s+/g, '').toLowerCase()
44
+ const match = text.match(/^(\d*)d(\d+)([+-]\d+)?$/)
45
+ if (match === null) return text
46
+ const count = match[1] === '' ? 1 : Number.parseInt(match[1], 10)
47
+ const sides = Number.parseInt(match[2], 10)
48
+ const modifier = match[3] === undefined ? 0 : Number.parseInt(match[3], 10)
49
+ if (!Number.isSafeInteger(count) || count <= 0 || count > 100 || !Number.isSafeInteger(sides) || sides <= 0) return text
50
+ let sum = 0
51
+ for (let index = 0; index < count; index++) sum += 1 + Math.floor(Math.random() * sides)
52
+ return String(sum + modifier)
53
+ }
54
+
55
+ /** 百分比概率({{chance::50}} → true/false)。 */
56
+ function chancePercent(arg) {
57
+ const value = Number(String(arg ?? '').replace('%', '').trim())
58
+ if (!Number.isFinite(value)) return ''
59
+ return Math.random() * 100 < value ? 'true' : 'false'
60
+ }
61
+
62
+ /** 本地 HH:MM({{time}})。 */
63
+ function formatTime(now) {
64
+ return `${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}`
65
+ }
66
+
67
+ /** UTC YYYY-MM-DD({{date}})。 */
68
+ function formatDate(now) {
69
+ return `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}`
70
+ }
71
+
72
+ /** ST 动态宏(大小写不敏感;函数签名 (arg) => string;无会话上下文时同样可用)。 */
34
73
  const DYNAMIC_MACROS = {
35
- lastusermessage: (session) => lastMessageOf(session, 'user/message'),
36
- lastcharmessage: (session) => lastMessageOf(session, 'assistant/message'),
74
+ lastusermessage: (_arg, session) => lastMessageOf(session, 'user/message'),
75
+ lastcharmessage: (_arg, session) => lastMessageOf(session, 'assistant/message'),
37
76
  // charIfNotGroup:ST 群聊时空、单聊为角色名;dsh 会话 header 无角色名
38
77
  //(单角色会话),统一返回空串(不残留字面,也不注入错误内容)。
39
78
  charifnotgroup: () => '',
79
+ random: (arg) => pickRandom(arg),
80
+ pick: (arg) => pickRandom(arg),
81
+ roll: (arg) => rollDice(arg),
82
+ chance: (arg) => chancePercent(arg),
83
+ time: () => formatTime(new Date()),
84
+ date: () => formatDate(new Date()),
85
+ weekday: () => '星期' + '日一二三四五六'[new Date().getDay()],
86
+ isotime: () => new Date().toISOString().slice(11, 19),
87
+ isodate: () => new Date().toISOString().slice(0, 10),
88
+ newline: () => '\n',
89
+ pipe: () => '|',
40
90
  }
41
91
 
42
92
  /** 模板变量插值:配置 variables 优先,ST 运行时宏次之,内置 {{DSH_HOME}} / {{WORKSPACE}} / {{CWD}} 兜底。 */
@@ -46,21 +96,21 @@ export function interpolateVariables(text, variables, session) {
46
96
  WORKSPACE: process.env.DSH_WORKSPACE ?? session?.header?.cwd ?? process.cwd(),
47
97
  CWD: session?.header?.cwd ?? process.cwd(),
48
98
  }
49
- return text.replace(/\{\{([A-Za-z0-9_.\u4e00-\u9fff-]+)\}\}/g, (whole, key) => {
99
+ return text.replace(/\{\{([A-Za-z0-9_.\u4e00-\u9fff-]+)(?:::(.*?))?\}\}/g, (whole, key, arg) => {
50
100
  if (Object.prototype.hasOwnProperty.call(variables, key)) return String(variables[key])
51
101
  const dynamic = DYNAMIC_MACROS[key.toLowerCase()]
52
- if (dynamic !== undefined) return dynamic(session)
102
+ if (dynamic !== undefined) return dynamic(arg, session)
53
103
  return Object.prototype.hasOwnProperty.call(builtins, key) ? builtins[key] : whole
54
104
  })
55
105
  }
56
106
 
57
107
  /** 仅做配置级静态变量替换(无 session 上下文的层)。 */
58
108
  export function interpolateStatic(text, variables) {
59
- return text.replace(/\{\{([A-Za-z0-9_.\u4e00-\u9fff-]+)\}\}/g, (whole, key) => {
109
+ return text.replace(/\{\{([A-Za-z0-9_.\u4e00-\u9fff-]+)(?:::(.*?))?\}\}/g, (whole, key, arg) => {
60
110
  if (Object.prototype.hasOwnProperty.call(variables, key)) return String(variables[key])
61
111
  // ST 运行时宏在无会话上下文(system-section 注册期)时替换为空串——
62
112
  // 不残留字面,也不触发官方 unknown variable 渲染报错。
63
113
  const dynamic = DYNAMIC_MACROS[key.toLowerCase()]
64
- return dynamic !== undefined ? dynamic(undefined) : whole
114
+ return dynamic !== undefined ? dynamic(arg, undefined) : whole
65
115
  })
66
116
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-plugin-prompt-tool",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "description": "DSH 插件:提示词工具,规范模型的思维链与回答内容,提供 Web UI 编辑 preset.md 与 AGENTS.md,并按 skills 目录注册可开关技能。",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -0,0 +1,38 @@
1
+ # 模板:子代理状态 / 记忆维护(audience=subagent 专用注入)
2
+ # 用途:把 ST 的「角色状态跟踪 + 关系记忆」委派给子代理完成——引擎保持确定性
3
+ # (插值/匹配/注入),智能判断(何时更新、更新成什么)交给委派子代理,
4
+ # 写入经确定性工具边界(session_var 会话状态 / world_book note 持久记忆)。
5
+ # 接入:模板选择器「消息批层」插入;默认关闭,插入后启用并按需改 stateKeys。
6
+ id: subagent-maintenance
7
+ name: 子代理状态/记忆维护
8
+ enabled: false
9
+ layer: pre-step
10
+ strategy: static
11
+ position: after-user
12
+ dedupe: none
13
+ promotion: none
14
+ audience: subagent
15
+ modelScope: all
16
+ configKind: ordered
17
+ order: 2000
18
+ role: user
19
+ mergeMode: merged
20
+ sourceKind: ''
21
+ form: hint
22
+ summary: ''
23
+ identity:
24
+ field: plugin
25
+ value: subagent-maintenance
26
+ text: |-
27
+ 你是本会话的「状态与记忆维护者」,与创作类子代理职责互补:
28
+ - 状态(本会话临时,模板变量注入用):观察互动中明确的角色状态变化
29
+ (心情、态度、接受度等),用 session_var 工具 set 更新——变量名见下方
30
+ 「状态变量」清单;状态未变化时不要重复写入。
31
+ - 记忆(跨会话持久):有人际关系进展或重要事实时,用 world_book_upsert
32
+ 的 note 参数写入来源角色卡记忆(条目 id 带 chara- 前缀 → 角色卡
33
+ memory.md,跨会话跟随角色卡);无归属条目写入预设记忆。
34
+ - 克制:仅在状态确实变化时更新;不确定时保留原值;不编造未发生的内容。
35
+ 状态变量清单:{{stateKeys}}
36
+ variables:
37
+ stateKeys: 心情, 接受值, 关系进度
38
+ params: {}