@baishuyun/chat-sdk 0.0.17 → 0.0.18
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/.turbo/turbo-build.log +178 -115
- package/CHANGELOG.md +8 -0
- package/dist/chat-sdk.js +26425 -34262
- package/dist/chat-sdk.js.map +1 -1
- package/dist/chat-sdk.umd.cjs +219 -296
- package/dist/chat-sdk.umd.cjs.map +1 -1
- package/dist/index.css +1 -1
- package/package.json +4 -4
- package/src/chat.tsx +4 -1
- package/src/components/biz-comp/chat-client.tsx +1 -1
- package/src/components/biz-comp/multi-modal-input/index.tsx +22 -5
- package/src/components/biz-comp/preview-message.tsx +25 -3
- package/src/components/bs-ui/attachment-part-group.tsx +5 -2
- package/src/components/bs-ui/attachment-part.tsx +14 -9
- package/src/components/bs-ui/attachments-previewer.tsx +2 -2
- package/src/components/bs-ui/base-button.tsx +14 -4
- package/src/components/bs-ui/border-animation.tsx +107 -0
- package/src/components/bs-ui/bs-icons.tsx +6 -0
- package/src/components/bs-ui/confirm-dialog.tsx +17 -11
- package/src/components/bs-ui/fields-previewer.tsx +16 -8
- package/src/components/bs-ui/img-part.tsx +4 -2
- package/src/components/bs-ui/previewer-header.tsx +26 -7
- package/src/components/bs-ui/primary-entry-btn.tsx +2 -1
- package/src/index.tsx +0 -1
- package/src/lib/utils.ts +60 -2
- package/src/plugins/form-builder-plugin/components/create-form-confirm.tsx +0 -2
- package/src/plugins/form-builder-plugin/components/design-doc-part.tsx +19 -0
- package/src/plugins/form-builder-plugin/components/fields-part.tsx +78 -0
- package/src/plugins/form-builder-plugin/components/msg-part.tsx +20 -165
- package/src/plugins/form-builder-plugin/components/suggestion-part.tsx +62 -0
- package/src/plugins/form-builder-plugin/hooks/index.tsx +50 -0
- package/src/plugins/form-builder-plugin/index.ts +39 -30
- package/src/plugins/form-builder-plugin/types.ts +19 -2
- package/src/plugins/form-builder-plugin/utils/get-render-strategy.ts +27 -0
- package/src/plugins/form-builder-plugin/utils/index.ts +44 -37
- package/src/plugins/form-filling-plugin/components/FormFillingOpeningLines.tsx +4 -0
- package/src/plugins/form-filling-plugin/components/batch-fill-part.tsx +17 -0
- package/src/plugins/form-filling-plugin/components/batch-generator-action.tsx +6 -1
- package/src/plugins/form-filling-plugin/components/entry-btn.tsx +1 -1
- package/src/plugins/form-filling-plugin/components/first-batch-generating-animation.tsx +6 -16
- package/src/plugins/form-filling-plugin/components/msg-part.tsx +39 -122
- package/src/plugins/form-filling-plugin/components/non-first-batch-generating-animation.tsx +9 -19
- package/src/plugins/form-filling-plugin/components/single-fill-part.tsx +42 -0
- package/src/plugins/form-filling-plugin/hooks/use-conversation-id-in-ctx.ts +13 -0
- package/src/plugins/form-filling-plugin/hooks/use-fields-data.ts +110 -0
- package/src/plugins/form-filling-plugin/index.ts +49 -43
- package/src/plugins/form-filling-plugin/types.ts +19 -1
- package/src/plugins/report-query-plugin/components/query-msg-part.tsx +13 -4
- package/src/plugins/report-query-plugin/index.ts +20 -11
- package/src/store/index.ts +0 -1
- package/src/stories/BorderAnimation.stories.tsx +116 -0
- package/src/stories/PreviewerHeader.stories.tsx +24 -0
- package/src/style.css +25 -0
- package/src/plugins/form-builder-plugin/hooks/index.ts +0 -0
- package/src/plugins/general-model-form-builder-plugin/components/confirmer.tsx +0 -90
- package/src/plugins/general-model-form-builder-plugin/components/ghost-evt-dispatcher.tsx +0 -69
- package/src/plugins/general-model-form-builder-plugin/components/msg-part.tsx +0 -147
- package/src/plugins/general-model-form-builder-plugin/components/new-confirmer.tsx +0 -191
- package/src/plugins/general-model-form-builder-plugin/const.ts +0 -3
- package/src/plugins/general-model-form-builder-plugin/index.ts +0 -20
- package/src/plugins/general-model-form-builder-plugin/types.ts +0 -1
|
@@ -1,178 +1,33 @@
|
|
|
1
1
|
import { MarkdownMsgpart } from '@/components/biz-comp/markdown-part';
|
|
2
|
-
import { MessageContent } from '@/components/biz-comp/message-content';
|
|
3
|
-
import { FollowUp } from './follow-up';
|
|
4
2
|
|
|
5
|
-
import {
|
|
6
|
-
GetFieldJsonInfo,
|
|
7
|
-
getIconValue,
|
|
8
|
-
IsFieldsJsonPart,
|
|
9
|
-
IsSuggesstionPart,
|
|
10
|
-
NeedToAppendFieldsSaveConfirm,
|
|
11
|
-
} from '@/lib/utils';
|
|
12
|
-
import { MsgPartCompProps, RealFormInfo } from '@baishuyun/types';
|
|
3
|
+
import { MsgPartCompProps } from '@baishuyun/types';
|
|
13
4
|
import { TextUIPart } from 'ai';
|
|
14
5
|
import { useFieldsConfirmed } from '../hooks/use-fields-confirmed';
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
import { McpFormBuilderPluginCtx } from '../types';
|
|
30
|
-
import { DesignInfo } from './design-info';
|
|
31
|
-
import { useRef } from 'react';
|
|
6
|
+
import { FormBuildPartRenderStrategyMap } from '../types';
|
|
7
|
+
import { FieldsPart } from './fields-part';
|
|
8
|
+
import { SuggestionPart, SuggestionPrefixPart } from './suggestion-part';
|
|
9
|
+
import { getRenderStrategy } from '../utils/get-render-strategy';
|
|
10
|
+
import { DesignDocPart } from './design-doc-part';
|
|
11
|
+
|
|
12
|
+
const FormBuildPartRenderer: FormBuildPartRenderStrategyMap = {
|
|
13
|
+
fields: FieldsPart,
|
|
14
|
+
followup: SuggestionPart,
|
|
15
|
+
followup_prefix: SuggestionPrefixPart,
|
|
16
|
+
design_doc: DesignDocPart,
|
|
17
|
+
markdown: MarkdownMsgpart,
|
|
18
|
+
unknown: MarkdownMsgpart,
|
|
19
|
+
};
|
|
32
20
|
|
|
33
21
|
export const McpMessagePart = (props: MsgPartCompProps) => {
|
|
34
|
-
const { part: p
|
|
35
|
-
|
|
36
|
-
const fieldsConfirmed = useFieldsConfirmed();
|
|
22
|
+
const { part: p } = props;
|
|
37
23
|
|
|
38
24
|
const part = p as TextUIPart;
|
|
39
25
|
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
const isFieldsSaveConfirm = NeedToAppendFieldsSaveConfirm(part);
|
|
43
|
-
|
|
44
|
-
const evtBus = useEvtBus();
|
|
45
|
-
|
|
46
|
-
const plugin = usePlugin<FormBuilderPlugin>(MCP_PLUGIN_NAME);
|
|
47
|
-
|
|
48
|
-
const checkerRef = useRef<FieldCheckerListMsgRef>(null);
|
|
49
|
-
|
|
50
|
-
const ctx = usePluginCtx<McpFormBuilderPluginCtx, FormBuilderPlugin>(MCP_PLUGIN_NAME);
|
|
51
|
-
|
|
52
|
-
const fieldsParts = Array.isArray(part) && part.length ? part : isFieldsJson ? [part] : [];
|
|
26
|
+
const strategy = getRenderStrategy(part);
|
|
53
27
|
|
|
54
|
-
|
|
55
|
-
const fieldPropsArray = fieldsParts.map((p) => {
|
|
56
|
-
const field = GetFieldJsonInfo(p);
|
|
57
|
-
return {
|
|
58
|
-
field,
|
|
59
|
-
disabled: fieldsConfirmed,
|
|
60
|
-
onLoaded: (field: any) => {
|
|
61
|
-
const finalField = plugin?.onBeforeFieldCreate(field);
|
|
62
|
-
evtBus.emit('form-builder-FieldCreated', {
|
|
63
|
-
field: finalField,
|
|
64
|
-
checked: true,
|
|
65
|
-
});
|
|
66
|
-
plugin?.onAfterFieldCreate(field);
|
|
67
|
-
},
|
|
68
|
-
icon: <FieldIcon type={field.widget?.type} />,
|
|
69
|
-
onChange: (check: boolean, field: any, parentFieldName?: string, index?: number) => {
|
|
70
|
-
console.log('field checked changed:', { check, field, parentFieldName, index });
|
|
71
|
-
evtBus.emit('form-builder-FieldCheckedChanged', {
|
|
72
|
-
field,
|
|
73
|
-
checked: check,
|
|
74
|
-
parentFieldName,
|
|
75
|
-
index,
|
|
76
|
-
});
|
|
77
|
-
},
|
|
78
|
-
};
|
|
79
|
-
});
|
|
28
|
+
const PartComp = FormBuildPartRenderer[strategy] || MarkdownMsgpart;
|
|
80
29
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
return (
|
|
84
|
-
<MessageContent className="gap-0 py-0" compact>
|
|
85
|
-
<div>
|
|
86
|
-
<b style={{ display: 'inline-block' }}>{formName}</b>
|
|
87
|
-
{` 已生成${fieldPropsArray.length}个字段`}
|
|
88
|
-
</div>
|
|
89
|
-
<FieldCheckerListMsg
|
|
90
|
-
ref={checkerRef}
|
|
91
|
-
fields={fieldPropsArray}
|
|
92
|
-
streaming={status === 'streaming'}
|
|
93
|
-
confirmed={fieldsConfirmed}
|
|
94
|
-
>
|
|
95
|
-
{status === 'ready' ? (
|
|
96
|
-
<PrimaryConfirmBtn
|
|
97
|
-
className="mt-[20px] mb-[10px]"
|
|
98
|
-
disabledWithInfo={fieldsConfirmed}
|
|
99
|
-
onClick={() => {
|
|
100
|
-
evtBus.emit(
|
|
101
|
-
'form-builder-FieldsConfirmed',
|
|
102
|
-
plugin?.getCurrentWorkingForm() as RealFormInfo
|
|
103
|
-
);
|
|
104
|
-
plugin.onAfterFieldsSave((processedInfo) => {
|
|
105
|
-
evtBus.emit('form-builder-FieldsConfirmed', processedInfo as RealFormInfo);
|
|
106
|
-
});
|
|
107
|
-
}}
|
|
108
|
-
>
|
|
109
|
-
{fieldsConfirmed ? (
|
|
110
|
-
<>
|
|
111
|
-
<CheckerIcon className="text-[#0265ff]" /> 已保存{' '}
|
|
112
|
-
{checkerRef.current?.getCheckedFieldsLength() ?? 0} 个字段
|
|
113
|
-
</>
|
|
114
|
-
) : (
|
|
115
|
-
'保存字段'
|
|
116
|
-
)}
|
|
117
|
-
</PrimaryConfirmBtn>
|
|
118
|
-
) : null}
|
|
119
|
-
</FieldCheckerListMsg>
|
|
120
|
-
{status === 'ready'
|
|
121
|
-
? '请选择需要的字段添加到表单。您可以补充描述后重新生成,表单中已添加字段在下次生成时保留。'
|
|
122
|
-
: null}
|
|
123
|
-
</MessageContent>
|
|
124
|
-
);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// suggestion
|
|
128
|
-
if (IsSuggesstionPart(part)) {
|
|
129
|
-
return fieldsConfirmed ? (
|
|
130
|
-
<FollowUp
|
|
131
|
-
title={part.text}
|
|
132
|
-
description={part.text}
|
|
133
|
-
onSelect={(title, icon) => {
|
|
134
|
-
if (ctx) {
|
|
135
|
-
ctx.workStage === 'design';
|
|
136
|
-
|
|
137
|
-
console.log('follow up icon code', icon);
|
|
138
|
-
console.log('follow up icon value', getIconValue(icon));
|
|
139
|
-
ctx.pickedIconValue = getIconValue(icon);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
sendMessage(
|
|
143
|
-
{ text: title },
|
|
144
|
-
{
|
|
145
|
-
body: {
|
|
146
|
-
stage: 'design',
|
|
147
|
-
},
|
|
148
|
-
}
|
|
149
|
-
);
|
|
150
|
-
}}
|
|
151
|
-
headless
|
|
152
|
-
/>
|
|
153
|
-
) : null;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
// save fields confirm
|
|
157
|
-
if (isFieldsSaveConfirm) {
|
|
158
|
-
const formInfo = plugin?.getCurrentWorkingForm() as RealFormInfo;
|
|
159
|
-
evtBus.emit('form-builder-FieldsCreatedFinish', formInfo);
|
|
160
|
-
return <>{fieldsConfirmed ? <FakeBotMessage>试试以下建议</FakeBotMessage> : null}</>;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
const appendConfirmBtn =
|
|
164
|
-
// TODO: 特殊文本解析在 node 端处理,前端只负责渲染
|
|
165
|
-
part.text?.includes('【确认搭建');
|
|
166
|
-
|
|
167
|
-
const isDesignDoc = part.text?.startsWith('待搭建表单信息');
|
|
30
|
+
const fieldsConfirmed = useFieldsConfirmed();
|
|
168
31
|
|
|
169
|
-
return
|
|
170
|
-
<DesignInfo designMarkdown={part.text} id={props.id}>
|
|
171
|
-
{appendConfirmBtn ? (
|
|
172
|
-
<CreateFormConfirm sendMessage={sendMessage} designDoc={part.text} />
|
|
173
|
-
) : null}
|
|
174
|
-
</DesignInfo>
|
|
175
|
-
) : (
|
|
176
|
-
<MarkdownMsgpart {...props}></MarkdownMsgpart>
|
|
177
|
-
);
|
|
32
|
+
return <PartComp {...props} part={part} confirmed={fieldsConfirmed} />;
|
|
178
33
|
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { MsgPartCompProps, RealFormInfo } from '@baishuyun/types';
|
|
2
|
+
import { IExtraPartProps, McpFormBuilderPluginCtx } from '../types';
|
|
3
|
+
import { FollowUp } from './follow-up';
|
|
4
|
+
import { TextUIPart } from 'ai';
|
|
5
|
+
import { usePluginCtx } from '@/hooks/use-plugin-ctx';
|
|
6
|
+
import { FormBuilderPlugin } from '..';
|
|
7
|
+
import { MCP_PLUGIN_NAME } from '../const';
|
|
8
|
+
import { getIconValue } from '@/lib/utils';
|
|
9
|
+
import { usePlugin } from '@/hooks/use-plugin';
|
|
10
|
+
import { FakeBotMessage } from '@/components/biz-comp/FakeBotMsg';
|
|
11
|
+
import { useEffect } from 'react';
|
|
12
|
+
import { useEvtBus } from '@/hooks/use-evt-bus';
|
|
13
|
+
|
|
14
|
+
export const SuggestionPrefixPart: React.FC<MsgPartCompProps & IExtraPartProps> = (props) => {
|
|
15
|
+
const { confirmed: fieldsConfirmed } = props;
|
|
16
|
+
const plugin = usePlugin<FormBuilderPlugin>(MCP_PLUGIN_NAME);
|
|
17
|
+
const formInfo = plugin?.getCurrentWorkingForm() as RealFormInfo;
|
|
18
|
+
const evtBus = useEvtBus();
|
|
19
|
+
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
evtBus.emit('form-builder-FieldsCreatedFinish', formInfo);
|
|
22
|
+
}, []);
|
|
23
|
+
|
|
24
|
+
return <>{fieldsConfirmed ? <FakeBotMessage>试试以下建议</FakeBotMessage> : null}</>;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export const SuggestionPart: React.FC<MsgPartCompProps & IExtraPartProps> = (props) => {
|
|
28
|
+
const { confirmed, sendMessage, part: p } = props;
|
|
29
|
+
const part = p as TextUIPart;
|
|
30
|
+
|
|
31
|
+
const ctx = usePluginCtx<McpFormBuilderPluginCtx, FormBuilderPlugin>(MCP_PLUGIN_NAME);
|
|
32
|
+
|
|
33
|
+
if (!confirmed) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return (
|
|
38
|
+
<FollowUp
|
|
39
|
+
title={part.text}
|
|
40
|
+
description={part.text}
|
|
41
|
+
onSelect={(title, icon) => {
|
|
42
|
+
if (ctx) {
|
|
43
|
+
ctx.workStage === 'design';
|
|
44
|
+
|
|
45
|
+
console.log('follow up icon code', icon);
|
|
46
|
+
console.log('follow up icon value', getIconValue(icon));
|
|
47
|
+
ctx.pickedIconValue = getIconValue(icon);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
sendMessage(
|
|
51
|
+
{ text: title },
|
|
52
|
+
{
|
|
53
|
+
body: {
|
|
54
|
+
stage: 'design',
|
|
55
|
+
},
|
|
56
|
+
}
|
|
57
|
+
);
|
|
58
|
+
}}
|
|
59
|
+
headless
|
|
60
|
+
/>
|
|
61
|
+
);
|
|
62
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { TextUIPart } from 'ai';
|
|
2
|
+
import { usePlugin } from '@/hooks/use-plugin';
|
|
3
|
+
import { useEvtBus } from '@/hooks/use-evt-bus';
|
|
4
|
+
import { GetFieldJsonInfo, IsFieldsJsonPart } from '@/lib/utils';
|
|
5
|
+
import { FormBuilderPlugin } from '..';
|
|
6
|
+
import { MCP_PLUGIN_NAME } from '../const';
|
|
7
|
+
import { FieldValueCheckerProps } from '@/components/biz-comp/FieldValueChecker';
|
|
8
|
+
import { FieldIcon } from '@/components/biz-comp/field-icon';
|
|
9
|
+
|
|
10
|
+
export const useBuildFieldsData = (part: TextUIPart, fieldsConfirmed: boolean) => {
|
|
11
|
+
const isFieldsJson = IsFieldsJsonPart(part);
|
|
12
|
+
const fieldsParts = Array.isArray(part) && part.length ? part : isFieldsJson ? [part] : [];
|
|
13
|
+
|
|
14
|
+
const evtBus = useEvtBus();
|
|
15
|
+
|
|
16
|
+
const plugin = usePlugin<FormBuilderPlugin>(MCP_PLUGIN_NAME);
|
|
17
|
+
|
|
18
|
+
return fieldsParts
|
|
19
|
+
.map((p) => {
|
|
20
|
+
const field = GetFieldJsonInfo(p);
|
|
21
|
+
|
|
22
|
+
if (!field?.widget) {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
field,
|
|
28
|
+
disabled: fieldsConfirmed,
|
|
29
|
+
onLoaded: (field: any) => {
|
|
30
|
+
const finalField = plugin?.onBeforeFieldCreate(field);
|
|
31
|
+
evtBus.emit('form-builder-FieldCreated', {
|
|
32
|
+
field: finalField,
|
|
33
|
+
checked: true,
|
|
34
|
+
});
|
|
35
|
+
plugin?.onAfterFieldCreate(field);
|
|
36
|
+
},
|
|
37
|
+
icon: <FieldIcon type={field.widget?.type} />,
|
|
38
|
+
onChange: (check: boolean, field: any, parentFieldName?: string, index?: number) => {
|
|
39
|
+
console.log('field checked changed:', { check, field, parentFieldName, index });
|
|
40
|
+
evtBus.emit('form-builder-FieldCheckedChanged', {
|
|
41
|
+
field,
|
|
42
|
+
checked: check,
|
|
43
|
+
parentFieldName,
|
|
44
|
+
index,
|
|
45
|
+
});
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
})
|
|
49
|
+
.filter(Boolean) as Array<FieldValueCheckerProps>;
|
|
50
|
+
};
|
|
@@ -20,9 +20,10 @@ import {
|
|
|
20
20
|
hasSubFields,
|
|
21
21
|
hasLinkInfo,
|
|
22
22
|
fieldProcessorFactory,
|
|
23
|
+
ensureCleanFormName,
|
|
23
24
|
} from './utils';
|
|
24
25
|
import { EVENTS } from '../form-builder-base-plugin/const';
|
|
25
|
-
import { IsFieldsJsonPart, mergeConsecutiveTargets } from '@/lib/utils';
|
|
26
|
+
import { ensureEndSlash, IsFieldsJsonPart, mergeConsecutiveTargets } from '@/lib/utils';
|
|
26
27
|
import { EntryButton } from './components/entry-btn';
|
|
27
28
|
import { FormBuilderOpeningLines } from './components/opening-lines';
|
|
28
29
|
|
|
@@ -45,10 +46,6 @@ export class FormBuilderPlugin extends FormBuilderBasePlugin<McpFormBuilderPlugi
|
|
|
45
46
|
OpeningLines: FormBuilderOpeningLines,
|
|
46
47
|
};
|
|
47
48
|
|
|
48
|
-
// clear cwf(current working form) when workStage is build, which means rebuild fields from scratch.
|
|
49
|
-
// 1. clear fields.
|
|
50
|
-
// 2. clear fieldMap.
|
|
51
|
-
// 3. rebuild linkInfo based on rebuild fields?
|
|
52
49
|
private clearCurrentWorkingForm = () => {
|
|
53
50
|
if (this.Context.workStage !== 'build') {
|
|
54
51
|
// 仅在搭建阶段清空当前表单信息
|
|
@@ -60,14 +57,6 @@ export class FormBuilderPlugin extends FormBuilderBasePlugin<McpFormBuilderPlugi
|
|
|
60
57
|
return;
|
|
61
58
|
}
|
|
62
59
|
|
|
63
|
-
// 清空当前表单字段信息
|
|
64
|
-
cwf.fields = [];
|
|
65
|
-
cwf.fieldMap.clear();
|
|
66
|
-
|
|
67
|
-
// TODO: 清空当前表单关联信息
|
|
68
|
-
// cwf.designInfo.linkInfoMap.clear();
|
|
69
|
-
|
|
70
|
-
// 触发字段清空事件,通知更新状态
|
|
71
60
|
const evtBus = this._chatInstance?.eventBus;
|
|
72
61
|
if (evtBus) {
|
|
73
62
|
evtBus.emit<'form-builder-FieldsCleared'>(EVENTS.FIELDS_CLEARED, {});
|
|
@@ -76,15 +65,7 @@ export class FormBuilderPlugin extends FormBuilderBasePlugin<McpFormBuilderPlugi
|
|
|
76
65
|
|
|
77
66
|
public lifecycleHooks?: Partial<PluginHooks> | undefined = {
|
|
78
67
|
onBeforeMessagesClear: (conversationId) => {
|
|
79
|
-
|
|
80
|
-
await fetch(`https://agent.online-office.net/web/api/form/conversation/clear`, {
|
|
81
|
-
method: 'POST',
|
|
82
|
-
body: JSON.stringify({ conversationId }),
|
|
83
|
-
});
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
req();
|
|
87
|
-
|
|
68
|
+
this.clearHistoryConversation(conversationId || '', this._chatInstance || undefined);
|
|
88
69
|
this.Context.workStage = 'design';
|
|
89
70
|
},
|
|
90
71
|
onBeforeMessagePartsRender(parts: Array<part>) {
|
|
@@ -99,12 +80,20 @@ export class FormBuilderPlugin extends FormBuilderBasePlugin<McpFormBuilderPlugi
|
|
|
99
80
|
body: {
|
|
100
81
|
stage: this.Context.workStage,
|
|
101
82
|
name: this.getCurrentWorkingForm()?.formName || text,
|
|
83
|
+
text,
|
|
102
84
|
},
|
|
103
85
|
},
|
|
104
86
|
};
|
|
105
87
|
},
|
|
106
|
-
onAfterChatAreaHide({ clearMsgs }) {
|
|
88
|
+
onAfterChatAreaHide: ({ clearMsgs }) => {
|
|
107
89
|
clearMsgs();
|
|
90
|
+
|
|
91
|
+
this.clearCurrentWorkingForm();
|
|
92
|
+
|
|
93
|
+
this.Context = {
|
|
94
|
+
formMap: new Map(),
|
|
95
|
+
workStage: 'design',
|
|
96
|
+
};
|
|
108
97
|
},
|
|
109
98
|
onBeforeChatRender: () => {
|
|
110
99
|
return {
|
|
@@ -162,6 +151,24 @@ export class FormBuilderPlugin extends FormBuilderBasePlugin<McpFormBuilderPlugi
|
|
|
162
151
|
}
|
|
163
152
|
}
|
|
164
153
|
|
|
154
|
+
private clearHistoryConversation = async (conversationId: string, inst?: IChatSDK) => {
|
|
155
|
+
const apiEndpoint = inst?.options.backendApiEndpoint;
|
|
156
|
+
if (!apiEndpoint) {
|
|
157
|
+
console.error('Backend API endpoint is not defined in SDK options.');
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (!conversationId) {
|
|
162
|
+
console.error('Conversation ID is required to clear history.');
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
await fetch(`${ensureEndSlash(apiEndpoint)}form/conversation/clear`, {
|
|
167
|
+
method: 'POST',
|
|
168
|
+
body: JSON.stringify({ conversationId }),
|
|
169
|
+
});
|
|
170
|
+
};
|
|
171
|
+
|
|
165
172
|
private enhanceField(field: Field) {
|
|
166
173
|
const processorCreator = fieldProcessorFactory[field.widget.type as FieldType];
|
|
167
174
|
if (!processorCreator) {
|
|
@@ -258,19 +265,17 @@ export class FormBuilderPlugin extends FormBuilderBasePlugin<McpFormBuilderPlugi
|
|
|
258
265
|
this.Context.pickedIconValue = 33;
|
|
259
266
|
};
|
|
260
267
|
|
|
261
|
-
public onAfterFieldsSave(onFormProcessed: (processedForm: FormInfo) => void) {
|
|
268
|
+
public onAfterFieldsSave = (onFormProcessed: (processedForm: FormInfo) => void) => {
|
|
262
269
|
// 取当前正在处理的表单 current working form
|
|
263
270
|
const cwf = this.getCurrentWorkingForm();
|
|
264
271
|
if (!cwf) {
|
|
265
272
|
return;
|
|
266
273
|
}
|
|
267
274
|
|
|
268
|
-
// 上下文中表单字段遍历,识别需要回写的表单、字段
|
|
269
275
|
formFieldsWalker(this.Context.formMap, {
|
|
270
276
|
// 目标表单筛选
|
|
271
277
|
isTargetForm: (formName: string, formInfo: FormInfo) => {
|
|
272
278
|
if (formName === cwf.formName) {
|
|
273
|
-
console.log('跳过自身表单');
|
|
274
279
|
return false;
|
|
275
280
|
}
|
|
276
281
|
|
|
@@ -284,16 +289,21 @@ export class FormBuilderPlugin extends FormBuilderBasePlugin<McpFormBuilderPlugi
|
|
|
284
289
|
|
|
285
290
|
// 目标字段筛选
|
|
286
291
|
isTargetField: (_: string, linkInfo: LinkInfo) => {
|
|
287
|
-
|
|
288
|
-
return linkInfo.targetFormName === cwf.formName;
|
|
292
|
+
return ensureCleanFormName(linkInfo.targetFormName) === ensureCleanFormName(cwf.formName!);
|
|
289
293
|
},
|
|
290
294
|
|
|
291
295
|
// 字段处理,补全关联信息
|
|
292
296
|
fieldProcessor: (formInfo: FormInfo, field: Field, linkInfo: LinkInfo) => {
|
|
297
|
+
if (!field) {
|
|
298
|
+
console.log('[fieldProcessor] 字段信息不存在,跳过处理');
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
|
|
293
302
|
const fieldType = field.widget?.type as FieldType;
|
|
294
303
|
|
|
295
304
|
// 没有对应的处理器,跳过
|
|
296
305
|
if (!fieldProcessorFactory[fieldType]) {
|
|
306
|
+
console.log(`[fieldProcessor] 未找到${fieldType}类型的处理器,跳过处理`);
|
|
297
307
|
return;
|
|
298
308
|
}
|
|
299
309
|
|
|
@@ -307,7 +317,7 @@ export class FormBuilderPlugin extends FormBuilderBasePlugin<McpFormBuilderPlugi
|
|
|
307
317
|
|
|
308
318
|
onFormProcessed,
|
|
309
319
|
});
|
|
310
|
-
}
|
|
320
|
+
};
|
|
311
321
|
|
|
312
322
|
public getCurrentWorkingForm() {
|
|
313
323
|
return this.Context.formMap.get(this.currentWorkingFormName);
|
|
@@ -324,7 +334,6 @@ export const FormBuilderPluginRegisterEntry: PluginRegistryEntry<McpFormBuilderP
|
|
|
324
334
|
createContext: () => {
|
|
325
335
|
return {
|
|
326
336
|
formMap: new Map(),
|
|
327
|
-
|
|
328
337
|
workStage: 'design', // 默认设计阶段
|
|
329
338
|
};
|
|
330
339
|
},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { FieldsTools } from '@baishuyun/agents';
|
|
2
|
-
import { FormBuilderWorkStage, ValueOf } from '@baishuyun/types';
|
|
3
|
-
import { ToolUIPart } from 'ai';
|
|
2
|
+
import { FormBuilderWorkStage, MsgPartCompProps, ValueOf } from '@baishuyun/types';
|
|
3
|
+
import { TextUIPart, ToolUIPart } from 'ai';
|
|
4
4
|
import { DesignInfo } from './utils';
|
|
5
5
|
|
|
6
6
|
export type Field = ValueOf<Pick<ToolUIPart<FieldsTools>, 'output'>>;
|
|
@@ -24,3 +24,20 @@ export interface McpFormBuilderPluginCtx {
|
|
|
24
24
|
|
|
25
25
|
pickedIconValue?: number;
|
|
26
26
|
}
|
|
27
|
+
|
|
28
|
+
export type FormBuildPartRenderStrategy =
|
|
29
|
+
| 'fields'
|
|
30
|
+
| 'followup'
|
|
31
|
+
| 'followup_prefix'
|
|
32
|
+
| 'design_doc'
|
|
33
|
+
| 'markdown'
|
|
34
|
+
| 'unknown';
|
|
35
|
+
|
|
36
|
+
export interface IExtraPartProps {
|
|
37
|
+
confirmed?: boolean;
|
|
38
|
+
part: TextUIPart;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export type FormBuildPartRenderStrategyMap = {
|
|
42
|
+
[key in FormBuildPartRenderStrategy]: React.FC<MsgPartCompProps & IExtraPartProps>;
|
|
43
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { IsFieldsJsonPart, IsSuggesstionPart, NeedToAppendFieldsSaveConfirm } from '@/lib/utils';
|
|
2
|
+
import { TextUIPart } from 'ai';
|
|
3
|
+
|
|
4
|
+
export const getRenderStrategy = (part: TextUIPart) => {
|
|
5
|
+
const isFieldsJson = IsFieldsJsonPart(part);
|
|
6
|
+
const fieldsParts = Array.isArray(part) && part.length ? part : isFieldsJson ? [part] : [];
|
|
7
|
+
|
|
8
|
+
if (fieldsParts.length) {
|
|
9
|
+
return 'fields';
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (IsSuggesstionPart(part)) {
|
|
13
|
+
return 'followup';
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const isFieldsSaveConfirm = NeedToAppendFieldsSaveConfirm(part);
|
|
17
|
+
if (isFieldsSaveConfirm) {
|
|
18
|
+
return 'followup_prefix';
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const isDesignDoc = part.text?.startsWith('待搭建表单信息');
|
|
22
|
+
if (isDesignDoc) {
|
|
23
|
+
return 'design_doc';
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return 'markdown';
|
|
27
|
+
};
|