@next-open-ai/openbot 0.3.2 → 0.6.8
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 +46 -7
- package/apps/desktop/renderer/dist/assets/index-LCp1YPVA.css +10 -0
- package/apps/desktop/renderer/dist/assets/index-l5fpDsHs.js +89 -0
- package/apps/desktop/renderer/dist/index.html +2 -2
- package/dist/core/agent/agent-manager.d.ts +15 -7
- package/dist/core/agent/agent-manager.js +52 -21
- package/dist/core/agent/run.js +2 -2
- package/dist/core/config/desktop-config.d.ts +24 -0
- package/dist/core/config/desktop-config.js +19 -1
- package/dist/core/session-current-agent.d.ts +34 -0
- package/dist/core/session-current-agent.js +32 -0
- package/dist/core/tools/create-agent-tool.d.ts +6 -0
- package/dist/core/tools/create-agent-tool.js +97 -0
- package/dist/core/tools/index.d.ts +3 -0
- package/dist/core/tools/index.js +3 -0
- package/dist/core/tools/list-agents-tool.d.ts +5 -0
- package/dist/core/tools/list-agents-tool.js +45 -0
- package/dist/core/tools/switch-agent-tool.d.ts +6 -0
- package/dist/core/tools/switch-agent-tool.js +54 -0
- package/dist/gateway/channel/adapters/dingtalk.d.ts +11 -0
- package/dist/gateway/channel/adapters/dingtalk.js +190 -0
- package/dist/gateway/channel/adapters/feishu.d.ts +11 -0
- package/dist/gateway/channel/adapters/feishu.js +218 -0
- package/dist/gateway/channel/adapters/telegram.d.ts +14 -0
- package/dist/gateway/channel/adapters/telegram.js +197 -0
- package/dist/gateway/channel/channel-core.d.ts +9 -0
- package/dist/gateway/channel/channel-core.js +135 -0
- package/dist/gateway/channel/registry.d.ts +16 -0
- package/dist/gateway/channel/registry.js +54 -0
- package/dist/gateway/channel/run-agent.d.ts +26 -0
- package/dist/gateway/channel/run-agent.js +137 -0
- package/dist/gateway/channel/session-persistence.d.ts +36 -0
- package/dist/gateway/channel/session-persistence.js +46 -0
- package/dist/gateway/channel/types.d.ts +74 -0
- package/dist/gateway/channel/types.js +4 -0
- package/dist/gateway/channel-handler.d.ts +3 -4
- package/dist/gateway/channel-handler.js +8 -2
- package/dist/gateway/methods/agent-chat.js +30 -12
- package/dist/gateway/methods/run-scheduled-task.js +4 -2
- package/dist/gateway/server.js +84 -1
- package/dist/server/agent-config/agent-config.controller.d.ts +6 -1
- package/dist/server/agent-config/agent-config.service.d.ts +12 -1
- package/dist/server/agent-config/agent-config.service.js +10 -3
- package/dist/server/agents/agents.controller.d.ts +10 -0
- package/dist/server/agents/agents.controller.js +35 -1
- package/dist/server/agents/agents.gateway.js +18 -4
- package/dist/server/agents/agents.service.d.ts +4 -0
- package/dist/server/agents/agents.service.js +17 -1
- package/dist/server/config/config.controller.d.ts +2 -0
- package/dist/server/config/config.service.d.ts +3 -0
- package/dist/server/config/config.service.js +3 -1
- package/dist/server/saved-items/saved-items.controller.d.ts +32 -1
- package/dist/server/saved-items/saved-items.controller.js +154 -3
- package/dist/server/saved-items/saved-items.module.js +3 -1
- package/dist/server/workspace/workspace.service.d.ts +11 -0
- package/dist/server/workspace/workspace.service.js +40 -1
- package/package.json +3 -1
- package/apps/desktop/renderer/dist/assets/index-DKtaRFW4.js +0 -89
- package/apps/desktop/renderer/dist/assets/index-QHuqXpWQ.css +0 -10
|
@@ -49,13 +49,16 @@ export async function handleRunScheduledTask(req, res) {
|
|
|
49
49
|
if (agentConfig.apiKey)
|
|
50
50
|
apiKey = agentConfig.apiKey;
|
|
51
51
|
}
|
|
52
|
+
const COMPOSITE_KEY_SEP = "::";
|
|
52
53
|
try {
|
|
53
54
|
const session = await agentManager.getOrCreateSession(sessionId, {
|
|
55
|
+
agentId: sessionAgentId,
|
|
54
56
|
workspace: resolvedWorkspace,
|
|
55
57
|
provider,
|
|
56
58
|
modelId,
|
|
57
59
|
apiKey,
|
|
58
60
|
mcpServers: agentConfig?.mcpServers,
|
|
61
|
+
systemPrompt: agentConfig?.systemPrompt,
|
|
59
62
|
});
|
|
60
63
|
let assistantContent = "";
|
|
61
64
|
let turnPromptTokens = 0;
|
|
@@ -121,7 +124,6 @@ export async function handleRunScheduledTask(req, res) {
|
|
|
121
124
|
res.end(JSON.stringify({ success: false, error: friendlyError }));
|
|
122
125
|
}
|
|
123
126
|
finally {
|
|
124
|
-
|
|
125
|
-
agentManager.deleteSession(sessionId);
|
|
127
|
+
agentManager.deleteSession(sessionId + COMPOSITE_KEY_SEP + sessionAgentId);
|
|
126
128
|
}
|
|
127
129
|
}
|
package/dist/gateway/server.js
CHANGED
|
@@ -35,8 +35,16 @@ import multer from "multer";
|
|
|
35
35
|
import { handleInstallSkillFromPath } from "./methods/install-skill-from-path.js";
|
|
36
36
|
import { handleInstallSkillFromUpload } from "./methods/install-skill-from-upload.js";
|
|
37
37
|
import { setBackendBaseUrl } from "./backend-url.js";
|
|
38
|
-
import { ensureDesktopConfigInitialized } from "../core/config/desktop-config.js";
|
|
38
|
+
import { ensureDesktopConfigInitialized, getChannelsConfigSync } from "../core/config/desktop-config.js";
|
|
39
39
|
import { createNestAppEmbedded } from "../server/bootstrap.js";
|
|
40
|
+
import { registerChannel, startAllChannels, stopAllChannels } from "./channel/registry.js";
|
|
41
|
+
import { createFeishuChannel } from "./channel/adapters/feishu.js";
|
|
42
|
+
import { createDingTalkChannel } from "./channel/adapters/dingtalk.js";
|
|
43
|
+
import { createTelegramChannel } from "./channel/adapters/telegram.js";
|
|
44
|
+
import { setChannelSessionPersistence } from "./channel/session-persistence.js";
|
|
45
|
+
import { setSessionCurrentAgentResolver, setSessionCurrentAgentUpdater, setAgentListProvider, setCreateAgentProvider, } from "../core/session-current-agent.js";
|
|
46
|
+
import { AgentsService } from "../server/agents/agents.service.js";
|
|
47
|
+
import { AgentConfigService } from "../server/agent-config/agent-config.service.js";
|
|
40
48
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
41
49
|
const PACKAGE_ROOT = join(__dirname, "..", "..");
|
|
42
50
|
/** 内嵌到 Electron 时由主进程设置 OPENBOT_STATIC_DIR,指向打包后的 renderer/dist */
|
|
@@ -61,6 +69,27 @@ export async function startGatewayServer(port = 38080) {
|
|
|
61
69
|
console.log(`Starting gateway server on port ${port}...`);
|
|
62
70
|
setBackendBaseUrl(`http://localhost:${port}`);
|
|
63
71
|
const { app: nestApp, express: nestExpress } = await createNestAppEmbedded();
|
|
72
|
+
try {
|
|
73
|
+
const agentsService = nestApp.get(AgentsService);
|
|
74
|
+
setChannelSessionPersistence(agentsService);
|
|
75
|
+
setSessionCurrentAgentResolver((sessionId) => agentsService.getSession(sessionId)?.agentId);
|
|
76
|
+
setSessionCurrentAgentUpdater((sessionId, agentId) => agentsService.updateSessionAgentId(sessionId, agentId));
|
|
77
|
+
const agentConfigService = nestApp.get(AgentConfigService);
|
|
78
|
+
setAgentListProvider(() => agentConfigService.listAgents().then((agents) => agents.map((a) => ({ id: a.id, name: a.name }))));
|
|
79
|
+
setCreateAgentProvider(async (params) => {
|
|
80
|
+
try {
|
|
81
|
+
const agent = await agentConfigService.createAgent(params);
|
|
82
|
+
return { id: agent.id, name: agent.name };
|
|
83
|
+
}
|
|
84
|
+
catch (e) {
|
|
85
|
+
const msg = e?.message ?? e?.response?.message ?? String(e);
|
|
86
|
+
return { error: msg };
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
catch (e) {
|
|
91
|
+
console.warn("[Gateway] Channel session persistence / session-agent bridge unavailable:", e);
|
|
92
|
+
}
|
|
64
93
|
const gatewayExpress = express();
|
|
65
94
|
gatewayExpress.get(PATHS.HEALTH, (_req, res) => {
|
|
66
95
|
res.status(200).json({ status: "ok", timestamp: Date.now() });
|
|
@@ -178,8 +207,62 @@ export async function startGatewayServer(port = 38080) {
|
|
|
178
207
|
resolve(p);
|
|
179
208
|
});
|
|
180
209
|
});
|
|
210
|
+
// 通道:根据配置注册并启动(飞书 WebSocket、钉钉 Stream 等)
|
|
211
|
+
const channelsConfig = getChannelsConfigSync();
|
|
212
|
+
const feishuCfg = channelsConfig.feishu;
|
|
213
|
+
if (feishuCfg?.enabled && feishuCfg.appId?.trim() && feishuCfg.appSecret?.trim()) {
|
|
214
|
+
try {
|
|
215
|
+
const feishuChannel = createFeishuChannel({
|
|
216
|
+
appId: feishuCfg.appId.trim(),
|
|
217
|
+
appSecret: feishuCfg.appSecret.trim(),
|
|
218
|
+
defaultAgentId: feishuCfg.defaultAgentId?.trim() || "default",
|
|
219
|
+
});
|
|
220
|
+
registerChannel(feishuChannel);
|
|
221
|
+
}
|
|
222
|
+
catch (e) {
|
|
223
|
+
console.warn("Feishu channel register failed:", e);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
else if (feishuCfg?.enabled) {
|
|
227
|
+
console.warn("[Channel] Feishu is enabled but appId or appSecret is missing; skip. Check Settings → Channels.");
|
|
228
|
+
}
|
|
229
|
+
const dingtalkCfg = channelsConfig.dingtalk;
|
|
230
|
+
if (dingtalkCfg?.enabled && dingtalkCfg.clientId?.trim() && dingtalkCfg.clientSecret?.trim()) {
|
|
231
|
+
try {
|
|
232
|
+
const dingtalkChannel = createDingTalkChannel({
|
|
233
|
+
clientId: dingtalkCfg.clientId.trim(),
|
|
234
|
+
clientSecret: dingtalkCfg.clientSecret.trim(),
|
|
235
|
+
defaultAgentId: dingtalkCfg.defaultAgentId?.trim() || "default",
|
|
236
|
+
});
|
|
237
|
+
registerChannel(dingtalkChannel);
|
|
238
|
+
}
|
|
239
|
+
catch (e) {
|
|
240
|
+
console.warn("DingTalk channel register failed:", e);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
else if (dingtalkCfg?.enabled) {
|
|
244
|
+
console.warn("[Channel] DingTalk is enabled but clientId or clientSecret is missing; skip. Check Settings → Channels.");
|
|
245
|
+
}
|
|
246
|
+
const telegramCfg = channelsConfig.telegram;
|
|
247
|
+
if (telegramCfg?.enabled && telegramCfg.botToken?.trim()) {
|
|
248
|
+
try {
|
|
249
|
+
const telegramChannel = createTelegramChannel({
|
|
250
|
+
botToken: telegramCfg.botToken.trim(),
|
|
251
|
+
defaultAgentId: telegramCfg.defaultAgentId?.trim() || "default",
|
|
252
|
+
});
|
|
253
|
+
registerChannel(telegramChannel);
|
|
254
|
+
}
|
|
255
|
+
catch (e) {
|
|
256
|
+
console.warn("Telegram channel register failed:", e);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
else if (telegramCfg?.enabled) {
|
|
260
|
+
console.warn("[Channel] Telegram is enabled but botToken is missing; skip. Check Settings → Channels.");
|
|
261
|
+
}
|
|
262
|
+
await startAllChannels();
|
|
181
263
|
const close = async () => {
|
|
182
264
|
console.log("Closing gateway server...");
|
|
265
|
+
await stopAllChannels();
|
|
183
266
|
await nestApp.close();
|
|
184
267
|
wss.clients.forEach((c) => c.close());
|
|
185
268
|
await new Promise((r) => wss.close(() => r()));
|
|
@@ -16,11 +16,16 @@ export declare class AgentConfigController {
|
|
|
16
16
|
createAgent(body: {
|
|
17
17
|
name: string;
|
|
18
18
|
workspace: string;
|
|
19
|
+
provider?: string;
|
|
20
|
+
model?: string;
|
|
21
|
+
modelItemCode?: string;
|
|
22
|
+
systemPrompt?: string;
|
|
23
|
+
icon?: string;
|
|
19
24
|
}): Promise<{
|
|
20
25
|
success: boolean;
|
|
21
26
|
data: AgentConfigItem;
|
|
22
27
|
}>;
|
|
23
|
-
updateAgent(id: string, body: Partial<Pick<AgentConfigItem, 'name' | 'provider' | 'model' | 'modelItemCode' | 'mcpServers'>>): Promise<{
|
|
28
|
+
updateAgent(id: string, body: Partial<Pick<AgentConfigItem, 'name' | 'provider' | 'model' | 'modelItemCode' | 'mcpServers' | 'systemPrompt' | 'icon'>>): Promise<{
|
|
24
29
|
success: boolean;
|
|
25
30
|
data: AgentConfigItem;
|
|
26
31
|
}>;
|
|
@@ -17,6 +17,10 @@ export interface AgentConfigItem {
|
|
|
17
17
|
isDefault?: boolean;
|
|
18
18
|
/** MCP 服务器配置列表,创建 Session 时传入(与 Skill 类似) */
|
|
19
19
|
mcpServers?: McpServerConfig[];
|
|
20
|
+
/** 自定义系统提示词,会与技能等一起组成最终 systemPrompt */
|
|
21
|
+
systemPrompt?: string;
|
|
22
|
+
/** 智能体图标标识(前端预设图标 id,如 default、star、code 等) */
|
|
23
|
+
icon?: string;
|
|
20
24
|
}
|
|
21
25
|
export declare class AgentConfigService {
|
|
22
26
|
private configDir;
|
|
@@ -33,8 +37,15 @@ export declare class AgentConfigService {
|
|
|
33
37
|
createAgent(params: {
|
|
34
38
|
name: string;
|
|
35
39
|
workspace: string;
|
|
40
|
+
provider?: string;
|
|
41
|
+
model?: string;
|
|
42
|
+
modelItemCode?: string;
|
|
43
|
+
/** 自定义系统提示词;可由用户描述生成,创建后可在详情页修改 */
|
|
44
|
+
systemPrompt?: string;
|
|
45
|
+
/** 智能体图标标识 */
|
|
46
|
+
icon?: string;
|
|
36
47
|
}): Promise<AgentConfigItem>;
|
|
37
|
-
updateAgent(id: string, updates: Partial<Pick<AgentConfigItem, 'name' | 'provider' | 'model' | 'modelItemCode' | 'mcpServers'>>): Promise<AgentConfigItem>;
|
|
48
|
+
updateAgent(id: string, updates: Partial<Pick<AgentConfigItem, 'name' | 'provider' | 'model' | 'modelItemCode' | 'mcpServers' | 'systemPrompt' | 'icon'>>): Promise<AgentConfigItem>;
|
|
38
49
|
deleteAgent(id: string): Promise<void>;
|
|
39
50
|
/**
|
|
40
51
|
* 根据 config 的 defaultProvider / defaultModel / defaultModelItemCode 及 configuredModels 同步 agents.json 中缺省智能体的 provider、model、modelItemCode。
|
|
@@ -93,7 +93,7 @@ let AgentConfigService = class AgentConfigService {
|
|
|
93
93
|
return null;
|
|
94
94
|
}
|
|
95
95
|
async createAgent(params) {
|
|
96
|
-
const { name, workspace } = params;
|
|
96
|
+
const { name, workspace, provider, model, modelItemCode, systemPrompt, icon } = params;
|
|
97
97
|
if (workspace === DEFAULT_AGENT_ID) {
|
|
98
98
|
throw new BadRequestException('工作空间名 default 为系统保留(主智能体),请使用其他名称');
|
|
99
99
|
}
|
|
@@ -118,8 +118,11 @@ let AgentConfigService = class AgentConfigService {
|
|
|
118
118
|
id: workspace,
|
|
119
119
|
name: trimmedName,
|
|
120
120
|
workspace,
|
|
121
|
-
provider: undefined,
|
|
122
|
-
model: undefined,
|
|
121
|
+
provider: provider?.trim() || undefined,
|
|
122
|
+
model: model?.trim() || undefined,
|
|
123
|
+
modelItemCode: modelItemCode?.trim() || undefined,
|
|
124
|
+
systemPrompt: systemPrompt?.trim() || undefined,
|
|
125
|
+
icon: icon?.trim() || undefined,
|
|
123
126
|
};
|
|
124
127
|
file.agents.push(agent);
|
|
125
128
|
await this.writeAgentsFile(file);
|
|
@@ -152,6 +155,10 @@ let AgentConfigService = class AgentConfigService {
|
|
|
152
155
|
agent.modelItemCode = updates.modelItemCode;
|
|
153
156
|
if (updates.mcpServers !== undefined)
|
|
154
157
|
agent.mcpServers = updates.mcpServers;
|
|
158
|
+
if (updates.systemPrompt !== undefined)
|
|
159
|
+
agent.systemPrompt = updates.systemPrompt?.trim() || undefined;
|
|
160
|
+
if (updates.icon !== undefined)
|
|
161
|
+
agent.icon = updates.icon?.trim() || undefined;
|
|
155
162
|
await this.writeAgentsFile(file);
|
|
156
163
|
return { ...agent, isDefault: agent.id === DEFAULT_AGENT_ID };
|
|
157
164
|
}
|
|
@@ -22,6 +22,12 @@ export declare class AgentsController {
|
|
|
22
22
|
success: boolean;
|
|
23
23
|
data: import("./agents.service.js").AgentSession;
|
|
24
24
|
};
|
|
25
|
+
updateSession(id: string, body: {
|
|
26
|
+
agentId?: string;
|
|
27
|
+
}): {
|
|
28
|
+
success: boolean;
|
|
29
|
+
data: import("./agents.service.js").AgentSession | undefined;
|
|
30
|
+
};
|
|
25
31
|
deleteSession(id: string): Promise<{
|
|
26
32
|
success: boolean;
|
|
27
33
|
message: string;
|
|
@@ -30,6 +36,10 @@ export declare class AgentsController {
|
|
|
30
36
|
success: boolean;
|
|
31
37
|
data: import("./agents.service.js").ChatMessage[];
|
|
32
38
|
};
|
|
39
|
+
clearHistory(id: string): {
|
|
40
|
+
success: boolean;
|
|
41
|
+
message: string;
|
|
42
|
+
};
|
|
33
43
|
appendMessage(id: string, body: {
|
|
34
44
|
role: 'user' | 'assistant';
|
|
35
45
|
content: string;
|
|
@@ -10,7 +10,7 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
10
10
|
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
11
11
|
return function (target, key) { decorator(target, key, paramIndex); }
|
|
12
12
|
};
|
|
13
|
-
import { Controller, Get,
|
|
13
|
+
import { Controller, Delete, Get, Patch, Post, Body, Param, Header, HttpException, HttpStatus, } from '@nestjs/common';
|
|
14
14
|
import { AgentsService } from './agents.service.js';
|
|
15
15
|
let AgentsController = class AgentsController {
|
|
16
16
|
agentsService;
|
|
@@ -46,6 +46,17 @@ let AgentsController = class AgentsController {
|
|
|
46
46
|
data: session,
|
|
47
47
|
};
|
|
48
48
|
}
|
|
49
|
+
updateSession(id, body) {
|
|
50
|
+
const session = this.agentsService.getSession(id);
|
|
51
|
+
if (!session) {
|
|
52
|
+
throw new HttpException('Session not found', HttpStatus.NOT_FOUND);
|
|
53
|
+
}
|
|
54
|
+
if (body.agentId != null) {
|
|
55
|
+
this.agentsService.updateSessionAgentId(id, String(body.agentId));
|
|
56
|
+
}
|
|
57
|
+
const updated = this.agentsService.getSession(id);
|
|
58
|
+
return { success: true, data: updated };
|
|
59
|
+
}
|
|
49
60
|
async deleteSession(id) {
|
|
50
61
|
await this.agentsService.deleteSession(id);
|
|
51
62
|
return {
|
|
@@ -60,6 +71,14 @@ let AgentsController = class AgentsController {
|
|
|
60
71
|
data: history,
|
|
61
72
|
};
|
|
62
73
|
}
|
|
74
|
+
clearHistory(id) {
|
|
75
|
+
const session = this.agentsService.getSession(id);
|
|
76
|
+
if (!session) {
|
|
77
|
+
throw new HttpException('Session not found', HttpStatus.NOT_FOUND);
|
|
78
|
+
}
|
|
79
|
+
this.agentsService.clearSessionMessages(id);
|
|
80
|
+
return { success: true, message: 'Messages cleared' };
|
|
81
|
+
}
|
|
63
82
|
appendMessage(id, body) {
|
|
64
83
|
this.agentsService.appendMessage(id, body.role, body.content, {
|
|
65
84
|
toolCalls: body.toolCalls,
|
|
@@ -89,6 +108,14 @@ __decorate([
|
|
|
89
108
|
__metadata("design:paramtypes", [String]),
|
|
90
109
|
__metadata("design:returntype", void 0)
|
|
91
110
|
], AgentsController.prototype, "getSession", null);
|
|
111
|
+
__decorate([
|
|
112
|
+
Patch('sessions/:id'),
|
|
113
|
+
__param(0, Param('id')),
|
|
114
|
+
__param(1, Body()),
|
|
115
|
+
__metadata("design:type", Function),
|
|
116
|
+
__metadata("design:paramtypes", [String, Object]),
|
|
117
|
+
__metadata("design:returntype", void 0)
|
|
118
|
+
], AgentsController.prototype, "updateSession", null);
|
|
92
119
|
__decorate([
|
|
93
120
|
Delete('sessions/:id'),
|
|
94
121
|
__param(0, Param('id')),
|
|
@@ -103,6 +130,13 @@ __decorate([
|
|
|
103
130
|
__metadata("design:paramtypes", [String]),
|
|
104
131
|
__metadata("design:returntype", void 0)
|
|
105
132
|
], AgentsController.prototype, "getHistory", null);
|
|
133
|
+
__decorate([
|
|
134
|
+
Delete('sessions/:id/messages'),
|
|
135
|
+
__param(0, Param('id')),
|
|
136
|
+
__metadata("design:type", Function),
|
|
137
|
+
__metadata("design:paramtypes", [String]),
|
|
138
|
+
__metadata("design:returntype", void 0)
|
|
139
|
+
], AgentsController.prototype, "clearHistory", null);
|
|
106
140
|
__decorate([
|
|
107
141
|
Post('sessions/:id/messages'),
|
|
108
142
|
__param(0, Param('id')),
|
|
@@ -51,14 +51,28 @@ let AgentsGateway = class AgentsGateway {
|
|
|
51
51
|
client.emit('agent_tool', data);
|
|
52
52
|
});
|
|
53
53
|
subscriptions.set('tool', unsubTool);
|
|
54
|
-
//
|
|
54
|
+
// turn_end / agent_end:各通道均可收到,按自身逻辑处理(如 desktop 用 agent_end 开放输入)
|
|
55
|
+
const unsubTurnEnd = this.agentsService.addEventListener('turn_end', (data) => {
|
|
56
|
+
if (data.sessionId === sessionId)
|
|
57
|
+
client.emit('turn_end', data);
|
|
58
|
+
});
|
|
59
|
+
subscriptions.set('turn_end', unsubTurnEnd);
|
|
60
|
+
const unsubAgentEnd = this.agentsService.addEventListener('agent_end', (data) => {
|
|
61
|
+
if (data.sessionId === sessionId)
|
|
62
|
+
client.emit('agent_end', data);
|
|
63
|
+
});
|
|
64
|
+
subscriptions.set('agent_end', unsubAgentEnd);
|
|
65
|
+
// 兼容:message_complete(turn_end 语义)、conversation_end(agent_end 语义)
|
|
55
66
|
const unsubComplete = this.agentsService.addEventListener('message_complete', (data) => {
|
|
56
|
-
|
|
57
|
-
if (data.sessionId === sessionId) {
|
|
67
|
+
if (data.sessionId === sessionId)
|
|
58
68
|
client.emit('message_complete', data);
|
|
59
|
-
}
|
|
60
69
|
});
|
|
61
70
|
subscriptions.set('complete', unsubComplete);
|
|
71
|
+
const unsubConversationEnd = this.agentsService.addEventListener('conversation_end', (data) => {
|
|
72
|
+
if (data.sessionId === sessionId)
|
|
73
|
+
client.emit('conversation_end', data);
|
|
74
|
+
});
|
|
75
|
+
subscriptions.set('conversation_end', unsubConversationEnd);
|
|
62
76
|
this.sessionSubscriptions.set(client.id, subscriptions);
|
|
63
77
|
return { success: true };
|
|
64
78
|
}
|
|
@@ -53,6 +53,8 @@ export declare class AgentsService {
|
|
|
53
53
|
}): Promise<AgentSession>;
|
|
54
54
|
getSessions(): AgentSession[];
|
|
55
55
|
getSession(sessionId: string): AgentSession | undefined;
|
|
56
|
+
/** 更新会话的当前 agent(同一 session 内切换 agent 时调用) */
|
|
57
|
+
updateSessionAgentId(sessionId: string, agentId: string): void;
|
|
56
58
|
deleteSession(sessionId: string): Promise<void>;
|
|
57
59
|
getMessageHistory(sessionId: string): ChatMessage[];
|
|
58
60
|
addAssistantMessage(sessionId: string, content: string): void;
|
|
@@ -60,4 +62,6 @@ export declare class AgentsService {
|
|
|
60
62
|
toolCalls?: any[];
|
|
61
63
|
contentParts?: any[];
|
|
62
64
|
}): void;
|
|
65
|
+
/** 清除会话的所有对话消息(保留会话本身,message_count 置 0) */
|
|
66
|
+
clearSessionMessages(sessionId: string): void;
|
|
63
67
|
}
|
|
@@ -134,12 +134,19 @@ let AgentsService = class AgentsService {
|
|
|
134
134
|
const r = this.db.get('SELECT * FROM sessions WHERE id = ?', [sessionId]);
|
|
135
135
|
return r ? this.rowToSession(r) : undefined;
|
|
136
136
|
}
|
|
137
|
+
/** 更新会话的当前 agent(同一 session 内切换 agent 时调用) */
|
|
138
|
+
updateSessionAgentId(sessionId, agentId) {
|
|
139
|
+
const session = this.getSession(sessionId);
|
|
140
|
+
if (!session)
|
|
141
|
+
return;
|
|
142
|
+
this.db.run('UPDATE sessions SET agent_id = ? WHERE id = ?', [agentId, sessionId]);
|
|
143
|
+
}
|
|
137
144
|
async deleteSession(sessionId) {
|
|
138
145
|
const result = this.db.run('DELETE FROM sessions WHERE id = ?', [sessionId]);
|
|
139
146
|
if (result.changes > 0) {
|
|
140
147
|
this.db.persist();
|
|
141
148
|
}
|
|
142
|
-
agentManager.
|
|
149
|
+
agentManager.deleteSessionsByBusinessId(sessionId);
|
|
143
150
|
}
|
|
144
151
|
getMessageHistory(sessionId) {
|
|
145
152
|
const rows = this.db.all('SELECT * FROM chat_messages WHERE session_id = ? ORDER BY timestamp ASC', [sessionId]);
|
|
@@ -161,6 +168,15 @@ let AgentsService = class AgentsService {
|
|
|
161
168
|
this.db.run(`INSERT INTO chat_messages (id, session_id, role, content, timestamp, tool_calls_json) VALUES (?, ?, ?, ?, ?, ?)`, [id, sessionId, role, content, now, toolCallsJson]);
|
|
162
169
|
this.db.run('UPDATE sessions SET last_active_at = ?, status = ?, message_count = message_count + 1 WHERE id = ?', [now, role === 'assistant' ? 'idle' : session.status, sessionId]);
|
|
163
170
|
}
|
|
171
|
+
/** 清除会话的所有对话消息(保留会话本身,message_count 置 0) */
|
|
172
|
+
clearSessionMessages(sessionId) {
|
|
173
|
+
const session = this.getSession(sessionId);
|
|
174
|
+
if (!session)
|
|
175
|
+
return;
|
|
176
|
+
this.db.run('DELETE FROM chat_messages WHERE session_id = ?', [sessionId]);
|
|
177
|
+
this.db.run('UPDATE sessions SET message_count = 0 WHERE id = ?', [sessionId]);
|
|
178
|
+
this.db.persist();
|
|
179
|
+
}
|
|
164
180
|
};
|
|
165
181
|
AgentsService = __decorate([
|
|
166
182
|
Injectable(),
|
|
@@ -26,6 +26,7 @@ export declare class ConfigController {
|
|
|
26
26
|
embeddingProvider?: string;
|
|
27
27
|
embeddingModel?: string;
|
|
28
28
|
};
|
|
29
|
+
channels?: import("../../core/config/desktop-config.js").ChannelsConfig;
|
|
29
30
|
};
|
|
30
31
|
}>;
|
|
31
32
|
updateConfig(updates: Partial<AppConfig>): Promise<{
|
|
@@ -52,6 +53,7 @@ export declare class ConfigController {
|
|
|
52
53
|
embeddingProvider?: string;
|
|
53
54
|
embeddingModel?: string;
|
|
54
55
|
};
|
|
56
|
+
channels?: import("../../core/config/desktop-config.js").ChannelsConfig;
|
|
55
57
|
};
|
|
56
58
|
}>;
|
|
57
59
|
getProviders(): Promise<{
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type ChannelsConfig } from '../../core/config/desktop-config.js';
|
|
1
2
|
import { AgentConfigService } from '../agent-config/agent-config.service.js';
|
|
2
3
|
/** 模型 cost 配置,写入 models.json;缺省均为 0 */
|
|
3
4
|
export interface ModelCost {
|
|
@@ -55,6 +56,8 @@ export interface AppConfig {
|
|
|
55
56
|
embeddingProvider?: string;
|
|
56
57
|
embeddingModel?: string;
|
|
57
58
|
};
|
|
59
|
+
/** 通道配置:飞书、Telegram 等 token/key */
|
|
60
|
+
channels?: ChannelsConfig;
|
|
58
61
|
}
|
|
59
62
|
export declare class ConfigService {
|
|
60
63
|
private readonly agentConfigService;
|
|
@@ -11,6 +11,7 @@ import { Injectable } from '@nestjs/common';
|
|
|
11
11
|
import { readFile, writeFile, mkdir } from 'fs/promises';
|
|
12
12
|
import { join } from 'path';
|
|
13
13
|
import { existsSync } from 'fs';
|
|
14
|
+
import { homedir } from 'os';
|
|
14
15
|
import { getProviderSupport, syncDesktopConfigToModelsJson } from '../../core/config/desktop-config.js';
|
|
15
16
|
import { AgentConfigService } from '../agent-config/agent-config.service.js';
|
|
16
17
|
let ConfigService = class ConfigService {
|
|
@@ -19,7 +20,7 @@ let ConfigService = class ConfigService {
|
|
|
19
20
|
config;
|
|
20
21
|
constructor(agentConfigService) {
|
|
21
22
|
this.agentConfigService = agentConfigService;
|
|
22
|
-
const homeDir = process.env.HOME || process.env.USERPROFILE ||
|
|
23
|
+
const homeDir = process.env.HOME || process.env.USERPROFILE || homedir();
|
|
23
24
|
const configDir = join(homeDir, '.openbot', 'desktop');
|
|
24
25
|
this.configPath = join(configDir, 'config.json');
|
|
25
26
|
// Ensure config directory exists
|
|
@@ -40,6 +41,7 @@ let ConfigService = class ConfigService {
|
|
|
40
41
|
providers: {},
|
|
41
42
|
configuredModels: [],
|
|
42
43
|
rag: undefined,
|
|
44
|
+
channels: {},
|
|
43
45
|
};
|
|
44
46
|
}
|
|
45
47
|
/** 当前缺省智能体 id */
|
|
@@ -1,11 +1,17 @@
|
|
|
1
|
+
import type { Response } from 'express';
|
|
1
2
|
import { SavedItemsService } from './saved-items.service.js';
|
|
3
|
+
import { WorkspaceService } from '../workspace/workspace.service.js';
|
|
4
|
+
import { ConfigService } from '../config/config.service.js';
|
|
2
5
|
export declare class SavedItemsController {
|
|
3
6
|
private readonly savedItemsService;
|
|
4
|
-
|
|
7
|
+
private readonly workspaceService;
|
|
8
|
+
private readonly configService;
|
|
9
|
+
constructor(savedItemsService: SavedItemsService, workspaceService: WorkspaceService, configService: ConfigService);
|
|
5
10
|
list(tagId?: string, workspace?: string): Promise<{
|
|
6
11
|
success: boolean;
|
|
7
12
|
data: import("./saved-items.service.js").SavedItem[];
|
|
8
13
|
}>;
|
|
14
|
+
imageProxy(url: string, res: Response): Promise<void>;
|
|
9
15
|
get(id: string): Promise<{
|
|
10
16
|
success: boolean;
|
|
11
17
|
data: import("./saved-items.service.js").SavedItem;
|
|
@@ -23,4 +29,29 @@ export declare class SavedItemsController {
|
|
|
23
29
|
delete(id: string): Promise<{
|
|
24
30
|
success: boolean;
|
|
25
31
|
}>;
|
|
32
|
+
/**
|
|
33
|
+
* Download the saved item URL to workspace .favorite or to a user-chosen directory.
|
|
34
|
+
* Body: { workspace?: string, targetDir?: string }.
|
|
35
|
+
* If targetDir (absolute path) is provided, file is written there; otherwise to workspace/.favorite.
|
|
36
|
+
*/
|
|
37
|
+
downloadToWorkspace(id: string, body: {
|
|
38
|
+
workspace?: string;
|
|
39
|
+
targetDir?: string;
|
|
40
|
+
}): Promise<{
|
|
41
|
+
success: boolean;
|
|
42
|
+
data: {
|
|
43
|
+
absolutePath: string;
|
|
44
|
+
targetDir: string;
|
|
45
|
+
relativePath?: undefined;
|
|
46
|
+
workspace?: undefined;
|
|
47
|
+
};
|
|
48
|
+
} | {
|
|
49
|
+
success: boolean;
|
|
50
|
+
data: {
|
|
51
|
+
relativePath: string;
|
|
52
|
+
workspace: string;
|
|
53
|
+
absolutePath?: undefined;
|
|
54
|
+
targetDir?: undefined;
|
|
55
|
+
};
|
|
56
|
+
}>;
|
|
26
57
|
}
|