@nocobase/plugin-ai 2.0.0-alpha.25 → 2.0.0-alpha.27

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.
Files changed (37) hide show
  1. package/dist/client/ai-employees/flow/index.d.ts +2 -0
  2. package/dist/client/ai-employees/flow/models/AIEmployeeShortcutModel.d.ts +6 -0
  3. package/dist/client/ai-employees/types.d.ts +1 -0
  4. package/dist/client/index.js +1 -1
  5. package/dist/externalVersion.js +11 -11
  6. package/dist/locale/en-US.json +7 -1
  7. package/dist/locale/zh-CN.json +7 -1
  8. package/dist/node_modules/@langchain/anthropic/package.json +1 -1
  9. package/dist/node_modules/@langchain/core/package.json +1 -1
  10. package/dist/node_modules/@langchain/deepseek/package.json +1 -1
  11. package/dist/node_modules/@langchain/google-genai/package.json +1 -1
  12. package/dist/node_modules/@langchain/ollama/package.json +1 -1
  13. package/dist/node_modules/@langchain/openai/package.json +1 -1
  14. package/dist/node_modules/nodejs-snowflake/package.json +1 -1
  15. package/dist/node_modules/zod/package.json +1 -1
  16. package/dist/node_modules/zod-to-json-schema/package.json +1 -1
  17. package/dist/server/ai-employees/built-in/ai-coding/index.js +8 -0
  18. package/dist/server/ai-employees/built-in/data-modeling/index.js +8 -0
  19. package/dist/server/ai-employees/built-in/data-organizer/index.js +8 -0
  20. package/dist/server/ai-employees/built-in/form-filler/index.js +13 -1
  21. package/dist/server/ai-employees/built-in/insights-analyst/index.js +8 -0
  22. package/dist/server/ai-employees/built-in/nocobase-assistant/index.d.ts +4 -1
  23. package/dist/server/ai-employees/built-in/nocobase-assistant/index.js +10 -1
  24. package/dist/server/ai-employees/built-in/research-analyst/index.js +8 -0
  25. package/dist/server/ai-employees/built-in/translator/index.js +8 -0
  26. package/dist/server/manager/ai-chat-conversation.js +4 -4
  27. package/dist/server/manager/ai-context-datasource-manager.d.ts +5 -1
  28. package/dist/server/manager/ai-context-datasource-manager.js +10 -2
  29. package/dist/server/plugin.js +15 -0
  30. package/dist/server/resource/aiEmployees.d.ts +1 -0
  31. package/dist/server/resource/aiEmployees.js +19 -0
  32. package/dist/server/tools/datasource-query.d.ts +11 -0
  33. package/dist/server/tools/datasource-query.js +133 -0
  34. package/dist/server/utils.js +2 -2
  35. package/package.json +2 -2
  36. /package/dist/server/migrations/{20250923221104-setup-build-in.d.ts → 20250923221106-setup-build-in.d.ts} +0 -0
  37. /package/dist/server/migrations/{20250923221104-setup-build-in.js → 20250923221106-setup-build-in.js} +0 -0
@@ -141,14 +141,14 @@ class AIChatConversationImpl {
141
141
  };
142
142
  }
