dsh-plugin-prompt-tool 2.0.1 → 3.0.0
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/README.md +100 -233
- package/engine/actions/append-context.mjs +3 -24
- package/engine/actions/assembly.mjs +70 -94
- package/engine/actions/catalog.mjs +65 -28
- package/engine/actions/content.mjs +8 -152
- package/engine/actions/examples.mjs +8 -4
- package/engine/actions/inbox-prepend.mjs +5 -7
- package/engine/actions/index.mjs +17 -9
- package/engine/actions/inject-text.mjs +24 -4
- package/engine/actions/pre-step-filter.mjs +3 -4
- package/engine/actions/registration.mjs +20 -28
- package/engine/actions/request-params.mjs +21 -1
- package/engine/actions/shared.mjs +23 -15
- package/engine/actions/stream-output.mjs +26 -0
- package/engine/actions/tool-gate.mjs +31 -0
- package/engine/actions/tool-result.mjs +36 -0
- package/engine/actions/tool-visibility.mjs +248 -0
- package/engine/agent-capability.mjs +67 -0
- package/engine/anchor-match.mjs +14 -21
- package/engine/audience.d.mts +2 -0
- package/engine/audience.mjs +102 -0
- package/engine/branch.d.mts +4 -0
- package/engine/branch.mjs +62 -19
- package/engine/compaction-epoch.d.mts +25 -0
- package/engine/compaction-epoch.mjs +27 -4
- package/engine/compositions/source/local/filesystem-editor.yml +3 -3
- package/engine/compositions/source/local/instruction-hint.yml +4 -7
- package/engine/compositions/source/local/module-file-tools.yml +2 -0
- package/engine/compositions/source/local/module-import-tools.yml +4 -0
- package/engine/compositions/source/local/module-manifest-tools.yml +2 -0
- package/engine/compositions/source/local/module-rule-tools.yml +5 -0
- package/engine/compositions/source/local/module-variable-tools.yml +5 -0
- package/engine/compositions/source/local/present-as.yml +26 -0
- package/engine/compositions/source/local/tool-config-engine.yml +2 -3
- package/engine/compositions/source/local/tool-search.yml +11 -0
- package/engine/condition-facts.mjs +84 -0
- package/engine/conditions/anchor.mjs +63 -23
- package/engine/conditions/availability.mjs +1 -1
- package/engine/conditions/composite.mjs +4 -4
- package/engine/conditions/count.mjs +43 -13
- package/engine/conditions/evaluation.mjs +74 -19
- package/engine/conditions/examples.mjs +2 -1
- package/engine/conditions/index.d.mts +15 -0
- package/engine/conditions/index.mjs +23 -9
- package/engine/conditions/operators.mjs +4 -0
- package/engine/conditions/phase.mjs +10 -5
- package/engine/conditions/preset.mjs +1 -1
- package/engine/conditions/session.mjs +8 -2
- package/engine/conditions/subject.mjs +144 -65
- package/engine/conditions/text.mjs +26 -8
- package/engine/conditions/variable.mjs +83 -0
- package/engine/context-activation.d.mts +11 -0
- package/engine/{st-world-book.mjs → context-activation.mjs} +104 -64
- package/engine/delivery.d.mts +2 -0
- package/engine/delivery.mjs +93 -0
- package/engine/discovery.d.mts +38 -0
- package/engine/discovery.mjs +146 -0
- package/engine/env-safety.mjs +14 -0
- package/engine/executor.d.mts +28 -0
- package/engine/executor.mjs +290 -205
- package/engine/fillers.mjs +39 -8
- package/engine/fixed-registration.mjs +12 -0
- package/engine/history.mjs +71 -0
- package/engine/instruction-blocks.d.mts +13 -0
- package/engine/instruction-blocks.mjs +21 -0
- package/engine/instruction-files.d.mts +5 -0
- package/engine/instruction-files.mjs +97 -0
- package/engine/instruction-hint.mjs +69 -103
- package/engine/interpolate.d.mts +7 -0
- package/engine/interpolate.mjs +44 -13
- package/engine/layers.mjs +165 -230
- package/engine/machine-paths.mjs +40 -0
- package/engine/module-file-tools.mjs +8 -0
- package/engine/module-import-tools.mjs +10 -0
- package/engine/module-manifest-tools.mjs +8 -0
- package/engine/module-rule-tools.mjs +10 -0
- package/engine/module-variable-tools.mjs +10 -0
- package/engine/order.d.mts +14 -0
- package/engine/order.mjs +0 -3
- package/engine/path-safety.d.mts +2 -0
- package/engine/path-safety.mjs +58 -0
- package/engine/pre-step-source.d.mts +69 -0
- package/engine/pre-step-source.mjs +103 -0
- package/engine/present-as.mjs +77 -0
- package/engine/promotion-pool.d.mts +9 -0
- package/engine/promotion-pool.mjs +69 -0
- package/engine/record.mjs +2 -0
- package/engine/rule-engine.mjs +3 -2
- package/engine/rule-facts.d.mts +11 -0
- package/engine/rule-facts.mjs +60 -0
- package/engine/rule-runtime.d.mts +46 -0
- package/engine/rule-runtime.mjs +98 -13
- package/engine/rule-spec.d.mts +106 -0
- package/engine/rule-spec.mjs +302 -28
- package/engine/run-code-env.mjs +73 -19
- package/engine/schema.mjs +165 -243
- package/engine/sdk-strip.mjs +2 -2
- package/engine/service-names.d.mts +10 -0
- package/engine/service-names.mjs +10 -0
- package/engine/shared.d.mts +21 -0
- package/engine/shared.mjs +47 -26
- package/engine/skill-search.mjs +125 -53
- package/engine/source-kind.d.mts +9 -0
- package/engine/source-kind.mjs +16 -0
- package/engine/strategy-ids.mjs +5 -0
- package/engine/template-evaluation.d.mts +16 -0
- package/engine/template-evaluation.mjs +178 -0
- package/engine/template-frame.d.mts +16 -0
- package/engine/template-frame.mjs +69 -0
- package/engine/tool-config-engine.mjs +39 -35
- package/engine/tool-definition.d.mts +4 -0
- package/engine/tool-definition.mjs +5 -1
- package/engine/tool-git-bash.mjs +5 -1
- package/engine/tool-scope.mjs +22 -0
- package/engine/{dev-tool-search.mjs → tool-search.mjs} +63 -65
- package/engine/trigger.mjs +15 -270
- package/engine/vendor/yaml/dist/compose/resolve-flow-scalar.js +19 -18
- package/engine/vendor/yaml/dist/nodes/Alias.js +25 -23
- package/engine/vendor/yaml/package.json +1 -1
- package/lib/client.js +8312 -6724
- package/lib/client.js.map +1 -1
- package/lib/index.d.mts +37 -762
- package/lib/index.mjs +26919 -5791
- package/modules/ponytail/module.yml +83 -203
- package/modules/ptc-mode/module.yml +45 -0
- package/modules/soul/assets/core-hard.md +6 -0
- package/modules/soul/assets/criteria.md +12 -0
- package/modules/soul/assets/echo.md +12 -0
- package/modules/soul/assets/layers.md +11 -0
- package/modules/soul/assets/ledger.md +9 -0
- package/modules/soul/assets/manifest.yml +20 -0
- package/modules/soul/assets/reference/00-layers.md +27 -0
- package/modules/soul/assets/reference/01-criteria.md +32 -0
- package/modules/soul/assets/reference/02-echo.md +158 -0
- package/modules/soul/assets/reference/03-vital.md +183 -0
- package/modules/soul/assets/reference/04-manifest.json +106 -0
- package/modules/soul/assets/reference/05-doctor.md +67 -0
- package/modules/soul/assets/reference/06-reference.md +189 -0
- package/modules/soul/assets/reference/07-bundle.json +431 -0
- package/modules/soul/assets/reference/08-/350/270/251/345/235/221/345/256/236/345/275/225.md +59 -0
- package/modules/soul/assets/reference/09-dev-workflow.md +109 -0
- package/modules/soul/assets/reference/10-echo-anatomy.md +100 -0
- package/modules/soul/assets/reference/11-self.md +80 -0
- package/modules/soul/assets/reference/12-ledger.md +159 -0
- package/modules/soul/assets/reference/README.md +10 -0
- package/modules/soul/assets/templates/agents-template.md +6 -0
- package/modules/soul/assets/vital.md +9 -0
- package/modules/soul/module.yml +311 -0
- package/modules/superpowers/module.yml +122 -0
- package/modules/tool-surface/module.yml +51 -47
- package/package.json +40 -41
- package/skills/dsh-module/SKILL.md +119 -0
- package/skills/dsh-module/reference.md +185 -0
- package/templates/10-pre-step.yml +2 -3
- package/templates/14-first-turn-anchor.yml +10 -14
- package/templates/15-guide-auto.yml +32 -28
- package/templates/16-custom-fallback.yml +33 -21
- package/templates/20-system-section.yml +1 -4
- package/templates/50-llm-stream.yml +4 -10
- package/templates/60-tool-pipeline.yml +12 -10
- package/templates/63-append-context.yml +20 -0
- package/templates/64-pre-step-filter.yml +23 -0
- package/templates/65-turn-stop.yml +2 -2
- package/templates/67-inbox-prepend.yml +22 -0
- package/templates/70-subagent-maintenance.yml +9 -10
- package/templates/75-subagent-end.yml +2 -2
- package/templates/80-tool-surface.yml +41 -57
- package/templates/tools/40-delegate-module-import.yml +22 -0
- package/templates/tools/50-delegate-module-rules.yml +14 -0
- package/templates/tools/60-delegate-module-variables.yml +17 -0
- package/templates/tools/70-delegate-module-rules-edit.yml +31 -0
- package/engine/actions/decision.mjs +0 -54
- package/engine/actions/guard.mjs +0 -80
- package/engine/actions/sdk-strip.mjs +0 -30
- package/engine/character-tools.mjs +0 -8
- package/engine/classify-task.mjs +0 -53
- package/engine/compositions/library/agent-instructions.yml +0 -9
- package/engine/compositions/library/command-goal.yml +0 -7
- package/engine/compositions/library/compaction.yml +0 -22
- package/engine/compositions/library/delegation-ptc.yml +0 -58
- package/engine/compositions/library/delegation.yml +0 -56
- package/engine/compositions/library/persistent-shell.yml +0 -50
- package/engine/compositions/library/planning.yml +0 -26
- package/engine/compositions/library/skill-filesystem-cordis.yml +0 -10
- package/engine/compositions/library/skill-filesystem.yml +0 -7
- package/engine/compositions/library/tool-ask-user.yml +0 -7
- package/engine/compositions/library/tool-bash.yml +0 -8
- package/engine/compositions/library/tool-cordis.yml +0 -7
- package/engine/compositions/library/tool-fs-search.yml +0 -9
- package/engine/compositions/library/tool-fs.yml +0 -7
- package/engine/compositions/library/tool-goal.yml +0 -7
- package/engine/compositions/library/tool-jobs.yml +0 -7
- package/engine/compositions/library/tool-plugin-manager-disabled.yml +0 -8
- package/engine/compositions/library/tool-plugin-manager.yml +0 -8
- package/engine/compositions/library/tool-present.yml +0 -7
- package/engine/compositions/library/tool-presentation.yml +0 -9
- package/engine/compositions/library/tool-pwsh.yml +0 -8
- package/engine/compositions/library/tool-skill.yml +0 -7
- package/engine/compositions/library/tool-todo.yml +0 -9
- package/engine/compositions/library/tool-web.yml +0 -10
- package/engine/compositions/source/local/character-tools.yml +0 -5
- package/engine/compositions/source/local/declared-triggers.yml +0 -12
- package/engine/compositions/source/local/dev-tool-search.yml +0 -11
- package/engine/compositions/source/local/session-var-tools.yml +0 -5
- package/engine/compositions/source/local/subagent-tool-policy.yml +0 -21
- package/engine/compositions/source/local/world-book-tools.yml +0 -5
- package/engine/condition.mjs +0 -96
- package/engine/declared-triggers.mjs +0 -93
- package/engine/session-var-tools.mjs +0 -8
- package/engine/session-vars.mjs +0 -54
- package/engine/st-macros.d.mts +0 -22
- package/engine/st-macros.mjs +0 -208
- package/engine/st-render.mjs +0 -109
- package/engine/st-world-book.d.mts +0 -10
- package/engine/subagent-tool-policy-core.mjs +0 -400
- package/engine/subagent-tool-policy.mjs +0 -352
- package/engine/trigger-spec.mjs +0 -173
- package/engine/world-book-tools.mjs +0 -8
- package/lib/migrate-rules.d.mts +0 -1
- package/lib/migrate-rules.mjs +0 -39
- package/lib/module-package-CHPFweqK.mjs +0 -2
- package/lib/module-package-Cnd1_mwx.mjs +0 -2872
- package/lib/paths-CyP0IkaM.d.mts +0 -1390
- package/lib/preset-transfer.d.mts +0 -2
- package/lib/preset-transfer.mjs +0 -3
- package/lib/rules-migration-DJ6vASB5.mjs +0 -15334
- package/templates/policies/legacy-defaults.yml +0 -34
- package/templates/tools/40-delegate-character.yml +0 -15
- package/templates/tools/50-delegate-worldbook.yml +0 -15
- package/templates/tools/60-delegate-session-var.yml +0 -15
- package/templates/tools/70-delegate-worldbook-upsert.yml +0 -36
|
@@ -1,35 +1,47 @@
|
|
|
1
|
-
#
|
|
2
|
-
#
|
|
3
|
-
#
|
|
4
|
-
# 两者都为空 = 不做词确认,只走未命中兜底注入(引擎不内置确认词)。
|
|
5
|
-
# 提示:把本文件放入 模块规则模板目录,或把对象写入 module.yml.rules 数组。
|
|
1
|
+
# 先投递锚句,仅确认该次投递后的模型推理,再注入正文。
|
|
2
|
+
# 默认持续等待;需要兜底时在 anchor 下显式添加 fallbackAfter: N。
|
|
3
|
+
# 默认等待下一次正常请求;续跑通过既有 turn-stop 规则显式配置。
|
|
6
4
|
id: example-custom-fallback
|
|
7
|
-
name:
|
|
5
|
+
name: 示例:锚句确认后注入
|
|
8
6
|
enabled: false
|
|
9
7
|
layer: pre-step
|
|
10
|
-
if:
|
|
11
|
-
all:
|
|
12
|
-
- phase:
|
|
13
|
-
promoted: true
|
|
14
|
-
includeSubagents: false
|
|
15
|
-
- anchor:
|
|
16
|
-
keys: []
|
|
17
|
-
fallbackAfter: 1
|
|
18
8
|
then:
|
|
19
|
-
- id:
|
|
9
|
+
- id: seed
|
|
20
10
|
kind: inject-text
|
|
21
11
|
config:
|
|
22
|
-
id: example-custom-fallback
|
|
12
|
+
id: example-custom-fallback-seed
|
|
23
13
|
layer: pre-step
|
|
24
|
-
strategy:
|
|
25
|
-
position:
|
|
14
|
+
strategy: static
|
|
15
|
+
position: after-user
|
|
26
16
|
dedupe: session
|
|
27
17
|
configKind: ordered
|
|
28
|
-
order:
|
|
18
|
+
order: 0
|
|
29
19
|
role: user
|
|
30
20
|
mergeMode: separate
|
|
31
21
|
sourceKind: plugin
|
|
32
22
|
form: notice
|
|
33
23
|
params:
|
|
34
|
-
text: "" #
|
|
35
|
-
|
|
24
|
+
text: "" # 自定义锚句,要求模型输出约定确认词
|
|
25
|
+
- if:
|
|
26
|
+
anchor:
|
|
27
|
+
subject: assistantReasoning
|
|
28
|
+
keys: [自定义确认词]
|
|
29
|
+
after:
|
|
30
|
+
action: seed
|
|
31
|
+
then:
|
|
32
|
+
- id: body
|
|
33
|
+
kind: inject-text
|
|
34
|
+
config:
|
|
35
|
+
id: example-custom-fallback-body
|
|
36
|
+
layer: pre-step
|
|
37
|
+
strategy: static
|
|
38
|
+
position: before-all
|
|
39
|
+
dedupe: session
|
|
40
|
+
configKind: ordered
|
|
41
|
+
order: 20
|
|
42
|
+
role: user
|
|
43
|
+
mergeMode: separate
|
|
44
|
+
sourceKind: plugin
|
|
45
|
+
form: notice
|
|
46
|
+
params:
|
|
47
|
+
text: "" # 自定义正文
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
# 模板:system-section 静态 system 段(缓存友好,静态内容优先放这里)
|
|
2
2
|
# order 参考:-100 身份 / 0 persona-prefix / 100-199 工具引导 / 10200 persona-suffix。
|
|
3
|
-
#
|
|
4
|
-
# deployment:persona-suffix(第一方指导之后)时注册为人设段
|
|
5
|
-
# (同名 shadow 全局 persona,模块列表显示「人设」徽标;子代理经 scope 链继承)。
|
|
3
|
+
# 自定义系统段使用自己的 sectionName;官方人设覆盖由独立 persona.main/subagent 卡管理。
|
|
6
4
|
# - complete: true 让本段成为唯一的 system prompt 段(身份注入、人设后缀、工具指南等
|
|
7
5
|
# 其余 system 段全部被抑制;工具链、运行时上下文与变量仍保留)。同一模块只能有一个,
|
|
8
6
|
# 且与顶层人设的「独占」互斥:写盘前由 bridge 拒绝(400),装配前另有一道兜底校验,
|
|
@@ -22,7 +20,6 @@ then:
|
|
|
22
20
|
mergeMode: merged
|
|
23
21
|
text: |
|
|
24
22
|
|
|
25
|
-
variables: {}
|
|
26
23
|
params:
|
|
27
24
|
complete: false
|
|
28
25
|
suppressRuntimeContext: false
|
|
@@ -5,13 +5,7 @@ if:
|
|
|
5
5
|
scope:
|
|
6
6
|
modelScope: flash
|
|
7
7
|
then:
|
|
8
|
-
- id:
|
|
9
|
-
kind:
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
layer: llm-stream
|
|
13
|
-
strategy: static
|
|
14
|
-
order: 0
|
|
15
|
-
text: "" # mode=replace 时替代整个模型流的文本
|
|
16
|
-
params:
|
|
17
|
-
mode: pass
|
|
8
|
+
- id: output
|
|
9
|
+
kind: stream-output
|
|
10
|
+
mode: pass
|
|
11
|
+
text: "" # mode=replace 时替代整个模型流的文本
|
|
@@ -1,19 +1,21 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
#
|
|
4
|
-
#
|
|
1
|
+
# 模板:tool-pipeline 工具行为策略
|
|
2
|
+
#
|
|
3
|
+
# 工具链拆成两个动作、两个执行点:
|
|
4
|
+
# - `tool-gate`(tools/pre-execute):allow / deny / ask,只读 decision / reason;
|
|
5
|
+
# - `tool-result`(tools/post-execute):accept / replace / block,只读 action / text。
|
|
6
|
+
# 工具名只在共享 names 条件声明。
|
|
7
|
+
# 写错相位的字段在编译期就是未知字段,不会静默失效。
|
|
5
8
|
id: example-tool-pipeline
|
|
6
9
|
layer: tool-pipeline
|
|
10
|
+
if:
|
|
11
|
+
names:
|
|
12
|
+
allow: [bash, run_code]
|
|
7
13
|
then:
|
|
8
14
|
- id: before
|
|
9
|
-
kind:
|
|
10
|
-
phase: pre
|
|
15
|
+
kind: tool-gate
|
|
11
16
|
decision: allow
|
|
12
|
-
toolNames: bash,run_code
|
|
13
17
|
reason: 该工具被提示词配置禁用
|
|
14
18
|
- id: after
|
|
15
|
-
kind:
|
|
16
|
-
phase: post
|
|
19
|
+
kind: tool-result
|
|
17
20
|
action: accept
|
|
18
|
-
toolNames: bash,run_code
|
|
19
21
|
text: ""
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# 模板:工具结果之后追加一条 durable user 通知。
|
|
2
|
+
#
|
|
3
|
+
# 与 `tool-result` 的分工:`tool-result` 改写的是**工具结果本身**(replace / block),
|
|
4
|
+
# `append-context` 不动结果,只在结果之后追加一条 user 角色通知。
|
|
5
|
+
# 需要模型**再做一步**时使用 `inject-text` 的 `turn-stop` 层(模板65),
|
|
6
|
+
# 每个来源(模块)每轮 1 次 / 每会话 3 次的上限由引擎内置,不能配置关闭(失控的续跑会把会话卡住)。
|
|
7
|
+
#
|
|
8
|
+
# 工具名条件统一用规则级或分支级 `if.names`(取自 exec.name)。
|
|
9
|
+
id: example-append-context
|
|
10
|
+
name: 工具结果后追加上下文
|
|
11
|
+
enabled: false
|
|
12
|
+
layer: tool-pipeline
|
|
13
|
+
if:
|
|
14
|
+
names:
|
|
15
|
+
allow:
|
|
16
|
+
- web_fetch
|
|
17
|
+
then:
|
|
18
|
+
- id: note-after-tool
|
|
19
|
+
kind: append-context
|
|
20
|
+
text: 网络结果可能已过期;引用它时说明来源与抓取时间。
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# 模板:前置步骤(agent/pre-step)注入过滤。
|
|
2
|
+
#
|
|
3
|
+
# 两种白名单模式**互斥**:
|
|
4
|
+
# - `sources`:严格白名单,只放行列表里的 `source.kind`,**同时作用于本批已领取的消息**。
|
|
5
|
+
# 漏一个 kind 就是静默删掉一段上下文(无告警、无计数),所以它只适合你**枚举过真实 kind**
|
|
6
|
+
# 的场合——`modules/skill-surface/module.yml` 就是这种用法(14 种 kind 的实测枚举)。
|
|
7
|
+
# - `keepKinds`:保留已领取基线的对象身份 + 这些 kind。实测它什么都不删(claimed 基线
|
|
8
|
+
# 的身份保留规则把所有消息都保住了),所以本模板不推荐它。
|
|
9
|
+
# 未声明任一模式 = 不注册、零开销。
|
|
10
|
+
#
|
|
11
|
+
# `blockPlugins` 是与两者**正交**的另一维度,可共存:仅当 `source.kind` 是插件来源时,
|
|
12
|
+
# 按 `source.plugin` 做大小写不敏感的**精确等值**匹配(不做子串 / 正则 / glob——要覆盖某个
|
|
13
|
+
# 插件就得写全名)。空名单 = 关闭,这与白名单「空 = 全拦」正好相反。
|
|
14
|
+
id: example-pre-step-filter
|
|
15
|
+
name: 前置步骤过滤(按插件屏蔽)
|
|
16
|
+
enabled: false
|
|
17
|
+
layer: pre-step
|
|
18
|
+
then:
|
|
19
|
+
- id: block-one-plugin
|
|
20
|
+
kind: pre-step-filter
|
|
21
|
+
blockPlugins:
|
|
22
|
+
- example-plugin
|
|
23
|
+
# sources: ['user', 'agent-instructions']
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# 模板:turn-stop 轮次停止层(命中条件时阻止本轮停止,强制模型续跑一步)
|
|
2
|
-
#
|
|
3
|
-
#
|
|
2
|
+
# 接入:条件写在规则 if(本模板用 text);turn-stop 不再有 config.subject/match。
|
|
3
|
+
# 续跑上限固定在引擎内——每个来源(模块)每轮 1 次 / 每会话 3 次,配置关不掉。
|
|
4
4
|
id: example-turn-stop
|
|
5
5
|
name: 未完成时强制续跑
|
|
6
6
|
layer: turn-stop
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# 模板:首轮向收件箱前置一条消息。
|
|
2
|
+
#
|
|
3
|
+
# `inbox-prepend` 走 `agent/inbox/inserted`(emit 通道,没有 next):命中即前置,
|
|
4
|
+
# 不命中什么都不做。缺省 `target: next-turn`,也可写 `next-step`。
|
|
5
|
+
# 插件来源的消息(含本动作自己插入的那条)永不再次前置,防自触发插队。
|
|
6
|
+
#
|
|
7
|
+
# 判「首轮」用 `session: { type: user/message, present: false }`——模型**当前可见**
|
|
8
|
+
# 的上下文里还没有 user/message 事件(判据按可见上下文,压缩遮蔽的历史不算数)。注意 `agent/inbox/inserted` 拿不到任务文本本身,所以别在这里
|
|
9
|
+
# 用 `text` 谓词筛任务内容(那是 `pre-step` 层的事,见 70-subagent-maintenance.yml)。
|
|
10
|
+
id: example-inbox-prepend
|
|
11
|
+
name: 首轮前置一条消息
|
|
12
|
+
enabled: false
|
|
13
|
+
layer: pre-step
|
|
14
|
+
if:
|
|
15
|
+
session:
|
|
16
|
+
type: user/message
|
|
17
|
+
present: false
|
|
18
|
+
then:
|
|
19
|
+
- id: prepend-first-turn
|
|
20
|
+
kind: inbox-prepend
|
|
21
|
+
target: next-turn
|
|
22
|
+
text: 动手之前先读工作区的 AGENTS.md,再决定改哪里。
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
# 模板:子代理状态 / 记忆维护(audience=subagent 专用注入)
|
|
2
2
|
# 用途:把 ST 的「角色状态跟踪 + 关系记忆」委派给子代理完成——引擎保持确定性
|
|
3
3
|
# (插值/匹配/注入),智能判断(何时更新、更新成什么)交给委派子代理,
|
|
4
|
-
#
|
|
5
|
-
#
|
|
4
|
+
# 写入经 module_variables 持久变量与 module_file_append 文件工具。
|
|
5
|
+
# 接入:声明 module-variable-tools、module-file-tools;默认关闭。
|
|
6
|
+
# 先在工作台的模块变量卡手动建立 stateKeys,例如「心情, 接受值, 关系进度」。
|
|
6
7
|
id: subagent-maintenance
|
|
7
8
|
name: 子代理状态/记忆维护
|
|
8
9
|
enabled: false
|
|
@@ -31,14 +32,12 @@ then:
|
|
|
31
32
|
value: subagent-maintenance
|
|
32
33
|
text: |-
|
|
33
34
|
你是本会话的「状态与记忆维护者」,与创作类子代理职责互补:
|
|
34
|
-
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
memory.md
|
|
35
|
+
- 状态(当前模块跨会话持久):观察互动中明确的角色状态变化。
|
|
36
|
+
先用 module_variables 的 scope=module、action=list 读取身份与版本,
|
|
37
|
+
再用 action=set 和显式字符串 value 更新下方清单中的变量;带回读取时
|
|
38
|
+
的 expectedModuleId 与 expectedRevisions,冲突时重读,不覆盖未知修改。
|
|
39
|
+
- 记忆(当前模块 memory.md):重要事实先用 module_file_read 核对(path 为 memory.md),
|
|
40
|
+
确有新增时用 module_file_append 追加(path 为 memory.md);记忆不会自动变成注入规则。
|
|
40
41
|
- 克制:仅在状态确实变化时更新;不确定时保留原值;不编造未发生的内容。
|
|
41
42
|
状态变量清单:{{stateKeys}}
|
|
42
|
-
variables:
|
|
43
|
-
stateKeys: 心情, 接受值, 关系进度
|
|
44
43
|
params: {}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# 模板:subagent-end 子代理结束层
|
|
2
2
|
# 默认仅记录。将 params.action 改为 inject-main 并填写 text,
|
|
3
3
|
# 通过官方 Agent.inject 向所属主会话投递上下文;不改写子代理结果、不唤醒空闲主会话。
|
|
4
|
-
#
|
|
5
|
-
#
|
|
4
|
+
# 接入:条件写在规则 if;subagent-end 不再有 config.subject/match。
|
|
5
|
+
# 载荷里没有稳定角色名,需要筛的时候按实际 runId 在 if 里写条件。
|
|
6
6
|
# 默认关闭:它只写日志,需要审计子代理收尾时再打开。
|
|
7
7
|
id: example-subagent-end
|
|
8
8
|
name: 子代理结束记录(只观察)
|
|
@@ -1,66 +1,50 @@
|
|
|
1
1
|
# 模板:工具面收窄(核心文件与任务集)+ 按需解锁
|
|
2
2
|
#
|
|
3
|
-
#
|
|
4
|
-
#
|
|
3
|
+
# `tool-visibility` 声明常驻集、目录与 SDK 正文的呈现、执行闸和发现来源。
|
|
4
|
+
# 首轮提示由同规则的普通注入动作组合;常驻名单只写一次。
|
|
5
5
|
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
6
|
+
# 本模板只带规则、不带 `modules` 声明:装配里没有提供方时 `bash` 就是缺失名,
|
|
7
|
+
# `requireMatch` 反过来把整条收窄废掉——用模板建模块时要自己把提供方行带进装配。
|
|
8
|
+
# 写错名字的后果很隐蔽:allow 里的名字不存在会触发 requireMatch 的 fail-open,
|
|
9
|
+
# 表现为「收窄没生效」而不是报错。
|
|
10
10
|
#
|
|
11
|
-
#
|
|
12
|
-
#
|
|
13
|
-
# ——唯一发现入口,模型靠它搜索并解锁。
|
|
14
|
-
# 2. `allowFrom`(engine/actions/assembly.mjs)——从历史 `tool/call` 参数回收解锁名单。
|
|
15
|
-
# 只挂插件不配 allowFrom 的话,解锁是**一次性的**(当次请求用完即被裁)。
|
|
16
|
-
#
|
|
17
|
-
# 工具名必须与**实际装配名**一致。本项目 harness 是 `pwsh`(不是 `bash`)、
|
|
18
|
-
# `edit` + `write`(不是 `str_replace_editor`)。写错名字有两个后果,都很隐蔽:
|
|
19
|
-
# - 写进 allow 的名字不存在 → `requireMatch` 触发 fail-open,**静默暴露完整目录**;
|
|
20
|
-
# - 该在的没写进去 → 该工具被裁掉,模型只能用别的方式硬凑。
|
|
21
|
-
#
|
|
22
|
-
# `requireMatch: true` 是刻意的:任一 allow 工具缺失(或模型解锁了一个不存在的名字)
|
|
23
|
-
# 就放弃裁剪、暴露完整目录。宁可多给上下文,也不静默裁成空目录——收窄错了会让当前
|
|
24
|
-
# 工作流调不到工具,那是比多花 token 严重得多的故障。
|
|
25
|
-
#
|
|
26
|
-
# **本模板走规则路径,不能声明 `waterfallPosition`**(那是声明 `triggers` 路径的字段,
|
|
27
|
-
# `compileRules` 会以 unknown fields 拒绝)。`assembly` 的改写发生在通道下游结算之后,
|
|
28
|
-
# 与相邻动作的先后由规则顺序与模块顺序决定。若确实需要 `outermost`(`prepend: true`,
|
|
29
|
-
# 保证本动作在普通注册之外先看到装配),改用声明路径(同 test/engine/declarations/
|
|
30
|
-
# tool-bootstrap.yml 的格式)而不是本模板。
|
|
11
|
+
# 发现适配器由 `tool-search` 行提供(模块必须列该行);解锁名从持久 `tool/call` 参数回收,
|
|
12
|
+
# 因此下一步请求即可见,压缩遮蔽后仍然保留。
|
|
31
13
|
id: tool-surface-resident
|
|
32
14
|
name: 工具面收窄(核心文件与任务集)
|
|
33
15
|
enabled: true
|
|
34
|
-
if:
|
|
35
|
-
# 覆盖全部相位。为什么不能只写 `phase: { promoteOn, includeSubagents }`:
|
|
36
|
-
# `promoted` 的缺省是 **true**(= 只匹配已晋升),不是「任意」;而 `compacted` 未声明才是
|
|
37
|
-
# 「不判该维度」(engine/conditions/phase.mjs:27-48)。更麻烦的是 `promoted: 'ignore'`
|
|
38
|
-
# 要求同时声明 `compacted`,而 `compacted` 只接受布尔值——**没有任何单节点组合能表达
|
|
39
|
-
# 「两个相位都命中」**,必须用 `any` 拼两支(phase.mjs:30-35 的注释正是在讲这个表达力边界)。
|
|
40
|
-
# 支 1 `promoted: true` → 已晋升(不论压缩与否)
|
|
41
|
-
# 支 2 `{compacted: true, promoted: false}` → 压缩后未晋升(受控相位的压缩回退)
|
|
42
|
-
# 未晋升且未压缩的**首轮不收窄**:与「首轮保全文」同一取舍——先让模型看到完整目录,
|
|
43
|
-
# 再随相位推进收窄。收窄的价值在于工具描述是**每请求固定开销**(实测 46894 字符),
|
|
44
|
-
# 而长会话必然进入上面两支,所以省下的正是大头。
|
|
45
|
-
any:
|
|
46
|
-
- phase: { promoteOn: either, includeSubagents: true, promoted: true }
|
|
47
|
-
- phase: { promoteOn: either, includeSubagents: true, compacted: true, promoted: false }
|
|
48
16
|
then:
|
|
49
17
|
- id: narrow-tools
|
|
50
|
-
kind:
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
18
|
+
kind: tool-visibility
|
|
19
|
+
allow:
|
|
20
|
+
- pwsh
|
|
21
|
+
- read
|
|
22
|
+
- write
|
|
23
|
+
- edit
|
|
24
|
+
- glob
|
|
25
|
+
- grep
|
|
26
|
+
- todo_write
|
|
27
|
+
- skill_search
|
|
28
|
+
- skill_load
|
|
29
|
+
- tool_search
|
|
30
|
+
# 平台各自的 bash 名:装配里没有提供方时这里就是缺失名,收窄整体失效。
|
|
31
|
+
- bash
|
|
32
|
+
discovery: { kind: tools }
|
|
33
|
+
# 任一常驻工具缺失就放弃裁剪、暴露完整目录(fail-open),避免静默裁成空目录。
|
|
34
|
+
requireMatch: true
|
|
35
|
+
- if:
|
|
36
|
+
count:
|
|
37
|
+
of: user-message
|
|
38
|
+
max: 1
|
|
39
|
+
then:
|
|
40
|
+
- id: discovery-notice
|
|
41
|
+
kind: inject-text
|
|
42
|
+
config:
|
|
43
|
+
layer: pre-step
|
|
44
|
+
strategy: placeholder
|
|
45
|
+
fill: tool-catalog
|
|
46
|
+
position: after-all
|
|
47
|
+
dedupe: session
|
|
48
|
+
text: 常驻工具:{{RESIDENT_TOOLS}}。缺少所需工具时,先用 {{DISCOVERY_TOOL}} 搜索并解锁。
|
|
49
|
+
params:
|
|
50
|
+
action: narrow-tools
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# 模块导入预览;保存模板时按实际工具目录补装 module-import-tools。
|
|
2
|
+
id: delegate-module-import
|
|
3
|
+
name: my_module_import_preview
|
|
4
|
+
description: 预览模块导入来源、降级报告与版本凭据
|
|
5
|
+
parameters:
|
|
6
|
+
files:
|
|
7
|
+
type: json
|
|
8
|
+
required: true
|
|
9
|
+
description: 文件数组,每项包含相对 path、content 和可选 encoding
|
|
10
|
+
output:
|
|
11
|
+
schema:
|
|
12
|
+
type: object
|
|
13
|
+
additionalProperties: true
|
|
14
|
+
properties:
|
|
15
|
+
ok: { type: boolean }
|
|
16
|
+
value: { type: json }
|
|
17
|
+
execute:
|
|
18
|
+
kind: delegate
|
|
19
|
+
tool: module_import
|
|
20
|
+
args:
|
|
21
|
+
files: '{{args.files}}'
|
|
22
|
+
preview: true
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# 完整规则读取;保存模板时补装 module-rule-tools。
|
|
2
|
+
id: delegate-module-rules-read
|
|
3
|
+
name: my_module_rules_read
|
|
4
|
+
description: 读取当前模块的完整规则树和版本
|
|
5
|
+
output:
|
|
6
|
+
schema:
|
|
7
|
+
type: object
|
|
8
|
+
additionalProperties: true
|
|
9
|
+
properties:
|
|
10
|
+
ok: { type: boolean }
|
|
11
|
+
value: { type: json }
|
|
12
|
+
execute:
|
|
13
|
+
kind: delegate
|
|
14
|
+
tool: module_rules_read
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# 持久变量读取;保存模板时补装 module-variable-tools。
|
|
2
|
+
id: delegate-module-variables
|
|
3
|
+
name: my_module_variables
|
|
4
|
+
description: 列出当前模块的有效持久变量、覆盖来源和版本
|
|
5
|
+
output:
|
|
6
|
+
schema:
|
|
7
|
+
type: object
|
|
8
|
+
additionalProperties: true
|
|
9
|
+
properties:
|
|
10
|
+
ok: { type: boolean }
|
|
11
|
+
value: { type: json }
|
|
12
|
+
execute:
|
|
13
|
+
kind: delegate
|
|
14
|
+
tool: module_variables
|
|
15
|
+
args:
|
|
16
|
+
scope: module
|
|
17
|
+
action: list
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# 完整规则事务;先读取规则和版本,只改需要的字段。
|
|
2
|
+
id: delegate-module-rules-edit
|
|
3
|
+
name: my_module_rules_edit
|
|
4
|
+
description: 按读取版本编辑当前模块的完整规则
|
|
5
|
+
parameters:
|
|
6
|
+
moduleId:
|
|
7
|
+
type: string
|
|
8
|
+
required: true
|
|
9
|
+
description: 读取时返回的模块身份
|
|
10
|
+
revisions:
|
|
11
|
+
type: json
|
|
12
|
+
required: true
|
|
13
|
+
description: 读取时返回的按域版本
|
|
14
|
+
edits:
|
|
15
|
+
type: json
|
|
16
|
+
required: true
|
|
17
|
+
description: 完整规则修改数组,整规则删除须显式 rule 为 null
|
|
18
|
+
output:
|
|
19
|
+
schema:
|
|
20
|
+
type: object
|
|
21
|
+
additionalProperties: true
|
|
22
|
+
properties:
|
|
23
|
+
ok: { type: boolean }
|
|
24
|
+
value: { type: json }
|
|
25
|
+
execute:
|
|
26
|
+
kind: delegate
|
|
27
|
+
tool: module_rules_edit
|
|
28
|
+
args:
|
|
29
|
+
expectedModuleId: '{{args.moduleId}}'
|
|
30
|
+
expectedRevisions: '{{args.revisions}}'
|
|
31
|
+
edits: '{{args.edits}}'
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { labelOf, toolNameSet } from './shared.mjs'
|
|
2
|
-
|
|
3
|
-
export function prepareDecision(action, plugin) {
|
|
4
|
-
const label = labelOf(action)
|
|
5
|
-
const names = toolNameSet(action.toolNames, plugin, `${label}.toolNames`)
|
|
6
|
-
const matchesTool = (exec) => names === undefined || names.has(exec?.name)
|
|
7
|
-
const hit = (exec, result) => typeof action.match !== 'function' || action.match(exec, result) === true
|
|
8
|
-
const phase = action.phase === undefined ? 'pre' : action.phase
|
|
9
|
-
if (!['pre', 'post'].includes(phase)) {
|
|
10
|
-
throw new TypeError(`${plugin}: ${label}.phase must be one of pre, post`)
|
|
11
|
-
}
|
|
12
|
-
if (phase === 'pre') {
|
|
13
|
-
const decision = action.decision ?? 'allow'
|
|
14
|
-
if (!['allow', 'deny', 'ask'].includes(decision)) {
|
|
15
|
-
throw new TypeError(`${plugin}: ${label}.decision must be one of allow, deny, ask`)
|
|
16
|
-
}
|
|
17
|
-
return (_ctx, { warnOnce, on, collect, take }) => collect(on('tools/pre-execute', async (exec, next) => {
|
|
18
|
-
try {
|
|
19
|
-
if (!matchesTool(exec) || !hit(exec)) return next()
|
|
20
|
-
if (decision === 'allow') return next()
|
|
21
|
-
const outcome = decision === 'deny'
|
|
22
|
-
? { kind: 'deny', reason: String(action.reason ?? `${label}: denied by action`) }
|
|
23
|
-
: { kind: 'ask' }
|
|
24
|
-
return take(exec) ? outcome : next()
|
|
25
|
-
} catch (error) {
|
|
26
|
-
warnOnce(`${plugin}: decision(pre) action ${label} failed: ${String(error?.message ?? error)}`)
|
|
27
|
-
return next()
|
|
28
|
-
}
|
|
29
|
-
}))
|
|
30
|
-
}
|
|
31
|
-
const postAction = action.action ?? 'accept'
|
|
32
|
-
if (!['accept', 'replace', 'block'].includes(postAction)) {
|
|
33
|
-
throw new TypeError(`${plugin}: ${label}.action must be one of accept, replace, block`)
|
|
34
|
-
}
|
|
35
|
-
const text = typeof action.text === 'string' ? action.text : ''
|
|
36
|
-
return (_ctx, { warnOnce, on, collect, take }) => collect(on('tools/post-execute', async (exec, result, next) => {
|
|
37
|
-
try {
|
|
38
|
-
if (!matchesTool(exec) || !hit(exec, result)) return next()
|
|
39
|
-
if (postAction === 'accept') return next()
|
|
40
|
-
if (postAction === 'replace' && text.length > 0) {
|
|
41
|
-
if (!take(exec)) return next()
|
|
42
|
-
return { kind: 'accept', content: [{ type: 'text', text }] }
|
|
43
|
-
}
|
|
44
|
-
if (postAction === 'block') {
|
|
45
|
-
if (!take(exec)) return next()
|
|
46
|
-
return { kind: 'block', feedback: [{ type: 'text', text: text.length > 0 ? text : `${label}: blocked by action` }] }
|
|
47
|
-
}
|
|
48
|
-
return next()
|
|
49
|
-
} catch (error) {
|
|
50
|
-
warnOnce(`${plugin}: decision(post) action ${label} failed: ${String(error?.message ?? error)}`)
|
|
51
|
-
return next()
|
|
52
|
-
}
|
|
53
|
-
}))
|
|
54
|
-
}
|
package/engine/actions/guard.mjs
DELETED
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import { labelOf, createMask, RUN_CODE } from './shared.mjs'
|
|
2
|
-
|
|
3
|
-
export function prepareGuard(action, plugin) {
|
|
4
|
-
const label = labelOf(action)
|
|
5
|
-
const mask = createMask(action.mask ?? action, `${label}.mask`, plugin)
|
|
6
|
-
const includeSubagents = action.includeSubagents === true
|
|
7
|
-
const reasonFor = (toolName) => String(action.reason ?? `${label}: tool ${JSON.stringify(toolName)} is denied by action`)
|
|
8
|
-
|
|
9
|
-
return (_ctx, { warnOnce, on, collect }) => {
|
|
10
|
-
/** session -> { ctx, disposers }:同一 agent.ctx 只注册一次,重绑后按新 ctx 重注册。 */
|
|
11
|
-
const appliedBySession = new WeakMap()
|
|
12
|
-
const states = new Set()
|
|
13
|
-
const releaseState = (state) => {
|
|
14
|
-
states.delete(state)
|
|
15
|
-
for (const dispose of state.disposers.splice(0)) {
|
|
16
|
-
try { dispose() } catch { /* 释放失败不得反过来打断卸载 */ }
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
const releaseAll = () => { for (const state of [...states]) releaseState(state) }
|
|
20
|
-
|
|
21
|
-
const applyTo = (agent) => {
|
|
22
|
-
const session = agent?.session
|
|
23
|
-
const scoped = agent?.ctx
|
|
24
|
-
if (session === undefined || scoped === undefined) return
|
|
25
|
-
// 受众不在本动作的裁决面内就不注册(子代理的 guard 由它自己的 assembly 决定;
|
|
26
|
-
// 万一父 guard 经 scope 链被走到,guard 体内的同一道受众判定仍然放行)。
|
|
27
|
-
const depth = session.header?.delegationDepth ?? 0
|
|
28
|
-
if (depth > 0 ? !includeSubagents : action.audience === 'subagent') return
|
|
29
|
-
const existing = appliedBySession.get(session)
|
|
30
|
-
if (existing !== undefined) {
|
|
31
|
-
// 预设切换/重绑会换掉 agent.ctx:旧 scope 的 guard 随旧 scope 失效,必须重注册。
|
|
32
|
-
if (existing.ctx === scoped) return
|
|
33
|
-
releaseState(existing)
|
|
34
|
-
appliedBySession.delete(session)
|
|
35
|
-
}
|
|
36
|
-
const tools = scoped.tools
|
|
37
|
-
if (tools === undefined || typeof tools.guard !== 'function') {
|
|
38
|
-
warnOnce(`${plugin}: guard action ${label} found no agent-scoped tools service — execution guard not registered`)
|
|
39
|
-
return
|
|
40
|
-
}
|
|
41
|
-
const state = { ctx: scoped, disposers: [] }
|
|
42
|
-
states.add(state)
|
|
43
|
-
appliedBySession.set(session, state)
|
|
44
|
-
const denials = {
|
|
45
|
-
...(mask.allow !== undefined ? { allow: [...mask.allow] } : {}),
|
|
46
|
-
...(mask.deny !== undefined ? { deny: [...mask.deny] } : {}),
|
|
47
|
-
}
|
|
48
|
-
// restrict 沿父 scope 链传播且不识别受众;只在子代理也受限时复用。
|
|
49
|
-
if (includeSubagents && typeof tools.restrict === 'function') {
|
|
50
|
-
try {
|
|
51
|
-
const dispose = tools.restrict(denials)
|
|
52
|
-
if (typeof dispose === 'function') state.disposers.push(dispose)
|
|
53
|
-
} catch (error) {
|
|
54
|
-
// restrict 只收继承面:本层/晚到工具不在它的可限制集合里,交给 guard 裁决。
|
|
55
|
-
warnOnce(`${plugin}: guard action ${label} restrict skipped (own-layer/late tools stay covered by the guard): ${String(error?.message ?? error)}`)
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
state.disposers.push(tools.guard((exec) => {
|
|
59
|
-
const toolName = exec?.name
|
|
60
|
-
if (toolName === RUN_CODE || typeof toolName !== 'string' || toolName.length === 0) return undefined
|
|
61
|
-
const depth = exec?.agent?.session?.header?.delegationDepth ?? 0
|
|
62
|
-
// 主子代理隔离:scope 注册之外再按受众判定一次(子代理 scope 可能挂在父链上)。
|
|
63
|
-
if (depth > 0 ? !includeSubagents : action.audience === 'subagent') return undefined
|
|
64
|
-
return mask.blocks(toolName) ? reasonFor(toolName) : undefined
|
|
65
|
-
}))
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
collect(releaseAll)
|
|
69
|
-
collect(on('system-prompt/assemble', async (assembly, context, next) => {
|
|
70
|
-
// Downstream errors propagate untouched; only this action's own logic is guarded.
|
|
71
|
-
const assembled = await next()
|
|
72
|
-
try {
|
|
73
|
-
applyTo(context?.agent)
|
|
74
|
-
} catch (error) {
|
|
75
|
-
warnOnce(`${plugin}: guard action ${label} failed to register: ${String(error?.message ?? error)}`)
|
|
76
|
-
}
|
|
77
|
-
return assembled
|
|
78
|
-
}))
|
|
79
|
-
}
|
|
80
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { labelOf, createMask } from './shared.mjs'
|
|
2
|
-
import { SDK_SECTION_NAME, sdkToolNames, stripSdkDeclarations } from '../sdk-strip.mjs'
|
|
3
|
-
|
|
4
|
-
export function prepareSdkStrip(action, plugin) {
|
|
5
|
-
const label = labelOf(action)
|
|
6
|
-
const mask = createMask(action.mask ?? action, `${label}.mask`, plugin)
|
|
7
|
-
return (_ctx, { warnOnce, on, collect, take }) => collect(on('system-prompt/assemble', async (assembly, context, next) => {
|
|
8
|
-
// Downstream errors propagate untouched; only this action's own logic is guarded.
|
|
9
|
-
const assembled = await next()
|
|
10
|
-
try {
|
|
11
|
-
if (!Array.isArray(assembled.sections)) return assembled
|
|
12
|
-
let changed = false
|
|
13
|
-
const sections = assembled.sections.map((section) => {
|
|
14
|
-
if (section?.name !== SDK_SECTION_NAME || typeof section.text !== 'string') return section
|
|
15
|
-
const names = mask.allow === undefined
|
|
16
|
-
? mask.deny
|
|
17
|
-
: new Set([...sdkToolNames(section.text)].filter((toolName) => mask.blocks(toolName)))
|
|
18
|
-
if (names === undefined || names.size === 0) return section
|
|
19
|
-
const stripped = stripSdkDeclarations(section.text, names)
|
|
20
|
-
if (stripped === section.text) return section
|
|
21
|
-
changed = true
|
|
22
|
-
return { ...section, text: stripped }
|
|
23
|
-
})
|
|
24
|
-
return changed && take(context) ? { ...assembled, sections } : assembled
|
|
25
|
-
} catch (error) {
|
|
26
|
-
warnOnce(`${plugin}: sdk-strip action ${label} failed, keeping the original SDK text: ${String(error?.message ?? error)}`)
|
|
27
|
-
return assembled
|
|
28
|
-
}
|
|
29
|
-
}))
|
|
30
|
-
}
|