@morlay/dsh-tool-guidance 0.0.10 → 0.0.11-alpha.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/dist/index.d.mts CHANGED
@@ -1,11 +1,9 @@
1
1
  import { Context } from "@deepseek-ai/cordis";
2
2
  import z from "@deepseek-ai/schemastery";
3
- //#region src/index.d.ts
4
3
  export declare const name = "tool-guidance";
5
4
  export declare const inject: string[];
6
5
  export interface Config {
7
6
  groups?: boolean;
8
7
  }
9
8
  export declare const Config: z<Config>;
10
- export declare function apply(ctx: Context, config: Config): void;
11
- //#endregion
9
+ export declare function apply(ctx: Context, config: Config): void;
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { createUserMessage } from "@deepseek-ai/dsh-llm";
2
2
  import z from "@deepseek-ai/schemastery";
3
- //#region src/guidance/packs/ask.ts
3
+ // src/guidance/packs/ask.ts
4
4
  const ASK_PACK = {
5
5
  family: "ask",
6
6
  tools: [{
@@ -8,8 +8,7 @@ const ASK_PACK = {
8
8
  short: "向用户提问并等待回答"
9
9
  }]
10
10
  };
11
- //#endregion
12
- //#region src/guidance/packs/code.ts
11
+ // src/guidance/packs/code.ts
13
12
  const CODE_PACK = {
14
13
  family: "code",
15
14
  tools: [{
@@ -17,8 +16,7 @@ const CODE_PACK = {
17
16
  short: "用代码调用其它工具(PTC)"
18
17
  }]
19
18
  };
20
- //#endregion
21
- //#region src/guidance/packs/delegation.ts
19
+ // src/guidance/packs/delegation.ts
22
20
  const DELEGATION_PACK = {
23
21
  family: "delegation",
24
22
  tools: [
@@ -40,8 +38,7 @@ const DELEGATION_PACK = {
40
38
  }
41
39
  ]
42
40
  };
43
- //#endregion
44
- //#region src/guidance/packs/flow.ts
41
+ // src/guidance/packs/flow.ts
45
42
  const FLOW_PACK = {
46
43
  family: "flow",
47
44
  tools: [
@@ -84,11 +81,14 @@ const FLOW_PACK = {
84
81
  {
85
82
  tool: "schedule_delete",
86
83
  short: "删除一个提醒"
84
+ },
85
+ {
86
+ tool: "plugin_manager",
87
+ short: "管理本 profile 的插件与 bundle"
87
88
  }
88
89
  ]
89
90
  };
90
- //#endregion
91
- //#region src/guidance/packs/fs.ts
91
+ // src/guidance/packs/fs.ts
92
92
  const FS_PACK = {
93
93
  family: "fs",
94
94
  tools: [
@@ -126,8 +126,7 @@ const FS_PACK = {
126
126
  }
127
127
  ]
128
128
  };
129
- //#endregion
130
- //#region src/guidance/packs/shell.ts
129
+ // src/guidance/packs/shell.ts
131
130
  const SHELL_PACK = {
132
131
  family: "shell",
133
132
  tools: [
@@ -177,8 +176,7 @@ const SHELL_PACK = {
177
176
  }
178
177
  ]
179
178
  };
180
- //#endregion
181
- //#region src/guidance/packs/skill.ts
179
+ // src/guidance/packs/skill.ts
182
180
  const SKILL_PACK = {
183
181
  family: "skill",
184
182
  tools: [{
@@ -186,8 +184,7 @@ const SKILL_PACK = {
186
184
  short: "按需加载技能说明"
187
185
  }]
188
186
  };
189
- //#endregion
190
- //#region src/guidance/packs/team.ts
187
+ // src/guidance/packs/team.ts
191
188
  const TEAM_PACK = {
192
189
  family: "team",
193
190
  tools: [
@@ -229,8 +226,7 @@ const TEAM_PACK = {
229
226
  }
230
227
  ]
231
228
  };
232
- //#endregion
233
- //#region src/guidance/packs/web.ts
229
+ // src/guidance/packs/web.ts
234
230
  const WEB_PACK = {
235
231
  family: "web",
236
232
  tools: [{
@@ -241,8 +237,7 @@ const WEB_PACK = {
241
237
  short: "联网搜索"
242
238
  }]
243
239
  };
244
- //#endregion
245
- //#region src/guidance/packs/group-base.ts
240
+ // src/guidance/packs/group-base.ts
246
241
  const BASE_GROUP = {
247
242
  family: "group-base",
248
243
  group: {
@@ -373,8 +368,7 @@ const BASE_GROUP = {
373
368
  ]
374
369
  }
375
370
  };
376
- //#endregion
377
- //#region src/guidance/packs/group-delegation.ts
371
+ // src/guidance/packs/group-delegation.ts
378
372
  const DELEGATION_GROUP = {
379
373
  family: "group-delegation",
380
374
  group: {
@@ -431,8 +425,7 @@ const DELEGATION_GROUP = {
431
425
  ]
432
426
  }
433
427
  };
434
- //#endregion
435
- //#region src/guidance/packs/group-flow.ts
428
+ // src/guidance/packs/group-flow.ts
436
429
  const FLOW_GROUP = {
437
430
  family: "group-flow",
438
431
  group: {
@@ -484,8 +477,7 @@ const FLOW_GROUP = {
484
477
  ]
485
478
  }
486
479
  };
487
- //#endregion
488
- //#region src/guidance/packs/group-team.ts
480
+ // src/guidance/packs/group-team.ts
489
481
  const TEAM_GROUP = {
490
482
  family: "group-team",
491
483
  group: {
@@ -526,8 +518,7 @@ const TEAM_GROUP = {
526
518
  ]
527
519
  }
528
520
  };
529
- //#endregion
530
- //#region src/guidance/packs/index.ts
521
+ // src/guidance/packs/index.ts
531
522
  const TOOL_PACKS = [
532
523
  ASK_PACK,
533
524
  CODE_PACK,
@@ -567,14 +558,12 @@ function groupsOf(packs = GROUP_PACKS) {
567
558
  }
568
559
  return groups;
569
560
  }
570
- //#endregion
571
- //#region src/guidance/types.ts
561
+ // src/guidance/types.ts
572
562
  const BASE_GROUP_KEY = "base";
573
563
  function skillNameOf(key) {
574
564
  return `tool-group-${key}`;
575
565
  }
576
- //#endregion
577
- //#region src/guidance/groups.ts
566
+ // src/guidance/groups.ts
578
567
  const TOOL_GROUPS = groupsOf(GROUP_PACKS);
579
568
  const SHORT_TOOL_DESCRIPTIONS = shortDescriptionsOf(TOOL_PACKS);
580
569
  function groupByKey(key) {
@@ -589,8 +578,7 @@ function groupSkillBody(group, visible = () => true) {
589
578
  return typeof when === "string" ? visible(when) : when.some(visible);
590
579
  }).map((line) => `- ${line.text}`).join("\n");
591
580
  }
592
- //#endregion
593
- //#region src/index.ts
581
+ // src/index.ts
594
582
  const name = "tool-guidance";
595
583
  const inject = [
596
584
  "tools",
@@ -633,15 +621,47 @@ function apply(ctx, config) {
633
621
  };
634
622
  });
635
623
  }
624
+ const projected = /* @__PURE__ */ new WeakSet();
625
+ const project = (definition) => {
626
+ if (projected.has(definition)) return;
627
+ projected.add(definition);
628
+ const description = SHORT_TOOL_DESCRIPTIONS[definition.name];
629
+ if (description !== void 0) Object.defineProperty(definition, "description", {
630
+ value: description,
631
+ configurable: true,
632
+ enumerable: true,
633
+ writable: true
634
+ });
635
+ Object.defineProperty(definition, "parameters", {
636
+ value: slimSchema(definition.parameters),
637
+ configurable: true,
638
+ enumerable: true,
639
+ writable: true
640
+ });
641
+ };
636
642
  ctx.on("system-prompt/assemble", async (_assembly, context, next) => {
637
643
  const result = await next();
638
644
  const agent = context.agent;
639
- if (agent !== void 0) visibleTools.set(agent, new Set(result.tools.map((tool) => tool.name)));
640
- return {
641
- ...result,
642
- tools: shortenTools(result.tools)
643
- };
645
+ if (agent !== void 0) {
646
+ const toolSet = context.toolSet;
647
+ const definitions = ctx.tools.definitions(agent, toolSet);
648
+ visibleTools.set(agent, new Set(definitions.map((tool) => tool.name)));
649
+ for (const definition of definitions) project(definition);
650
+ }
651
+ return result;
644
652
  }, { prepend: true });
653
+ ctx.on("agent/created", ({ agent }) => {
654
+ const projectAgent = () => {
655
+ for (const definition of ctx.tools.definitions(agent)) project(definition);
656
+ };
657
+ projectAgent();
658
+ agent.ctx.on("tools/change", projectAgent);
659
+ });
660
+ const projectVisible = () => {
661
+ for (const definition of ctx.tools.definitions()) project(definition);
662
+ };
663
+ ctx.on("tools/change", projectVisible);
664
+ projectVisible();
645
665
  }
646
666
  const baseGroup = groupByKey(BASE_GROUP_KEY);
647
667
  function registeredIn(ctx, agent) {
@@ -670,13 +690,12 @@ function injectMessage(name, text) {
670
690
  });
671
691
  }
