@mybricks/plugin-ai 0.0.1 → 0.0.2
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/package.json +7 -2
- package/src/agents/app.ts +188 -60
- package/src/agents/common.ts +428 -68
- package/src/agents/custom.ts +14 -0
- package/src/agents/index.ts +31 -1
- package/src/agents/knowledges/README.md +614 -0
- package/src/agents/knowledges/SUMMARY.md +527 -0
- package/src/agents/knowledges/index.ts +8 -0
- package/src/agents/knowledges/knowledge-base.ts +565 -0
- package/src/agents/knowledges/knowledge-node.ts +266 -0
- package/src/agents/knowledges/types.ts +208 -0
- package/src/agents/utils/config.ts +427 -0
- package/src/agents/workspace/coding-manager.ts +31 -0
- package/src/agents/workspace/components-manager.ts +124 -0
- package/src/agents/workspace/outline-focus.ts +188 -0
- package/src/agents/workspace/outline-info.ts +520 -0
- package/src/agents/workspace/page-tree-generator.ts +83 -0
- package/src/agents/workspace/workspace.ts +319 -0
- package/src/agents/workspace-by-knowledges/MIGRATION.md +568 -0
- package/src/agents/workspace-by-knowledges/README.md +521 -0
- package/src/agents/workspace-by-knowledges/index.ts +11 -0
- package/src/agents/workspace-by-knowledges/providers/component-docs-provider.ts +92 -0
- package/src/agents/workspace-by-knowledges/providers/focus-info-provider.ts +131 -0
- package/src/agents/workspace-by-knowledges/providers/index.ts +8 -0
- package/src/agents/workspace-by-knowledges/providers/project-info-provider.ts +151 -0
- package/src/agents/workspace-by-knowledges/test.ts +240 -0
- package/src/agents/workspace-by-knowledges/types.ts +56 -0
- package/src/agents/workspace-by-knowledges/utils/components-manager.ts +145 -0
- package/src/agents/workspace-by-knowledges/utils/index.ts +8 -0
- package/src/agents/workspace-by-knowledges/utils/outline-focus.ts +178 -0
- package/src/agents/workspace-by-knowledges/utils/outline-info.ts +521 -0
- package/src/agents/workspace-by-knowledges/workspace.ts +166 -0
- package/src/api/cloud-components.ts +129 -0
- package/src/api-record-replay/README.md +187 -0
- package/src/api-record-replay/index.ts +11 -0
- package/src/api-record-replay/manager.ts +168 -0
- package/src/api-record-replay/recorder.ts +117 -0
- package/src/api-record-replay/replayer.ts +148 -0
- package/src/components/attachments/index.less +117 -0
- package/src/components/attachments/index.tsx +136 -0
- package/src/components/icons/index.tsx +21 -1
- package/src/components/index.less +34 -0
- package/src/components/mention/index.less +23 -0
- package/src/components/mention/index.tsx +19 -0
- package/src/components/messages/index.less +444 -237
- package/src/components/messages/index.tsx +371 -88
- package/src/components/sender/index.less +203 -0
- package/src/components/sender/index.tsx +298 -0
- package/src/components/types.ts +31 -0
- package/src/constants/index.ts +8 -0
- package/src/context/RequestStatusTracker.ts +50 -0
- package/src/context/index.ts +68 -6
- package/src/{types.d.ts → global.d.ts} +40 -5
- package/src/index.tsx +212 -32
- package/src/preset/agents.ts +380 -0
- package/src/preset/createTemplates.ts +25 -0
- package/src/preset/index.ts +12 -0
- package/src/preset/prompts.ts +235 -0
- package/src/preset/requestAsStream.ts +246 -0
- package/src/preset/user.ts +6 -0
- package/src/startView/components/header/header.less +17 -0
- package/src/startView/components/header/header.tsx +15 -0
- package/src/startView/components/index.ts +1 -0
- package/src/startView/index.less +22 -204
- package/src/startView/index.tsx +35 -203
- package/src/tools/analyze-and-expand-prd.ts +192 -86
- package/src/tools/analyze-requirement-and-components.ts +589 -0
- package/src/tools/answer.ts +59 -0
- package/src/tools/build-process.ts +1174 -0
- package/src/tools/coding-subagent-as-tool.ts +119 -0
- package/src/tools/generate-ui-content.ts +1083 -0
- package/src/tools/index.ts +22 -19
- package/src/tools/open-dsl.ts +69 -0
- package/src/tools/refactor-ui-content.ts +801 -0
- package/src/tools/utils.ts +880 -28
- package/src/types/index.ts +4 -0
- package/src/view/components/header/header.less +36 -2
- package/src/view/components/header/header.tsx +47 -2
- package/src/view/components/index.ts +0 -2
- package/src/view/index.tsx +158 -8
- package/src/tools/answer-user.ts +0 -35
- package/src/tools/focus-element.ts +0 -47
- package/src/tools/generate-page.ts +0 -750
- package/src/tools/get-component-info-by-ids.ts +0 -166
- package/src/tools/get-component-info.ts +0 -53
- package/src/tools/get-components-doc-and-prd.ts +0 -137
- package/src/tools/get-focus-mybricks-dsl.ts +0 -26
- package/src/tools/get-mybricks-dsl.ts +0 -73
- package/src/tools/modify-component.ts +0 -385
- package/src/view/components/messages/messages.less +0 -228
- package/src/view/components/messages/messages.tsx +0 -172
- package/src/view/components/sender/sender.less +0 -44
- package/src/view/components/sender/sender.tsx +0 -62
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
.header {
|
|
2
2
|
width: 100%;
|
|
3
3
|
height: 40px;
|
|
4
|
+
min-height: 40px;
|
|
4
5
|
display: flex;
|
|
5
6
|
align-items: center;
|
|
6
|
-
padding: 0
|
|
7
|
-
justify-content: space-between;
|
|
7
|
+
padding: 0 60px 0 13px;
|
|
8
|
+
// justify-content: space-between;
|
|
8
9
|
border-bottom: 1px solid #f3f3f3;
|
|
10
|
+
background: rgba(255, 255, 255, .8);
|
|
11
|
+
gap: 6px;
|
|
9
12
|
|
|
10
13
|
.title {
|
|
11
14
|
font-weight: 700;
|
|
@@ -14,4 +17,35 @@
|
|
|
14
17
|
line-height: 18px;
|
|
15
18
|
cursor: default;
|
|
16
19
|
}
|
|
20
|
+
|
|
21
|
+
.actions {
|
|
22
|
+
display: flex;
|
|
23
|
+
align-items: center;
|
|
24
|
+
|
|
25
|
+
.action {
|
|
26
|
+
display: flex;
|
|
27
|
+
align-items: center;
|
|
28
|
+
cursor: pointer;
|
|
29
|
+
color: #AAA;
|
|
30
|
+
width: 20px;
|
|
31
|
+
height: 20px;
|
|
32
|
+
justify-content: center;
|
|
33
|
+
|
|
34
|
+
&:hover {
|
|
35
|
+
color: var(--mybricks-color-primary, #FA6400);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
svg {
|
|
39
|
+
width: 12px;
|
|
40
|
+
height: 12px;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
&.export {
|
|
44
|
+
svg {
|
|
45
|
+
width: 14px;
|
|
46
|
+
height: 14px;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
17
51
|
}
|
|
@@ -1,15 +1,60 @@
|
|
|
1
1
|
import React from "react"
|
|
2
2
|
import classNames from "classnames"
|
|
3
|
+
import { Rxai } from "@mybricks/rxai";
|
|
4
|
+
import { Delete, Export } from "../../../components/icons"
|
|
5
|
+
import { context } from "../../../context";
|
|
3
6
|
import css from "./header.less"
|
|
4
7
|
|
|
5
|
-
|
|
8
|
+
interface HeaderParams {
|
|
9
|
+
rxai: Rxai;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const Header = (params: HeaderParams) => {
|
|
13
|
+
const clear = () => {
|
|
14
|
+
params.rxai.clear();
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const exportRxai = async () => {
|
|
18
|
+
try {
|
|
19
|
+
const content = await params.rxai.export();
|
|
20
|
+
downloadToFile({
|
|
21
|
+
content: content,
|
|
22
|
+
name: `rxai-${new Date().getTime()}.json`
|
|
23
|
+
})
|
|
24
|
+
} catch (e) {
|
|
25
|
+
console.error("[@mybricks/plugin-ai - exportRxai - error]", e);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
6
29
|
return (
|
|
7
30
|
<div className={classNames(css.header)}>
|
|
8
31
|
<span className={classNames(css.title)}>
|
|
9
|
-
MyBricks.ai
|
|
32
|
+
{/* MyBricks.ai */}
|
|
33
|
+
智能助手
|
|
10
34
|
</span>
|
|
35
|
+
<div className={css['actions']}>
|
|
36
|
+
<div className={css['action']} data-mybricks-tip={"清空对话记录"} onClick={clear}>
|
|
37
|
+
<Delete />
|
|
38
|
+
</div>
|
|
39
|
+
<div className={classNames(css['action'], css['export'])} data-mybricks-tip={"导出对话记录"} onClick={exportRxai}>
|
|
40
|
+
<Export />
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
11
43
|
</div>
|
|
12
44
|
)
|
|
13
45
|
}
|
|
14
46
|
|
|
15
47
|
export { Header }
|
|
48
|
+
|
|
49
|
+
function downloadToFile ({ content, name }: { content: any, name: string }) {
|
|
50
|
+
const eleLink = document.createElement('a')
|
|
51
|
+
eleLink.download = name
|
|
52
|
+
eleLink.style.display = 'none'
|
|
53
|
+
|
|
54
|
+
const blob = new Blob([JSON.stringify(content)])
|
|
55
|
+
|
|
56
|
+
eleLink.href = URL.createObjectURL(blob)
|
|
57
|
+
document.body.appendChild(eleLink)
|
|
58
|
+
eleLink.click()
|
|
59
|
+
document.body.removeChild(eleLink)
|
|
60
|
+
}
|
package/src/view/index.tsx
CHANGED
|
@@ -1,18 +1,168 @@
|
|
|
1
|
-
import React from "react"
|
|
1
|
+
import React, { useEffect, useRef, useState } from "react"
|
|
2
2
|
import classNames from "classnames";
|
|
3
|
-
import { Header
|
|
3
|
+
import { Header } from "./components";
|
|
4
4
|
import { Messages } from "../components/messages";
|
|
5
|
+
import { Sender, SenderRef, SenderProps } from "../components/sender";
|
|
5
6
|
import { context } from "../context";
|
|
7
|
+
import { Agents } from '../agents'
|
|
8
|
+
import { AbstractAgent } from "../agents/utils/config";
|
|
6
9
|
import css from "./index.less";
|
|
7
10
|
|
|
8
|
-
|
|
11
|
+
interface ViewProps {
|
|
12
|
+
api: AiViewApi;
|
|
13
|
+
user: any;
|
|
14
|
+
copilot: any;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const View = ({ user, copilot, api }: ViewProps) => {
|
|
18
|
+
const senderRef = useRef<SenderRef>(null);
|
|
19
|
+
const [rxai, setRxai] = useState(context.rxai);
|
|
20
|
+
const [vibeCoding, setVibeCoding] = useState(false);
|
|
21
|
+
|
|
22
|
+
const PLACEHOLDER_MAP = {
|
|
23
|
+
normal: `您好,我是${context.name},请详细描述您的需求`,
|
|
24
|
+
disabled: `您好,我是${context.name},请先从画布中选择场景或组件,再开始对话`,
|
|
25
|
+
loading: "处理中,请稍后..."
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const [senderStateProps, setSenderStateProps] = useState(() => {
|
|
29
|
+
return {
|
|
30
|
+
loading: false,
|
|
31
|
+
disabled: true,
|
|
32
|
+
placeholder: PLACEHOLDER_MAP["disabled"]
|
|
33
|
+
}
|
|
34
|
+
})
|
|
35
|
+
const focusID = useRef<string>(null);
|
|
36
|
+
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
const statusChange = (state: "loading" | "normal" | "disabled") => {
|
|
39
|
+
if (state === "disabled") {
|
|
40
|
+
setSenderStateProps({
|
|
41
|
+
disabled: true,
|
|
42
|
+
loading: false,
|
|
43
|
+
placeholder: PLACEHOLDER_MAP["disabled"]
|
|
44
|
+
})
|
|
45
|
+
} else {
|
|
46
|
+
const bool = state === "loading";
|
|
47
|
+
setSenderStateProps({
|
|
48
|
+
disabled: bool,
|
|
49
|
+
loading: bool,
|
|
50
|
+
placeholder: PLACEHOLDER_MAP[state]
|
|
51
|
+
})
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const disconnectAiViewDisplay = context.events.on("aiViewDisplay", () => {
|
|
56
|
+
setTimeout(() => {
|
|
57
|
+
senderRef.current!.focus();
|
|
58
|
+
})
|
|
59
|
+
}, true)
|
|
60
|
+
const disconnectFocus = context.events.on("focus", (focus) => {
|
|
61
|
+
if (!focus) {
|
|
62
|
+
senderRef.current!.setMentions([]);
|
|
63
|
+
focusID.current = null;
|
|
64
|
+
statusChange("disabled");
|
|
65
|
+
setRxai(context.rxai);
|
|
66
|
+
} else {
|
|
67
|
+
const type = focus.type;
|
|
68
|
+
const id = ["page", "section"].includes(type) ? focus.pageId : focus.comId;
|
|
69
|
+
const { onProgress, ...other } = focus;
|
|
70
|
+
senderRef.current!.setMentions([other] as any);
|
|
71
|
+
setVibeCoding(other.vibeCoding || false);
|
|
72
|
+
focusID.current = id;
|
|
73
|
+
const status = context.requestStatusTracker.getStatus(id);
|
|
74
|
+
statusChange(status.state === "pending" ? "loading" : "normal");
|
|
75
|
+
// setTimeout(() => {
|
|
76
|
+
// senderRef.current!.focus();
|
|
77
|
+
// })
|
|
78
|
+
if (focus.vibeCoding) {
|
|
79
|
+
setTimeout(() => {
|
|
80
|
+
// TODO: ai组件库里注册agents的时机不对
|
|
81
|
+
const agent = context.agents!.find((agent) => {
|
|
82
|
+
return agent instanceof AbstractAgent && agent.type === "vibeCoding"
|
|
83
|
+
});
|
|
84
|
+
if (agent) {
|
|
85
|
+
const rxai = (agent as AbstractAgent).getRxai({
|
|
86
|
+
key: `${context.pluginParams.key}_${focus.pageId}_${focus.comId}`,
|
|
87
|
+
})
|
|
88
|
+
setRxai(rxai);
|
|
89
|
+
} else {
|
|
90
|
+
setRxai(context.rxai);
|
|
91
|
+
}
|
|
92
|
+
})
|
|
93
|
+
} else {
|
|
94
|
+
setRxai(context.rxai);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}, true)
|
|
98
|
+
const disconnectPromiseStatusTracker = context.requestStatusTracker.events.on("promise", (promise) => {
|
|
99
|
+
if (promise.id === focusID.current) {
|
|
100
|
+
statusChange(promise.status.state === "pending" ? "loading" : "normal");
|
|
101
|
+
}
|
|
102
|
+
})
|
|
103
|
+
return () => {
|
|
104
|
+
disconnectAiViewDisplay()
|
|
105
|
+
disconnectFocus()
|
|
106
|
+
disconnectPromiseStatusTracker()
|
|
107
|
+
}
|
|
108
|
+
}, [])
|
|
109
|
+
|
|
110
|
+
const onSend = (sendMessage: Parameters<SenderProps["onSend"]>[0]) => {
|
|
111
|
+
const { message, attachments, ...extension } = sendMessage;
|
|
112
|
+
|
|
113
|
+
if (!focusID.current) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
context.requestStatusTracker.track(focusID.current, Agents.requestAgent({
|
|
118
|
+
message,
|
|
119
|
+
attachments,
|
|
120
|
+
extension,
|
|
121
|
+
onProgress: context.currentFocus?.onProgress
|
|
122
|
+
}));
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const onMentionClick: NonNullable<SenderProps["onMentionClick"]> = (mention) => {
|
|
126
|
+
const { id, type, comId, pageId } = mention;
|
|
127
|
+
api[type === "page" ? "focusPage" : "focusCom"]((type === "page" ? pageId : comId) || id as string);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const onMessagesSend = (sendMessage: Parameters<SenderProps["onSend"]>[0]) => {
|
|
131
|
+
const { message, attachments, insertAfter, ...extension } = sendMessage;
|
|
132
|
+
const { mentions } = extension
|
|
133
|
+
const mention = sendMessage.mentions[0];
|
|
134
|
+
context.requestStatusTracker.track(mention.type === "page" ? mention.pageId : mention.comId, Agents.requestAgent({
|
|
135
|
+
message,
|
|
136
|
+
attachments,
|
|
137
|
+
insertAfter,
|
|
138
|
+
extension,
|
|
139
|
+
focus: mentions[0],
|
|
140
|
+
onProgress: context.currentFocus?.onProgress
|
|
141
|
+
}));
|
|
142
|
+
}
|
|
143
|
+
|
|
9
144
|
return (
|
|
10
|
-
<div className={classNames(css.view)}>
|
|
11
|
-
<Header />
|
|
12
|
-
<Messages
|
|
13
|
-
|
|
145
|
+
<div className={classNames(css.view)} style={vibeCoding ? ({ '--mybricks-color-primary': '#16A157' } as React.CSSProperties) : undefined}>
|
|
146
|
+
<Header rxai={rxai}/>
|
|
147
|
+
<Messages
|
|
148
|
+
key={rxai.key}
|
|
149
|
+
user={user}
|
|
150
|
+
copilot={copilot}
|
|
151
|
+
rxai={rxai}
|
|
152
|
+
onSend={onMessagesSend}
|
|
153
|
+
onMentionClick={onMentionClick}
|
|
154
|
+
/>
|
|
155
|
+
<Sender
|
|
156
|
+
ref={senderRef}
|
|
157
|
+
loading={senderStateProps.loading}
|
|
158
|
+
placeholder={senderStateProps.placeholder}
|
|
159
|
+
disabled={senderStateProps.disabled}
|
|
160
|
+
mode="mention"
|
|
161
|
+
onSend={onSend}
|
|
162
|
+
onMentionClick={onMentionClick}
|
|
163
|
+
/>
|
|
14
164
|
</div>
|
|
15
165
|
)
|
|
16
166
|
}
|
|
17
167
|
|
|
18
|
-
export { View }
|
|
168
|
+
export { View }
|
package/src/tools/answer-user.ts
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { fileFormat } from '@mybricks/rxai'
|
|
2
|
-
|
|
3
|
-
interface AnswerUserParams {
|
|
4
|
-
// 暂无配置参数,未来可扩展语气风格、知识库范围等
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export default function answerUser(config: AnswerUserParams): any {
|
|
8
|
-
return {
|
|
9
|
-
name: 'answer-user',
|
|
10
|
-
displayName: "专家思考中",
|
|
11
|
-
description: `回答用户在页面搭建过程中/对话中的问题。
|
|
12
|
-
参数:用户提出的问题(文本),前面工具仅获取一些小白难以理解的内容;
|
|
13
|
-
作用:理解用户意图,针对搭建专用术语和前面工具的复杂返回,为用户提供清晰、准确、与 MyBricks 平台相关的解答或引导;
|
|
14
|
-
返回值:一段自然语言回答;
|
|
15
|
-
|
|
16
|
-
建议使用场景:
|
|
17
|
-
1. 前置只有一个获取DSL工具,返回的是MyBricksDsl
|
|
18
|
-
2. 前置只有一个获取组件配置文档,返回的是专业的组件知识
|
|
19
|
-
`,
|
|
20
|
-
getPrompts: () => {
|
|
21
|
-
return `<工具总览>
|
|
22
|
-
你是一个 MyBricks 低代码平台的智能问答助手,专注于解答用户在页面/组件搭建过程中提出的各类问题。
|
|
23
|
-
你需要根据历史对话记录,为用户解答疑难问题。
|
|
24
|
-
</工具总览>
|
|
25
|
-
|
|
26
|
-
<人设>
|
|
27
|
-
你是一个能将复杂问题通俗易懂进行解释的MyBricks 平台专家,擅长用简单易懂的语言帮助用户理解问题。
|
|
28
|
-
</人设>
|
|
29
|
-
`;
|
|
30
|
-
},
|
|
31
|
-
execute({ content }) {
|
|
32
|
-
return content;
|
|
33
|
-
}
|
|
34
|
-
};
|
|
35
|
-
}
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { fileFormat } from '@mybricks/rxai'
|
|
2
|
-
|
|
3
|
-
interface FocusElementToolParams {
|
|
4
|
-
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export default function focusElement(config: FocusElementToolParams, ): Tool {
|
|
8
|
-
return {
|
|
9
|
-
name: 'focus-element',
|
|
10
|
-
description: `通过id聚焦到任何可聚焦的页面 / 组件。
|
|
11
|
-
参数:页面ID或者组件ID;
|
|
12
|
-
作用:聚焦到某个可搭建的元素上,获取元素元信息,用于后续搭建;
|
|
13
|
-
返回值:聚焦元素的元信息,格式是包含id、type(component / page)、namespace(可能存在)字段的对象;
|
|
14
|
-
`,
|
|
15
|
-
getPrompts: () => {
|
|
16
|
-
return `<工具总览>
|
|
17
|
-
你是一个可以聚焦页面/组件的工具,你作为MyBricks低代码平台(以下简称MyBricks平台或MyBricks)的资深页面搭建助手,可以根据需求聚焦元素用于下一步的搭建。
|
|
18
|
-
</工具总览>
|
|
19
|
-
|
|
20
|
-
<任务流程>
|
|
21
|
-
按照以下格式返回所要聚焦的元素:
|
|
22
|
-
${fileFormat({ content: '{ "id": "u_1sd23" }', fileName: '聚焦元素ID.json' })}
|
|
23
|
-
- 注意:文件要严格按照JSON格式返回,注意不要出现语法错误;
|
|
24
|
-
</任务流程>`
|
|
25
|
-
},
|
|
26
|
-
execute({ files, content }) {
|
|
27
|
-
let selectFile: File | undefined = undefined;
|
|
28
|
-
Object.keys(files).forEach((fileKey) => {
|
|
29
|
-
const file: File = files[fileKey] as File;
|
|
30
|
-
if (file.extension === 'json') {
|
|
31
|
-
selectFile = file
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
let selectFileId = {};
|
|
37
|
-
try {
|
|
38
|
-
selectFileId = JSON.parse(selectFile?.content);
|
|
39
|
-
} catch (error) {}
|
|
40
|
-
|
|
41
|
-
return `<当前选中元素情况>
|
|
42
|
-
ID: ${selectFileId.id}
|
|
43
|
-
类型:页面
|
|
44
|
-
</当前选中元素情况>`
|
|
45
|
-
},
|
|
46
|
-
}
|
|
47
|
-
}
|