feat: manually mirror opencoze's code from bytedance
Change-Id: I09a73aadda978ad9511264a756b2ce51f5761adf
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
const { defineConfig } = require('@coze-arch/stylelint-config');
|
||||
|
||||
module.exports = defineConfig({
|
||||
extends: [],
|
||||
});
|
||||
16
frontend/packages/agent-ide/chat-debug-area/README.md
Normal file
16
frontend/packages/agent-ide/chat-debug-area/README.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# @coze-agent-ide/chat-debug-area
|
||||
|
||||
> Project template for react component with storybook.
|
||||
|
||||
## Features
|
||||
|
||||
- [x] eslint & ts
|
||||
- [x] esm bundle
|
||||
- [x] umd bundle
|
||||
- [x] storybook
|
||||
|
||||
## Commands
|
||||
|
||||
- init: `rush update`
|
||||
- dev: `npm run dev`
|
||||
- build: `npm run build`
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"operationSettings": [
|
||||
{
|
||||
"operationName": "test:cov",
|
||||
"outputFolderNames": ["coverage"]
|
||||
},
|
||||
{
|
||||
"operationName": "ts-check",
|
||||
"outputFolderNames": ["./dist"]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
const { defineConfig } = require('@coze-arch/eslint-config');
|
||||
|
||||
module.exports = defineConfig({
|
||||
packageRoot: __dirname,
|
||||
preset: 'web',
|
||||
rules: {},
|
||||
});
|
||||
103
frontend/packages/agent-ide/chat-debug-area/package.json
Normal file
103
frontend/packages/agent-ide/chat-debug-area/package.json
Normal file
@@ -0,0 +1,103 @@
|
||||
{
|
||||
"name": "@coze-agent-ide/chat-debug-area",
|
||||
"version": "0.0.1",
|
||||
"description": "bot编辑页调试对话区",
|
||||
"license": "Apache-2.0",
|
||||
"author": "meixuliang.3@bytedance.com",
|
||||
"maintainers": [],
|
||||
"exports": {
|
||||
".": "./src/index.tsx",
|
||||
"./onboarding": "./src/components/onboarding-message-pop/index.tsx"
|
||||
},
|
||||
"main": "src/index.tsx",
|
||||
"typesVersions": {
|
||||
"*": {
|
||||
"./onboarding": [
|
||||
"./src/components/onboarding-message-pop/index.tsx"
|
||||
]
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"build": "exit 0",
|
||||
"lint": "eslint ./ --cache",
|
||||
"test": "vitest --run --passWithNoTests",
|
||||
"test:cov": "npm run test -- --coverage"
|
||||
},
|
||||
"dependencies": {
|
||||
"@coze-agent-ide/chat-answer-action-adapter": "workspace:*",
|
||||
"@coze-agent-ide/chat-area-plugin-debug-common": "workspace:*",
|
||||
"@coze-agent-ide/chat-components-adapter": "workspace:*",
|
||||
"@coze-agent-ide/onboarding": "workspace:*",
|
||||
"@coze-arch/bot-api": "workspace:*",
|
||||
"@coze-arch/bot-error": "workspace:*",
|
||||
"@coze-arch/bot-flags": "workspace:*",
|
||||
"@coze-arch/bot-hooks": "workspace:*",
|
||||
"@coze-arch/bot-semi": "workspace:*",
|
||||
"@coze-arch/bot-studio-store": "workspace:*",
|
||||
"@coze-arch/bot-tea": "workspace:*",
|
||||
"@coze-arch/bot-utils": "workspace:*",
|
||||
"@coze-arch/coze-design": "0.0.6-alpha.346d77",
|
||||
"@coze-arch/i18n": "workspace:*",
|
||||
"@coze-arch/idl": "workspace:*",
|
||||
"@coze-arch/logger": "workspace:*",
|
||||
"@coze-arch/report-events": "workspace:*",
|
||||
"@coze-arch/report-tti": "workspace:*",
|
||||
"@coze-common/chat-answer-action": "workspace:*",
|
||||
"@coze-common/chat-area": "workspace:*",
|
||||
"@coze-common/chat-area-plugin-chat-background": "workspace:*",
|
||||
"@coze-common/chat-area-plugin-message-grab": "workspace:*",
|
||||
"@coze-common/chat-area-plugin-reasoning": "workspace:*",
|
||||
"@coze-common/chat-area-plugin-resume": "workspace:*",
|
||||
"@coze-common/chat-area-plugins-chat-shortcuts": "workspace:*",
|
||||
"@coze-common/chat-core": "workspace:*",
|
||||
"@coze-common/chat-uikit": "workspace:*",
|
||||
"@coze-common/chat-workflow-render": "workspace:*",
|
||||
"@coze-studio/user-store": "workspace:*",
|
||||
"@douyinfe/semi-icons": "^2.36.0",
|
||||
"ahooks": "^3.7.8",
|
||||
"classnames": "^2.3.2",
|
||||
"copy-to-clipboard": "^3.3.3",
|
||||
"dayjs": "^1.11.7",
|
||||
"immer": "^10.0.3",
|
||||
"lodash-es": "^4.17.21",
|
||||
"nanoid": "^4.0.2",
|
||||
"use-event-callback": "~0.1.0",
|
||||
"zustand": "^4.4.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@coze-agent-ide/space-bot": "workspace:*",
|
||||
"@coze-arch/bot-env": "workspace:*",
|
||||
"@coze-arch/bot-typings": "workspace:*",
|
||||
"@coze-arch/eslint-config": "workspace:*",
|
||||
"@coze-arch/stylelint-config": "workspace:*",
|
||||
"@coze-arch/ts-config": "workspace:*",
|
||||
"@coze-arch/vitest-config": "workspace:*",
|
||||
"@coze-studio/bot-detail-store": "workspace:*",
|
||||
"@rsbuild/core": "1.1.13",
|
||||
"@testing-library/jest-dom": "^6.1.5",
|
||||
"@testing-library/react": "^14.1.2",
|
||||
"@testing-library/react-hooks": "^8.0.1",
|
||||
"@types/lodash-es": "^4.17.10",
|
||||
"@types/node": "18.18.9",
|
||||
"@types/react": "18.2.37",
|
||||
"@types/react-dom": "18.2.15",
|
||||
"@vitest/coverage-v8": "~3.0.5",
|
||||
"react": "~18.2.0",
|
||||
"react-dom": "~18.2.0",
|
||||
"react-is": ">= 16.8.0",
|
||||
"react-router-dom": "^6.22.0",
|
||||
"styled-components": ">= 2",
|
||||
"stylelint": "^15.11.0",
|
||||
"typescript": "~5.8.2",
|
||||
"vite": "^4.3.9",
|
||||
"vite-plugin-svgr": "~3.3.0",
|
||||
"vitest": "~3.0.5",
|
||||
"webpack": "~5.91.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=18.2.0",
|
||||
"react-dom": ">=18.2.0"
|
||||
},
|
||||
"// deps": "immer@^10.0.3 为脚本自动补齐,请勿改动"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
.ui-kit-onboarding {
|
||||
// figma 此处为 70px 时机 dom 为 safe area 24px + 此处 46px = 70px
|
||||
margin-top: 46px;
|
||||
padding: 0 24px
|
||||
}
|
||||
|
||||
.message {
|
||||
align-self: flex-start;
|
||||
max-width: 100%;
|
||||
margin-bottom: 8px;
|
||||
padding: 0 1px;
|
||||
}
|
||||
|
||||
.message-selectable {
|
||||
margin-left: 29px;
|
||||
}
|
||||
|
||||
.onboarding-message-content {
|
||||
word-break: break-word;
|
||||
}
|
||||
@@ -0,0 +1,243 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* eslint-disable @coze-arch/max-line-per-function */
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
import classNames from 'classnames';
|
||||
import { useDebounce, useSize, useUpdateEffect } from 'ahooks';
|
||||
import { userStoreService } from '@coze-studio/user-store';
|
||||
import { useReportTti } from '@coze-arch/report-tti';
|
||||
import {
|
||||
BotMode,
|
||||
SuggestedQuestionsShowMode,
|
||||
} from '@coze-arch/bot-api/developer_api';
|
||||
import { useBotSkillStore } from '@coze-studio/bot-detail-store/bot-skill';
|
||||
import { useBotInfoStore } from '@coze-studio/bot-detail-store/bot-info';
|
||||
import { useChatBackgroundState } from '@coze-studio/bot-detail-store';
|
||||
import {
|
||||
CozeImageWithPreview,
|
||||
CozeLink,
|
||||
LazyCozeMdBox,
|
||||
MessageBox,
|
||||
NO_MESSAGE_ID_MARK,
|
||||
OnBoarding as UIKitOnBoarding,
|
||||
} from '@coze-common/chat-uikit';
|
||||
import {
|
||||
type ComponentTypesMap,
|
||||
useOnboardingCenterOffset,
|
||||
} from '@coze-common/chat-area';
|
||||
import {
|
||||
ONBOARDING_PREVIEW_DELAY,
|
||||
OnboardingVariable,
|
||||
useRenderVariable,
|
||||
} from '@coze-agent-ide/onboarding';
|
||||
|
||||
import s from './index.module.less';
|
||||
/**
|
||||
* 当有无开场白的状态变化时, 会依次一次 reflow 同时高度发生变化, useSize 监听变化后, marginTop 改变触发一次 repaint, 导致会有两次渲染, 产生抖动
|
||||
* 现在需要调和这两次渲染
|
||||
* 需要优化 onboarding dom 结构, 使得 onboarding 的居中能力是 css 实现的, 解决这个问题
|
||||
* not-needed
|
||||
* |
|
||||
* |
|
||||
* ready-empty-onboarding <--+--> ready-onboarding
|
||||
* | |
|
||||
* | v
|
||||
* harmonized-empty-onboarding harmonized-onboarding
|
||||
* | |
|
||||
* v |
|
||||
* not-needed <------------------------+
|
||||
*/
|
||||
type HarmonizeOnboardingRender =
|
||||
| 'not-needed'
|
||||
| 'ready-empty-onboarding'
|
||||
| 'ready-onboarding'
|
||||
| 'harmonized-onboarding'
|
||||
| 'harmonized-empty-onboarding';
|
||||
|
||||
const getHarmonizedOnboardingHeight = ({
|
||||
onboardingHeight = 0,
|
||||
status,
|
||||
}: {
|
||||
onboardingHeight?: number;
|
||||
status: HarmonizeOnboardingRender;
|
||||
}) => {
|
||||
const emptyOnboardingHeight = 56;
|
||||
const contentOnboardingHeight = 118;
|
||||
switch (status) {
|
||||
case 'not-needed':
|
||||
return onboardingHeight;
|
||||
case 'ready-onboarding':
|
||||
case 'harmonized-onboarding':
|
||||
return contentOnboardingHeight;
|
||||
default:
|
||||
return emptyOnboardingHeight;
|
||||
}
|
||||
};
|
||||
|
||||
export const OnboardingMessagePop: ComponentTypesMap['onboarding'] = ({
|
||||
prologue,
|
||||
suggestions,
|
||||
sendTextMessage,
|
||||
hasMessages,
|
||||
enableImageAutoSize,
|
||||
imageAutoSizeContainerWidth,
|
||||
showBackground: showBackgroundProp,
|
||||
eventCallbacks,
|
||||
}) => {
|
||||
const [harmonizeRenders, setHarmonizeRenders] =
|
||||
useState<HarmonizeOnboardingRender>('not-needed');
|
||||
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
const onboardingSize = useSize(ref);
|
||||
const {
|
||||
avatar,
|
||||
name,
|
||||
mode,
|
||||
id = '',
|
||||
} = useBotInfoStore(
|
||||
useShallow(state => ({
|
||||
mode: state.mode,
|
||||
avatar: state.icon_url,
|
||||
name: state.name,
|
||||
id: state.botId,
|
||||
})),
|
||||
);
|
||||
const { onBoardingSuggestionWrap } = useBotSkillStore(
|
||||
useShallow(state => ({
|
||||
onBoardingSuggestionWrap:
|
||||
state.onboardingContent.suggested_questions_show_mode ===
|
||||
SuggestedQuestionsShowMode.All,
|
||||
})),
|
||||
);
|
||||
const debouncedPrologue = useDebounce(prologue, {
|
||||
wait: ONBOARDING_PREVIEW_DELAY,
|
||||
});
|
||||
const userInfo = userStoreService.useUserInfo();
|
||||
const { showBackground: showBackgroundFromChatBackgroundState } =
|
||||
useChatBackgroundState();
|
||||
const showBackground =
|
||||
showBackgroundProp ?? showBackgroundFromChatBackgroundState;
|
||||
|
||||
const renderVariable = useRenderVariable({
|
||||
[OnboardingVariable.USER_NAME]: userInfo?.name ?? '',
|
||||
});
|
||||
|
||||
// TTI
|
||||
useReportTti({
|
||||
isLive: mode === BotMode.SingleMode,
|
||||
extra: {
|
||||
mode: 'single-agent',
|
||||
},
|
||||
});
|
||||
const harmonizedHeight = getHarmonizedOnboardingHeight({
|
||||
onboardingHeight: onboardingSize?.height,
|
||||
status: harmonizeRenders,
|
||||
});
|
||||
const marginTop = useOnboardingCenterOffset({
|
||||
onboardingHeight: harmonizedHeight,
|
||||
});
|
||||
|
||||
const isOnboardingEmpty = !debouncedPrologue && !suggestions.length;
|
||||
|
||||
useUpdateEffect(() => {
|
||||
if (isOnboardingEmpty) {
|
||||
setHarmonizeRenders('ready-empty-onboarding');
|
||||
return;
|
||||
}
|
||||
setHarmonizeRenders('ready-onboarding');
|
||||
}, [isOnboardingEmpty]);
|
||||
|
||||
useEffect(() => {
|
||||
if (harmonizeRenders === 'not-needed') {
|
||||
return;
|
||||
}
|
||||
if (harmonizeRenders === 'ready-onboarding') {
|
||||
setHarmonizeRenders('harmonized-onboarding');
|
||||
return;
|
||||
}
|
||||
if (harmonizeRenders === 'ready-empty-onboarding') {
|
||||
setHarmonizeRenders('harmonized-empty-onboarding');
|
||||
return;
|
||||
}
|
||||
setHarmonizeRenders('not-needed');
|
||||
}, [onboardingSize?.height]);
|
||||
|
||||
if (hasMessages && !prologue) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (hasMessages && prologue) {
|
||||
return (
|
||||
<div className={classNames(s.message)}>
|
||||
<MessageBox
|
||||
messageId={null}
|
||||
senderInfo={{ url: avatar, nickname: name, id }}
|
||||
showUserInfo={true}
|
||||
theme="grey"
|
||||
getBotInfo={() => undefined}
|
||||
showBackground={showBackground}
|
||||
enableImageAutoSize={enableImageAutoSize}
|
||||
imageAutoSizeContainerWidth={imageAutoSizeContainerWidth}
|
||||
eventCallbacks={eventCallbacks}
|
||||
>
|
||||
<div
|
||||
className={s['onboarding-message-content']}
|
||||
data-grab-mark={NO_MESSAGE_ID_MARK}
|
||||
>
|
||||
<LazyCozeMdBox
|
||||
insertedElements={renderVariable(prologue)}
|
||||
markDown={prologue}
|
||||
autoFixSyntax={{ autoFixEnding: false }}
|
||||
slots={{
|
||||
Image: CozeImageWithPreview,
|
||||
Link: CozeLink,
|
||||
}}
|
||||
></LazyCozeMdBox>
|
||||
</div>
|
||||
</MessageBox>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<UIKitOnBoarding
|
||||
ref={ref}
|
||||
style={{ marginTop }}
|
||||
className={s['ui-kit-onboarding']}
|
||||
name={name}
|
||||
avatar={avatar}
|
||||
prologue={debouncedPrologue}
|
||||
suggestionListWithString={suggestions.map(sug => sug.content)}
|
||||
onSuggestionClick={sendTextMessage}
|
||||
showBackground={showBackground}
|
||||
suggestionsWithStringWrap={onBoardingSuggestionWrap}
|
||||
mdBoxProps={{
|
||||
insertedElements: renderVariable(prologue),
|
||||
slots: {
|
||||
Image: CozeImageWithPreview,
|
||||
Link: CozeLink,
|
||||
},
|
||||
}}
|
||||
enableAutoSizeImage={enableImageAutoSize}
|
||||
imageAutoSizeContainerWidth={imageAutoSizeContainerWidth}
|
||||
eventCallbacks={eventCallbacks}
|
||||
suggestionItemColor="white"
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,11 @@
|
||||
.more-btn-tooltip {
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
letter-spacing: -0.3px;
|
||||
|
||||
.tool-text {
|
||||
cursor: pointer;
|
||||
color: var(--light-color-brand-brand-3, #9197f1);
|
||||
text-decoration: underline dotted;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import classnames from 'classnames';
|
||||
import { useBotInfoStore } from '@coze-studio/bot-detail-store/bot-info';
|
||||
import { useBotDetailIsReadonly } from '@coze-studio/bot-detail-store';
|
||||
import { I18n } from '@coze-arch/i18n';
|
||||
import { OpenModalEvent, emitEvent } from '@coze-arch/bot-utils';
|
||||
import { BotMode } from '@coze-arch/bot-api/playground_api';
|
||||
|
||||
import s from './index.module.less';
|
||||
|
||||
export const UploadTooltipsContent = () => {
|
||||
const isReadonly = useBotDetailIsReadonly();
|
||||
|
||||
const mode = useBotInfoStore(state => state.mode);
|
||||
const isMulti = mode === BotMode.MultiMode;
|
||||
const isWorkflow = mode === BotMode.WorkflowMode;
|
||||
|
||||
const botPreviewAttachI18nKey = 'bot_preview_attach_0319';
|
||||
|
||||
const addApi = () => {
|
||||
if (isReadonly) {
|
||||
return;
|
||||
}
|
||||
emitEvent(OpenModalEvent.PLUGIN_API_MODAL_OPEN, { type: 1 });
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={s['more-btn-tooltip']} onClick={e => e.stopPropagation()}>
|
||||
{I18n.t(botPreviewAttachI18nKey, {
|
||||
placeholder:
|
||||
isMulti || isWorkflow ? (
|
||||
I18n.t('bot_preview_attach_select')
|
||||
) : (
|
||||
<span className={classnames(s['tool-text'])} onClick={addApi}>
|
||||
{I18n.t('bot_preview_attach_select')}
|
||||
</span>
|
||||
),
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { createContext, useContext } from 'react';
|
||||
|
||||
import { type ComponentTypesMap } from '@coze-common/chat-area';
|
||||
|
||||
export const BotDebugChatAreaComponentContext = createContext<
|
||||
Partial<ComponentTypesMap>
|
||||
>({});
|
||||
|
||||
export const useBotDebugChatAreaComponent = () =>
|
||||
useContext(BotDebugChatAreaComponentContext);
|
||||
|
||||
export const BotDebugChatAreaComponentProvider =
|
||||
BotDebugChatAreaComponentContext.Provider;
|
||||
@@ -0,0 +1,26 @@
|
||||
.chat-input-wrapper {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.preview-not-save {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
width: 100%;
|
||||
height: 24px;
|
||||
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #a7abb0;
|
||||
}
|
||||
|
||||
.coz-debug-shortcut-bar-wrapper {
|
||||
width: calc(100% - 92px);
|
||||
margin-right: 24px;
|
||||
margin-left: 68px;
|
||||
}
|
||||
|
||||
.chat-area-message-group-list {
|
||||
padding: 0;
|
||||
}
|
||||
176
frontend/packages/agent-ide/chat-debug-area/src/index.tsx
Normal file
176
frontend/packages/agent-ide/chat-debug-area/src/index.tsx
Normal file
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { type ReactNode, useEffect, useState } from 'react';
|
||||
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
import { merge } from 'lodash-es';
|
||||
import classNames from 'classnames';
|
||||
import { IconAlertCircle } from '@douyinfe/semi-icons';
|
||||
import { usePageRuntimeStore } from '@coze-studio/bot-detail-store/page-runtime';
|
||||
import { WorkflowRender } from '@coze-common/chat-workflow-render';
|
||||
import {
|
||||
ChatArea,
|
||||
type ComponentTypesMap,
|
||||
useChatArea,
|
||||
useInitStatus,
|
||||
useLatestSectionMessage,
|
||||
} from '@coze-common/chat-area';
|
||||
import { getSlardarInstance } from '@coze-arch/logger';
|
||||
import { I18n } from '@coze-arch/i18n';
|
||||
import { Spin, Toast } from '@coze-arch/bot-semi';
|
||||
import { CustomError } from '@coze-arch/bot-error';
|
||||
import { SendType } from '@coze-arch/bot-api/developer_api';
|
||||
import { ReceiveMessageBox } from '@coze-agent-ide/chat-components-adapter';
|
||||
import { MessageBoxActionBarAdapter } from '@coze-agent-ide/chat-answer-action-adapter';
|
||||
|
||||
import { ShortcutBarRender } from './plugins/shortcut';
|
||||
import { useBotDebugChatAreaComponent } from './context';
|
||||
import { UploadTooltipsContent } from './components/upload-tooltips-content';
|
||||
import { OnboardingMessagePop } from './components/onboarding-message-pop';
|
||||
|
||||
import retryStyles from './retry.module.less';
|
||||
import s from './index.module.less';
|
||||
|
||||
export { BotDebugChatAreaComponentProvider } from './context';
|
||||
|
||||
export const BotDebugChatArea = ({
|
||||
readOnly = false,
|
||||
headerNode,
|
||||
}: {
|
||||
readOnly?: boolean;
|
||||
headerNode?: ReactNode;
|
||||
}) => {
|
||||
const [enableSendMultimodalMessage, setEnableSendMultimodalMessage] =
|
||||
useState<boolean>(true);
|
||||
|
||||
const initStatus = useInitStatus();
|
||||
|
||||
const { savingInfo } = usePageRuntimeStore(
|
||||
useShallow(state => ({
|
||||
savingInfo: state.savingInfo,
|
||||
})),
|
||||
);
|
||||
|
||||
const interceptSend = savingInfo.saving;
|
||||
|
||||
const onBeforeSubmit = () => {
|
||||
if (interceptSend) {
|
||||
Toast.warning({
|
||||
content: I18n.t('bot_execute_by_autosave'),
|
||||
showClose: false,
|
||||
});
|
||||
}
|
||||
|
||||
return !interceptSend;
|
||||
};
|
||||
const { latestSectionMessageLength } = useLatestSectionMessage();
|
||||
const injectComponents = useBotDebugChatAreaComponent();
|
||||
const userHasSentMessage = latestSectionMessageLength > 0;
|
||||
|
||||
if (initStatus === 'unInit' || initStatus === 'loading') {
|
||||
return (
|
||||
<div className={retryStyles['home-state']}>
|
||||
<Spin size="middle" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (initStatus === 'initFail') {
|
||||
return <InitFail />;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated 请勿新增或修改,review 不会通过
|
||||
* 请使用插件化方案实现
|
||||
*/
|
||||
const chatAreaComponentTypes: Partial<ComponentTypesMap> = {
|
||||
messageActionBarFooter: MessageBoxActionBarAdapter,
|
||||
messageActionBarHoverContent: () => null,
|
||||
contentBox: WorkflowRender,
|
||||
onboarding: OnboardingMessagePop,
|
||||
receiveMessageBox: ReceiveMessageBox,
|
||||
chatInputIntegration: {
|
||||
renderChatInputTopSlot: controller =>
|
||||
ShortcutBarRender({
|
||||
controller,
|
||||
onShortcutActive: shortcut => {
|
||||
const isTemplateShortcutActive =
|
||||
shortcut?.send_type === SendType.SendTypePanel;
|
||||
const enableMultimodalArea = !isTemplateShortcutActive;
|
||||
setEnableSendMultimodalMessage(enableMultimodalArea);
|
||||
},
|
||||
}),
|
||||
},
|
||||
};
|
||||
|
||||
return (
|
||||
<ChatArea
|
||||
readonly={readOnly}
|
||||
componentTypes={merge(chatAreaComponentTypes, injectComponents)}
|
||||
enableMessageBoxActionBar
|
||||
messageGroupListClassName={s['chat-area-message-group-list']}
|
||||
enableMultimodalUpload={enableSendMultimodalMessage}
|
||||
enableLegacyUpload={!enableSendMultimodalMessage}
|
||||
textareaBottomTips={I18n.t('chat_GenAI_tips')}
|
||||
chatInputProps={{
|
||||
wrapperClassName: classNames(s['chat-input-wrapper']),
|
||||
onBeforeSubmit,
|
||||
uploadButtonTooltipContent: <UploadTooltipsContent />,
|
||||
submitClearInput: !interceptSend,
|
||||
}}
|
||||
textareaPlaceholder={
|
||||
userHasSentMessage
|
||||
? I18n.t('store_chat_placeholder_continue')
|
||||
: I18n.t('store_chat_placeholder_blank')
|
||||
}
|
||||
isOnboardingCentered
|
||||
headerNode={headerNode}
|
||||
fileLimit={10}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const InitFail = () => {
|
||||
const { refreshMessageList } = useChatArea();
|
||||
const [sessionId] = useState(() => getSlardarInstance()?.config()?.sessionId);
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
await Promise.resolve();
|
||||
throw new CustomError('BotDebugAreaInitFail', '');
|
||||
})();
|
||||
}, []);
|
||||
return (
|
||||
<div className={retryStyles['home-state']}>
|
||||
<IconAlertCircle className={retryStyles['fail-page-icon']} />
|
||||
<div className={retryStyles['fail-page-text']}>
|
||||
<span>{I18n.t('coze_home_page_fail_text')}</span>
|
||||
<span
|
||||
className={retryStyles['fail-page-retry']}
|
||||
onClick={refreshMessageList}
|
||||
>
|
||||
{I18n.t('coze_home_page_fail_btn_retry')}
|
||||
</span>
|
||||
</div>
|
||||
{!!sessionId && (
|
||||
<div className="leading-[12px] mt-[8px] text-[12px] text-gray-400">
|
||||
{sessionId}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { useRef } from 'react';
|
||||
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
import { BotMode } from '@coze-arch/bot-api/playground_api';
|
||||
import { useBotSkillStore } from '@coze-studio/bot-detail-store/bot-skill';
|
||||
import { useBotInfoStore } from '@coze-studio/bot-detail-store/bot-info';
|
||||
import { manuallySwitchAgent } from '@coze-studio/bot-detail-store';
|
||||
import {
|
||||
ShortcutBar,
|
||||
getUIModeByBizScene,
|
||||
type ShortCutCommand,
|
||||
} from '@coze-common/chat-area-plugins-chat-shortcuts';
|
||||
import { useShowBackGround } from '@coze-common/chat-area/hooks/public/use-show-bgackground';
|
||||
import { type ChatInputIntegrationController } from '@coze-common/chat-area';
|
||||
|
||||
import s from '../../index.module.less';
|
||||
|
||||
export const ShortcutBarRender = ({
|
||||
controller,
|
||||
onShortcutActive,
|
||||
}: {
|
||||
controller: ChatInputIntegrationController;
|
||||
onShortcutActive?: (shortcut: ShortCutCommand | undefined) => void;
|
||||
}) => (
|
||||
<ShortcutBarRenderImpl
|
||||
controller={controller}
|
||||
onShortcutActive={onShortcutActive}
|
||||
/>
|
||||
);
|
||||
|
||||
const ShortcutBarRenderImpl: React.FC<{
|
||||
controller: ChatInputIntegrationController;
|
||||
onShortcutActive?: (shortcut: ShortCutCommand | undefined) => void;
|
||||
}> = ({ controller, onShortcutActive }) => {
|
||||
const activeShortcutRef = useRef<ShortCutCommand | undefined>(undefined);
|
||||
const showBackground = useShowBackGround();
|
||||
|
||||
const { mode, botName, botUrl } = useBotInfoStore(
|
||||
useShallow(state => ({
|
||||
botUrl: state.icon_url,
|
||||
botName: state.name,
|
||||
mode: state.mode,
|
||||
})),
|
||||
);
|
||||
const { chatShortcuts } = useBotSkillStore(
|
||||
useShallow(state => ({
|
||||
chatShortcuts: state.shortcut,
|
||||
})),
|
||||
);
|
||||
|
||||
const chatShortcutsWithBotInfo = chatShortcuts.shortcut_list?.map(
|
||||
shortcut => ({
|
||||
...shortcut,
|
||||
bot_info: {
|
||||
icon_url: botUrl,
|
||||
name: botName,
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
const singleModeShortcuts = chatShortcutsWithBotInfo?.filter(
|
||||
shortcut => !shortcut.agent_id,
|
||||
);
|
||||
|
||||
const showShortcuts = {
|
||||
[BotMode.SingleMode]: singleModeShortcuts,
|
||||
[BotMode.WorkflowMode]: [],
|
||||
[BotMode.MultiMode]: chatShortcutsWithBotInfo,
|
||||
}[mode];
|
||||
|
||||
const defaultId = showShortcuts?.at(0)?.command_id;
|
||||
|
||||
if (mode === BotMode.WorkflowMode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<ShortcutBar
|
||||
shortcuts={showShortcuts ?? []}
|
||||
defaultId={defaultId}
|
||||
wrapperClassName={s['coz-debug-shortcut-bar-wrapper']}
|
||||
uiMode={getUIModeByBizScene({
|
||||
bizScene: 'debug',
|
||||
showBackground,
|
||||
})}
|
||||
onActiveShortcutChange={(shortcutInfo, isTemplateShortcutActive) => {
|
||||
activeShortcutRef.current = shortcutInfo;
|
||||
// 开启template快捷指令时,隐藏输入框&快捷指令bar
|
||||
const chatInputSlotVisible = !isTemplateShortcutActive;
|
||||
controller.setChatInputSlotVisible(chatInputSlotVisible);
|
||||
// 当template快捷指令激活时,禁用发送多模态消息
|
||||
onShortcutActive?.(shortcutInfo);
|
||||
// 如果指定了agent,切换到指定的agent
|
||||
if (mode === BotMode.MultiMode) {
|
||||
shortcutInfo?.agent_id && manuallySwitchAgent(shortcutInfo.agent_id);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,29 @@
|
||||
.home-state {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
height: 100%;
|
||||
|
||||
:global(.semi-spin-children) {
|
||||
background: white !important;
|
||||
}
|
||||
|
||||
.fail-page-icon {
|
||||
font-size: 32px;
|
||||
color: #FF2710;
|
||||
}
|
||||
|
||||
.fail-page-text {
|
||||
margin-top: 10px;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.fail-page-retry {
|
||||
cursor: pointer;
|
||||
color: #4D53E8;
|
||||
}
|
||||
}
|
||||
17
frontend/packages/agent-ide/chat-debug-area/src/typings.d.ts
vendored
Normal file
17
frontend/packages/agent-ide/chat-debug-area/src/typings.d.ts
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/// <reference types='@coze-arch/bot-typings' />
|
||||
123
frontend/packages/agent-ide/chat-debug-area/tsconfig.build.json
Normal file
123
frontend/packages/agent-ide/chat-debug-area/tsconfig.build.json
Normal file
@@ -0,0 +1,123 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"extends": "@coze-arch/ts-config/tsconfig.web.json",
|
||||
"compilerOptions": {
|
||||
"types": [],
|
||||
"strictNullChecks": true,
|
||||
"noImplicitAny": true,
|
||||
"rootDir": "./src",
|
||||
"outDir": "./dist",
|
||||
"tsBuildInfoFile": "./dist/tsconfig.build.tsbuildinfo"
|
||||
},
|
||||
"include": ["src"],
|
||||
"references": [
|
||||
{
|
||||
"path": "../../arch/bot-api/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../arch/bot-env/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../arch/bot-error/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../arch/bot-flags/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../arch/bot-hooks/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../arch/bot-store/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../arch/bot-tea/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../arch/bot-typings/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../arch/bot-utils/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../arch/i18n/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../arch/idl/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../arch/logger/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../arch/report-events/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../arch/report-tti/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../chat-answer-action-adapter/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../chat-area-plugin-debug-common/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../chat-components-adapter/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../common/chat-area/chat-answer-action/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../common/chat-area/chat-area-plugin-reasoning/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../common/chat-area/chat-area/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../common/chat-area/chat-core/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../common/chat-area/chat-uikit/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../common/chat-area/chat-workflow-render/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../common/chat-area/plugin-chat-background/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../common/chat-area/plugin-chat-shortcuts/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../common/chat-area/plugin-message-grab/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../common/chat-area/plugin-resume/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../components/bot-semi/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../../config/eslint-config/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../../config/stylelint-config/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../../config/ts-config/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../../config/vitest-config/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../onboarding/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../space-bot/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../studio/stores/bot-detail/tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "../../studio/user-store/tsconfig.build.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
15
frontend/packages/agent-ide/chat-debug-area/tsconfig.json
Normal file
15
frontend/packages/agent-ide/chat-debug-area/tsconfig.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"compilerOptions": {
|
||||
"composite": true
|
||||
},
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.build.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.misc.json"
|
||||
}
|
||||
],
|
||||
"exclude": ["**/*"]
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"extends": "@coze-arch/ts-config/tsconfig.web.json",
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"include": ["__tests__", "stories", "vitest.config.ts", "tailwind.config.ts"],
|
||||
"exclude": ["./dist"],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.build.json"
|
||||
}
|
||||
],
|
||||
"compilerOptions": {
|
||||
"rootDir": "./",
|
||||
"outDir": "./dist",
|
||||
"types": ["vitest/globals"],
|
||||
"strictNullChecks": true,
|
||||
"noImplicitAny": true
|
||||
}
|
||||
}
|
||||
22
frontend/packages/agent-ide/chat-debug-area/vitest.config.ts
Normal file
22
frontend/packages/agent-ide/chat-debug-area/vitest.config.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2025 coze-dev Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { defineConfig } from '@coze-arch/vitest-config';
|
||||
|
||||
export default defineConfig({
|
||||
dirname: __dirname,
|
||||
preset: 'web',
|
||||
});
|
||||
Reference in New Issue
Block a user