feat: manually mirror opencoze's code from bytedance

Change-Id: I09a73aadda978ad9511264a756b2ce51f5761adf
This commit is contained in:
fanlv
2025-07-20 17:36:12 +08:00
commit 890153324f
14811 changed files with 1923430 additions and 0 deletions

View File

@@ -0,0 +1,18 @@
/*
* 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.
*/
export const primitiveExhaustiveCheck = (_: never) => 0;
export const recordExhaustiveCheck = (_: Record<string, never>) => 0;

View File

@@ -0,0 +1,71 @@
/*
* 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 OnboardingVariable,
type OnboardingVariableMap,
} from '../constant/onboarding-variable';
import { typedKeys } from './typed-keys';
export interface VariableWithRange {
range: [number, number];
variable: OnboardingVariable;
}
export const getFixedVariableTemplate = (template: string) => `{{${template}}}`;
export const matchAllTemplateRanges = (
text: string,
template: string,
): { start: number; end: number }[] => {
// 正则表达式,用于匹配双花括号内的内容
const templateRegex = new RegExp(getFixedVariableTemplate(template), 'g');
const matches: { start: number; end: number }[] = [];
// 循环查找所有匹配项
while (true) {
const match = templateRegex.exec(text);
if (!match) {
break;
}
const templateString = match[0];
const start = match.index;
const end = templateString.length + start;
matches.push({ start, end });
}
return matches;
};
export const getVariableRangeList = (
content: string,
variableMap: OnboardingVariableMap,
) => {
const result: VariableWithRange[] = [];
typedKeys(variableMap).forEach(variable => {
const allMatchedRanges = matchAllTemplateRanges(content, variable);
const variableWithRangeList: VariableWithRange[] = allMatchedRanges.map(
({ start, end }) => ({
variable,
range: [start, end],
}),
);
result.push(...variableWithRangeList);
});
return result;
};

View File

@@ -0,0 +1,124 @@
/*
* 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 { intersectionBy, xorBy } from 'lodash-es';
import { produce } from 'immer';
import { useBotSkillStore } from '@coze-studio/bot-detail-store/bot-skill';
import { type BotEditorOnboardingSuggestion } from '@coze-agent-ide/bot-editor-context-store';
import { recordExhaustiveCheck } from './exhaustive-check';
export const getImmerUpdateOnboardingSuggestion = (
suggestionList: BotEditorOnboardingSuggestion[],
{ id, content, highlight }: Partial<BotEditorOnboardingSuggestion>,
) =>
produce(suggestionList, draft => {
const target = draft.find(suggestion => suggestion.id === id);
if (!target) {
return;
}
if (typeof content !== 'undefined') {
target.content = content;
}
target.highlight = highlight;
return draft;
});
export const getOnboardingSuggestionAfterDeleteById = (
suggestionList: BotEditorOnboardingSuggestion[],
id: string,
) => suggestionList.filter(suggestion => suggestion.id !== id);
export const immerUpdateOnboardingStoreSuggestion = (
id: string,
value: Partial<BotEditorOnboardingSuggestion>,
) => {
const { updateSkillOnboarding, onboardingContent } =
useBotSkillStore.getState();
updateSkillOnboarding({
suggested_questions: getImmerUpdateOnboardingSuggestion(
onboardingContent.suggested_questions,
value,
),
});
};
export const updateOnboardingStorePrologue = (content: string) => {
useBotSkillStore.getState().updateSkillOnboarding({ prologue: content });
};
export const deleteOnboardingStoreSuggestion = (id: string) => {
useBotSkillStore.getState().updateSkillOnboarding(prev => ({
suggested_questions: getOnboardingSuggestionAfterDeleteById(
prev.suggested_questions,
id,
),
}));
};
export const getShuffledSuggestions = ({
originSuggestions,
shuffledSuggestions,
maxLength,
}: {
originSuggestions: BotEditorOnboardingSuggestion[];
shuffledSuggestions: BotEditorOnboardingSuggestion[];
maxLength: number;
}) => {
const intersectionSuggestion = intersectionBy(
originSuggestions,
shuffledSuggestions,
suggestion => suggestion.id,
);
const preVisibleSuggestion = xorBy(
originSuggestions,
intersectionSuggestion,
suggestion => suggestion.id,
);
// chatArea 数据中比交集多的就是要删除的
const toDeleteSuggestion = xorBy(
shuffledSuggestions,
intersectionSuggestion,
suggestion => suggestion.id,
);
// bot 调试页面数据中比交集多的就是要添加的
const toAddSuggestion = preVisibleSuggestion.slice(
0,
maxLength - intersectionSuggestion.length,
);
const toUpdateMessage = shuffledSuggestions
.filter(
({ id }) =>
!toDeleteSuggestion.find(toDeleteItem => toDeleteItem.id === id),
)
.concat(toAddSuggestion);
return produce(toUpdateMessage, draft => {
intersectionSuggestion.forEach(({ id, content, highlight, ...rest }) => {
recordExhaustiveCheck(rest);
const target = draft.find(item => item.id === id);
if (!target) {
return;
}
target.content = content;
target.highlight = highlight;
});
});
};

View File

@@ -0,0 +1,19 @@
/*
* 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.
*/
export const typedKeys = <T extends Parameters<typeof Object.keys>[number]>(
o: T,
): Array<keyof T> => Object.keys(o) as Array<keyof T>;