@amical/aiagent-sdk 0.1.11 → 0.1.12
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/dist/{WebMemoryManager-DXxLUDBB.d.ts → WebMemoryManager-BZNjinHF.d.ts} +10 -3
- package/dist/{WebMemoryManager-Bk19j8i6.d.mts → WebMemoryManager-DpaY-f0l.d.mts} +10 -3
- package/dist/index.d.mts +13 -1
- package/dist/index.d.ts +13 -1
- package/dist/index.js +100 -17
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +100 -17
- package/dist/index.mjs.map +1 -1
- package/dist/runtime/nodeRuntime.d.mts +11 -2
- package/dist/runtime/nodeRuntime.d.ts +11 -2
- package/dist/runtime/nodeRuntime.js +230 -30
- package/dist/runtime/nodeRuntime.js.map +1 -1
- package/dist/runtime/nodeRuntime.mjs +230 -30
- package/dist/runtime/nodeRuntime.mjs.map +1 -1
- package/dist/runtime/webRuntime.d.mts +2 -1
- package/dist/runtime/webRuntime.d.ts +2 -1
- package/dist/runtime/webRuntime.js +230 -30
- package/dist/runtime/webRuntime.js.map +1 -1
- package/dist/runtime/webRuntime.mjs +230 -30
- package/dist/runtime/webRuntime.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { IApiHandler, ApiProviderInfo, AgentMessage, ApiStreamChunk, IPromptManager, IMcpManager, McpServerInfo, McpTool, McpToolCallResult, IAgentRuntime, ClineAgent } from '../index.mjs';
|
|
2
2
|
export { AgentDefaultTool, AgentOptions, AgentState, AssistantMessageContent, CustomToolDefinition, IMemoryManager, READ_ONLY_TOOLS, ReasoningStreamContent, TOOL_RESULT_BLOCK, TextStreamContent, ToolParamName, ToolUse, VERSION, collectCustomToolNames, defaultTools, getToolUseNames, isCustomToolGroup, parseAssistantMessageV2, renderCustomToolPrompt, renderCustomToolsPrompt, setDynamicToolUseNames, toolParamNames, toolUseNames } from '../index.mjs';
|
|
3
|
-
import { W as WebMemoryManager } from '../WebMemoryManager-
|
|
3
|
+
import { W as WebMemoryManager } from '../WebMemoryManager-DpaY-f0l.mjs';
|
|
4
4
|
|
|
5
5
|
interface WebApiHandlerConfig {
|
|
6
6
|
providerId?: string;
|
|
@@ -21,6 +21,7 @@ declare class WebApiHandler implements IApiHandler {
|
|
|
21
21
|
constructor(config: WebApiHandlerConfig);
|
|
22
22
|
getModelInfo(): ApiProviderInfo;
|
|
23
23
|
createMessage(systemPrompt: string, messages: AgentMessage[]): AsyncGenerator<ApiStreamChunk, void, unknown>;
|
|
24
|
+
clearConversationId(): void;
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
declare class WebPromptManager implements IPromptManager {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { IApiHandler, ApiProviderInfo, AgentMessage, ApiStreamChunk, IPromptManager, IMcpManager, McpServerInfo, McpTool, McpToolCallResult, IAgentRuntime, ClineAgent } from '../index.js';
|
|
2
2
|
export { AgentDefaultTool, AgentOptions, AgentState, AssistantMessageContent, CustomToolDefinition, IMemoryManager, READ_ONLY_TOOLS, ReasoningStreamContent, TOOL_RESULT_BLOCK, TextStreamContent, ToolParamName, ToolUse, VERSION, collectCustomToolNames, defaultTools, getToolUseNames, isCustomToolGroup, parseAssistantMessageV2, renderCustomToolPrompt, renderCustomToolsPrompt, setDynamicToolUseNames, toolParamNames, toolUseNames } from '../index.js';
|
|
3
|
-
import { W as WebMemoryManager } from '../WebMemoryManager-
|
|
3
|
+
import { W as WebMemoryManager } from '../WebMemoryManager-BZNjinHF.js';
|
|
4
4
|
|
|
5
5
|
interface WebApiHandlerConfig {
|
|
6
6
|
providerId?: string;
|
|
@@ -21,6 +21,7 @@ declare class WebApiHandler implements IApiHandler {
|
|
|
21
21
|
constructor(config: WebApiHandlerConfig);
|
|
22
22
|
getModelInfo(): ApiProviderInfo;
|
|
23
23
|
createMessage(systemPrompt: string, messages: AgentMessage[]): AsyncGenerator<ApiStreamChunk, void, unknown>;
|
|
24
|
+
clearConversationId(): void;
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
declare class WebPromptManager implements IPromptManager {
|
|
@@ -142,9 +142,11 @@ return (
|
|
|
142
142
|
},
|
|
143
143
|
{
|
|
144
144
|
name: "agent_read_file" /* FILE_READ */,
|
|
145
|
-
description: "Read the contents of a specific file.",
|
|
145
|
+
description: "Read the contents of a specific file. The returned content includes line numbers (e.g. '10|const x = 1;') so you can reference exact lines when editing.",
|
|
146
146
|
params: {
|
|
147
|
-
path: "(required) The absolute or relative file path to read."
|
|
147
|
+
path: "(required) The absolute or relative file path to read.",
|
|
148
|
+
start_line: "(optional) The 1-based line number to start reading from (inclusive). Defaults to 1.",
|
|
149
|
+
end_line: "(optional) The 1-based line number to stop reading at (inclusive). Defaults to the last line."
|
|
148
150
|
}
|
|
149
151
|
},
|
|
150
152
|
{
|
|
@@ -587,7 +589,17 @@ var TEXT_FILE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
|
587
589
|
"dockerfile",
|
|
588
590
|
"makefile",
|
|
589
591
|
"properties",
|
|
590
|
-
"lock"
|
|
592
|
+
"lock",
|
|
593
|
+
"node-version",
|
|
594
|
+
"nvmrc",
|
|
595
|
+
"editorconfig",
|
|
596
|
+
"prettierrc",
|
|
597
|
+
"eslintrc",
|
|
598
|
+
"babelrc",
|
|
599
|
+
"stylelintrc",
|
|
600
|
+
"huskyrc",
|
|
601
|
+
"commitlintrc",
|
|
602
|
+
"lintstagedrc"
|
|
591
603
|
]);
|
|
592
604
|
var AgentState = /* @__PURE__ */ ((AgentState2) => {
|
|
593
605
|
AgentState2["IDLE"] = "idle";
|
|
@@ -678,6 +690,13 @@ var ClineAgent = class {
|
|
|
678
690
|
}
|
|
679
691
|
this.skillDir = this.runtime.path.join(this.runtime.env.cwd(), ".agents/skills");
|
|
680
692
|
this.rulesDir = this.runtime.path.join(this.runtime.env.cwd(), ".agents/rules");
|
|
693
|
+
const originalOnCondense = this.memory.onCondense;
|
|
694
|
+
this.memory.onCondense = async () => {
|
|
695
|
+
this.api.clearConversationId();
|
|
696
|
+
if (originalOnCondense) {
|
|
697
|
+
await originalOnCondense();
|
|
698
|
+
}
|
|
699
|
+
};
|
|
681
700
|
}
|
|
682
701
|
setState(newState) {
|
|
683
702
|
this.state = newState;
|
|
@@ -735,16 +754,6 @@ var ClineAgent = class {
|
|
|
735
754
|
async getAgentRules() {
|
|
736
755
|
const cwd = this.runtime.env.cwd();
|
|
737
756
|
const rules = [];
|
|
738
|
-
const agentsMdPath = this.runtime.path.join(cwd, "Agents.md");
|
|
739
|
-
try {
|
|
740
|
-
if (await this.runtime.fs.fileExists(agentsMdPath)) {
|
|
741
|
-
const content = await this.runtime.fs.readFile(agentsMdPath);
|
|
742
|
-
if (content && content.trim()) {
|
|
743
|
-
rules.push(content.trim());
|
|
744
|
-
}
|
|
745
|
-
}
|
|
746
|
-
} catch (e) {
|
|
747
|
-
}
|
|
748
757
|
try {
|
|
749
758
|
if (await this.runtime.fs.fileExists(this.rulesDir)) {
|
|
750
759
|
const files = await this.runtime.fs.readDir(this.rulesDir);
|
|
@@ -770,6 +779,28 @@ ${content.trim()}\`\`\``);
|
|
|
770
779
|
}
|
|
771
780
|
} catch (e) {
|
|
772
781
|
}
|
|
782
|
+
try {
|
|
783
|
+
const getAgentsMdPath = async () => {
|
|
784
|
+
const agentsMdPathList = [
|
|
785
|
+
this.runtime.path.join(cwd, "AGENTS.md"),
|
|
786
|
+
this.runtime.path.join(cwd, "Agents.md"),
|
|
787
|
+
this.runtime.path.join(cwd, "agents.md")
|
|
788
|
+
];
|
|
789
|
+
for (const item of agentsMdPathList) {
|
|
790
|
+
if (await this.runtime.fs.fileExists(item)) {
|
|
791
|
+
return item;
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
};
|
|
795
|
+
const agentsMdPath = await getAgentsMdPath();
|
|
796
|
+
if (agentsMdPath) {
|
|
797
|
+
const content = await this.runtime.fs.readFile(agentsMdPath);
|
|
798
|
+
if (content && content.trim()) {
|
|
799
|
+
rules.push(content.trim());
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
} catch (e) {
|
|
803
|
+
}
|
|
773
804
|
return rules.join("\n---\n");
|
|
774
805
|
}
|
|
775
806
|
async getSkills() {
|
|
@@ -907,7 +938,8 @@ ${finalPrompt}` : finalPrompt;
|
|
|
907
938
|
if (path2) {
|
|
908
939
|
try {
|
|
909
940
|
const content = await this.runtime.fs.readFile(path2);
|
|
910
|
-
|
|
941
|
+
const result = this.formatFileContentWithLineNumbers(content, tool.params.start_line, tool.params.end_line);
|
|
942
|
+
toolResults.push({ tool, result });
|
|
911
943
|
} catch (error) {
|
|
912
944
|
toolResults.push({ tool, result: `Error: ${error.message}` });
|
|
913
945
|
}
|
|
@@ -920,6 +952,8 @@ ${finalPrompt}` : finalPrompt;
|
|
|
920
952
|
const result = await this.runtime.terminal.execCommand(cmd);
|
|
921
953
|
toolResults.push({ tool, result: `STDOUT: ${result.stdout}
|
|
922
954
|
STDERR: ${result.stderr}` });
|
|
955
|
+
} else {
|
|
956
|
+
toolResults.push({ tool, result: "Error: No command provided." });
|
|
923
957
|
}
|
|
924
958
|
} else if (tool.name === "agent_write_to_file" /* FILE_NEW */) {
|
|
925
959
|
const path2 = tool.params.path;
|
|
@@ -931,12 +965,18 @@ STDERR: ${result.stderr}` });
|
|
|
931
965
|
} catch (error) {
|
|
932
966
|
toolResults.push({ tool, result: `Error: ${error.message}` });
|
|
933
967
|
}
|
|
968
|
+
} else {
|
|
969
|
+
toolResults.push({ tool, result: "Error: Missing path or content." });
|
|
934
970
|
}
|
|
935
971
|
} else if (tool.name === "agent_list_files" /* LIST_FILES */) {
|
|
936
972
|
const path2 = tool.params.path || this.runtime.env.cwd();
|
|
973
|
+
const recursive = tool.params.recursive === "true";
|
|
937
974
|
try {
|
|
938
|
-
const files = await this.runtime.fs.readDir(path2);
|
|
939
|
-
toolResults.push({
|
|
975
|
+
const files = await this.runtime.fs.readDir(path2, { recursive });
|
|
976
|
+
toolResults.push({
|
|
977
|
+
tool,
|
|
978
|
+
result: files.map((f) => `${f.isDirectory() ? "[DIR] " : " "}${f.name}${f.isDirectory() ? "/" : ""}`).join("\n")
|
|
979
|
+
});
|
|
940
980
|
} catch (e) {
|
|
941
981
|
toolResults.push({ tool, result: `Error: ${e.message}` });
|
|
942
982
|
}
|
|
@@ -1076,10 +1116,15 @@ STDERR: ${result.stderr}` });
|
|
|
1076
1116
|
try {
|
|
1077
1117
|
const res = await fetch(url);
|
|
1078
1118
|
const text = await res.text();
|
|
1079
|
-
|
|
1119
|
+
const MAX_LEN = 8e3;
|
|
1120
|
+
const truncated = text.length > MAX_LEN ? `${text.substring(0, MAX_LEN)}
|
|
1121
|
+
...[truncated ${text.length - MAX_LEN} chars]` : text;
|
|
1122
|
+
toolResults.push({ tool, result: truncated });
|
|
1080
1123
|
} catch (e) {
|
|
1081
1124
|
toolResults.push({ tool, result: `Error: ${e.message}` });
|
|
1082
1125
|
}
|
|
1126
|
+
} else {
|
|
1127
|
+
toolResults.push({ tool, result: "Error: No url provided." });
|
|
1083
1128
|
}
|
|
1084
1129
|
} else if (tool.name === "agent_focus_chain" /* TODO */) {
|
|
1085
1130
|
toolResults.push({ tool, result: `Focus chain updated successfully.` });
|
|
@@ -1167,6 +1212,44 @@ ${this.promptManager.getUsedToolResultInstructions()}`;
|
|
|
1167
1212
|
}
|
|
1168
1213
|
return this.getPrompt();
|
|
1169
1214
|
}
|
|
1215
|
+
/**
|
|
1216
|
+
* 将文件内容格式化为带行号文本(模拟编辑器行号显示),
|
|
1217
|
+
* 支持通过 start_line / end_line 截取读取范围。
|
|
1218
|
+
*/
|
|
1219
|
+
formatFileContentWithLineNumbers(content, startLineParam, endLineParam) {
|
|
1220
|
+
const lines = content.split(/\r?\n/);
|
|
1221
|
+
const normalized = lines.length > 0 && lines[lines.length - 1] === "" ? lines.slice(0, -1) : lines;
|
|
1222
|
+
const total = normalized.length;
|
|
1223
|
+
if (total === 0) {
|
|
1224
|
+
return "1|(empty file)";
|
|
1225
|
+
}
|
|
1226
|
+
const parseLine = (val, fallback) => {
|
|
1227
|
+
if (val === void 0 || val === null || val.trim() === "") {
|
|
1228
|
+
return fallback;
|
|
1229
|
+
}
|
|
1230
|
+
const num = Number.parseInt(val, 10);
|
|
1231
|
+
if (!Number.isFinite(num) || num <= 0) {
|
|
1232
|
+
return fallback;
|
|
1233
|
+
}
|
|
1234
|
+
return num;
|
|
1235
|
+
};
|
|
1236
|
+
const start = parseLine(startLineParam, 1);
|
|
1237
|
+
const end = parseLine(endLineParam, total);
|
|
1238
|
+
if (start > end) {
|
|
1239
|
+
return `Error: start_line (${start}) cannot be greater than end_line (${end}).`;
|
|
1240
|
+
}
|
|
1241
|
+
if (start > total) {
|
|
1242
|
+
return `Error: start_line (${start}) is out of range. The file has ${total} lines.`;
|
|
1243
|
+
}
|
|
1244
|
+
const from = Math.max(1, start);
|
|
1245
|
+
const to = Math.min(total, end);
|
|
1246
|
+
const width = String(total).length;
|
|
1247
|
+
const selected = normalized.slice(from - 1, to);
|
|
1248
|
+
const numbered = selected.map((line, idx) => `${String(from + idx).padStart(width)}|${line}`).join("\n");
|
|
1249
|
+
const header = from === 1 && to === total ? `1-${total}/${total}` : `${from}-${to}/${total}`;
|
|
1250
|
+
return `${header}
|
|
1251
|
+
${numbered}`;
|
|
1252
|
+
}
|
|
1170
1253
|
/**
|
|
1171
1254
|
* 简单的 Diff 解析与替换辅助方法
|
|
1172
1255
|
*/
|
|
@@ -1416,6 +1499,9 @@ var WebApiHandler = class {
|
|
|
1416
1499
|
};
|
|
1417
1500
|
}
|
|
1418
1501
|
}
|
|
1502
|
+
clearConversationId() {
|
|
1503
|
+
this.conversationId = void 0;
|
|
1504
|
+
}
|
|
1419
1505
|
};
|
|
1420
1506
|
|
|
1421
1507
|
// src/prompt/WebPromptManager.ts
|
|
@@ -1721,16 +1807,127 @@ ${this?.getEnvironmentInfoPrompt?.(context)}`;
|
|
|
1721
1807
|
}
|
|
1722
1808
|
};
|
|
1723
1809
|
|
|
1810
|
+
// src/memory/condense.ts
|
|
1811
|
+
var TOOL_RESULT_CONTENT_REGEX = /<tool_call_result[^>]*>[\s\S]*?<\/tool_call_result>/;
|
|
1812
|
+
var EXPIRED_MARKER_TEXT = "[The result has expired and has been removed from the context]";
|
|
1813
|
+
var ATTEMPT_TOOL_NAME = "agent_attempt_completion" /* ATTEMPT */;
|
|
1814
|
+
function getContentString(content) {
|
|
1815
|
+
return typeof content === "string" ? content : "";
|
|
1816
|
+
}
|
|
1817
|
+
function isToolResultMessage(content) {
|
|
1818
|
+
if (typeof content !== "string") {
|
|
1819
|
+
return false;
|
|
1820
|
+
}
|
|
1821
|
+
return TOOL_RESULT_CONTENT_REGEX.test(content);
|
|
1822
|
+
}
|
|
1823
|
+
function isAttemptCallMessage(message) {
|
|
1824
|
+
if (message.role !== "assistant") {
|
|
1825
|
+
return false;
|
|
1826
|
+
}
|
|
1827
|
+
const content = getContentString(message.content);
|
|
1828
|
+
return new RegExp(`<${ATTEMPT_TOOL_NAME}[\\s>]`).test(content) || new RegExp(`<name>\\s*${ATTEMPT_TOOL_NAME}\\s*</name>`).test(content);
|
|
1829
|
+
}
|
|
1830
|
+
function markExpiredToolResult(content) {
|
|
1831
|
+
if (typeof content !== "string") {
|
|
1832
|
+
return content;
|
|
1833
|
+
}
|
|
1834
|
+
return content.replace(
|
|
1835
|
+
/(<tool_call_result[^>]*tool_name="([^"]*)"[^>]*>)[\s\S]*?(<\/tool_call_result>)/g,
|
|
1836
|
+
(_match, openTag, _toolName, closeTag) => {
|
|
1837
|
+
return `${openTag}
|
|
1838
|
+
${EXPIRED_MARKER_TEXT}
|
|
1839
|
+
${closeTag}`;
|
|
1840
|
+
}
|
|
1841
|
+
);
|
|
1842
|
+
}
|
|
1843
|
+
function splitConversations(messages) {
|
|
1844
|
+
const conversations = [];
|
|
1845
|
+
let current = [];
|
|
1846
|
+
for (const message of messages) {
|
|
1847
|
+
current.push(message);
|
|
1848
|
+
if (isAttemptCallMessage(message)) {
|
|
1849
|
+
conversations.push(current);
|
|
1850
|
+
current = [];
|
|
1851
|
+
}
|
|
1852
|
+
}
|
|
1853
|
+
if (current.length > 0) {
|
|
1854
|
+
conversations.push(current);
|
|
1855
|
+
}
|
|
1856
|
+
return conversations;
|
|
1857
|
+
}
|
|
1858
|
+
function isCompleteConversation(conversation) {
|
|
1859
|
+
if (conversation.length === 0) {
|
|
1860
|
+
return false;
|
|
1861
|
+
}
|
|
1862
|
+
return isAttemptCallMessage(conversation[conversation.length - 1]);
|
|
1863
|
+
}
|
|
1864
|
+
function compressCompleteConversation(conversation) {
|
|
1865
|
+
if (conversation.length <= 2) {
|
|
1866
|
+
return conversation;
|
|
1867
|
+
}
|
|
1868
|
+
const head = conversation[0];
|
|
1869
|
+
const tail = conversation[conversation.length - 1];
|
|
1870
|
+
const mergedMarker = {
|
|
1871
|
+
role: "user",
|
|
1872
|
+
content: "[History Condensed] The intermediate tool calls and tool call results of this conversation have been merged. Please refer to the `agent_attempt_completion` summary below for the final conclusion."
|
|
1873
|
+
};
|
|
1874
|
+
return [head, mergedMarker, tail];
|
|
1875
|
+
}
|
|
1876
|
+
function markExpiredFirstHalf(messages) {
|
|
1877
|
+
const half = Math.floor(messages.length / 2);
|
|
1878
|
+
return messages.map((message, index) => {
|
|
1879
|
+
if (index < half && isToolResultMessage(message.content)) {
|
|
1880
|
+
return { ...message, content: markExpiredToolResult(message.content) };
|
|
1881
|
+
}
|
|
1882
|
+
return message;
|
|
1883
|
+
});
|
|
1884
|
+
}
|
|
1885
|
+
function condenseMessages(messages, maxMessages) {
|
|
1886
|
+
if (messages.length <= maxMessages) {
|
|
1887
|
+
return messages;
|
|
1888
|
+
}
|
|
1889
|
+
const systemMessages = messages.filter((message) => message.role === "system");
|
|
1890
|
+
const restMessages = messages.filter((message) => message.role !== "system");
|
|
1891
|
+
const conversations = splitConversations(restMessages);
|
|
1892
|
+
const completeIndices = [];
|
|
1893
|
+
for (let i = 0; i < conversations.length; i++) {
|
|
1894
|
+
if (isCompleteConversation(conversations[i])) {
|
|
1895
|
+
completeIndices.push(i);
|
|
1896
|
+
}
|
|
1897
|
+
}
|
|
1898
|
+
const currentLength = () => systemMessages.length + conversations.reduce((acc, c) => acc + c.length, 0);
|
|
1899
|
+
if (completeIndices.length >= 2) {
|
|
1900
|
+
const lastCompleteIndex = completeIndices[completeIndices.length - 1];
|
|
1901
|
+
for (const idx of completeIndices) {
|
|
1902
|
+
if (idx === lastCompleteIndex) {
|
|
1903
|
+
break;
|
|
1904
|
+
}
|
|
1905
|
+
conversations[idx] = compressCompleteConversation(conversations[idx]);
|
|
1906
|
+
if (currentLength() <= maxMessages) {
|
|
1907
|
+
break;
|
|
1908
|
+
}
|
|
1909
|
+
}
|
|
1910
|
+
}
|
|
1911
|
+
let condensed = conversations.flat();
|
|
1912
|
+
condensed = markExpiredFirstHalf(condensed);
|
|
1913
|
+
if (systemMessages.length + condensed.length > maxMessages) {
|
|
1914
|
+
const nonSystemBudget = Math.max(0, maxMessages - systemMessages.length);
|
|
1915
|
+
condensed = condensed.slice(-nonSystemBudget);
|
|
1916
|
+
}
|
|
1917
|
+
return [...systemMessages, ...condensed];
|
|
1918
|
+
}
|
|
1919
|
+
|
|
1724
1920
|
// src/memory/WebMemoryManager.ts
|
|
1725
1921
|
var WebMemoryManager = class {
|
|
1726
1922
|
storageKey;
|
|
1727
1923
|
maxMessages;
|
|
1728
1924
|
inMemoryFallback = [];
|
|
1925
|
+
onCondense;
|
|
1729
1926
|
/**
|
|
1730
1927
|
* @param storageKey SessionStorage 中的键名
|
|
1731
|
-
* @param maxMessages 保留的最大消息数量,用于简单的历史截断(默认
|
|
1928
|
+
* @param maxMessages 保留的最大消息数量,用于简单的历史截断(默认 200)
|
|
1732
1929
|
*/
|
|
1733
|
-
constructor(storageKey = "cline_agent_memory", maxMessages =
|
|
1930
|
+
constructor(storageKey = "cline_agent_memory", maxMessages = 200) {
|
|
1734
1931
|
this.storageKey = storageKey;
|
|
1735
1932
|
this.maxMessages = maxMessages;
|
|
1736
1933
|
}
|
|
@@ -1771,19 +1968,22 @@ var WebMemoryManager = class {
|
|
|
1771
1968
|
this.writeMessages(messages);
|
|
1772
1969
|
await this.condenseHistory();
|
|
1773
1970
|
}
|
|
1971
|
+
/**
|
|
1972
|
+
* 压缩历史:
|
|
1973
|
+
* - system 消息保持不变
|
|
1974
|
+
* - 以 agent_attempt_completion 为边界切分完整对话,仅合并“后面还有其他完整对话”的旧完整对话
|
|
1975
|
+
* - 其余需要压缩的场景下,对前半段工具调用结果标记为“结果已过期”
|
|
1976
|
+
* - 同时触发 onCondense 回调(宿主可据此清空 dify conversationId 新开窗口)
|
|
1977
|
+
*/
|
|
1774
1978
|
async condenseHistory() {
|
|
1775
1979
|
const messages = this.readMessages();
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
} else {
|
|
1784
|
-
condensed = messages.slice(sliceCount);
|
|
1785
|
-
}
|
|
1786
|
-
this.writeMessages(condensed);
|
|
1980
|
+
const condensed = condenseMessages(messages, this.maxMessages);
|
|
1981
|
+
if (condensed === messages) {
|
|
1982
|
+
return Promise.resolve();
|
|
1983
|
+
}
|
|
1984
|
+
this.writeMessages(condensed);
|
|
1985
|
+
if (this.onCondense) {
|
|
1986
|
+
await this.onCondense();
|
|
1787
1987
|
}
|
|
1788
1988
|
return Promise.resolve();
|
|
1789
1989
|
}
|