@downcity/agent 1.1.200 → 1.1.203
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 +3 -7
- package/bin/agent/local/Agent.d.ts.map +1 -1
- package/bin/agent/local/Agent.js +14 -19
- package/bin/agent/local/Agent.js.map +1 -1
- package/bin/agent/local/services/{AgentSessionManager.d.ts → AgentSessions.d.ts} +12 -17
- package/bin/agent/local/services/AgentSessions.d.ts.map +1 -0
- package/bin/agent/local/services/{AgentSessionManager.js → AgentSessions.js} +11 -26
- package/bin/agent/local/services/AgentSessions.js.map +1 -0
- package/bin/agent/remote/RemoteAgent.d.ts +2 -9
- package/bin/agent/remote/RemoteAgent.d.ts.map +1 -1
- package/bin/agent/remote/RemoteAgent.js +40 -22
- package/bin/agent/remote/RemoteAgent.js.map +1 -1
- package/bin/agent/remote/RemoteSession.d.ts +5 -5
- package/bin/agent/remote/RemoteSession.d.ts.map +1 -1
- package/bin/agent/remote/RemoteSession.js +5 -3
- package/bin/agent/remote/RemoteSession.js.map +1 -1
- package/bin/agent/remote/RemoteTransport.d.ts +2 -2
- package/bin/agent/remote/transports/HttpRemoteAgentTransport.d.ts +2 -2
- package/bin/agent/remote/transports/HttpRemoteAgentTransport.js +5 -5
- package/bin/agent/remote/transports/RpcRemoteAgentTransport.d.ts +2 -2
- package/bin/agent/remote/transports/RpcRemoteAgentTransport.js +2 -2
- package/bin/executor/Executor.d.ts +5 -5
- package/bin/executor/Executor.d.ts.map +1 -1
- package/bin/executor/Executor.js +22 -13
- package/bin/executor/Executor.js.map +1 -1
- package/bin/executor/SessionRunScope.d.ts +1 -1
- package/bin/executor/SessionRunScope.d.ts.map +1 -1
- package/bin/executor/composer/compaction/SessionCompactionComposer.d.ts +3 -3
- package/bin/executor/composer/compaction/SessionCompactionComposer.d.ts.map +1 -1
- package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionExecutor.d.ts +4 -5
- package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionExecutor.d.ts.map +1 -1
- package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionExecutor.js +56 -16
- package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionExecutor.js.map +1 -1
- package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionFileOperations.d.ts +27 -0
- package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionFileOperations.d.ts.map +1 -0
- package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionFileOperations.js +181 -0
- package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionFileOperations.js.map +1 -0
- package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionPrompts.d.ts +45 -0
- package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionPrompts.d.ts.map +1 -0
- package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionPrompts.js +144 -0
- package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionPrompts.js.map +1 -0
- package/bin/executor/composer/context/LocalSessionContextComposer.d.ts +3 -3
- package/bin/executor/composer/context/LocalSessionContextComposer.d.ts.map +1 -1
- package/bin/executor/composer/context/SessionContextComposer.d.ts +3 -3
- package/bin/executor/composer/context/SessionContextComposer.d.ts.map +1 -1
- package/bin/executor/composer/history/SessionHistoryComposer.d.ts +2 -2
- package/bin/executor/composer/history/SessionHistoryComposer.d.ts.map +1 -1
- package/bin/executor/composer/history/SessionHistoryWriter.d.ts +5 -5
- package/bin/executor/composer/history/SessionHistoryWriter.d.ts.map +1 -1
- package/bin/executor/composer/history/SessionHistoryWriter.js +6 -6
- package/bin/executor/composer/history/SessionHistoryWriter.js.map +1 -1
- package/bin/executor/composer/history/jsonl/JsonlSessionHistoryComposer.d.ts +2 -2
- package/bin/executor/composer/history/jsonl/JsonlSessionHistoryComposer.d.ts.map +1 -1
- package/bin/executor/composer/history/jsonl/JsonlSessionHistoryComposer.js +5 -5
- package/bin/executor/composer/history/jsonl/JsonlSessionHistoryComposer.js.map +1 -1
- package/bin/executor/core-engine/CoreEngineMessageState.d.ts +5 -5
- package/bin/executor/core-engine/CoreEngineMessageState.d.ts.map +1 -1
- package/bin/executor/core-engine/CoreEngineMessageState.js.map +1 -1
- package/bin/executor/core-engine/CoreEngineRunner.js.map +1 -1
- package/bin/executor/core-engine/CoreEngineSignals.d.ts +4 -4
- package/bin/executor/core-engine/CoreEngineSignals.d.ts.map +1 -1
- package/bin/executor/core-engine/CoreEngineSignals.js.map +1 -1
- package/bin/executor/core-engine/CoreEngineUiStreamCollector.d.ts +3 -3
- package/bin/executor/core-engine/CoreEngineUiStreamCollector.d.ts.map +1 -1
- package/bin/executor/core-engine/CoreEngineUiStreamCollector.js.map +1 -1
- package/bin/executor/messages/AssistantResultPersistence.d.ts +5 -5
- package/bin/executor/messages/AssistantResultPersistence.d.ts.map +1 -1
- package/bin/executor/messages/AssistantResultPersistence.js +1 -1
- package/bin/executor/messages/AssistantResultPersistence.js.map +1 -1
- package/bin/executor/messages/SessionAttachmentMapper.d.ts +3 -3
- package/bin/executor/messages/SessionAttachmentMapper.d.ts.map +1 -1
- package/bin/executor/messages/SessionAttachmentMapper.js.map +1 -1
- package/bin/executor/messages/SessionMessageCodec.d.ts +4 -4
- package/bin/executor/messages/SessionMessageCodec.d.ts.map +1 -1
- package/bin/executor/messages/SessionMessageCodec.js +5 -5
- package/bin/executor/messages/SessionMessageCodec.js.map +1 -1
- package/bin/executor/messages/SessionMessageLog.d.ts +3 -3
- package/bin/executor/messages/SessionMessageLog.d.ts.map +1 -1
- package/bin/executor/messages/SessionMessageLog.js.map +1 -1
- package/bin/executor/messages/SessionStepEventMapper.d.ts +2 -2
- package/bin/executor/messages/SessionStepEventMapper.d.ts.map +1 -1
- package/bin/executor/messages/SessionStepEventMapper.js.map +1 -1
- package/bin/executor/messages/UserVisibleText.d.ts +3 -3
- package/bin/executor/messages/UserVisibleText.d.ts.map +1 -1
- package/bin/executor/messages/UserVisibleText.js +3 -3
- package/bin/executor/messages/UserVisibleText.js.map +1 -1
- package/bin/executor/services/ExecutorInflightService.d.ts +2 -2
- package/bin/executor/services/ExecutorInflightService.d.ts.map +1 -1
- package/bin/executor/services/ExecutorInflightService.js +4 -4
- package/bin/executor/services/ExecutorInflightService.js.map +1 -1
- package/bin/executor/store/history/SessionHistoryStore.d.ts +24 -21
- package/bin/executor/store/history/SessionHistoryStore.d.ts.map +1 -1
- package/bin/executor/store/history/SessionHistoryStore.js +3 -3
- package/bin/executor/store/history/jsonl/JsonlSessionHistoryStore.d.ts +18 -19
- package/bin/executor/store/history/jsonl/JsonlSessionHistoryStore.d.ts.map +1 -1
- package/bin/executor/store/history/jsonl/JsonlSessionHistoryStore.js +33 -36
- package/bin/executor/store/history/jsonl/JsonlSessionHistoryStore.js.map +1 -1
- package/bin/executor/tools/plugin/PluginToolDefinition.d.ts +1 -7
- package/bin/executor/tools/plugin/PluginToolDefinition.d.ts.map +1 -1
- package/bin/executor/tools/plugin/PluginToolSchemas.d.ts +4 -6
- package/bin/executor/tools/plugin/PluginToolSchemas.d.ts.map +1 -1
- package/bin/executor/tools/plugin/PluginToolSchemas.js +24 -10
- package/bin/executor/tools/plugin/PluginToolSchemas.js.map +1 -1
- package/bin/executor/types/{SessionMessages.d.ts → SessionRecords.d.ts} +53 -28
- package/bin/executor/types/SessionRecords.d.ts.map +1 -0
- package/bin/executor/types/SessionRecords.js +52 -0
- package/bin/executor/types/SessionRecords.js.map +1 -0
- package/bin/executor/types/SessionRun.d.ts +3 -3
- package/bin/executor/types/SessionRun.d.ts.map +1 -1
- package/bin/index.d.ts +1 -1
- package/bin/index.d.ts.map +1 -1
- package/bin/rpc/Client.d.ts +5 -5
- package/bin/rpc/Client.js +4 -4
- package/bin/session/Session.d.ts +6 -6
- package/bin/session/Session.d.ts.map +1 -1
- package/bin/session/Session.js +8 -8
- package/bin/session/Session.js.map +1 -1
- package/bin/session/SessionTitle.d.ts +2 -2
- package/bin/session/SessionTitle.d.ts.map +1 -1
- package/bin/session/SessionTitle.js +3 -3
- package/bin/session/SessionTitle.js.map +1 -1
- package/bin/session/browse/Browse.d.ts +12 -12
- package/bin/session/browse/Browse.d.ts.map +1 -1
- package/bin/session/browse/Browse.js +9 -9
- package/bin/session/browse/Browse.js.map +1 -1
- package/bin/session/index.d.ts +1 -1
- package/bin/session/index.js +1 -1
- package/bin/session/runtime/SessionPromptRuntime.d.ts +3 -3
- package/bin/session/runtime/SessionPromptRuntime.d.ts.map +1 -1
- package/bin/session/services/SessionStateService.d.ts +7 -8
- package/bin/session/services/SessionStateService.d.ts.map +1 -1
- package/bin/session/services/SessionStateService.js +24 -34
- package/bin/session/services/SessionStateService.js.map +1 -1
- package/bin/session/services/SessionViewService.d.ts +4 -4
- package/bin/session/services/SessionViewService.js +12 -12
- package/bin/session/services/SessionViewService.js.map +1 -1
- package/bin/session/storage/Persistence.d.ts +4 -4
- package/bin/session/storage/Persistence.d.ts.map +1 -1
- package/bin/session/storage/RuntimeSessionPort.d.ts +2 -2
- package/bin/session/storage/RuntimeSessionPort.d.ts.map +1 -1
- package/bin/session/storage/RuntimeSessionPort.js +4 -4
- package/bin/session/storage/RuntimeSessionPort.js.map +1 -1
- package/bin/types/agent/AgentTypes.d.ts +2 -2
- package/bin/types/agent/AgentTypes.d.ts.map +1 -1
- package/bin/types/agent/SessionActor.d.ts +11 -11
- package/bin/types/agent/SessionActor.d.ts.map +1 -1
- package/bin/types/agent/SessionTypes.d.ts +12 -12
- package/bin/types/agent/SessionTypes.d.ts.map +1 -1
- package/bin/types/executor/SessionRunContext.d.ts +2 -2
- package/bin/types/executor/SessionRunContext.d.ts.map +1 -1
- package/bin/types/rpc/RpcProtocol.d.ts +6 -6
- package/bin/types/runtime/agent/AgentContext.d.ts +7 -7
- package/bin/types/runtime/agent/AgentContext.d.ts.map +1 -1
- package/bin/types/sdk/AgentSessionAction.d.ts +8 -49
- package/bin/types/sdk/AgentSessionAction.d.ts.map +1 -1
- package/bin/types/sdk/AgentSessionAction.js +4 -4
- package/bin/types/sdk/AgentSessionTurn.d.ts +2 -2
- package/bin/types/sdk/AgentSessionTurn.d.ts.map +1 -1
- package/package.json +3 -3
- package/scripts/agent-ready.test.mjs +1 -1
- package/scripts/city-model-tool-loop.test.mjs +36 -4
- package/scripts/plugin-tool-bridge.test.mjs +13 -0
- package/scripts/session-action-message.test.mjs +71 -27
- package/scripts/session-compaction-prompts.test.mjs +97 -0
- package/scripts/session-history-archive.test.mjs +8 -8
- package/scripts/session-history-inflight.test.mjs +10 -10
- package/scripts/session-list-title.test.mjs +9 -9
- package/scripts/session-title-event.test.mjs +12 -10
- package/src/agent/local/Agent.ts +16 -22
- package/src/agent/local/services/{AgentSessionManager.ts → AgentSessions.ts} +16 -32
- package/src/agent/remote/RemoteAgent.ts +58 -23
- package/src/agent/remote/RemoteSession.ts +10 -8
- package/src/agent/remote/RemoteTransport.ts +5 -5
- package/src/agent/remote/transports/HttpRemoteAgentTransport.ts +10 -10
- package/src/agent/remote/transports/RpcRemoteAgentTransport.ts +6 -6
- package/src/executor/Executor.ts +30 -19
- package/src/executor/SessionRunScope.ts +1 -1
- package/src/executor/composer/compaction/SessionCompactionComposer.ts +3 -3
- package/src/executor/composer/compaction/jsonl/JsonlSessionCompactionExecutor.ts +73 -29
- package/src/executor/composer/compaction/jsonl/JsonlSessionCompactionFileOperations.ts +197 -0
- package/src/executor/composer/compaction/jsonl/JsonlSessionCompactionPrompts.ts +162 -0
- package/src/executor/composer/context/LocalSessionContextComposer.ts +5 -5
- package/src/executor/composer/context/SessionContextComposer.ts +5 -5
- package/src/executor/composer/history/SessionHistoryComposer.ts +2 -2
- package/src/executor/composer/history/SessionHistoryWriter.ts +10 -10
- package/src/executor/composer/history/jsonl/JsonlSessionHistoryComposer.ts +13 -13
- package/src/executor/core-engine/CoreEngineMessageState.ts +8 -8
- package/src/executor/core-engine/CoreEngineRunner.ts +7 -7
- package/src/executor/core-engine/CoreEngineSignals.ts +7 -7
- package/src/executor/core-engine/CoreEngineUiStreamCollector.ts +5 -5
- package/src/executor/messages/AssistantResultPersistence.ts +8 -8
- package/src/executor/messages/SessionAttachmentMapper.ts +11 -11
- package/src/executor/messages/SessionMessageCodec.ts +10 -10
- package/src/executor/messages/SessionMessageLog.ts +3 -3
- package/src/executor/messages/SessionStepEventMapper.ts +5 -5
- package/src/executor/messages/UserVisibleText.ts +9 -9
- package/src/executor/services/ExecutorInflightService.ts +7 -7
- package/src/executor/store/history/SessionHistoryStore.ts +26 -23
- package/src/executor/store/history/jsonl/JsonlSessionHistoryStore.ts +58 -62
- package/src/executor/tools/plugin/PluginToolSchemas.ts +24 -10
- package/src/executor/types/{SessionMessages.ts → SessionRecords.ts} +71 -40
- package/src/executor/types/SessionRun.ts +5 -5
- package/src/index.ts +4 -4
- package/src/rpc/Client.ts +9 -9
- package/src/session/Session.ts +10 -10
- package/src/session/SessionTitle.ts +7 -7
- package/src/session/browse/Browse.ts +38 -38
- package/src/session/index.ts +1 -1
- package/src/session/runtime/SessionPromptRuntime.ts +6 -6
- package/src/session/services/SessionStateService.ts +40 -47
- package/src/session/services/SessionTurnService.ts +4 -4
- package/src/session/services/SessionViewService.ts +21 -21
- package/src/session/storage/Persistence.ts +6 -6
- package/src/session/storage/RuntimeSessionPort.ts +6 -6
- package/src/types/agent/AgentTypes.ts +4 -4
- package/src/types/agent/SessionActor.ts +12 -12
- package/src/types/agent/SessionTypes.ts +12 -12
- package/src/types/executor/SessionRunContext.ts +2 -2
- package/src/types/rpc/RpcProtocol.ts +6 -6
- package/src/types/runtime/agent/AgentContext.ts +8 -8
- package/src/types/sdk/AgentSessionAction.ts +12 -56
- package/src/types/sdk/AgentSessionTurn.ts +2 -2
- package/tsconfig.tsbuildinfo +1 -1
- package/bin/agent/local/services/AgentSessionManager.d.ts.map +0 -1
- package/bin/agent/local/services/AgentSessionManager.js.map +0 -1
- package/bin/executor/types/SessionMessages.d.ts.map +0 -1
- package/bin/executor/types/SessionMessages.js +0 -46
- package/bin/executor/types/SessionMessages.js.map +0 -1
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JsonlSessionCompactionFileOperations:上下文压缩文件操作记录模块。
|
|
3
|
+
*
|
|
4
|
+
* 关键点(中文)
|
|
5
|
+
* - 从被压缩的 session 消息中 best-effort 提取文件读写痕迹。
|
|
6
|
+
* - 输出结构化 XML 片段,追加到 LLM 生成的 compact summary 末尾。
|
|
7
|
+
* - 解析失败或没有文件操作时不影响 compact 主流程。
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { isTextUIPart } from "ai";
|
|
11
|
+
import type { SessionMessageRecordV1 } from "@/executor/types/SessionRecords.js";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* 压缩范围内的文件操作汇总。
|
|
15
|
+
*/
|
|
16
|
+
export type SessionCompactionFileOperations = {
|
|
17
|
+
/** 本次压缩范围内被读取或查看过的文件路径。 */
|
|
18
|
+
read_files: string[];
|
|
19
|
+
/** 本次压缩范围内被新增、修改或删除过的文件路径。 */
|
|
20
|
+
modified_files: string[];
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
type UnknownRecord = Record<string, unknown>;
|
|
24
|
+
|
|
25
|
+
const PATH_CANDIDATE_RE =
|
|
26
|
+
/(?:\.{1,2}\/|\/|[A-Za-z0-9_.@-]+\/)[A-Za-z0-9_.@~:+/=-]+/g;
|
|
27
|
+
const PATCH_FILE_RE = /^\*\*\* (?:Add|Update|Delete) File: (.+)$/gm;
|
|
28
|
+
const GIT_STATUS_FILE_RE = /^\s*(?:[MADRCU?!]{1,2}|[ MADRCU?!][ MADRCU?!])\s+(.+)$/gm;
|
|
29
|
+
const READ_COMMAND_RE =
|
|
30
|
+
/\b(?:cat|less|more|sed|nl|head|tail|rg|grep|find|ls|wc|stat|open|git\s+(?:show|diff|status|grep|ls-files))\b/;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* 把压缩范围内的文件操作格式化为 XML。
|
|
34
|
+
*/
|
|
35
|
+
export function format_session_compaction_file_operations(
|
|
36
|
+
messages: SessionMessageRecordV1[],
|
|
37
|
+
): string {
|
|
38
|
+
const operations = collect_session_compaction_file_operations(messages);
|
|
39
|
+
if (operations.read_files.length === 0 && operations.modified_files.length === 0) {
|
|
40
|
+
return "";
|
|
41
|
+
}
|
|
42
|
+
return [
|
|
43
|
+
"<read-files>",
|
|
44
|
+
...operations.read_files.map((file_path) => xml_escape(file_path)),
|
|
45
|
+
"</read-files>",
|
|
46
|
+
"",
|
|
47
|
+
"<modified-files>",
|
|
48
|
+
...operations.modified_files.map((file_path) => xml_escape(file_path)),
|
|
49
|
+
"</modified-files>",
|
|
50
|
+
].join("\n");
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* 收集压缩范围内的文件操作。
|
|
55
|
+
*/
|
|
56
|
+
export function collect_session_compaction_file_operations(
|
|
57
|
+
messages: SessionMessageRecordV1[],
|
|
58
|
+
): SessionCompactionFileOperations {
|
|
59
|
+
const read_files = new Set<string>();
|
|
60
|
+
const modified_files = new Set<string>();
|
|
61
|
+
|
|
62
|
+
for (const message of Array.isArray(messages) ? messages : []) {
|
|
63
|
+
const text_blocks = extract_message_operation_texts(message);
|
|
64
|
+
for (const text of text_blocks) {
|
|
65
|
+
for (const file_path of extract_modified_files(text)) {
|
|
66
|
+
modified_files.add(file_path);
|
|
67
|
+
}
|
|
68
|
+
for (const file_path of extract_read_files(text)) {
|
|
69
|
+
read_files.add(file_path);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
for (const file_path of modified_files) {
|
|
75
|
+
read_files.delete(file_path);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
read_files: [...read_files].sort(),
|
|
80
|
+
modified_files: [...modified_files].sort(),
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* 提取单条消息中可能包含文件操作的文本块。
|
|
86
|
+
*/
|
|
87
|
+
function extract_message_operation_texts(message: SessionMessageRecordV1): string[] {
|
|
88
|
+
const out: string[] = [];
|
|
89
|
+
const parts = Array.isArray(message.parts) ? message.parts : [];
|
|
90
|
+
for (const part of parts) {
|
|
91
|
+
if (isTextUIPart(part)) {
|
|
92
|
+
const text = String(part.text ?? "").trim();
|
|
93
|
+
if (text) out.push(text);
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
const part_record = to_record(part);
|
|
97
|
+
if (!part_record) continue;
|
|
98
|
+
const input_text = stringify_compact(part_record.input);
|
|
99
|
+
const output_text = stringify_compact(part_record.output);
|
|
100
|
+
const error_text = stringify_compact(part_record.errorText);
|
|
101
|
+
if (input_text) out.push(input_text);
|
|
102
|
+
if (output_text) out.push(output_text);
|
|
103
|
+
if (error_text) out.push(error_text);
|
|
104
|
+
}
|
|
105
|
+
return out;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* 提取 patch / git status 中的修改文件。
|
|
110
|
+
*/
|
|
111
|
+
function extract_modified_files(text: string): string[] {
|
|
112
|
+
const out = new Set<string>();
|
|
113
|
+
for (const file_path of match_group_values(text, PATCH_FILE_RE)) {
|
|
114
|
+
const normalized = normalize_file_path(file_path);
|
|
115
|
+
if (normalized) out.add(normalized);
|
|
116
|
+
}
|
|
117
|
+
for (const file_path of match_group_values(text, GIT_STATUS_FILE_RE)) {
|
|
118
|
+
const normalized = normalize_file_path(file_path);
|
|
119
|
+
if (normalized) out.add(normalized);
|
|
120
|
+
}
|
|
121
|
+
return [...out];
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* 从读命令文本中提取读取路径。
|
|
126
|
+
*/
|
|
127
|
+
function extract_read_files(text: string): string[] {
|
|
128
|
+
const out = new Set<string>();
|
|
129
|
+
const lines = String(text || "").split(/\r?\n/);
|
|
130
|
+
for (const line of lines) {
|
|
131
|
+
if (!READ_COMMAND_RE.test(line)) continue;
|
|
132
|
+
for (const candidate of line.match(PATH_CANDIDATE_RE) || []) {
|
|
133
|
+
const normalized = normalize_file_path(candidate);
|
|
134
|
+
if (normalized) out.add(normalized);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return [...out];
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* 获取正则第一个捕获组的所有结果。
|
|
142
|
+
*/
|
|
143
|
+
function match_group_values(text: string, pattern: RegExp): string[] {
|
|
144
|
+
const out: string[] = [];
|
|
145
|
+
pattern.lastIndex = 0;
|
|
146
|
+
let match = pattern.exec(text);
|
|
147
|
+
while (match) {
|
|
148
|
+
const value = String(match[1] || "").trim();
|
|
149
|
+
if (value) out.push(value);
|
|
150
|
+
match = pattern.exec(text);
|
|
151
|
+
}
|
|
152
|
+
return out;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* 归一化候选路径。
|
|
157
|
+
*/
|
|
158
|
+
function normalize_file_path(value: string): string {
|
|
159
|
+
let file_path = String(value || "").trim();
|
|
160
|
+
if (!file_path || file_path.includes("://")) return "";
|
|
161
|
+
file_path = file_path.replace(/^["'`]+|["'`]+$/g, "");
|
|
162
|
+
file_path = file_path.replace(/[),.;:]+$/g, "");
|
|
163
|
+
if (!file_path || file_path === "." || file_path === "..") return "";
|
|
164
|
+
if (file_path.startsWith("-")) return "";
|
|
165
|
+
return file_path;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* 转成对象记录。
|
|
170
|
+
*/
|
|
171
|
+
function to_record(value: unknown): UnknownRecord | null {
|
|
172
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
173
|
+
return value as UnknownRecord;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* 将未知结构紧凑地转为文本。
|
|
178
|
+
*/
|
|
179
|
+
function stringify_compact(value: unknown): string {
|
|
180
|
+
if (value === undefined || value === null) return "";
|
|
181
|
+
if (typeof value === "string") return value;
|
|
182
|
+
try {
|
|
183
|
+
return JSON.stringify(value);
|
|
184
|
+
} catch {
|
|
185
|
+
return String(value);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* XML 文本转义。
|
|
191
|
+
*/
|
|
192
|
+
function xml_escape(value: string): string {
|
|
193
|
+
return String(value || "")
|
|
194
|
+
.replace(/&/g, "&")
|
|
195
|
+
.replace(/</g, "<")
|
|
196
|
+
.replace(/>/g, ">");
|
|
197
|
+
}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JsonlSessionCompactionPrompts:上下文压缩提示词模块。
|
|
3
|
+
*
|
|
4
|
+
* 关键点(中文)
|
|
5
|
+
* - 统一维护 session compact 使用的 system prompt 与 user prompt。
|
|
6
|
+
* - 支持初始压缩、迭代更新压缩、turn prefix 压缩三类场景。
|
|
7
|
+
* - prompt 文本保持结构化格式稳定,便于后续 LLM 继续接力。
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* 上下文压缩 system prompt。
|
|
12
|
+
*/
|
|
13
|
+
export const SESSION_COMPACTION_SYSTEM_PROMPT = [
|
|
14
|
+
"You are a context summarization assistant. Your task is to read a conversation between a user and an AI assistant, then produce a structured summary following the exact format specified.",
|
|
15
|
+
"",
|
|
16
|
+
"Do NOT continue the conversation. Do NOT respond to any questions in the conversation. ONLY output the structured summary.",
|
|
17
|
+
].join("\n");
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* 构建初始上下文压缩 prompt。
|
|
21
|
+
*/
|
|
22
|
+
export function build_initial_session_compaction_prompt(params: {
|
|
23
|
+
/** 待压缩的历史对话文本。 */
|
|
24
|
+
conversation_text: string;
|
|
25
|
+
}): string {
|
|
26
|
+
return [
|
|
27
|
+
String(params.conversation_text || "").trim(),
|
|
28
|
+
"",
|
|
29
|
+
"The messages above are a conversation to summarize. Create a structured context checkpoint summary that another LLM will use to continue the work.",
|
|
30
|
+
"",
|
|
31
|
+
"Use this EXACT format:",
|
|
32
|
+
"",
|
|
33
|
+
"## Goal",
|
|
34
|
+
"[What is the user trying to accomplish? Can be multiple items if the session covers different tasks.]",
|
|
35
|
+
"",
|
|
36
|
+
"## Constraints & Preferences",
|
|
37
|
+
"- [Any constraints, preferences, or requirements mentioned by user]",
|
|
38
|
+
'- [Or "(none)" if none were mentioned]',
|
|
39
|
+
"",
|
|
40
|
+
"## Progress",
|
|
41
|
+
"### Done",
|
|
42
|
+
"- [x] [Completed tasks/changes]",
|
|
43
|
+
"",
|
|
44
|
+
"### In Progress",
|
|
45
|
+
"- [ ] [Current work]",
|
|
46
|
+
"",
|
|
47
|
+
"### Blocked",
|
|
48
|
+
"[Issues preventing progress, if any]",
|
|
49
|
+
"",
|
|
50
|
+
"## Key Decisions",
|
|
51
|
+
"- **[Decision]**: [Brief rationale]",
|
|
52
|
+
"",
|
|
53
|
+
"## Next Steps",
|
|
54
|
+
"1. [Ordered list of what should happen next]",
|
|
55
|
+
"",
|
|
56
|
+
"## Critical Context",
|
|
57
|
+
"- [Any data, examples, or references needed to continue]",
|
|
58
|
+
'- [Or "(none)" if not applicable]',
|
|
59
|
+
"",
|
|
60
|
+
"Keep each section concise. Preserve exact file paths, function names, and error messages.",
|
|
61
|
+
].join("\n");
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* 构建迭代更新上下文压缩 prompt。
|
|
66
|
+
*/
|
|
67
|
+
export function build_update_session_compaction_prompt(params: {
|
|
68
|
+
/** 已存在的旧摘要。 */
|
|
69
|
+
previous_summary: string;
|
|
70
|
+
/** 本次需要合入旧摘要的新对话文本。 */
|
|
71
|
+
new_conversation_text: string;
|
|
72
|
+
}): string {
|
|
73
|
+
return [
|
|
74
|
+
"<previous-summary>",
|
|
75
|
+
String(params.previous_summary || "").trim(),
|
|
76
|
+
"</previous-summary>",
|
|
77
|
+
"",
|
|
78
|
+
String(params.new_conversation_text || "").trim(),
|
|
79
|
+
"",
|
|
80
|
+
"The messages above are NEW conversation messages to incorporate into the existing summary provided in <previous-summary> tags.",
|
|
81
|
+
"",
|
|
82
|
+
"Update the existing structured summary with new information. RULES:",
|
|
83
|
+
"- PRESERVE all existing information from the previous summary",
|
|
84
|
+
"- ADD new progress, decisions, and context from the new messages",
|
|
85
|
+
'- UPDATE the Progress section: move items from "In Progress" to "Done" when completed',
|
|
86
|
+
'- UPDATE "Next Steps" based on what was accomplished',
|
|
87
|
+
"- PRESERVE exact file paths, function names, and error messages",
|
|
88
|
+
"- If something is no longer relevant, you may remove it",
|
|
89
|
+
"",
|
|
90
|
+
"Use this EXACT format:",
|
|
91
|
+
"",
|
|
92
|
+
"## Goal",
|
|
93
|
+
"[Preserve existing goals, add new ones if the task expanded]",
|
|
94
|
+
"",
|
|
95
|
+
"## Constraints & Preferences",
|
|
96
|
+
"- [Preserve existing, add new ones discovered]",
|
|
97
|
+
"",
|
|
98
|
+
"## Progress",
|
|
99
|
+
"### Done",
|
|
100
|
+
"- [x] [Include previously done items AND newly completed items]",
|
|
101
|
+
"",
|
|
102
|
+
"### In Progress",
|
|
103
|
+
"- [ ] [Current work - update based on progress]",
|
|
104
|
+
"",
|
|
105
|
+
"### Blocked",
|
|
106
|
+
"[Current blockers - remove if resolved]",
|
|
107
|
+
"",
|
|
108
|
+
"## Key Decisions",
|
|
109
|
+
"- **[Decision]**: [Brief rationale] (preserve all previous, add new)",
|
|
110
|
+
"",
|
|
111
|
+
"## Next Steps",
|
|
112
|
+
"1. [Update based on current state]",
|
|
113
|
+
"",
|
|
114
|
+
"## Critical Context",
|
|
115
|
+
"- [Preserve important context, add new if needed]",
|
|
116
|
+
"",
|
|
117
|
+
"Keep each section concise. Preserve exact file paths, function names, and error messages.",
|
|
118
|
+
].join("\n");
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* 构建 turn prefix 压缩 prompt。
|
|
123
|
+
*/
|
|
124
|
+
export function build_turn_prefix_session_compaction_prompt(params: {
|
|
125
|
+
/** 被切下来的 turn prefix 文本。 */
|
|
126
|
+
prefix_text: string;
|
|
127
|
+
}): string {
|
|
128
|
+
return [
|
|
129
|
+
String(params.prefix_text || "").trim(),
|
|
130
|
+
"",
|
|
131
|
+
"This is the PREFIX of a turn that was too large to keep. The SUFFIX (recent work) is retained.",
|
|
132
|
+
"",
|
|
133
|
+
"Summarize the prefix to provide context for the retained suffix:",
|
|
134
|
+
"",
|
|
135
|
+
"## Original Request",
|
|
136
|
+
"[What did the user ask for in this turn?]",
|
|
137
|
+
"",
|
|
138
|
+
"## Early Progress",
|
|
139
|
+
"- [Key decisions and work done in the prefix]",
|
|
140
|
+
"",
|
|
141
|
+
"## Context for Suffix",
|
|
142
|
+
"- [Information needed to understand the retained recent work]",
|
|
143
|
+
"",
|
|
144
|
+
"Be concise. Focus on what's needed to understand the kept suffix.",
|
|
145
|
+
].join("\n");
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* 给摘要追加文件操作 XML。
|
|
150
|
+
*/
|
|
151
|
+
export function append_session_compaction_file_operations(params: {
|
|
152
|
+
/** LLM 生成的结构化摘要。 */
|
|
153
|
+
summary: string;
|
|
154
|
+
/** 文件操作 XML,空字符串时不追加。 */
|
|
155
|
+
file_operations_xml?: string;
|
|
156
|
+
}): string {
|
|
157
|
+
const summary = String(params.summary || "").trim();
|
|
158
|
+
const file_operations_xml = String(params.file_operations_xml || "").trim();
|
|
159
|
+
if (!file_operations_xml) return summary;
|
|
160
|
+
if (!summary) return file_operations_xml;
|
|
161
|
+
return `${summary}\n\n${file_operations_xml}`;
|
|
162
|
+
}
|
|
@@ -13,9 +13,9 @@ import type {
|
|
|
13
13
|
SessionContextComposeResult,
|
|
14
14
|
} from "@executor/composer/context/SessionContextComposer.js";
|
|
15
15
|
import type {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
} from "@/executor/types/
|
|
16
|
+
SessionRecordV1,
|
|
17
|
+
SessionMessageRecordV1,
|
|
18
|
+
} from "@/executor/types/SessionRecords.js";
|
|
19
19
|
import type { SessionSystemMessage } from "@/executor/types/SessionPrompts.js";
|
|
20
20
|
import type { Tool } from "ai";
|
|
21
21
|
import type { SessionRunContext } from "@/types/executor/SessionRunContext.js";
|
|
@@ -66,7 +66,7 @@ export class LocalSessionContextComposer implements SessionContextComposer {
|
|
|
66
66
|
input: {
|
|
67
67
|
system: SessionSystemMessage[];
|
|
68
68
|
appendMergedUserMessages: (
|
|
69
|
-
messages:
|
|
69
|
+
messages: SessionRecordV1[],
|
|
70
70
|
) => Promise<ModelMessage[]>;
|
|
71
71
|
runContext: SessionRunContext;
|
|
72
72
|
},
|
|
@@ -150,7 +150,7 @@ export class LocalSessionContextComposer implements SessionContextComposer {
|
|
|
150
150
|
buildFallbackAssistantMessage(
|
|
151
151
|
text: string,
|
|
152
152
|
run_context: SessionRunContext,
|
|
153
|
-
):
|
|
153
|
+
): SessionMessageRecordV1 {
|
|
154
154
|
const sessionId = String(
|
|
155
155
|
run_context.sessionId || this.sessionId || "",
|
|
156
156
|
).trim();
|
|
@@ -8,9 +8,9 @@
|
|
|
8
8
|
|
|
9
9
|
import type { ModelMessage, Tool } from "ai";
|
|
10
10
|
import type {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
} from "@/executor/types/
|
|
11
|
+
SessionRecordV1,
|
|
12
|
+
SessionMessageRecordV1,
|
|
13
|
+
} from "@/executor/types/SessionRecords.js";
|
|
14
14
|
import type { SessionSystemMessage } from "@/executor/types/SessionPrompts.js";
|
|
15
15
|
import type { SessionRunContext } from "@/types/executor/SessionRunContext.js";
|
|
16
16
|
|
|
@@ -51,7 +51,7 @@ export interface SessionContextComposer {
|
|
|
51
51
|
* 将新增 user 消息转换为可追加的模型消息。
|
|
52
52
|
*/
|
|
53
53
|
appendMergedUserMessages: (
|
|
54
|
-
messages:
|
|
54
|
+
messages: SessionRecordV1[],
|
|
55
55
|
) => Promise<ModelMessage[]>;
|
|
56
56
|
/**
|
|
57
57
|
* 当前显式运行上下文。
|
|
@@ -79,5 +79,5 @@ export interface SessionContextComposer {
|
|
|
79
79
|
buildFallbackAssistantMessage(
|
|
80
80
|
text: string,
|
|
81
81
|
run_context: SessionRunContext,
|
|
82
|
-
):
|
|
82
|
+
): SessionMessageRecordV1;
|
|
83
83
|
}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import type { LanguageModel, Tool } from "ai";
|
|
11
|
-
import type {
|
|
11
|
+
import type { SessionRecordV1 } from "@/executor/types/SessionRecords.js";
|
|
12
12
|
import type { SessionSystemMessage } from "@/executor/types/SessionPrompts.js";
|
|
13
13
|
|
|
14
14
|
/**
|
|
@@ -58,5 +58,5 @@ export interface SessionHistoryComposer {
|
|
|
58
58
|
/**
|
|
59
59
|
* 为本轮 Session 执行准备模型输入消息。
|
|
60
60
|
*/
|
|
61
|
-
prepare(input: SessionHistoryPrepareInput): Promise<
|
|
61
|
+
prepare(input: SessionHistoryPrepareInput): Promise<SessionRecordV1[]>;
|
|
62
62
|
}
|
|
@@ -9,9 +9,9 @@
|
|
|
9
9
|
|
|
10
10
|
import type { JsonObject } from "@/types/common/Json.js";
|
|
11
11
|
import type {
|
|
12
|
-
|
|
12
|
+
SessionRecordV1,
|
|
13
13
|
SessionMetadataV1,
|
|
14
|
-
} from "@/executor/types/
|
|
14
|
+
} from "@/executor/types/SessionRecords.js";
|
|
15
15
|
import type { SessionHistoryStore } from "@/executor/store/history/SessionHistoryStore.js";
|
|
16
16
|
|
|
17
17
|
type SessionHistoryWriterOptions = {
|
|
@@ -63,15 +63,15 @@ export class SessionHistoryWriter {
|
|
|
63
63
|
/**
|
|
64
64
|
* 追加一条 user 消息。
|
|
65
65
|
*/
|
|
66
|
-
async
|
|
67
|
-
message?:
|
|
66
|
+
async append_user_message(params: {
|
|
67
|
+
message?: SessionRecordV1 | null;
|
|
68
68
|
text?: string;
|
|
69
69
|
extra?: JsonObject;
|
|
70
70
|
}): Promise<void> {
|
|
71
71
|
try {
|
|
72
72
|
const historyStore = this.getHistoryStore();
|
|
73
73
|
if (params.message && typeof params.message === "object") {
|
|
74
|
-
await historyStore.
|
|
74
|
+
await historyStore.write_record(params.message);
|
|
75
75
|
void this.afterSessionUpdatedAsync();
|
|
76
76
|
return;
|
|
77
77
|
}
|
|
@@ -86,7 +86,7 @@ export class SessionHistoryWriter {
|
|
|
86
86
|
extra: params.extra,
|
|
87
87
|
} as Omit<SessionMetadataV1, "v" | "ts">,
|
|
88
88
|
});
|
|
89
|
-
await historyStore.
|
|
89
|
+
await historyStore.write_record(message);
|
|
90
90
|
void this.afterSessionUpdatedAsync();
|
|
91
91
|
} catch {
|
|
92
92
|
// ignore
|
|
@@ -96,15 +96,15 @@ export class SessionHistoryWriter {
|
|
|
96
96
|
/**
|
|
97
97
|
* 追加一条 assistant 消息。
|
|
98
98
|
*/
|
|
99
|
-
async
|
|
100
|
-
message?:
|
|
99
|
+
async append_assistant_message(params: {
|
|
100
|
+
message?: SessionRecordV1 | null;
|
|
101
101
|
fallbackText?: string;
|
|
102
102
|
extra?: JsonObject;
|
|
103
103
|
}): Promise<void> {
|
|
104
104
|
try {
|
|
105
105
|
const historyStore = this.getHistoryStore();
|
|
106
106
|
if (params.message && typeof params.message === "object") {
|
|
107
|
-
await historyStore.
|
|
107
|
+
await historyStore.finalize_inflight(params.message);
|
|
108
108
|
void this.afterSessionUpdatedAsync();
|
|
109
109
|
return;
|
|
110
110
|
}
|
|
@@ -112,7 +112,7 @@ export class SessionHistoryWriter {
|
|
|
112
112
|
const fallbackText = String(params.fallbackText || "").trim();
|
|
113
113
|
if (!fallbackText) return;
|
|
114
114
|
|
|
115
|
-
await historyStore.
|
|
115
|
+
await historyStore.finalize_inflight(
|
|
116
116
|
historyStore.assistantText({
|
|
117
117
|
text: fallbackText,
|
|
118
118
|
metadata: {
|
|
@@ -9,11 +9,11 @@
|
|
|
9
9
|
|
|
10
10
|
import type { Tool } from "ai";
|
|
11
11
|
import {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
type
|
|
15
|
-
type
|
|
16
|
-
} from "@/executor/types/
|
|
12
|
+
is_session_action_record,
|
|
13
|
+
is_session_message_record,
|
|
14
|
+
type SessionRecordV1,
|
|
15
|
+
type SessionMessageRecordV1,
|
|
16
|
+
} from "@/executor/types/SessionRecords.js";
|
|
17
17
|
import type { SessionHistoryStore } from "@/executor/store/history/SessionHistoryStore.js";
|
|
18
18
|
import type {
|
|
19
19
|
SessionHistoryComposer,
|
|
@@ -51,7 +51,7 @@ export class JsonlSessionHistoryComposer implements SessionHistoryComposer {
|
|
|
51
51
|
return tools && typeof tools === "object" ? { ...tools } : {};
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
private readUserSessionMessageText(message:
|
|
54
|
+
private readUserSessionMessageText(message: SessionMessageRecordV1): string {
|
|
55
55
|
if (!message || typeof message !== "object" || message.role !== "user") {
|
|
56
56
|
return "";
|
|
57
57
|
}
|
|
@@ -70,7 +70,7 @@ export class JsonlSessionHistoryComposer implements SessionHistoryComposer {
|
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
private hasTrailingUserQuery(
|
|
73
|
-
messages:
|
|
73
|
+
messages: SessionRecordV1[],
|
|
74
74
|
query: string,
|
|
75
75
|
): boolean {
|
|
76
76
|
const target = String(query || "").trim();
|
|
@@ -78,17 +78,17 @@ export class JsonlSessionHistoryComposer implements SessionHistoryComposer {
|
|
|
78
78
|
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
79
79
|
const item = messages[index];
|
|
80
80
|
if (!item || typeof item !== "object") continue;
|
|
81
|
-
if (!
|
|
81
|
+
if (!is_session_message_record(item) || item.role !== "user") continue;
|
|
82
82
|
return this.readUserSessionMessageText(item) === target;
|
|
83
83
|
}
|
|
84
84
|
return false;
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
private sanitizeMessages(messages:
|
|
87
|
+
private sanitizeMessages(messages: SessionRecordV1[]): SessionRecordV1[] {
|
|
88
88
|
if (!Array.isArray(messages)) return [];
|
|
89
89
|
return messages
|
|
90
|
-
.filter((message) => !
|
|
91
|
-
.filter(
|
|
90
|
+
.filter((message) => !is_session_action_record(message))
|
|
91
|
+
.filter(is_session_message_record)
|
|
92
92
|
.map((message) => {
|
|
93
93
|
const parts = Array.isArray(message.parts)
|
|
94
94
|
? message.parts.filter((part) => part && typeof part === "object")
|
|
@@ -101,12 +101,12 @@ export class JsonlSessionHistoryComposer implements SessionHistoryComposer {
|
|
|
101
101
|
.filter((message) => Array.isArray(message.parts) && message.parts.length > 0);
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
-
async prepare(input: SessionHistoryPrepareInput): Promise<
|
|
104
|
+
async prepare(input: SessionHistoryPrepareInput): Promise<SessionRecordV1[]> {
|
|
105
105
|
const query = String(input.query || "").trim();
|
|
106
106
|
const tools = this.normalizeTools(input.tools);
|
|
107
107
|
void tools;
|
|
108
108
|
|
|
109
|
-
let baseMessages = this.sanitizeMessages(await this.store.
|
|
109
|
+
let baseMessages = this.sanitizeMessages(await this.store.list_records());
|
|
110
110
|
if ((!Array.isArray(baseMessages) || baseMessages.length === 0) && query) {
|
|
111
111
|
baseMessages = [
|
|
112
112
|
this.store.userText({
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import type { ModelMessage, Tool } from "ai";
|
|
11
|
-
import type {
|
|
11
|
+
import type { SessionRecordV1 } from "@/executor/types/SessionRecords.js";
|
|
12
12
|
import {
|
|
13
13
|
pickMergedUserMessages,
|
|
14
14
|
toModelMessages,
|
|
@@ -21,7 +21,7 @@ export class CoreEngineMessageState {
|
|
|
21
21
|
/**
|
|
22
22
|
* 当前运行时 session 语义消息。
|
|
23
23
|
*/
|
|
24
|
-
private sessionMessages:
|
|
24
|
+
private sessionMessages: SessionRecordV1[];
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
27
|
* 当前模型侧消息基线。
|
|
@@ -42,7 +42,7 @@ export class CoreEngineMessageState {
|
|
|
42
42
|
/**
|
|
43
43
|
* 当前运行时 session 语义消息。
|
|
44
44
|
*/
|
|
45
|
-
sessionMessages:
|
|
45
|
+
sessionMessages: SessionRecordV1[];
|
|
46
46
|
/**
|
|
47
47
|
* 当前模型侧消息基线。
|
|
48
48
|
*/
|
|
@@ -69,7 +69,7 @@ export class CoreEngineMessageState {
|
|
|
69
69
|
/**
|
|
70
70
|
* 初始 session 语义消息。
|
|
71
71
|
*/
|
|
72
|
-
messages:
|
|
72
|
+
messages: SessionRecordV1[];
|
|
73
73
|
/**
|
|
74
74
|
* 当前轮可用工具集合。
|
|
75
75
|
*/
|
|
@@ -105,7 +105,7 @@ export class CoreEngineMessageState {
|
|
|
105
105
|
* 把 step 间新增的 user 消息并入两份基线。
|
|
106
106
|
*/
|
|
107
107
|
async appendMergedUserMessages(
|
|
108
|
-
messages:
|
|
108
|
+
messages: SessionRecordV1[],
|
|
109
109
|
): Promise<ModelMessage[]> {
|
|
110
110
|
const mergedMessages = pickMergedUserMessages(messages);
|
|
111
111
|
if (mergedMessages.length === 0) return [];
|
|
@@ -115,14 +115,14 @@ export class CoreEngineMessageState {
|
|
|
115
115
|
/**
|
|
116
116
|
* 追加内部生成的 user nudge 消息。
|
|
117
117
|
*/
|
|
118
|
-
async appendUserTextMessage(message:
|
|
118
|
+
async appendUserTextMessage(message: SessionRecordV1): Promise<void> {
|
|
119
119
|
await this.appendSessionMessagesAsModelMessages([message]);
|
|
120
120
|
}
|
|
121
121
|
|
|
122
122
|
/**
|
|
123
123
|
* 追加 assistant UI 消息到 session 语义基线。
|
|
124
124
|
*/
|
|
125
|
-
appendRuntimeSessionMessage(message:
|
|
125
|
+
appendRuntimeSessionMessage(message: SessionRecordV1): void {
|
|
126
126
|
this.sessionMessages = [...this.sessionMessages, message];
|
|
127
127
|
}
|
|
128
128
|
|
|
@@ -135,7 +135,7 @@ export class CoreEngineMessageState {
|
|
|
135
135
|
}
|
|
136
136
|
|
|
137
137
|
private async appendSessionMessagesAsModelMessages(
|
|
138
|
-
messages:
|
|
138
|
+
messages: SessionRecordV1[],
|
|
139
139
|
): Promise<ModelMessage[]> {
|
|
140
140
|
this.sessionMessages = [...this.sessionMessages, ...messages];
|
|
141
141
|
const modelMessages = await toModelMessages(
|
|
@@ -42,9 +42,9 @@ import type {
|
|
|
42
42
|
SessionRunResult,
|
|
43
43
|
} from "@/executor/types/SessionRun.js";
|
|
44
44
|
import type {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
} from "@/executor/types/
|
|
45
|
+
SessionRecordV1,
|
|
46
|
+
SessionMessageRecordV1,
|
|
47
|
+
} from "@/executor/types/SessionRecords.js";
|
|
48
48
|
|
|
49
49
|
const TURN_STOPPED_MESSAGE = "Turn stopped";
|
|
50
50
|
|
|
@@ -64,9 +64,9 @@ function build_file_part_key(part: FileUIPart): string {
|
|
|
64
64
|
* 把 tool/plugin 运行期产生的 file parts 并入最终 assistant UIMessage。
|
|
65
65
|
*/
|
|
66
66
|
function mergePendingAssistantFileParts(
|
|
67
|
-
message:
|
|
67
|
+
message: SessionMessageRecordV1,
|
|
68
68
|
parts: FileUIPart[],
|
|
69
|
-
):
|
|
69
|
+
): SessionMessageRecordV1 {
|
|
70
70
|
if (!Array.isArray(parts) || parts.length === 0) return message;
|
|
71
71
|
const current_parts = Array.isArray(message.parts) ? message.parts : [];
|
|
72
72
|
const seen = new Set<string>();
|
|
@@ -154,7 +154,7 @@ export class CoreEngineRunner {
|
|
|
154
154
|
: [];
|
|
155
155
|
const tools = input.execute_input.tools;
|
|
156
156
|
let last_observed_stream_error: unknown = undefined;
|
|
157
|
-
let final_assistant_ui_message:
|
|
157
|
+
let final_assistant_ui_message: SessionMessageRecordV1 | null = null;
|
|
158
158
|
|
|
159
159
|
try {
|
|
160
160
|
const message_state = await CoreEngineMessageState.create({
|
|
@@ -163,7 +163,7 @@ export class CoreEngineRunner {
|
|
|
163
163
|
projectRoot: input.run_context.projectRoot,
|
|
164
164
|
});
|
|
165
165
|
|
|
166
|
-
const append_merged_user_messages = (messages:
|
|
166
|
+
const append_merged_user_messages = (messages: SessionRecordV1[]) =>
|
|
167
167
|
message_state.appendMergedUserMessages(messages);
|
|
168
168
|
|
|
169
169
|
const context_composer_on_step_finish =
|