@ai-zen/agents-sdk 0.6.0 → 0.7.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.
- package/CHANGELOG.md +37 -0
- package/README.md +10 -7
- package/README.zh.md +10 -7
- package/dist/capabilities/discovery/builtin.d.ts +3 -3
- package/dist/capabilities/discovery/builtin.js +4 -12
- package/dist/capabilities/implements/builtin/FindTextTool.d.ts +3 -0
- package/dist/capabilities/implements/builtin/FindTextTool.js +69 -23
- package/dist/capabilities/implements/builtin/GenerateImageTool.d.ts +8 -8
- package/dist/capabilities/implements/builtin/GenerateImageTool.js +26 -27
- package/dist/capabilities/implements/builtin/ViewImageTool.d.ts +24 -0
- package/dist/capabilities/implements/builtin/ViewImageTool.js +109 -0
- package/dist/capabilities/implements/builtin/index.d.ts +6 -4
- package/dist/capabilities/implements/builtin/index.js +8 -4
- package/dist/capabilities/implements/skillTools.js +5 -5
- package/dist/capabilities/implements/subAgentTools.js +17 -8
- package/dist/config/constants.js +12 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/plugin/AutoMigratePlugin.d.ts +1 -1
- package/dist/plugin/AutoMigratePlugin.js +1 -1
- package/dist/plugin/AutoRefreshToolsPlugin.d.ts +1 -1
- package/dist/plugin/AutoRefreshToolsPlugin.js +2 -2
- package/dist/plugin/ContextGuardPlugin.d.ts +2 -2
- package/dist/plugin/ContextGuardPlugin.js +1 -1
- package/dist/plugin/UnknownToolHintPlugin.d.ts +21 -0
- package/dist/plugin/UnknownToolHintPlugin.js +30 -0
- package/dist/runtime/Provider.d.ts +8 -7
- package/dist/runtime/Provider.js +14 -4
- package/dist/runtime/SdkAgent.d.ts +14 -107
- package/dist/runtime/SdkAgent.js +8 -120
- package/dist/runtime/SdkCallbackTool.d.ts +12 -4
- package/dist/runtime/SdkCallbackTool.js +5 -2
- package/dist/runtime/createAgent.js +4 -3
- package/dist/runtime/createModel.d.ts +17 -4
- package/dist/runtime/createModel.js +15 -11
- package/dist/types/index.d.ts +2 -0
- package/package.json +3 -2
|
@@ -113,17 +113,17 @@ export function createCallSkillSubAgentTool(skillDirs, filteredSkills, provider)
|
|
|
113
113
|
if (!skill.subAgent) {
|
|
114
114
|
return `Skill "${skillId}" 不支持子 Agent 模式,请使用 load_skill 加载指导后自行处理`;
|
|
115
115
|
}
|
|
116
|
+
// 临时 Skill 子 Agent 复用父 Agent 定义(权限 + 模型),排除当前 Skill 防自调用
|
|
116
117
|
const parentAgent = ctx.agent;
|
|
117
|
-
const
|
|
118
|
-
? parentAgent.
|
|
119
|
-
: undefined;
|
|
120
|
-
const skillTools = provider && parentPermissions
|
|
121
|
-
? provider.buildTools(parentPermissions, {
|
|
118
|
+
const skillTools = provider && parentAgent instanceof SdkAgent
|
|
119
|
+
? provider.buildTools(parentAgent.definition, {
|
|
122
120
|
exclude: { skills: [skillId] },
|
|
123
121
|
})
|
|
124
122
|
: [];
|
|
125
123
|
const subAgent = new Agent({
|
|
124
|
+
client: parentAgent.client,
|
|
126
125
|
model: parentAgent.model,
|
|
126
|
+
modelConfig: parentAgent.modelConfig,
|
|
127
127
|
messages: [
|
|
128
128
|
Message.System(skill.content),
|
|
129
129
|
Message.User(task),
|
|
@@ -18,28 +18,37 @@ export function createSubAgentTool(def, provider) {
|
|
|
18
18
|
parameters: def.function.parameters,
|
|
19
19
|
},
|
|
20
20
|
messages: def.messages,
|
|
21
|
-
buildAgent: (
|
|
21
|
+
buildAgent: (_parsedArgs, ctx) => {
|
|
22
22
|
// 模型解析:SubAgent 可指定独立模型,否则复用父 Agent 的模型
|
|
23
|
-
let
|
|
23
|
+
let client;
|
|
24
|
+
let model;
|
|
25
|
+
let modelConfig;
|
|
24
26
|
if (def.modelId) {
|
|
25
|
-
|
|
27
|
+
const m = createModel(provider, def.modelId);
|
|
28
|
+
client = m.client;
|
|
29
|
+
model = m.model;
|
|
30
|
+
modelConfig = m.modelConfig;
|
|
26
31
|
}
|
|
27
32
|
else {
|
|
28
|
-
const
|
|
29
|
-
if (!
|
|
33
|
+
const parent = ctx.agent;
|
|
34
|
+
if (!parent) {
|
|
30
35
|
throw new Error(`SubAgent "${selfName}" 未指定 modelId,且父 Agent 没有可复用的模型`);
|
|
31
36
|
}
|
|
32
|
-
|
|
37
|
+
client = parent.client;
|
|
38
|
+
model = parent.model;
|
|
39
|
+
modelConfig = parent.modelConfig;
|
|
33
40
|
}
|
|
34
41
|
// SubAgent 独立解析自己的工具(排除自身,防止递归)
|
|
35
|
-
const subFiltered = provider.filter(def
|
|
42
|
+
const subFiltered = provider.filter(def, {
|
|
36
43
|
exclude: {
|
|
37
44
|
subagents: def.function?.name ? [def.function.name] : undefined,
|
|
38
45
|
},
|
|
39
46
|
});
|
|
40
47
|
const tools = provider.instantiate(subFiltered);
|
|
41
48
|
const subAgent = new Agent({
|
|
42
|
-
|
|
49
|
+
client,
|
|
50
|
+
model,
|
|
51
|
+
modelConfig,
|
|
43
52
|
tools,
|
|
44
53
|
});
|
|
45
54
|
return subAgent;
|
package/dist/config/constants.js
CHANGED
|
@@ -119,7 +119,8 @@ export const DEFAULT_APP_CONFIG = {
|
|
|
119
119
|
modelName: "glm-5v-turbo",
|
|
120
120
|
maxContextTokens: 250_000,
|
|
121
121
|
defaultParams: {},
|
|
122
|
-
|
|
122
|
+
vision: true,
|
|
123
|
+
description: "智谱AI 多模态Coding基座(支持图片输入)",
|
|
123
124
|
},
|
|
124
125
|
{
|
|
125
126
|
id: "glm-4.7-flash",
|
|
@@ -148,6 +149,16 @@ export const DEFAULT_APP_CONFIG = {
|
|
|
148
149
|
defaultParams: { thinking: { type: "enabled" } },
|
|
149
150
|
description: "DeepSeek 经济高效模型",
|
|
150
151
|
},
|
|
152
|
+
{
|
|
153
|
+
id: "deepseek-v4-flash-vision-exp",
|
|
154
|
+
name: "DeepSeek-V4-Flash-Vision-Exp",
|
|
155
|
+
endpointId: "deepseek",
|
|
156
|
+
modelName: "deepseek-v4-flash-vision-exp",
|
|
157
|
+
maxContextTokens: 250_000,
|
|
158
|
+
defaultParams: { thinking: { type: "enabled" } },
|
|
159
|
+
vision: true,
|
|
160
|
+
description: "DeepSeek 视觉实验模型(支持图片/文件输入)",
|
|
161
|
+
},
|
|
151
162
|
],
|
|
152
163
|
imageModels: [
|
|
153
164
|
{
|
package/dist/index.d.ts
CHANGED
|
@@ -29,9 +29,11 @@ export type { AutoMigrateOptions } from "./plugin/AutoMigratePlugin.js";
|
|
|
29
29
|
export { AutoRefreshToolsPlugin } from "./plugin/AutoRefreshToolsPlugin.js";
|
|
30
30
|
export { ContextGuardPlugin } from "./plugin/ContextGuardPlugin.js";
|
|
31
31
|
export type { ContextGuardOptions } from "./plugin/ContextGuardPlugin.js";
|
|
32
|
+
export { UnknownToolHintPlugin } from "./plugin/UnknownToolHintPlugin.js";
|
|
32
33
|
export { BUILTIN_TOOL_CLASSES } from "./capabilities/implements/builtin/index.js";
|
|
33
34
|
export { CwdTool, ReadFileTool, WriteFileTool, ExecTool, MkdirTool, RmTool, GlobTool, LsTool, ExistTool, FindTextTool, DownloadFileTool, RenameTool, CopyTool, BatchEditTool, EditTool, ExecAsyncTool, SleepTool, } from "./capabilities/implements/builtin/index.js";
|
|
34
35
|
export { GenerateImageTool } from "./capabilities/implements/builtin/GenerateImageTool.js";
|
|
36
|
+
export { ViewImageTool } from "./capabilities/implements/builtin/ViewImageTool.js";
|
|
35
37
|
export { createLoadSkillTool, createCallSkillSubAgentTool } from "./capabilities/implements/skillTools.js";
|
|
36
38
|
export { createLoadMcpTool, createCallMcpTool, createReadMcpResourceTool } from "./capabilities/implements/mcpTools.js";
|
|
37
39
|
export { createSubAgentTool } from "./capabilities/implements/subAgentTools.js";
|
package/dist/index.js
CHANGED
|
@@ -24,10 +24,12 @@ export { TaskMigrationService } from "./runtime/TaskMigrationService.js";
|
|
|
24
24
|
export { AutoMigratePlugin } from "./plugin/AutoMigratePlugin.js";
|
|
25
25
|
export { AutoRefreshToolsPlugin } from "./plugin/AutoRefreshToolsPlugin.js";
|
|
26
26
|
export { ContextGuardPlugin } from "./plugin/ContextGuardPlugin.js";
|
|
27
|
+
export { UnknownToolHintPlugin } from "./plugin/UnknownToolHintPlugin.js";
|
|
27
28
|
// 工具 — 内置工具类 + 动态工具工厂
|
|
28
29
|
export { BUILTIN_TOOL_CLASSES } from "./capabilities/implements/builtin/index.js";
|
|
29
30
|
export { CwdTool, ReadFileTool, WriteFileTool, ExecTool, MkdirTool, RmTool, GlobTool, LsTool, ExistTool, FindTextTool, DownloadFileTool, RenameTool, CopyTool, BatchEditTool, EditTool, ExecAsyncTool, SleepTool, } from "./capabilities/implements/builtin/index.js";
|
|
30
31
|
export { GenerateImageTool } from "./capabilities/implements/builtin/GenerateImageTool.js";
|
|
32
|
+
export { ViewImageTool } from "./capabilities/implements/builtin/ViewImageTool.js";
|
|
31
33
|
export { createLoadSkillTool, createCallSkillSubAgentTool } from "./capabilities/implements/skillTools.js";
|
|
32
34
|
export { createLoadMcpTool, createCallMcpTool, createReadMcpResourceTool } from "./capabilities/implements/mcpTools.js";
|
|
33
35
|
export { createSubAgentTool } from "./capabilities/implements/subAgentTools.js";
|
|
@@ -22,7 +22,7 @@ export class AutoMigratePlugin {
|
|
|
22
22
|
this.options = options;
|
|
23
23
|
}
|
|
24
24
|
async onAfterSend(ctx) {
|
|
25
|
-
const
|
|
25
|
+
const agent = ctx.agent;
|
|
26
26
|
const { maxTokens, migrationAgent, onBeforeMigrate, onMigrated } = this.options;
|
|
27
27
|
const promptTokens = agent.lastUsage?.prompt_tokens;
|
|
28
28
|
if (promptTokens == null)
|
|
@@ -8,9 +8,9 @@
|
|
|
8
8
|
*/
|
|
9
9
|
export class AutoRefreshToolsPlugin {
|
|
10
10
|
async onBeforeSend(ctx) {
|
|
11
|
-
const
|
|
11
|
+
const agent = ctx.agent;
|
|
12
12
|
await agent.provider.refresh({ silent: true });
|
|
13
|
-
agent.tools = agent.provider.buildTools(agent.
|
|
13
|
+
agent.tools = agent.provider.buildTools(agent.definition, {
|
|
14
14
|
exclude: {
|
|
15
15
|
subagents: agent.definition.function?.name
|
|
16
16
|
? [agent.definition.function.name]
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import type { AgentPlugin, SendContext } from "
|
|
1
|
+
import type { AgentPlugin, SendContext } from "@ai-zen/agents-core";
|
|
2
2
|
export interface ContextGuardOptions {
|
|
3
3
|
/** 上下文告警阈值(token)。用量超过 maxTokens × ratio 即中断。 */
|
|
4
4
|
maxTokens: number;
|
|
5
5
|
/**
|
|
6
6
|
* 超出比例。用量 > maxTokens × ratio 时判定为「严重超限」(如读入超大文件),
|
|
7
|
-
* 在请求前抛出 ContextOverflowError 中断对话。默认 1.
|
|
7
|
+
* 在请求前抛出 ContextOverflowError 中断对话。默认 1.5(即 +50%)。
|
|
8
8
|
*/
|
|
9
9
|
ratio?: number;
|
|
10
10
|
}
|
|
@@ -25,7 +25,7 @@ export class ContextGuardPlugin {
|
|
|
25
25
|
}
|
|
26
26
|
async onInnerLoopStart(ctx) {
|
|
27
27
|
const { agent } = ctx;
|
|
28
|
-
const { maxTokens, ratio = 1.
|
|
28
|
+
const { maxTokens, ratio = 1.5 } = this.options;
|
|
29
29
|
// 首轮请求前尚无用量数据,跳过(只能在发出首轮请求、拿到 usage 后才有据可查)
|
|
30
30
|
const promptTokens = agent.lastUsage?.prompt_tokens;
|
|
31
31
|
if (promptTokens == null)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { AgentPlugin, UnknownToolContext } from "@ai-zen/agents-core";
|
|
2
|
+
import type { Provider } from "../runtime/Provider.js";
|
|
3
|
+
/**
|
|
4
|
+
* 未知工具智能提示插件 — MCP 场景引导。
|
|
5
|
+
*
|
|
6
|
+
* 当 LLM 调用不存在的工具时,根据当前环境给出更智能的提示:
|
|
7
|
+
* - 有 MCP 配置但 `call_mcp_tool` 不在工具列表中(权限禁用)→ 提示权限问题
|
|
8
|
+
* - 有 MCP 配置且 `call_mcp_tool` 可用 → 提示使用 `call_mcp_tool`
|
|
9
|
+
* - 否则 → 仅提示工具不存在
|
|
10
|
+
*
|
|
11
|
+
* 由调用方显式注册(`agent.use(new UnknownToolHintPlugin({ provider }))`)。
|
|
12
|
+
* 未注册时,Agent 回落到底层的简单文本默认提示(core 内建)。
|
|
13
|
+
*/
|
|
14
|
+
export declare class UnknownToolHintPlugin implements AgentPlugin {
|
|
15
|
+
/** 全局 Provider 实例 */
|
|
16
|
+
private readonly provider;
|
|
17
|
+
constructor(options: {
|
|
18
|
+
provider: Provider;
|
|
19
|
+
});
|
|
20
|
+
onUnknownTool(ctx: UnknownToolContext): string | undefined;
|
|
21
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 未知工具智能提示插件 — MCP 场景引导。
|
|
3
|
+
*
|
|
4
|
+
* 当 LLM 调用不存在的工具时,根据当前环境给出更智能的提示:
|
|
5
|
+
* - 有 MCP 配置但 `call_mcp_tool` 不在工具列表中(权限禁用)→ 提示权限问题
|
|
6
|
+
* - 有 MCP 配置且 `call_mcp_tool` 可用 → 提示使用 `call_mcp_tool`
|
|
7
|
+
* - 否则 → 仅提示工具不存在
|
|
8
|
+
*
|
|
9
|
+
* 由调用方显式注册(`agent.use(new UnknownToolHintPlugin({ provider }))`)。
|
|
10
|
+
* 未注册时,Agent 回落到底层的简单文本默认提示(core 内建)。
|
|
11
|
+
*/
|
|
12
|
+
export class UnknownToolHintPlugin {
|
|
13
|
+
/** 全局 Provider 实例 */
|
|
14
|
+
provider;
|
|
15
|
+
constructor(options) {
|
|
16
|
+
this.provider = options.provider;
|
|
17
|
+
}
|
|
18
|
+
onUnknownTool(ctx) {
|
|
19
|
+
const toolName = ctx.toolCall.function?.name ?? "未知";
|
|
20
|
+
const hasMcpConfig = this.provider.mcpPaths.length > 0;
|
|
21
|
+
const hasCallMcpTool = ctx.availableTools.some((t) => t.function.name === "call_mcp_tool");
|
|
22
|
+
if (hasMcpConfig && !hasCallMcpTool) {
|
|
23
|
+
return `工具 "${toolName}" 不存在。当前有 MCP 服务器配置,但 call_mcp_tool 权限已被禁用,如需使用 MCP 工具请调整权限。`;
|
|
24
|
+
}
|
|
25
|
+
if (hasMcpConfig && hasCallMcpTool) {
|
|
26
|
+
return `工具 "${toolName}" 不存在。如果要调用 MCP 工具,请使用 call_mcp_tool。`;
|
|
27
|
+
}
|
|
28
|
+
return `工具 "${toolName}" 不存在。`;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Tool } from "@ai-zen/agents-core";
|
|
2
|
-
import type { AppConfig, AgentDefinition,
|
|
2
|
+
import type { AppConfig, AgentDefinition, McpServerConfig, ToolEnv } from "../types/index.js";
|
|
3
3
|
import type { SkillInfo } from "../capabilities/discovery/skills.js";
|
|
4
4
|
import { McpConnectionManager } from "./McpConnectionManager.js";
|
|
5
5
|
/**
|
|
@@ -22,6 +22,11 @@ export interface ExcludeOptions {
|
|
|
22
22
|
mcps?: string[];
|
|
23
23
|
subagents?: string[];
|
|
24
24
|
}
|
|
25
|
+
/** filter / buildTools 的过滤选项 */
|
|
26
|
+
export interface FilterOptions {
|
|
27
|
+
/** 排除项黑名单(优先级高于 permissions) */
|
|
28
|
+
exclude?: ExcludeOptions;
|
|
29
|
+
}
|
|
25
30
|
/**
|
|
26
31
|
* Provider — 全局上下文实例 + 能力注册表。
|
|
27
32
|
*
|
|
@@ -96,15 +101,11 @@ export declare class Provider {
|
|
|
96
101
|
* 按权限过滤候选集,返回过滤后的名称列表。
|
|
97
102
|
* 纯名称操作(安全预过滤 + 权限过滤),不涉及 Tool 实例化。
|
|
98
103
|
*/
|
|
99
|
-
filter(
|
|
100
|
-
exclude?: ExcludeOptions;
|
|
101
|
-
}): FilterOutput;
|
|
104
|
+
filter(definition: AgentDefinition, options?: FilterOptions): FilterOutput;
|
|
102
105
|
/**
|
|
103
106
|
* 快捷方法:filter + instantiate 一步完成。
|
|
104
107
|
*/
|
|
105
|
-
buildTools(
|
|
106
|
-
exclude?: ExcludeOptions;
|
|
107
|
-
}): Tool[];
|
|
108
|
+
buildTools(definition: AgentDefinition, options?: FilterOptions): Tool[];
|
|
108
109
|
/**
|
|
109
110
|
* 将过滤后的名称列表实例化为 Tool 数组。
|
|
110
111
|
*/
|
package/dist/runtime/Provider.js
CHANGED
|
@@ -91,7 +91,7 @@ export class Provider {
|
|
|
91
91
|
* 按权限过滤候选集,返回过滤后的名称列表。
|
|
92
92
|
* 纯名称操作(安全预过滤 + 权限过滤),不涉及 Tool 实例化。
|
|
93
93
|
*/
|
|
94
|
-
filter(
|
|
94
|
+
filter(definition, options) {
|
|
95
95
|
const exclude = options?.exclude ?? {};
|
|
96
96
|
const excludeTools = new Set(exclude.tools ?? []);
|
|
97
97
|
const excludeSkills = new Set(exclude.skills ?? []);
|
|
@@ -112,7 +112,17 @@ export class Provider {
|
|
|
112
112
|
...this.userTools.map((t) => t.function.name),
|
|
113
113
|
...DYNAMIC_TOOL_NAMES,
|
|
114
114
|
].filter((name) => !excludeTools.has(name));
|
|
115
|
-
|
|
115
|
+
// 工具可用性过滤:调用候选工具的 isAvailable(直接透传完整 app config + agent definition)。
|
|
116
|
+
// 工具自行声明可用条件(如依赖图片模型配置、仅视觉模型可用),返回 false 则剔除。
|
|
117
|
+
const candidates = [...this.builtinTools, ...this.userTools];
|
|
118
|
+
for (let i = toolNames.length - 1; i >= 0; i--) {
|
|
119
|
+
const tool = candidates.find((t) => t.function.name === toolNames[i]);
|
|
120
|
+
const isAvailable = tool?.isAvailable;
|
|
121
|
+
if (isAvailable && !isAvailable(this.config, definition)) {
|
|
122
|
+
toolNames.splice(i, 1);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
const evaluator = new PermissionEvaluator(definition.permissions);
|
|
116
126
|
const filtered = evaluator.filter({
|
|
117
127
|
tools: toolNames,
|
|
118
128
|
skills: this.skills
|
|
@@ -133,8 +143,8 @@ export class Provider {
|
|
|
133
143
|
/**
|
|
134
144
|
* 快捷方法:filter + instantiate 一步完成。
|
|
135
145
|
*/
|
|
136
|
-
buildTools(
|
|
137
|
-
return this.instantiate(this.filter(
|
|
146
|
+
buildTools(definition, options) {
|
|
147
|
+
return this.instantiate(this.filter(definition, options));
|
|
138
148
|
}
|
|
139
149
|
/**
|
|
140
150
|
* 将过滤后的名称列表实例化为 Tool 数组。
|
|
@@ -1,127 +1,34 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import type {
|
|
1
|
+
import type OpenAI from "openai";
|
|
2
|
+
import { Agent } from "@ai-zen/agents-core";
|
|
3
|
+
import type { AgentNS, Tool } from "@ai-zen/agents-core";
|
|
4
|
+
import type { AgentDefinition } from "../types/index.js";
|
|
4
5
|
import type { Provider } from "./Provider.js";
|
|
5
|
-
|
|
6
|
-
* Agent 插件上下文:当前 SdkAgent + 发送内容 + 消息列表。
|
|
7
|
-
*
|
|
8
|
-
* 注意:
|
|
9
|
-
* - messages 是当前 agent 消息数组的**快照**(浅拷贝),插件不应直接修改它。
|
|
10
|
-
* 所有消息变更应通过 agent 上的方法进行。
|
|
11
|
-
* - 如果 onAfterSend 替换了 ctx.agent,send() 方法会使用新 agent 的消息作为返回值。
|
|
12
|
-
*/
|
|
13
|
-
export interface SendContext {
|
|
14
|
-
agent: SdkAgent;
|
|
15
|
-
content: string;
|
|
16
|
-
/** 当前 agent 消息数组的浅拷贝快照,仅供读取,不应直接修改 */
|
|
17
|
-
messages: AgentNS.Message[];
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Agent 插件接口。
|
|
21
|
-
* 每个插件单一职责,通过钩子介入 Agent 生命周期。
|
|
22
|
-
*
|
|
23
|
-
* onInit: Agent.init() 时调用,用于异步初始化
|
|
24
|
-
* onBeforeSend: Agent.send() 调用前触发。可用于刷新工具列表等。
|
|
25
|
-
* onAfterSend: Agent.send() 返回后调用。可通过 ctx.agent 替换当前 Agent。
|
|
26
|
-
* onInnerLoopStart: Agent 内循环开始前触发。由 Core Agent 在内循环中调用。
|
|
27
|
-
* onInnerLoopEnd: Agent 内循环结束后触发。由 Core Agent 在内循环中调用。
|
|
28
|
-
* onInnerLoopsStart: Agent 整组内循环开始前触发(一次 send 仅一次)。由 Core Agent 在 run() 的 while 循环前调用。
|
|
29
|
-
* onInnerLoopsEnd: Agent 整组内循环结束后触发(一次 send 仅一次)。由 Core Agent 在 run() 的 while 循环后调用。
|
|
30
|
-
* onToolCall: 单个工具调用执行前触发(对应 Core onToolCall 钩子)。
|
|
31
|
-
* 返回字符串 = 拒绝该工具(原因作为工具结果回给 LLM,工具不执行);
|
|
32
|
-
* 返回 undefined = 放行。多个插件按注册顺序调用,任一返回字符串即拒绝。
|
|
33
|
-
*/
|
|
34
|
-
export interface AgentPlugin {
|
|
35
|
-
/** Agent.init() 时调用,用于异步初始化 */
|
|
36
|
-
onInit?(): Promise<void>;
|
|
37
|
-
/** Agent.send() 调用前触发 */
|
|
38
|
-
onBeforeSend?(ctx: SendContext): Promise<void>;
|
|
39
|
-
/** Agent.send() 返回后调用,可通过 ctx.agent 替换当前 Agent */
|
|
40
|
-
onAfterSend?(ctx: SendContext): Promise<void>;
|
|
41
|
-
/** Agent 内循环开始前触发 */
|
|
42
|
-
onInnerLoopStart?(ctx: SendContext): Promise<void>;
|
|
43
|
-
/** Agent 内循环结束后触发 */
|
|
44
|
-
onInnerLoopEnd?(ctx: SendContext): Promise<void>;
|
|
45
|
-
/** Agent 整组内循环开始前触发(一次 send 仅一次) */
|
|
46
|
-
onInnerLoopsStart?(ctx: SendContext): Promise<void>;
|
|
47
|
-
/** Agent 整组内循环结束后触发(一次 send 仅一次) */
|
|
48
|
-
onInnerLoopsEnd?(ctx: SendContext): Promise<void>;
|
|
49
|
-
/**
|
|
50
|
-
* 单个工具调用执行前触发(对应 Core onToolCall 钩子,收同一个 ToolCallContext 实例)。
|
|
51
|
-
* 返回字符串 = 拒绝该工具(不执行,原因作为工具结果回给 LLM,继续下一轮);
|
|
52
|
-
* 返回 undefined = 放行。多个插件按注册顺序调用,任一返回字符串即拒绝。
|
|
53
|
-
*/
|
|
54
|
-
onToolCall?(ctx: ToolCallContext): string | undefined | Promise<string | undefined>;
|
|
55
|
-
}
|
|
6
|
+
export type { AgentPlugin, SendContext } from "@ai-zen/agents-core";
|
|
56
7
|
/**
|
|
57
8
|
* SDK Agent — 继承 Core Agent,携带 SDK 层额外信息。
|
|
58
9
|
*
|
|
59
|
-
* Core Agent
|
|
60
|
-
* SdkAgent 在 Core Agent 基础上增加了 SDK
|
|
61
|
-
* 并通过 provider 字段访问全局上下文。
|
|
62
|
-
*
|
|
63
|
-
* 携带:
|
|
10
|
+
* Core Agent 不感知权限、文件系统等业务逻辑;
|
|
11
|
+
* SdkAgent 在 Core Agent 基础上增加了 SDK 层需要的元数据:
|
|
64
12
|
* - provider:全局 Provider 实例
|
|
65
|
-
* - definition:Agent
|
|
66
|
-
* - permissions:Agent 权限,供 call_skill_sub_agent 等回调读取
|
|
13
|
+
* - definition:Agent 原始定义(含权限 permissions)
|
|
67
14
|
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
* - send():重写,在前后执行插件钩子
|
|
15
|
+
* 插件能力(use / init / send 钩子分发)继承自 Core Agent,此处不再重复实现。
|
|
16
|
+
* 未知工具的 MCP 智能提示由独立插件 `UnknownToolHintPlugin` 提供(调用方显式 use)。
|
|
17
|
+
* 权限统一从 `definition.permissions` 读取,不再单独持有。
|
|
72
18
|
*/
|
|
73
19
|
export declare class SdkAgent extends Agent {
|
|
74
20
|
/** 全局 Provider 实例 */
|
|
75
21
|
readonly provider: Provider;
|
|
76
22
|
/** Agent 原始定义 */
|
|
77
23
|
readonly definition: AgentDefinition;
|
|
78
|
-
/** Agent 权限 */
|
|
79
|
-
readonly permissions?: AgentPermissions;
|
|
80
|
-
/**
|
|
81
|
-
* 当 LLM 调用不存在的工具时,给出智能提示。
|
|
82
|
-
* 如果有 MCP 配置但 call_mcp_tool 不在工具列表中(权限禁用),提示权限问题;
|
|
83
|
-
* 如果有 MCP 配置且 call_mcp_tool 可用,提示使用 call_mcp_tool;
|
|
84
|
-
* 否则仅提示工具不存在。
|
|
85
|
-
*/
|
|
86
|
-
onUnknownTool: (ctx: UnknownToolContext) => string;
|
|
87
|
-
/** 已注册的插件列表 */
|
|
88
|
-
private _plugins;
|
|
89
24
|
constructor(params: {
|
|
90
25
|
provider: Provider;
|
|
91
26
|
definition: AgentDefinition;
|
|
92
|
-
|
|
93
|
-
|
|
27
|
+
client: OpenAI;
|
|
28
|
+
model: string;
|
|
29
|
+
modelConfig?: Record<string, unknown>;
|
|
94
30
|
messages?: AgentNS.Message[];
|
|
95
31
|
tools?: Tool[];
|
|
96
|
-
permissions?: AgentPermissions;
|
|
97
|
-
rag?: any;
|
|
98
32
|
allowJsonParseError?: boolean;
|
|
99
33
|
});
|
|
100
|
-
/**
|
|
101
|
-
* 注册一个插件。
|
|
102
|
-
* 可以在 init() 之前或之后调用,但 beforeSend/afterSend 钩子仅在
|
|
103
|
-
* init() 之后发送消息时生效。
|
|
104
|
-
*/
|
|
105
|
-
use(plugin: AgentPlugin): void;
|
|
106
|
-
/**
|
|
107
|
-
* 初始化所有已注册插件。
|
|
108
|
-
* SdkAgent 本身没有异步初始化需求——模型、工具、消息在构造时已就绪。
|
|
109
|
-
* init() 的存在完全是为了给插件一个执行异步初始化的机会。
|
|
110
|
-
*
|
|
111
|
-
* 如果不使用任何插件,可以不调 init()。
|
|
112
|
-
*/
|
|
113
|
-
init(): Promise<void>;
|
|
114
|
-
/**
|
|
115
|
-
* 发送消息,在前后执行插件钩子。
|
|
116
|
-
*
|
|
117
|
-
* 流程:
|
|
118
|
-
* 1. onBeforeSend — send 外部准备(刷新工具等)
|
|
119
|
-
* 2. super.send() — 委托 Core Agent,内含内循环及其钩子
|
|
120
|
-
* 3. onAfterSend — send 外部后处理(保存草稿、迁移等)
|
|
121
|
-
*
|
|
122
|
-
* 注意:
|
|
123
|
-
* - ctx.messages 是当前 agent 消息的**浅拷贝快照**,仅供读取,不应直接修改。
|
|
124
|
-
* 所有消息变更应通过 agent 上的方法进行(如 agent.messages.push 等)。
|
|
125
|
-
*/
|
|
126
|
-
send(content: string): Promise<AgentNS.Message[]>;
|
|
127
34
|
}
|
package/dist/runtime/SdkAgent.js
CHANGED
|
@@ -1,143 +1,31 @@
|
|
|
1
1
|
import { Agent } from "@ai-zen/agents-core";
|
|
2
|
-
// ---------------------------------------------------------------------------
|
|
3
|
-
// SdkAgent
|
|
4
|
-
// ---------------------------------------------------------------------------
|
|
5
2
|
/**
|
|
6
3
|
* SDK Agent — 继承 Core Agent,携带 SDK 层额外信息。
|
|
7
4
|
*
|
|
8
|
-
* Core Agent
|
|
9
|
-
* SdkAgent 在 Core Agent 基础上增加了 SDK
|
|
10
|
-
* 并通过 provider 字段访问全局上下文。
|
|
11
|
-
*
|
|
12
|
-
* 携带:
|
|
5
|
+
* Core Agent 不感知权限、文件系统等业务逻辑;
|
|
6
|
+
* SdkAgent 在 Core Agent 基础上增加了 SDK 层需要的元数据:
|
|
13
7
|
* - provider:全局 Provider 实例
|
|
14
|
-
* - definition:Agent
|
|
15
|
-
* - permissions:Agent 权限,供 call_skill_sub_agent 等回调读取
|
|
8
|
+
* - definition:Agent 原始定义(含权限 permissions)
|
|
16
9
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* - send():重写,在前后执行插件钩子
|
|
10
|
+
* 插件能力(use / init / send 钩子分发)继承自 Core Agent,此处不再重复实现。
|
|
11
|
+
* 未知工具的 MCP 智能提示由独立插件 `UnknownToolHintPlugin` 提供(调用方显式 use)。
|
|
12
|
+
* 权限统一从 `definition.permissions` 读取,不再单独持有。
|
|
21
13
|
*/
|
|
22
14
|
export class SdkAgent extends Agent {
|
|
23
15
|
/** 全局 Provider 实例 */
|
|
24
16
|
provider;
|
|
25
17
|
/** Agent 原始定义 */
|
|
26
18
|
definition;
|
|
27
|
-
/** Agent 权限 */
|
|
28
|
-
permissions;
|
|
29
|
-
/**
|
|
30
|
-
* 当 LLM 调用不存在的工具时,给出智能提示。
|
|
31
|
-
* 如果有 MCP 配置但 call_mcp_tool 不在工具列表中(权限禁用),提示权限问题;
|
|
32
|
-
* 如果有 MCP 配置且 call_mcp_tool 可用,提示使用 call_mcp_tool;
|
|
33
|
-
* 否则仅提示工具不存在。
|
|
34
|
-
*/
|
|
35
|
-
onUnknownTool = (ctx) => {
|
|
36
|
-
const toolName = ctx.toolCall.function?.name ?? "未知";
|
|
37
|
-
const hasMcpConfig = this.provider.mcpPaths.length > 0;
|
|
38
|
-
const hasCallMcpTool = (this.tools ?? []).some((t) => t.function.name === "call_mcp_tool");
|
|
39
|
-
if (hasMcpConfig && !hasCallMcpTool) {
|
|
40
|
-
return `工具 "${toolName}" 不存在。当前有 MCP 服务器配置,但 call_mcp_tool 权限已被禁用,如需使用 MCP 工具请调整权限。`;
|
|
41
|
-
}
|
|
42
|
-
if (hasMcpConfig && hasCallMcpTool) {
|
|
43
|
-
return `工具 "${toolName}" 不存在。如果要调用 MCP 工具,请使用 call_mcp_tool。`;
|
|
44
|
-
}
|
|
45
|
-
return `工具 "${toolName}" 不存在。`;
|
|
46
|
-
};
|
|
47
|
-
/** 已注册的插件列表 */
|
|
48
|
-
_plugins = [];
|
|
49
19
|
constructor(params) {
|
|
50
20
|
super({
|
|
21
|
+
client: params.client,
|
|
51
22
|
model: params.model,
|
|
52
|
-
|
|
23
|
+
modelConfig: params.modelConfig,
|
|
53
24
|
messages: params.messages,
|
|
54
25
|
tools: params.tools,
|
|
55
|
-
rag: params.rag,
|
|
56
26
|
allowJsonParseError: params.allowJsonParseError,
|
|
57
27
|
});
|
|
58
28
|
this.provider = params.provider;
|
|
59
29
|
this.definition = params.definition;
|
|
60
|
-
this.permissions = params.permissions;
|
|
61
|
-
}
|
|
62
|
-
/**
|
|
63
|
-
* 注册一个插件。
|
|
64
|
-
* 可以在 init() 之前或之后调用,但 beforeSend/afterSend 钩子仅在
|
|
65
|
-
* init() 之后发送消息时生效。
|
|
66
|
-
*/
|
|
67
|
-
use(plugin) {
|
|
68
|
-
this._plugins.push(plugin);
|
|
69
|
-
}
|
|
70
|
-
/**
|
|
71
|
-
* 初始化所有已注册插件。
|
|
72
|
-
* SdkAgent 本身没有异步初始化需求——模型、工具、消息在构造时已就绪。
|
|
73
|
-
* init() 的存在完全是为了给插件一个执行异步初始化的机会。
|
|
74
|
-
*
|
|
75
|
-
* 如果不使用任何插件,可以不调 init()。
|
|
76
|
-
*/
|
|
77
|
-
async init() {
|
|
78
|
-
for (const plugin of this._plugins) {
|
|
79
|
-
await plugin.onInit?.();
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
/**
|
|
83
|
-
* 发送消息,在前后执行插件钩子。
|
|
84
|
-
*
|
|
85
|
-
* 流程:
|
|
86
|
-
* 1. onBeforeSend — send 外部准备(刷新工具等)
|
|
87
|
-
* 2. super.send() — 委托 Core Agent,内含内循环及其钩子
|
|
88
|
-
* 3. onAfterSend — send 外部后处理(保存草稿、迁移等)
|
|
89
|
-
*
|
|
90
|
-
* 注意:
|
|
91
|
-
* - ctx.messages 是当前 agent 消息的**浅拷贝快照**,仅供读取,不应直接修改。
|
|
92
|
-
* 所有消息变更应通过 agent 上的方法进行(如 agent.messages.push 等)。
|
|
93
|
-
*/
|
|
94
|
-
async send(content) {
|
|
95
|
-
const ctx = {
|
|
96
|
-
agent: this,
|
|
97
|
-
content,
|
|
98
|
-
messages: [...this.messages],
|
|
99
|
-
};
|
|
100
|
-
for (const plugin of this._plugins) {
|
|
101
|
-
await plugin.onBeforeSend?.(ctx);
|
|
102
|
-
}
|
|
103
|
-
this.onInnerLoopStart = async () => {
|
|
104
|
-
for (const plugin of this._plugins) {
|
|
105
|
-
await plugin.onInnerLoopStart?.(ctx);
|
|
106
|
-
}
|
|
107
|
-
};
|
|
108
|
-
this.onInnerLoopEnd = async () => {
|
|
109
|
-
for (const plugin of this._plugins) {
|
|
110
|
-
await plugin.onInnerLoopEnd?.(ctx);
|
|
111
|
-
}
|
|
112
|
-
};
|
|
113
|
-
this.onInnerLoopsStart = async () => {
|
|
114
|
-
for (const plugin of this._plugins) {
|
|
115
|
-
await plugin.onInnerLoopsStart?.(ctx);
|
|
116
|
-
}
|
|
117
|
-
};
|
|
118
|
-
this.onInnerLoopsEnd = async () => {
|
|
119
|
-
for (const plugin of this._plugins) {
|
|
120
|
-
await plugin.onInnerLoopsEnd?.(ctx);
|
|
121
|
-
}
|
|
122
|
-
};
|
|
123
|
-
// 工具调用拦截:任一插件返回字符串即拒绝该工具(短路),全部放行则返回 undefined
|
|
124
|
-
this.onToolCall = async (ctx) => {
|
|
125
|
-
for (const plugin of this._plugins) {
|
|
126
|
-
const denied = await plugin.onToolCall?.(ctx);
|
|
127
|
-
if (denied !== undefined)
|
|
128
|
-
return denied;
|
|
129
|
-
}
|
|
130
|
-
return undefined;
|
|
131
|
-
};
|
|
132
|
-
await super.send(content);
|
|
133
|
-
this.onInnerLoopStart = undefined;
|
|
134
|
-
this.onInnerLoopEnd = undefined;
|
|
135
|
-
this.onInnerLoopsStart = undefined;
|
|
136
|
-
this.onInnerLoopsEnd = undefined;
|
|
137
|
-
this.onToolCall = undefined;
|
|
138
|
-
for (const plugin of this._plugins) {
|
|
139
|
-
await plugin.onAfterSend?.(ctx);
|
|
140
|
-
}
|
|
141
|
-
return this.messages;
|
|
142
30
|
}
|
|
143
31
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Tool, ToolCallContext } from "@ai-zen/agents-core";
|
|
2
2
|
import type { AgentNS } from "@ai-zen/agents-core";
|
|
3
|
-
import type { ToolEnv } from "../types/index.js";
|
|
3
|
+
import type { AgentDefinition, AppConfig, ToolEnv } from "../types/index.js";
|
|
4
4
|
/** SdkCallbackTool 构造选项。env 为核心字段,未来可在此扩展可选项。 */
|
|
5
5
|
export interface SdkCallbackToolOptions {
|
|
6
6
|
/** 注入的工具环境 */
|
|
@@ -23,14 +23,22 @@ export declare abstract class SdkCallbackTool extends Tool {
|
|
|
23
23
|
readonly env: ToolEnv;
|
|
24
24
|
/** 工具定义。由子类以类体字段 function = {...} 提供。 */
|
|
25
25
|
function: AgentNS.FunctionDefine;
|
|
26
|
+
/**
|
|
27
|
+
* 工具对当前 Agent 的可用性判断。由工具自行声明,直接透传完整
|
|
28
|
+
* app config 与 agent definition(含 modelId / permissions 等),工具自取所需
|
|
29
|
+
* (如是否配置了图片模型、当前模型是否为视觉模型)。
|
|
30
|
+
* 在 buildTools/filter 阶段调用;返回 false 的工具不会注册给该 Agent。
|
|
31
|
+
* 不实现则默认可用。
|
|
32
|
+
*/
|
|
33
|
+
isAvailable?(config: AppConfig, definition: AgentDefinition): boolean;
|
|
26
34
|
constructor(options: SdkCallbackToolOptions);
|
|
27
35
|
/**
|
|
28
|
-
* 工具核心逻辑(由子类实现,参数为
|
|
36
|
+
* 工具核心逻辑(由子类实现,参数为 parsedArgs)。
|
|
29
37
|
* 可选第二参 ctx:透传完整 ToolCallContext,需中止能力(signal)的工具自行读取。
|
|
30
38
|
*/
|
|
31
39
|
abstract call(input: unknown, ctx?: ToolCallContext): unknown | Promise<unknown>;
|
|
32
|
-
/** 桥接 core 的 Tool.exec:解析参数 → call →
|
|
33
|
-
exec(ctx: ToolCallContext): Promise<
|
|
40
|
+
/** 桥接 core 的 Tool.exec:解析参数 → call → 序列化/透传内容块 */
|
|
41
|
+
exec(ctx: ToolCallContext): Promise<AgentNS.MessageContent>;
|
|
34
42
|
/** 将相对路径解析到 env.cwd,绝对路径原样返回 */
|
|
35
43
|
resolve(p: string): string;
|
|
36
44
|
}
|