dsh-plugin-prompt-tool 1.0.0 → 2.0.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.
Files changed (95) hide show
  1. package/README.md +38 -29
  2. package/engine/actions/append-context.mjs +49 -0
  3. package/engine/actions/assembly.mjs +150 -0
  4. package/engine/actions/catalog.mjs +92 -0
  5. package/engine/actions/content.mjs +205 -0
  6. package/engine/actions/decision.mjs +54 -0
  7. package/engine/actions/examples.mjs +11 -0
  8. package/engine/actions/guard.mjs +80 -0
  9. package/engine/actions/inbox-prepend.mjs +37 -0
  10. package/engine/actions/index.mjs +100 -0
  11. package/engine/actions/inject-text.mjs +22 -0
  12. package/engine/actions/pre-step-filter.mjs +55 -0
  13. package/engine/actions/registration.mjs +168 -0
  14. package/engine/actions/request-params.mjs +32 -0
  15. package/engine/actions/sdk-strip.mjs +30 -0
  16. package/engine/actions/shared.mjs +71 -0
  17. package/engine/actions.mjs +2 -931
  18. package/engine/branch.mjs +44 -0
  19. package/engine/compaction-epoch.mjs +31 -13
  20. package/engine/compositions/source/local/dev-tool-search.yml +11 -0
  21. package/engine/compositions/source/local/instruction-hint.yml +22 -1
  22. package/engine/compositions/source/local/rule-engine.yml +6 -0
  23. package/engine/condition.mjs +16 -3
  24. package/engine/conditions/anchor.mjs +32 -0
  25. package/engine/conditions/availability.mjs +47 -0
  26. package/engine/conditions/composite.mjs +83 -0
  27. package/engine/conditions/count.mjs +140 -0
  28. package/engine/conditions/evaluation.mjs +41 -0
  29. package/engine/conditions/examples.mjs +11 -0
  30. package/engine/conditions/index.mjs +85 -0
  31. package/engine/conditions/names.mjs +21 -0
  32. package/engine/conditions/phase.mjs +54 -0
  33. package/engine/conditions/preset.mjs +94 -0
  34. package/engine/conditions/scope.mjs +18 -0
  35. package/engine/conditions/session.mjs +22 -0
  36. package/engine/conditions/source.mjs +63 -0
  37. package/engine/conditions/subject.mjs +121 -0
  38. package/engine/conditions/text.mjs +44 -0
  39. package/engine/conditions/values.mjs +32 -0
  40. package/engine/dev-tool-search.mjs +213 -0
  41. package/engine/executor.mjs +55 -6
  42. package/engine/fillers.mjs +23 -16
  43. package/engine/instruction-hint.mjs +34 -22
  44. package/engine/layers.mjs +135 -49
  45. package/engine/order.mjs +4 -1
  46. package/engine/predicates.mjs +2 -753
  47. package/engine/rule-engine.mjs +40 -0
  48. package/engine/rule-runtime.mjs +110 -0
  49. package/engine/rule-spec.mjs +187 -0
  50. package/engine/schema.mjs +16 -5
  51. package/engine/shared.mjs +1 -1
  52. package/engine/strategies.mjs +2 -235
  53. package/engine/subagent-tool-policy-core.mjs +7 -7
  54. package/engine/subagent-tool-policy.mjs +20 -10
  55. package/engine/tool-config-engine.mjs +53 -32
  56. package/engine/trigger-spec.mjs +49 -133
  57. package/lib/client.js +11117 -10860
  58. package/lib/client.js.map +1 -1
  59. package/lib/index.d.mts +82 -139
  60. package/lib/index.mjs +826 -1087
  61. package/lib/migrate-rules.d.mts +1 -0
  62. package/lib/migrate-rules.mjs +39 -0
  63. package/lib/module-package-CHPFweqK.mjs +2 -0
  64. package/lib/module-package-Cnd1_mwx.mjs +2872 -0
  65. package/lib/{paths-BgL42sSM.d.mts → paths-CyP0IkaM.d.mts} +223 -108
  66. package/lib/preset-transfer.d.mts +2 -2
  67. package/lib/preset-transfer.mjs +3 -2
  68. package/lib/{module-package-Cm3fHHlp.mjs → rules-migration-DJ6vASB5.mjs} +13696 -15557
  69. package/modules/ponytail/module.yml +381 -147
  70. package/modules/skill-surface/module.yml +74 -0
  71. package/modules/tool-surface/module.yml +67 -0
  72. package/package.json +5 -1
  73. package/templates/10-pre-step.yml +26 -22
  74. package/templates/14-first-turn-anchor.yml +25 -21
  75. package/templates/15-guide-auto.yml +34 -19
  76. package/templates/16-custom-fallback.yml +27 -15
  77. package/templates/18-placeholder-env-facts.yml +23 -14
  78. package/templates/20-system-section.yml +16 -10
  79. package/templates/30-runtime-context.yml +13 -7
  80. package/templates/40-agent-request.yml +11 -8
  81. package/templates/50-llm-stream.yml +14 -6
  82. package/templates/60-tool-pipeline.yml +15 -9
  83. package/templates/65-turn-stop.yml +19 -12
  84. package/templates/66-subagent-start.yml +12 -7
  85. package/templates/70-subagent-maintenance.yml +35 -29
  86. package/templates/75-subagent-end.yml +10 -5
  87. package/templates/80-tool-surface.yml +66 -0
  88. package/templates/policies/legacy-defaults.yml +34 -0
  89. package/engine/compositions/source/local/prompt-config-engine.yml +0 -7
  90. package/engine/prompt-config-engine.mjs +0 -104
  91. package/engine/trigger-editor-meta.mjs +0 -48
  92. package/modules/ponytail/configs/0000-ponytail-rules.yml +0 -102
  93. package/modules/ponytail/configs/0010-ponytail-level-full.yml +0 -19
  94. package/modules/ponytail/configs/0020-ponytail-level-lite.yml +0 -19
  95. package/modules/ponytail/configs/0030-ponytail-level-ultra.yml +0 -19
