@nocobase/plugin-ai 3.0.0-alpha.3 → 3.0.0-alpha.4
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/docs/nocobase/ai-employees/dev/ai-employee/complete-example.md +206 -0
- package/dist/ai/docs/nocobase/ai-employees/dev/ai-employee/define-ai-employee.md +149 -0
- package/dist/ai/docs/nocobase/ai-employees/dev/ai-employee/define-skill.md +138 -0
- package/dist/ai/docs/nocobase/ai-employees/dev/ai-employee/define-tool.md +189 -0
- package/dist/ai/docs/nocobase/ai-employees/dev/ai-employee/frontend-tool-ui.md +296 -0
- package/dist/ai/docs/nocobase/ai-employees/dev/ai-employee/index.md +126 -0
- package/dist/ai/docs/nocobase/ai-employees/dev/ai-employee/internationalization.md +88 -0
- package/dist/ai/docs/nocobase/ai-employees/dev/ai-employee/troubleshooting.md +86 -0
- package/dist/ai/docs/nocobase/ai-employees/{knowledge-base/dev → dev/knowledge-base}/external-knowledge-base.md +2 -2
- package/dist/ai/docs/nocobase/ai-employees/knowledge-base/knowledge-base/index.md +1 -1
- package/dist/ai/docs/nocobase/development/index.md +1 -1
- package/dist/client/{244.8631eb5cf3f05e21.js → 244.145eb763339a109b.js} +1 -1
- package/dist/client/{264.cc98933ef65608b6.js → 264.6ca5f2eeb4173d86.js} +1 -1
- package/dist/client/index.js +2 -2
- package/dist/client-v2/{244.c428e645ecb94414.js → 244.64cb9d3ee27dcdc6.js} +1 -1
- package/dist/client-v2/{264.be92ff6a4d2612f1.js → 264.3c7d8e90aa7f46ee.js} +1 -1
- package/dist/client-v2/index.js +2 -2
- package/dist/client-v2/pages/LLMServicesPage.d.ts +9 -4
- package/dist/externalVersion.js +15 -15
- package/dist/locale/de-DE.json +2 -1
- package/dist/locale/en-US.json +3 -1
- package/dist/locale/es-ES.json +2 -1
- package/dist/locale/fr-FR.json +2 -1
- package/dist/locale/hu-HU.json +2 -1
- package/dist/locale/id-ID.json +2 -1
- package/dist/locale/it-IT.json +2 -1
- package/dist/locale/ja-JP.json +2 -1
- package/dist/locale/ko-KR.json +2 -1
- package/dist/locale/nl-NL.json +2 -1
- package/dist/locale/pt-BR.json +2 -1
- package/dist/locale/ru-RU.json +2 -1
- package/dist/locale/tr-TR.json +2 -1
- package/dist/locale/uk-UA.json +2 -1
- package/dist/locale/vi-VN.json +2 -1
- package/dist/locale/zh-CN.json +3 -1
- package/dist/locale/zh-TW.json +2 -1
- package/dist/node_modules/@langchain/mistralai/package.json +1 -1
- package/dist/node_modules/@langchain/xai/package.json +1 -1
- package/dist/node_modules/fs-extra/package.json +1 -1
- package/dist/node_modules/jsonrepair/package.json +1 -1
- package/dist/node_modules/just-bash/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/swagger/index.d.ts +8 -0
- package/dist/swagger/llm.d.ts +8 -0
- package/dist/swagger/llm.js +8 -0
- package/package.json +2 -2
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Add Frontend Interaction to a Tool"
|
|
3
|
+
description: "Explains frontend interaction for NocoBase AI employee Tools, including cards, modals, decisions.edit, and frontend execution."
|
|
4
|
+
keywords: "NocoBase,Tool frontend card,ToolsUIProperties,decisions.edit,SuggestionsOptionsCard,frontend Tool"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Add Frontend Interaction to a Tool
|
|
8
|
+
|
|
9
|
+
Some Tools only need to run on the server and require no custom interface. Other Tools need the user to confirm, select, or edit arguments. In those cases, register a frontend card for the Tool with the same name.
|
|
10
|
+
|
|
11
|
+
:::tip Distinguish the two concepts
|
|
12
|
+
|
|
13
|
+
A **frontend card** only handles ToolCall display and human interaction. It does not mean that the Tool's business logic must run in the browser.
|
|
14
|
+
|
|
15
|
+
If the card only displays options like `suggestions` and continues to the server-side `invoke()` after the user selects one, keep the default `execution: 'backend'`. Set `execution: 'frontend'` and implement a frontend `invoke` only when the Tool's actual logic must access the current browser page, FlowModel, or editor state.
|
|
16
|
+
|
|
17
|
+
:::
|
|
18
|
+
|
|
19
|
+
## Define arguments and execution logic on the server first
|
|
20
|
+
|
|
21
|
+
The built-in `suggestions` Tool is located at:
|
|
22
|
+
|
|
23
|
+
```text
|
|
24
|
+
packages/plugins/@nocobase/plugin-ai/src/ai/tools/suggestions.ts
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Its schema includes both the candidate options and the user's final selection:
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
schema: z.object({
|
|
31
|
+
option: z.string().describe('user selected option, ignore this param').optional(),
|
|
32
|
+
options: z.array(z.string()).describe('A list of suggested prompts for the user to choose from.'),
|
|
33
|
+
})
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
According to the Tool description, the model should generate only `options` on the first call. Because this Tool does not set `defaultPermission: 'ALLOW'`, its default permission is `ASK`, and the ToolCall pauses for user input.
|
|
37
|
+
|
|
38
|
+
After the user makes a selection, the frontend uses `decisions.edit()` to merge `option` into the original arguments and resume the ToolCall. The server-side `invoke()` then returns the selected content:
|
|
39
|
+
|
|
40
|
+
```ts
|
|
41
|
+
return {
|
|
42
|
+
status: 'success',
|
|
43
|
+
content: args?.option,
|
|
44
|
+
};
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
The built-in implementation also writes the selection back to `aiMessages.toolCalls`, so rerendered historical messages can still show which option the user selected.
|
|
48
|
+
|
|
49
|
+
## Write the card component
|
|
50
|
+
|
|
51
|
+
A frontend card receives `ToolsUIProperties`:
|
|
52
|
+
|
|
53
|
+
```tsx
|
|
54
|
+
import { useState } from 'react';
|
|
55
|
+
import type { ToolsUIProperties } from '@nocobase/client-v2';
|
|
56
|
+
import { Button, Flex } from 'antd';
|
|
57
|
+
|
|
58
|
+
interface DeveloperChoiceArgs {
|
|
59
|
+
options?: string[] | string;
|
|
60
|
+
option?: string;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const parseOptions = (value: DeveloperChoiceArgs['options']): string[] => {
|
|
64
|
+
if (Array.isArray(value)) {
|
|
65
|
+
return value.filter((option): option is string => typeof option === 'string');
|
|
66
|
+
}
|
|
67
|
+
if (typeof value !== 'string') {
|
|
68
|
+
return [];
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
try {
|
|
72
|
+
const parsed = JSON.parse(value) as unknown;
|
|
73
|
+
return Array.isArray(parsed) ? parsed.filter((option): option is string => typeof option === 'string') : [];
|
|
74
|
+
} catch {
|
|
75
|
+
return [];
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export const DeveloperChoiceCard = ({
|
|
80
|
+
toolCall,
|
|
81
|
+
decisions,
|
|
82
|
+
}: ToolsUIProperties<DeveloperChoiceArgs>) => {
|
|
83
|
+
const [submitting, setSubmitting] = useState(false);
|
|
84
|
+
const options = parseOptions(toolCall.args?.options);
|
|
85
|
+
|
|
86
|
+
const handleSelect = async (option: string) => {
|
|
87
|
+
if (submitting) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
setSubmitting(true);
|
|
92
|
+
try {
|
|
93
|
+
await decisions.edit({
|
|
94
|
+
...toolCall.args,
|
|
95
|
+
option,
|
|
96
|
+
});
|
|
97
|
+
} finally {
|
|
98
|
+
setSubmitting(false);
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
return (
|
|
103
|
+
<Flex gap="small" wrap="wrap">
|
|
104
|
+
{options.map((option, index) => (
|
|
105
|
+
<Button
|
|
106
|
+
key={`${option}-${index}`}
|
|
107
|
+
disabled={toolCall.invokeStatus !== 'interrupted' || submitting}
|
|
108
|
+
onClick={() => handleSelect(option)}
|
|
109
|
+
>
|
|
110
|
+
{option}
|
|
111
|
+
</Button>
|
|
112
|
+
))}
|
|
113
|
+
</Flex>
|
|
114
|
+
);
|
|
115
|
+
};
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
:::warning Note
|
|
119
|
+
|
|
120
|
+
This component demonstrates the general use of `decisions.edit()` and handles repeated clicks and JSON-string arguments. In production, you must also account for read-only conversations, the current active message, and historical selection state in the surrounding chat interface. See the complete implementation in `packages/plugins/@nocobase/plugin-ai/src/client-v2/ai-employees/tools/SuggestionsOptionsCard.tsx`.
|
|
121
|
+
|
|
122
|
+
:::
|
|
123
|
+
|
|
124
|
+
`decisions` provides three operations:
|
|
125
|
+
|
|
126
|
+
| Method | Purpose |
|
|
127
|
+
| --- | --- |
|
|
128
|
+
| `approve()` | Continue with the original arguments |
|
|
129
|
+
| `edit(args)` | Modify the arguments and continue |
|
|
130
|
+
| `reject(message?)` | Reject execution and return the reason to the conversation flow |
|
|
131
|
+
|
|
132
|
+
The built-in `SuggestionsOptionsCard.tsx` also handles these details:
|
|
133
|
+
|
|
134
|
+
- Supports both array and JSON-string forms of `options`
|
|
135
|
+
- Displays a loading state while the ToolCall is still being generated
|
|
136
|
+
- Allows selection only for a ToolCall with the `interrupted` status
|
|
137
|
+
- Disables buttons immediately after a click to prevent duplicate submission
|
|
138
|
+
- Preserves and highlights the selected option in historical messages
|
|
139
|
+
- Allows actions only in the current editable conversation
|
|
140
|
+
|
|
141
|
+
## Register it in the client plugin
|
|
142
|
+
|
|
143
|
+
The frontend registration name must exactly match the server-side Tool name:
|
|
144
|
+
|
|
145
|
+
```tsx
|
|
146
|
+
import { Plugin } from '@nocobase/client-v2';
|
|
147
|
+
import { DeveloperChoiceCard } from './ai-employees/tools/DeveloperChoiceCard';
|
|
148
|
+
|
|
149
|
+
export class PluginDeveloperHelperClient extends Plugin {
|
|
150
|
+
async load() {
|
|
151
|
+
this.ai.toolsManager.registerTools('developerChoice', {
|
|
152
|
+
ui: {
|
|
153
|
+
card: DeveloperChoiceCard,
|
|
154
|
+
},
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export default PluginDeveloperHelperClient;
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
If the server-side file is `src/ai/tools/developerChoice.ts`, register `developerChoice` here.
|
|
163
|
+
|
|
164
|
+
The built-in `suggestions` registration works the same way:
|
|
165
|
+
|
|
166
|
+
```ts
|
|
167
|
+
export const suggestionsTool = [
|
|
168
|
+
'suggestions',
|
|
169
|
+
{
|
|
170
|
+
ui: {
|
|
171
|
+
card: SuggestionsOptionsCard,
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
];
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
`PluginAIClientV2.load()` then calls `registerPluginAIClientV2BuiltinTools(this.ai.toolsManager)` to merge the card into the same-named Tool definition returned by the server.
|
|
178
|
+
|
|
179
|
+
## Choose a card, modal, or frontend execution
|
|
180
|
+
|
|
181
|
+
### Use a card
|
|
182
|
+
|
|
183
|
+
The following lists only the commonly used client-side `ToolsOptions` settings. See the complete type in `packages/core/client-v2/src/ai/tools-manager/types.ts`.
|
|
184
|
+
|
|
185
|
+
```ts
|
|
186
|
+
type ToolsOptions = {
|
|
187
|
+
ui?: {
|
|
188
|
+
card?: ComponentType<ToolsUIProperties>;
|
|
189
|
+
modal?: {
|
|
190
|
+
title?: string;
|
|
191
|
+
okText?: string;
|
|
192
|
+
Component?: ComponentType;
|
|
193
|
+
footer?: ComponentType;
|
|
194
|
+
hideOkButton?: boolean;
|
|
195
|
+
// modal.props、useOnOk 等配置请查看完整类型。
|
|
196
|
+
};
|
|
197
|
+
};
|
|
198
|
+
invoke?: (app, params) => unknown | Promise<unknown>;
|
|
199
|
+
// useHooks 等其他配置请查看完整类型。
|
|
200
|
+
};
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
Use `card` first by default.
|
|
204
|
+
|
|
205
|
+
### Use a modal
|
|
206
|
+
|
|
207
|
+
Add a `modal` only when the content is extensive or requires a large preview or complex argument editing.
|
|
208
|
+
|
|
209
|
+
### Execute a Tool in the browser
|
|
210
|
+
|
|
211
|
+
If the server-side Tool sets `execution: 'frontend'`, the client must also provide `invoke`. Such Tools are suitable for reading the current page context, editor content, or FlowEngine state. They are not suitable for data writes that require server-side permission enforcement.
|
|
212
|
+
|
|
213
|
+
## Complete example: Add a selection card to a built-in AI employee
|
|
214
|
+
|
|
215
|
+
After completing [Complete Example: Create a Built-in AI Employee](./complete-example.md), turn `Dev Helper`'s follow-up question into clickable options by defining another Tool named `developerChoice` and registering a frontend card. Put the server-side file at:
|
|
216
|
+
|
|
217
|
+
```text
|
|
218
|
+
src/ai/ai-employees/dev-helper/skills/welcome-developer/tools/developerChoice.ts
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
This Tool declares the options and accepts the user's selection:
|
|
222
|
+
|
|
223
|
+
```ts
|
|
224
|
+
import type { Context } from '@nocobase/actions';
|
|
225
|
+
import { defineTools } from '@nocobase/ai';
|
|
226
|
+
import { z } from 'zod';
|
|
227
|
+
|
|
228
|
+
export default defineTools({
|
|
229
|
+
scope: 'SPECIFIED',
|
|
230
|
+
introduction: {
|
|
231
|
+
title: '{{t("ai.tools.developerChoice.title", { ns: "@nocobase/plugin-developer-helper" })}}',
|
|
232
|
+
about: '{{t("ai.tools.developerChoice.about", { ns: "@nocobase/plugin-developer-helper" })}}',
|
|
233
|
+
},
|
|
234
|
+
definition: {
|
|
235
|
+
name: 'developerChoice',
|
|
236
|
+
description: 'Show a short list of plugin-development directions for the user to choose from.',
|
|
237
|
+
schema: z.object({
|
|
238
|
+
options: z.array(z.string()).min(2).max(4),
|
|
239
|
+
option: z.string().optional(),
|
|
240
|
+
}),
|
|
241
|
+
},
|
|
242
|
+
invoke: async (_ctx: Context, args: { options: string[]; option?: string }) => {
|
|
243
|
+
return {
|
|
244
|
+
status: 'success',
|
|
245
|
+
content: args.option,
|
|
246
|
+
};
|
|
247
|
+
},
|
|
248
|
+
});
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
Because `developerChoice.ts` is in the `welcome-developer` Skill's `tools/` directory, it is automatically bound to the current Skill. However, binding only means the model can use the Tool; it does not guarantee that the model will call it.
|
|
252
|
+
|
|
253
|
+
Also update the workflow in `SKILLS.md`, replacing the original steps 5–6 with:
|
|
254
|
+
|
|
255
|
+
```md
|
|
256
|
+
5. Use `content.name` to write a short welcome message in the same language as the user.
|
|
257
|
+
6. Call `developerChoice` exactly once with 2–4 plugin-development directions written in the user's language.
|
|
258
|
+
7. Wait for the user to select an option.
|
|
259
|
+
8. Continue according to the selected option.
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
Reuse the `DeveloperChoiceCard` defined above and save it to:
|
|
263
|
+
|
|
264
|
+
```text
|
|
265
|
+
src/client-v2/ai-employees/tools/DeveloperChoiceCard.tsx
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
Finally, register it in `src/client-v2/plugin.tsx`:
|
|
269
|
+
|
|
270
|
+
```tsx
|
|
271
|
+
import { Plugin } from '@nocobase/client-v2';
|
|
272
|
+
import { DeveloperChoiceCard } from './ai-employees/tools/DeveloperChoiceCard';
|
|
273
|
+
|
|
274
|
+
export class PluginDeveloperHelperClient extends Plugin {
|
|
275
|
+
async load() {
|
|
276
|
+
this.ai.toolsManager.registerTools('developerChoice', {
|
|
277
|
+
ui: {
|
|
278
|
+
card: DeveloperChoiceCard,
|
|
279
|
+
},
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
export default PluginDeveloperHelperClient;
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
After registering the card, rebuild the client. When a conversation reaches `developerChoice`, the ToolCall pauses and displays clickable options.
|
|
288
|
+
|
|
289
|
+
<!-- 需要一张对话中显示 developerChoice 可点击选项的截图 -->
|
|
290
|
+
|
|
291
|
+
## Related links
|
|
292
|
+
|
|
293
|
+
- [Define a server-side Tool](./define-tool.md) — Define the server-side Tool corresponding to a frontend card
|
|
294
|
+
- [Complete example: Create a built-in AI employee](./complete-example.md) — Complete the basic example without frontend code first
|
|
295
|
+
- [Internationalization for AI employee plugins](./internationalization.md) — Translate Tool and Skill management-interface text
|
|
296
|
+
- [Client Plugin](../../../plugin-development/client/plugin.md) — Learn about the client plugin entry point and `load()`
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "AI Employee Plugin Development"
|
|
3
|
+
description: "Explains the relationships, directory conventions, and learning path for Tools, Skills, built-in AI employees, and frontend Tool UI in NocoBase plugins."
|
|
4
|
+
keywords: "NocoBase,AI employee plugin development,Tool,Skill,defineAIEmployee,src/ai"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# AI Employee Plugin Development
|
|
8
|
+
|
|
9
|
+
In NocoBase, plugins can make their business capabilities available to AI employees. Three extension points cover different layers:
|
|
10
|
+
|
|
11
|
+
- **Tool** — Performs specific operations such as querying data, calling APIs, and modifying records
|
|
12
|
+
- **Skill** — Tells the model when to use Tools and which steps to follow to complete a task
|
|
13
|
+
- **Built-in AI Employee** — Assembles a role profile, system prompt, Skills, and Tools into an employee that is ready to use
|
|
14
|
+
|
|
15
|
+
Usually, you do not need to call registration APIs manually. Put files in the plugin's conventional `src/ai` directories, and NocoBase automatically scans and registers them when the plugin loads. You only need to register the corresponding frontend component or execution logic in `src/client-v2/plugin.tsx` when a Tool requires a custom card, modal, or browser-side execution.
|
|
16
|
+
|
|
17
|
+
Before you begin, make sure the application has installed and enabled `@nocobase/plugin-ai`. Plugin code can use the types and definition functions provided by `@nocobase/ai` and `@nocobase/actions`.
|
|
18
|
+
|
|
19
|
+
:::tip Prerequisites
|
|
20
|
+
|
|
21
|
+
- [Write your first plugin](../../../plugin-development/write-your-first-plugin.md) — If you are new to plugin development, start with the plugin directory, build, and activation workflow
|
|
22
|
+
- [AI employees](../../index.md) — Learn how to configure and use AI employees first
|
|
23
|
+
|
|
24
|
+
:::
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
## Quick index
|
|
28
|
+
|
|
29
|
+
| I want to... | Read this |
|
|
30
|
+
| --- | --- |
|
|
31
|
+
| Let AI call a server-side operation | [Define a server-side Tool](./define-tool.md) |
|
|
32
|
+
| Specify the call sequence for multiple Tools | [Define a Skill](./define-skill.md) |
|
|
33
|
+
| Provide a fixed AI role with a plugin | [Define a built-in AI employee](./define-ai-employee.md) |
|
|
34
|
+
| See how a Tool, Skill, and employee work together | [Complete example: Create a built-in AI employee](./complete-example.md) |
|
|
35
|
+
| Add confirmation, selection, or editing UI to a Tool | [Add frontend interaction to a Tool](./frontend-tool-ui.md) |
|
|
36
|
+
| Add management-interface translations for Tools and Skills | [Internationalization for AI employee plugins](./internationalization.md) |
|
|
37
|
+
| Troubleshoot registration, binding, and execution | [Troubleshooting AI employee plugin development](./troubleshooting.md) |
|
|
38
|
+
|
|
39
|
+
## Decide which layer to extend first
|
|
40
|
+
|
|
41
|
+
Tools, Skills, and built-in AI employees are not three separate features. They form layers that build on one another from the bottom up. Not every plugin needs to implement all three.
|
|
42
|
+
|
|
43
|
+
```text
|
|
44
|
+
Tool:让 AI 能执行一个具体动作
|
|
45
|
+
↓
|
|
46
|
+
Skill:让 AI 按固定方法完成一类任务
|
|
47
|
+
↓
|
|
48
|
+
内置 AI 员工:把这些能力装配成一个固定角色和使用入口
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Choose the starting layer based on your requirements:
|
|
52
|
+
|
|
53
|
+
- If AI only needs to query data, call an API, or modify records, defining a Tool is enough
|
|
54
|
+
- If you need to specify Tool call order, confirmation steps, and output format, define a Skill for those Tools
|
|
55
|
+
- If the plugin should provide a fixed role immediately after it is enabled, create a built-in AI employee and bind the corresponding Skills and Tools
|
|
56
|
+
|
|
57
|
+
When all three layers are used, a task follows this sequence:
|
|
58
|
+
|
|
59
|
+
1. The user gives the AI employee a task
|
|
60
|
+
2. The AI employee uses its system prompt to decide which Skill is needed
|
|
61
|
+
3. The Skill tells the model which Tools to call and in what order
|
|
62
|
+
4. The Tool performs a query, write, or external request and returns the result
|
|
63
|
+
5. The AI employee prepares the final response from the Tool result
|
|
64
|
+
|
|
65
|
+
A frontend Tool card is not a fourth capability layer. It only adds an interaction UI to a ToolCall when the Tool needs the user to confirm, select an option, or edit arguments.
|
|
66
|
+
|
|
67
|
+
## Put AI resources under `src/ai`
|
|
68
|
+
|
|
69
|
+
NocoBase discovers a plugin's AI resources by directory convention. With the standard plugin layout, put Tools, Skills, and built-in AI employees under `src/ai`; you do not need to register them one by one in `load()` in `src/server/plugin.ts`.
|
|
70
|
+
|
|
71
|
+
A complete directory can be organized like this:
|
|
72
|
+
|
|
73
|
+
```text
|
|
74
|
+
src/ai/
|
|
75
|
+
├── tools/
|
|
76
|
+
│ └── searchDocs.ts
|
|
77
|
+
├── skills/
|
|
78
|
+
│ └── document-search/
|
|
79
|
+
│ ├── SKILLS.md
|
|
80
|
+
│ └── tools/
|
|
81
|
+
│ └── readDocument.ts
|
|
82
|
+
└── ai-employees/
|
|
83
|
+
├── translator.ts
|
|
84
|
+
└── developer/
|
|
85
|
+
├── index.ts
|
|
86
|
+
├── prompt.md
|
|
87
|
+
├── skills/
|
|
88
|
+
└── tools/
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Each location uses a different registration method:
|
|
92
|
+
|
|
93
|
+
| File or directory | How NocoBase handles it |
|
|
94
|
+
| --- | --- |
|
|
95
|
+
| `src/ai/tools/<name>.ts` | Registers an independent Tool |
|
|
96
|
+
| `src/ai/skills/<name>/SKILLS.md` | Registers a Skill |
|
|
97
|
+
| `tools/` under a Skill directory | Registers Tools and automatically binds them to the current Skill |
|
|
98
|
+
| `src/ai/ai-employees/<name>.ts` | Registers a single-file built-in AI employee |
|
|
99
|
+
| `src/ai/ai-employees/<name>/index.ts` | Registers a directory-based built-in AI employee |
|
|
100
|
+
| `prompt.md` under an AI employee directory | Provides the employee's default system prompt |
|
|
101
|
+
| `skills/` and `tools/` under an AI employee directory | Registers resources and automatically binds them to the current employee |
|
|
102
|
+
|
|
103
|
+
When a plugin loads, NocoBase completes these steps before running the plugin's own `load()` method:
|
|
104
|
+
|
|
105
|
+
1. Scan and register Tools
|
|
106
|
+
2. Parse `SKILLS.md` and bind Tools in each Skill directory to that Skill
|
|
107
|
+
3. Load built-in AI employees and merge the `prompt.md`, Skills, and Tools in each employee directory
|
|
108
|
+
|
|
109
|
+
`src/client-v2` is not part of this automatic scanning convention. Register something there only when a Tool needs a frontend card, modal, or browser-side execution logic.
|
|
110
|
+
|
|
111
|
+
## Extension points and directory quick reference
|
|
112
|
+
|
|
113
|
+
| Extension point | Responsibility | Default location |
|
|
114
|
+
| --- | --- | --- |
|
|
115
|
+
| Tool | Performs specific operations such as queries, writes, and external requests | `src/ai/**/tools/` |
|
|
116
|
+
| Skill | Specifies the workflow, Tool call order, and output constraints | `src/ai/**/skills/<name>/SKILLS.md` |
|
|
117
|
+
| Built-in AI employee | Defines a fixed role and assembles its system prompt, Skills, and Tools | `src/ai/ai-employees/` |
|
|
118
|
+
| Frontend Tool card | Displays a ToolCall and collects confirmation, edits, or rejection | `src/client-v2/` |
|
|
119
|
+
|
|
120
|
+
Implement the Tool first by default. Add a Skill when you need a fixed workflow, then create a built-in AI employee when you need a fixed role entry point. Add a frontend card only when the Tool requires browser interaction.
|
|
121
|
+
|
|
122
|
+
## Related links
|
|
123
|
+
|
|
124
|
+
- [Write your first plugin](../../../plugin-development/write-your-first-plugin.md) — Create and run a NocoBase plugin from scratch
|
|
125
|
+
- [AI employees overview](../../index.md) — Learn where to access and use AI employees
|
|
126
|
+
- [Prompt engineering guide](../../configuration/prompt-engineering-guide.md) — Write system prompts and task constraints
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Internationalization for AI Employee Plugins"
|
|
3
|
+
description: "Explains internationalization files, translation templates, and current limitations for NocoBase AI employee Tools, Skills, and built-in employee profiles."
|
|
4
|
+
keywords: "NocoBase,AI employee plugin internationalization,Tool introduction,Skill introduction,locale"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Internationalization for AI Employee Plugins
|
|
8
|
+
|
|
9
|
+
Management-interface text in an AI employee plugin should follow the current interface language. Tools and Skills can use the plugin's own locale files through `introduction`, while AI employee profile fields are handled differently.
|
|
10
|
+
|
|
11
|
+
## What needs internationalization
|
|
12
|
+
|
|
13
|
+
Usually, you need to internationalize text displayed to administrators or users:
|
|
14
|
+
|
|
15
|
+
- `introduction.title` and `introduction.about` for Tools
|
|
16
|
+
- `introduction.title` and `introduction.about` for Skills
|
|
17
|
+
- Text in frontend cards, modals, and action buttons
|
|
18
|
+
|
|
19
|
+
`definition.name`, `definition.description`, schema descriptions, Skill content, and AI employee system prompts are primarily intended for the model. Do not change a Tool's stable name or workflow content for interface translation.
|
|
20
|
+
|
|
21
|
+
## Translate Tool and Skill management-interface text
|
|
22
|
+
|
|
23
|
+
A Tool's `introduction` can use the `{{t(...)}}` translation template:
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
introduction: {
|
|
27
|
+
title: '{{t("ai.tools.greetDeveloper.title", { ns: "@nocobase/plugin-developer-helper" })}}',
|
|
28
|
+
about: '{{t("ai.tools.greetDeveloper.about", { ns: "@nocobase/plugin-developer-helper" })}}',
|
|
29
|
+
},
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Use the same format in the frontmatter of a Skill's `SKILLS.md`:
|
|
33
|
+
|
|
34
|
+
```yaml
|
|
35
|
+
introduction:
|
|
36
|
+
title: '{{t("ai.skills.welcomeDeveloper.title", { ns: "@nocobase/plugin-developer-helper" })}}'
|
|
37
|
+
about: '{{t("ai.skills.welcomeDeveloper.about", { ns: "@nocobase/plugin-developer-helper" })}}'
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
The `ns` value must match the internationalization namespace actually used by the plugin.
|
|
41
|
+
|
|
42
|
+
## Add locale files
|
|
43
|
+
|
|
44
|
+
Plugin locale files are stored in `src/locale/`. Use the same keys for each language and change only the corresponding text.
|
|
45
|
+
|
|
46
|
+
### Add English text
|
|
47
|
+
|
|
48
|
+
Add the following to `src/locale/en-US.json`:
|
|
49
|
+
|
|
50
|
+
```json
|
|
51
|
+
{
|
|
52
|
+
"ai.tools.greetDeveloper.title": "Developer name check",
|
|
53
|
+
"ai.tools.greetDeveloper.about": "Validate the developer name before writing a welcome message.",
|
|
54
|
+
"ai.tools.developerChoice.title": "Developer choices",
|
|
55
|
+
"ai.tools.developerChoice.about": "Ask the developer to choose the next plugin capability.",
|
|
56
|
+
"ai.skills.welcomeDeveloper.title": "Developer welcome",
|
|
57
|
+
"ai.skills.welcomeDeveloper.about": "Welcome a developer and ask what plugin capability they want to build."
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Add Chinese text
|
|
62
|
+
|
|
63
|
+
Add the following to `src/locale/zh-CN.json`:
|
|
64
|
+
|
|
65
|
+
```json
|
|
66
|
+
{
|
|
67
|
+
"ai.tools.greetDeveloper.title": "开发者姓名确认",
|
|
68
|
+
"ai.tools.greetDeveloper.about": "在生成欢迎语之前确认开发者姓名。",
|
|
69
|
+
"ai.tools.developerChoice.title": "开发方向选择",
|
|
70
|
+
"ai.tools.developerChoice.about": "让开发者选择下一步要实现的插件能力。",
|
|
71
|
+
"ai.skills.welcomeDeveloper.title": "欢迎开发者",
|
|
72
|
+
"ai.skills.welcomeDeveloper.about": "欢迎开发者,并询问接下来要实现的插件能力。"
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Current limitations for AI employee profiles
|
|
77
|
+
|
|
78
|
+
The `nickname`, `position`, `bio`, and `greeting` fields in an AI employee profile do not use the `{{t(...)}}` template mechanism above. At runtime, built-in employees currently translate these raw strings in the `@nocobase/plugin-ai` namespace, so third-party plugins should not assume that a custom namespace will take effect automatically.
|
|
79
|
+
|
|
80
|
+
Unless you add separate localization logic, choose one default language for the employee profile and put the interface text for Tools, Skills, and frontend interactions in the plugin's own locale files.
|
|
81
|
+
|
|
82
|
+
## Related links
|
|
83
|
+
|
|
84
|
+
- [AI employee plugin development](./index.md) — Return to the development guide overview
|
|
85
|
+
- [Define a server-side Tool](./define-tool.md) — Use translation templates in a Tool introduction
|
|
86
|
+
- [Define a Skill](./define-skill.md) — Use translation templates in Skill frontmatter
|
|
87
|
+
- [Define a built-in AI employee](./define-ai-employee.md) — Learn about employee profile fields
|
|
88
|
+
- [Add frontend interaction to a Tool](./frontend-tool-ui.md) — Add interface translations to frontend cards and modals
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Troubleshooting AI Employee Plugin Development"
|
|
3
|
+
description: "Troubleshoot NocoBase AI employee Tools, Skills, built-in employees, and frontend Tool cards that are not registered or do not run."
|
|
4
|
+
keywords: "NocoBase,AI employee troubleshooting,Tool not registered,Skill not loaded,frontend card"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Troubleshooting AI Employee Plugin Development
|
|
8
|
+
|
|
9
|
+
## The Tool is not registered
|
|
10
|
+
|
|
11
|
+
Check the following in order:
|
|
12
|
+
|
|
13
|
+
- The file is under `src/ai/**/tools/` within the plugin's build scope
|
|
14
|
+
- The file uses the `.ts` or `.js` extension
|
|
15
|
+
- It uses `export default defineTools(...)`
|
|
16
|
+
- The Tool file is not mistakenly named with the `.d.ts` extension
|
|
17
|
+
- There is no duplicate Tool name causing the later registration to be ignored
|
|
18
|
+
- The plugin has been rebuilt and loaded
|
|
19
|
+
|
|
20
|
+
## The Skill does not appear
|
|
21
|
+
|
|
22
|
+
Check the filename first. It must currently be:
|
|
23
|
+
|
|
24
|
+
```text
|
|
25
|
+
SKILLS.md
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Also confirm that the frontmatter contains a stable `name` and `description`, and that the file is located at `src/ai/**/skills/<skill-name>/SKILLS.md`.
|
|
29
|
+
|
|
30
|
+
## The Skill loads but cannot call the Tool
|
|
31
|
+
|
|
32
|
+
Check the following:
|
|
33
|
+
|
|
34
|
+
- The Skill's `tools` list includes the Tool name
|
|
35
|
+
- The Tool is in the current Skill's `tools/` directory
|
|
36
|
+
- The Tool filename, `definition.name`, and Skill reference are consistent
|
|
37
|
+
- The `scope` is appropriate for the current binding method
|
|
38
|
+
- The Tool was not skipped because of a duplicate name
|
|
39
|
+
|
|
40
|
+
Binding a Tool only means the model can use it. If the Tool appears in the Skill but the model still does not call it, explicitly state the call timing, parameter requirements, and result-waiting step in the `SKILLS.md` workflow.
|
|
41
|
+
|
|
42
|
+
## The frontend card does not appear
|
|
43
|
+
|
|
44
|
+
The frontend registration name must exactly match the final server-side Tool name:
|
|
45
|
+
|
|
46
|
+
```ts
|
|
47
|
+
this.ai.toolsManager.registerTools('developerChoice', options);
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Also check:
|
|
51
|
+
|
|
52
|
+
- The custom plugin uses the `src/client-v2/` runtime
|
|
53
|
+
- The card is registered in the client plugin's `load()` method
|
|
54
|
+
- The ToolCall has entered a state supported by the card
|
|
55
|
+
- The card is not disabled by its `invokeStatus` check
|
|
56
|
+
- The client plugin has been rebuilt and loaded
|
|
57
|
+
|
|
58
|
+
## The Tool does not continue after clicking the card
|
|
59
|
+
|
|
60
|
+
Confirm that one of `approve()`, `edit()`, or `reject()` is called. To write the user's selection back into the arguments, use:
|
|
61
|
+
|
|
62
|
+
```ts
|
|
63
|
+
await decisions.edit({
|
|
64
|
+
...toolCall.args,
|
|
65
|
+
option: selectedOption,
|
|
66
|
+
});
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Also confirm that the server-side schema allows this field and that `invoke()` reads it.
|
|
70
|
+
|
|
71
|
+
## Changing `definition.name` has no effect
|
|
72
|
+
|
|
73
|
+
An automatically loaded Tool's name is determined by its filename or directory name. For example:
|
|
74
|
+
|
|
75
|
+
```text
|
|
76
|
+
src/ai/tools/developerChoice.ts
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
The final name is `developerChoice`. To rename it, also rename the file, Skill references, AI employee configuration, and frontend registration name.
|
|
80
|
+
|
|
81
|
+
## Related links
|
|
82
|
+
|
|
83
|
+
- [AI employee plugin development](./index.md) — Return to the development guide overview
|
|
84
|
+
- [Define a server-side Tool](./define-tool.md) — Check Tool naming and registration
|
|
85
|
+
- [Define a Skill](./define-skill.md) — Check Skill and Tool binding
|
|
86
|
+
- [Add frontend interaction to a Tool](./frontend-tool-ui.md) — Check ToolCall and frontend registration
|
|
@@ -12,7 +12,7 @@ An external knowledge base plugin does not participate in document upload, segme
|
|
|
12
12
|
|
|
13
13
|
:::tip Prereading
|
|
14
14
|
|
|
15
|
-
- [Knowledge base overview](
|
|
15
|
+
- [Knowledge base overview](../../knowledge-base/knowledge-base/index.md) - Understand the boundaries of Local, Readonly, and External knowledge bases
|
|
16
16
|
- [Plugin](../../../plugin-development/server/plugin.md) - Understand server-side plugin lifecycle and `this.app.pm`
|
|
17
17
|
- [i18n](../../../plugin-development/server/i18n.md) - Prepare translations if the plugin provides a configuration form
|
|
18
18
|
|
|
@@ -312,7 +312,7 @@ At this point, the external knowledge base plugin can be called by AI employees.
|
|
|
312
312
|
|
|
313
313
|
## Related links
|
|
314
314
|
|
|
315
|
-
- [Knowledge base overview](
|
|
315
|
+
- [Knowledge base overview](../../knowledge-base/knowledge-base/index.md) - Boundaries of Local, Readonly, and External knowledge bases
|
|
316
316
|
- [Plugin](../../../plugin-development/server/plugin.md) - Server-side plugin lifecycle and `this.app.pm`
|
|
317
317
|
- [i18n](../../../plugin-development/server/i18n.md) - Plugin frontend and server-side translations
|
|
318
318
|
- [Client plugin development overview](../../../plugin-development/client/index.md) - Client entry, components, and context capabilities
|
|
@@ -39,7 +39,7 @@ The three knowledge base types have different capability boundaries:
|
|
|
39
39
|
| --- | --- |
|
|
40
40
|
| Local | Documents, segment files, and vector data are managed by NocoBase. It supports uploading documents in the UI, and also supports creating, updating, deleting, and retrieving knowledge base documents through workflow nodes |
|
|
41
41
|
| Readonly | Documents and vector data are maintained by an external system. NocoBase cannot maintain this data in the UI or workflows, and only uses the knowledge base as a RAG retrieval source. Currently, PGVector is the only supported vector database |
|
|
42
|
-
| External | Documents, vector data, and retrieval logic are all handled by an external system. NocoBase cannot directly maintain documents or vector data. Developers need to provide a plugin and implement the retrieval logic in that plugin, such as connecting to a vector database not yet supported by NocoBase or calling a third-party retrieval API. For development details, see [External Knowledge Base plugin](
|
|
42
|
+
| External | Documents, vector data, and retrieval logic are all handled by an external system. NocoBase cannot directly maintain documents or vector data. Developers need to provide a plugin and implement the retrieval logic in that plugin, such as connecting to a vector database not yet supported by NocoBase or calling a third-party retrieval API. For development details, see [External Knowledge Base plugin](../../dev/knowledge-base/external-knowledge-base.md) |
|
|
43
43
|
|
|
44
44
|
Local knowledge bases are recommended by default. Only consider Readonly or External when documents and vector data are already maintained outside NocoBase and NocoBase only needs to read retrieval results.
|
|
45
45
|
|
|
@@ -52,5 +52,5 @@ features:
|
|
|
52
52
|
link: /file-manager/development
|
|
53
53
|
- title: Knowledge Base Extension
|
|
54
54
|
details: Connect external knowledge bases or custom retrieval services to extend RAG retrieval sources for AI employees.
|
|
55
|
-
link: /ai-employees/knowledge-base/
|
|
55
|
+
link: /ai-employees/dev/knowledge-base/external-knowledge-base
|
|
56
56
|
---
|