@ai-zen/agents-sdk 0.2.1 → 0.2.3
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 +19 -0
- package/dist/capabilities/Capabilities.js +7 -6
- package/dist/capabilities/discovery/mcp.d.ts +6 -1
- package/dist/capabilities/discovery/mcp.js +62 -8
- package/dist/capabilities/implements/mcpTools.d.ts +3 -5
- package/dist/capabilities/implements/mcpTools.js +11 -5
- package/dist/plugin/AutoMigratePlugin.d.ts +10 -4
- package/dist/plugin/AutoMigratePlugin.js +19 -11
- package/dist/runtime/McpConnectionManager.js +4 -2
- package/dist/runtime/Provider.d.ts +8 -16
- package/dist/runtime/Provider.js +12 -8
- package/dist/runtime/SdkAgent.d.ts +10 -0
- package/dist/runtime/SdkAgent.js +7 -3
- package/dist/runtime/TaskMigrationService.js +1 -3
- package/dist/types/index.d.ts +4 -4
- package/package.json +1 -1
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [0.2.2] - 2026-07-20
|
|
4
|
+
|
|
5
|
+
### 🔧 修复
|
|
6
|
+
|
|
7
|
+
- **`SdkAgent.send()` — `ctx.messages` 不再直接引用 `this.messages`** — 改为浅拷贝快照,确保消息数组仅由 agent 作为唯一维护者
|
|
8
|
+
- **`AutoMigratePlugin` — 不再创建新 Agent 实例** — 直接替换 `agent.messages` 数组,保留所有引用、插件绑定和事件监听
|
|
9
|
+
- **`AutoMigratePlugin` — 迁移前增加日志提示** — 使用 `log.warn` 输出迁移开始通知
|
|
10
|
+
|
|
11
|
+
### 🎯 优化
|
|
12
|
+
|
|
13
|
+
- **`AutoMigratePlugin` — `onHandoff` 签名简化** — 从 `(doc, oldAgent, newAgent)` 改为 `(doc, agent)`,因为 agent 是同一对象
|
|
14
|
+
- **`TaskMigrationService.createPrompt()` — 精简提示词** — 明确要求只输出交接文档,不做任何解释
|
|
15
|
+
|
|
16
|
+
### ✅ 测试
|
|
17
|
+
|
|
18
|
+
- 补充迁移前后消息数组**长度精确断言**(迁移前 3 条 → 迁移后 2 条)
|
|
19
|
+
- 补充迁移失败时消息数组**长度和内容不变**的断言
|
|
@@ -116,14 +116,15 @@ export class Capabilities {
|
|
|
116
116
|
if (allowedToolNames.has("call_skill_sub_agent") && hasSubAgentSkills) {
|
|
117
117
|
result.push(createCallSkillSubAgentTool(provider.skillsPaths, filteredSkills, this));
|
|
118
118
|
}
|
|
119
|
-
|
|
120
|
-
|
|
119
|
+
const mcpManager = provider.getMcpManager();
|
|
120
|
+
if (allowedToolNames.has("load_mcp") && mcpManager && filteredMcps.length > 0) {
|
|
121
|
+
result.push(createLoadMcpTool(mcpManager, filteredMcps));
|
|
121
122
|
}
|
|
122
|
-
if (allowedToolNames.has("call_mcp_tool") &&
|
|
123
|
-
result.push(createCallMcpTool(
|
|
123
|
+
if (allowedToolNames.has("call_mcp_tool") && mcpManager) {
|
|
124
|
+
result.push(createCallMcpTool(mcpManager));
|
|
124
125
|
}
|
|
125
|
-
if (allowedToolNames.has("read_mcp_resource") &&
|
|
126
|
-
result.push(createReadMcpResourceTool(
|
|
126
|
+
if (allowedToolNames.has("read_mcp_resource") && mcpManager) {
|
|
127
|
+
result.push(createReadMcpResourceTool(mcpManager));
|
|
127
128
|
}
|
|
128
129
|
// 4. SubAgent
|
|
129
130
|
const allowedSubagentSet = new Set(filtered.subagents);
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import type { McpServerConfig } from "../../types/index.js";
|
|
2
2
|
/**
|
|
3
3
|
* 从 mcp.json 文件列表中发现所有 MCP server 配置。
|
|
4
|
+
*
|
|
5
|
+
* 遵循业界标准格式:
|
|
6
|
+
* ```json
|
|
7
|
+
* { "mcpServers": { "server-id": { "type": "stdio", "command": "npx", ... } } }
|
|
8
|
+
* ```
|
|
9
|
+
*
|
|
4
10
|
* 按优先级从高到低传入路径列表,同名 server 靠前的文件优先(先到先得)。
|
|
5
|
-
* 返回完整配置,不再丢失信息。
|
|
6
11
|
*/
|
|
7
12
|
export declare function discoverMcpServers(paths: string[]): McpServerConfig[];
|
|
@@ -1,8 +1,55 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
/**
|
|
3
|
+
* 归一化原始 MCP server 配置为内部 McpServerConfig。
|
|
4
|
+
* 处理业界标准中的字段别名差异。
|
|
5
|
+
*/
|
|
6
|
+
function normalizeConfig(id, raw) {
|
|
7
|
+
// disabled 处理
|
|
8
|
+
if (raw.disabled === true)
|
|
9
|
+
return null;
|
|
10
|
+
// transport 类型:优先取 type,兼容 transport/transportType
|
|
11
|
+
const transportRaw = (raw.type ?? raw.transport ?? raw.transportType ?? "");
|
|
12
|
+
const transport = normalizeTransport(transportRaw, raw);
|
|
13
|
+
if (!transport)
|
|
14
|
+
return null;
|
|
15
|
+
const config = {
|
|
16
|
+
id,
|
|
17
|
+
transport,
|
|
18
|
+
command: raw.command,
|
|
19
|
+
args: raw.args,
|
|
20
|
+
env: raw.env,
|
|
21
|
+
url: raw.url,
|
|
22
|
+
headers: raw.headers,
|
|
23
|
+
};
|
|
24
|
+
return config;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* 归一化 transport 取值。
|
|
28
|
+
* 不填时自动推断:有 command→stdio,有 url→http。
|
|
29
|
+
*/
|
|
30
|
+
function normalizeTransport(type, raw) {
|
|
31
|
+
if (type === "stdio")
|
|
32
|
+
return "stdio";
|
|
33
|
+
if (type === "http")
|
|
34
|
+
return "http";
|
|
35
|
+
if (type === "sse")
|
|
36
|
+
return "sse";
|
|
37
|
+
// 自动推断
|
|
38
|
+
if (raw.command)
|
|
39
|
+
return "stdio";
|
|
40
|
+
if (raw.url)
|
|
41
|
+
return "http";
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
2
44
|
/**
|
|
3
45
|
* 从 mcp.json 文件列表中发现所有 MCP server 配置。
|
|
46
|
+
*
|
|
47
|
+
* 遵循业界标准格式:
|
|
48
|
+
* ```json
|
|
49
|
+
* { "mcpServers": { "server-id": { "type": "stdio", "command": "npx", ... } } }
|
|
50
|
+
* ```
|
|
51
|
+
*
|
|
4
52
|
* 按优先级从高到低传入路径列表,同名 server 靠前的文件优先(先到先得)。
|
|
5
|
-
* 返回完整配置,不再丢失信息。
|
|
6
53
|
*/
|
|
7
54
|
export function discoverMcpServers(paths) {
|
|
8
55
|
const seen = new Set();
|
|
@@ -13,16 +60,23 @@ export function discoverMcpServers(paths) {
|
|
|
13
60
|
try {
|
|
14
61
|
const raw = readFileSync(path, "utf-8");
|
|
15
62
|
const config = JSON.parse(raw);
|
|
16
|
-
|
|
63
|
+
// 业界标准使用 mcpServers 顶层字段
|
|
64
|
+
const servers = config.mcpServers ?? {};
|
|
17
65
|
for (const id of Object.keys(servers)) {
|
|
18
|
-
if (
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
66
|
+
if (seen.has(id))
|
|
67
|
+
continue;
|
|
68
|
+
const rawServer = servers[id];
|
|
69
|
+
if (!rawServer || typeof rawServer !== "object")
|
|
70
|
+
continue;
|
|
71
|
+
const normalized = normalizeConfig(id, rawServer);
|
|
72
|
+
if (!normalized)
|
|
73
|
+
continue;
|
|
74
|
+
seen.add(id);
|
|
75
|
+
items.push(normalized);
|
|
22
76
|
}
|
|
23
77
|
}
|
|
24
|
-
catch {
|
|
25
|
-
|
|
78
|
+
catch (err) {
|
|
79
|
+
console.warn(`[sdk] 解析 MCP 配置失败: ${path}`, err);
|
|
26
80
|
}
|
|
27
81
|
}
|
|
28
82
|
return items;
|
|
@@ -3,12 +3,10 @@ import type { McpConnectionManager } from "../../runtime/McpConnectionManager.js
|
|
|
3
3
|
import type { McpServerConfig } from "../../types/index.js";
|
|
4
4
|
/**
|
|
5
5
|
* 创建 load_mcp 工具。
|
|
6
|
-
* server 枚举由 filteredMcps (完整 McpServerConfig[]
|
|
6
|
+
* server 枚举由 filteredMcps (完整 McpServerConfig[])自动推导,
|
|
7
|
+
* 查找配置也直接使用 filteredMcps,与枚举来源一致。
|
|
7
8
|
*/
|
|
8
|
-
export declare function createLoadMcpTool(mcpManager: McpConnectionManager,
|
|
9
|
-
name: string;
|
|
10
|
-
config: McpServerConfig;
|
|
11
|
-
}>, filteredMcps: McpServerConfig[]): CallbackTool;
|
|
9
|
+
export declare function createLoadMcpTool(mcpManager: McpConnectionManager, filteredMcps: McpServerConfig[]): CallbackTool;
|
|
12
10
|
/**
|
|
13
11
|
* 创建 call_mcp_tool 工具。
|
|
14
12
|
* 通过官方 Client.callTool() API 调用 MCP 服务器上的工具。
|
|
@@ -3,9 +3,15 @@ import { createDisclosureParam } from "../disclosure.js";
|
|
|
3
3
|
const EMPTY_HINT = "(当前没有可用的 MCP 服务器,请联系用户添加)";
|
|
4
4
|
/**
|
|
5
5
|
* 创建 load_mcp 工具。
|
|
6
|
-
* server 枚举由 filteredMcps (完整 McpServerConfig[]
|
|
6
|
+
* server 枚举由 filteredMcps (完整 McpServerConfig[])自动推导,
|
|
7
|
+
* 查找配置也直接使用 filteredMcps,与枚举来源一致。
|
|
7
8
|
*/
|
|
8
|
-
export function createLoadMcpTool(mcpManager,
|
|
9
|
+
export function createLoadMcpTool(mcpManager, filteredMcps) {
|
|
10
|
+
// 构建 id→config 查找表
|
|
11
|
+
const configMap = new Map();
|
|
12
|
+
for (const s of filteredMcps) {
|
|
13
|
+
configMap.set(s.id, s);
|
|
14
|
+
}
|
|
9
15
|
const ids = filteredMcps.map((s) => s.id);
|
|
10
16
|
const param = createDisclosureParam(ids, "选择一个 MCP 服务器", EMPTY_HINT);
|
|
11
17
|
return new CallbackTool({
|
|
@@ -27,8 +33,8 @@ export function createLoadMcpTool(mcpManager, mcpConfigs, filteredMcps) {
|
|
|
27
33
|
},
|
|
28
34
|
callback: async (input) => {
|
|
29
35
|
const serverName = input.server;
|
|
30
|
-
const
|
|
31
|
-
if (!
|
|
36
|
+
const config = configMap.get(serverName);
|
|
37
|
+
if (!config) {
|
|
32
38
|
return `❌ MCP 服务器 "${serverName}" 不存在`;
|
|
33
39
|
}
|
|
34
40
|
const existingManifest = mcpManager.getManifest(serverName);
|
|
@@ -38,7 +44,7 @@ export function createLoadMcpTool(mcpManager, mcpConfigs, filteredMcps) {
|
|
|
38
44
|
return `✅ MCP 服务器 "${serverName}" 已连接 (${existingManifest.tools.length} 个工具):\n${toolList}`;
|
|
39
45
|
}
|
|
40
46
|
try {
|
|
41
|
-
const manifest = await mcpManager.connect(serverName,
|
|
47
|
+
const manifest = await mcpManager.connect(serverName, config);
|
|
42
48
|
const toolList = manifest.tools.map((t) => `- ${t.name}: ${t.description}`).join("\n");
|
|
43
49
|
return `✅ MCP 服务器 "${serverName}" 已连接 (${manifest.tools.length} 个工具):\n${toolList}`;
|
|
44
50
|
}
|
|
@@ -1,18 +1,24 @@
|
|
|
1
|
-
import { SdkAgent } from "../runtime/SdkAgent.js";
|
|
2
1
|
import type { AgentPlugin, SendContext } from "../runtime/SdkAgent.js";
|
|
2
|
+
import { SdkAgent } from "../runtime/SdkAgent.js";
|
|
3
3
|
export interface AutoMigrateOptions {
|
|
4
4
|
maxTokens: number;
|
|
5
5
|
migrationAgent: SdkAgent;
|
|
6
|
-
|
|
6
|
+
/** 迁移开始前触发(promptTokens 刚超限时),可在此向用户展示迁移提示 */
|
|
7
|
+
onBeforeMigrate?: (promptTokens: number, maxTokens: number, agent: SdkAgent) => void;
|
|
8
|
+
/** 迁移完成后触发(交接文档已注入 agent.messages),可在此保存对话等 */
|
|
9
|
+
onHandoff?: (handoffDoc: string, agent: SdkAgent) => void;
|
|
7
10
|
}
|
|
8
11
|
/**
|
|
9
12
|
* 自动迁移插件。
|
|
10
13
|
*
|
|
14
|
+
* 当 token 使用量超过 maxTokens 时,自动将对话历史交给 migrationAgent 生成交接文档,
|
|
15
|
+
* 然后用交接文档替换当前 agent 的消息列表,实现无缝迁移。
|
|
16
|
+
*
|
|
11
17
|
* ```ts
|
|
12
18
|
* agent.use(new AutoMigratePlugin({
|
|
13
19
|
* maxTokens: 250_000,
|
|
14
|
-
* migrationAgent,
|
|
15
|
-
* onHandoff: (doc,
|
|
20
|
+
* migrationAgent: anotherAgent,
|
|
21
|
+
* onHandoff: (doc, agent) => { ... },
|
|
16
22
|
* }));
|
|
17
23
|
* ```
|
|
18
24
|
*/
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import { AgentNS } from "@ai-zen/agents-core";
|
|
2
|
-
import { SdkAgent } from "../runtime/SdkAgent.js";
|
|
3
2
|
import { TaskMigrationService } from "../runtime/TaskMigrationService.js";
|
|
4
3
|
import { createLogger } from "../shared/logger.js";
|
|
5
4
|
const log = createLogger();
|
|
6
5
|
/**
|
|
7
6
|
* 自动迁移插件。
|
|
8
7
|
*
|
|
8
|
+
* 当 token 使用量超过 maxTokens 时,自动将对话历史交给 migrationAgent 生成交接文档,
|
|
9
|
+
* 然后用交接文档替换当前 agent 的消息列表,实现无缝迁移。
|
|
10
|
+
*
|
|
9
11
|
* ```ts
|
|
10
12
|
* agent.use(new AutoMigratePlugin({
|
|
11
13
|
* maxTokens: 250_000,
|
|
12
|
-
* migrationAgent,
|
|
13
|
-
* onHandoff: (doc,
|
|
14
|
+
* migrationAgent: anotherAgent,
|
|
15
|
+
* onHandoff: (doc, agent) => { ... },
|
|
14
16
|
* }));
|
|
15
17
|
* ```
|
|
16
18
|
*/
|
|
@@ -21,27 +23,33 @@ export class AutoMigratePlugin {
|
|
|
21
23
|
}
|
|
22
24
|
async onAfterSend(ctx) {
|
|
23
25
|
const { agent } = ctx;
|
|
24
|
-
const { maxTokens, migrationAgent, onHandoff } = this.options;
|
|
26
|
+
const { maxTokens, migrationAgent, onBeforeMigrate, onHandoff } = this.options;
|
|
25
27
|
const promptTokens = agent.lastUsage?.prompt_tokens;
|
|
26
28
|
if (promptTokens == null)
|
|
27
29
|
return;
|
|
28
30
|
if (!TaskMigrationService.shouldMigrate(promptTokens, maxTokens))
|
|
29
31
|
return;
|
|
32
|
+
// 迁移前钩子:由上层(CLI)处理用户提示
|
|
33
|
+
if (onBeforeMigrate) {
|
|
34
|
+
try {
|
|
35
|
+
await onBeforeMigrate(promptTokens, maxTokens, agent);
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
log.error(`[autoMigrate] onBeforeMigrate 回调失败: ${err?.message ?? err}`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
30
41
|
try {
|
|
31
42
|
const historyText = this.serializeMessages(agent.messages);
|
|
32
43
|
const migrationResult = await migrationAgent.send(historyText);
|
|
33
44
|
const handoffDoc = this.getLastAssistantContent(migrationResult);
|
|
34
45
|
if (!handoffDoc)
|
|
35
46
|
return;
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
];
|
|
40
|
-
const newAgent = new SdkAgent({ ...agent, messages: newMessages });
|
|
41
|
-
ctx.agent = newAgent;
|
|
47
|
+
// 仅替换消息列表,不重建 agent,保留所有引用和插件绑定
|
|
48
|
+
agent.messages.length = 0;
|
|
49
|
+
agent.messages.push(...agent.definition.messages, ...TaskMigrationService.createPostMessages(handoffDoc));
|
|
42
50
|
if (onHandoff) {
|
|
43
51
|
try {
|
|
44
|
-
await onHandoff(handoffDoc, agent
|
|
52
|
+
await onHandoff(handoffDoc, agent);
|
|
45
53
|
}
|
|
46
54
|
catch (err) {
|
|
47
55
|
log.error(`[autoMigrate] onHandoff 回调失败: ${err?.message ?? err}`);
|
|
@@ -4,6 +4,7 @@ import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/
|
|
|
4
4
|
const DEFAULT_IDLE_TIMEOUT = {
|
|
5
5
|
stdio: 30 * 60 * 1000,
|
|
6
6
|
http: 5 * 60 * 1000,
|
|
7
|
+
sse: 5 * 60 * 1000,
|
|
7
8
|
};
|
|
8
9
|
/** 指数退避: 1s → 2s → 4s → 8s → 16s → 30s(封顶) */
|
|
9
10
|
function backoff(attempt) {
|
|
@@ -169,9 +170,10 @@ export class McpConnectionManager {
|
|
|
169
170
|
env: config.env,
|
|
170
171
|
});
|
|
171
172
|
}
|
|
172
|
-
|
|
173
|
+
// http 和 sse 都使用 StreamableHTTPClientTransport
|
|
174
|
+
if (config.transport === "http" || config.transport === "sse") {
|
|
173
175
|
if (!config.url) {
|
|
174
|
-
throw new Error(`MCP
|
|
176
|
+
throw new Error(`MCP ${config.transport} server 缺少 url`);
|
|
175
177
|
}
|
|
176
178
|
return new StreamableHTTPClientTransport(new URL(config.url), {
|
|
177
179
|
requestInit: config.headers ? { headers: config.headers } : undefined,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { AppConfig
|
|
2
|
-
import
|
|
1
|
+
import type { AppConfig } from "../types/index.js";
|
|
2
|
+
import { McpConnectionManager } from "./McpConnectionManager.js";
|
|
3
3
|
/**
|
|
4
4
|
* Provider — 全局上下文实例。
|
|
5
5
|
*
|
|
@@ -19,13 +19,7 @@ export declare class Provider {
|
|
|
19
19
|
readonly skillsPaths: string[];
|
|
20
20
|
readonly toolsPaths: string[];
|
|
21
21
|
readonly mcpPaths: string[];
|
|
22
|
-
|
|
23
|
-
readonly draftsDir: string;
|
|
24
|
-
readonly mcpManager?: McpConnectionManager;
|
|
25
|
-
readonly mcpConfigs?: Map<string, {
|
|
26
|
-
name: string;
|
|
27
|
-
config: McpServerConfig;
|
|
28
|
-
}>;
|
|
22
|
+
private _mcpManager?;
|
|
29
23
|
constructor(options: {
|
|
30
24
|
config: AppConfig;
|
|
31
25
|
agentsDir: string;
|
|
@@ -33,12 +27,10 @@ export declare class Provider {
|
|
|
33
27
|
skillsPaths?: string[];
|
|
34
28
|
toolsPaths?: string[];
|
|
35
29
|
mcpPaths?: string[];
|
|
36
|
-
conversationsDir: string;
|
|
37
|
-
draftsDir: string;
|
|
38
|
-
mcpManager?: McpConnectionManager;
|
|
39
|
-
mcpConfigs?: Map<string, {
|
|
40
|
-
name: string;
|
|
41
|
-
config: McpServerConfig;
|
|
42
|
-
}>;
|
|
43
30
|
});
|
|
31
|
+
/**
|
|
32
|
+
* 获取 McpConnectionManager,有 mcpPaths 时延迟创建。
|
|
33
|
+
* 首次访问时创建,后续复用同一实例。
|
|
34
|
+
*/
|
|
35
|
+
getMcpManager(): McpConnectionManager | undefined;
|
|
44
36
|
}
|
package/dist/runtime/Provider.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { McpConnectionManager } from "./McpConnectionManager.js";
|
|
1
2
|
/**
|
|
2
3
|
* Provider — 全局上下文实例。
|
|
3
4
|
*
|
|
@@ -18,11 +19,8 @@ export class Provider {
|
|
|
18
19
|
skillsPaths;
|
|
19
20
|
toolsPaths;
|
|
20
21
|
mcpPaths;
|
|
21
|
-
conversationsDir;
|
|
22
|
-
draftsDir;
|
|
23
22
|
// ---- MCP ----
|
|
24
|
-
|
|
25
|
-
mcpConfigs;
|
|
23
|
+
_mcpManager;
|
|
26
24
|
constructor(options) {
|
|
27
25
|
this.config = options.config;
|
|
28
26
|
this.agentsDir = options.agentsDir;
|
|
@@ -30,9 +28,15 @@ export class Provider {
|
|
|
30
28
|
this.skillsPaths = options.skillsPaths ?? [];
|
|
31
29
|
this.toolsPaths = options.toolsPaths ?? [];
|
|
32
30
|
this.mcpPaths = options.mcpPaths ?? [];
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* 获取 McpConnectionManager,有 mcpPaths 时延迟创建。
|
|
34
|
+
* 首次访问时创建,后续复用同一实例。
|
|
35
|
+
*/
|
|
36
|
+
getMcpManager() {
|
|
37
|
+
if (!this._mcpManager && this.mcpPaths.length > 0) {
|
|
38
|
+
this._mcpManager = new McpConnectionManager();
|
|
39
|
+
}
|
|
40
|
+
return this._mcpManager;
|
|
37
41
|
}
|
|
38
42
|
}
|
|
@@ -5,10 +5,16 @@ import type { Capabilities } from "../capabilities/Capabilities.js";
|
|
|
5
5
|
import type { Provider } from "./Provider.js";
|
|
6
6
|
/**
|
|
7
7
|
* Agent 插件上下文:当前 SdkAgent + 发送内容 + 消息列表。
|
|
8
|
+
*
|
|
9
|
+
* 注意:
|
|
10
|
+
* - messages 是当前 agent 消息数组的**快照**(浅拷贝),插件不应直接修改它。
|
|
11
|
+
* 所有消息变更应通过 agent 上的方法进行。
|
|
12
|
+
* - 如果 onAfterSend 替换了 ctx.agent,send() 方法会使用新 agent 的消息作为返回值。
|
|
8
13
|
*/
|
|
9
14
|
export interface SendContext {
|
|
10
15
|
agent: SdkAgent;
|
|
11
16
|
content: string;
|
|
17
|
+
/** 当前 agent 消息数组的浅拷贝快照,仅供读取,不应直接修改 */
|
|
12
18
|
messages: AgentNS.Message[];
|
|
13
19
|
}
|
|
14
20
|
/**
|
|
@@ -95,6 +101,10 @@ export declare class SdkAgent extends Agent {
|
|
|
95
101
|
* 1. onBeforeSend — send 外部准备(刷新工具等)
|
|
96
102
|
* 2. super.send() — 委托 Core Agent,内含内循环及其钩子
|
|
97
103
|
* 3. onAfterSend — send 外部后处理(保存草稿、迁移等)
|
|
104
|
+
*
|
|
105
|
+
* 注意:
|
|
106
|
+
* - ctx.messages 是当前 agent 消息的**浅拷贝快照**,仅供读取,不应直接修改。
|
|
107
|
+
* 所有消息变更应通过 agent 上的方法进行(如 agent.messages.push 等)。
|
|
98
108
|
*/
|
|
99
109
|
send(content: string): Promise<AgentNS.Message[]>;
|
|
100
110
|
}
|
package/dist/runtime/SdkAgent.js
CHANGED
|
@@ -72,12 +72,16 @@ export class SdkAgent extends Agent {
|
|
|
72
72
|
* 1. onBeforeSend — send 外部准备(刷新工具等)
|
|
73
73
|
* 2. super.send() — 委托 Core Agent,内含内循环及其钩子
|
|
74
74
|
* 3. onAfterSend — send 外部后处理(保存草稿、迁移等)
|
|
75
|
+
*
|
|
76
|
+
* 注意:
|
|
77
|
+
* - ctx.messages 是当前 agent 消息的**浅拷贝快照**,仅供读取,不应直接修改。
|
|
78
|
+
* 所有消息变更应通过 agent 上的方法进行(如 agent.messages.push 等)。
|
|
75
79
|
*/
|
|
76
80
|
async send(content) {
|
|
77
81
|
const ctx = {
|
|
78
82
|
agent: this,
|
|
79
83
|
content,
|
|
80
|
-
messages: this.messages,
|
|
84
|
+
messages: [...this.messages],
|
|
81
85
|
};
|
|
82
86
|
for (const plugin of this._plugins) {
|
|
83
87
|
await plugin.onBeforeSend?.(ctx);
|
|
@@ -92,12 +96,12 @@ export class SdkAgent extends Agent {
|
|
|
92
96
|
await plugin.onInnerLoopEnd?.(ctx);
|
|
93
97
|
}
|
|
94
98
|
};
|
|
95
|
-
|
|
99
|
+
await super.send(content);
|
|
96
100
|
this.onInnerLoopStart = undefined;
|
|
97
101
|
this.onInnerLoopEnd = undefined;
|
|
98
102
|
for (const plugin of this._plugins) {
|
|
99
103
|
await plugin.onAfterSend?.(ctx);
|
|
100
104
|
}
|
|
101
|
-
return messages;
|
|
105
|
+
return this.messages;
|
|
102
106
|
}
|
|
103
107
|
}
|
|
@@ -16,7 +16,7 @@ export class TaskMigrationService {
|
|
|
16
16
|
}
|
|
17
17
|
static createPrompt() {
|
|
18
18
|
return [
|
|
19
|
-
"
|
|
19
|
+
"根据以下对话历史,生成一篇结构化交接文档。不要做任何解释,只输出交接文档。",
|
|
20
20
|
"",
|
|
21
21
|
`文档必须包含以下章节:`,
|
|
22
22
|
`${TaskMigrationService.HANDOFF_SECTIONS.breakpoint}`,
|
|
@@ -36,8 +36,6 @@ export class TaskMigrationService {
|
|
|
36
36
|
"",
|
|
37
37
|
`${TaskMigrationService.HANDOFF_SECTIONS.instructions}`,
|
|
38
38
|
`- 接手后建议的操作步骤`,
|
|
39
|
-
"",
|
|
40
|
-
"只输出交接文档本身,不要加额外说明。",
|
|
41
39
|
].join("\n");
|
|
42
40
|
}
|
|
43
41
|
static createAgentDefinition(options = {}) {
|
package/dist/types/index.d.ts
CHANGED
|
@@ -92,13 +92,13 @@ export interface AppConfig {
|
|
|
92
92
|
}
|
|
93
93
|
/** MCP 连接状态 */
|
|
94
94
|
export type McpConnectionState = "disconnected" | "connecting" | "connected" | "error";
|
|
95
|
-
/** MCP
|
|
95
|
+
/** MCP 服务器配置 */
|
|
96
96
|
export interface McpServerConfig {
|
|
97
97
|
id: string;
|
|
98
|
-
|
|
98
|
+
/** transport 类型,内部统一使用 "stdio" | "http" | "sse" */
|
|
99
99
|
transport: "stdio" | "http" | "sse";
|
|
100
|
-
/**
|
|
101
|
-
|
|
100
|
+
/** 是否禁用,默认为 false */
|
|
101
|
+
disabled?: boolean;
|
|
102
102
|
command?: string;
|
|
103
103
|
args?: string[];
|
|
104
104
|
env?: Record<string, string>;
|