@@ -1,141 +1,42 @@
1
- /**
2
- * trigger-spec — 声明编译器(B7 T1):把**纯数据**的触发器声明编译成可注册的形状。
3
- *
4
- * 分工:`predicates.mjs` 提供判断原语、`actions.mjs` 提供动作、`trigger.mjs` 提供调度机制,
5
- * 本文件只做「数据 → 函数」这一步,**不含任何判断或执行的实现**。
6
- *
7
- * ## 词汇原样透传(这是本文件最重要的约束)
8
- *
9
- * `when` 的键要么是组合运算符(`any` / `all` / `not` / `notAny`),要么是七类原语之一
10
- * (`text` / `phase` / `source` / `count` / `names` / `session` / `preset`),**值原样传给对应的
11
- * `createXxxPredicate`**。声明层**不翻译、不改名、不补默认**——一旦这里长出第二套词汇,
12
- * 「文档里写的选项」与「谓词真正接受的选项」就会开始漂移,而这正是本项目要收敛的问题。
13
- *
14
- * ## 为什么 `when` 省略 = 无条件
15
- *
16
- * `when` 是**收窄**条件:不写表示「这个动作在该通道上总是执行」。这与「写一个恒真谓词」
17
- * 在行为上等价,但省略更好读;编译器对省略返回 `undefined`,注册侧据此跳过判定(零开销)。
18
- *
19
- * ## 与 `mountTriggers` 的关系
20
- *
21
- * `trigger.mjs` 的 `mountTriggers` 要求 `do` 是**函数**,而声明的 `do` 是**动作声明**;
22
- * B3 收口时两者从未对接。本文件不去接那条线(查证过:`inject-text` 与 `guard` 不经
23
- * `on(...)` 注册,"执行体"抽不出来),而是编译出 `{when, actions}` 交给
24
- * `registerAction(ctx, action, { when })` ——判定由动作侧按固定执行阶段提供。
25
- * 调度层面仍复用 `trigger.mjs` 的 `orderTriggers` / `registrationOptions`。
26
- */
27
- import {
28
- composite,
29
- createCountPredicate,
30
- createNameListPredicate,
31
- createPhasePredicate,
32
- createPresetPredicate,
33
- createSessionStatePredicate,
34
- createSourcePredicate,
35
- createTextPredicate,
36
- } from './predicates.mjs'
1
+ /** 旧 triggers 声明供离线迁移与历史契约验证;新运行时只编译 rules。 */
37
2
  import { ACTION_KINDS, actionExecutionPoint, prepareAction, registerAction } from './actions.mjs'
