@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.
Files changed (93) hide show
  1. package/package.json +7 -2
  2. package/src/agents/app.ts +188 -60
  3. package/src/agents/common.ts +428 -68
  4. package/src/agents/custom.ts +14 -0
  5. package/src/agents/index.ts +31 -1
  6. package/src/agents/knowledges/README.md +614 -0
  7. package/src/agents/knowledges/SUMMARY.md +527 -0
  8. package/src/agents/knowledges/index.ts +8 -0
  9. package/src/agents/knowledges/knowledge-base.ts +565 -0
  10. package/src/agents/knowledges/knowledge-node.ts +266 -0
  11. package/src/agents/knowledges/types.ts +208 -0
  12. package/src/agents/utils/config.ts +427 -0
  13. package/src/agents/workspace/coding-manager.ts +31 -0
  14. package/src/agents/workspace/components-manager.ts +124 -0
  15. package/src/agents/workspace/outline-focus.ts +188 -0
  16. package/src/agents/workspace/outline-info.ts +520 -0
  17. package/src/agents/workspace/page-tree-generator.ts +83 -0
  18. package/src/agents/workspace/workspace.ts +319 -0
  19. package/src/agents/workspace-by-knowledges/MIGRATION.md +568 -0
  20. package/src/agents/workspace-by-knowledges/README.md +521 -0
  21. package/src/agents/workspace-by-knowledges/index.ts +11 -0
  22. package/src/agents/workspace-by-knowledges/providers/component-docs-provider.ts +92 -0
  23. package/src/agents/workspace-by-knowledges/providers/focus-info-provider.ts +131 -0
  24. package/src/agents/workspace-by-knowledges/providers/index.ts +8 -0
  25. package/src/agents/workspace-by-knowledges/providers/project-info-provider.ts +151 -0
  26. package/src/agents/workspace-by-knowledges/test.ts +240 -0
  27. package/src/agents/workspace-by-knowledges/types.ts +56 -0
  28. package/src/agents/workspace-by-knowledges/utils/components-manager.ts +145 -0
  29. package/src/agents/workspace-by-knowledges/utils/index.ts +8 -0
  30. package/src/agents/workspace-by-knowledges/utils/outline-focus.ts +178 -0
  31. package/src/agents/workspace-by-knowledges/utils/outline-info.ts +521 -0
  32. package/src/agents/workspace-by-knowledges/workspace.ts +166 -0
  33. package/src/api/cloud-components.ts +129 -0
  34. package/src/api-record-replay/README.md +187 -0
  35. package/src/api-record-replay/index.ts +11 -0
  36. package/src/api-record-replay/manager.ts +168 -0
  37. package/src/api-record-replay/recorder.ts +117 -0
  38. package/src/api-record-replay/replayer.ts +148 -0
  39. package/src/components/attachments/index.less +117 -0
  40. package/src/components/attachments/index.tsx +136 -0
  41. package/src/components/icons/index.tsx +21 -1
  42. package/src/components/index.less +34 -0
  43. package/src/components/mention/index.less +23 -0
  44. package/src/components/mention/index.tsx +19 -0
  45. package/src/components/messages/index.less +444 -237
  46. package/src/components/messages/index.tsx +371 -88
  47. package/src/components/sender/index.less +203 -0
  48. package/src/components/sender/index.tsx +298 -0
  49. package/src/components/types.ts +31 -0
  50. package/src/constants/index.ts +8 -0
  51. package/src/context/RequestStatusTracker.ts +50 -0
  52. package/src/context/index.ts +68 -6
  53. package/src/{types.d.ts → global.d.ts} +40 -5
  54. package/src/index.tsx +212 -32
  55. package/src/preset/agents.ts +380 -0
  56. package/src/preset/createTemplates.ts +25 -0
  57. package/src/preset/index.ts +12 -0
  58. package/src/preset/prompts.ts +235 -0
  59. package/src/preset/requestAsStream.ts +246 -0
  60. package/src/preset/user.ts +6 -0
  61. package/src/startView/components/header/header.less +17 -0
  62. package/src/startView/components/header/header.tsx +15 -0
  63. package/src/startView/components/index.ts +1 -0
  64. package/src/startView/index.less +22 -204
  65. package/src/startView/index.tsx +35 -203
  66. package/src/tools/analyze-and-expand-prd.ts +192 -86
  67. package/src/tools/analyze-requirement-and-components.ts +589 -0
  68. package/src/tools/answer.ts +59 -0
  69. package/src/tools/build-process.ts +1174 -0
  70. package/src/tools/coding-subagent-as-tool.ts +119 -0
  71. package/src/tools/generate-ui-content.ts +1083 -0
  72. package/src/tools/index.ts +22 -19
  73. package/src/tools/open-dsl.ts +69 -0
  74. package/src/tools/refactor-ui-content.ts +801 -0
  75. package/src/tools/utils.ts +880 -28
  76. package/src/types/index.ts +4 -0
  77. package/src/view/components/header/header.less +36 -2
  78. package/src/view/components/header/header.tsx +47 -2
  79. package/src/view/components/index.ts +0 -2
  80. package/src/view/index.tsx +158 -8
  81. package/src/tools/answer-user.ts +0 -35
  82. package/src/tools/focus-element.ts +0 -47
  83. package/src/tools/generate-page.ts +0 -750
  84. package/src/tools/get-component-info-by-ids.ts +0 -166
  85. package/src/tools/get-component-info.ts +0 -53
  86. package/src/tools/get-components-doc-and-prd.ts +0 -137
  87. package/src/tools/get-focus-mybricks-dsl.ts +0 -26
  88. package/src/tools/get-mybricks-dsl.ts +0 -73
  89. package/src/tools/modify-component.ts +0 -385
  90. package/src/view/components/messages/messages.less +0 -228
  91. package/src/view/components/messages/messages.tsx +0 -172
  92. package/src/view/components/sender/sender.less +0 -44
  93. package/src/view/components/sender/sender.tsx +0 -62
@@ -0,0 +1,4 @@
1
+ export enum DeviceType {
2
+ Desktop = 'desktop',
3
+ Mobile = 'mobile'
4
+ }
@@ -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 40px 0 8px;
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
- const Header = () => {
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
+ }
@@ -1,3 +1 @@
1
1
  export * from "./header/header";
2
- export * from "./messages/messages";
3
- export * from "./sender/sender";
@@ -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, Sender } from "./components";
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
- const View = ({ user, copilot }: any) => {
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 user={user} copilot={copilot} rxai={context.rxai}/>
13
- <Sender />
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 }
@@ -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
- }