@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,246 @@
1
+ import forge from "node-forge";
2
+
3
+ function generateRandomKey(length: number) {
4
+ const chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
5
+ let result = "";
6
+ for (let i = 0; i < length; i++) {
7
+ const randomIndex = Math.floor(Math.random() * chars.length);
8
+ result += chars[randomIndex];
9
+ }
10
+ return result;
11
+ }
12
+
13
+ function getAiEncryptData(params: { mode: any; data: unknown }) {
14
+ const { mode, data } = params;
15
+ if (mode === "development") {
16
+ return data;
17
+ }
18
+ const PUBLIC_KEY = `-----BEGIN PUBLIC KEY-----
19
+ MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1ITWRl6ePMu7Fhusup2d
20
+ FEz/hCRTE5mUIeGIjtezG5g8ewBdTaR2FRxtTFONYTaaSR6yFXm9k74tkS1/i0Z8
21
+ 7eIV130XydOn4zFhk2sOkG46mQ+lZwJkyVwvMaAOCnHluTIaPMPMV3sYpp3cWspl
22
+ 2H++R5/kOGVm6EG9HivrimQEKDDJLg9owbfWO2kSEM9ZpUHUt29msYq+lDtBrivG
23
+ oodvC8p5H4a/jXKvLtPRGO09ZO3xk1ktS8isc376Ec9L9Zo8wSwaj5Z/Pg7nd7Sa
24
+ tqj5BEj3YH8rSr1dg77ZMMH1lsuzdA0NHmRGYEvWnUoD6dMqjJjufNwAw9D47DQH
25
+ lwIDAQAB
26
+ -----END PUBLIC KEY-----`;
27
+
28
+ // 生成一个随机的AES密钥
29
+ const AESKey = generateRandomKey(16);
30
+
31
+ // 用AES密钥加密数据
32
+ const cipher = forge.cipher.createCipher("AES-CBC", AESKey);
33
+ cipher.start({ iv: AESKey });
34
+ cipher.update(
35
+ forge.util.createBuffer(forge.util.encodeUtf8(JSON.stringify(data))),
36
+ );
37
+ cipher.finish();
38
+ const encryptedData = forge.util.encode64(cipher.output.getBytes());
39
+
40
+ // 使用RSA公钥加密AES密钥
41
+ const publicKey = forge.pki.publicKeyFromPem(PUBLIC_KEY);
42
+ const encryptedAESKey = forge.util.encode64(publicKey.encrypt(AESKey));
43
+
44
+ return { chatContent: encryptedData, chatKey: encryptedAESKey };
45
+ }
46
+
47
+ const logger = {
48
+ info(message: string) {
49
+ console.log(
50
+ "%c%s%c %s",
51
+ "background-color: #fa6400; color: #ffffff;padding: 0px 6px",
52
+ "AI-SDK",
53
+ "color: #ffffff",
54
+ message,
55
+ );
56
+ },
57
+ };
58
+
59
+ enum FetchTarget {
60
+ CustomApp = "CustomApp",
61
+ Platform = "Platform",
62
+ Center = "Center",
63
+ }
64
+
65
+ let fetchTaget: FetchTarget;
66
+
67
+ async function checkFetchTarget(): Promise<FetchTarget> {
68
+ if (fetchTaget) {
69
+ return Promise.resolve(fetchTaget);
70
+ }
71
+
72
+ /** 如果安装了自定义的AI服务,请求自定义服务 */
73
+ const hasAICustomApp = await fetch("/api/ai-service/check-config")
74
+ .then((res) => {
75
+ return res.json();
76
+ })
77
+ .then((data: any) => {
78
+ if (data?.code === 1) {
79
+ return true;
80
+ } else {
81
+ return false;
82
+ }
83
+ })
84
+ .catch((e: any) => {
85
+ return false;
86
+ });
87
+
88
+ if (hasAICustomApp) {
89
+ logger.info("使用自定义服务");
90
+ return (fetchTaget = FetchTarget.CustomApp);
91
+ }
92
+
93
+ /** 如果配置了平台token,请求平台服务 */
94
+ const hasPlatformToken = await fetch("/api/assistant/status")
95
+ .then((res) => {
96
+ return res.json();
97
+ })
98
+ .then((data: any) => {
99
+ if (data?.code === 1) {
100
+ return true;
101
+ } else {
102
+ return false;
103
+ }
104
+ })
105
+ .catch((e: any) => {
106
+ return false;
107
+ });
108
+
109
+ if (hasPlatformToken) {
110
+ logger.info("使用平台服务");
111
+ return (fetchTaget = FetchTarget.Platform);
112
+ }
113
+
114
+ logger.info("使用AI服务");
115
+ return (fetchTaget = FetchTarget.Center);
116
+ }
117
+
118
+ const transfromExtendParams = (extendParams: { aiRole?: string }) => {
119
+ const { aiRole } = extendParams;
120
+ let model = "google/gemini-3-flash-preview";
121
+ let role = "default";
122
+
123
+ if (!aiRole) {
124
+ return {
125
+ model,
126
+ role,
127
+ };
128
+ }
129
+
130
+ switch (true) {
131
+ case ["image"].includes(aiRole): {
132
+ model = "anthropic/claude-sonnet-4.5";
133
+ role = "image";
134
+ break;
135
+ }
136
+ case ["junior"].includes(aiRole): {
137
+ model = "z-ai/glm-4.7";
138
+ role = "junior";
139
+ break;
140
+ }
141
+ case ["architect"].includes(aiRole): {
142
+ model = "google/gemini-3-pro-preview";
143
+ role = "architect";
144
+ break;
145
+ }
146
+ case ["expert"].includes(aiRole): {
147
+ model = "anthropic/claude-sonnet-4.5";
148
+ role = "expert";
149
+ break;
150
+ }
151
+ default: {
152
+ role = "default";
153
+ break;
154
+ }
155
+ }
156
+
157
+ return {
158
+ model,
159
+ role,
160
+ };
161
+ };
162
+
163
+ export type RequestAsStreamMode = "development" | "production";
164
+
165
+ const createRequestAsStream = (mode: RequestAsStreamMode) =>
166
+ async (params: {
167
+ messages: any;
168
+ emits: any;
169
+ aiRole?: any;
170
+ }) => {
171
+ const { messages, emits, aiRole } = params;
172
+ const { cancel, write, complete, error } = emits;
173
+
174
+ if (mode !== "development") {
175
+ await checkFetchTarget();
176
+ }
177
+
178
+ const extendParams = transfromExtendParams({ aiRole });
179
+
180
+ try {
181
+ const controller = new AbortController();
182
+
183
+ let streamUrl = "//ai.mybricks.world/stream-with-tools";
184
+ if (fetchTaget === FetchTarget.CustomApp) {
185
+ streamUrl = "/api/ai-service/stream";
186
+ } else if (fetchTaget === FetchTarget.Platform) {
187
+ streamUrl = "/api/assistant/stream";
188
+ }
189
+
190
+ fetch(
191
+ mode === "development" ? "//ai.mybricks.world/stream-test" : streamUrl,
192
+ {
193
+ signal: controller.signal,
194
+ method: "POST",
195
+ credentials: "include", // 跨域时携带 cookie
196
+ headers: {
197
+ "Content-Type": "application/json",
198
+ ...(extendParams.role
199
+ ? {
200
+ "M-Request-Role": extendParams.role,
201
+ }
202
+ : {}),
203
+ },
204
+ body: JSON.stringify(
205
+ mode === "development"
206
+ ? {
207
+ messages,
208
+ ...extendParams,
209
+ }
210
+ : getAiEncryptData({
211
+ mode,
212
+ data: {
213
+ messages,
214
+ ...extendParams,
215
+ },
216
+ }),
217
+ ),
218
+ },
219
+ ).then(async (response) => {
220
+ cancel(() => {
221
+ //注册回调
222
+ controller.abort(); //取消请求
223
+ });
224
+
225
+ const reader = response.body!.getReader();
226
+ const decoder = new TextDecoder();
227
+
228
+ while (true) {
229
+ const { done, value } = await reader.read();
230
+
231
+ if (done) {
232
+ break;
233
+ }
234
+
235
+ const chunk = decoder.decode(value, { stream: true });
236
+ write(chunk);
237
+ }
238
+
239
+ complete("");
240
+ });
241
+ } catch (ex) {
242
+ error(ex as any);
243
+ }
244
+ };
245
+
246
+ export { createRequestAsStream };
@@ -0,0 +1,6 @@
1
+ const user = {
2
+ name: "user",
3
+ avatar: "https://my.mybricks.world/default_avatar.png"
4
+ }
5
+
6
+ export { user }
@@ -0,0 +1,17 @@
1
+ .header {
2
+ color: var(--mybricks-color-primary);
3
+ flex-wrap: wrap;
4
+ justify-content: center;
5
+ align-items: center;
6
+ margin-bottom: 8px;
7
+ font-size: 24px;
8
+ font-weight: 600;
9
+ line-height: 32px;
10
+ display: flex;
11
+
12
+ img {
13
+ width: 40px;
14
+ height: 40px;
15
+ object-fit: cover;
16
+ }
17
+ }
@@ -0,0 +1,15 @@
1
+ import React from "react"
2
+ import classNames from "classnames"
3
+ import css from "./header.less"
4
+
5
+ const Header = () => {
6
+ return (
7
+ <div className={classNames(css.header)}>
8
+ 欢迎使用
9
+ {/* <img src="https://my.mybricks.world/image/icon.png"/>
10
+ MyBricks.ai */}
11
+ </div>
12
+ )
13
+ }
14
+
15
+ export { Header }
@@ -0,0 +1 @@
1
+ export * from "./header/header";
@@ -1,216 +1,34 @@
1
- .editor {
2
- z-index: 13;
3
- position: relative;
4
- background-color: #ffffff;
5
- border: solid 1px rgba(0, 0, 0, .13);
1
+ .start-view {
2
+ width: 80%;
6
3
  max-width: 768px;
7
- width: 100%;
8
- border-radius: 20px;
9
- box-shadow: 0 5px 16px -4px #00000012;
10
- color: rgba(0, 0, 0, .9);
11
- cursor: default;
12
-
13
- .topArea {
14
- padding: 12px;
15
- display: flex;
16
- gap: 8px;
17
- align-items: center;
18
- box-shadow: 0 .5px 0 0 rgba(0, 0, 0, .13);
19
-
20
- .imageThumbnail {
21
- cursor: pointer;
22
- pointer-events: auto;
23
- flex-shrink: 0;
24
- width: 56px;
25
- aspect-ratio: 1;
26
- min-width: 56px;
27
- border-radius: 8px;
28
- border: 1px solid rgba(0, 0, 0, .13);
29
- position: relative;
30
-
31
- img {
32
- width: 100%;
33
- height: 100%;
34
- display: inline-block;
35
- background-repeat: no-repeat;
36
- background-size: cover;
37
- overflow: hidden;
38
- }
39
-
40
- .imageDeleteContainer {
41
- cursor: pointer;
42
- position: absolute;
43
- top: 0;
44
- right: 0;
45
- padding: 4px;
46
- z-index: 2;
47
-
48
- .imageDeleteIcon {
49
- width: 12px;
50
- height: 12px;
51
- border-radius: 50%;
52
- background-color: rgba(0, 0, 0, .4);
53
- display: flex;
54
- align-items: center;
55
- justify-content: center;
56
- color: #ffffff;
57
4
 
58
- svg {
59
- width: 8px;
60
- height: 8px;
61
- }
62
-
63
- &:hover {
64
- opacity: 0.8;
65
- background-color: var(--mybricks-color-primary);
66
- }
67
- }
68
- }
69
- }
70
- }
71
-
72
- .input {
73
- padding: 12px 16px 10px;
74
- line-height: 20px;
75
- min-height: 60px;
76
- position: relative;
77
-
78
- .inputEditorContainer {
79
- font-size: 12px;
80
- max-height: 140px;
81
- scrollbar-width: none;
82
- position: relative;
83
- min-height: inherit;
84
- overflow: auto;
85
-
86
- .inputEditor {
87
- user-select: text;
88
- white-space: pre-wrap;
89
- word-break: break-word;
90
- width: 100%;
91
- max-height: fit-content;
92
- min-height: inherit;
93
- overflow: hidden;
94
- outline: none;
95
- cursor: text;
96
-
97
- &[contentEditable="false"] {
98
- cursor: default;
99
- }
100
- }
101
-
102
- .inputPlaceholder {
103
- position: absolute;
104
- overflow: hidden;
105
- text-overflow: ellipsis;
106
- top: 1px;
107
- left: 1px;
108
- user-select: none;
109
- pointer-events: none;
110
- color: rgba(0, 0, 0, .6);
111
- }
112
- }
113
- }
114
-
115
- .editorAction {
116
- display: flex;
117
- justify-content: space-between;
118
- align-items: flex-end;
119
- padding: 0 8px;
120
- margin-top: 2px;
121
- margin-bottom: 8px;
122
- position: relative;
123
-
124
- .leftArea {
125
- display: flex;
126
- align-items: center;
127
-
128
- .attachmentButton {
129
- overflow: hidden;
130
- display: flex;
131
- align-items: center;
132
- justify-content: center;
133
- width: 32px;
134
- border-radius: 20px;
135
- height: 32px;
136
- cursor: pointer;
137
-
138
- svg {
139
- width: 20px;
140
- height: 20px;
141
- color: rgba(0, 0, 0, .6);
142
- }
143
-
144
- &:hover {
145
- background-color: rgba(0, 0, 0, .09);
146
- }
147
-
148
- input {
149
- display: none;
150
- }
151
- }
152
- }
153
-
154
- .rightArea {
155
- display: flex;
156
- align-items: center;
157
-
158
- .sendButtonContainer {
159
- cursor: pointer;
160
- background-color: var(--mybricks-color-primary);
161
- border-radius: 12px;
162
- display: flex;
163
- align-items: center;
164
- color: rgba(255, 255, 255, .9);
165
-
166
- .sendButton {
167
- overflow: hidden;
168
- display: flex;
169
- align-items: center;
170
- justify-content: center;
171
- width: 32px;
172
- height: 32px;
173
-
174
- svg {
175
- width: 28px;
176
- height: 28px;
177
- }
178
- }
179
-
180
- .loadingButton {
181
- svg {
182
- width: 14px;
183
- height: 14px;
184
- }
185
- }
186
- }
187
-
188
- .disabled {
189
- cursor: default;
190
- opacity: 0.5;
191
- }
192
- }
193
- }
194
-
195
- :global {
196
- * {
197
- scrollbar-color: transparent transparent;
198
- }
5
+ .editor {
6
+ width: 100%;
199
7
  }
200
8
  }
201
9
 
202
- .temp {
203
- z-index: 13;
204
- position: relative;
205
- background-color: #ffffff;
206
- border: solid 1px rgba(0, 0, 0, .13);
10
+ .view {
11
+ width: 80%;
207
12
  max-width: 768px;
208
- width: 100%;
13
+ // background-color: #ffffff;
14
+ background-color: transparent;
15
+ border: solid 1px rgba(0, 0, 0, .13);
209
16
  border-radius: 20px;
210
17
  box-shadow: 0 5px 16px -4px #00000012;
211
18
  color: rgba(0, 0, 0, .9);
212
19
  cursor: default;
213
20
  height: 80%;
214
- padding: 10px;
21
+ // padding: 10px;
22
+
215
23
  display: flex;
216
- }
24
+ flex-direction: column;
25
+
26
+ &.empty {
27
+ display: flex;
28
+ flex-direction: column;
29
+ // background-color: transparent;
30
+ border: none;
31
+ height: fit-content;
32
+ box-shadow: none;
33
+ }
34
+ }