38
3
  import { WATERFALL_POSITIONS, orderTriggers, registrationOptions, wireTriggerObservers } from './trigger.mjs'
39
-
40
- /** 七类判断原语:声明里的键 → 工厂。键名与 `predicates.mjs` 的工厂一一对应。 */
41
- export const PREDICATE_FACTORIES = Object.freeze({
42
- text: createTextPredicate,
43
- phase: createPhasePredicate,
44
- source: createSourcePredicate,
45
- count: createCountPredicate,
46
- names: createNameListPredicate,
47
- session: createSessionStatePredicate,
48
- preset: createPresetPredicate,
49
- })
50
-
51
- /** 组合运算符(与 `composite` 的词汇同源,不另立别名)。 */
52
- export const COMPOSITE_OPERATORS = Object.freeze(['any', 'all', 'not', 'notAny'])
53
-
54
- /** 声明允许的字段(未知字段 fail loud:写错键名是最容易被静默忽略的一类错)。 */
55
- const DECLARATION_FIELDS = Object.freeze(['id', 'channel', 'channelOrder', 'waterfallPosition', 'phase', 'when', 'do'])
56
-
57
- /** 判定/动作在 `next()` 之前还是之后执行。 */
4
+ import { compileWhen } from './conditions/index.mjs'
5
+ import { conjunction, expandActions } from './branch.mjs'
6
+ export { compileWhen, COMPOSITE_OPERATORS, PREDICATE_FACTORIES } from './conditions/index.mjs'
7
+ const DECLARATION_FIELDS = Object.freeze(['id', 'channel', 'channelOrder', 'waterfallPosition', 'phase', 'if', 'then', 'else', 'when', 'do'])
58
8
  const ACTION_PHASES = Object.freeze(['before-next', 'after-next'])
59
9
 
