@downcity/agent 1.1.79 → 1.1.82
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 +1 -1
- package/bin/agent/local/Agent.d.ts +8 -121
- package/bin/agent/local/Agent.d.ts.map +1 -1
- package/bin/agent/local/Agent.js +63 -381
- package/bin/agent/local/Agent.js.map +1 -1
- package/bin/agent/local/AgentRuntimeFactory.d.ts +2 -2
- package/bin/agent/local/AgentRuntimeFactory.d.ts.map +1 -1
- package/bin/agent/local/AgentRuntimeFactory.js +2 -23
- package/bin/agent/local/AgentRuntimeFactory.js.map +1 -1
- package/bin/agent/local/services/AgentAssemblyService.d.ts +112 -0
- package/bin/agent/local/services/AgentAssemblyService.d.ts.map +1 -0
- package/bin/agent/local/services/AgentAssemblyService.js +135 -0
- package/bin/agent/local/services/AgentAssemblyService.js.map +1 -0
- package/bin/agent/local/services/AgentLifecycleService.d.ts +59 -0
- package/bin/agent/local/services/AgentLifecycleService.d.ts.map +1 -0
- package/bin/agent/local/services/AgentLifecycleService.js +136 -0
- package/bin/agent/local/services/AgentLifecycleService.js.map +1 -0
- package/bin/agent/local/services/AgentSessionManager.d.ts +106 -0
- package/bin/agent/local/services/AgentSessionManager.d.ts.map +1 -0
- package/bin/agent/local/services/AgentSessionManager.js +182 -0
- package/bin/agent/local/services/AgentSessionManager.js.map +1 -0
- package/bin/executor/Executor.d.ts +7 -24
- package/bin/executor/Executor.d.ts.map +1 -1
- package/bin/executor/Executor.js +73 -361
- package/bin/executor/Executor.js.map +1 -1
- package/bin/executor/SessionRunScope.d.ts +18 -34
- package/bin/executor/SessionRunScope.d.ts.map +1 -1
- package/bin/executor/SessionRunScope.js +42 -28
- package/bin/executor/SessionRunScope.js.map +1 -1
- package/bin/executor/composer/context/LocalSessionContextComposer.d.ts +5 -3
- package/bin/executor/composer/context/LocalSessionContextComposer.d.ts.map +1 -1
- package/bin/executor/composer/context/LocalSessionContextComposer.js +11 -18
- package/bin/executor/composer/context/LocalSessionContextComposer.js.map +1 -1
- package/bin/executor/composer/context/SessionContextComposer.d.ts +8 -3
- package/bin/executor/composer/context/SessionContextComposer.d.ts.map +1 -1
- package/bin/executor/composer/system/SessionSystemComposer.d.ts +2 -1
- package/bin/executor/composer/system/SessionSystemComposer.d.ts.map +1 -1
- package/bin/executor/composer/system/default/DefaultSessionSystemComposer.d.ts +2 -1
- package/bin/executor/composer/system/default/DefaultSessionSystemComposer.d.ts.map +1 -1
- package/bin/executor/composer/system/default/DefaultSessionSystemComposer.js +2 -4
- package/bin/executor/composer/system/default/DefaultSessionSystemComposer.js.map +1 -1
- package/bin/executor/core-engine/CoreEngineRunner.d.ts +62 -0
- package/bin/executor/core-engine/CoreEngineRunner.d.ts.map +1 -0
- package/bin/executor/core-engine/CoreEngineRunner.js +309 -0
- package/bin/executor/core-engine/CoreEngineRunner.js.map +1 -0
- package/bin/executor/core-engine/CoreEngineUiStreamCollector.d.ts +5 -0
- package/bin/executor/core-engine/CoreEngineUiStreamCollector.d.ts.map +1 -1
- package/bin/executor/core-engine/CoreEngineUiStreamCollector.js +2 -4
- package/bin/executor/core-engine/CoreEngineUiStreamCollector.js.map +1 -1
- package/bin/executor/services/ExecutorInflightService.d.ts +39 -0
- package/bin/executor/services/ExecutorInflightService.d.ts.map +1 -0
- package/bin/executor/services/ExecutorInflightService.js +75 -0
- package/bin/executor/services/ExecutorInflightService.js.map +1 -0
- package/bin/executor/services/ExecutorRecoveryPolicy.d.ts +103 -0
- package/bin/executor/services/ExecutorRecoveryPolicy.d.ts.map +1 -0
- package/bin/executor/services/ExecutorRecoveryPolicy.js +87 -0
- package/bin/executor/services/ExecutorRecoveryPolicy.js.map +1 -0
- package/bin/executor/tools/plugin/PluginToolBridge.d.ts +19 -0
- package/bin/executor/tools/plugin/PluginToolBridge.d.ts.map +1 -0
- package/bin/executor/tools/plugin/PluginToolBridge.js +143 -0
- package/bin/executor/tools/plugin/PluginToolBridge.js.map +1 -0
- package/bin/executor/tools/plugin/PluginToolDefinition.d.ts +32 -0
- package/bin/executor/tools/plugin/PluginToolDefinition.d.ts.map +1 -0
- package/bin/executor/tools/plugin/PluginToolDefinition.js +27 -0
- package/bin/executor/tools/plugin/PluginToolDefinition.js.map +1 -0
- package/bin/executor/tools/plugin/PluginToolSchemas.d.ts +14 -0
- package/bin/executor/tools/plugin/PluginToolSchemas.d.ts.map +1 -0
- package/bin/executor/tools/plugin/PluginToolSchemas.js +19 -0
- package/bin/executor/tools/plugin/PluginToolSchemas.js.map +1 -0
- package/bin/executor/tools/plugin/types/PluginTool.d.ts +39 -0
- package/bin/executor/tools/plugin/types/PluginTool.d.ts.map +1 -0
- package/bin/executor/tools/plugin/types/PluginTool.js +9 -0
- package/bin/executor/tools/plugin/types/PluginTool.js.map +1 -0
- package/bin/executor/tools/shell/ShellToolBridge.js +3 -3
- package/bin/executor/tools/shell/ShellToolBridge.js.map +1 -1
- package/bin/executor/types/SessionRun.d.ts +18 -0
- package/bin/executor/types/SessionRun.d.ts.map +1 -1
- package/bin/index.d.ts +10 -1
- package/bin/index.d.ts.map +1 -1
- package/bin/index.js +3 -0
- package/bin/index.js.map +1 -1
- package/bin/plugin/core/BasePlugin.d.ts +2 -2
- package/bin/plugin/core/BasePlugin.d.ts.map +1 -1
- package/bin/plugin/core/BasePlugin.js.map +1 -1
- package/bin/plugin/core/ImagePlugin.d.ts +56 -0
- package/bin/plugin/core/ImagePlugin.d.ts.map +1 -0
- package/bin/plugin/core/ImagePlugin.js +109 -0
- package/bin/plugin/core/ImagePlugin.js.map +1 -0
- package/bin/session/Session.d.ts +25 -84
- package/bin/session/Session.d.ts.map +1 -1
- package/bin/session/Session.js +162 -367
- package/bin/session/Session.js.map +1 -1
- package/bin/session/SessionSystemBuilder.d.ts +2 -1
- package/bin/session/SessionSystemBuilder.d.ts.map +1 -1
- package/bin/session/SessionSystemBuilder.js +2 -3
- package/bin/session/SessionSystemBuilder.js.map +1 -1
- package/bin/session/services/SessionStateService.d.ts +132 -0
- package/bin/session/services/SessionStateService.d.ts.map +1 -0
- package/bin/session/services/SessionStateService.js +242 -0
- package/bin/session/services/SessionStateService.js.map +1 -0
- package/bin/session/services/SessionTurnService.d.ts +66 -0
- package/bin/session/services/SessionTurnService.d.ts.map +1 -0
- package/bin/session/services/SessionTurnService.js +137 -0
- package/bin/session/services/SessionTurnService.js.map +1 -0
- package/bin/session/services/SessionViewService.d.ts +106 -0
- package/bin/session/services/SessionViewService.d.ts.map +1 -0
- package/bin/session/services/SessionViewService.js +198 -0
- package/bin/session/services/SessionViewService.js.map +1 -0
- package/bin/types/agent/AgentOptions.d.ts +18 -0
- package/bin/types/agent/AgentOptions.d.ts.map +1 -1
- package/bin/types/agent/AgentTypes.d.ts +3 -1
- package/bin/types/agent/AgentTypes.d.ts.map +1 -1
- package/bin/types/agent/SessionTypes.d.ts.map +1 -1
- package/bin/types/executor/SessionRunContext.d.ts +66 -0
- package/bin/types/executor/SessionRunContext.d.ts.map +1 -0
- package/bin/types/executor/SessionRunContext.js +10 -0
- package/bin/types/executor/SessionRunContext.js.map +1 -0
- package/bin/types/plugin/ImagePlugin.d.ts +94 -0
- package/bin/types/plugin/ImagePlugin.d.ts.map +1 -0
- package/bin/types/plugin/ImagePlugin.js +10 -0
- package/bin/types/plugin/ImagePlugin.js.map +1 -0
- package/bin/types/session/SessionComposerOptions.d.ts +90 -0
- package/bin/types/session/SessionComposerOptions.d.ts.map +1 -0
- package/bin/types/session/SessionComposerOptions.js +10 -0
- package/bin/types/session/SessionComposerOptions.js.map +1 -0
- package/bin/types/session/SessionLocalState.d.ts +35 -0
- package/bin/types/session/SessionLocalState.d.ts.map +1 -0
- package/bin/types/session/SessionLocalState.js +10 -0
- package/bin/types/session/SessionLocalState.js.map +1 -0
- package/bin/types/session/SessionOptions.d.ts +85 -0
- package/bin/types/session/SessionOptions.d.ts.map +1 -0
- package/bin/types/session/SessionOptions.js +10 -0
- package/bin/types/session/SessionOptions.js.map +1 -0
- package/package.json +1 -1
- package/src/agent/local/Agent.ts +74 -433
- package/src/agent/local/AgentRuntimeFactory.ts +4 -25
- package/src/agent/local/services/AgentAssemblyService.ts +268 -0
- package/src/agent/local/services/AgentLifecycleService.ts +187 -0
- package/src/agent/local/services/AgentSessionManager.ts +290 -0
- package/src/executor/Executor.ts +103 -441
- package/src/executor/README.md +4 -4
- package/src/executor/SessionRunScope.ts +47 -71
- package/src/executor/composer/context/LocalSessionContextComposer.ts +24 -20
- package/src/executor/composer/context/SessionContextComposer.ts +13 -3
- package/src/executor/composer/system/SessionSystemComposer.ts +2 -1
- package/src/executor/composer/system/default/DefaultSessionSystemComposer.ts +3 -4
- package/src/executor/core-engine/CoreEngineRunner.ts +433 -0
- package/src/executor/core-engine/CoreEngineUiStreamCollector.ts +7 -5
- package/src/executor/services/ExecutorInflightService.ts +101 -0
- package/src/executor/services/ExecutorRecoveryPolicy.ts +213 -0
- package/src/executor/tools/plugin/PluginToolBridge.ts +161 -0
- package/src/executor/tools/plugin/PluginToolDefinition.ts +32 -0
- package/src/executor/tools/plugin/PluginToolSchemas.ts +20 -0
- package/src/executor/tools/plugin/types/PluginTool.ts +41 -0
- package/src/executor/tools/shell/ShellToolBridge.ts +3 -3
- package/src/executor/types/SessionRun.ts +20 -0
- package/src/index.ts +33 -0
- package/src/plugin/core/BasePlugin.ts +2 -2
- package/src/plugin/core/ImagePlugin.ts +128 -0
- package/src/session/Session.ts +216 -500
- package/src/session/SessionSystemBuilder.ts +3 -3
- package/src/session/services/SessionStateService.ts +341 -0
- package/src/session/services/SessionTurnService.ts +202 -0
- package/src/session/services/SessionViewService.ts +323 -0
- package/src/types/agent/AgentOptions.ts +25 -0
- package/src/types/agent/AgentTypes.ts +10 -0
- package/src/types/agent/SessionTypes.ts +1 -0
- package/src/types/executor/SessionRunContext.ts +76 -0
- package/src/types/plugin/ImagePlugin.ts +103 -0
- package/src/types/session/SessionComposerOptions.ts +107 -0
- package/src/types/session/SessionLocalState.ts +40 -0
- package/src/types/session/SessionOptions.ts +99 -0
- package/tsconfig.tsbuildinfo +1 -1
package/src/agent/local/Agent.ts
CHANGED
|
@@ -1,66 +1,38 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Agent local
|
|
2
|
+
* Agent local:本地入口与 facade。
|
|
3
3
|
*
|
|
4
4
|
* 职责说明(中文)
|
|
5
5
|
* - 对外暴露 `Agent` 这一唯一的本地实例类。
|
|
6
|
-
* -
|
|
7
|
-
* -
|
|
8
|
-
*
|
|
9
|
-
* 边界说明(中文)
|
|
10
|
-
* - 这里负责“单个 agent 实例”的长期状态与装配,不负责平台级多 agent 管理。
|
|
11
|
-
* - 这里不直接实现 session 执行细节,而是继续复用 `Session` / `Executor` 体系。
|
|
6
|
+
* - facade 只保留公开 API 与 service 组合,不再直接承载装配、session 管理与生命周期细节。
|
|
7
|
+
* - 单个 agent 的长期对象装配、session 管理、后台能力生命周期分别下沉到独立 service。
|
|
12
8
|
*/
|
|
13
9
|
|
|
14
|
-
import fs from "fs-extra";
|
|
15
|
-
import { nanoid } from "nanoid";
|
|
16
10
|
import type { Tool } from "ai";
|
|
17
|
-
import type { BasePlugin } from "@/plugin/core/BasePlugin.js";
|
|
18
11
|
import type { AgentContext } from "@/types/runtime/agent/AgentContext.js";
|
|
19
12
|
import type { AgentRuntime } from "@/types/runtime/agent/AgentRuntime.js";
|
|
20
13
|
import type { DowncityConfig } from "@/types/config/DowncityConfig.js";
|
|
21
14
|
import type { PluginPort } from "@/plugin/types/Plugin.js";
|
|
22
15
|
import type {
|
|
23
|
-
AgentSession,
|
|
24
16
|
AgentCreateSessionInput,
|
|
25
17
|
AgentListSessionsInput,
|
|
18
|
+
AgentModel,
|
|
26
19
|
AgentOptions,
|
|
20
|
+
AgentSession,
|
|
21
|
+
AgentSessionCollection,
|
|
22
|
+
AgentSessionSummaryPage,
|
|
27
23
|
AgentStartOptions,
|
|
28
24
|
AgentStartResult,
|
|
29
25
|
AgentStopResult,
|
|
30
|
-
AgentRpcBinding,
|
|
31
|
-
AgentRpcStartOptions,
|
|
32
|
-
AgentSessionCollection,
|
|
33
|
-
AgentSessionSummaryPage,
|
|
34
|
-
AgentSessionSystemBlock,
|
|
35
26
|
} from "@/types/agent/AgentTypes.js";
|
|
36
|
-
import type { AgentModel } from "@/model/CityModelAdapter.js";
|
|
37
|
-
import { Logger } from "@/utils/logger/Logger.js";
|
|
38
|
-
import { Session } from "@/session/Session.js";
|
|
39
|
-
import {
|
|
40
|
-
getSdkAgentSessionDirPath,
|
|
41
|
-
listAgentSessionSummaryPage,
|
|
42
|
-
} from "@/session/index.js";
|
|
43
|
-
import { loadDowncityConfig, resolveAgentEnv } from "@/config/Config.js";
|
|
44
27
|
import { PluginRegistry } from "@/plugin/core/PluginRegistry.js";
|
|
45
|
-
import {
|
|
46
|
-
import {
|
|
47
|
-
import { startAllPlugins, stopAllPlugins } from "@/plugin/core/Manager.js";
|
|
48
|
-
import type { ActionScheduleRuntimeHandle } from "@/plugin/core/ActionScheduleRuntime.js";
|
|
49
|
-
import { startActionScheduleRuntime } from "@/plugin/core/ActionScheduleRuntime.js";
|
|
50
|
-
import { startRpcServer } from "@/rpc/Server.js";
|
|
51
|
-
import {
|
|
52
|
-
createFallbackSdkConfig,
|
|
53
|
-
createInstructionSystemBlocks,
|
|
54
|
-
normalizeInstructionInput,
|
|
55
|
-
} from "@/agent/local/AgentInstructions.js";
|
|
56
|
-
import {
|
|
57
|
-
createAgentPluginPort,
|
|
58
|
-
createAgentPluginRegistry,
|
|
59
|
-
} from "@/agent/local/AgentPluginFactory.js";
|
|
28
|
+
import { Logger } from "@/utils/logger/Logger.js";
|
|
29
|
+
import { normalizeInstructionInput } from "@/agent/local/AgentInstructions.js";
|
|
60
30
|
import {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
} from "@/agent/local/
|
|
31
|
+
AgentAssemblyService,
|
|
32
|
+
type AgentAssemblyResult,
|
|
33
|
+
} from "@/agent/local/services/AgentAssemblyService.js";
|
|
34
|
+
import { AgentSessionManager } from "@/agent/local/services/AgentSessionManager.js";
|
|
35
|
+
import { AgentLifecycleService } from "@/agent/local/services/AgentLifecycleService.js";
|
|
64
36
|
|
|
65
37
|
/**
|
|
66
38
|
* SDK 本地 Agent。
|
|
@@ -72,137 +44,73 @@ export class Agent {
|
|
|
72
44
|
readonly plugins: PluginPort;
|
|
73
45
|
|
|
74
46
|
private readonly logger: Logger;
|
|
75
|
-
private readonly sessionsById = new Map<string, Session>();
|
|
76
47
|
private readonly runtime: AgentRuntime;
|
|
77
48
|
private readonly agentContext: AgentContext;
|
|
78
49
|
private readonly pluginRegistry: PluginRegistry;
|
|
79
50
|
private readonly config: DowncityConfig;
|
|
80
51
|
private readonly env: Record<string, string>;
|
|
81
52
|
private readonly defaultModel?: AgentModel;
|
|
82
|
-
private readonly
|
|
83
|
-
private readonly
|
|
53
|
+
private readonly SessionClass: AgentOptions["Session"];
|
|
54
|
+
private readonly sessionManager: AgentSessionManager;
|
|
55
|
+
private readonly lifecycleService: AgentLifecycleService;
|
|
84
56
|
|
|
85
57
|
private instruction: string[];
|
|
86
|
-
private configuredSessionIds = new Set<string>();
|
|
87
|
-
private pluginsStarted = false;
|
|
88
|
-
private actionScheduleRuntime: ActionScheduleRuntimeHandle | null = null;
|
|
89
|
-
private startPromise: Promise<AgentStartResult> | null = null;
|
|
90
|
-
private rpcBinding: AgentRpcBinding | null = null;
|
|
91
58
|
|
|
92
59
|
constructor(options: AgentOptions) {
|
|
93
|
-
this.id = String(options.id || "").trim();
|
|
94
|
-
this.path = String(options.path || "").trim();
|
|
95
|
-
this.tools = options.tools && typeof options.tools === "object"
|
|
96
|
-
? { ...options.tools }
|
|
97
|
-
: {};
|
|
98
|
-
if (!this.id) {
|
|
99
|
-
throw new Error("Agent requires a non-empty id");
|
|
100
|
-
}
|
|
101
|
-
if (!this.path) {
|
|
102
|
-
throw new Error("Agent requires a non-empty path");
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
this.logger = new Logger();
|
|
106
|
-
this.logger.bindProjectRoot(this.path);
|
|
107
|
-
this.env = resolveAgentEnv(this.path, options.env);
|
|
108
|
-
this.instruction = normalizeInstructionInput(options.instruction);
|
|
109
60
|
this.defaultModel = options.model;
|
|
110
|
-
this.
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
this.getOrCreateSession(session_id).getRuntimePort(),
|
|
122
|
-
list_cached_sessions: () => [...this.sessionsById.values()],
|
|
123
|
-
});
|
|
124
|
-
this.registerPlugins(options.plugins || []);
|
|
125
|
-
this.pluginRegistry = createAgentPluginRegistry({
|
|
126
|
-
plugins: [...this.pluginInstances.values()],
|
|
127
|
-
get_context: () => this.agentContext,
|
|
128
|
-
});
|
|
129
|
-
this.plugins = createAgentPluginPort(this.pluginRegistry);
|
|
130
|
-
this.agentContext = createAgentContext({
|
|
131
|
-
runtime: this.runtime,
|
|
132
|
-
project_root: this.path,
|
|
133
|
-
logger: this.logger,
|
|
134
|
-
config: this.config,
|
|
135
|
-
env: this.env,
|
|
136
|
-
systems: this.instruction,
|
|
137
|
-
plugin_instances: this.pluginInstances,
|
|
138
|
-
plugins: this.plugins,
|
|
139
|
-
get_session_port: (session_id) =>
|
|
140
|
-
this.getOrCreateSession(session_id).getRuntimePort(),
|
|
61
|
+
this.SessionClass = options.Session;
|
|
62
|
+
let session_manager_ref: AgentSessionManager | null = null;
|
|
63
|
+
const assembly_service = new AgentAssemblyService({
|
|
64
|
+
options,
|
|
65
|
+
list_cached_sessions: () => session_manager_ref?.list_cached_sessions() || [],
|
|
66
|
+
get_session_port: (session_id) => {
|
|
67
|
+
if (!session_manager_ref) {
|
|
68
|
+
throw new Error("Agent session manager is not initialized");
|
|
69
|
+
}
|
|
70
|
+
return session_manager_ref.get_session_port(session_id);
|
|
71
|
+
},
|
|
141
72
|
resolve_session_model: async (session_id) => {
|
|
142
|
-
|
|
73
|
+
if (!session_manager_ref) return undefined;
|
|
74
|
+
const session = await session_manager_ref.get_session(session_id);
|
|
143
75
|
return session.config.model;
|
|
144
76
|
},
|
|
145
77
|
});
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
this.
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
78
|
+
const assembly = assembly_service.assemble();
|
|
79
|
+
|
|
80
|
+
this.id = assembly.id;
|
|
81
|
+
this.path = assembly.path;
|
|
82
|
+
this.tools = assembly.tools;
|
|
83
|
+
this.plugins = assembly.plugins;
|
|
84
|
+
this.logger = assembly.logger;
|
|
85
|
+
this.runtime = assembly.runtime;
|
|
86
|
+
this.agentContext = assembly.agent_context;
|
|
87
|
+
this.pluginRegistry = assembly.plugin_registry;
|
|
88
|
+
this.config = assembly.config;
|
|
89
|
+
this.env = assembly.env;
|
|
90
|
+
this.instruction = assembly.instruction;
|
|
91
|
+
|
|
92
|
+
this.sessionManager = this.create_session_manager(assembly);
|
|
93
|
+
session_manager_ref = this.sessionManager;
|
|
94
|
+
this.lifecycleService = new AgentLifecycleService({
|
|
95
|
+
logger: this.logger,
|
|
96
|
+
agent_context: this.agentContext,
|
|
97
|
+
session_collection: this.sessionManager.get_session_collection(),
|
|
98
|
+
get_runtime: () => this.runtime,
|
|
99
|
+
});
|
|
153
100
|
}
|
|
154
101
|
|
|
155
102
|
/**
|
|
156
103
|
* 新建一个 session。
|
|
157
|
-
*
|
|
158
|
-
* 关键点(中文)
|
|
159
|
-
* - 若调用方显式传入 `sessionId`,这里会先检查缓存与磁盘目录,避免重复创建。
|
|
160
|
-
* - session 初始化完成后会立即应用默认模型。
|
|
161
104
|
*/
|
|
162
105
|
async createSession(input?: AgentCreateSessionInput): Promise<AgentSession> {
|
|
163
|
-
|
|
164
|
-
if (
|
|
165
|
-
explicitSessionId &&
|
|
166
|
-
(this.sessionsById.has(explicitSessionId) ||
|
|
167
|
-
(await fs.pathExists(
|
|
168
|
-
getSdkAgentSessionDirPath(this.path, this.id, explicitSessionId),
|
|
169
|
-
)))
|
|
170
|
-
) {
|
|
171
|
-
throw new Error(`Session "${explicitSessionId}" already exists`);
|
|
172
|
-
}
|
|
173
|
-
const session = this.getOrCreateSession(explicitSessionId);
|
|
174
|
-
await session.initialize();
|
|
175
|
-
await this.applySessionDefaults(session);
|
|
176
|
-
return session;
|
|
106
|
+
return await this.sessionManager.create_session(input);
|
|
177
107
|
}
|
|
178
108
|
|
|
179
109
|
/**
|
|
180
110
|
* 获取一个已存在的 session。
|
|
181
|
-
*
|
|
182
|
-
* 关键点(中文)
|
|
183
|
-
* - 若缓存中没有该 session,会根据磁盘目录决定是否允许懒加载恢复。
|
|
184
|
-
* - 返回前同样会兜底执行一次默认配置装配。
|
|
185
111
|
*/
|
|
186
112
|
async getSession(sessionId: string): Promise<AgentSession> {
|
|
187
|
-
|
|
188
|
-
if (!resolvedSessionId) {
|
|
189
|
-
throw new Error("getSession requires a non-empty sessionId");
|
|
190
|
-
}
|
|
191
|
-
const sessionDirPath = getSdkAgentSessionDirPath(
|
|
192
|
-
this.path,
|
|
193
|
-
this.id,
|
|
194
|
-
resolvedSessionId,
|
|
195
|
-
);
|
|
196
|
-
if (
|
|
197
|
-
!this.sessionsById.has(resolvedSessionId) &&
|
|
198
|
-
!(await fs.pathExists(sessionDirPath))
|
|
199
|
-
) {
|
|
200
|
-
throw new Error(`Session "${resolvedSessionId}" not found`);
|
|
201
|
-
}
|
|
202
|
-
const session = this.getOrCreateSession(resolvedSessionId);
|
|
203
|
-
await session.initialize();
|
|
204
|
-
await this.applySessionDefaults(session);
|
|
205
|
-
return session;
|
|
113
|
+
return await this.sessionManager.get_session(sessionId);
|
|
206
114
|
}
|
|
207
115
|
|
|
208
116
|
/**
|
|
@@ -211,85 +119,25 @@ export class Agent {
|
|
|
211
119
|
async listSessions(
|
|
212
120
|
input?: AgentListSessionsInput,
|
|
213
121
|
): Promise<AgentSessionSummaryPage> {
|
|
214
|
-
return await
|
|
215
|
-
projectRoot: this.path,
|
|
216
|
-
agentId: this.id,
|
|
217
|
-
input,
|
|
218
|
-
executingSessionIds: new Set(this.runtime.listExecutingSessionIds()),
|
|
219
|
-
});
|
|
122
|
+
return await this.sessionManager.list_sessions(input);
|
|
220
123
|
}
|
|
221
124
|
|
|
222
125
|
/**
|
|
223
126
|
* 启动当前 agent 实例的长期运行能力。
|
|
224
|
-
*
|
|
225
|
-
* 关键点(中文)
|
|
226
|
-
* - `start()` 是唯一公开的长期运行生命周期入口。
|
|
227
|
-
* - 多次并发调用会复用同一个启动 Promise,避免重复启动 plugins / rpc。
|
|
228
127
|
*/
|
|
229
128
|
async start(options?: AgentStartOptions): Promise<AgentStartResult> {
|
|
230
|
-
|
|
231
|
-
return await this.startPromise;
|
|
232
|
-
}
|
|
233
|
-
this.startPromise = (async () => {
|
|
234
|
-
const shouldStartPlugins = options?.plugins !== false;
|
|
235
|
-
|
|
236
|
-
if (shouldStartPlugins) {
|
|
237
|
-
await this.ensurePluginsStarted();
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
const rpcBinding =
|
|
241
|
-
options?.rpc === false || options?.rpc === undefined
|
|
242
|
-
? undefined
|
|
243
|
-
: await this.startRpc(options.rpc);
|
|
244
|
-
|
|
245
|
-
return {
|
|
246
|
-
...(rpcBinding ? { rpc: rpcBinding } : {}),
|
|
247
|
-
pluginsStarted: this.pluginsStarted,
|
|
248
|
-
};
|
|
249
|
-
})();
|
|
250
|
-
try {
|
|
251
|
-
return await this.startPromise;
|
|
252
|
-
} catch (error) {
|
|
253
|
-
this.startPromise = null;
|
|
254
|
-
throw error;
|
|
255
|
-
}
|
|
129
|
+
return await this.lifecycleService.start(options);
|
|
256
130
|
}
|
|
257
131
|
|
|
258
132
|
/**
|
|
259
133
|
* 停止当前 agent 实例的长期运行能力。
|
|
260
|
-
*
|
|
261
|
-
* 关键点(中文)
|
|
262
|
-
* - 停止顺序保持为 plugins -> rpc,与当前运行语义一致。
|
|
263
|
-
* - 停止后会清空 `startPromise`,允许后续再次 `start()`。
|
|
264
134
|
*/
|
|
265
135
|
async stop(): Promise<AgentStopResult> {
|
|
266
|
-
|
|
267
|
-
const rpcStarted = this.rpcBinding !== null;
|
|
268
|
-
|
|
269
|
-
if (pluginsStarted) {
|
|
270
|
-
await this.stopActionScheduleRuntime();
|
|
271
|
-
await stopAllPlugins(this.agentContext);
|
|
272
|
-
this.pluginsStarted = false;
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
if (rpcStarted) {
|
|
276
|
-
await this.stopRpc();
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
this.startPromise = null;
|
|
280
|
-
|
|
281
|
-
return {
|
|
282
|
-
rpcStopped: rpcStarted,
|
|
283
|
-
pluginsStopped: pluginsStarted,
|
|
284
|
-
};
|
|
136
|
+
return await this.lifecycleService.stop();
|
|
285
137
|
}
|
|
286
138
|
|
|
287
139
|
/**
|
|
288
140
|
* 更新当前 SDK Agent 的静态基础指令。
|
|
289
|
-
*
|
|
290
|
-
* 关键点(中文)
|
|
291
|
-
* - instruction 不做动态变量替换。
|
|
292
|
-
* - 已创建的 session 后续 run 会读取最新 instruction blocks。
|
|
293
141
|
*/
|
|
294
142
|
setInstruction(input: string | string[]): void {
|
|
295
143
|
this.instruction = normalizeInstructionInput(input);
|
|
@@ -311,10 +159,6 @@ export class Agent {
|
|
|
311
159
|
|
|
312
160
|
/**
|
|
313
161
|
* 返回当前 agent runtime。
|
|
314
|
-
*
|
|
315
|
-
* 关键点(中文)
|
|
316
|
-
* - 供宿主在 agent 外部装配 transport(例如 Town HTTP gateway)时复用。
|
|
317
|
-
* - 不暴露启动语义,只暴露运行时访问口。
|
|
318
162
|
*/
|
|
319
163
|
getRuntime(): AgentRuntime {
|
|
320
164
|
return this.runtime;
|
|
@@ -322,9 +166,6 @@ export class Agent {
|
|
|
322
166
|
|
|
323
167
|
/**
|
|
324
168
|
* 返回当前 agent context。
|
|
325
|
-
*
|
|
326
|
-
* 关键点(中文)
|
|
327
|
-
* - 供宿主装配 plugin/control 相关外层协议面。
|
|
328
169
|
*/
|
|
329
170
|
getContext(): AgentContext {
|
|
330
171
|
return this.agentContext;
|
|
@@ -332,225 +173,25 @@ export class Agent {
|
|
|
332
173
|
|
|
333
174
|
/**
|
|
334
175
|
* 返回当前 session collection。
|
|
335
|
-
*
|
|
336
|
-
* 关键点(中文)
|
|
337
|
-
* - 供宿主在外层挂载 RemoteAgent transport 时复用。
|
|
338
176
|
*/
|
|
339
177
|
getSessionCollection(): AgentSessionCollection {
|
|
340
|
-
return this.
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
`Plugin start failed: ${item.plugin?.name || "unknown"} - ${item.error || "unknown error"}`,
|
|
358
|
-
);
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
await this.ensureActionScheduleRuntimeStarted();
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
/**
|
|
365
|
-
* 确保 ActionSchedule runtime 已随 Agent 长期生命周期启动。
|
|
366
|
-
*
|
|
367
|
-
* 关键点(中文)
|
|
368
|
-
* - ActionSchedule 不作为 plugin 注册,但它依赖 plugin action 执行能力。
|
|
369
|
-
* - 因此这里放在普通 plugins 启动之后,避免到期任务执行到尚未启动的 plugin。
|
|
370
|
-
*/
|
|
371
|
-
private async ensureActionScheduleRuntimeStarted(): Promise<void> {
|
|
372
|
-
if (this.actionScheduleRuntime) return;
|
|
373
|
-
try {
|
|
374
|
-
this.actionScheduleRuntime = await startActionScheduleRuntime(
|
|
375
|
-
this.agentContext,
|
|
376
|
-
);
|
|
377
|
-
} catch (error) {
|
|
378
|
-
this.logger.error(
|
|
379
|
-
`ActionSchedule start failed: ${String(error)}`,
|
|
380
|
-
);
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
/**
|
|
385
|
-
* 停止 ActionSchedule runtime。
|
|
386
|
-
*
|
|
387
|
-
* 关键点(中文)
|
|
388
|
-
* - Agent 停止时先停 ActionSchedule,再停普通 plugin,避免关停期间继续触发 action。
|
|
389
|
-
*/
|
|
390
|
-
private async stopActionScheduleRuntime(): Promise<void> {
|
|
391
|
-
const runtime = this.actionScheduleRuntime;
|
|
392
|
-
this.actionScheduleRuntime = null;
|
|
393
|
-
runtime?.stop();
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
/**
|
|
397
|
-
* 启动当前 agent 的本机 RPC server。
|
|
398
|
-
*/
|
|
399
|
-
private async startRpc(
|
|
400
|
-
options?: AgentRpcStartOptions,
|
|
401
|
-
): Promise<AgentRpcBinding> {
|
|
402
|
-
if (this.rpcBinding) {
|
|
403
|
-
return this.rpcBinding;
|
|
404
|
-
}
|
|
405
|
-
const host = String(options?.host || "127.0.0.1").trim() || "127.0.0.1";
|
|
406
|
-
const port =
|
|
407
|
-
typeof options?.port === "number" && Number.isInteger(options.port)
|
|
408
|
-
? options.port
|
|
409
|
-
: 15314;
|
|
410
|
-
const server = await startRpcServer({
|
|
411
|
-
host,
|
|
412
|
-
port,
|
|
413
|
-
sessionCollection: this.sessionCollection,
|
|
414
|
-
getAgentContext: () => this.agentContext,
|
|
415
|
-
getAgentRuntime: () => this.getRuntime(),
|
|
178
|
+
return this.sessionManager.get_session_collection();
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
private create_session_manager(
|
|
182
|
+
assembly: AgentAssemblyResult,
|
|
183
|
+
): AgentSessionManager {
|
|
184
|
+
return new AgentSessionManager({
|
|
185
|
+
agent_id: this.id || assembly.id,
|
|
186
|
+
project_root: this.path || assembly.path,
|
|
187
|
+
tools: this.tools || assembly.tools,
|
|
188
|
+
logger: this.logger || assembly.logger,
|
|
189
|
+
runtime: this.runtime || assembly.runtime,
|
|
190
|
+
get_agent_context: () => this.agentContext || assembly.agent_context,
|
|
191
|
+
get_instruction: () => this.instruction,
|
|
192
|
+
plugin_instances: assembly.plugin_instances,
|
|
193
|
+
default_model: this.defaultModel,
|
|
194
|
+
SessionClass: this.SessionClass,
|
|
416
195
|
});
|
|
417
|
-
this.rpcBinding = {
|
|
418
|
-
url: `rpc://${host}:${port}`,
|
|
419
|
-
host,
|
|
420
|
-
port,
|
|
421
|
-
server,
|
|
422
|
-
};
|
|
423
|
-
return this.rpcBinding;
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
/**
|
|
427
|
-
* 停止当前 agent 的本机 RPC server。
|
|
428
|
-
*/
|
|
429
|
-
private async stopRpc(): Promise<void> {
|
|
430
|
-
if (!this.rpcBinding) return;
|
|
431
|
-
const current = this.rpcBinding;
|
|
432
|
-
this.rpcBinding = null;
|
|
433
|
-
await current.server.stop();
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
/**
|
|
437
|
-
* 读取当前项目配置。
|
|
438
|
-
*
|
|
439
|
-
* 关键点(中文)
|
|
440
|
-
* - 若项目根目录尚未存在合法 `downcity.json`,会退回最小 SDK 占位配置。
|
|
441
|
-
* - 这样可以允许纯 SDK 场景在尚未初始化项目时继续装配本地 Agent。
|
|
442
|
-
*/
|
|
443
|
-
private loadConfig(): DowncityConfig {
|
|
444
|
-
try {
|
|
445
|
-
return loadDowncityConfig(this.path);
|
|
446
|
-
} catch {
|
|
447
|
-
return createFallbackSdkConfig(this.id);
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
/**
|
|
452
|
-
* 注册当前 agent 可见的 plugin 实例。
|
|
453
|
-
*
|
|
454
|
-
* 关键点(中文)
|
|
455
|
-
* - SDK 只注册宿主显式传入的 plugin 实例,不再隐式装配 built-in 集合。
|
|
456
|
-
* - 所有 plugin 在注册前都会绑定到当前实例 runtime。
|
|
457
|
-
*/
|
|
458
|
-
private registerPlugins(plugins: BasePlugin[]): void {
|
|
459
|
-
for (const plugin of plugins) {
|
|
460
|
-
const name = String(plugin?.name || "").trim();
|
|
461
|
-
if (!name) {
|
|
462
|
-
throw new Error("Agent received a plugin without a valid name");
|
|
463
|
-
}
|
|
464
|
-
if (this.pluginInstances.has(name)) {
|
|
465
|
-
throw new Error(`Duplicate plugin registration: ${name}`);
|
|
466
|
-
}
|
|
467
|
-
plugin.bindAgent(this.runtime);
|
|
468
|
-
this.pluginInstances.set(name, plugin);
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
/**
|
|
473
|
-
* 读取当前 agent 静态 instruction blocks。
|
|
474
|
-
*/
|
|
475
|
-
private loadInstructionSystemBlocks(): AgentSessionSystemBlock[] {
|
|
476
|
-
return createInstructionSystemBlocks(this.instruction, this.path);
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
/**
|
|
480
|
-
* 读取当前可用 plugin 暴露的 system blocks。
|
|
481
|
-
*
|
|
482
|
-
* 关键点(中文)
|
|
483
|
-
* - 单个 plugin system 失败不会阻断 session 主链路。
|
|
484
|
-
* - 这里只加载当前启用且可用的 plugin system 文本。
|
|
485
|
-
*/
|
|
486
|
-
private async loadPluginSystemBlocks(): Promise<AgentSessionSystemBlock[]> {
|
|
487
|
-
const out: AgentSessionSystemBlock[] = [];
|
|
488
|
-
for (const plugin of this.pluginInstances.values()) {
|
|
489
|
-
if (typeof plugin.system !== "function") continue;
|
|
490
|
-
try {
|
|
491
|
-
if (!isPluginEnabled({ plugin, context: this.agentContext })) continue;
|
|
492
|
-
if (typeof plugin.availability === "function") {
|
|
493
|
-
const availability = await plugin.availability(this.agentContext);
|
|
494
|
-
if (!availability.available) continue;
|
|
495
|
-
}
|
|
496
|
-
const text = String(await plugin.system(this.agentContext)).trim();
|
|
497
|
-
if (!text) continue;
|
|
498
|
-
out.push({
|
|
499
|
-
source: "plugin",
|
|
500
|
-
name: plugin.name,
|
|
501
|
-
content: text,
|
|
502
|
-
});
|
|
503
|
-
} catch {
|
|
504
|
-
// 单个 plugin system 失败不应阻断 SDK session 主链路。
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
return out;
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
/**
|
|
511
|
-
* 获取或创建一个本地 Session 实例。
|
|
512
|
-
*
|
|
513
|
-
* 关键点(中文)
|
|
514
|
-
* - 同一个 `sessionId` 在单个 Agent 实例内只会装配一次。
|
|
515
|
-
* - 新建 session 时会把 instruction 与 plugin system 读取能力注入进去。
|
|
516
|
-
*/
|
|
517
|
-
private getOrCreateSession(sessionId?: string): Session {
|
|
518
|
-
const resolvedSessionId =
|
|
519
|
-
String(sessionId || "").trim() || `session-${Date.now()}-${nanoid(8)}`;
|
|
520
|
-
const cached = this.sessionsById.get(resolvedSessionId);
|
|
521
|
-
if (cached) return cached;
|
|
522
|
-
|
|
523
|
-
const created = new Session({
|
|
524
|
-
agentId: this.id,
|
|
525
|
-
projectRoot: this.path,
|
|
526
|
-
sessionId: resolvedSessionId,
|
|
527
|
-
tools: this.tools,
|
|
528
|
-
logger: this.logger,
|
|
529
|
-
getInstructionSystemBlocks: () => this.loadInstructionSystemBlocks(),
|
|
530
|
-
getManagedPluginSystemBlocks: async () => [],
|
|
531
|
-
getPluginSystemBlocks: () => this.loadPluginSystemBlocks(),
|
|
532
|
-
ensureConfigured: async (session) => {
|
|
533
|
-
await this.applySessionDefaults(session);
|
|
534
|
-
},
|
|
535
|
-
});
|
|
536
|
-
this.sessionsById.set(resolvedSessionId, created);
|
|
537
|
-
return created;
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
/**
|
|
541
|
-
* 为 session 应用默认模型。
|
|
542
|
-
*
|
|
543
|
-
* 关键点(中文)
|
|
544
|
-
* - 同一个 session 在单个 Agent 实例中只会执行一次配置装配。
|
|
545
|
-
* - 默认模型会在首次访问/首次执行前写入当前 session。
|
|
546
|
-
*/
|
|
547
|
-
private async applySessionDefaults(session: Session): Promise<void> {
|
|
548
|
-
if (this.configuredSessionIds.has(session.id)) return;
|
|
549
|
-
if (this.defaultModel) {
|
|
550
|
-
await session.set({
|
|
551
|
-
model: this.defaultModel,
|
|
552
|
-
});
|
|
553
|
-
}
|
|
554
|
-
this.configuredSessionIds.add(session.id);
|
|
555
196
|
}
|
|
556
197
|
}
|
|
@@ -17,7 +17,7 @@ import type {
|
|
|
17
17
|
} from "@/types/runtime/agent/AgentContext.js";
|
|
18
18
|
import type { AgentRuntime } from "@/types/runtime/agent/AgentRuntime.js";
|
|
19
19
|
import type { PluginPort } from "@/plugin/types/Plugin.js";
|
|
20
|
-
import type {
|
|
20
|
+
import type { AgentManagedSession } from "@/types/agent/AgentTypes.js";
|
|
21
21
|
import {
|
|
22
22
|
createAgentPathRuntime,
|
|
23
23
|
createAgentPluginConfigRuntime,
|
|
@@ -44,7 +44,7 @@ export interface CreateAgentRuntimeOptions {
|
|
|
44
44
|
/** 获取或创建 session runtime port。 */
|
|
45
45
|
get_session_port: (session_id: string) => SessionPort;
|
|
46
46
|
/** 读取当前已缓存的 session 实例。 */
|
|
47
|
-
list_cached_sessions: () =>
|
|
47
|
+
list_cached_sessions: () => AgentManagedSession[];
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
/**
|
|
@@ -133,32 +133,11 @@ export function createAgentContext(
|
|
|
133
133
|
action: string;
|
|
134
134
|
payload?: JsonValue;
|
|
135
135
|
}) => {
|
|
136
|
-
const
|
|
137
|
-
const action_name = String(params.action || "").trim();
|
|
138
|
-
const plugin = options.plugin_instances.get(plugin_name);
|
|
139
|
-
if (!plugin) {
|
|
140
|
-
return {
|
|
141
|
-
success: false,
|
|
142
|
-
error: `Unknown plugin: ${plugin_name}`,
|
|
143
|
-
};
|
|
144
|
-
}
|
|
145
|
-
const action = plugin.actions[action_name];
|
|
146
|
-
if (!action) {
|
|
147
|
-
return {
|
|
148
|
-
success: false,
|
|
149
|
-
error: `Unknown action: ${plugin_name}.${action_name}`,
|
|
150
|
-
};
|
|
151
|
-
}
|
|
152
|
-
const result = await action.execute({
|
|
153
|
-
context,
|
|
154
|
-
payload: params.payload ?? null,
|
|
155
|
-
pluginName: plugin_name,
|
|
156
|
-
actionName: action_name,
|
|
157
|
-
});
|
|
136
|
+
const result = await options.plugins.runAction(params);
|
|
158
137
|
if (!result.success) {
|
|
159
138
|
return {
|
|
160
139
|
success: false,
|
|
161
|
-
|
|
140
|
+
error: result.error || result.message || "plugin action failed",
|
|
162
141
|
};
|
|
163
142
|
}
|
|
164
143
|
return {
|