@downcity/agent 1.1.199 → 1.1.202
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 +7 -7
- package/bin/executor/Executor.d.ts.map +1 -1
- package/bin/executor/Executor.js +41 -33
- 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 +5 -5
- package/bin/executor/composer/compaction/SessionCompactionComposer.d.ts.map +1 -1
- package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionComposer.js +1 -1
- package/bin/executor/composer/compaction/jsonl/JsonlSessionCompactionComposer.js.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 +73 -40
- 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 -4
- 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 +11 -7
- package/bin/executor/services/ExecutorInflightService.js.map +1 -1
- package/bin/executor/store/history/SessionHistoryStore.d.ts +30 -27
- 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 +21 -20
- package/bin/executor/store/history/jsonl/JsonlSessionHistoryStore.d.ts.map +1 -1
- package/bin/executor/store/history/jsonl/JsonlSessionHistoryStore.js +114 -72
- 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/SessionRecords.d.ts +162 -0
- 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 +2 -2
- package/bin/index.d.ts.map +1 -1
- package/bin/index.js.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 +5 -0
- 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 +37 -34
- 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 +11 -12
- package/bin/session/services/SessionStateService.d.ts.map +1 -1
- package/bin/session/services/SessionStateService.js +43 -69
- package/bin/session/services/SessionStateService.js.map +1 -1
- package/bin/session/services/SessionTurnService.js +3 -3
- package/bin/session/services/SessionTurnService.js.map +1 -1
- package/bin/session/services/SessionViewService.d.ts +4 -4
- package/bin/session/services/SessionViewService.d.ts.map +1 -1
- package/bin/session/services/SessionViewService.js +26 -36
- 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 +22 -22
- package/bin/types/agent/SessionTypes.d.ts.map +1 -1
- package/bin/types/executor/SessionRunContext.d.ts +7 -7
- 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 +26 -0
- package/bin/types/sdk/AgentSessionAction.d.ts.map +1 -0
- package/bin/types/sdk/AgentSessionAction.js +10 -0
- package/bin/types/sdk/AgentSessionAction.js.map +1 -0
- package/bin/types/sdk/AgentSessionEvent.d.ts +2 -2
- package/bin/types/sdk/AgentSessionEvent.d.ts.map +1 -1
- 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 +199 -0
- 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 +51 -41
- package/src/executor/SessionRunScope.ts +1 -1
- package/src/executor/composer/compaction/SessionCompactionComposer.ts +5 -5
- package/src/executor/composer/compaction/jsonl/JsonlSessionCompactionComposer.ts +1 -1
- package/src/executor/composer/compaction/jsonl/JsonlSessionCompactionExecutor.ts +91 -52
- 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 -10
- 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 +13 -9
- package/src/executor/store/history/SessionHistoryStore.ts +32 -28
- package/src/executor/store/history/jsonl/JsonlSessionHistoryStore.ts +146 -95
- package/src/executor/tools/plugin/PluginToolSchemas.ts +24 -10
- package/src/executor/types/SessionRecords.ts +217 -0
- package/src/executor/types/SessionRun.ts +5 -5
- package/src/index.ts +9 -10
- package/src/rpc/Client.ts +9 -9
- package/src/session/Session.ts +10 -10
- package/src/session/SessionTitle.ts +7 -4
- package/src/session/browse/Browse.ts +66 -58
- package/src/session/index.ts +1 -1
- package/src/session/runtime/SessionPromptRuntime.ts +6 -6
- package/src/session/services/SessionStateService.ts +61 -86
- package/src/session/services/SessionTurnService.ts +7 -7
- package/src/session/services/SessionViewService.ts +35 -45
- 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 +22 -22
- package/src/types/executor/SessionRunContext.ts +12 -12
- package/src/types/rpc/RpcProtocol.ts +6 -6
- package/src/types/runtime/agent/AgentContext.ts +8 -8
- package/src/types/sdk/AgentSessionAction.ts +35 -0
- package/src/types/sdk/AgentSessionEvent.ts +2 -2
- 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 +0 -118
- package/bin/executor/types/SessionMessages.d.ts.map +0 -1
- package/bin/executor/types/SessionMessages.js +0 -28
- package/bin/executor/types/SessionMessages.js.map +0 -1
- package/bin/types/sdk/AgentSessionOperation.d.ts +0 -99
- package/bin/types/sdk/AgentSessionOperation.d.ts.map +0 -1
- package/bin/types/sdk/AgentSessionOperation.js +0 -10
- package/bin/types/sdk/AgentSessionOperation.js.map +0 -1
- package/scripts/session-operation-message.test.mjs +0 -197
- package/src/executor/types/SessionMessages.ts +0 -148
- package/src/types/sdk/AgentSessionOperation.ts +0 -125
|
@@ -18,12 +18,22 @@ import {
|
|
|
18
18
|
import { generateId } from "@/utils/Id.js";
|
|
19
19
|
import { getLogger } from "@/utils/logger/Logger.js";
|
|
20
20
|
import type {
|
|
21
|
-
|
|
21
|
+
SessionActionRecordV1,
|
|
22
|
+
SessionRecordV1,
|
|
22
23
|
SessionMetadataV1,
|
|
23
|
-
|
|
24
|
-
|
|
24
|
+
SessionMessageRecordV1,
|
|
25
|
+
} from "@/executor/types/SessionRecords.js";
|
|
26
|
+
import {
|
|
27
|
+
is_session_message_record,
|
|
28
|
+
} from "@/executor/types/SessionRecords.js";
|
|
25
29
|
import type { SessionHistoryMetaV1 } from "@/executor/types/SessionHistoryMeta.js";
|
|
26
|
-
import
|
|
30
|
+
import {
|
|
31
|
+
append_session_compaction_file_operations,
|
|
32
|
+
build_initial_session_compaction_prompt,
|
|
33
|
+
build_update_session_compaction_prompt,
|
|
34
|
+
SESSION_COMPACTION_SYSTEM_PROMPT,
|
|
35
|
+
} from "@executor/composer/compaction/jsonl/JsonlSessionCompactionPrompts.js";
|
|
36
|
+
import { format_session_compaction_file_operations } from "@executor/composer/compaction/jsonl/JsonlSessionCompactionFileOperations.js";
|
|
27
37
|
|
|
28
38
|
export type SessionCompactParams = {
|
|
29
39
|
model: LanguageModel;
|
|
@@ -32,19 +42,19 @@ export type SessionCompactParams = {
|
|
|
32
42
|
maxInputTokensApprox: number;
|
|
33
43
|
archiveOnCompact: boolean;
|
|
34
44
|
compactRatio: number;
|
|
35
|
-
|
|
45
|
+
onAction?: (action: SessionActionRecordV1) => Promise<void>;
|
|
36
46
|
};
|
|
37
47
|
|
|
38
48
|
type SessionCompactDeps = {
|
|
39
49
|
rootPath: string;
|
|
40
50
|
sessionId: string;
|
|
41
51
|
withWriteLock: <T>(fn: () => Promise<T>) => Promise<T>;
|
|
42
|
-
loadAll: () => Promise<
|
|
52
|
+
loadAll: () => Promise<SessionRecordV1[]>;
|
|
43
53
|
createSummaryMessage: (params: {
|
|
44
54
|
text: string;
|
|
45
55
|
archiveId?: string;
|
|
46
56
|
sourceRange?: SessionMetadataV1["sourceRange"];
|
|
47
|
-
}) =>
|
|
57
|
+
}) => SessionRecordV1;
|
|
48
58
|
getArchiveDirPath: () => string;
|
|
49
59
|
getMessagesFilePath: () => string;
|
|
50
60
|
readMetaUnsafe: () => Promise<SessionHistoryMetaV1>;
|
|
@@ -63,17 +73,22 @@ export async function compactSessionMessagesIfNeeded(
|
|
|
63
73
|
params: SessionCompactParams,
|
|
64
74
|
): Promise<{ compacted: boolean; reason?: string }> {
|
|
65
75
|
const logger = getLogger(deps.rootPath, "info");
|
|
66
|
-
const
|
|
67
|
-
let
|
|
76
|
+
const action_id = `compacting:${deps.sessionId}:${Date.now()}:${generateId()}`;
|
|
77
|
+
let action_started = false;
|
|
68
78
|
|
|
69
|
-
const
|
|
70
|
-
|
|
79
|
+
const publish_action = async (
|
|
80
|
+
action: Omit<SessionActionRecordV1, "type" | "id" | "metadata">,
|
|
71
81
|
): Promise<void> => {
|
|
72
|
-
if (typeof params.
|
|
73
|
-
await params.
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
...
|
|
82
|
+
if (typeof params.onAction !== "function") return;
|
|
83
|
+
await params.onAction({
|
|
84
|
+
type: "action",
|
|
85
|
+
id: action_id,
|
|
86
|
+
...action,
|
|
87
|
+
metadata: {
|
|
88
|
+
v: 1,
|
|
89
|
+
ts: Date.now(),
|
|
90
|
+
sessionId: deps.sessionId,
|
|
91
|
+
},
|
|
77
92
|
});
|
|
78
93
|
};
|
|
79
94
|
|
|
@@ -81,12 +96,10 @@ export async function compactSessionMessagesIfNeeded(
|
|
|
81
96
|
// phase 1:snapshot(短锁)
|
|
82
97
|
// - 仅负责拿一致性快照,不做耗时的模型调用。
|
|
83
98
|
// - 目的是把锁持有时间降到最低。
|
|
84
|
-
let snapshot:
|
|
99
|
+
let snapshot: SessionMessageRecordV1[] = [];
|
|
85
100
|
let snapshotTailId = "";
|
|
86
101
|
await deps.withWriteLock(async () => {
|
|
87
|
-
snapshot = (await deps.loadAll()).filter(
|
|
88
|
-
(message) => !isSessionOperationMessage(message),
|
|
89
|
-
);
|
|
102
|
+
snapshot = (await deps.loadAll()).filter(is_session_message_record);
|
|
90
103
|
snapshotTailId =
|
|
91
104
|
snapshot.length > 0
|
|
92
105
|
? String(snapshot[snapshot.length - 1].id || "")
|
|
@@ -118,19 +131,29 @@ export async function compactSessionMessagesIfNeeded(
|
|
|
118
131
|
const older = snapshot.slice(0, compactCount);
|
|
119
132
|
if (older.length === 0) return { compacted: false, reason: "nothing_to_compact" };
|
|
120
133
|
|
|
121
|
-
|
|
122
|
-
await
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
progress: 0,
|
|
134
|
+
action_started = true;
|
|
135
|
+
await publish_action({
|
|
136
|
+
title: "Compacting session records",
|
|
137
|
+
state: "running",
|
|
126
138
|
});
|
|
127
139
|
|
|
128
|
-
const
|
|
140
|
+
const previous_summary = extract_existing_compaction_summary(older[0]);
|
|
141
|
+
const conversation_messages = previous_summary ? older.slice(1) : older;
|
|
142
|
+
const olderTextAll = extractPlainTextFromMessages(conversation_messages);
|
|
129
143
|
const maxOlderChars = 24_000;
|
|
130
144
|
const olderText =
|
|
131
145
|
olderTextAll.length > maxOlderChars
|
|
132
146
|
? "(注意:更早历史过长,已截断保留末尾)\n" + olderTextAll.slice(-maxOlderChars)
|
|
133
147
|
: olderTextAll;
|
|
148
|
+
const prompt = previous_summary
|
|
149
|
+
? build_update_session_compaction_prompt({
|
|
150
|
+
previous_summary,
|
|
151
|
+
new_conversation_text: olderText || "(none)",
|
|
152
|
+
})
|
|
153
|
+
: build_initial_session_compaction_prompt({
|
|
154
|
+
conversation_text: olderText || "(none)",
|
|
155
|
+
});
|
|
156
|
+
const file_operations_xml = format_session_compaction_file_operations(older);
|
|
134
157
|
|
|
135
158
|
// phase 1.5:生成摘要(不持锁)
|
|
136
159
|
// - 这一步最耗时,必须在锁外执行,避免阻塞 append。
|
|
@@ -141,18 +164,15 @@ export async function compactSessionMessagesIfNeeded(
|
|
|
141
164
|
system: [
|
|
142
165
|
{
|
|
143
166
|
role: "system",
|
|
144
|
-
content:
|
|
145
|
-
"你是对话压缩助手。请把更早的对话历史压缩成“可持续复用”的工作摘要。\n" +
|
|
146
|
-
"要求:\n" +
|
|
147
|
-
"- 输出中文\n" +
|
|
148
|
-
"- 不要复述无关细节,不要输出工具原始日志\n" +
|
|
149
|
-
"- 必须包含:已确认事实/用户偏好约束/已做决策/未完成事项\n" +
|
|
150
|
-
"- 使用 Markdown 列表,控制在 300~800 字",
|
|
167
|
+
content: SESSION_COMPACTION_SYSTEM_PROMPT,
|
|
151
168
|
},
|
|
152
169
|
],
|
|
153
|
-
prompt
|
|
170
|
+
prompt,
|
|
171
|
+
});
|
|
172
|
+
summary = append_session_compaction_file_operations({
|
|
173
|
+
summary: String(r.text || "").trim(),
|
|
174
|
+
file_operations_xml,
|
|
154
175
|
});
|
|
155
|
-
summary = String(r.text || "").trim();
|
|
156
176
|
} catch (e) {
|
|
157
177
|
await logger.log(
|
|
158
178
|
"warn",
|
|
@@ -162,12 +182,14 @@ export async function compactSessionMessagesIfNeeded(
|
|
|
162
182
|
error: String(e),
|
|
163
183
|
},
|
|
164
184
|
);
|
|
165
|
-
summary =
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
185
|
+
summary = append_session_compaction_file_operations({
|
|
186
|
+
summary: "(系统自动压缩:摘要生成失败,已丢弃更早历史,仅保留最近对话。)",
|
|
187
|
+
file_operations_xml,
|
|
188
|
+
});
|
|
189
|
+
await publish_action({
|
|
190
|
+
title: "Compacting session records",
|
|
191
|
+
description: "Summary generation failed; using a fallback summary.",
|
|
192
|
+
state: "running",
|
|
171
193
|
});
|
|
172
194
|
}
|
|
173
195
|
|
|
@@ -191,7 +213,7 @@ export async function compactSessionMessagesIfNeeded(
|
|
|
191
213
|
void snapshotTailId;
|
|
192
214
|
|
|
193
215
|
const current_model_messages = current.filter(
|
|
194
|
-
|
|
216
|
+
is_session_message_record,
|
|
195
217
|
);
|
|
196
218
|
const currentCompactCount = resolveCompactCount(
|
|
197
219
|
current_model_messages.length,
|
|
@@ -242,15 +264,11 @@ export async function compactSessionMessagesIfNeeded(
|
|
|
242
264
|
});
|
|
243
265
|
});
|
|
244
266
|
|
|
245
|
-
if (
|
|
246
|
-
await
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
result: {
|
|
251
|
-
archiveId,
|
|
252
|
-
compactedCount: older.length,
|
|
253
|
-
},
|
|
267
|
+
if (action_started) {
|
|
268
|
+
await publish_action({
|
|
269
|
+
title: "Session records compacted",
|
|
270
|
+
description: `Compacted ${String(older.length)} earlier messages into ${archiveId}.`,
|
|
271
|
+
state: "completed",
|
|
254
272
|
});
|
|
255
273
|
}
|
|
256
274
|
|
|
@@ -302,7 +320,7 @@ function estimateTokensApproxFromText(text: string): number {
|
|
|
302
320
|
* - 统一把 user / assistant 内容线性化,作为 compact 摘要输入。
|
|
303
321
|
* - tool 原始结构不会原样输出,避免把噪声日志喂给摘要模型。
|
|
304
322
|
*/
|
|
305
|
-
function extractPlainTextFromMessages(messages:
|
|
323
|
+
function extractPlainTextFromMessages(messages: SessionMessageRecordV1[]): string {
|
|
306
324
|
const lines: string[] = [];
|
|
307
325
|
for (const m of messages) {
|
|
308
326
|
if (!m || typeof m !== "object") continue;
|
|
@@ -315,3 +333,24 @@ function extractPlainTextFromMessages(messages: SessionMessageV1[]): string {
|
|
|
315
333
|
}
|
|
316
334
|
return lines.join("\n");
|
|
317
335
|
}
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* 从已有 compact summary 消息中提取旧摘要。
|
|
339
|
+
*
|
|
340
|
+
* 关键点(中文)
|
|
341
|
+
* - 旧摘要通常位于 messages.jsonl 第一条,后续 compact 应基于它迭代更新。
|
|
342
|
+
* - 只识别 compact 生成的 summary,避免误把普通 assistant 文本当作旧摘要。
|
|
343
|
+
*/
|
|
344
|
+
function extract_existing_compaction_summary(
|
|
345
|
+
message: SessionMessageRecordV1 | undefined,
|
|
346
|
+
): string {
|
|
347
|
+
if (!message || typeof message !== "object") return "";
|
|
348
|
+
const metadata = message.metadata;
|
|
349
|
+
if (metadata?.source !== "compact" || metadata.kind !== "summary") return "";
|
|
350
|
+
const parts = Array.isArray(message.parts) ? message.parts : [];
|
|
351
|
+
return parts
|
|
352
|
+
.filter(isTextUIPart)
|
|
353
|
+
.map((part) => String(part.text ?? ""))
|
|
354
|
+
.join("\n")
|
|
355
|
+
.trim();
|
|
356
|
+
}
|
|
@@ -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
|
}
|