672
692
  function latestInjectText(agent, name) {
673
- for (const seq of agent.session.surface.nodes.toReversed()) {
674
- const event = agent.session.eventAt(seq);
675
- if (event?.type !== "user/message") continue;
676
- const source = event.data.source;
693
+ for (const message of agent.session.deriveMessages().toReversed()) {
694
+ if (message.role !== "user") continue;
695
+ const source = message.source;
677
696
  if (source.kind !== "skill-invocation" || source.name !== name) continue;
678
- const [block] = event.data.content;
679
- return event.data.content.length === 1 && block?.type === "text" ? block.text : "";
697
+ const [block] = message.content;
698
+ return message.content.length === 1 && block?.type === "text" ? block.text : "";
680
699
  }
681
700
  }
682
701
  function slimSchema(schema) {
@@ -688,15 +707,4 @@ function slimSchema(schema) {
688
707
  for (const key of ["items", "additionalProperties"]) if (key in rest) rest[key] = slimSchema(rest[key]);
689
708
  return rest;
690
709
  }
691
- function shortenTools(tools) {
692
- return tools.map((tool) => {
693
- const description = SHORT_TOOL_DESCRIPTIONS[tool.name];
694
- return {
695
- ...tool,
696
- parameters: slimSchema(tool.parameters),
697
- ...description === void 0 ? {} : { description }
698
- };
699
- });
700
- }
701
- //#endregion
702
710
  export { Config, apply, inject, name };
package/dist/rows.d.mts CHANGED
@@ -1,7 +1,5 @@
1
- //#region src/rows.d.ts
2
1
  export declare function toolGuidanceRow(config?: Readonly<Record<string, unknown>>): {
3
2
  readonly id: string;
4
3
  readonly name: string;
5
4
  readonly config?: Readonly<Record<string, unknown>>;
6
- };
7
- //#endregion
5
+ };
package/dist/rows.mjs CHANGED
@@ -1,4 +1,4 @@
1
- //#region src/rows.ts
1
+ // src/rows.ts
2
2
  function toolGuidanceRow(config) {
3
3
  return {
4
4
  id: "tool-guidance",
@@ -6,5 +6,4 @@ function toolGuidanceRow(config) {
6
6
  ...config === void 0 ? {} : { config }
7
7
  };
8
8
  }
9
- //#endregion
10
9
  export { toolGuidanceRow };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@morlay/dsh-tool-guidance",
3
- "version": "0.0.10",
3
+ "version": "0.0.11-alpha.0",
4
4
  "description": "Tool guidance for dsh: localized short tool descriptions, trimmed schema and usage groups as one host-plane row. The agent row list lives in the agent presets themselves (shipped or deployment-owned).",
5
5
  "keywords": [
6
6
  "dsh",
@@ -34,29 +34,29 @@
34
34
  "./locale/*.json": "./locale/*.json"
35
35
  },
36
36
  "devDependencies": {
37
- "@deepseek-ai/cordis-plugin-include": "^1.0.10",
38
- "@deepseek-ai/dsh-agent-loop-testkit": "^0.2.1-rc.1",
39
- "@deepseek-ai/dsh-llm": "^0.2.1-rc.1",
40
- "@deepseek-ai/dsh-scope": "^0.2.1-rc.1",
41
- "@deepseek-ai/dsh-session": "^0.2.1-rc.1",
42
- "@deepseek-ai/dsh-system-prompt": "^0.2.1-rc.1",
43
- "@deepseek-ai/schemastery": "^3.18.5",
44
- "@morlay/dsh-context-assembler": "0.0.10",
45
- "@morlay/dsh-session-mode": "0.0.13",
37
+ "@deepseek-ai/cordis-plugin-include": "^1.0.11-alpha.1",
38
+ "@deepseek-ai/dsh-agent-loop-testkit": "^0.2.2-alpha.2",
39
+ "@deepseek-ai/dsh-llm": "^0.2.2-alpha.2",
40
+ "@deepseek-ai/dsh-scope": "^0.2.2-alpha.2",
41
+ "@deepseek-ai/dsh-session": "^0.2.2-alpha.2",
42
+ "@deepseek-ai/dsh-system-prompt": "^0.2.2-alpha.2",
43
+ "@deepseek-ai/schemastery": "^3.18.6-alpha.1",
44
+ "@morlay/dsh-context-assembler": "0.0.11-alpha.0",
45
+ "@morlay/dsh-session-mode": "0.0.14-alpha.0",
46
46
  "@types/js-yaml": "^4.0.9",
47
47
  "js-yaml": "^4.1.0"
48
48
  },
49
49
  "peerDependencies": {
50
- "@deepseek-ai/cordis": "^4.0.5",
51
- "@deepseek-ai/dsh-agent": "^0.2.1-rc.1",
52
- "@deepseek-ai/dsh-llm": "^0.2.1-rc.1",
53
- "@deepseek-ai/dsh-skill": "^0.2.1-rc.1",
54
- "@deepseek-ai/dsh-tools": "^0.2.1-rc.1",
55
- "@deepseek-ai/schemastery": "^3.18.5",
56
- "@morlay/dsh-context-assembler": "0.0.10"
50
+ "@deepseek-ai/cordis": "^4.0.6-alpha.1",
51
+ "@deepseek-ai/dsh-agent": "^0.2.2-alpha.2",
52
+ "@deepseek-ai/dsh-llm": "^0.2.2-alpha.2",
53
+ "@deepseek-ai/dsh-skill": "^0.2.2-alpha.2",
54
+ "@deepseek-ai/dsh-tools": "^0.2.2-alpha.2",
55
+ "@deepseek-ai/schemastery": "^3.18.6-alpha.1",
56
+ "@morlay/dsh-context-assembler": "0.0.11-alpha.0"
57
57
  },
58
58
  "engines": {
59
- "dsh": ">= 0.2.1-rc.1 < 0.2.2"
59
+ "dsh": ">= 0.2.2-alpha.2 < 0.2.3"
60
60
  },
61
61
  "scripts": {
62
62
  "build": "pnpm exec tsdown"
@@ -14,5 +14,6 @@ export const FLOW_PACK: ToolPack = {
14
14
  { tool: "schedule_list", short: "列出本会话的活动提醒" },
15
15
  { tool: "schedule_update", short: "原地改一个提醒" },
16
16
  { tool: "schedule_delete", short: "删除一个提醒" },
17
+ { tool: "plugin_manager", short: "管理本 profile 的插件与 bundle" },
17
18
  ],
18
19
  };
package/src/index.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import type { Context } from "@deepseek-ai/cordis";
2
2
  import type { Agent } from "@deepseek-ai/dsh-agent";
3
- import { createUserMessage, type ToolSchema } from "@deepseek-ai/dsh-llm";
3
+ import { createUserMessage } from "@deepseek-ai/dsh-llm";
4
4
  import type {} from "@deepseek-ai/dsh-skill";
5
- import type {} from "@deepseek-ai/dsh-tools";
5
+ import type { ToolDefinition } from "@deepseek-ai/dsh-tools";
6
6
  import type {} from "@morlay/dsh-context-assembler";
7
7
  import z from "@deepseek-ai/schemastery";
8
8
  import {
@@ -89,24 +89,72 @@ export function apply(ctx: Context, config: Config): void {
89
89
  });
90
90
  }
91
91
 
92
- // 本行挂在**最外层**(`prepend`):会话收窄的监听比本行先注册(host 平面的行先于本行的 scope),而瀑布里
93
- // 先注册的是外层——收窄发生在它的返回路径上,站在内层读 `next()` 拿到的是收窄**之前**的目录。站到最外层,
94
- // 一次装配走完手里的 `result` 才是这个会话最终可见的那份。工具投影的改写与过滤可交换(只换描述与 schema,
95
- // 不动名字),所以把改写一并挪到最外层,别人看到的结果不变。
92
+ // 工具投影的改写落在**工具定义**上:装配瀑布不再承载工具声明,而 `llm/stream` 的 options 是上游冻结过的
93
+ // (`agent-loop` 用 `Object.freeze` 构造请求),在监听器里写 `options.tools` 会抛
94
+ // `Cannot assign to read only property 'tools'`。定义对象本身可变,改它的 `description` / `parameters` 就等于
95
+ // 改了 `executor.describe()` 的输出(模型面),**不经过 `tools.register`,也不触发 `tools/change` 重入**;
96
+ // 执行期的输入校验用的是 `defineTool` 闭包里那份原 schema,不受这里替换影响。
97
+ const projected = new WeakSet<object>();
98
+ const project = (definition: ToolDefinition): void => {
99
+ if (projected.has(definition)) return;
100
+ projected.add(definition);
101
+ const description = SHORT_TOOL_DESCRIPTIONS[definition.name];
102
+ if (description !== undefined) {
103
+ Object.defineProperty(definition, "description", {
104
+ value: description,
105
+ configurable: true,
106
+ enumerable: true,
107
+ writable: true,
108
+ });
109
+ }
110
+ Object.defineProperty(definition, "parameters", {
111
+ value: slimSchema(definition.parameters),
112
+ configurable: true,
113
+ enumerable: true,
114
+ writable: true,
115
+ });
116
+ };
117
+ // 本行挂在**最外层**(`prepend`):`base` 正文要按这个会话最终可见的工具目录过滤,而装配上下文里的
118
+ // `toolSet` 就是这一步的准入集(上游 0.2.1-rc.2 起工具声明由 `tools.resolve` 定,装配瀑布不再带 `tools`)。
96
119
  ctx.on(
97
120
  "system-prompt/assemble",
98
121
  async (_assembly, context, next) => {
99
122
  const result = await next();
100
123
  const agent = context.agent;
101
- // 记名字集合:`result.tools` 是投影**之后**的目录(收窄已生效、描述已被 `shortenTools` 换过),
102
- // 名字不受描述改写影响。诊断式的无 agent 装配不记(那种装配也不属于任何会话)。
124
+ // 记名字集合:准入集已应用这个会话的收窄(`tools.restrict`)与条件激活,名字不受描述改写影响。
125
+ // 诊断式的无 agent 装配不记(那种装配也不属于任何会话)。
103
126
  if (agent !== undefined) {
104
- visibleTools.set(agent, new Set(result.tools.map((tool) => tool.name)));
127
+ const toolSet = context.toolSet;
128
+ const definitions = ctx.tools.definitions(agent, toolSet);
129
+ visibleTools.set(
130
+ agent,
131
+ new Set(definitions.map((tool) => tool.name)),
132
+ );
133
+ // 会话内晚注册的工具(MCP 重连、skill 重载)赶不上 `agent/created`:这里补一次改写。本次装配的声明已经
134
+ // 按旧定义收集过了,所以从**下一次**请求开始生效。
135
+ for (const definition of definitions) project(definition);
105
136
  }
106
- return { ...result, tools: shortenTools(result.tools) };
137
+ return result;
107
138
  },
108
139
  { prepend: true },
109
140
  );
141
+
142
+ // 工具注册在**会话挂着的那份 preset 的 scope** 上,全局 `definitions()` 看不到它们:会话建好时按它的视图改一遍,
143
+ // 这是第一次装配之前的时机。`tools/change` 只管全局可见的那部分;会话内晚注册的工具由装配监听补(下一次请求生效)。
144
+ ctx.on("agent/created", ({ agent }) => {
145
+ const projectAgent = (): void => {
146
+ for (const definition of ctx.tools.definitions(agent)) project(definition);
147
+ };
148
+ projectAgent();
149
+ // 团队、schedule 这类行在**会话建好之后**才把工具注册进 agent scope:全局 `tools/change` 看不到它们,
150
+ // 所以每个会话自己跟这条事件(监听挂在 `agent.ctx` 上,随会话收回)。
151
+ agent.ctx.on("tools/change", projectAgent);
152
+ });
153
+ const projectVisible = (): void => {
154
+ for (const definition of ctx.tools.definitions()) project(definition);
155
+ };
156
+ ctx.on("tools/change", projectVisible);
157
+ projectVisible();
110
158
  }
