@morlay/dsh-context-assembler 0.0.1-alpha.2 → 0.0.1-alpha.4
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 +59 -32
- package/dist/{agent-instructions-BNEiZl0P.mjs → agent-instructions-CIgUVIeo.mjs} +36 -1
- package/dist/agent-instructions.mjs +1 -1
- package/dist/{assembler-_F9urbPj.mjs → assembler-CDMIBAi8.mjs} +18 -6
- package/dist/assembler.d.mts +1 -1
- package/dist/assembler.mjs +1 -1
- package/dist/{index-BGkeEaQA.d.mts → index-zhmD45A9.d.mts} +21 -4
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +3 -3
- package/dist/rows.d.mts +13 -11
- package/dist/rows.mjs +15 -10
- package/dist/scope.d.mts +33 -39
- package/dist/scope.mjs +102 -2
- package/dist/skill-catalog.d.mts +7 -0
- package/dist/skill-catalog.mjs +29 -7
- package/locale/en.json +1 -1
- package/locale/zh.json +1 -1
- package/package.json +37 -39
- package/src/agent-instructions/index.ts +6 -2
- package/src/agent-instructions/preset-owner.ts +70 -0
- package/src/assembler/channel.ts +34 -10
- package/src/assembler/reminder.ts +12 -3
- package/src/index.ts +5 -5
- package/src/rows.ts +14 -13
- package/src/scope/index.ts +131 -99
- package/src/skill-catalog/index.ts +44 -18
- package/cordis.patch.yml +0 -9
- package/dist/scope-CI-fNq5A.mjs +0 -104
- package/tool/patch.ts +0 -43
package/README.md
CHANGED
|
@@ -5,13 +5,13 @@
|
|
|
5
5
|
见 [`src/rows.ts` 的 `contextChannel()`](./src/rows.ts)。引用展开原先也在这个包里,
|
|
6
6
|
现在独立成 [`@morlay/dsh-reference`](../dsh-reference/README.md)(它只挂 `agent/pre-step`、不依赖通道)。
|
|
7
7
|
|
|
8
|
-
| 出口 | 行 id / 插件 name | 做什么
|
|
9
|
-
| ---------------------- | --------------------------------------------------------- |
|
|
10
|
-
| `.` | `context-assembler`(插件 name `context-assembler-tree`) | **组装出口**:按 config 决定装哪些能力、各带什么参数(缺省即四套能力)
|
|
11
|
-
| `./assembler` | `context-assembler` | 注入通道:唯一渲染者与唯一覆盖判定处,发布 `ctx.contextAssembler`
|
|
12
|
-
| `./agent-instructions` | `context-agent-instructions` | 工作区指令链(`$DSH_HOME/AGENTS.md` + 项目根到 cwd 逐级)
|
|
13
|
-
| `./skill-catalog` | `context-skill-catalog` | skill 目录规则块 + 模型侧 `skill` 工具
|
|
14
|
-
| `./scope` | `context-scope`
|
|
8
|
+
| 出口 | 行 id / 插件 name | 做什么 |
|
|
9
|
+
| ---------------------- | --------------------------------------------------------- | ---------------------------------------------------------------------------- |
|
|
10
|
+
| `.` | `context-assembler`(插件 name `context-assembler-tree`) | **组装出口**:按 config 决定装哪些能力、各带什么参数(缺省即四套能力) |
|
|
11
|
+
| `./assembler` | `context-assembler` | 注入通道:唯一渲染者与唯一覆盖判定处,发布 `ctx.contextAssembler` |
|
|
12
|
+
| `./agent-instructions` | `context-agent-instructions` | 工作区指令链(`$DSH_HOME/AGENTS.md` + 项目根到 cwd 逐级) |
|
|
13
|
+
| `./skill-catalog` | `context-skill-catalog` | skill 目录规则块 + 模型侧 `skill` 工具 |
|
|
14
|
+
| `./scope` | `context-assembler-scope` | 按会话收口:工具白名单、instruction 总开关、动态快照开关(模式把定义推给它) |
|
|
15
15
|
|
|
16
16
|
规则、id 表与分层的 home 在 [上下文注入规则](./.agents/designs/20260921-上下文注入规则.md);术语见
|
|
17
17
|
[本包 CONTEXT](./.agents/CONTEXT.md)。
|
|
@@ -23,17 +23,21 @@
|
|
|
23
23
|
([`@morlay/dsh-agent-toolkit`](../../profile/dsh-agent-toolkit/README.md) 的 `guidance`)这类消费者住在别的包里,
|
|
24
24
|
隔离会把它们挡在组外(行停在 waiting,不报错);理由见
|
|
25
25
|
[ADR 通道作为全局服务装配不隔离](./.agents/adrs/20260923-通道作为全局服务装配不隔离.md)。`scope` **不在这份 patch 里**
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
——它是模式那一层的收口行,由 [`@morlay/dsh-session-mode`](../../profile/dsh-session-mode/README.md) 的 patch 与模式定义
|
|
27
|
+
一起装(行 id 与 name 归本包的 `scopeRow()`,单一 home)。
|
|
28
|
+
|
|
29
|
+
装一次不等于每次都注入:这两条面各自按**会话**判归谁——`agent-instructions` 在预设自带那一行时**让位**,
|
|
30
|
+
`skill-catalog` 反过来把同名工具注册进 agent 自己那一层**抢面**(见下面两节)。所以 `capabilities` 不在装配期
|
|
31
|
+
按模式裁。
|
|
28
32
|
|
|
29
33
|
工具说明(汉化 / 精简 / 用法分组)也不在这里:它归
|
|
30
34
|
[`@morlay/dsh-agent-toolkit`](../../profile/dsh-agent-toolkit/README.md),同样在 profile 平面装一次。
|
|
31
35
|
|
|
32
36
|
## 装配形态
|
|
33
37
|
|
|
34
|
-
本包是 bundle:`cordis.patch.yml` 由 [`
|
|
35
|
-
`rows` 出口导出同一份清单。`dsh.profile.bundles`
|
|
36
|
-
|
|
38
|
+
本包是 bundle:`cordis.patch.yml` 由 [`src/rows.ts`](./src/rows.ts) 从 [`src/rows.ts`](./src/rows.ts) 渲染,
|
|
39
|
+
`rows` 出口导出同一份清单。`dsh.profile.bundles` 列出本包即装一次,**服务全局共享、不隔离**;模式的收口是
|
|
40
|
+
另一行(`scopeRow()`:工具白名单 / instruction / 动态快照),别的包的行(工具说明、skill 目录)直接 `inject`
|
|
37
41
|
同一份通道。
|
|
38
42
|
|
|
39
43
|
## 为什么合成一个包
|
|
@@ -47,7 +51,7 @@
|
|
|
47
51
|
全局通道)。本包只做上下文重排。
|
|
48
52
|
|
|
49
53
|
引用展开不住在这里:它不依赖 `ctx.contextAssembler`(`inject` 只有 `skills`),也没有「读文件 + 字节预算」
|
|
50
|
-
以外与组装出口共享的东西,所以独立成包、由 [`@morlay/better-session`](../../
|
|
54
|
+
以外与组装出口共享的东西,所以独立成包、由 [`@morlay/better-session`](../../bundles/better-session/cordis.patch.yml)
|
|
51
55
|
装配(见 [ADR-引用展开拆成独立包](../../../.agents/adrs/20260923-引用展开拆成独立包并按profile装配.md))。
|
|
52
56
|
|
|
53
57
|
**每个出口仍是独立的 cordis 插件**(各自的 `apply` 与 `inject`)——这一点是硬要求:合成单入口会让 `inject`
|
|
@@ -70,7 +74,7 @@ user 消息注入(每条按文本幂等,只有变化的那条重发)。
|
|
|
70
74
|
| `hiddenSkills(visible)` | 声明了 `requires` 而入口工具一个都不可见的 skill 名 |
|
|
71
75
|
|
|
72
76
|
配置(`keep` / `suppress` / `replace`)的默认值在 [`src/assembler/defaults.ts`](./src/assembler/defaults.ts)。
|
|
73
|
-
**全局一份、不隔离**:模式差异由 `context-scope` 登记(`setInstructions` / `restrictTools`)收口,跨包的
|
|
77
|
+
**全局一份、不隔离**:模式差异由 `context-assembler-scope` 登记(`setInstructions` / `restrictTools`)收口,跨包的
|
|
74
78
|
消费者(工具说明、技能目录)直接 `inject` 同一份通道(见
|
|
75
79
|
[ADR 通道作为全局服务装配不隔离](./.agents/adrs/20260923-通道作为全局服务装配不隔离.md))。
|
|
76
80
|
|
|
@@ -79,23 +83,42 @@ user 消息注入(每条按文本幂等,只有变化的那条重发)。
|
|
|
79
83
|
`$DSH_HOME/AGENTS.md` 加项目根到 cwd 的逐级 `AGENTS.md` / `AGENTS.local.md`,**一条文件一条 id**
|
|
80
84
|
(`agent-instructions:<根标识>:<文件>`,根标识是根目录的 8 位摘要——同进程两个项目根的同名文件因此不会互相
|
|
81
85
|
顶掉),文件变化时只重发变了的那一份。取代上游 `@deepseek-ai/dsh-agent-instructions`(host 那行由上游
|
|
82
|
-
web-app bundle
|
|
86
|
+
web-app bundle 自己设在装配层;我们那份由本包的组装出口在 profile 平面装)——**在该会话的 preset 行清单没有
|
|
87
|
+
上游那一行时**。
|
|
83
88
|
|
|
89
|
+
- **preset 自带那一行时让位**:官方 `standard` / `ptc` / `cordis` 的 preset 行清单里有
|
|
90
|
+
`@deepseek-ai/dsh-agent-instructions`(`minimal` 没有),装上的会话由 preset 侧注入,这一条一条都不注入;
|
|
91
|
+
`chat` 挂的 `minimal` 会话仍由我们提供。判据与理由见
|
|
92
|
+
[ADR-工作区指令让位skill面由通道抢面](./.agents/adrs/20260929-工作区指令让位skill面由通道抢面.md)。
|
|
84
93
|
- **不跟踪 `read`/`write`/`edit`**:上游靠 touch 上浮触发刷新;本部署的 `AGENTS.md` 几乎不变,按
|
|
85
94
|
`mtime:size` 对账足够。
|
|
86
95
|
- **超预算可见**:单文件超过 `maxBytes` 时截断并留一行提示,不静默丢内容。
|
|
87
96
|
- **与上游的 baseline 认领对齐**:`source` 带 `kind: "agent-instructions"` + `baseline: true` +
|
|
88
|
-
`baselineIdentity`(身份与上游 `workspaceBaselineIdentity`
|
|
89
|
-
|
|
90
|
-
|
|
97
|
+
`baselineIdentity`(身份与上游 `workspaceBaselineIdentity` 逐字相等)。上游的认领判据只看本步 claimed 的
|
|
98
|
+
消息与会话 surface,所以它救不了首步两侧同时注入(那由让位管),但管得住另一件事:**我们注入过基线的历史
|
|
99
|
+
会话在 preset 会话里恢复时**,上游认得出那条、不再补一份自己的模板("Use them as guidance…")。
|
|
91
100
|
- 配置:`instructionFileCandidates` / `localInstructionFileCandidates`(覆盖成只读 `AGENTS*`,不含 CLAUDE
|
|
92
101
|
系列)、`maxBytes`(65536)、`dshHome`。
|
|
93
102
|
|
|
94
103
|
## skill-catalog
|
|
95
104
|
|
|
96
105
|
`skill-catalog` 规则块(`<available_skills>`,一行 `名字: 摘要`,只列模型可调用的 skill)加模型侧 `skill`
|
|
97
|
-
工具。取代上游 `@deepseek-ai/dsh-tool-skill`(`skill-filesystem` 保留——它提供 skill
|
|
98
|
-
|
|
106
|
+
工具。取代上游 `@deepseek-ai/dsh-tool-skill`(`skill-filesystem` 保留——它提供 skill 发现)。目录变更走同 id
|
|
107
|
+
覆盖;`auto` 的 skill 不进目录(正文已随提示送达)。
|
|
108
|
+
|
|
109
|
+
**这一面归通道**(工作区指令那一面相反,是让位):`skill` 工具按**会话**注册进 agent 自己那一层,最近的一层
|
|
110
|
+
赢,遮蔽 preset 那份;上游的目录发布判据是"它自己注册的那个工具是本会话可见的那个",被遮蔽之后它不发目录,
|
|
111
|
+
目录由我们发布。要点:
|
|
112
|
+
|
|
113
|
+
- 目录那条注入消息的 **kind 是我们自己的**(`context-assembler` + `form: "catalog"` + `entries`)。上游把任何
|
|
114
|
+
`kind: "skill-catalog"` 且条目可读的消息当成它自己的账本:kind 用它的,它会在首步删掉我们这条、在有可见
|
|
115
|
+
目录之后补一条"没有可用 skill"把目录顶掉(它文档里的 visibility-loss 语义)。`form` 与 `entries` 照旧,
|
|
116
|
+
客户端那张条目表不受影响;注入行的标签变成 `context-assembler`。
|
|
117
|
+
- 按会话注册随 agent 收回;这一行重挂(HMR / 设置面)时不再重复注册同一份定义。
|
|
118
|
+
- `chat`(挂 `minimal`,没有上游那一行):工具与目录同样是我们提供的,但它的模式定义不收这两样
|
|
119
|
+
(`instructions: false`、白名单里没有 `skill`)——白名单把它挡在模型目录外,执行层 guard 拒绝调用。
|
|
120
|
+
|
|
121
|
+
取舍与上游判据见 [ADR-工作区指令让位skill面由通道抢面](./.agents/adrs/20260929-工作区指令让位skill面由通道抢面.md)。
|
|
99
122
|
|
|
100
123
|
## 工具说明(不在这个包里)
|
|
101
124
|
|
|
@@ -105,10 +128,16 @@ web-app bundle 自己设在 preset 平面)。
|
|
|
105
128
|
|
|
106
129
|
## scope
|
|
107
130
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
131
|
+
按会话收口的出口(行 id `context-assembler-scope`):工具白名单(装配期投影 + 执行层 guard + 与工具同源的
|
|
132
|
+
`tool:<工具名>` 说明 section,三侧同判据)、`instructions`(关掉一切 instruction 类送达:常驻组正文、规则块
|
|
133
|
+
与降级 section;按需 skill 与 `@` 引用材料不受它管)、`runtimeContext`
|
|
134
|
+
(关掉沙箱 / 审批那两条动态快照,按 scope 抑制)。
|
|
135
|
+
|
|
136
|
+
**定义由消费方推给它**,它自己不认识"模式":`ctx.sessionToolScope.apply(agent, mode)` 是唯一入口,落在该
|
|
137
|
+
agent 的 `ctx` 上(抑制器、guard 都在那里),同一个 agent 再 apply 一次就是换一份——旧的 effect 树收回、按新
|
|
138
|
+
的装一遍。它解决的是"模式只能决定加什么、管不了 host 平面":`dsh.profile.bundles` 打开的包(工具行、
|
|
139
|
+
实验性的 Agent Teams)在 host 平面插行,对所有会话一视同仁;模式要表达"我只有这几个工具、一条提示词都不要"
|
|
140
|
+
时,唯一与来源无关的做法是在会话语义上收口。
|
|
112
141
|
|
|
113
142
|
白名单同时登记给通道(`restrictTools`):技能目录与用法组正文按 `visibleTools` 收口,所以被收窄的工具既不在
|
|
114
143
|
目录、也不会被讲——注册表里"装着"不等于这个会话"能用"。
|
|
@@ -125,15 +154,12 @@ scope 抑制)。它解决的是"preset 只能决定加什么、管不了 host
|
|
|
125
154
|
capabilities: [assembler, agent-instructions, skill-catalog]
|
|
126
155
|
```
|
|
127
156
|
|
|
128
|
-
|
|
157
|
+
**模式平面**:收口那一行(不带 config——模式定义在 `session-mode` 行的 `config.modes` 里)由
|
|
158
|
+
[`@morlay/dsh-session-mode`](../../profile/dsh-session-mode/README.md) 的 patch 装,通道由 profile 那份共享:
|
|
129
159
|
|
|
130
160
|
```yaml
|
|
131
|
-
- id: context-scope
|
|
161
|
+
- id: context-assembler-scope
|
|
132
162
|
name: "@morlay/dsh-context-assembler/scope"
|
|
133
|
-
config:
|
|
134
|
-
allowTools: [ask_user_question, web_search, web_fetch]
|
|
135
|
-
instructions: false
|
|
136
|
-
runtimeContext: false
|
|
137
163
|
```
|
|
138
164
|
|
|
139
165
|
几点硬要求:
|
|
@@ -141,9 +167,10 @@ scope 抑制)。它解决的是"preset 只能决定加什么、管不了 host
|
|
|
141
167
|
- **每个能力仍是独立的 cordis 插件**(组装出口只是 `ctx.plugin()` 装它们),各自带自己的 `inject`;合成单入口会让
|
|
142
168
|
`inject` 变并集,一个可选搭档缺席就拖垮整包。
|
|
143
169
|
- **通道不做隔离**:消费者跨包(`@morlay/dsh-agent-toolkit` 的工具说明、本包的技能目录),隔离会把它们挡在组外
|
|
144
|
-
(行停在 waiting);模式差异改由 `context-scope` 登记给通道,见
|
|
170
|
+
(行停在 waiting);模式差异改由 `context-assembler-scope` 登记给通道,见
|
|
145
171
|
[ADR 通道作为全局服务装配不隔离](./.agents/adrs/20260923-通道作为全局服务装配不隔离.md)。真装配的判据是
|
|
146
|
-
`pnpm exec tsx packages/desktop/dsh-desktop-host/tool/verify-
|
|
172
|
+
`pnpm exec tsx packages/desktop/dsh-desktop-host/tool/verify-session-mode.mts`(装配层可见一份、收口行装上、
|
|
173
|
+
官方 agent preset 不在)。
|
|
147
174
|
- **子出口仍可单独装配**(`@morlay/dsh-context-assembler/assembler` 等):同一些插件,只是默认走组装出口。
|
|
148
175
|
|
|
149
176
|
## 维护注意
|
|
@@ -121,6 +121,40 @@ async function baselineIdentity(cwd) {
|
|
|
121
121
|
});
|
|
122
122
|
}
|
|
123
123
|
//#endregion
|
|
124
|
+
//#region src/agent-instructions/preset-owner.ts
|
|
125
|
+
/** 上游那一行的模块名:与 `presets/*.patch.yml` 里写的一字不差。 */
|
|
126
|
+
const UPSTREAM_MODULE = "@deepseek-ai/dsh-agent-instructions";
|
|
127
|
+
/** 会话 → 它当前的 preset。preset 变了(空白窗口里换 preset)就整份重算。 */
|
|
128
|
+
const decided = /* @__PURE__ */ new WeakMap();
|
|
129
|
+
/**
|
|
130
|
+
* 该会话的 preset 自己提供了工作区指令这一面吗。
|
|
131
|
+
* @param ctx - 能解析到注册表的上下文(能力自己的 apply ctx)。
|
|
132
|
+
* @param agent - 要判的会话。
|
|
133
|
+
* @returns 行清单里有上游那一行且它是启用的。
|
|
134
|
+
*/
|
|
135
|
+
function presetOwnsInstructions(ctx, agent) {
|
|
136
|
+
const registry = registryOf(ctx);
|
|
137
|
+
if (registry === void 0) return Promise.resolve(false);
|
|
138
|
+
const preset = registry.composedPreset(agent.ctx);
|
|
139
|
+
if (preset === void 0) return Promise.resolve(false);
|
|
140
|
+
const cached = decided.get(agent);
|
|
141
|
+
if (cached?.preset === preset) return cached.owns;
|
|
142
|
+
const owns = registry.compositionInventory().then((inventory) => inventory.some((composition) => composition.id === preset && composition.rows.some((row) => row.moduleName === UPSTREAM_MODULE && row.enabled === true))).catch(() => false);
|
|
143
|
+
decided.set(agent, {
|
|
144
|
+
preset,
|
|
145
|
+
owns
|
|
146
|
+
});
|
|
147
|
+
return owns;
|
|
148
|
+
}
|
|
149
|
+
/** 注册表可能压根没装(没有 preset 的部署形态);`ctx.get` 在不提供时读到 undefined。 */
|
|
150
|
+
function registryOf(ctx) {
|
|
151
|
+
try {
|
|
152
|
+
return ctx.get("agentPresets");
|
|
153
|
+
} catch {
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
//#endregion
|
|
124
158
|
//#region src/agent-instructions/index.ts
|
|
125
159
|
var agent_instructions_exports = /* @__PURE__ */ __exportAll({
|
|
126
160
|
Config: () => Config$1,
|
|
@@ -170,7 +204,8 @@ function apply(ctx, config) {
|
|
|
170
204
|
baselineIdentity: identity,
|
|
171
205
|
changes: []
|
|
172
206
|
}),
|
|
173
|
-
text: (target) => {
|
|
207
|
+
text: async (target) => {
|
|
208
|
+
if (await presetOwnsInstructions(ctx, target)) return "";
|
|
174
209
|
const current = chains.get(target);
|
|
175
210
|
if (current === void 0 || !current.files.some((entry) => entry.path === file.path)) return "";
|
|
176
211
|
return readInstruction(file, cache, maxBytes);
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as name, i as inject, r as apply, t as Config } from "./agent-instructions-
|
|
1
|
+
import { a as name, i as inject, r as apply, t as Config } from "./agent-instructions-CIgUVIeo.mjs";
|
|
2
2
|
export { Config, apply, inject, name };
|
|
@@ -13,7 +13,7 @@ const REMINDER_CLOSE = "</system-reminder>";
|
|
|
13
13
|
const RULES_SECTION = "assembler:rules";
|
|
14
14
|
/**
|
|
15
15
|
* 这条消息是不是通道注入的条目——判据是 source 里的幂等键,而不是 kind:接管上游那两面的条目
|
|
16
|
-
*
|
|
16
|
+
* 接管工作区指令那一面的条目用上游 kind(`agent-instructions`),幂等必须照样认。
|
|
17
17
|
*/
|
|
18
18
|
function promptEntryIdOf(source) {
|
|
19
19
|
const id = source.id;
|
|
@@ -53,7 +53,7 @@ function latestReminderText(agent, id) {
|
|
|
53
53
|
}
|
|
54
54
|
/**
|
|
55
55
|
* 注入一条提醒:`text` 是已渲染好的完整正文(规则块或内容块),`key` 是它的幂等键。
|
|
56
|
-
* `source`
|
|
56
|
+
* `source` 声明这条消息对外的身份——工作区指令那一面用上游 kind,我们自己的条目留默认。
|
|
57
57
|
*/
|
|
58
58
|
function reminderMessage(key, text, source) {
|
|
59
59
|
return createUserMessage({
|
|
@@ -89,7 +89,10 @@ var ContextAssembler = class extends Service {
|
|
|
89
89
|
suppressed = /* @__PURE__ */ new Set();
|
|
90
90
|
skills = /* @__PURE__ */ new Map();
|
|
91
91
|
states = /* @__PURE__ */ new WeakMap();
|
|
92
|
-
/**
|
|
92
|
+
/**
|
|
93
|
+
* 不要 instruction 类注入的会话(模式说了 `instructions: false`):常驻正文、规则块与降级 section 都不进。
|
|
94
|
+
* 按需 skill 不受它管(那是模型自己加载),引用材料也不经通道。
|
|
95
|
+
*/
|
|
93
96
|
withoutInstructions = /* @__PURE__ */ new WeakSet();
|
|
94
97
|
/** 本会话的模式收窄(白名单):投影层的过滤不碰注册表,注册表上看不出"谁能用"。 */
|
|
95
98
|
toolScopes = /* @__PURE__ */ new WeakMap();
|
|
@@ -137,7 +140,7 @@ var ContextAssembler = class extends Service {
|
|
|
137
140
|
* 本步要注入的条目:键 → 已渲染好的正文(规则块或内容块)。
|
|
138
141
|
* `sections` 来自本步装配,`rules` 与 `auto` skill 正文在这里现算。
|
|
139
142
|
*/
|
|
140
|
-
/**
|
|
143
|
+
/** 这个会话要不要 instruction 类注入(模式说了 `instructions: false` 就是不要,见 {@link withoutInstructions})。 */
|
|
141
144
|
setInstructions(agent, on) {
|
|
142
145
|
if (on) this.withoutInstructions.delete(agent);
|
|
143
146
|
else this.withoutInstructions.add(agent);
|
|
@@ -179,14 +182,23 @@ var ContextAssembler = class extends Service {
|
|
|
179
182
|
contentFor(name, agent) {
|
|
180
183
|
return this.declarations.get(name)?.content(agent);
|
|
181
184
|
}
|
|
185
|
+
/** 一个 skill 在这个会话能不能被用到:声明了 `requires` 时至少一个工具在模式收窄内。 */
|
|
186
|
+
reachable(declaration, scope) {
|
|
187
|
+
const requires = declaration.requires;
|
|
188
|
+
if (requires === void 0 || requires.length === 0) return true;
|
|
189
|
+
if (scope === void 0) return true;
|
|
190
|
+
return requires.some((tool) => scope(tool));
|
|
191
|
+
}
|
|
182
192
|
async collect(agent) {
|
|
183
193
|
const entries = /* @__PURE__ */ new Map();
|
|
184
|
-
|
|
194
|
+
const scope = this.toolScopes.get(agent);
|
|
195
|
+
const instructionsOff = this.withoutInstructions.has(agent);
|
|
196
|
+
if (!instructionsOff) for (const declaration of this.declarations.values()) {
|
|
185
197
|
if ((declaration.injection ?? "on-demand") !== "auto") continue;
|
|
198
|
+
if (!this.reachable(declaration, scope)) continue;
|
|
186
199
|
const body = declaration.content(agent);
|
|
187
200
|
if (body.length > 0) entries.set(declaration.name, { text: renderVirtualSkill(declaration.name, body) });
|
|
188
201
|
}
|
|
189
|
-
const instructionsOff = this.withoutInstructions.has(agent);
|
|
190
202
|
for (const declaration of this.rules.values()) {
|
|
191
203
|
if (instructionsOff) break;
|
|
192
204
|
const text = await withTimeout(declaration.text(agent), CONTENT_TIMEOUT_MS);
|
package/dist/assembler.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as name, c as InjectionMode, d as PromptSkillDeclaration, f as DEFAULT_KEEP, i as inject, l as PromptEntry, m as DEFAULT_SUPPRESS, n as apply, o as renderVirtualSkill, p as DEFAULT_REPLACE, s as ContextAssembler, t as Config, u as PromptRuleDeclaration } from "./index-
|
|
1
|
+
import { a as name, c as InjectionMode, d as PromptSkillDeclaration, f as DEFAULT_KEEP, i as inject, l as PromptEntry, m as DEFAULT_SUPPRESS, n as apply, o as renderVirtualSkill, p as DEFAULT_REPLACE, s as ContextAssembler, t as Config, u as PromptRuleDeclaration } from "./index-zhmD45A9.mjs";
|
|
2
2
|
export { Config, ContextAssembler, DEFAULT_KEEP, DEFAULT_REPLACE, DEFAULT_SUPPRESS, type InjectionMode, type PromptEntry, type PromptRuleDeclaration, type PromptSkillDeclaration, apply, inject, name, renderVirtualSkill };
|
package/dist/assembler.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as name, c as DEFAULT_SUPPRESS, i as inject, l as ContextAssembler, n as apply, o as DEFAULT_KEEP, s as DEFAULT_REPLACE, t as Config, u as renderVirtualSkill } from "./assembler-
|
|
1
|
+
import { a as name, c as DEFAULT_SUPPRESS, i as inject, l as ContextAssembler, n as apply, o as DEFAULT_KEEP, s as DEFAULT_REPLACE, t as Config, u as renderVirtualSkill } from "./assembler-CDMIBAi8.mjs";
|
|
2
2
|
export { Config, ContextAssembler, DEFAULT_KEEP, DEFAULT_REPLACE, DEFAULT_SUPPRESS, apply, inject, name, renderVirtualSkill };
|
|
@@ -68,7 +68,7 @@ interface PromptRuleDeclaration {
|
|
|
68
68
|
readonly id: string;
|
|
69
69
|
readonly text: (agent: Agent) => string | Promise<string>;
|
|
70
70
|
/**
|
|
71
|
-
*
|
|
71
|
+
* 这条规则的对外身份。工作区指令那一面按上游 kind 发消息(skill 面相反,用我们自己的 kind),好让按 kind 认领的
|
|
72
72
|
* 消费方(客户端标签、上游的实验性约束收集)认得出来;不声明就是通道自己的 `context-assembler`。
|
|
73
73
|
* 幂等键仍是 `id`(`reminderMessage` 会把它塞进 source)。
|
|
74
74
|
*/
|
|
@@ -96,7 +96,10 @@ declare class ContextAssembler extends Service {
|
|
|
96
96
|
private readonly suppressed;
|
|
97
97
|
private readonly skills;
|
|
98
98
|
private readonly states;
|
|
99
|
-
/**
|
|
99
|
+
/**
|
|
100
|
+
* 不要 instruction 类注入的会话(模式说了 `instructions: false`):常驻正文、规则块与降级 section 都不进。
|
|
101
|
+
* 按需 skill 不受它管(那是模型自己加载),引用材料也不经通道。
|
|
102
|
+
*/
|
|
100
103
|
private readonly withoutInstructions;
|
|
101
104
|
/** 本会话的模式收窄(白名单):投影层的过滤不碰注册表,注册表上看不出"谁能用"。 */
|
|
102
105
|
private readonly toolScopes;
|
|
@@ -113,7 +116,7 @@ declare class ContextAssembler extends Service {
|
|
|
113
116
|
* 本步要注入的条目:键 → 已渲染好的正文(规则块或内容块)。
|
|
114
117
|
* `sections` 来自本步装配,`rules` 与 `auto` skill 正文在这里现算。
|
|
115
118
|
*/
|
|
116
|
-
/**
|
|
119
|
+
/** 这个会话要不要 instruction 类注入(模式说了 `instructions: false` 就是不要,见 {@link withoutInstructions})。 */
|
|
117
120
|
setInstructions(agent: Agent, on: boolean): void;
|
|
118
121
|
/**
|
|
119
122
|
* 本会话的**工具收窄**(模式白名单):投影层只过滤装配结果、不碰工具注册表,所以"谁能用"这件事
|
|
@@ -137,6 +140,8 @@ declare class ContextAssembler extends Service {
|
|
|
137
140
|
* 路径(接管的 `skill` 工具)要用这里重新算一次,才和 `auto` 正文一样跟着工具走。
|
|
138
141
|
*/
|
|
139
142
|
contentFor(name: string, agent: Agent | undefined): string | undefined;
|
|
143
|
+
/** 一个 skill 在这个会话能不能被用到:声明了 `requires` 时至少一个工具在模式收窄内。 */
|
|
144
|
+
private reachable;
|
|
140
145
|
collect(agent: Agent): Promise<Map<string, PromptEntry>>;
|
|
141
146
|
private sectionsOf;
|
|
142
147
|
/**
|
|
@@ -159,7 +164,19 @@ declare module "@deepseek-ai/cordis" {
|
|
|
159
164
|
/** 通道自己的条目形态(注入方没声明 source 时的默认):规则块,幂等键是 id。 */
|
|
160
165
|
interface PromptReminderSource {
|
|
161
166
|
kind: "context-assembler";
|
|
162
|
-
|
|
167
|
+
/**
|
|
168
|
+
* 条目形态:`instructions` 是规则块;`catalog` 是"带清单的目录"(客户端按 `entries` 列条目,
|
|
169
|
+
* 而不是读正文)。
|
|
170
|
+
*/
|
|
171
|
+
form: "instructions" | "catalog";
|
|
172
|
+
/**
|
|
173
|
+
* `catalog` 形态发布的那份清单。**只有我们自己发布的目录**用它:上游 `tool-skill` 的账本扫法
|
|
174
|
+
* 只认它自己的 `kind`,所以这里的 kind 必须是我们自己的(见 [`skill-catalog`](../skill-catalog/index.ts))。
|
|
175
|
+
*/
|
|
176
|
+
entries?: readonly {
|
|
177
|
+
readonly name: string;
|
|
178
|
+
readonly description: string;
|
|
179
|
+
}[];
|
|
163
180
|
/** 条目 id:同 id 的最新一条取代更早的同 id 条目。本插件早先落库的消息没有它。 */
|
|
164
181
|
id?: string;
|
|
165
182
|
}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as index_d_exports } from "./agent-instructions.mjs";
|
|
2
|
-
import { r as index_d_exports$1 } from "./index-
|
|
2
|
+
import { r as index_d_exports$1 } from "./index-zhmD45A9.mjs";
|
|
3
3
|
import { t as index_d_exports$2 } from "./scope.mjs";
|
|
4
4
|
import { t as index_d_exports$3 } from "./skill-catalog.mjs";
|
|
5
5
|
import z from "@deepseek-ai/schemastery";
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { n as agent_instructions_exports } from "./agent-instructions-
|
|
2
|
-
import { r as assembler_exports } from "./assembler-
|
|
3
|
-
import {
|
|
1
|
+
import { n as agent_instructions_exports } from "./agent-instructions-CIgUVIeo.mjs";
|
|
2
|
+
import { r as assembler_exports } from "./assembler-CDMIBAi8.mjs";
|
|
3
|
+
import { t as scope_exports } from "./scope.mjs";
|
|
4
4
|
import { t as skill_catalog_exports } from "./skill-catalog.mjs";
|
|
5
5
|
import z from "@deepseek-ai/schemastery";
|
|
6
6
|
//#region src/index.ts
|
package/dist/rows.d.mts
CHANGED
|
@@ -6,8 +6,9 @@
|
|
|
6
6
|
* (`@morlay/dsh-agent-toolkit/guidance`,在别的包里)与 skill 目录这类消费者都在别的行上
|
|
7
7
|
* `inject` 它,隔离会把它们挡在组外(行停在 waiting,不报错)。
|
|
8
8
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
9
|
+
* 本包自己的 bundle 只装通道(`PATCH_ROWS`)。模式的收口是另一行(`scopeRow()`),它由
|
|
10
|
+
* [`@morlay/dsh-session-mode`](../../../profile/dsh-session-mode/README.md) 的 patch 与模式定义一起装——
|
|
11
|
+
* 那一行的 config 就是模式清单。
|
|
11
12
|
*/
|
|
12
13
|
/** 组装出口(包根)就是那个"按 config 装能力"的插件。 */
|
|
13
14
|
declare const CONTEXT_PACKAGE = "@morlay/dsh-context-assembler";
|
|
@@ -23,18 +24,19 @@ interface ContextRow {
|
|
|
23
24
|
*/
|
|
24
25
|
declare function contextChannel(config?: Readonly<Record<string, unknown>>): ContextRow;
|
|
25
26
|
/**
|
|
26
|
-
*
|
|
27
|
+
* 模式收口那一行:`scope` 出口按 `ctx.sessionModes` 的模式定义收口(工具白名单、instruction 总开关、
|
|
28
|
+
* 动态快照开关)。
|
|
27
29
|
*
|
|
28
|
-
*
|
|
29
|
-
* `ctx.
|
|
30
|
+
* 行 id 用全名 `context-assembler-scope`:它的搭档是同一份装配里的 `context-assembler`(通道),两个 id 放在
|
|
31
|
+
* 一起才看得出这一行属于哪个包、做什么——`context-scope` 那种短名会被误当成 `ctx.contextScope` 之类的服务。
|
|
32
|
+
*
|
|
33
|
+
* 行本身**不带 config**:装哪些模式、每个模式收什么,都由 `session-mode` 行的 `config.modes` 决定,
|
|
34
|
+
* 这一行只把它落到会话上(`inject` `sessionModes`,由
|
|
35
|
+
* [`@morlay/dsh-session-mode`](../../../profile/dsh-session-mode/README.md) 的 patch 插一行)。
|
|
30
36
|
*/
|
|
31
|
-
declare function scopeRow(
|
|
32
|
-
readonly id: string;
|
|
33
|
-
readonly name: string;
|
|
34
|
-
readonly config?: Readonly<Record<string, unknown>>;
|
|
35
|
-
};
|
|
37
|
+
declare function scopeRow(): ContextRow;
|
|
36
38
|
/**
|
|
37
|
-
* bundle patch
|
|
39
|
+
* bundle patch 的行清单:只有通道一行(模式收口那一行归 `session-mode` 的 patch 装)。
|
|
38
40
|
*
|
|
39
41
|
* 形态是 `insert`:这些行由本包提供给 host 平面。写成 `- id: x` 那种"改已有行"的形态时,装配期找不到
|
|
40
42
|
* 目标行(只 warn 后跳过),通道根本没装上,引用它的行停在 waiting。
|
package/dist/rows.mjs
CHANGED
|
@@ -6,8 +6,9 @@
|
|
|
6
6
|
* (`@morlay/dsh-agent-toolkit/guidance`,在别的包里)与 skill 目录这类消费者都在别的行上
|
|
7
7
|
* `inject` 它,隔离会把它们挡在组外(行停在 waiting,不报错)。
|
|
8
8
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
9
|
+
* 本包自己的 bundle 只装通道(`PATCH_ROWS`)。模式的收口是另一行(`scopeRow()`),它由
|
|
10
|
+
* [`@morlay/dsh-session-mode`](../../../profile/dsh-session-mode/README.md) 的 patch 与模式定义一起装——
|
|
11
|
+
* 那一行的 config 就是模式清单。
|
|
11
12
|
*/
|
|
12
13
|
/** 组装出口(包根)就是那个"按 config 装能力"的插件。 */
|
|
13
14
|
const CONTEXT_PACKAGE = "@morlay/dsh-context-assembler";
|
|
@@ -23,20 +24,24 @@ function contextChannel(config) {
|
|
|
23
24
|
};
|
|
24
25
|
}
|
|
25
26
|
/**
|
|
26
|
-
*
|
|
27
|
+
* 模式收口那一行:`scope` 出口按 `ctx.sessionModes` 的模式定义收口(工具白名单、instruction 总开关、
|
|
28
|
+
* 动态快照开关)。
|
|
27
29
|
*
|
|
28
|
-
*
|
|
29
|
-
* `ctx.
|
|
30
|
+
* 行 id 用全名 `context-assembler-scope`:它的搭档是同一份装配里的 `context-assembler`(通道),两个 id 放在
|
|
31
|
+
* 一起才看得出这一行属于哪个包、做什么——`context-scope` 那种短名会被误当成 `ctx.contextScope` 之类的服务。
|
|
32
|
+
*
|
|
33
|
+
* 行本身**不带 config**:装哪些模式、每个模式收什么,都由 `session-mode` 行的 `config.modes` 决定,
|
|
34
|
+
* 这一行只把它落到会话上(`inject` `sessionModes`,由
|
|
35
|
+
* [`@morlay/dsh-session-mode`](../../../profile/dsh-session-mode/README.md) 的 patch 插一行)。
|
|
30
36
|
*/
|
|
31
|
-
function scopeRow(
|
|
37
|
+
function scopeRow() {
|
|
32
38
|
return {
|
|
33
|
-
id: "context-scope",
|
|
34
|
-
name: "@morlay/dsh-context-assembler/scope"
|
|
35
|
-
...config === void 0 ? {} : { config }
|
|
39
|
+
id: "context-assembler-scope",
|
|
40
|
+
name: "@morlay/dsh-context-assembler/scope"
|
|
36
41
|
};
|
|
37
42
|
}
|
|
38
43
|
/**
|
|
39
|
-
* bundle patch
|
|
44
|
+
* bundle patch 的行清单:只有通道一行(模式收口那一行归 `session-mode` 的 patch 装)。
|
|
40
45
|
*
|
|
41
46
|
* 形态是 `insert`:这些行由本包提供给 host 平面。写成 `- id: x` 那种"改已有行"的形态时,装配期找不到
|
|
42
47
|
* 目标行(只 warn 后跳过),通道根本没装上,引用它的行停在 waiting。
|
package/dist/scope.d.mts
CHANGED
|
@@ -1,47 +1,41 @@
|
|
|
1
1
|
import z from "@deepseek-ai/schemastery";
|
|
2
|
-
import { Context } from "@deepseek-ai/cordis";
|
|
2
|
+
import { Context, Service } from "@deepseek-ai/cordis";
|
|
3
|
+
import { Agent } from "@deepseek-ai/dsh-agent";
|
|
3
4
|
declare namespace index_d_exports {
|
|
4
|
-
export { Config, apply, inject, name };
|
|
5
|
+
export { Config, SessionToolScope, SessionToolScopeMode, apply, inject, name };
|
|
5
6
|
}
|
|
6
|
-
declare const name = "context-scope";
|
|
7
|
+
declare const name = "context-assembler-scope";
|
|
8
|
+
/** 收口要的服务;`sessionToolScope` 由本行自己发布,`tools` 的 guard 挂在每个 agent 的 ctx 上。 */
|
|
7
9
|
declare const inject: string[];
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
10
|
+
/** 本行不吃 config:要收成什么样由消费方在 `apply` 时给。 */
|
|
11
|
+
declare const Config: z<Schemastery.ObjectS<{}>, Schemastery.ObjectT<{}>, "plain">;
|
|
12
|
+
/** 一次收口的全部输入:模式定义里本出口用到的那几项。 */
|
|
13
|
+
interface SessionToolScopeMode {
|
|
14
|
+
/** 拒绝对话时用的模式名。 */
|
|
15
|
+
readonly name: string;
|
|
16
|
+
/** 这个会话能用的工具;其余既不进目录,调用也被拒。 */
|
|
17
|
+
readonly allowTools: readonly string[];
|
|
18
|
+
/** 缺省为要;`false` 表示这个会话不要任何 instruction 类注入。 */
|
|
19
|
+
readonly instructions?: boolean | undefined;
|
|
20
|
+
/** 缺省为要;`false` 表示这个会话不要动态快照。 */
|
|
21
|
+
readonly runtimeContext?: boolean | undefined;
|
|
22
|
+
}
|
|
23
|
+
declare module "@deepseek-ai/cordis" {
|
|
24
|
+
interface Context {
|
|
25
|
+
sessionToolScope: SessionToolScope;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/** 按会话收口工具与注入的服务。 */
|
|
29
|
+
declare class SessionToolScope extends Service {
|
|
30
|
+
private readonly applied;
|
|
31
|
+
constructor(ctx: Context);
|
|
24
32
|
/**
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
* 抑制是**按 scope** 的(上游按装配的 scope 链查抑制器),所以本行装在 preset 子树里就只作用于这个
|
|
29
|
-
* 模式的会话;它只挡注入,不改任何提供方的行为(沙箱该怎么判还怎么判)。
|
|
33
|
+
* 把某个会话收口到这份定义上(同一个 agent 再调就是换一份)。
|
|
34
|
+
* @param agent - 目标会话的 agent。
|
|
35
|
+
* @param mode - 收口的全部输入。
|
|
30
36
|
*/
|
|
31
|
-
|
|
37
|
+
apply(agent: Agent, mode: SessionToolScopeMode): void;
|
|
32
38
|
}
|
|
33
|
-
declare
|
|
34
|
-
/**
|
|
35
|
-
* 把某个 preset 的工具收成"只有这些"。
|
|
36
|
-
*
|
|
37
|
-
* 为什么需要它:preset composition 只能决定"加什么",管不了 host 层——`dsh.profile.bundles` 打开的
|
|
38
|
-
* bundle(例如实验性的 Agent Teams)会在 host 层插工具行与 section,对所有 preset 一视同仁。模式想
|
|
39
|
-
* 表达"我只有这几个工具、一条提示词都不要"时,唯一与来源无关的做法是收口"有什么"。
|
|
40
|
-
*
|
|
41
|
-
* 为什么不是 `tools.restrict()`:它会改动可见工具集,从而触发 `tools/change`;上游 `tool-subagent`
|
|
42
|
-
* 正是用该事件做 composition reconcile——两边互相触发会变成装配风暴。这里用投影过滤加执行层 guard:
|
|
43
|
-
* 既不碰注册表、也不发事件。
|
|
44
|
-
*/
|
|
45
|
-
declare function apply(ctx: Context, config: Config): void;
|
|
39
|
+
declare function apply(ctx: Context): void;
|
|
46
40
|
//#endregion
|
|
47
|
-
export { Config, apply, inject, name, index_d_exports as t };
|
|
41
|
+
export { Config, SessionToolScope, SessionToolScopeMode, apply, inject, name, index_d_exports as t };
|