@next-open-ai/openclawx 0.8.17 → 0.8.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -8
- package/apps/desktop/renderer/dist/assets/index-B0_RWD2F.css +10 -0
- package/apps/desktop/renderer/dist/assets/index-B8jRTtME.js +89 -0
- package/apps/desktop/renderer/dist/index.html +2 -2
- package/dist/core/agent/agent-manager.d.ts +10 -4
- package/dist/core/agent/agent-manager.js +49 -22
- package/dist/core/agent/proxy/adapters/coze-adapter.js +7 -0
- package/dist/core/agent/proxy/adapters/local-adapter.js +4 -11
- package/dist/core/agent/proxy/adapters/openclawx-adapter.js +7 -0
- package/dist/core/agent/proxy/adapters/opencode-adapter.d.ts +11 -0
- package/dist/core/agent/proxy/adapters/opencode-adapter.js +716 -0
- package/dist/core/agent/proxy/adapters/opencode-free-models.d.ts +20 -0
- package/dist/core/agent/proxy/adapters/opencode-free-models.js +14 -0
- package/dist/core/agent/proxy/adapters/opencode-local-runner.d.ts +5 -0
- package/dist/core/agent/proxy/adapters/opencode-local-runner.js +86 -0
- package/dist/core/agent/proxy/index.js +3 -1
- package/dist/core/agent/proxy/run-for-channel.js +1 -1
- package/dist/core/agent/proxy/types.d.ts +2 -0
- package/dist/core/agent/run.js +1 -1
- package/dist/core/config/desktop-config.d.ts +71 -3
- package/dist/core/config/desktop-config.js +222 -24
- package/dist/core/memory/compaction-extension.d.ts +4 -3
- package/dist/core/memory/compaction-extension.js +6 -14
- package/dist/core/memory/embedding-types.d.ts +10 -0
- package/dist/core/memory/embedding-types.js +5 -0
- package/dist/core/memory/embedding.d.ts +2 -1
- package/dist/core/memory/embedding.js +38 -6
- package/dist/core/memory/index.js +3 -0
- package/dist/core/memory/local-embedding-llama.d.ts +13 -0
- package/dist/core/memory/local-embedding-llama.js +76 -0
- package/dist/core/memory/local-embedding.d.ts +10 -0
- package/dist/core/memory/local-embedding.js +29 -0
- package/dist/core/memory/persist-compaction-on-close.d.ts +14 -0
- package/dist/core/memory/persist-compaction-on-close.js +32 -0
- package/dist/core/tools/bookmark-tool.d.ts +4 -0
- package/dist/core/tools/bookmark-tool.js +59 -3
- package/dist/core/tools/index.d.ts +2 -1
- package/dist/core/tools/index.js +2 -1
- package/dist/core/tools/memory-recall-tool.d.ts +6 -0
- package/dist/core/tools/memory-recall-tool.js +77 -0
- package/dist/gateway/channel/adapters/wechat.d.ts +24 -0
- package/dist/gateway/channel/adapters/wechat.js +205 -0
- package/dist/gateway/methods/agent-cancel.d.ts +3 -1
- package/dist/gateway/methods/agent-cancel.js +13 -2
- package/dist/gateway/methods/agent-chat.js +112 -23
- package/dist/gateway/methods/run-scheduled-task.js +3 -7
- package/dist/gateway/proxy-run-abort.d.ts +6 -0
- package/dist/gateway/proxy-run-abort.js +39 -0
- package/dist/gateway/server.js +62 -7
- package/dist/server/agent-config/agent-config.controller.d.ts +2 -2
- package/dist/server/agent-config/agent-config.controller.js +8 -4
- package/dist/server/agent-config/agent-config.module.js +3 -1
- package/dist/server/agent-config/agent-config.service.d.ts +41 -6
- package/dist/server/agent-config/agent-config.service.js +30 -3
- package/dist/server/agents/agents.service.js +1 -1
- package/dist/server/bootstrap.js +9 -2
- package/dist/server/config/config.controller.d.ts +31 -2
- package/dist/server/config/config.controller.js +14 -0
- package/dist/server/config/config.module.js +2 -2
- package/dist/server/config/config.service.d.ts +14 -1
- package/dist/server/config/config.service.js +1 -0
- package/dist/server/workspace/workspace.service.d.ts +7 -0
- package/dist/server/workspace/workspace.service.js +16 -0
- package/package.json +6 -1
- package/skills/url-bookmark/SKILL.md +12 -12
- package/apps/desktop/renderer/dist/assets/index-DmIfN-Vc.js +0 -89
- package/apps/desktop/renderer/dist/assets/index-DvB8yW8I.css +0 -10
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
<link
|
|
12
12
|
href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Roboto+Mono:wght@400;500&display=swap"
|
|
13
13
|
rel="stylesheet">
|
|
14
|
-
<script type="module" crossorigin src="/assets/index-
|
|
15
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
14
|
+
<script type="module" crossorigin src="/assets/index-B8jRTtME.js"></script>
|
|
15
|
+
<link rel="stylesheet" crossorigin href="/assets/index-B0_RWD2F.css">
|
|
16
16
|
</head>
|
|
17
17
|
|
|
18
18
|
<body>
|
|
@@ -14,6 +14,8 @@ export declare class AgentManager {
|
|
|
14
14
|
private sessions;
|
|
15
15
|
/** 每个 session 最后被使用的时间戳,用于 LRU 淘汰 */
|
|
16
16
|
private sessionLastActiveAt;
|
|
17
|
+
/** 每个 SessionAgent 当前最新的 compaction summary,关闭会话时写入向量库(infotype: compaction) */
|
|
18
|
+
private sessionLatestCompactionSummary;
|
|
17
19
|
private agentDir;
|
|
18
20
|
private workspaceDir;
|
|
19
21
|
private skillPaths;
|
|
@@ -60,13 +62,17 @@ export declare class AgentManager {
|
|
|
60
62
|
mcpServers?: McpServerConfig[];
|
|
61
63
|
/** 自定义系统提示词(来自 agent 配置),会与技能等一起组成最终 systemPrompt */
|
|
62
64
|
systemPrompt?: string;
|
|
65
|
+
/** 是否使用长记忆(memory_recall/save_experience);默认 true */
|
|
66
|
+
useLongMemory?: boolean;
|
|
63
67
|
}): Promise<AgentSession>;
|
|
64
68
|
/** 按复合 key 获取(key = sessionId + "::" + agentId) */
|
|
65
69
|
getSession(compositeKey: string): AgentSession | undefined;
|
|
66
|
-
/**
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
|
|
70
|
+
/** 按业务 sessionId 查找一个 Session(取最近活跃的),用于 agent.cancel 等 */
|
|
71
|
+
getSessionBySessionId(sessionId: string): AgentSession | undefined;
|
|
72
|
+
/** 删除一个 Agent Session(传入复合 key);关闭前将本 session 最新 compaction summary 写入向量库 */
|
|
73
|
+
deleteSession(compositeKey: string): Promise<boolean>;
|
|
74
|
+
/** 按业务 sessionId 删除该会话下所有 agent 的 Core Session(如删除会话时);关闭前将各 session 最新 compaction 写入向量库 */
|
|
75
|
+
deleteSessionsByBusinessId(sessionId: string): Promise<void>;
|
|
70
76
|
clearAll(): void;
|
|
71
77
|
}
|
|
72
78
|
export declare const agentManager: AgentManager;
|
|
@@ -2,8 +2,9 @@ import { createAgentSession, AuthStorage, DefaultResourceLoader, ModelRegistry,
|
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
import { existsSync, mkdirSync } from "node:fs";
|
|
4
4
|
import { createCompactionMemoryExtensionFactory } from "../memory/compaction-extension.js";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { addMemory } from "../memory/index.js";
|
|
6
|
+
import { persistStoredCompactionForSession, persistStoredCompactionForBusinessSession, } from "../memory/persist-compaction-on-close.js";
|
|
7
|
+
import { createBrowserTool, createSaveExperienceTool, createMemoryRecallTool, createInstallSkillTool, createSwitchAgentTool, createListAgentsTool, createCreateAgentTool, createGetBookmarkTagsTool, createSaveBookmarkTool, createAddBookmarkTagTool } from "../tools/index.js";
|
|
7
8
|
/** Agent Session 缓存 key:sessionId + "::" + agentId,同一业务 session 下不同 agent 各自一个 Core Session */
|
|
8
9
|
const COMPOSITE_KEY_SEP = "::";
|
|
9
10
|
function toCompositeKey(sessionId, agentId) {
|
|
@@ -24,6 +25,8 @@ export class AgentManager {
|
|
|
24
25
|
sessions = new Map();
|
|
25
26
|
/** 每个 session 最后被使用的时间戳,用于 LRU 淘汰 */
|
|
26
27
|
sessionLastActiveAt = new Map();
|
|
28
|
+
/** 每个 SessionAgent 当前最新的 compaction summary,关闭会话时写入向量库(infotype: compaction) */
|
|
29
|
+
sessionLatestCompactionSummary = new Map();
|
|
27
30
|
agentDir;
|
|
28
31
|
workspaceDir;
|
|
29
32
|
skillPaths = [];
|
|
@@ -89,10 +92,16 @@ You have access to a \`browser\` tool for web automation:
|
|
|
89
92
|
|
|
90
93
|
Use refs from snapshots (e.g., @e1) for reliable element selection.
|
|
91
94
|
For downloads, provide either a direct URL or a selector to click.`;
|
|
95
|
+
const experienceMemoryDesc = `
|
|
96
|
+
## Long-term memory
|
|
97
|
+
|
|
98
|
+
- **save_experience**: Store summaries in long-term memory. **At the end of each round of conversation** (after you have finished replying to the user), briefly summarize the main outcomes, conclusions, or reusable points and call \`save_experience\` with that summary.
|
|
99
|
+
- **memory_recall**: Retrieve relevant memories by semantic search. **When the user asks about past work, decisions, dates, people, preferences, todos, complex tasks, scheduled tasks, or anything that may need past experience**, call \`memory_recall\` first with a suitable query, then answer using the recalled content. Do not inject any history or memory into your replies unless you have just retrieved it via \`memory_recall\` for that question.`;
|
|
92
100
|
const parts = [
|
|
93
101
|
"You are a helpful assistant. When users ask about skills, explain what skills are available.",
|
|
94
102
|
browserToolDesc,
|
|
95
103
|
skillsBlock,
|
|
104
|
+
experienceMemoryDesc,
|
|
96
105
|
].filter(Boolean);
|
|
97
106
|
return parts.join("\n\n");
|
|
98
107
|
}
|
|
@@ -106,27 +115,25 @@ For downloads, provide either a direct URL or a selector to click.`;
|
|
|
106
115
|
const systemPrompt = this.buildSystemPrompt(loadedSkills);
|
|
107
116
|
return { systemPrompt, skills: loadedSkills };
|
|
108
117
|
}
|
|
109
|
-
createResourceLoader(workspaceDir, sessionId,
|
|
118
|
+
createResourceLoader(workspaceDir, sessionId, customAgentPrompt, identity, onUpdateLatestCompaction) {
|
|
110
119
|
const loader = new DefaultResourceLoader({
|
|
111
120
|
cwd: workspaceDir,
|
|
112
121
|
agentDir: this.agentDir,
|
|
113
122
|
noSkills: true, // Disable SDK's built-in skills logic to take full control
|
|
114
123
|
additionalSkillPaths: this.resolveSkillPaths(workspaceDir),
|
|
115
|
-
extensionFactories: sessionId
|
|
124
|
+
extensionFactories: sessionId && onUpdateLatestCompaction
|
|
125
|
+
? [createCompactionMemoryExtensionFactory(sessionId, onUpdateLatestCompaction)]
|
|
126
|
+
: [],
|
|
116
127
|
systemPromptOverride: (base) => {
|
|
117
128
|
const loadedSkills = loader.getSkills().skills;
|
|
118
|
-
|
|
129
|
+
const basePrompt = this.buildSystemPrompt(loadedSkills);
|
|
119
130
|
const withCustom = customAgentPrompt && customAgentPrompt.trim()
|
|
120
131
|
? customAgentPrompt.trim() + "\n\n" + basePrompt
|
|
121
132
|
: basePrompt;
|
|
122
|
-
|
|
133
|
+
return identity && identity.agentId
|
|
123
134
|
? `[Session identity] You are the agent with ID: ${identity.agentId}, workspace: ${identity.workspace || identity.agentId}. When asked which agent you are, answer according to this identity.\n\n` +
|
|
124
135
|
withCustom
|
|
125
136
|
: withCustom;
|
|
126
|
-
if (compactionBlock?.trim()) {
|
|
127
|
-
return withIdentity + "\n\n" + compactionBlock.trim();
|
|
128
|
-
}
|
|
129
|
-
return withIdentity;
|
|
130
137
|
},
|
|
131
138
|
});
|
|
132
139
|
return loader;
|
|
@@ -182,7 +189,7 @@ For downloads, provide either a direct URL or a selector to click.`;
|
|
|
182
189
|
}
|
|
183
190
|
}
|
|
184
191
|
if (oldestId != null) {
|
|
185
|
-
this.deleteSession(oldestId);
|
|
192
|
+
await this.deleteSession(oldestId);
|
|
186
193
|
}
|
|
187
194
|
}
|
|
188
195
|
const workspaceRoot = getOpenbotWorkspaceDir();
|
|
@@ -238,8 +245,7 @@ For downloads, provide either a direct URL or a selector to click.`;
|
|
|
238
245
|
return process.env.OPENAI_API_KEY;
|
|
239
246
|
return process.env.OPENAI_API_KEY;
|
|
240
247
|
});
|
|
241
|
-
const
|
|
242
|
-
const loader = this.createResourceLoader(sessionWorkspaceDir, sessionId, compactionBlock, options.systemPrompt, { agentId, workspace: workspaceName });
|
|
248
|
+
const loader = this.createResourceLoader(sessionWorkspaceDir, sessionId, options.systemPrompt, { agentId, workspace: workspaceName }, (summary) => this.sessionLatestCompactionSummary.set(compositeKey, summary));
|
|
243
249
|
await loader.reload();
|
|
244
250
|
const coreTools = {
|
|
245
251
|
read: createReadTool(sessionWorkspaceDir),
|
|
@@ -250,16 +256,19 @@ For downloads, provide either a direct URL or a selector to click.`;
|
|
|
250
256
|
grep: createGrepTool(sessionWorkspaceDir),
|
|
251
257
|
ls: createLsTool(sessionWorkspaceDir),
|
|
252
258
|
};
|
|
259
|
+
const useLongMemory = options.useLongMemory !== false;
|
|
253
260
|
const mcpTools = await createMcpToolsForSession({ mcpServers: options.mcpServers });
|
|
254
261
|
const customTools = [
|
|
255
262
|
createBrowserTool(sessionWorkspaceDir),
|
|
256
263
|
createSaveExperienceTool(sessionId),
|
|
264
|
+
createMemoryRecallTool(useLongMemory),
|
|
257
265
|
createInstallSkillTool(options.targetAgentId ?? agentId),
|
|
258
266
|
createSwitchAgentTool(sessionId),
|
|
259
267
|
createListAgentsTool(),
|
|
260
268
|
createCreateAgentTool(),
|
|
261
269
|
createGetBookmarkTagsTool(),
|
|
262
270
|
createSaveBookmarkTool(),
|
|
271
|
+
createAddBookmarkTagTool(),
|
|
263
272
|
...mcpTools,
|
|
264
273
|
];
|
|
265
274
|
const { session } = await createAgentSession({
|
|
@@ -285,24 +294,42 @@ For downloads, provide either a direct URL or a selector to click.`;
|
|
|
285
294
|
getSession(compositeKey) {
|
|
286
295
|
return this.sessions.get(compositeKey);
|
|
287
296
|
}
|
|
288
|
-
/**
|
|
289
|
-
|
|
297
|
+
/** 按业务 sessionId 查找一个 Session(取最近活跃的),用于 agent.cancel 等 */
|
|
298
|
+
getSessionBySessionId(sessionId) {
|
|
299
|
+
const prefix = sessionId + COMPOSITE_KEY_SEP;
|
|
300
|
+
let bestKey;
|
|
301
|
+
let bestAt = 0;
|
|
302
|
+
for (const key of this.sessions.keys()) {
|
|
303
|
+
if (!key.startsWith(prefix))
|
|
304
|
+
continue;
|
|
305
|
+
const at = this.sessionLastActiveAt.get(key) ?? 0;
|
|
306
|
+
if (at >= bestAt) {
|
|
307
|
+
bestAt = at;
|
|
308
|
+
bestKey = key;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
return bestKey != null ? this.sessions.get(bestKey) : undefined;
|
|
312
|
+
}
|
|
313
|
+
/** 删除一个 Agent Session(传入复合 key);关闭前将本 session 最新 compaction summary 写入向量库 */
|
|
314
|
+
async deleteSession(compositeKey) {
|
|
315
|
+
await persistStoredCompactionForSession(this.sessionLatestCompactionSummary, compositeKey, addMemory);
|
|
290
316
|
this.sessionLastActiveAt.delete(compositeKey);
|
|
291
317
|
return this.sessions.delete(compositeKey);
|
|
292
318
|
}
|
|
293
|
-
/** 按业务 sessionId 删除该会话下所有 agent 的 Core Session
|
|
294
|
-
deleteSessionsByBusinessId(sessionId) {
|
|
319
|
+
/** 按业务 sessionId 删除该会话下所有 agent 的 Core Session(如删除会话时);关闭前将各 session 最新 compaction 写入向量库 */
|
|
320
|
+
async deleteSessionsByBusinessId(sessionId) {
|
|
295
321
|
const prefix = sessionId + COMPOSITE_KEY_SEP;
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
322
|
+
const keysToProcess = Array.from(this.sessions.keys()).filter((k) => k.startsWith(prefix));
|
|
323
|
+
await persistStoredCompactionForBusinessSession(this.sessionLatestCompactionSummary, keysToProcess, sessionId, addMemory);
|
|
324
|
+
for (const key of keysToProcess) {
|
|
325
|
+
this.sessionLastActiveAt.delete(key);
|
|
326
|
+
this.sessions.delete(key);
|
|
301
327
|
}
|
|
302
328
|
}
|
|
303
329
|
clearAll() {
|
|
304
330
|
this.sessions.clear();
|
|
305
331
|
this.sessionLastActiveAt.clear();
|
|
332
|
+
this.sessionLatestCompactionSummary.clear();
|
|
306
333
|
}
|
|
307
334
|
}
|
|
308
335
|
// Singleton for easy access (e.g., from Gateway)
|
|
@@ -176,6 +176,13 @@ export const cozeAdapter = {
|
|
|
176
176
|
};
|
|
177
177
|
const controller = new AbortController();
|
|
178
178
|
const timeoutId = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
|
|
179
|
+
const userSignal = options.signal;
|
|
180
|
+
if (userSignal) {
|
|
181
|
+
if (userSignal.aborted)
|
|
182
|
+
controller.abort();
|
|
183
|
+
else
|
|
184
|
+
userSignal.addEventListener("abort", () => controller.abort(), { once: true });
|
|
185
|
+
}
|
|
179
186
|
try {
|
|
180
187
|
console.log(`[Coze] POST ${url} (stream=true)`);
|
|
181
188
|
const res = await fetch(url, {
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { agentManager } from "../../agent-manager.js";
|
|
5
5
|
import { getDesktopConfig } from "../../../config/desktop-config.js";
|
|
6
|
-
import { getExperienceContextForUserMessage } from "../../../memory/index.js";
|
|
7
6
|
const CHANNEL_AGENT_TIMEOUT_MS = 120_000;
|
|
8
7
|
export const localAdapter = {
|
|
9
8
|
type: "local",
|
|
@@ -21,6 +20,7 @@ export const localAdapter = {
|
|
|
21
20
|
targetAgentId: agentId,
|
|
22
21
|
mcpServers: config.mcpServers,
|
|
23
22
|
systemPrompt: config.systemPrompt,
|
|
23
|
+
useLongMemory: config.useLongMemory,
|
|
24
24
|
});
|
|
25
25
|
let resolveDone;
|
|
26
26
|
const donePromise = new Promise((r) => {
|
|
@@ -39,11 +39,7 @@ export const localAdapter = {
|
|
|
39
39
|
}
|
|
40
40
|
});
|
|
41
41
|
try {
|
|
42
|
-
|
|
43
|
-
const userMessageToSend = experienceBlock.trim().length > 0
|
|
44
|
-
? `${experienceBlock}\n\n用户问题:\n${message}`
|
|
45
|
-
: message;
|
|
46
|
-
await session.sendUserMessage(userMessageToSend, { deliverAs: "followUp" });
|
|
42
|
+
await session.sendUserMessage(message, { deliverAs: "followUp" });
|
|
47
43
|
await Promise.race([
|
|
48
44
|
donePromise,
|
|
49
45
|
new Promise((_, rej) => setTimeout(() => rej(new Error("Channel agent reply timeout")), CHANNEL_AGENT_TIMEOUT_MS)),
|
|
@@ -67,6 +63,7 @@ export const localAdapter = {
|
|
|
67
63
|
targetAgentId: agentId,
|
|
68
64
|
mcpServers: config.mcpServers,
|
|
69
65
|
systemPrompt: config.systemPrompt,
|
|
66
|
+
useLongMemory: config.useLongMemory,
|
|
70
67
|
});
|
|
71
68
|
const chunks = [];
|
|
72
69
|
let resolveDone;
|
|
@@ -82,11 +79,7 @@ export const localAdapter = {
|
|
|
82
79
|
}
|
|
83
80
|
});
|
|
84
81
|
try {
|
|
85
|
-
|
|
86
|
-
const userMessageToSend = experienceBlock.trim().length > 0
|
|
87
|
-
? `${experienceBlock}\n\n用户问题:\n${message}`
|
|
88
|
-
: message;
|
|
89
|
-
await session.sendUserMessage(userMessageToSend, { deliverAs: "followUp" });
|
|
82
|
+
await session.sendUserMessage(message, { deliverAs: "followUp" });
|
|
90
83
|
await Promise.race([
|
|
91
84
|
donePromise,
|
|
92
85
|
new Promise((_, rej) => setTimeout(() => rej(new Error("Channel agent reply timeout")), CHANNEL_AGENT_TIMEOUT_MS)),
|
|
@@ -25,6 +25,13 @@ export const openclawxAdapter = {
|
|
|
25
25
|
const body = { sessionId: options.sessionId, message: options.message, agentId: options.agentId };
|
|
26
26
|
const controller = new AbortController();
|
|
27
27
|
const timeoutId = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
|
|
28
|
+
const userSignal = options.signal;
|
|
29
|
+
if (userSignal) {
|
|
30
|
+
if (userSignal.aborted)
|
|
31
|
+
controller.abort();
|
|
32
|
+
else
|
|
33
|
+
userSignal.addEventListener("abort", () => controller.abort(), { once: true });
|
|
34
|
+
}
|
|
28
35
|
try {
|
|
29
36
|
const res = await fetch(url, {
|
|
30
37
|
method: "POST",
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { IAgentProxyAdapter } from "../types.js";
|
|
2
|
+
export interface ResolvedOpenCodeConfig {
|
|
3
|
+
baseUrl: string;
|
|
4
|
+
username: string;
|
|
5
|
+
password?: string;
|
|
6
|
+
model: {
|
|
7
|
+
providerID: string;
|
|
8
|
+
modelID: string;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
export declare const opencodeAdapter: IAgentProxyAdapter;
|