fix: split wiki template instruction and example (#17891)

This commit is contained in:
buua436
2026-08-06 09:41:57 +08:00
committed by GitHub
parent d5000de534
commit d16b2556a2
20 changed files with 166 additions and 147 deletions

View File

@@ -74,5 +74,5 @@ export interface IWikiPreset {
id: string;
topic: string;
instruction: string;
page_example: string;
example: string;
}

View File

@@ -3,8 +3,11 @@
* Theme follows the app's Nimbalyst theme system.
*/
import type { OnChange, OnMount } from '@monaco-editor/react';
import Editor from '@monaco-editor/react';
import Editor, {
loader,
type OnChange,
type OnMount,
} from '@monaco-editor/react';
import { Eye } from 'lucide-react';
import type { editor as monacoEditor } from 'monaco-editor';
import type { JSX } from 'react';
@@ -12,6 +15,8 @@ import { useEffect, useRef } from 'react';
import { useTheme } from '@/components/theme-provider';
loader.config({ paths: { vs: '/vs' } });
interface Props {
content: string;
onChange?: (value: string) => void;

View File

@@ -72,14 +72,14 @@ export function BlueprintsStep({
const instructionPath =
`templates.${selectedTemplateIndex}.config.instruction` as const;
const pageExamplePath =
`templates.${selectedTemplateIndex}.config.page_example` as const;
const examplePath =
`templates.${selectedTemplateIndex}.config.example` as const;
const useBlueprintPath =
`templates.${selectedTemplateIndex}.config.use_blueprint` as const;
const pageExample = useWatch({
const example = useWatch({
control: form.control,
name: pageExamplePath,
name: examplePath,
});
const instruction = useWatch({
@@ -100,7 +100,7 @@ export function BlueprintsStep({
return selectedItem?.name ?? '';
}, [treeData, selectedItemId]);
const hasTemplateData = Boolean(selectedItemId || instruction || pageExample);
const hasTemplateData = Boolean(selectedItemId || instruction || example);
const handleSelect = useCallback(
(item?: TreeDataItem) => {
@@ -113,11 +113,11 @@ export function BlueprintsStep({
form.setValue(instructionPath, preset.instruction, {
shouldValidate: false,
});
form.setValue(pageExamplePath, preset.page_example, {
form.setValue(examplePath, preset.example, {
shouldValidate: false,
});
},
[form, instructionPath, pageExamplePath],
[form, instructionPath, examplePath],
);
const handleToggleBlueprint = useCallback(
@@ -128,11 +128,11 @@ export function BlueprintsStep({
[form, useBlueprintPath],
);
const handlePageExampleChange = useCallback(
const handleExampleChange = useCallback(
(value: string) => {
form.setValue(pageExamplePath, value, { shouldValidate: false });
form.setValue(examplePath, value, { shouldValidate: false });
},
[form, pageExamplePath],
[form, examplePath],
);
return (
@@ -175,8 +175,8 @@ export function BlueprintsStep({
<div className="flex-1 min-h-0 flex flex-col">
<MarkdownEditor
content={String(pageExample ?? '')}
onChange={handlePageExampleChange}
content={String(example ?? '')}
onChange={handleExampleChange}
/>
</div>
</div>

View File

@@ -20,7 +20,6 @@ export const DefaultTemplateValues: TemplateSchemaType = {
global_rules: '',
example: '',
instruction: '',
page_example: '',
use_blueprint: false,
plan: true,
rechunk: false,

View File

@@ -20,20 +20,6 @@ import {
SectionPriority,
} from './constant';
export const splitExampleToBlueprintFields = (
example: string,
): { instruction: string; page_example: string } => {
const trimmed = example.trim();
const separatorIndex = trimmed.indexOf('\n\n');
if (separatorIndex === -1) {
return { instruction: trimmed, page_example: '' };
}
return {
instruction: trimmed.slice(0, separatorIndex).trim(),
page_example: trimmed.slice(separatorIndex + 2).trim(),
};
};
export const getFieldKeyOrder = (keys: string[]): string[] => {
const sortedKeys = [...keys].sort();
return (
@@ -52,7 +38,6 @@ export const isConfigMetaKey = (key: string) =>
'global_rules',
'example',
'instruction',
'page_example',
'synthesis',
'use_blueprint',
'plan',
@@ -85,6 +70,10 @@ export const buildConfigFromBuiltin = (
kind: string,
llmId: string,
): TemplateSchemaType['config'] => {
const instruction =
typeof builtinTemplate.config?.instruction === 'string'
? builtinTemplate.config.instruction
: '';
const example =
typeof builtinTemplate.config?.example === 'string'
? builtinTemplate.config.example
@@ -108,7 +97,8 @@ export const buildConfigFromBuiltin = (
}
: {}),
use_blueprint:
kind === CompilationTemplateKind.Artifacts && example.length > 0,
kind === CompilationTemplateKind.Artifacts &&
(instruction.length > 0 || example.length > 0),
plan:
typeof builtinTemplate.config?.plan === 'boolean'
? builtinTemplate.config.plan
@@ -124,11 +114,12 @@ export const buildConfigFromBuiltin = (
: {}),
};
if (kind === CompilationTemplateKind.Artifacts && example.length > 0) {
const { instruction, page_example } =
splitExampleToBlueprintFields(example);
if (
kind === CompilationTemplateKind.Artifacts &&
(instruction.length > 0 || example.length > 0)
) {
sections.instruction = instruction;
sections.page_example = page_example;
sections.example = example;
}
if (kind === CompilationTemplateKind.Tree) {
@@ -160,12 +151,18 @@ export const transformDetailToForm = (
detail: ICompilationTemplate,
): TemplateSchemaType => {
const config = detail.config ?? {};
const example = typeof config.example === 'string' ? config.example : '';
const storedInstruction =
typeof config.instruction === 'string' ? config.instruction : '';
const storedExample =
typeof config.example === 'string' ? config.example : '';
const hasBlueprintContent = Boolean(
storedInstruction.trim() || storedExample.trim(),
);
const base: TemplateSchemaType['config'] = {
kind: config.kind ?? '',
llm_id: config.llm_id ?? '',
global_rules: config.global_rules ?? '',
example: typeof config.example === 'string' ? config.example : '',
example: storedExample,
...(typeof config.synthesis === 'object' && config.synthesis !== null
? {
synthesis:
@@ -173,7 +170,7 @@ export const transformDetailToForm = (
}
: {}),
use_blueprint:
detail.kind === CompilationTemplateKind.Artifacts && example.length > 0,
detail.kind === CompilationTemplateKind.Artifacts && hasBlueprintContent,
plan: typeof config.plan === 'boolean' ? config.plan : true,
...(detail.kind !== CompilationTemplateKind.Tree
? {
@@ -186,11 +183,12 @@ export const transformDetailToForm = (
: {}),
};
if (detail.kind === CompilationTemplateKind.Artifacts && example.length > 0) {
const { instruction, page_example } =
splitExampleToBlueprintFields(example);
base.instruction = instruction;
base.page_example = page_example;
if (
detail.kind === CompilationTemplateKind.Artifacts &&
hasBlueprintContent
) {
base.instruction = storedInstruction;
base.example = storedExample;
}
if (detail.kind === CompilationTemplateKind.Tree) {
@@ -254,7 +252,7 @@ export const transformTemplateToPayload = (template: TemplateSchemaType) => {
Object.entries(template.config).forEach(([key, value]) => {
if (key === 'kind' || key === 'llm_id') return;
if (key === 'instruction' || key === 'page_example') return;
if (key === 'example' || key === 'instruction') return;
if (key === 'synthesis') {
config[key] = value as ICompilationTemplateConfigRequest[string];
return;
@@ -274,9 +272,11 @@ export const transformTemplateToPayload = (template: TemplateSchemaType) => {
if (template.kind === CompilationTemplateKind.Artifacts) {
if (template.config.use_blueprint) {
const instruction = String(template.config.instruction ?? '').trim();
const pageExample = String(template.config.page_example ?? '').trim();
config.example = [instruction, pageExample].filter(Boolean).join('\n\n');
const example = String(template.config.example ?? '').trim();
config.instruction = instruction;
config.example = example;
} else {
config.instruction = '';
config.example = '';
}
}

View File

@@ -29,8 +29,8 @@ export function BlueprintSection({
options,
handleSelect,
instructionPath,
pageExample,
handlePageExampleChange,
example,
handleExampleChange,
} = useBlueprintSelection({ form, selectedTemplateIndex, presets, builtins });
if (presets.length === 0) {
@@ -63,8 +63,8 @@ export function BlueprintSection({
<div className="flex h-[50vh] min-h-0 flex-col">
<MarkdownEditor
content={String(pageExample ?? '')}
onChange={handlePageExampleChange}
content={String(example ?? '')}
onChange={handleExampleChange}
/>
</div>
</div>

View File

@@ -20,7 +20,6 @@ export const DefaultTemplateValues: TemplateSchemaType = {
global_rules: '',
example: '',
instruction: '',
page_example: '',
use_blueprint: false,
plan: true,
rechunk: false,

View File

@@ -9,7 +9,6 @@ import { UseFormReturn, useWatch } from 'react-hook-form';
import { useTranslation } from 'react-i18next';
import { FormSchemaType } from '../schema';
import { splitExampleToBlueprintFields } from '../utils';
export const CustomBlueprintValue = '__custom__';
@@ -23,10 +22,10 @@ type UseBlueprintSelectionParams = {
const isSameBlueprintContent = (
preset: IWikiPreset,
instruction: string,
pageExample: string,
example: string,
) =>
preset.instruction.trim() === instruction.trim() &&
preset.page_example.trim() === pageExample.trim();
preset.example.trim() === example.trim();
export function useBlueprintSelection({
form,
@@ -40,8 +39,8 @@ export function useBlueprintSelection({
const kindPath = `templates.${selectedTemplateIndex}.kind` as const;
const instructionPath =
`templates.${selectedTemplateIndex}.config.instruction` as const;
const pageExamplePath =
`templates.${selectedTemplateIndex}.config.page_example` as const;
const examplePath =
`templates.${selectedTemplateIndex}.config.example` as const;
const useBlueprintPath =
`templates.${selectedTemplateIndex}.config.use_blueprint` as const;
@@ -53,21 +52,21 @@ export function useBlueprintSelection({
control: form.control,
name: instructionPath,
});
const pageExample = useWatch({
const example = useWatch({
control: form.control,
name: pageExamplePath,
name: examplePath,
});
const matchedPresetId = useMemo(() => {
const currentInstruction = String(instruction ?? '');
const currentPageExample = String(pageExample ?? '');
if (!currentInstruction.trim() && !currentPageExample.trim()) {
const currentExample = String(example ?? '');
if (!currentInstruction.trim() && !currentExample.trim()) {
return undefined;
}
return presets.find((preset) =>
isSameBlueprintContent(preset, currentInstruction, currentPageExample),
isSameBlueprintContent(preset, currentInstruction, currentExample),
)?.id;
}, [instruction, pageExample, presets]);
}, [instruction, example, presets]);
const selectedValue =
explicitValue ?? matchedPresetId ?? CustomBlueprintValue;
@@ -92,18 +91,18 @@ export function useBlueprintSelection({
const builtinTemplate = builtins.find(
(template) => template.kind === kind,
);
const example =
const defaultInstruction =
typeof builtinTemplate?.config?.instruction === 'string'
? builtinTemplate.config.instruction
: '';
const defaultPageExample =
typeof builtinTemplate?.config?.example === 'string'
? builtinTemplate.config.example
: '';
const {
instruction: defaultInstruction,
page_example: defaultPageExample,
} = splitExampleToBlueprintFields(example);
form.setValue(instructionPath, defaultInstruction, {
shouldValidate: false,
});
form.setValue(pageExamplePath, defaultPageExample, {
form.setValue(examplePath, defaultPageExample, {
shouldValidate: false,
});
} else {
@@ -112,7 +111,7 @@ export function useBlueprintSelection({
form.setValue(instructionPath, preset.instruction, {
shouldValidate: false,
});
form.setValue(pageExamplePath, preset.page_example, {
form.setValue(examplePath, preset.example, {
shouldValidate: false,
});
}
@@ -124,18 +123,18 @@ export function useBlueprintSelection({
form,
instructionPath,
kind,
pageExamplePath,
examplePath,
presets,
selectedValue,
useBlueprintPath,
],
);
const handlePageExampleChange = useCallback(
const handleExampleChange = useCallback(
(value: string) => {
form.setValue(pageExamplePath, value, { shouldValidate: false });
form.setValue(examplePath, value, { shouldValidate: false });
},
[form, pageExamplePath],
[form, examplePath],
);
return {
@@ -143,7 +142,7 @@ export function useBlueprintSelection({
options,
handleSelect,
instructionPath,
pageExample,
handlePageExampleChange,
example,
handleExampleChange,
};
}

View File

@@ -19,20 +19,6 @@ import {
SectionPriority,
} from './constant';
export const splitExampleToBlueprintFields = (
example: string,
): { instruction: string; page_example: string } => {
const trimmed = example.trim();
const separatorIndex = trimmed.indexOf('\n\n');
if (separatorIndex === -1) {
return { instruction: trimmed, page_example: '' };
}
return {
instruction: trimmed.slice(0, separatorIndex).trim(),
page_example: trimmed.slice(separatorIndex + 2).trim(),
};
};
export const getFieldKeyOrder = (keys: string[]): string[] => {
const sortedKeys = [...keys].sort();
return (
@@ -48,7 +34,6 @@ export const isConfigMetaKey = (key: string) =>
'global_rules',
'example',
'instruction',
'page_example',
'synthesis',
'use_blueprint',
'plan',
@@ -81,6 +66,10 @@ export const buildConfigFromBuiltin = (
kind: string,
llmId: string,
): TemplateSchemaType['config'] => {
const instruction =
typeof builtinTemplate.config?.instruction === 'string'
? builtinTemplate.config.instruction
: '';
const example =
typeof builtinTemplate.config?.example === 'string'
? builtinTemplate.config.example
@@ -104,7 +93,8 @@ export const buildConfigFromBuiltin = (
}
: {}),
use_blueprint:
kind === CompilationTemplateKind.Artifacts && example.length > 0,
kind === CompilationTemplateKind.Artifacts &&
(instruction.length > 0 || example.length > 0),
plan:
typeof builtinTemplate.config?.plan === 'boolean'
? builtinTemplate.config.plan
@@ -120,11 +110,12 @@ export const buildConfigFromBuiltin = (
: {}),
};
if (kind === CompilationTemplateKind.Artifacts && example.length > 0) {
const { instruction, page_example } =
splitExampleToBlueprintFields(example);
if (
kind === CompilationTemplateKind.Artifacts &&
(instruction.length > 0 || example.length > 0)
) {
sections.instruction = instruction;
sections.page_example = page_example;
sections.example = example;
}
if (kind === CompilationTemplateKind.Tree) {
@@ -156,12 +147,18 @@ export const transformDetailToForm = (
detail: ICompilationTemplate,
): TemplateSchemaType => {
const config = detail.config ?? {};
const example = typeof config.example === 'string' ? config.example : '';
const storedInstruction =
typeof config.instruction === 'string' ? config.instruction : '';
const storedExample =
typeof config.example === 'string' ? config.example : '';
const hasBlueprintContent = Boolean(
storedInstruction.trim() || storedExample.trim(),
);
const base: TemplateSchemaType['config'] = {
kind: config.kind ?? '',
llm_id: config.llm_id ?? '',
global_rules: config.global_rules ?? '',
example: typeof config.example === 'string' ? config.example : '',
example: storedExample,
...(typeof config.synthesis === 'object' && config.synthesis !== null
? {
synthesis:
@@ -169,7 +166,7 @@ export const transformDetailToForm = (
}
: {}),
use_blueprint:
detail.kind === CompilationTemplateKind.Artifacts && example.length > 0,
detail.kind === CompilationTemplateKind.Artifacts && hasBlueprintContent,
plan: typeof config.plan === 'boolean' ? config.plan : true,
...(detail.kind !== CompilationTemplateKind.Tree
? {
@@ -182,11 +179,12 @@ export const transformDetailToForm = (
: {}),
};
if (detail.kind === CompilationTemplateKind.Artifacts && example.length > 0) {
const { instruction, page_example } =
splitExampleToBlueprintFields(example);
base.instruction = instruction;
base.page_example = page_example;
if (
detail.kind === CompilationTemplateKind.Artifacts &&
hasBlueprintContent
) {
base.instruction = storedInstruction;
base.example = storedExample;
}
if (detail.kind === CompilationTemplateKind.Tree) {
@@ -250,7 +248,7 @@ export const transformTemplateToPayload = (template: TemplateSchemaType) => {
Object.entries(template.config).forEach(([key, value]) => {
if (key === 'kind' || key === 'llm_id') return;
if (key === 'instruction' || key === 'page_example') return;
if (key === 'example' || key === 'instruction') return;
if (key === 'synthesis') {
config[key] = value as ICompilationTemplateConfigRequest[string];
return;
@@ -270,9 +268,11 @@ export const transformTemplateToPayload = (template: TemplateSchemaType) => {
if (template.kind === CompilationTemplateKind.Artifacts) {
if (template.config.use_blueprint) {
const instruction = String(template.config.instruction ?? '').trim();
const pageExample = String(template.config.page_example ?? '').trim();
config.example = [instruction, pageExample].filter(Boolean).join('\n\n');
const example = String(template.config.example ?? '').trim();
config.instruction = instruction;
config.example = example;
} else {
config.instruction = '';
config.example = '';
}
}