111
159
 
112
160
  const baseGroup = groupByKey(BASE_GROUP_KEY);
@@ -141,13 +189,14 @@ function injectMessage(name: string, text: string): ReturnType<typeof createUser
141
189
  // surface 上最近一条该键注入的正文(含信封);没有则 undefined——压缩掉它、或进程重启后 resume 折叠出它,
142
190
  // 都由这一眼分辨。
143
191
  function latestInjectText(agent: Agent, name: string): string | undefined {
144
- for (const seq of agent.session.surface.nodes.toReversed()) {
145
- const event = agent.session.eventAt(seq);
146
- if (event?.type !== "user/message") continue;
147
- const source = event.data.source as { readonly kind?: unknown; readonly name?: unknown };
192
+ // `deriveMessages()` 是 surface 的派生消息视图(受支持的同步读);逐 seq 读事件的
193
+ // `eventAt` / `snapshotEvents` / `ownEvents` 已被上游声明为「新调用禁止」。
194
+ for (const message of agent.session.deriveMessages().toReversed()) {
195
+ if (message.role !== "user") continue;
196
+ const source = message.source as { readonly kind?: unknown; readonly name?: unknown };
148
197
  if (source.kind !== "skill-invocation" || source.name !== name) continue;
149
- const [block] = event.data.content;
150
- return event.data.content.length === 1 && block?.type === "text" ? block.text : "";
198
+ const [block] = message.content;
199
+ return message.content.length === 1 && block?.type === "text" ? block.text : "";
151
200
  }
152
201
  return undefined;
153
202
  }
@@ -179,16 +228,3 @@ function slimSchema(schema: unknown): unknown {
179
228
  return rest;
180
229
  }
181
230
 
182
- // 改写模型看到的工具投影:描述换成一行中文,参数只留约束(`type` / `enum` / `oneOf` / `required` / `default`),
183
- // 说明性字段整段丢弃。改装配结果而不是注册表——注册同名工具会触发 `tools/change`,与上游 `tool-subagent` 的
184
- // composition reconcile 互相触发会造成装配风暴式重入;投影只影响本次请求,晚注册的工具也照样能覆盖。
185
- function shortenTools(tools: readonly ToolSchema[]): ToolSchema[] {
186
- return tools.map((tool) => {
187
- const description = SHORT_TOOL_DESCRIPTIONS[tool.name];
188
- return {
189
- ...tool,
190
- parameters: slimSchema(tool.parameters),
191
- ...(description === undefined ? {} : { description }),
192
- } as ToolSchema;
193
- });
194
- }