60
- const objectOrUndefined = (value, label) => {
61
- if (value === undefined || value === null) return undefined
62
- if (typeof value !== 'object' || Array.isArray(value)) {
63
- throw new TypeError(`trigger-spec: ${label} must be an object`)
64
- }
65
- return value
10
+ /** `then`/`do` 归一化为动作声明数组;分支节点留到 `expandActions` 展开。 */
11
+ function actionList(value, label) {
12
+ const list = Array.isArray(value) ? value : [value]
13
+ if (list.length === 0) throw new TypeError(`${label} must be an action declaration or a non-empty array of them`)
14
+ return list
66
15
  }
67
16
 
68
- /**
69
- * 编译 `when`:声明对象 → 谓词函数;`undefined` / `null` → `undefined`(无条件)。
70
- *
71
- * 节点形状(两种,互斥):
72
- * - 组合节点:`{ any: [节点…] }` / `{ all: [节点…] }` / `{ notAny: [节点…] }` / `{ not: 节点 }`
73
- * - 原语节点:`{ <类别>: <选项对象> }`
74
- * **一个节点只能声明一个键**——混合声明(如同时给 `all` 与 `not`)在编译期抛错,
75
- * 于是优先级永远是显式的树形嵌套,而不是靠"先算 not 再算 and"的隐式约定。
76
- *
77
- * @param {unknown} node 声明里的 `when`
78
- * @param {object} [context] `{ ctx, standingMountFor }`:`preset` 原语需要它们(挂载期注入)
79
- * @returns {Function|undefined} 谓词函数
80
- */
81
- export function compileWhen(node, context = {}) {
82
- if (node === undefined || node === null) return undefined
83
- if (typeof node !== 'object' || Array.isArray(node)) {
84
- throw new TypeError('trigger-spec: when must be an object (a composite node or a predicate node)')
85
- }
86
- const keys = Object.keys(node)
87
- if (keys.length === 0) {
88
- throw new TypeError('trigger-spec: when must not be an empty object — 空节点是「恒真」还是「写漏了」无法区分')
89
- }
90
- if (keys.length > 1) {
91
- throw new TypeError(
92
- `trigger-spec: when must declare exactly one key — got ${keys.sort().join(', ')}`
93
- + `(allowed: ${[...COMPOSITE_OPERATORS, ...Object.keys(PREDICATE_FACTORIES)].sort().join(', ')})`,
94
- )
95
- }
96
- const [key] = keys
97
- const value = node[key]
98
-
99
- if (COMPOSITE_OPERATORS.includes(key)) {
100
- if (key === 'not') {
101
- return composite({ not: compileWhen(value, context) })
102
- }
103
- if (!Array.isArray(value) || value.length === 0) {
104
- throw new TypeError(`trigger-spec: when.${key} must be a non-empty array of nodes`)
105
- }
106
- return composite({ [key]: value.map((child) => compileWhen(child, context)) })
17
+ /** 展开后的叶子必须是已知动作。 */
18
+ function assertActionKind(action, at) {
19
+ if (action === null || typeof action !== 'object' || Array.isArray(action)) {
20
+ throw new TypeError(`trigger-spec: ${at} must be an action declaration object`)
107
21
  }
108
-
109
- const factory = PREDICATE_FACTORIES[key]
110
- if (factory === undefined) {
22
+ if (typeof action.kind !== 'string' || !Object.hasOwn(ACTION_KINDS, action.kind)) {
111
23
  throw new TypeError(
112
- `trigger-spec: unknown predicate ${JSON.stringify(key)}`
113
- + ` — known predicates: ${Object.keys(PREDICATE_FACTORIES).join(', ')}; composite: ${COMPOSITE_OPERATORS.join(', ')}`,
24
+ `trigger-spec: ${at}.kind must be one of ${Object.keys(ACTION_KINDS).join(', ')} — got ${JSON.stringify(action.kind)}`,
114
25
  )
115
26
  }
116
- const options = objectOrUndefined(value, `when.${key}`) ?? {}
117
- // `preset` 原语的取法需要挂载期注入(见 predicates.mjs 的三条硬约束),其余原语只用选项。
118
- if (key === 'preset') {
119
- return createPresetPredicate({ ...options, ctx: context.ctx, standingMountFor: context.standingMountFor })
120
- }
121
- return factory(options)
27
+ return action
122
28
  }
123
29
 
124
- /** `do` 归一化为动作声明数组;每个元素的 `kind` 必须是已知动作。 */
125
- function compileActions(value) {
126
- const list = Array.isArray(value) ? value : [value]
127
- if (list.length === 0) throw new TypeError('trigger-spec: do must be an action declaration or a non-empty array of them')
128
- return list.map((action, index) => {
129
- if (action === null || typeof action !== 'object' || Array.isArray(action)) {
130
- throw new TypeError(`trigger-spec: do[${index}] must be an action declaration object`)
131
- }
132
- if (typeof action.kind !== 'string' || !Object.hasOwn(ACTION_KINDS, action.kind)) {
133
- throw new TypeError(
134
- `trigger-spec: do[${index}].kind must be one of ${Object.keys(ACTION_KINDS).join(', ')} — got ${JSON.stringify(action.kind)}`,
135
- )
136
- }
137
- return action
138
- })
30
+ /**
31
+ * 声明级 `if` 与动作自身分支条件的合取;来自**声明级** `else` 的动作跳过声明级判定
32
+ * (它的条件里已含 `not(if)`)。两个条件缺省都表示无条件。
33
+ */
34
+ function actionGate(declarationWhen, action) {
35
+ const own = action.actionWhen
36
+ const base = action.bypassRuleWhen === true ? undefined : declarationWhen
37
+ if (base === undefined) return own
38
+ if (own === undefined) return base
39
+ return subject => base(subject) === true && own(subject) === true
139
40
  }
140
41
 
141
42
  /**
@@ -161,9 +62,13 @@ export function compileDeclaration(spec, context = {}) {
161
62
  if (typeof spec.channel !== 'string' || spec.channel.length === 0) {
162
63
  throw new TypeError(`trigger-spec: trigger ${spec.id}: channel must be a non-empty event name`)
163
64
  }
164
- if (spec.do === undefined) {
165
- throw new TypeError(`trigger-spec: trigger ${spec.id}: do is required`)
166
- }
65
+ const label = `trigger-spec: trigger ${spec.id}`
66
+ // 旧名已按引擎重构退役:显式拒绝并给出新名。
67
+ if (spec.when !== undefined) throw new TypeError(`${label}: "when" 已退役,改用 "if"`)
68
+ if (spec.do !== undefined) throw new TypeError(`${label}: "do" 已退役,改用 "then"`)
69
+ const triggerIf = spec.if
70
+ const triggerThen = spec.then
71
+ if (triggerThen === undefined) throw new TypeError(`${label}: then is required`)
167
72
  const channelOrder = spec.channelOrder ?? 0
168
73
  if (!Number.isSafeInteger(channelOrder) || channelOrder < 0) {
169
74
  throw new TypeError(`trigger-spec: trigger ${spec.id}: channelOrder must be a non-negative safe integer`)
@@ -172,11 +77,22 @@ export function compileDeclaration(spec, context = {}) {
172
77
  if (!WATERFALL_POSITIONS.has(waterfallPosition)) {
173
78
  throw new TypeError(`trigger-spec: trigger ${spec.id}: waterfallPosition must be one of ${[...WATERFALL_POSITIONS].join(', ')}`)
174
79
  }
175
- const actions = compileActions(spec.do)
176
- const when = compileWhen(spec.when, context)
80
+ // 声明级 `if` 由注册侧判定;声明级 `else` 的动作自带 `not(if)` 并跳过它,否则自相矛盾。
81
+ const expanded = [
82
+ ...expandActions(actionList(triggerThen, `${label}.then`), {}, `${label}.then`),
83
+ ...(spec.else === undefined ? [] : expandActions(actionList(spec.else, `${label}.else`), {
84
+ outer: triggerIf === undefined ? [] : [{ not: triggerIf }],
85
+ bypass: true,
86
+ }, `${label}.else`)),
87
+ ]
88
+ const when = compileWhen(triggerIf, context)
89
+ const actions = expanded.map(({ node, conditions, bypass }, index) => Object.assign(
90
+ { ...assertActionKind(node, `action[${index}]`) },
91
+ { actionWhen: compileWhen(conjunction(conditions), context), bypassRuleWhen: bypass },
92
+ ))
177
93
  // 保存期复用注册入口的纯准备阶段;不绑定 ctx,不创建预算或监听器。
178
94
  for (const action of actions) prepareAction(action, {
179
- when, promptConfigOptions: context.promptConfigOptions, ...registrationOptions({ waterfallPosition }),
95
+ when: action.actionWhen ?? when, promptConfigOptions: context.promptConfigOptions, ...registrationOptions({ waterfallPosition }),
180
96
  })
181
97
  const phase = spec.phase ?? actionExecutionPoint(actions[0]).phase
182
98
  if (!ACTION_PHASES.includes(phase)) {
@@ -240,7 +156,7 @@ export function mountDeclarations(ctx, compiled, { plugin, warnOnce } = {}) {
240
156
  plugin,
241
157
  warnOnce,
242
158
  promptConfigOptions: trigger.promptConfigOptions,
243
- when: trigger.when,
159
+ when: actionGate(trigger.when, action),
244
160
  prepend: trigger.waterfallPosition === 'outermost',
245
161
  }))
246
162
  }