@baishuyun/agents 0.0.1
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/CHANGELOG.md +7 -0
- package/index.ts +10 -0
- package/package.json +30 -0
- package/src/continue-confirmer/index.ts +41 -0
- package/src/continue-confirmer/prompt.ts +11 -0
- package/src/fields-builder/fields-builder.ts +43 -0
- package/src/fields-builder/index.ts +109 -0
- package/src/form-builder/consts/index.ts +5 -0
- package/src/form-builder/index.ts +24 -0
- package/src/form-builder/model/ds.ts +8 -0
- package/src/form-builder/model/openai.ts +7 -0
- package/src/form-builder/model/v0.ts +7 -0
- package/src/form-builder/model/xai.ts +7 -0
- package/src/form-builder/prompts/fields-design-docs.ts +3 -0
- package/src/form-builder/prompts/index.ts +32 -0
- package/src/form-builder/schema/index.ts +7 -0
- package/src/form-builder/tools/address.ts +58 -0
- package/src/form-builder/tools/attachment.ts +62 -0
- package/src/form-builder/tools/button.ts +73 -0
- package/src/form-builder/tools/checkbox.ts +55 -0
- package/src/form-builder/tools/confirm-to-create-fields-for-related-form.ts +16 -0
- package/src/form-builder/tools/confirm-to-create-form.ts +11 -0
- package/src/form-builder/tools/confirm-to-create-related-form.ts +16 -0
- package/src/form-builder/tools/confirm-to-save-checked-fields.ts +11 -0
- package/src/form-builder/tools/date-time.ts +73 -0
- package/src/form-builder/tools/department-group.ts +49 -0
- package/src/form-builder/tools/department.ts +49 -0
- package/src/form-builder/tools/image.ts +123 -0
- package/src/form-builder/tools/index.ts +27 -0
- package/src/form-builder/tools/input.ts +70 -0
- package/src/form-builder/tools/link-data.ts +70 -0
- package/src/form-builder/tools/load-data.ts +49 -0
- package/src/form-builder/tools/location.ts +94 -0
- package/src/form-builder/tools/member-group.ts +51 -0
- package/src/form-builder/tools/member.ts +51 -0
- package/src/form-builder/tools/number-input.ts +106 -0
- package/src/form-builder/tools/prompt-to-create-realted-form.ts +12 -0
- package/src/form-builder/tools/radio.ts +54 -0
- package/src/form-builder/tools/select-checker.ts +58 -0
- package/src/form-builder/tools/select.ts +56 -0
- package/src/form-builder/tools/serial-number.ts +75 -0
- package/src/form-builder/tools/signature.ts +38 -0
- package/src/form-builder/tools/splitline.ts +41 -0
- package/src/form-builder/tools/textarea.ts +55 -0
- package/src/form-builder/types/index.ts +53 -0
- package/src/form-builder/utils/index.ts +5 -0
- package/src/form-builder/utils/process-confirm-tool-call.ts +123 -0
- package/src/form-designer/index.ts +61 -0
- package/src/form-designer/prompts.ts +50 -0
- package/src/utils/index.ts +104 -0
- package/tsconfig.json +7 -0
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import {
|
|
2
|
+
convertToModelMessages,
|
|
3
|
+
type Tool,
|
|
4
|
+
type ToolCallOptions,
|
|
5
|
+
type ToolSet,
|
|
6
|
+
type UIMessageStreamWriter,
|
|
7
|
+
getToolName,
|
|
8
|
+
isToolUIPart,
|
|
9
|
+
} from "ai";
|
|
10
|
+
|
|
11
|
+
import type { FormBuildUIMessage } from "../types/index.js";
|
|
12
|
+
import { APPROVAL } from "../consts/index.js";
|
|
13
|
+
|
|
14
|
+
function isValidToolName<K extends PropertyKey, T extends object>(
|
|
15
|
+
key: K,
|
|
16
|
+
obj: T,
|
|
17
|
+
): key is K & keyof T {
|
|
18
|
+
return key in obj;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export async function processFormBuildConfirmToolCalls<
|
|
22
|
+
Tools extends ToolSet,
|
|
23
|
+
ExecutableTools extends {
|
|
24
|
+
[Tool in keyof Tools as Tools[Tool] extends { execute: Function }
|
|
25
|
+
? never
|
|
26
|
+
: Tool]: Tools[Tool];
|
|
27
|
+
},
|
|
28
|
+
>(
|
|
29
|
+
{
|
|
30
|
+
writer,
|
|
31
|
+
messages,
|
|
32
|
+
}: {
|
|
33
|
+
tools: Tools; // used for type inference
|
|
34
|
+
writer: UIMessageStreamWriter;
|
|
35
|
+
messages: FormBuildUIMessage[]; // IMPORTANT: replace with your message type
|
|
36
|
+
},
|
|
37
|
+
executeFunctions: {
|
|
38
|
+
[K in keyof Tools & keyof ExecutableTools]?: (
|
|
39
|
+
args: ExecutableTools[K] extends Tool<infer P> ? P : never,
|
|
40
|
+
context: ToolCallOptions,
|
|
41
|
+
) => Promise<any>;
|
|
42
|
+
},
|
|
43
|
+
): Promise<FormBuildUIMessage[]> {
|
|
44
|
+
const lastMessage = messages[messages.length - 1];
|
|
45
|
+
const parts = lastMessage.parts;
|
|
46
|
+
if (!parts) return messages;
|
|
47
|
+
|
|
48
|
+
const processedParts = await Promise.all(
|
|
49
|
+
parts.map(async (part) => {
|
|
50
|
+
// Only process tool invocations parts
|
|
51
|
+
if (!isToolUIPart(part)) return part;
|
|
52
|
+
|
|
53
|
+
const toolName = getToolName(part);
|
|
54
|
+
|
|
55
|
+
// Only continue if we have an execute function for the tool (meaning it requires confirmation) and it's in a 'output-available' state
|
|
56
|
+
if (!(toolName in executeFunctions) || part.state !== "output-available")
|
|
57
|
+
return part;
|
|
58
|
+
|
|
59
|
+
let result;
|
|
60
|
+
|
|
61
|
+
if (part.output === APPROVAL.YES) {
|
|
62
|
+
// Get the tool and check if the tool has an execute function.
|
|
63
|
+
if (
|
|
64
|
+
!isValidToolName(toolName, executeFunctions) ||
|
|
65
|
+
part.state !== "output-available"
|
|
66
|
+
) {
|
|
67
|
+
return part;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const toolInstance = executeFunctions[toolName] as Tool["execute"];
|
|
71
|
+
if (toolInstance) {
|
|
72
|
+
result = await toolInstance(part.input, {
|
|
73
|
+
messages: convertToModelMessages(messages),
|
|
74
|
+
toolCallId: part.toolCallId,
|
|
75
|
+
});
|
|
76
|
+
} else {
|
|
77
|
+
result = "Error: No execute function found on tool";
|
|
78
|
+
}
|
|
79
|
+
} else if (part.output === APPROVAL.NO) {
|
|
80
|
+
result = "已取消操作。";
|
|
81
|
+
} else {
|
|
82
|
+
// For any unhandled responses, return the original part.
|
|
83
|
+
return part;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Forward updated tool result to the client.
|
|
87
|
+
writer.write({
|
|
88
|
+
type: "tool-output-available",
|
|
89
|
+
toolCallId: part.toolCallId,
|
|
90
|
+
output: result,
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// Return updated toolInvocation with the actual result.
|
|
94
|
+
return {
|
|
95
|
+
...part,
|
|
96
|
+
output: result,
|
|
97
|
+
};
|
|
98
|
+
}),
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
// Finally return the processed messages
|
|
102
|
+
return [...messages.slice(0, -1), { ...lastMessage, parts: processedParts }];
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export function getToolsRequiringConfirmation<T extends ToolSet>(
|
|
106
|
+
tools: T,
|
|
107
|
+
): string[] {
|
|
108
|
+
return (Object.keys(tools) as (keyof T)[]).filter((key) => {
|
|
109
|
+
const maybeTool = tools[key];
|
|
110
|
+
return typeof maybeTool.execute !== "function";
|
|
111
|
+
}) as string[];
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export function getExecutableTools<T extends ToolSet>(tools: T): Set<string> {
|
|
115
|
+
const results = new Set<string>();
|
|
116
|
+
(Object.keys(tools) as (keyof T)[]).forEach((key) => {
|
|
117
|
+
const maybeTool = tools[key];
|
|
118
|
+
if (typeof maybeTool.execute === "function") {
|
|
119
|
+
results.add(key as string);
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
return results;
|
|
123
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { type InferUITools } from 'ai';
|
|
2
|
+
import { designPrompt } from './prompts.js';
|
|
3
|
+
import { ds } from '../form-builder/model/ds.js';
|
|
4
|
+
import { confirmToCreateForm } from '../form-builder/tools/index.js';
|
|
5
|
+
import { EnhancedAgent } from '../utils/index.js';
|
|
6
|
+
|
|
7
|
+
const tools = {
|
|
8
|
+
confirmToCreateForm,
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export type DesignTools = InferUITools<typeof tools>;
|
|
12
|
+
|
|
13
|
+
export type DesignConfirmPayload = {
|
|
14
|
+
formName: string;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export const DesignWithConfirmAgent = new EnhancedAgent<DesignConfirmPayload, {}>(
|
|
18
|
+
{
|
|
19
|
+
system: designPrompt,
|
|
20
|
+
model: ds,
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
type: 'data-confirm',
|
|
24
|
+
data: {
|
|
25
|
+
type: 'tool-confirmToCreateForm',
|
|
26
|
+
payload: {
|
|
27
|
+
formName: '',
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
{},
|
|
32
|
+
(_, body) => {
|
|
33
|
+
return {
|
|
34
|
+
formName: body.name,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
export const createDisigner = () => {
|
|
40
|
+
return new EnhancedAgent<{ formName: string }, {}>(
|
|
41
|
+
{
|
|
42
|
+
system: designPrompt,
|
|
43
|
+
model: ds,
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
type: 'data-confirm',
|
|
47
|
+
data: {
|
|
48
|
+
type: 'tool-confirmToCreateForm',
|
|
49
|
+
payload: {
|
|
50
|
+
formName: '',
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
{},
|
|
55
|
+
(_, body) => {
|
|
56
|
+
return {
|
|
57
|
+
formName: body.name,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
);
|
|
61
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export const designPrompt = `
|
|
2
|
+
你是表单字段设计专家,根据设计说明理解业务需求,首先对表单进行介绍,从业务角度输出简要的字段设计说明。
|
|
3
|
+
|
|
4
|
+
格式:
|
|
5
|
+
- 关联字段 label 命名无需加“关联”二字,直接像设计普通字段一样命名
|
|
6
|
+
- 关联字段创建无需特定分区和说明,像设计普通字段一样设计
|
|
7
|
+
- 统一使用中文
|
|
8
|
+
|
|
9
|
+
注意:
|
|
10
|
+
- 必须设计一个关联字段,即使在关联表中,也尝试继续生成关联字段(优先使用记录类字段)
|
|
11
|
+
- 如果设计的是关联表,设计流水号字段,用来被其他表单关联
|
|
12
|
+
- 字段数量控制在 10 个以内
|
|
13
|
+
- 涉及到合同、记录相关等信息时,使用关联字段,组织架构相关信息,无需关联
|
|
14
|
+
- 无需设计真实的表单,只需输出字段设计说明
|
|
15
|
+
- 直接根据用户输入推断需求
|
|
16
|
+
- 字段类型尽量使用多样化字段,避免单一字段类型
|
|
17
|
+
|
|
18
|
+
输出示例:
|
|
19
|
+
|
|
20
|
+
创建一张“用户信息”表,用于系统中管理和维护所有用户的基本资料和账户状态,支持用户身份识别、权限管理及后续业务流程的对接。该表是用户相关业务的核心表单,广泛应用于认证授权、客户管理、营销活动、服务交付等环节。
|
|
21
|
+
|
|
22
|
+
**字段列举:**
|
|
23
|
+
- 用户编号(唯一标识,主键)
|
|
24
|
+
- 用户姓名(真实姓名)
|
|
25
|
+
- 用户昵称(系统显示名)
|
|
26
|
+
- 账户类型(如普通用户、管理员、VIP客户等)
|
|
27
|
+
- 手机号码(用于登录和联系)
|
|
28
|
+
- 电子邮箱(用于通知与找回密码)
|
|
29
|
+
- 性别
|
|
30
|
+
- 出生日期
|
|
31
|
+
- 所在地区(省市区)
|
|
32
|
+
- 详细地址
|
|
33
|
+
- 注册渠道(如官网、App、第三方授权)
|
|
34
|
+
- 用户状态(激活、冻结、注销等)
|
|
35
|
+
- 最近登录时间
|
|
36
|
+
- 登录次数
|
|
37
|
+
- 关联账户(如公司/组织、合作伙伴)
|
|
38
|
+
- 用户等级(积分等级或会员等级)
|
|
39
|
+
- 备注说明
|
|
40
|
+
|
|
41
|
+
**关联说明:**
|
|
42
|
+
- 关联订单表(用户可关联多个订单)
|
|
43
|
+
- 关联权限角色表(实现权限管理)
|
|
44
|
+
- 关联营销活动参与记录表(用户参与的营销活动)
|
|
45
|
+
- 关联客服工单表(用户反馈与支持)
|
|
46
|
+
|
|
47
|
+
**设计说明:**
|
|
48
|
+
该表结构设计兼顾用户身份信息的完整性与业务拓展需求,注重数据的规范化和关联性。字段覆盖用户基本身份信息及账户状态,有助于实现精准营销及服务管理。可根据实际业务需求扩展用户画像字段(如兴趣爱好、行为标签),或增加多账户、多设备管理等功能。与其他业务实体的关联设计方便后续业务流程的整合和数据分析。
|
|
49
|
+
|
|
50
|
+
`;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Experimental_Agent as Agent,
|
|
3
|
+
type Experimental_AgentSettings as AgentSettings,
|
|
4
|
+
type ToolSet,
|
|
5
|
+
type UIDataTypes,
|
|
6
|
+
} from 'ai';
|
|
7
|
+
|
|
8
|
+
import { type ConfirmDataPart, type ConfirmMsg, type ValueOf } from '@baishuyun/types';
|
|
9
|
+
|
|
10
|
+
type DataUIMessageChunk<DATA_TYPES extends UIDataTypes> = ValueOf<{
|
|
11
|
+
[NAME in keyof DATA_TYPES & string]: {
|
|
12
|
+
type: `data-${NAME}`;
|
|
13
|
+
id?: string;
|
|
14
|
+
data: DATA_TYPES[NAME];
|
|
15
|
+
transient?: boolean;
|
|
16
|
+
};
|
|
17
|
+
}>;
|
|
18
|
+
|
|
19
|
+
import { convertToModelMessages, createUIMessageStream, createUIMessageStreamResponse } from 'ai';
|
|
20
|
+
|
|
21
|
+
export class EnhancedAgent<
|
|
22
|
+
ConfirmPayload,
|
|
23
|
+
TOOLS extends ToolSet,
|
|
24
|
+
OUTPUT = never,
|
|
25
|
+
OUTPUT_PARTIAL = never,
|
|
26
|
+
> {
|
|
27
|
+
private agent: Agent<TOOLS, OUTPUT, OUTPUT_PARTIAL>;
|
|
28
|
+
|
|
29
|
+
private confirmInfo?: DataUIMessageChunk<ConfirmDataPart<ConfirmPayload>>;
|
|
30
|
+
|
|
31
|
+
private context: any = {};
|
|
32
|
+
|
|
33
|
+
private buildPayload: (ctx: any, body: any) => ConfirmPayload;
|
|
34
|
+
|
|
35
|
+
public static create<
|
|
36
|
+
ConfirmPayload,
|
|
37
|
+
TOOLS extends ToolSet,
|
|
38
|
+
OUTPUT = never,
|
|
39
|
+
OUTPUT_PARTIAL = never,
|
|
40
|
+
>(
|
|
41
|
+
agentSettings: AgentSettings<TOOLS, OUTPUT, OUTPUT_PARTIAL>,
|
|
42
|
+
confirmInfo?: DataUIMessageChunk<ConfirmDataPart<ConfirmPayload>>,
|
|
43
|
+
ctx: any = {},
|
|
44
|
+
buildPayload: (ctx: any, body: any) => ConfirmPayload = () => ({}) as ConfirmPayload
|
|
45
|
+
) {
|
|
46
|
+
return new EnhancedAgent<ConfirmPayload, TOOLS, OUTPUT, OUTPUT_PARTIAL>(
|
|
47
|
+
agentSettings,
|
|
48
|
+
confirmInfo,
|
|
49
|
+
ctx,
|
|
50
|
+
buildPayload
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
public constructor(
|
|
55
|
+
agentSettings: AgentSettings<TOOLS, OUTPUT, OUTPUT_PARTIAL>,
|
|
56
|
+
confirmInfo?: DataUIMessageChunk<ConfirmDataPart<ConfirmPayload>>,
|
|
57
|
+
ctx: any = {},
|
|
58
|
+
buildPayload: (ctx: any, body: any) => ConfirmPayload = () => ({}) as ConfirmPayload
|
|
59
|
+
) {
|
|
60
|
+
if (ctx) {
|
|
61
|
+
this.context = {
|
|
62
|
+
...this.context,
|
|
63
|
+
...ctx,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
this.agent = new Agent({
|
|
68
|
+
...agentSettings,
|
|
69
|
+
experimental_context: this.context,
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
this.buildPayload = buildPayload;
|
|
73
|
+
|
|
74
|
+
this.confirmInfo = confirmInfo;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
public getCtx() {
|
|
78
|
+
return this.context;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
public getResp(originalMessages: any, body: any) {
|
|
82
|
+
const stream = createUIMessageStream<ConfirmMsg<ConfirmPayload>>({
|
|
83
|
+
originalMessages,
|
|
84
|
+
execute: async ({ writer }) => {
|
|
85
|
+
const result = this.agent.stream({
|
|
86
|
+
messages: convertToModelMessages(originalMessages),
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
// 将结果写入流
|
|
90
|
+
writer.merge(result.toUIMessageStream({ originalMessages }));
|
|
91
|
+
|
|
92
|
+
for await (const _ of result.fullStream) {
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (this.confirmInfo) {
|
|
96
|
+
this.confirmInfo.data.payload = this.buildPayload(this.context, body);
|
|
97
|
+
writer.write(this.confirmInfo);
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
return createUIMessageStreamResponse({ stream });
|
|
103
|
+
}
|
|
104
|
+
}
|