@downcity/agent 1.1.228 → 1.1.236
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/bin/agent/local/Agent.d.ts +6 -1
- package/bin/agent/local/Agent.d.ts.map +1 -1
- package/bin/agent/local/Agent.js +30 -3
- package/bin/agent/local/Agent.js.map +1 -1
- package/bin/agent/local/services/AgentSessions.d.ts +23 -0
- package/bin/agent/local/services/AgentSessions.d.ts.map +1 -1
- package/bin/agent/local/services/AgentSessions.js +44 -0
- package/bin/agent/local/services/AgentSessions.js.map +1 -1
- package/bin/agent/remote/RemoteSession.d.ts +2 -0
- package/bin/agent/remote/RemoteSession.d.ts.map +1 -1
- package/bin/agent/remote/RemoteSession.js +4 -0
- package/bin/agent/remote/RemoteSession.js.map +1 -1
- package/bin/agent/remote/RemoteTransport.d.ts +2 -0
- package/bin/agent/remote/RemoteTransport.d.ts.map +1 -1
- package/bin/agent/remote/transports/HttpRemoteAgentTransport.d.ts +1 -0
- package/bin/agent/remote/transports/HttpRemoteAgentTransport.d.ts.map +1 -1
- package/bin/agent/remote/transports/HttpRemoteAgentTransport.js +11 -7
- package/bin/agent/remote/transports/HttpRemoteAgentTransport.js.map +1 -1
- package/bin/agent/remote/transports/RpcRemoteAgentTransport.d.ts +1 -0
- package/bin/agent/remote/transports/RpcRemoteAgentTransport.d.ts.map +1 -1
- package/bin/agent/remote/transports/RpcRemoteAgentTransport.js +3 -0
- package/bin/agent/remote/transports/RpcRemoteAgentTransport.js.map +1 -1
- package/bin/executor/Executor.d.ts +43 -0
- package/bin/executor/Executor.d.ts.map +1 -1
- package/bin/executor/Executor.js +127 -7
- package/bin/executor/Executor.js.map +1 -1
- package/bin/executor/composer/compaction/SessionCompactionComposer.d.ts +10 -0
- package/bin/executor/composer/compaction/SessionCompactionComposer.d.ts.map +1 -1
- package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionComposer.d.ts +0 -10
- package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionComposer.d.ts.map +1 -1
- package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionComposer.js +4 -34
- package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionComposer.js.map +1 -1
- package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionExecutor.d.ts +1 -3
- package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionExecutor.d.ts.map +1 -1
- package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionExecutor.js +7 -59
- package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionExecutor.js.map +1 -1
- package/bin/executor/core-engine/CoreEngineContextCompaction.d.ts +38 -0
- package/bin/executor/core-engine/CoreEngineContextCompaction.d.ts.map +1 -0
- package/bin/executor/core-engine/CoreEngineContextCompaction.js +392 -0
- package/bin/executor/core-engine/CoreEngineContextCompaction.js.map +1 -0
- package/bin/executor/core-engine/CoreEngineMessageState.d.ts +15 -0
- package/bin/executor/core-engine/CoreEngineMessageState.d.ts.map +1 -1
- package/bin/executor/core-engine/CoreEngineMessageState.js +20 -0
- package/bin/executor/core-engine/CoreEngineMessageState.js.map +1 -1
- package/bin/executor/core-engine/CoreEngineRunner.d.ts +15 -0
- package/bin/executor/core-engine/CoreEngineRunner.d.ts.map +1 -1
- package/bin/executor/core-engine/CoreEngineRunner.js +150 -35
- package/bin/executor/core-engine/CoreEngineRunner.js.map +1 -1
- package/bin/executor/store/history/SessionHistoryStore.d.ts +7 -23
- package/bin/executor/store/history/SessionHistoryStore.d.ts.map +1 -1
- package/bin/executor/store/history/jsonl/JsonlSessionHistoryStore.d.ts.map +1 -1
- package/bin/executor/store/history/jsonl/JsonlSessionHistoryStore.js +2 -4
- package/bin/executor/store/history/jsonl/JsonlSessionHistoryStore.js.map +1 -1
- package/bin/executor/tools/plugin/PluginToolBridge.d.ts.map +1 -1
- package/bin/executor/tools/plugin/PluginToolBridge.js +4 -2
- package/bin/executor/tools/plugin/PluginToolBridge.js.map +1 -1
- package/bin/executor/types/SessionRun.d.ts +8 -0
- package/bin/executor/types/SessionRun.d.ts.map +1 -1
- package/bin/index.d.ts +3 -2
- package/bin/index.d.ts.map +1 -1
- package/bin/index.js +2 -2
- package/bin/index.js.map +1 -1
- package/bin/model/CityModelAdapter.d.ts +6 -0
- package/bin/model/CityModelAdapter.d.ts.map +1 -1
- package/bin/model/CityModelAdapter.js +13 -0
- package/bin/model/CityModelAdapter.js.map +1 -1
- package/bin/plugin/core/PluginLocalExecution.js +3 -3
- package/bin/plugin/core/PluginLocalExecution.js.map +1 -1
- package/bin/plugin/core/PluginRegistry.d.ts +41 -2
- package/bin/plugin/core/PluginRegistry.d.ts.map +1 -1
- package/bin/plugin/core/PluginRegistry.js +145 -6
- package/bin/plugin/core/PluginRegistry.js.map +1 -1
- package/bin/rpc/Client.d.ts +4 -0
- package/bin/rpc/Client.d.ts.map +1 -1
- package/bin/rpc/Client.js +11 -0
- package/bin/rpc/Client.js.map +1 -1
- package/bin/session/Session.d.ts +15 -1
- package/bin/session/Session.d.ts.map +1 -1
- package/bin/session/Session.js +83 -11
- package/bin/session/Session.js.map +1 -1
- package/bin/session/SessionSystemBuilder.d.ts.map +1 -1
- package/bin/session/SessionSystemBuilder.js +3 -1
- package/bin/session/SessionSystemBuilder.js.map +1 -1
- package/bin/session/browse/Browse.d.ts +0 -8
- package/bin/session/browse/Browse.d.ts.map +1 -1
- package/bin/session/browse/Browse.js +72 -57
- package/bin/session/browse/Browse.js.map +1 -1
- package/bin/session/recorder/JsonlSessionMessageStore.d.ts +69 -16
- package/bin/session/recorder/JsonlSessionMessageStore.d.ts.map +1 -1
- package/bin/session/recorder/JsonlSessionMessageStore.js +283 -60
- package/bin/session/recorder/JsonlSessionMessageStore.js.map +1 -1
- package/bin/session/recorder/SessionRecorder.d.ts +20 -2
- package/bin/session/recorder/SessionRecorder.d.ts.map +1 -1
- package/bin/session/recorder/SessionRecorder.js +91 -46
- package/bin/session/recorder/SessionRecorder.js.map +1 -1
- package/bin/session/recorder/SessionRecorderCompaction.d.ts +3 -3
- package/bin/session/recorder/SessionRecorderCompaction.d.ts.map +1 -1
- package/bin/session/recorder/SessionRecorderCompaction.js +118 -88
- package/bin/session/recorder/SessionRecorderCompaction.js.map +1 -1
- package/bin/session/recorder/SessionRecorderHistoryStore.d.ts +2 -2
- package/bin/session/recorder/SessionRecorderHistoryStore.d.ts.map +1 -1
- package/bin/session/recorder/SessionRecorderHistoryStore.js +31 -36
- package/bin/session/recorder/SessionRecorderHistoryStore.js.map +1 -1
- package/bin/session/runtime/SessionPromptRuntime.d.ts +21 -1
- package/bin/session/runtime/SessionPromptRuntime.d.ts.map +1 -1
- package/bin/session/runtime/SessionPromptRuntime.js +65 -8
- package/bin/session/runtime/SessionPromptRuntime.js.map +1 -1
- package/bin/session/services/SessionStateService.d.ts +19 -1
- package/bin/session/services/SessionStateService.d.ts.map +1 -1
- package/bin/session/services/SessionStateService.js +70 -40
- package/bin/session/services/SessionStateService.js.map +1 -1
- package/bin/session/services/SessionTurnService.d.ts +15 -0
- package/bin/session/services/SessionTurnService.d.ts.map +1 -1
- package/bin/session/services/SessionTurnService.js +104 -7
- package/bin/session/services/SessionTurnService.js.map +1 -1
- package/bin/session/services/SessionViewService.d.ts +1 -5
- package/bin/session/services/SessionViewService.d.ts.map +1 -1
- package/bin/session/services/SessionViewService.js +4 -34
- package/bin/session/services/SessionViewService.js.map +1 -1
- package/bin/session/storage/Paths.d.ts +3 -15
- package/bin/session/storage/Paths.d.ts.map +1 -1
- package/bin/session/storage/Paths.js +5 -21
- package/bin/session/storage/Paths.js.map +1 -1
- package/bin/types/agent/SessionActor.d.ts +8 -0
- package/bin/types/agent/SessionActor.d.ts.map +1 -1
- package/bin/types/agent/SessionTypes.d.ts +2 -24
- package/bin/types/agent/SessionTypes.d.ts.map +1 -1
- package/bin/types/executor/SessionRunContext.d.ts +29 -0
- package/bin/types/executor/SessionRunContext.d.ts.map +1 -1
- package/bin/types/plugin/PluginRuntime.d.ts +59 -2
- package/bin/types/plugin/PluginRuntime.d.ts.map +1 -1
- package/bin/types/plugin/PluginState.d.ts +10 -0
- package/bin/types/plugin/PluginState.d.ts.map +1 -1
- package/bin/types/rpc/RpcProtocol.d.ts +10 -0
- package/bin/types/rpc/RpcProtocol.d.ts.map +1 -1
- package/bin/types/runtime/agent/AgentContext.d.ts +17 -5
- package/bin/types/runtime/agent/AgentContext.d.ts.map +1 -1
- package/bin/types/runtime/agent/AgentContext.js +29 -6
- package/bin/types/runtime/agent/AgentContext.js.map +1 -1
- package/bin/types/session/SessionLocalState.d.ts +8 -0
- package/bin/types/session/SessionLocalState.d.ts.map +1 -1
- package/bin/types/session/SessionMessage.d.ts +16 -12
- package/bin/types/session/SessionMessage.d.ts.map +1 -1
- package/bin/types/session/SessionMutation.d.ts +1 -1
- package/bin/types/session/SessionMutation.js +1 -1
- package/bin/types/session/SessionOptions.d.ts +16 -0
- package/bin/types/session/SessionOptions.d.ts.map +1 -1
- package/bin/types/session/SessionQueueCommand.d.ts +68 -0
- package/bin/types/session/SessionQueueCommand.d.ts.map +1 -0
- package/bin/types/session/SessionQueueCommand.js +10 -0
- package/bin/types/session/SessionQueueCommand.js.map +1 -0
- package/bin/types/session/SessionSegment.d.ts +57 -0
- package/bin/types/session/SessionSegment.d.ts.map +1 -0
- package/bin/types/session/SessionSegment.js +8 -0
- package/bin/types/session/SessionSegment.js.map +1 -0
- package/bin/utils/logger/Logger.d.ts +7 -9
- package/bin/utils/logger/Logger.d.ts.map +1 -1
- package/bin/utils/logger/Logger.js +11 -9
- package/bin/utils/logger/Logger.js.map +1 -1
- package/package.json +3 -3
- package/scripts/city-model-tool-loop.test.mjs +32 -0
- package/scripts/core-engine-context-compaction.test.mjs +411 -0
- package/scripts/logger-isolation.test.mjs +55 -0
- package/scripts/multi-agent-plugin-isolation.test.mjs +289 -0
- package/scripts/plugin-tool-bridge.test.mjs +52 -0
- package/scripts/remote-session-reconnect.test.mjs +18 -0
- package/scripts/session-action-message.test.mjs +59 -13
- package/scripts/session-compaction-context-window.test.mjs +96 -0
- package/scripts/session-config-turn-boundary.test.mjs +278 -0
- package/scripts/session-list-title.test.mjs +21 -3
- package/scripts/session-prompt-runtime.test.mjs +93 -0
- package/scripts/session-recorder.test.mjs +335 -15
- package/src/agent/local/Agent.ts +34 -3
- package/src/agent/local/services/AgentSessions.ts +61 -0
- package/src/agent/remote/RemoteSession.ts +5 -0
- package/src/agent/remote/RemoteTransport.ts +2 -0
- package/src/agent/remote/transports/HttpRemoteAgentTransport.ts +15 -5
- package/src/agent/remote/transports/RpcRemoteAgentTransport.ts +4 -0
- package/src/executor/Executor.ts +161 -7
- package/src/executor/composer/compaction/SessionCompactionComposer.ts +12 -0
- package/src/executor/composer/compaction/jsonl/JsonlSessionCompactionComposer.ts +4 -55
- package/src/executor/composer/compaction/jsonl/JsonlSessionCompactionExecutor.ts +8 -66
- package/src/executor/core-engine/CoreEngineContextCompaction.ts +477 -0
- package/src/executor/core-engine/CoreEngineMessageState.ts +29 -0
- package/src/executor/core-engine/CoreEngineRunner.ts +211 -43
- package/src/executor/store/history/SessionHistoryStore.ts +7 -26
- package/src/executor/store/history/jsonl/JsonlSessionHistoryStore.ts +2 -4
- package/src/executor/tools/plugin/PluginToolBridge.ts +4 -2
- package/src/executor/types/SessionRun.ts +9 -0
- package/src/index.ts +9 -1
- package/src/model/CityModelAdapter.ts +15 -0
- package/src/plugin/core/PluginLocalExecution.ts +3 -3
- package/src/plugin/core/PluginRegistry.ts +187 -6
- package/src/rpc/Client.ts +12 -0
- package/src/session/Session.ts +97 -11
- package/src/session/SessionSystemBuilder.ts +4 -1
- package/src/session/browse/Browse.ts +73 -69
- package/src/session/recorder/JsonlSessionMessageStore.ts +378 -60
- package/src/session/recorder/SessionRecorder.ts +116 -49
- package/src/session/recorder/SessionRecorderCompaction.ts +131 -108
- package/src/session/recorder/SessionRecorderHistoryStore.ts +29 -49
- package/src/session/runtime/SessionPromptRuntime.ts +86 -10
- package/src/session/services/SessionStateService.ts +89 -45
- package/src/session/services/SessionTurnService.ts +112 -7
- package/src/session/services/SessionViewService.ts +4 -50
- package/src/session/storage/Paths.ts +5 -38
- package/src/types/agent/SessionActor.ts +9 -0
- package/src/types/agent/SessionTypes.ts +2 -24
- package/src/types/executor/SessionRunContext.ts +34 -0
- package/src/types/plugin/PluginRuntime.ts +63 -2
- package/src/types/plugin/PluginState.ts +10 -0
- package/src/types/rpc/RpcProtocol.ts +11 -0
- package/src/types/runtime/agent/AgentContext.ts +32 -7
- package/src/types/session/SessionLocalState.ts +9 -0
- package/src/types/session/SessionMessage.ts +16 -12
- package/src/types/session/SessionMutation.ts +1 -1
- package/src/types/session/SessionOptions.ts +21 -0
- package/src/types/session/SessionQueueCommand.ts +78 -0
- package/src/types/session/SessionSegment.ts +62 -0
- package/src/utils/logger/Logger.ts +10 -10
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -7,7 +7,13 @@
|
|
|
7
7
|
* - 保持失败返回结构稳定,避免对外 Session 行为变化。
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
streamText,
|
|
12
|
+
type FileUIPart,
|
|
13
|
+
type LanguageModel,
|
|
14
|
+
type StepResult,
|
|
15
|
+
type Tool,
|
|
16
|
+
} from "ai";
|
|
11
17
|
import { buildOpenAIResponsesProviderOptions } from "@executor/messages/SessionMessageCodec.js";
|
|
12
18
|
import { logAssistantMessageNow } from "@executor/messages/SessionMessageLog.js";
|
|
13
19
|
import {
|
|
@@ -33,6 +39,11 @@ import {
|
|
|
33
39
|
} from "@executor/core-engine/CoreEngineError.js";
|
|
34
40
|
import { collectFinalAssistantMessageFromUiStream } from "@executor/core-engine/CoreEngineUiStreamCollector.js";
|
|
35
41
|
import { CoreEngineMessageState } from "@executor/core-engine/CoreEngineMessageState.js";
|
|
42
|
+
import {
|
|
43
|
+
deep_compact_model_messages,
|
|
44
|
+
resolve_model_usage_ratio,
|
|
45
|
+
should_compact_after_usage,
|
|
46
|
+
} from "@executor/core-engine/CoreEngineContextCompaction.js";
|
|
36
47
|
import type { Logger } from "@/utils/logger/Logger.js";
|
|
37
48
|
import type { SessionHistoryStore } from "@/executor/store/history/SessionHistoryStore.js";
|
|
38
49
|
import type { SessionContextComposer } from "@executor/composer/context/SessionContextComposer.js";
|
|
@@ -48,6 +59,9 @@ import type {
|
|
|
48
59
|
|
|
49
60
|
const TURN_STOPPED_MESSAGE = "Turn stopped";
|
|
50
61
|
|
|
62
|
+
/** Provider context-length error 在当前 step 内最多压缩重试三次。 */
|
|
63
|
+
const MAX_CONTEXT_ERROR_COMPACTION_RETRIES = 3;
|
|
64
|
+
|
|
51
65
|
/**
|
|
52
66
|
* 生成 file part 去重 key。
|
|
53
67
|
*/
|
|
@@ -125,6 +139,20 @@ interface CoreEngineRunInput {
|
|
|
125
139
|
* 当前显式运行上下文。
|
|
126
140
|
*/
|
|
127
141
|
run_context: SessionRunContext;
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* 在统一输入队列提交后解析当前 Session step 的 effective 配置。
|
|
145
|
+
*/
|
|
146
|
+
resolve_step_inputs: () => Promise<{
|
|
147
|
+
/** 当前 Session step 使用的模型。 */
|
|
148
|
+
model: LanguageModel;
|
|
149
|
+
/** 当前 Session step 使用的 system messages。 */
|
|
150
|
+
system: SessionExecuteInput["system"];
|
|
151
|
+
/** 当前 Session step 使用的工具集合。 */
|
|
152
|
+
tools: SessionExecuteInput["tools"];
|
|
153
|
+
/** 当前 Session step 模型支持的总上下文窗口长度。 */
|
|
154
|
+
context_window?: number;
|
|
155
|
+
}>;
|
|
128
156
|
}
|
|
129
157
|
|
|
130
158
|
/**
|
|
@@ -136,6 +164,9 @@ export class CoreEngineRunner {
|
|
|
136
164
|
private readonly logger: Logger;
|
|
137
165
|
private readonly should_compact_on_error: CoreEngineRunnerOptions["should_compact_on_error"];
|
|
138
166
|
|
|
167
|
+
/** 最近一次已经通过真实 usage 验收的持久化 Summary 标识。 */
|
|
168
|
+
private validated_compaction_summary_id = "";
|
|
169
|
+
|
|
139
170
|
constructor(options: CoreEngineRunnerOptions) {
|
|
140
171
|
this.history_store = options.history_store;
|
|
141
172
|
this.context_composer = options.context_composer;
|
|
@@ -149,12 +180,13 @@ export class CoreEngineRunner {
|
|
|
149
180
|
async run(input: CoreEngineRunInput): Promise<SessionRunResult> {
|
|
150
181
|
const start_time = Date.now();
|
|
151
182
|
const session_id = String(this.history_store.sessionId || "").trim();
|
|
152
|
-
|
|
183
|
+
let system = Array.isArray(input.execute_input.system)
|
|
153
184
|
? input.execute_input.system
|
|
154
185
|
: [];
|
|
155
|
-
|
|
186
|
+
let tools = input.execute_input.tools;
|
|
156
187
|
let last_observed_stream_error: unknown = undefined;
|
|
157
188
|
let final_assistant_ui_message: SessionMessageRecordV1 | null = null;
|
|
189
|
+
let compact_required = false;
|
|
158
190
|
|
|
159
191
|
try {
|
|
160
192
|
const message_state = await CoreEngineMessageState.create({
|
|
@@ -162,6 +194,9 @@ export class CoreEngineRunner {
|
|
|
162
194
|
tools,
|
|
163
195
|
projectRoot: input.run_context.projectRoot,
|
|
164
196
|
});
|
|
197
|
+
let persisted_compaction_summary_id = resolve_compaction_summary_id(
|
|
198
|
+
input.execute_input.messages,
|
|
199
|
+
);
|
|
165
200
|
|
|
166
201
|
const append_merged_user_messages = (messages: SessionRecordV1[]) =>
|
|
167
202
|
message_state.appendMergedUserMessages(messages);
|
|
@@ -188,7 +223,7 @@ export class CoreEngineRunner {
|
|
|
188
223
|
await context_composer_on_step_finish(step_result);
|
|
189
224
|
};
|
|
190
225
|
|
|
191
|
-
const
|
|
226
|
+
const prepare_step_inputs = this.context_composer.createPrepareStepHandler({
|
|
192
227
|
system,
|
|
193
228
|
appendMergedUserMessages: append_merged_user_messages,
|
|
194
229
|
runContext: input.run_context,
|
|
@@ -196,53 +231,169 @@ export class CoreEngineRunner {
|
|
|
196
231
|
|
|
197
232
|
let text_only_continuation_count = 0;
|
|
198
233
|
let incomplete_response_recovery_count = 0;
|
|
234
|
+
let context_error_compaction_retries = 0;
|
|
235
|
+
let compact_pending = false;
|
|
236
|
+
let compact_validation_pending = Boolean(
|
|
237
|
+
persisted_compaction_summary_id &&
|
|
238
|
+
persisted_compaction_summary_id !==
|
|
239
|
+
this.validated_compaction_summary_id,
|
|
240
|
+
);
|
|
241
|
+
let compact_depth = 0;
|
|
199
242
|
|
|
200
243
|
while (step_count < MAX_TOOL_LOOP_STEPS) {
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
const step_assistant_ui_message =
|
|
220
|
-
await collectFinalAssistantMessageFromUiStream({
|
|
221
|
-
result,
|
|
244
|
+
// 关键点(中文):steer 与 command 在同一个 Session step 检查点执行。
|
|
245
|
+
// 当前流与 tool callback 保持原执行视图,下一 step 再统一读取 effective 配置。
|
|
246
|
+
await prepare_step_inputs({ messages: [] });
|
|
247
|
+
const step_inputs = await input.resolve_step_inputs();
|
|
248
|
+
system = Array.isArray(step_inputs.system) ? step_inputs.system : [];
|
|
249
|
+
tools = step_inputs.tools;
|
|
250
|
+
if (input.run_context.consume_history_reload?.()) {
|
|
251
|
+
const canonical_records = await this.history_store.list_records();
|
|
252
|
+
await message_state.replace_session_messages(canonical_records, tools);
|
|
253
|
+
persisted_compaction_summary_id = resolve_compaction_summary_id(
|
|
254
|
+
canonical_records,
|
|
255
|
+
);
|
|
256
|
+
compact_validation_pending = Boolean(
|
|
257
|
+
persisted_compaction_summary_id &&
|
|
258
|
+
persisted_compaction_summary_id !==
|
|
259
|
+
this.validated_compaction_summary_id,
|
|
260
|
+
);
|
|
261
|
+
await this.logger.log("info", "[agent] context.history_reloaded", {
|
|
222
262
|
sessionId: session_id,
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
263
|
+
recordCount: canonical_records.length,
|
|
264
|
+
compactionSummaryId: persisted_compaction_summary_id || undefined,
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
if (compact_pending) {
|
|
268
|
+
const previous_message_count = message_state.modelMessages.length;
|
|
269
|
+
message_state.replace_model_messages(
|
|
270
|
+
deep_compact_model_messages(
|
|
271
|
+
message_state.modelMessages,
|
|
272
|
+
compact_depth,
|
|
273
|
+
),
|
|
274
|
+
);
|
|
275
|
+
compact_depth += 1;
|
|
276
|
+
compact_pending = false;
|
|
277
|
+
compact_validation_pending = true;
|
|
278
|
+
compact_required = true;
|
|
279
|
+
await this.logger.log("info", "[agent] context.compacted", {
|
|
280
|
+
sessionId: session_id,
|
|
281
|
+
reason: "usage_threshold",
|
|
282
|
+
compactDepth: compact_depth,
|
|
283
|
+
previousMessageCount: previous_message_count,
|
|
284
|
+
nextMessageCount: message_state.modelMessages.length,
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
last_observed_stream_error = undefined;
|
|
289
|
+
let step_assistant_ui_message: SessionMessageRecordV1;
|
|
290
|
+
let executed_steps: StepResult<Record<string, Tool>>[];
|
|
291
|
+
try {
|
|
292
|
+
const result = streamText({
|
|
293
|
+
model: step_inputs.model,
|
|
294
|
+
system,
|
|
295
|
+
onStepFinish: on_step_finish,
|
|
296
|
+
messages: message_state.modelMessages,
|
|
297
|
+
tools,
|
|
230
298
|
abortSignal: input.run_context.abortSignal,
|
|
299
|
+
providerOptions: buildOpenAIResponsesProviderOptions(),
|
|
300
|
+
onError: async ({ error }) => {
|
|
301
|
+
last_observed_stream_error = error;
|
|
302
|
+
await this.logger.log("error", "[agent] stream.error", {
|
|
303
|
+
sessionId: session_id,
|
|
304
|
+
...summarizeStreamError(error),
|
|
305
|
+
});
|
|
306
|
+
},
|
|
231
307
|
});
|
|
232
308
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
309
|
+
step_assistant_ui_message =
|
|
310
|
+
await collectFinalAssistantMessageFromUiStream({
|
|
311
|
+
result,
|
|
312
|
+
sessionId: session_id,
|
|
313
|
+
logger: this.logger,
|
|
314
|
+
buildFallbackAssistantMessage: (text) =>
|
|
315
|
+
this.context_composer.buildFallbackAssistantMessage(
|
|
316
|
+
text,
|
|
317
|
+
input.run_context,
|
|
318
|
+
),
|
|
319
|
+
onUiMessageChunkCallback: input.run_context.onUiMessageChunkCallback,
|
|
320
|
+
abortSignal: input.run_context.abortSignal,
|
|
321
|
+
});
|
|
237
322
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
323
|
+
final_assistant_ui_message = mergeAssistantUiMessages(
|
|
324
|
+
final_assistant_ui_message,
|
|
325
|
+
step_assistant_ui_message,
|
|
326
|
+
);
|
|
327
|
+
|
|
328
|
+
// 关键点(中文):先保存本 step 已收敛的 assistant 消息,再等待 steps。
|
|
329
|
+
// stop/abort 时 `result.steps` 可能抛错,但当前已经生成的文本仍应沉淀。
|
|
330
|
+
message_state.appendRuntimeSessionMessage(step_assistant_ui_message);
|
|
331
|
+
executed_steps = await result.steps;
|
|
332
|
+
} catch (error) {
|
|
333
|
+
const compact_error = this.should_compact_on_error(error)
|
|
334
|
+
? error
|
|
335
|
+
: last_observed_stream_error;
|
|
336
|
+
if (
|
|
337
|
+
this.should_compact_on_error(compact_error) &&
|
|
338
|
+
context_error_compaction_retries <
|
|
339
|
+
MAX_CONTEXT_ERROR_COMPACTION_RETRIES
|
|
340
|
+
) {
|
|
341
|
+
context_error_compaction_retries += 1;
|
|
342
|
+
const previous_message_count = message_state.modelMessages.length;
|
|
343
|
+
message_state.replace_model_messages(
|
|
344
|
+
deep_compact_model_messages(
|
|
345
|
+
message_state.modelMessages,
|
|
346
|
+
compact_depth,
|
|
347
|
+
),
|
|
348
|
+
);
|
|
349
|
+
compact_depth += 1;
|
|
350
|
+
compact_pending = false;
|
|
351
|
+
compact_validation_pending = true;
|
|
352
|
+
compact_required = true;
|
|
353
|
+
await this.logger.log("warn", "[agent] context.compacted", {
|
|
354
|
+
sessionId: session_id,
|
|
355
|
+
reason: "provider_context_error",
|
|
356
|
+
retryCount: context_error_compaction_retries,
|
|
357
|
+
compactDepth: compact_depth,
|
|
358
|
+
previousMessageCount: previous_message_count,
|
|
359
|
+
nextMessageCount: message_state.modelMessages.length,
|
|
360
|
+
...summarizeStreamError(compact_error),
|
|
361
|
+
});
|
|
362
|
+
continue;
|
|
363
|
+
}
|
|
364
|
+
throw error;
|
|
365
|
+
}
|
|
241
366
|
|
|
242
|
-
|
|
367
|
+
context_error_compaction_retries = 0;
|
|
243
368
|
const last_step = executed_steps[executed_steps.length - 1];
|
|
244
369
|
if (!last_step) break;
|
|
245
370
|
|
|
371
|
+
const usage_ratio = resolve_model_usage_ratio(
|
|
372
|
+
last_step.usage,
|
|
373
|
+
step_inputs.context_window,
|
|
374
|
+
);
|
|
375
|
+
if (usage_ratio !== null) {
|
|
376
|
+
const validating_compaction = compact_validation_pending;
|
|
377
|
+
compact_pending = should_compact_after_usage(
|
|
378
|
+
usage_ratio,
|
|
379
|
+
validating_compaction,
|
|
380
|
+
);
|
|
381
|
+
compact_validation_pending = false;
|
|
382
|
+
if (validating_compaction && persisted_compaction_summary_id) {
|
|
383
|
+
this.validated_compaction_summary_id =
|
|
384
|
+
persisted_compaction_summary_id;
|
|
385
|
+
}
|
|
386
|
+
if (compact_pending) compact_required = true;
|
|
387
|
+
await this.logger.log("info", "[agent] context.usage", {
|
|
388
|
+
sessionId: session_id,
|
|
389
|
+
stepIndex: step_count,
|
|
390
|
+
usageRatio: usage_ratio,
|
|
391
|
+
contextWindow: step_inputs.context_window,
|
|
392
|
+
validatingCompaction: validating_compaction,
|
|
393
|
+
compactPending: compact_pending,
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
|
|
246
397
|
const incomplete_response = detectIncompleteResponse({
|
|
247
398
|
stepResult: last_step,
|
|
248
399
|
assistantMessage: step_assistant_ui_message,
|
|
@@ -350,9 +501,8 @@ export class CoreEngineRunner {
|
|
|
350
501
|
}
|
|
351
502
|
|
|
352
503
|
// 关键点(中文):stop 前做 tail merge,覆盖最后一个 step 后才入队的新 user 消息。
|
|
353
|
-
const
|
|
354
|
-
|
|
355
|
-
? tail_prepared.messages.length
|
|
504
|
+
const tail_merged_message_count = input.run_context.hasPendingStepInput?.()
|
|
505
|
+
? 1
|
|
356
506
|
: 0;
|
|
357
507
|
if (
|
|
358
508
|
shouldContinueForTailMergedUserMessages({
|
|
@@ -408,6 +558,7 @@ export class CoreEngineRunner {
|
|
|
408
558
|
return {
|
|
409
559
|
success: true,
|
|
410
560
|
assistantMessage: final_message,
|
|
561
|
+
...(compact_required ? { compact_required: true } : {}),
|
|
411
562
|
deferredPersistedUserMessages: [
|
|
412
563
|
...input.run_context.deferredPersistedUserMessages,
|
|
413
564
|
],
|
|
@@ -428,6 +579,7 @@ export class CoreEngineRunner {
|
|
|
428
579
|
success: false,
|
|
429
580
|
error: error_text,
|
|
430
581
|
...(stopped_message ? { assistantMessage: stopped_message } : {}),
|
|
582
|
+
...(compact_required ? { compact_required: true } : {}),
|
|
431
583
|
deferredPersistedUserMessages: [
|
|
432
584
|
...input.run_context.deferredPersistedUserMessages,
|
|
433
585
|
],
|
|
@@ -454,6 +606,7 @@ export class CoreEngineRunner {
|
|
|
454
606
|
`Execution failed: ${error_text}`,
|
|
455
607
|
input.run_context,
|
|
456
608
|
),
|
|
609
|
+
...(compact_required ? { compact_required: true } : {}),
|
|
457
610
|
deferredPersistedUserMessages: [
|
|
458
611
|
...input.run_context.deferredPersistedUserMessages,
|
|
459
612
|
],
|
|
@@ -461,3 +614,18 @@ export class CoreEngineRunner {
|
|
|
461
614
|
}
|
|
462
615
|
}
|
|
463
616
|
}
|
|
617
|
+
|
|
618
|
+
/** 读取当前模型上下文中最新的持久化 compact Summary 标识。 */
|
|
619
|
+
function resolve_compaction_summary_id(messages: SessionRecordV1[]): string {
|
|
620
|
+
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
621
|
+
const message = messages[index];
|
|
622
|
+
if (!("role" in message) || message.role !== "assistant") continue;
|
|
623
|
+
if (
|
|
624
|
+
message.metadata?.source === "compact" &&
|
|
625
|
+
message.metadata.kind === "summary"
|
|
626
|
+
) {
|
|
627
|
+
return String(message.id || "").trim();
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
return "";
|
|
631
|
+
}
|
|
@@ -30,24 +30,11 @@ export type SessionHistoryCompactInput = {
|
|
|
30
30
|
system: SessionSystemMessage[];
|
|
31
31
|
|
|
32
32
|
/**
|
|
33
|
-
*
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* 输入 token 近似上限。
|
|
39
|
-
*/
|
|
40
|
-
maxInputTokensApprox: number;
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* compact 时是否归档旧消息。
|
|
44
|
-
*/
|
|
45
|
-
archiveOnCompact: boolean;
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* 前段压缩比例(0-1)。
|
|
33
|
+
* 是否明确要求本次执行持久化 deep compact。
|
|
34
|
+
*
|
|
35
|
+
* 真实 usage 触发与内存消息折叠由 CoreEngine 决定;Store 只负责归档已经完成的历史。
|
|
49
36
|
*/
|
|
50
|
-
|
|
37
|
+
force?: boolean;
|
|
51
38
|
|
|
52
39
|
/**
|
|
53
40
|
* 可选 action 发布回调。
|
|
@@ -88,19 +75,13 @@ export interface SessionHistoryStore {
|
|
|
88
75
|
*/
|
|
89
76
|
finalize_inflight(message?: SessionRecordV1 | null): Promise<void>;
|
|
90
77
|
|
|
91
|
-
/**
|
|
92
|
-
* 读取完整 session records。
|
|
93
|
-
*/
|
|
78
|
+
/** 读取当前模型上下文所需的 session records。 */
|
|
94
79
|
list_records(): Promise<SessionRecordV1[]>;
|
|
95
80
|
|
|
96
|
-
/**
|
|
97
|
-
* 读取 session record 区间 [start, end)。
|
|
98
|
-
*/
|
|
81
|
+
/** 读取当前模型上下文 record 区间 [start, end)。 */
|
|
99
82
|
slice_records(start: number, end: number): Promise<SessionRecordV1[]>;
|
|
100
83
|
|
|
101
|
-
/**
|
|
102
|
-
* 读取 session record 总条数。
|
|
103
|
-
*/
|
|
84
|
+
/** 读取当前模型上下文 record 总条数。 */
|
|
104
85
|
record_count(): Promise<number>;
|
|
105
86
|
|
|
106
87
|
/**
|
|
@@ -665,10 +665,8 @@ export class JsonlSessionHistoryStore implements SessionHistoryStore {
|
|
|
665
665
|
{
|
|
666
666
|
model: input.model,
|
|
667
667
|
system: this.normalizeSystem(input.system),
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
archiveOnCompact: input.archiveOnCompact,
|
|
671
|
-
compactRatio: input.compactRatio,
|
|
668
|
+
archiveOnCompact: false,
|
|
669
|
+
force: input.force,
|
|
672
670
|
...(input.onAction ? { onAction: input.onAction } : {}),
|
|
673
671
|
},
|
|
674
672
|
);
|
|
@@ -138,7 +138,8 @@ export async function invokePluginCallTool(
|
|
|
138
138
|
}
|
|
139
139
|
|
|
140
140
|
try {
|
|
141
|
-
const
|
|
141
|
+
const plugins = getSessionRunContext()?.agentPlugins || params.plugins;
|
|
142
|
+
const result = await plugins.runAction({
|
|
142
143
|
plugin,
|
|
143
144
|
action,
|
|
144
145
|
payload,
|
|
@@ -191,7 +192,8 @@ export async function invokePluginReadTool(
|
|
|
191
192
|
): Promise<PluginReadToolResult> {
|
|
192
193
|
const input: PluginReadInput = params.input;
|
|
193
194
|
try {
|
|
194
|
-
const
|
|
195
|
+
const plugins = getSessionRunContext()?.agentPlugins || params.plugins;
|
|
196
|
+
const data = plugins.read({
|
|
195
197
|
plugin: typeof input.plugin === "string" ? input.plugin : undefined,
|
|
196
198
|
action: typeof input.action === "string" ? input.action : undefined,
|
|
197
199
|
});
|
|
@@ -112,6 +112,15 @@ export interface SessionRunResult {
|
|
|
112
112
|
* - 为保证消息顺序稳定,统一在 assistant 结果落盘后再由外层 Session 持久化。
|
|
113
113
|
*/
|
|
114
114
|
deferredPersistedUserMessages?: SessionUserMessageV1[];
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* 本轮结束后是否需要把已完成的 canonical 历史持久化压缩。
|
|
118
|
+
*
|
|
119
|
+
* 关键点(中文)
|
|
120
|
+
* - 真实 usage 达到 95% 或本轮已经执行过内存 compact 时为 true。
|
|
121
|
+
* - 上层必须等 Assistant writer 收口后再执行,避免压缩流式草稿。
|
|
122
|
+
*/
|
|
123
|
+
compact_required?: boolean;
|
|
115
124
|
}
|
|
116
125
|
|
|
117
126
|
/**
|
package/src/index.ts
CHANGED
|
@@ -15,6 +15,7 @@ export type { SessionOptions } from "./types/session/SessionOptions.js";
|
|
|
15
15
|
export {
|
|
16
16
|
inferAgentModelLabel,
|
|
17
17
|
normalizeAgentModel,
|
|
18
|
+
read_agent_model_context_window,
|
|
18
19
|
} from "./model/CityModelAdapter.js";
|
|
19
20
|
export type { AgentModel } from "./model/CityModelAdapter.js";
|
|
20
21
|
export type {
|
|
@@ -48,6 +49,13 @@ export type {
|
|
|
48
49
|
SessionUserMessage,
|
|
49
50
|
SessionUserMessagePart,
|
|
50
51
|
} from "./types/session/SessionMessage.js";
|
|
52
|
+
export type {
|
|
53
|
+
SessionContextSnapshot,
|
|
54
|
+
SessionMessageStorageStats,
|
|
55
|
+
SessionSegmentRange,
|
|
56
|
+
SessionSegmentSnapshot,
|
|
57
|
+
SessionSegmentSummary,
|
|
58
|
+
} from "./types/session/SessionSegment.js";
|
|
51
59
|
export {
|
|
52
60
|
is_session_mutation,
|
|
53
61
|
} from "./types/session/SessionMutation.js";
|
|
@@ -239,7 +247,7 @@ export {
|
|
|
239
247
|
export { assertProjectExecutionTarget } from "./config/ExecutionBinding.js";
|
|
240
248
|
|
|
241
249
|
// 日志
|
|
242
|
-
export { getLogger,
|
|
250
|
+
export { getLogger, type Logger } from "./utils/logger/Logger.js";
|
|
243
251
|
export { generateId } from "./utils/Id.js";
|
|
244
252
|
export {
|
|
245
253
|
formatDateTimeInTimezone,
|
|
@@ -44,6 +44,21 @@ export function normalizeAgentModel(model: AgentModel): LanguageModel {
|
|
|
44
44
|
return model;
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
+
/**
|
|
48
|
+
* 从 Agent 模型输入读取已声明的上下文窗口。
|
|
49
|
+
*
|
|
50
|
+
* 只有 CityModel 携带可信的模型目录元数据;普通 AI SDK LanguageModel 未声明时返回空。
|
|
51
|
+
*/
|
|
52
|
+
export function read_agent_model_context_window(
|
|
53
|
+
model: AgentModel | undefined,
|
|
54
|
+
): number | undefined {
|
|
55
|
+
if (!model || !isCityModel(model)) return undefined;
|
|
56
|
+
const context_window = model.context_window;
|
|
57
|
+
return Number.isSafeInteger(context_window) && Number(context_window) > 0
|
|
58
|
+
? Number(context_window)
|
|
59
|
+
: undefined;
|
|
60
|
+
}
|
|
61
|
+
|
|
47
62
|
/**
|
|
48
63
|
* 从 Agent 模型输入推导展示标签。
|
|
49
64
|
*/
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import path from "node:path";
|
|
11
|
-
import {
|
|
11
|
+
import { getLogger } from "@/utils/logger/Logger.js";
|
|
12
12
|
import { resolve_agent_env } from "@/config/AgentEnv.js";
|
|
13
13
|
import { findPluginByName } from "@/plugin/core/PluginCatalog.js";
|
|
14
14
|
import {
|
|
@@ -45,12 +45,12 @@ export function createLocalPluginCommandContext(
|
|
|
45
45
|
: input.config;
|
|
46
46
|
const agent_id = String(config.id || "").trim() || path.basename(rootPath) || "agent";
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
const logger = getLogger(rootPath);
|
|
49
49
|
|
|
50
50
|
return {
|
|
51
51
|
cwd: rootPath,
|
|
52
52
|
rootPath,
|
|
53
|
-
logger
|
|
53
|
+
logger,
|
|
54
54
|
config,
|
|
55
55
|
env,
|
|
56
56
|
paths: createAgentPathRuntime(
|