143
143
  async formatMessages(messages, options) {
144
- var _a, _b, _c;
144
+ var _a, _b, _c, _d;
145
145
  const formattedMessages = [];
146
146
  const { provider, workContextHandler } = options;
147
147
  for (const msg of messages) {
148
148
  const attachments = msg.attachments;
149
149
  const workContext = msg.workContext;
150
- let content = msg.content.content;
151
- if (!content && !attachments && !((_a = msg.toolCalls) == null ? void 0 : _a.length)) {
150
+ let content = (_a = msg.content) == null ? void 0 : _a.content;
151
+ if (!content && !attachments && !((_b = msg.toolCalls) == null ? void 0 : _b.length)) {
152
152
  continue;
153
153
  }
154
154
  if (msg.role === "user") {
@@ -182,7 +182,7 @@ class AIChatConversationImpl {
182
182
  formattedMessages.push({
183
183
  role: "tool",
184
184
  content,
185
- tool_call_id: (_c = (_b = msg.metadata) == null ? void 0 : _b.toolCall) == null ? void 0 : _c.id
185
+ tool_call_id: (_d = (_c = msg.metadata) == null ? void 0 : _c.toolCall) == null ? void 0 : _d.id
186
186
  });
187
187
  continue;
188
188
  }
@@ -15,15 +15,19 @@ export declare class AIContextDatasourceManager {
15
15
  protected plugin: PluginAIServer;
16
16
  constructor(plugin: PluginAIServer);
17
17
  preview(ctx: Context, options: PreviewOptions): Promise<QueryResult | null>;
18
+ query(ctx: Context, options: InnerQueryOptions): Promise<QueryResult | null>;
18
19
  provideWorkContextResolveStrategy(): WorkContextResolveStrategy;
19
20
  private innerQuery;
20
21
  }
21
- export type PreviewOptions = Pick<AIContextDatasource, 'datasource' | 'collectionName' | 'fields' | 'appends' | 'filter' | 'sort' | 'limit'>;
22
+ export type PreviewOptions = Pick<AIContextDatasource, 'datasource' | 'collectionName' | 'fields' | 'appends' | 'filter' | 'sort' | 'limit'> & {
23
+ offset?: number;
24
+ };
22
25
  export type QueryOptions = {
23
26
  id: string;
24
27
  };
25
28
  export type QueryResult = {
26
29
  options: InnerQueryOptions;
30
+ total: number;
27
31
  records: {
28
32
  name: string;
29
33
  type: string;
@@ -37,6 +37,9 @@ class AIContextDatasourceManager {
37
37
  async preview(ctx, options) {
38
38
  return await this.innerQuery(ctx, { ...options, filter: options.filter ? (0, import_utils.transformFilter)(options.filter) : null });
39
39
  }
40
+ async query(ctx, options) {
41
+ return await this.innerQuery(ctx, { ...options, filter: options.filter });
42
+ }
40
43
  provideWorkContextResolveStrategy() {
41
44
  return async (ctx, contextItem) => {
42
45
  if (!contextItem.content) {
@@ -57,6 +60,7 @@ class AIContextDatasourceManager {
57
60
  this.plugin.log.warn(`Datasource ${datasource} not found`);
58
61
  return {
59
62
  options,
63
+ total: 0,
60
64
  records: []
61
65
  };
62
66
  }
@@ -65,6 +69,7 @@ class AIContextDatasourceManager {
65
69
  this.plugin.log.warn(`Collection ${collectionName} not found`);
66
70
  return {
67
71
  options,
72
+ total: 0,
68
73
  records: []
69
74
  };
70
75
  }
@@ -78,6 +83,7 @@ class AIContextDatasourceManager {
78
83
  if (!can || typeof can !== "object") {
79
84
  return {
80
85
  options,
86
+ total: 0,
81
87
  records: []
82
88
  };
83
89
  }
@@ -113,8 +119,9 @@ class AIContextDatasourceManager {
113
119
  }
114
120
  });
115
121
  }
116
- const { fields, filter, sort, limit } = options;
117
- const result = await collection.repository.find({ fields, filter, sort, limit });
122
+ const { fields, filter, sort, offset, limit } = options;
123
+ const result = await collection.repository.find({ fields, filter, sort, offset: offset ?? 0, limit });
124
+ const total = await collection.repository.count({ fields, filter });
118
125
  const records = result.map(
119
126
  (x) => fields.map((field) => {
120
127
  var _a2;
@@ -129,6 +136,7 @@ class AIContextDatasourceManager {
129
136
  );
130
137
  return {
131
138
  options,
139
+ total,
132
140
  records
133
141
  };
134
142
  }
@@ -66,6 +66,7 @@ var import_aiContextDatasources = require("./resource/aiContextDatasources");
66
66
  var import_work_context_handler = require("./manager/work-context-handler");
67
67
  var import_ai_coding_manager = require("./manager/ai-coding-manager");
68
68
  var import_code_editor = require("./tools/code-editor");
69
+ var import_datasource_query = require("./tools/datasource-query");
69
70
  class PluginAIServer extends import_server.Plugin {
70
71
  features = new import_ai_feature_manager.AIPluginFeatureManagerImpl();
71
72
  aiManager = new import_ai_manager.AIManager(this);
@@ -111,6 +112,7 @@ class PluginAIServer extends import_server.Plugin {
111
112
  const dataModelingGroupName = "dataModeling";
112
113
  const workflowGroupName = "workflowCaller";
113
114
  const codeEditorGroupName = "codeEditor";
115
+ const dataSourceGroupName = "dataSource";
114
116
  toolManager.registerToolGroup({
115
117
  groupName: frontendGroupName,
116
118
  title: '{{t("Frontend")}}',
@@ -131,6 +133,11 @@ class PluginAIServer extends import_server.Plugin {
131
133
  title: '{{t("CodeEditor")}}',
132
134
  description: '{{t("CodeEditor actions")}}'
133
135
  });
136
+ toolManager.registerToolGroup({
137
+ groupName: dataSourceGroupName,
138
+ title: '{{t("DataSource")}}',
139
+ description: '{{t("Data source query")}}'
140
+ });
134
141
  this.aiManager.toolManager.registerTools([
135
142
  {
136
143
  groupName: frontendGroupName,
@@ -162,6 +169,14 @@ class PluginAIServer extends import_server.Plugin {
162
169
  {
163
170
  groupName: codeEditorGroupName,
164
171
  tool: import_code_editor.getCodeSnippet
172
+ },
173
+ {
174
+ groupName: dataSourceGroupName,
175
+ tool: import_datasource_query.dataSourceCounting
176
+ },
177
+ {
178
+ groupName: dataSourceGroupName,
179
+ tool: import_datasource_query.dataSourceQuery
165
180
  }
166
181
  ]);
167
182
  toolManager.registerDynamicTool({
@@ -8,6 +8,7 @@
8
8
  */
9
9
  import { Context, Next } from '@nocobase/actions';
10
10
  export declare const list: (ctx: Context, next: Next) => Promise<void>;
11
+ export declare const create: (ctx: Context, next: Next) => Promise<void>;
11
12
  export declare const listByUser: (ctx: Context, next: Next) => Promise<any>;
12
13
  export declare const updateUserPrompt: (ctx: Context, next: Next) => Promise<any>;
13
14
  export declare const getTemplates: (ctx: Context, next: Next) => Promise<void>;
@@ -36,6 +36,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
36
36
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
37
37
  var aiEmployees_exports = {};
38
38
  __export(aiEmployees_exports, {
39
+ create: () => create,
39
40
  getTemplates: () => getTemplates,
40
41
  list: () => list,
41
42
  listByUser: () => listByUser,
@@ -44,6 +45,7 @@ __export(aiEmployees_exports, {
44
45
  module.exports = __toCommonJS(aiEmployees_exports);
45
46
  var import_actions = __toESM(require("@nocobase/actions"));
46
47
  var templates = __toESM(require("../ai-employees/templates"));
48
+ var import_lodash = __toESM(require("lodash"));
47
49
  const list = async (ctx, next) => {
48
50
  const { paginate } = ctx.action.params || {};
49
51
  const plugin = ctx.app.pm.get("ai");
@@ -62,6 +64,22 @@ const list = async (ctx, next) => {
62
64
  });
63
65
  await next();
64
66
  };
67
+ const create = async (ctx, next) => {
68
+ const { skillSettings } = ctx.action.params.values ?? {};
69
+ const skills = skillSettings.skills ?? [];
70
+ skills.push(
71
+ {
72
+ name: "dataSource-dataSourceCounting",
73
+ autoCall: true
74
+ },
75
+ {
76
+ name: "dataSource-dataSourceQuery",
77
+ autoCall: true
78
+ }
79
+ );
80
+ skillSettings.skills = import_lodash.default.uniqBy(skills, "name");
81
+ await import_actions.default.create(ctx, next);
82
+ };
65
83
  const listByUser = async (ctx, next) => {
66
84
  const plugin = ctx.app.pm.get("ai");
67
85
  const user = ctx.auth.user;
@@ -168,6 +186,7 @@ const getTemplates = async (ctx, next) => {
168
186
  };
169
187
  // Annotate the CommonJS export names for ESM import in node:
170
188
  0 && (module.exports = {
189
+ create,
171
190
  getTemplates,
172
191
  list,
173
192
  listByUser,
@@ -0,0 +1,11 @@
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 { ToolOptions } from '../manager/tool-manager';
10
+ export declare const dataSourceQuery: ToolOptions;
11
+ export declare const dataSourceCounting: ToolOptions;
@@ -0,0 +1,133 @@
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 datasource_query_exports = {};
28
+ __export(datasource_query_exports, {
29
+ dataSourceCounting: () => dataSourceCounting,
30
+ dataSourceQuery: () => dataSourceQuery
31
+ });
32
+ module.exports = __toCommonJS(datasource_query_exports);
33
+ var import_zod = require("zod");
34
+ const ArgSchema = import_zod.z.object({
35
+ datasource: import_zod.z.string().describe('{{t("Data source key")}}'),
36
+ collectionName: import_zod.z.string().describe('{{t("Collection name")}}'),
37
+ fields: import_zod.z.array(import_zod.z.string()).describe('{{t("Fields to be queried")}}'),
38
+ appends: import_zod.z.array(import_zod.z.string()).describe('{{t("Related collection to be queried")}}'),
39
+ filter: import_zod.z.object({}).catchall(import_zod.z.any()).describe(`# Parameters definition
40
+ \`\`\`
41
+ export type QueryCondition = {
42
+ [field: string]: { // \`field\` key is Field name
43
+ [operator: string]: any; // \`operator\` key is Query condition operator.
44
+ };
45
+ };
46
+
47
+
48
+ export type QueryObject =
49
+ | {
50
+ [logic: string]: (QueryCondition | QueryObject)[]; // \`logic\` key is the relationship between query conditions, should be one of '$and', '$or', the value is recursion object array, item in array can be QueryCondition or QueryObject
51
+ }
52
+ | QueryCondition // QueryCondition definition above;
53
+ \`\`\`
54
+
55
+
56
+ // QueryCondition examples
57
+
58
+ \`\`\`
59
+ const example1: QueryCondition = {
60
+ age: { $gt: 18 }, // age great than 18
61
+ name: { $like: '%John%' }, // name include John
62
+ };
63
+
64
+ const example2: QueryCondition = {
65
+ status: { $in: ['active', 'pending'] }, // status is active or pending
66
+ };
67
+ \`\`\`
68
+
69
+ // QueryObject example
70
+ \`\`\`
71
+ const example1: QueryObject = {
72
+ $and: [
73
+ { age: { $gt: 18 } },
74
+ { status: { $eq: 'active' } }
75
+ ]
76
+ };
77
+
78
+ const example2: QueryObject = {
79
+ $or: [
80
+ { name: { $like: '%John%' } },
81
+ {
82
+ $and: [
83
+ { age: { $gte: 30 } },
84
+ { status: { $eq: 'pending' } }
85
+ ]
86
+ }
87
+ ]
88
+ };
89
+
90
+ const example3: QueryObject = { age: { $lt: 50 } };
91
+ \`\`\`
92
+ `),
93
+ sort: import_zod.z.array(import_zod.z.string()).describe(
94
+ '{{t("Sort field names. By default, they are in ascending order. A minus sign before the field name indicates descending order")}}'
95
+ ),
96
+ offset: import_zod.z.number().describe('{{t("Offset of records to be queried")}}'),
97
+ limit: import_zod.z.number().describe('{{t("Maximum number of records to be queried")}}')
98
+ });
99
+ const dataSourceQuery = {
100
+ name: "dataSourceQuery",
101
+ title: '{{t("Data source query")}}',
102
+ description: '{{t("Use dataSource, collectionName, and collection fields to query data from the database")}}',
103
+ schema: ArgSchema,
104
+ invoke: async (ctx, args) => {
105
+ const plugin = ctx.app.pm.get("ai");
106
+ const content = await plugin.aiContextDatasourceManager.query(ctx, args);
107
+ return {
108
+ status: "success",
109
+ content: JSON.stringify(content)
110
+ };
111
+ }
112
+ };
113
+ const dataSourceCounting = {
114
+ name: "dataSourceCounting",
115
+ title: '{{t("Data source records counting")}}',
116
+ description: '{{t("Use dataSource, collectionName, and collection fields to query data from the database, get total count of records")}}',
117
+ schema: ArgSchema,
118
+ invoke: async (ctx, args) => {
119
+ const plugin = ctx.app.pm.get("ai");
120
+ args.offset = 0;
121
+ args.limit = 1;
122
+ const content = await plugin.aiContextDatasourceManager.query(ctx, args);
123
+ return {
124
+ status: "success",
125
+ content: String((content == null ? void 0 : content.total) ?? 0)
126
+ };
127
+ }
128
+ };
129
+ // Annotate the CommonJS export names for ESM import in node:
130
+ 0 && (module.exports = {
131
+ dataSourceCounting,
132
+ dataSourceQuery
133
+ });
@@ -56,8 +56,8 @@ function stripToolCallTags(content) {
56
56
  function parseResponseMessage(row) {
57
57
  const { content: rawContent, messageId, metadata, role, toolCalls, attachments, workContext } = row;
58
58
  const content = {
59
- ...rawContent,
60
- content: stripToolCallTags(rawContent.content),
59
+ ...rawContent ?? {},
60
+ content: stripToolCallTags(rawContent == null ? void 0 : rawContent.content),
61
61
  messageId,
62
62
  metadata,
63
63
  attachments,
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "displayName.zh-CN": "AI 员工",
5
5
  "description": "Create AI employees with diverse skills to collaborate with humans, build systems, and handle business operations.",
6
6
  "description.zh-CN": "创建各种技能的 AI 员工,与人类协同,搭建系统,处理业务。",
7
- "version": "2.0.0-alpha.25",
7
+ "version": "2.0.0-alpha.27",
8
8
  "main": "dist/server/index.js",
9
9
  "peerDependencies": {
10
10
  "@nocobase/client": "2.x",
@@ -42,5 +42,5 @@
42
42
  "keywords": [
43
43
  "AI"
44
44
  ],
45
- "gitHead": "8ce1972206272bd1723db193abd0425c532c5687"
45
+ "gitHead": "bb67b95bc49f8d808209e635296ba15a1bd72f72"
46
46
  }