@nocobase/plugin-ai 2.1.0-alpha.13 → 2.1.0-alpha.14
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/ai/ai-employees/atlas/index.d.ts +10 -0
- package/dist/ai/ai-employees/atlas/index.js +56 -0
- package/dist/ai/ai-employees/atlas/prompt.md +84 -0
- package/dist/ai/ai-employees/vera.js +1 -1
- package/dist/ai/tools/chartGenerator.js +1 -0
- package/dist/ai/tools/getSkill.js +1 -1
- package/dist/ai/tools/sub-agents/dispatch-sub-agent-task.d.ts +10 -0
- package/dist/ai/tools/sub-agents/dispatch-sub-agent-task.js +108 -0
- package/dist/ai/tools/sub-agents/get-ai-employee.d.ts +10 -0
- package/dist/ai/tools/sub-agents/get-ai-employee.js +67 -0
- package/dist/ai/tools/sub-agents/list-ai-employees.d.ts +10 -0
- package/dist/ai/tools/sub-agents/list-ai-employees.js +64 -0
- package/dist/ai/tools/sub-agents/shared.d.ts +33 -0
- package/dist/ai/tools/sub-agents/shared.js +169 -0
- package/dist/ai/tools/suggestions.js +2 -2
- package/dist/client/7237366e104efa7a.js +10 -0
- package/dist/client/748fbb87c1013c6e.js +10 -0
- package/dist/client/ai-employees/built-in/utils.d.ts +1 -0
- package/dist/client/ai-employees/chatbox/AIEmployeeSwitch.d.ts +0 -1
- package/dist/client/ai-employees/chatbox/hooks/useChatBoxActions.d.ts +5 -3
- package/dist/client/ai-employees/chatbox/roles.d.ts +1 -0
- package/dist/client/ai-employees/chatbox/stores/chat-messages.d.ts +8 -0
- package/dist/client/ai-employees/chatbox/utils.d.ts +15 -1
- package/dist/client/ai-employees/sub-agents/tools/index.d.ts +10 -0
- package/dist/client/ai-employees/sub-agents/ui/SubAgentDispatchCard.d.ts +21 -0
- package/dist/client/ai-employees/types.d.ts +19 -0
- package/dist/client/index.js +7 -7
- package/dist/externalVersion.js +16 -15
- package/dist/locale/en-US.json +10 -1
- package/dist/locale/zh-CN.json +10 -1
- package/dist/node_modules/fast-glob/package.json +1 -1
- package/dist/node_modules/flexsearch/package.json +1 -1
- package/dist/node_modules/fs-extra/package.json +1 -1
- package/dist/node_modules/nodejs-snowflake/package.json +1 -1
- package/dist/node_modules/openai/package.json +1 -1
- package/dist/node_modules/zod/package.json +1 -1
- package/dist/server/ai-employees/ai-conversations.d.ts +64 -0
- package/dist/server/ai-employees/ai-conversations.js +285 -0
- package/dist/server/ai-employees/ai-employee.d.ts +85 -9
- package/dist/server/ai-employees/ai-employee.js +264 -149
- package/dist/server/ai-employees/middleware/conversation.d.ts +2 -0
- package/dist/server/ai-employees/middleware/conversation.js +38 -5
- package/dist/server/ai-employees/middleware/tools.js +37 -10
- package/dist/server/ai-employees/prompts.d.ts +9 -1
- package/dist/server/ai-employees/prompts.js +24 -2
- package/dist/server/ai-employees/sub-agents/dispatcher.d.ts +36 -0
- package/dist/server/ai-employees/sub-agents/dispatcher.js +225 -0
- package/dist/server/ai-employees/sub-agents/index.d.ts +9 -0
- package/dist/server/ai-employees/sub-agents/index.js +36 -0
- package/dist/server/collections/ai-conversations.js +6 -0
- package/dist/server/llm-providers/anthropic.d.ts +1 -0
- package/dist/server/llm-providers/anthropic.js +2 -1
- package/dist/server/llm-providers/dashscope.d.ts +3 -0
- package/dist/server/llm-providers/dashscope.js +16 -2
- package/dist/server/llm-providers/deepseek.d.ts +1 -0
- package/dist/server/llm-providers/deepseek.js +5 -2
- package/dist/server/llm-providers/google-genai.d.ts +1 -0
- package/dist/server/llm-providers/google-genai.js +2 -1
- package/dist/server/llm-providers/kimi/provider.d.ts +1 -0
- package/dist/server/llm-providers/openai/responses.d.ts +1 -0
- package/dist/server/llm-providers/openai/responses.js +2 -1
- package/dist/server/llm-providers/provider.d.ts +1 -10
- package/dist/server/llm-providers/provider.js +3 -34
- package/dist/server/migrations/20260319000000-add-ai-conversations-from.d.ts +14 -0
- package/dist/server/migrations/20260319000000-add-ai-conversations-from.js +63 -0
- package/dist/server/plugin.d.ts +4 -0
- package/dist/server/plugin.js +4 -0
- package/dist/server/resource/aiConversations.d.ts +3 -3
- package/dist/server/resource/aiConversations.js +125 -159
- package/dist/server/types/ai-chat-conversation.type.d.ts +8 -2
- package/dist/server/types/ai-message.type.d.ts +7 -0
- package/dist/server/utils.d.ts +3 -0
- package/dist/server/utils.js +25 -1
- package/package.json +4 -2
- package/dist/client/27539a4356faebb1.js +0 -10
|
@@ -26,6 +26,8 @@ export declare const conversationMiddleware: (aiEmployee: AIEmployee, options: {
|
|
|
26
26
|
}, z.core.$strip>>;
|
|
27
27
|
}, z.core.$strip>, z.ZodObject<{
|
|
28
28
|
ctx: z.ZodAny;
|
|
29
|
+
appendMessage: z.ZodAny;
|
|
29
30
|
}, z.core.$strip>, {
|
|
30
31
|
ctx: any;
|
|
32
|
+
appendMessage: any;
|
|
31
33
|
}, readonly (import("@langchain/core/dist/tools").ClientTool | import("@langchain/core/dist/tools").ServerTool)[]>;
|
|
@@ -77,7 +77,8 @@ const conversationMiddleware = (aiEmployee, options) => {
|
|
|
77
77
|
return (0, import_langchain.createMiddleware)({
|
|
78
78
|
name: "ConversationMiddleware",
|
|
79
79
|
contextSchema: import_zod.default.object({
|
|
80
|
-
ctx: import_zod.default.any()
|
|
80
|
+
ctx: import_zod.default.any(),
|
|
81
|
+
appendMessage: import_zod.default.any()
|
|
81
82
|
}),
|
|
82
83
|
stateSchema: import_zod.default.object({
|
|
83
84
|
messageId: import_zod.default.coerce.string().optional(),
|
|
@@ -125,13 +126,28 @@ const conversationMiddleware = (aiEmployee, options) => {
|
|
|
125
126
|
toolMessages.map((x) => x.metadata.toolCallId)
|
|
126
127
|
);
|
|
127
128
|
});
|
|
128
|
-
|
|
129
|
+
const currentConversation = {
|
|
130
|
+
sessionId: aiEmployee.sessionId,
|
|
131
|
+
username: aiEmployee.employee.username,
|
|
132
|
+
from: aiEmployee.from
|
|
133
|
+
};
|
|
134
|
+
(_a = runtime.writer) == null ? void 0 : _a.call(runtime, {
|
|
135
|
+
action: "beforeSendToolMessage",
|
|
136
|
+
body: { messageId: messageId2, messages: toolMessages },
|
|
137
|
+
currentConversation
|
|
138
|
+
});
|
|
129
139
|
}
|
|
130
140
|
},
|
|
131
141
|
afterModel: async (state, runtime) => {
|
|
132
142
|
var _a, _b, _c, _d, _e, _f;
|
|
133
143
|
try {
|
|
144
|
+
const currentConversation = {
|
|
145
|
+
sessionId: aiEmployee.sessionId,
|
|
146
|
+
username: aiEmployee.employee.username,
|
|
147
|
+
from: aiEmployee.from
|
|
148
|
+
};
|
|
134
149
|
const newState = {
|
|
150
|
+
messageId: state.messageId,
|
|
135
151
|
lastMessageIndex: {
|
|
136
152
|
lastHumanMessageIndex: state.messages.filter((x) => x.type === "human").length,
|
|
137
153
|
lastAIMessageIndex: state.messages.filter((x) => x.type === "ai").length,
|
|
@@ -153,7 +169,7 @@ const conversationMiddleware = (aiEmployee, options) => {
|
|
|
153
169
|
if (values) {
|
|
154
170
|
await aiEmployee.aiChatConversation.withTransaction(async (conversation, transaction) => {
|
|
155
171
|
const result = await conversation.addMessages(values);
|
|
156
|
-
|
|
172
|
+
newState.messageId = result.messageId;
|
|
157
173
|
if (toolCalls == null ? void 0 : toolCalls.length) {
|
|
158
174
|
const toolsMap = await aiEmployee.getToolsMap();
|
|
159
175
|
const initializedToolCalls = await aiEmployee.initToolCall(
|
|
@@ -166,19 +182,36 @@ const conversationMiddleware = (aiEmployee, options) => {
|
|
|
166
182
|
});
|
|
167
183
|
(_b = runtime.writer) == null ? void 0 : _b.call(runtime, {
|
|
168
184
|
action: "AfterAIMessageSaved",
|
|
169
|
-
body: { id: aiMessage.id, messageId:
|
|
185
|
+
body: { id: aiMessage.id, messageId: newState.messageId },
|
|
186
|
+
currentConversation
|
|
170
187
|
});
|
|
171
188
|
}
|
|
172
189
|
if (toolCalls == null ? void 0 : toolCalls.length) {
|
|
173
190
|
(_c = runtime.writer) == null ? void 0 : _c.call(runtime, {
|
|
174
191
|
action: "initToolCalls",
|
|
175
|
-
body: { toolCalls }
|
|
192
|
+
body: { toolCalls },
|
|
193
|
+
currentConversation
|
|
176
194
|
});
|
|
177
195
|
}
|
|
178
196
|
return newState;
|
|
179
197
|
} catch (e) {
|
|
180
198
|
(_f = (_e = (_d = runtime.context) == null ? void 0 : _d.ctx) == null ? void 0 : _e.logger) == null ? void 0 : _f.error(e);
|
|
181
199
|
}
|
|
200
|
+
},
|
|
201
|
+
wrapModelCall: async (request, handler) => {
|
|
202
|
+
const runtimeContext = request.runtime.context;
|
|
203
|
+
const appendMessage = runtimeContext == null ? void 0 : runtimeContext.appendMessage;
|
|
204
|
+
if (Array.isArray(appendMessage) && appendMessage.length) {
|
|
205
|
+
await aiEmployee.aiChatConversation.withTransaction(async (conversation) => {
|
|
206
|
+
await conversation.addMessages(convertToolMessage(request.messages.at(-1)));
|
|
207
|
+
await conversation.addMessages(appendMessage.map((x) => x).map(convertHumanMessage));
|
|
208
|
+
});
|
|
209
|
+
request.messages.push(...appendMessage);
|
|
210
|
+
if (runtimeContext) {
|
|
211
|
+
delete runtimeContext.appendMessage;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return handler(request);
|
|
182
215
|
}
|
|
183
216
|
});
|
|
184
217
|
};
|
|
@@ -46,7 +46,16 @@ var import_lodash = __toESM(require("lodash"));
|
|
|
46
46
|
const toolInteractionMiddleware = (aiEmployee, tools) => {
|
|
47
47
|
const interruptOn = {};
|
|
48
48
|
for (const tool of tools) {
|
|
49
|
-
interruptOn[tool.definition.name] = aiEmployee.shouldInterruptToolCall(tool)
|
|
49
|
+
interruptOn[tool.definition.name] = aiEmployee.shouldInterruptToolCall(tool) ? {
|
|
50
|
+
allowedDecisions: ["approve", "reject", "edit"],
|
|
51
|
+
description: (toolCall) => JSON.stringify({
|
|
52
|
+
sessionId: aiEmployee.sessionId,
|
|
53
|
+
from: aiEmployee.from,
|
|
54
|
+
username: aiEmployee.employee.username,
|
|
55
|
+
toolCallId: toolCall.id,
|
|
56
|
+
toolCallName: toolCall.name
|
|
57
|
+
})
|
|
58
|
+
} : false;
|
|
50
59
|
}
|
|
51
60
|
return (0, import_langchain.humanInTheLoopMiddleware)({
|
|
52
61
|
interruptOn
|
|
@@ -60,13 +69,23 @@ const toolCallStatusMiddleware = (aiEmployee) => {
|
|
|
60
69
|
}),
|
|
61
70
|
wrapToolCall: async (request, handler) => {
|
|
62
71
|
var _a, _b, _c, _d;
|
|
72
|
+
let interrupted = false;
|
|
63
73
|
const { runtime, toolCall } = request;
|
|
64
74
|
const { messageId } = request.state;
|
|
75
|
+
const currentConversation = {
|
|
76
|
+
sessionId: aiEmployee.sessionId,
|
|
77
|
+
username: aiEmployee.employee.username,
|
|
78
|
+
from: aiEmployee.from
|
|
79
|
+
};
|
|
65
80
|
const tm = await aiEmployee.getToolCallResult(messageId, request.toolCall.id);
|
|
81
|
+
if (!tm) {
|
|
82
|
+
throw new Error(`Tool call result not found for messageId=${messageId}, toolCallId=${request.toolCall.id}`);
|
|
83
|
+
}
|
|
66
84
|
if (tm.status === "error") {
|
|
67
85
|
(_a = runtime.writer) == null ? void 0 : _a.call(runtime, {
|
|
68
86
|
action: "afterToolCall",
|
|
69
|
-
body: { toolCall, toolCallResult: tm }
|
|
87
|
+
body: { toolCall, toolCallResult: tm },
|
|
88
|
+
currentConversation
|
|
70
89
|
});
|
|
71
90
|
return new import_langchain.ToolMessage({
|
|
72
91
|
tool_call_id: request.toolCall.id,
|
|
@@ -78,7 +97,7 @@ const toolCallStatusMiddleware = (aiEmployee) => {
|
|
|
78
97
|
});
|
|
79
98
|
}
|
|
80
99
|
await aiEmployee.updateToolCallPending(messageId, request.toolCall.id);
|
|
81
|
-
(_b = runtime.writer) == null ? void 0 : _b.call(runtime, { action: "beforeToolCall", body: { toolCall } });
|
|
100
|
+
(_b = runtime.writer) == null ? void 0 : _b.call(runtime, { action: "beforeToolCall", body: { toolCall }, currentConversation });
|
|
82
101
|
let result;
|
|
83
102
|
try {
|
|
84
103
|
const toolMessage = await handler(request);
|
|
@@ -100,11 +119,16 @@ const toolCallStatusMiddleware = (aiEmployee) => {
|
|
|
100
119
|
}
|
|
101
120
|
return toolMessage;
|
|
102
121
|
} catch (e) {
|
|
122
|
+
if (e.name === "GraphInterrupt") {
|
|
123
|
+
interrupted = true;
|
|
124
|
+
throw e;
|
|
125
|
+
}
|
|
103
126
|
aiEmployee.logger.error(e);
|
|
104
127
|
result = { status: "error", content: e.message };
|
|
105
128
|
(_c = runtime.writer) == null ? void 0 : _c.call(runtime, {
|
|
106
129
|
action: "afterToolCallError",
|
|
107
|
-
body: { toolCall, error: e }
|
|
130
|
+
body: { toolCall, error: e },
|
|
131
|
+
currentConversation
|
|
108
132
|
});
|
|
109
133
|
return new import_langchain.ToolMessage({
|
|
110
134
|
tool_call_id: request.toolCall.id,
|
|
@@ -115,12 +139,15 @@ const toolCallStatusMiddleware = (aiEmployee) => {
|
|
|
115
139
|
}
|
|
116
140
|
});
|
|
117
141
|
} finally {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
142
|
+
if (!interrupted) {
|
|
143
|
+
await aiEmployee.updateToolCallDone(messageId, request.toolCall.id, result);
|
|
144
|
+
const toolCallResult = await aiEmployee.getToolCallResult(messageId, request.toolCall.id);
|
|
145
|
+
(_d = runtime.writer) == null ? void 0 : _d.call(runtime, {
|
|
146
|
+
action: "afterToolCall",
|
|
147
|
+
body: { toolCall, toolCallResult },
|
|
148
|
+
currentConversation
|
|
149
|
+
});
|
|
150
|
+
}
|
|
124
151
|
}
|
|
125
152
|
}
|
|
126
153
|
});
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
7
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
8
|
*/
|
|
9
|
-
export declare function getSystemPrompt({ aiEmployee, personal, task, environment, dataSources, knowledgeBase, availableSkills, }: {
|
|
9
|
+
export declare function getSystemPrompt({ aiEmployee, personal, task, environment, dataSources, knowledgeBase, availableSkills, availableAIEmployees, }: {
|
|
10
10
|
aiEmployee: {
|
|
11
11
|
nickname: string;
|
|
12
12
|
about: string;
|
|
@@ -27,4 +27,12 @@ export declare function getSystemPrompt({ aiEmployee, personal, task, environmen
|
|
|
27
27
|
description: string;
|
|
28
28
|
content?: string;
|
|
29
29
|
}[];
|
|
30
|
+
availableAIEmployees?: {
|
|
31
|
+
username: string;
|
|
32
|
+
nickname: string;
|
|
33
|
+
position: string;
|
|
34
|
+
bio: string;
|
|
35
|
+
greeting: string;
|
|
36
|
+
skillSettings: any;
|
|
37
|
+
}[];
|
|
30
38
|
}): string;
|
|
@@ -36,7 +36,8 @@ function getSystemPrompt({
|
|
|
36
36
|
environment,
|
|
37
37
|
dataSources,
|
|
38
38
|
knowledgeBase,
|
|
39
|
-
availableSkills
|
|
39
|
+
availableSkills,
|
|
40
|
+
availableAIEmployees
|
|
40
41
|
}) {
|
|
41
42
|
const getDatabaseQuotingRules = () => {
|
|
42
43
|
const quotingMap = {
|
|
@@ -138,12 +139,33 @@ ${task.context}
|
|
|
138
139
|
</environment>
|
|
139
140
|
|
|
140
141
|
${(availableSkills == null ? void 0 : availableSkills.length) ? `<skills>
|
|
141
|
-
You have access to the following skills (tools groups). When a user's request matches a skill's description, use the getSkill tool to load that skill's detailed content and available tools
|
|
142
|
+
You have access to the following skills (tools groups). When a user's request matches a skill's description, use the **getSkill** tool to load that skill's detailed content and available tools
|
|
142
143
|
|
|
143
144
|
${availableSkills.map((skill) => `- **${skill.name}**: ${skill.description || "No description"}`).join("\n")}
|
|
144
145
|
</skills>
|
|
145
146
|
` : ""}
|
|
146
147
|
|
|
148
|
+
${(availableAIEmployees == null ? void 0 : availableAIEmployees.length) ? `<sub_agents>
|
|
149
|
+
The following ${availableAIEmployees.length} AI employees are currently available as sub agents.
|
|
150
|
+
Treat this list as the authoritative routing roster for this conversation.
|
|
151
|
+
Do not call discovery tools just to confirm the same list again.
|
|
152
|
+
Only use discovery when this section is missing, clearly insufficient for the routing decision, contradictory to the current conversation, or you have strong evidence the roster has changed.
|
|
153
|
+
If one listed employee is already an obvious fit, dispatch directly.
|
|
154
|
+
Use profile lookup only when you need deeper instructions before dispatching.
|
|
155
|
+
|
|
156
|
+
${availableAIEmployees.map(
|
|
157
|
+
(it) => {
|
|
158
|
+
var _a, _b, _c, _d, _e, _f;
|
|
159
|
+
return `- ${it.nickname}
|
|
160
|
+
- username: ${it.username}
|
|
161
|
+
- description: ${it.bio}
|
|
162
|
+
- position: ${it.position}
|
|
163
|
+
${((_b = (_a = it.skillSettings) == null ? void 0 : _a.skills) == null ? void 0 : _b.length) ? "- skills:" + ((_c = it.skillSettings) == null ? void 0 : _c.skills.join(",")) : ""}
|
|
164
|
+
${((_e = (_d = it.skillSettings) == null ? void 0 : _d.tools) == null ? void 0 : _e.length) ? "- tools:" + ((_f = it.skillSettings) == null ? void 0 : _f.tools.map((t) => t.name).join(",")) : ""}`;
|
|
165
|
+
}
|
|
166
|
+
)}
|
|
167
|
+
</sub_agents>` : ""}
|
|
168
|
+
|
|
147
169
|
${knowledgeBase ? `<knowledgeBase>${knowledgeBase}</knowledgeBase>` : ""}
|
|
148
170
|
`;
|
|
149
171
|
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
import { Context } from '@nocobase/actions';
|
|
10
|
+
import { Model } from '@nocobase/database';
|
|
11
|
+
import { ModelRef } from '../ai-employee';
|
|
12
|
+
import type PluginAIServer from '../../plugin';
|
|
13
|
+
import type { UserDecision } from '../../types';
|
|
14
|
+
export type SubAgentTask = {
|
|
15
|
+
ctx: Context;
|
|
16
|
+
sessionId: string;
|
|
17
|
+
employee: Model;
|
|
18
|
+
model: ModelRef;
|
|
19
|
+
question: string;
|
|
20
|
+
skillSettings?: Record<string, any>;
|
|
21
|
+
writer?: (chunk: any) => void;
|
|
22
|
+
};
|
|
23
|
+
export declare class SubAgentsDispatcher {
|
|
24
|
+
protected plugin: PluginAIServer;
|
|
25
|
+
constructor(plugin: PluginAIServer);
|
|
26
|
+
private extractTextContent;
|
|
27
|
+
private extractLastMessageText;
|
|
28
|
+
private resolveSubAgentSessionId;
|
|
29
|
+
private resolveLastMessage;
|
|
30
|
+
run(task: SubAgentTask): Promise<string>;
|
|
31
|
+
isInterrupted(ctx: Context): Promise<boolean>;
|
|
32
|
+
reject(ctx: Context): Promise<{
|
|
33
|
+
interruptId?: string;
|
|
34
|
+
decisions: UserDecision[];
|
|
35
|
+
}>;
|
|
36
|
+
}
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
var __defProp = Object.defineProperty;
|
|
11
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
12
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
13
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
14
|
+
var __export = (target, all) => {
|
|
15
|
+
for (var name in all)
|
|
16
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
17
|
+
};
|
|
18
|
+
var __copyProps = (to, from, except, desc) => {
|
|
19
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
20
|
+
for (let key of __getOwnPropNames(from))
|
|
21
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
22
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
23
|
+
}
|
|
24
|
+
return to;
|
|
25
|
+
};
|
|
26
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
27
|
+
var dispatcher_exports = {};
|
|
28
|
+
__export(dispatcher_exports, {
|
|
29
|
+
SubAgentsDispatcher: () => SubAgentsDispatcher
|
|
30
|
+
});
|
|
31
|
+
module.exports = __toCommonJS(dispatcher_exports);
|
|
32
|
+
var import_ai_employee = require("../ai-employee");
|
|
33
|
+
class SubAgentsDispatcher {
|
|
34
|
+
constructor(plugin) {
|
|
35
|
+
this.plugin = plugin;
|
|
36
|
+
}
|
|
37
|
+
extractTextContent(content) {
|
|
38
|
+
if (typeof content === "string") {
|
|
39
|
+
return content;
|
|
40
|
+
}
|
|
41
|
+
if (Array.isArray(content)) {
|
|
42
|
+
return content.map((block) => {
|
|
43
|
+
if (typeof block === "string") {
|
|
44
|
+
return block;
|
|
45
|
+
}
|
|
46
|
+
if (block && typeof block === "object" && "type" in block && block.type === "text") {
|
|
47
|
+
return typeof block.text === "string" ? block.text : "";
|
|
48
|
+
}
|
|
49
|
+
return "";
|
|
50
|
+
}).join("");
|
|
51
|
+
}
|
|
52
|
+
if (content && typeof content === "object" && "content" in content) {
|
|
53
|
+
return this.extractTextContent(content.content);
|
|
54
|
+
}
|
|
55
|
+
return "";
|
|
56
|
+
}
|
|
57
|
+
extractLastMessageText(result) {
|
|
58
|
+
var _a;
|
|
59
|
+
const messages = result == null ? void 0 : result.messages;
|
|
60
|
+
if (!Array.isArray(messages) || messages.length === 0) {
|
|
61
|
+
return "";
|
|
62
|
+
}
|
|
63
|
+
return this.extractTextContent((_a = messages.at(-1)) == null ? void 0 : _a.content);
|
|
64
|
+
}
|
|
65
|
+
async resolveSubAgentSessionId(ctx) {
|
|
66
|
+
var _a, _b, _c, _d, _e;
|
|
67
|
+
const sessionId = (_c = (_b = (_a = ctx.action) == null ? void 0 : _a.params) == null ? void 0 : _b.values) == null ? void 0 : _c.sessionId;
|
|
68
|
+
if (!sessionId) {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
const aiToolMessage = await ctx.db.getRepository("aiToolMessages").findOne({
|
|
72
|
+
filter: {
|
|
73
|
+
sessionId,
|
|
74
|
+
toolName: "dispatch-sub-agent-task",
|
|
75
|
+
invokeStatus: {
|
|
76
|
+
$ne: "confirmed"
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
sort: ["-id"]
|
|
80
|
+
});
|
|
81
|
+
if (!(aiToolMessage == null ? void 0 : aiToolMessage.messageId)) {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
const aiMessage = await ctx.db.getRepository("aiMessages").findOne({
|
|
85
|
+
filter: {
|
|
86
|
+
sessionId,
|
|
87
|
+
messageId: aiToolMessage.messageId
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
const subAgentConversations = (_d = aiMessage == null ? void 0 : aiMessage.metadata) == null ? void 0 : _d.subAgentConversations;
|
|
91
|
+
if (!Array.isArray(subAgentConversations) || !subAgentConversations.length) {
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
return ((_e = subAgentConversations.at(-1)) == null ? void 0 : _e.sessionId) ?? null;
|
|
95
|
+
}
|
|
96
|
+
async resolveLastMessage(ctx) {
|
|
97
|
+
const subSessionId = await this.resolveSubAgentSessionId(ctx);
|
|
98
|
+
if (!subSessionId) {
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
return ctx.db.getRepository("aiMessages").findOne({
|
|
102
|
+
filter: {
|
|
103
|
+
sessionId: subSessionId
|
|
104
|
+
},
|
|
105
|
+
sort: ["-messageId"]
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
async run(task) {
|
|
109
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
110
|
+
const { ctx, sessionId, employee, model, question, skillSettings, writer } = task;
|
|
111
|
+
const { webSearch } = ((_b = (_a = ctx.action) == null ? void 0 : _a.params) == null ? void 0 : _b.values) ?? {};
|
|
112
|
+
const plugin = ctx.app.pm.get("ai");
|
|
113
|
+
const userId = (_d = (_c = ctx.auth) == null ? void 0 : _c.user) == null ? void 0 : _d.id;
|
|
114
|
+
if (!userId) {
|
|
115
|
+
throw new Error("User not authenticated");
|
|
116
|
+
}
|
|
117
|
+
if (!(model == null ? void 0 : model.llmService) || !(model == null ? void 0 : model.model)) {
|
|
118
|
+
throw new Error("LLM service not configured");
|
|
119
|
+
}
|
|
120
|
+
const aiEmployee = new import_ai_employee.AIEmployee({
|
|
121
|
+
ctx,
|
|
122
|
+
employee,
|
|
123
|
+
sessionId,
|
|
124
|
+
skillSettings,
|
|
125
|
+
webSearch,
|
|
126
|
+
model,
|
|
127
|
+
from: "sub-agent"
|
|
128
|
+
});
|
|
129
|
+
const lastMessage = await ctx.db.getRepository("aiMessages").findOne({
|
|
130
|
+
filter: {
|
|
131
|
+
sessionId
|
|
132
|
+
},
|
|
133
|
+
sort: ["-messageId"]
|
|
134
|
+
});
|
|
135
|
+
const decisions = lastMessage ? await plugin.aiConversationsManager.getUserDecisions(lastMessage.messageId) : null;
|
|
136
|
+
let context;
|
|
137
|
+
const { messages } = ((_f = (_e = ctx.action) == null ? void 0 : _e.params) == null ? void 0 : _f.values) ?? {};
|
|
138
|
+
if (messages && ((_g = decisions == null ? void 0 : decisions.decisions) == null ? void 0 : _g.some((it) => it.type === "reject"))) {
|
|
139
|
+
context = {
|
|
140
|
+
appendMessage: await aiEmployee.getFormatMessages(messages)
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
const result = await aiEmployee.invoke({
|
|
144
|
+
userDecisions: decisions,
|
|
145
|
+
userMessages: decisions ? void 0 : [
|
|
146
|
+
{
|
|
147
|
+
role: "user",
|
|
148
|
+
content: {
|
|
149
|
+
type: "text",
|
|
150
|
+
content: question
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
],
|
|
154
|
+
writer,
|
|
155
|
+
context
|
|
156
|
+
});
|
|
157
|
+
writer == null ? void 0 : writer({
|
|
158
|
+
action: "afterSubAgentInvoke",
|
|
159
|
+
body: {},
|
|
160
|
+
currentConversation: {
|
|
161
|
+
sessionId,
|
|
162
|
+
username: employee.username,
|
|
163
|
+
from: "sub-agent"
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
return this.extractLastMessageText(result);
|
|
167
|
+
}
|
|
168
|
+
async isInterrupted(ctx) {
|
|
169
|
+
var _a, _b, _c;
|
|
170
|
+
const sessionId = (_c = (_b = (_a = ctx.action) == null ? void 0 : _a.params) == null ? void 0 : _b.values) == null ? void 0 : _c.sessionId;
|
|
171
|
+
if (!sessionId) {
|
|
172
|
+
return false;
|
|
173
|
+
}
|
|
174
|
+
const aiToolMessage = await ctx.db.getRepository("aiToolMessages").findOne({
|
|
175
|
+
filter: {
|
|
176
|
+
sessionId,
|
|
177
|
+
toolName: "dispatch-sub-agent-task",
|
|
178
|
+
invokeStatus: "pending"
|
|
179
|
+
},
|
|
180
|
+
sort: ["-id"]
|
|
181
|
+
});
|
|
182
|
+
return aiToolMessage ? true : false;
|
|
183
|
+
}
|
|
184
|
+
async reject(ctx) {
|
|
185
|
+
var _a, _b, _c;
|
|
186
|
+
const plugin = ctx.app.pm.get("ai");
|
|
187
|
+
const { sessionId } = ((_b = (_a = ctx.action) == null ? void 0 : _a.params) == null ? void 0 : _b.values) ?? {};
|
|
188
|
+
const conversation = await ctx.db.getRepository("aiConversations").findOne({
|
|
189
|
+
filter: {
|
|
190
|
+
sessionId,
|
|
191
|
+
userId: (_c = ctx.auth) == null ? void 0 : _c.user.id
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
if (!conversation) {
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
const lastMessage = await this.resolveLastMessage(ctx);
|
|
198
|
+
if (!sessionId || !lastMessage) {
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
const userDecision = {
|
|
202
|
+
type: "reject",
|
|
203
|
+
message: `The user ignored the tools usage and send new messages`
|
|
204
|
+
};
|
|
205
|
+
const [updated] = await ctx.db.getRepository("aiToolMessages").model.update(
|
|
206
|
+
{ userDecision, invokeStatus: "waiting" },
|
|
207
|
+
{
|
|
208
|
+
where: {
|
|
209
|
+
sessionId: lastMessage.get("sessionId"),
|
|
210
|
+
messageId: lastMessage.get("messageId"),
|
|
211
|
+
invokeStatus: "interrupted"
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
);
|
|
215
|
+
if (updated > 0) {
|
|
216
|
+
return await plugin.aiConversationsManager.getUserDecisions(lastMessage.get("messageId"));
|
|
217
|
+
} else {
|
|
218
|
+
return null;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
223
|
+
0 && (module.exports = {
|
|
224
|
+
SubAgentsDispatcher
|
|
225
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
export { SubAgentsDispatcher } from './dispatcher';
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
var __defProp = Object.defineProperty;
|
|
11
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
12
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
13
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
14
|
+
var __export = (target, all) => {
|
|
15
|
+
for (var name in all)
|
|
16
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
17
|
+
};
|
|
18
|
+
var __copyProps = (to, from, except, desc) => {
|
|
19
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
20
|
+
for (let key of __getOwnPropNames(from))
|
|
21
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
22
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
23
|
+
}
|
|
24
|
+
return to;
|
|
25
|
+
};
|
|
26
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
27
|
+
var sub_agents_exports = {};
|
|
28
|
+
__export(sub_agents_exports, {
|
|
29
|
+
SubAgentsDispatcher: () => import_dispatcher.SubAgentsDispatcher
|
|
30
|
+
});
|
|
31
|
+
module.exports = __toCommonJS(sub_agents_exports);
|
|
32
|
+
var import_dispatcher = require("./dispatcher");
|
|
33
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
34
|
+
0 && (module.exports = {
|
|
35
|
+
SubAgentsDispatcher
|
|
36
|
+
});
|
|
@@ -50,6 +50,12 @@ var ai_conversations_default = (0, import_database.defineCollection)({
|
|
|
50
50
|
name: "topicId",
|
|
51
51
|
type: "string"
|
|
52
52
|
},
|
|
53
|
+
{
|
|
54
|
+
name: "from",
|
|
55
|
+
type: "string",
|
|
56
|
+
defaultValue: "main-agent",
|
|
57
|
+
allowNull: false
|
|
58
|
+
},
|
|
53
59
|
{
|
|
54
60
|
name: "user",
|
|
55
61
|
type: "belongsTo",
|
|
@@ -116,7 +116,7 @@ class AnthropicProvider extends import_provider.LLMProvider {
|
|
|
116
116
|
}
|
|
117
117
|
}
|
|
118
118
|
parseResponseMessage(message) {
|
|
119
|
-
const { content: rawContent, messageId, metadata, role, toolCalls, attachments, workContext } = message;
|
|
119
|
+
const { content: rawContent, messageId, metadata, role, toolCalls, attachments, workContext, createdAt } = message;
|
|
120
120
|
const content = {
|
|
121
121
|
...rawContent,
|
|
122
122
|
messageId,
|
|
@@ -149,6 +149,7 @@ class AnthropicProvider extends import_provider.LLMProvider {
|
|
|
149
149
|
}
|
|
150
150
|
return {
|
|
151
151
|
key: messageId,
|
|
152
|
+
createdAt,
|
|
152
153
|
content,
|
|
153
154
|
role
|
|
154
155
|
};
|
|
@@ -17,8 +17,11 @@ export declare class DashscopeProvider extends LLMProvider {
|
|
|
17
17
|
chatModel: ReasoningChatOpenAI;
|
|
18
18
|
get baseURL(): string;
|
|
19
19
|
createModel(): ReasoningChatOpenAI;
|
|
20
|
+
isToolConflict(): boolean;
|
|
21
|
+
resolveTools(toolDefinitions: any[]): any[];
|
|
20
22
|
parseResponseMessage(message: Model): {
|
|
21
23
|
key: any;
|
|
24
|
+
createdAt: any;
|
|
22
25
|
content: any;
|
|
23
26
|
role: any;
|
|
24
27
|
};
|
|
@@ -57,7 +57,9 @@ class DashscopeProvider extends import_provider.LLMProvider {
|
|
|
57
57
|
const { baseURL, apiKey } = this.serviceOptions || {};
|
|
58
58
|
const { responseFormat, structuredOutput } = this.modelOptions || {};
|
|
59
59
|
const { schema } = structuredOutput || {};
|
|
60
|
-
const modelKwargs = {
|
|
60
|
+
const modelKwargs = {
|
|
61
|
+
thinking_budget: 4e4
|
|
62
|
+
};
|
|
61
63
|
if (responseFormat) {
|
|
62
64
|
const responseFormatOptions = {
|
|
63
65
|
type: responseFormat
|
|
@@ -71,10 +73,11 @@ class DashscopeProvider extends import_provider.LLMProvider {
|
|
|
71
73
|
}
|
|
72
74
|
if (((_b = (_a = this.modelOptions) == null ? void 0 : _a.builtIn) == null ? void 0 : _b.webSearch) === true) {
|
|
73
75
|
modelKwargs["enable_search"] = true;
|
|
74
|
-
modelKwargs["search_options"] = { forced_search: true };
|
|
75
76
|
}
|
|
76
77
|
return new import_reasoning.ReasoningChatOpenAI({
|
|
77
78
|
apiKey,
|
|
79
|
+
topP: 0.8,
|
|
80
|
+
temperature: 0.7,
|
|
78
81
|
...this.modelOptions,
|
|
79
82
|
modelKwargs,
|
|
80
83
|
configuration: {
|
|
@@ -83,6 +86,17 @@ class DashscopeProvider extends import_provider.LLMProvider {
|
|
|
83
86
|
verbose: false
|
|
84
87
|
});
|
|
85
88
|
}
|
|
89
|
+
isToolConflict() {
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
resolveTools(toolDefinitions) {
|
|
93
|
+
var _a, _b;
|
|
94
|
+
if (this.isToolConflict() && ((_b = (_a = this.modelOptions) == null ? void 0 : _a.builtIn) == null ? void 0 : _b.webSearch) === true) {
|
|
95
|
+
return [];
|
|
96
|
+
} else {
|
|
97
|
+
return toolDefinitions;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
86
100
|
parseResponseMessage(message) {
|
|
87
101
|
var _a;
|
|
88
102
|
const result = super.parseResponseMessage(message);
|