Skip to content

Commit e5e3716

Browse files
authored
Merge pull request #1448 from refly-ai/fix/publish-controll
fix(variable-extraction): streamline variable usage analysis and enha…
2 parents 77f40e3 + 5d3e8d5 commit e5e3716

File tree

5 files changed

+102
-63
lines changed

5 files changed

+102
-63
lines changed

apps/api/src/modules/variable-extraction/app-publish-prompt.ts

Lines changed: 26 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,8 @@ export function buildAppPublishPrompt(
3232
canvasContext: CanvasContext,
3333
historicalData?: HistoricalData,
3434
): string {
35-
// Analyze which variables are actually used in canvas nodes
36-
const usedVariables = analyzeVariableUsage(canvasData.nodes, canvasData.variables);
37-
38-
// Filter variables to only include those that are actually used
39-
const filteredVariables = canvasData.variables.filter((variable) =>
40-
usedVariables.has(variable.name),
41-
);
42-
4335
const nodesText = buildNodesText(canvasData.nodes);
44-
const variablesText = buildVariablesText(filteredVariables);
36+
const variablesText = buildVariablesText(canvasData.variables);
4537
const canvasContextText = buildCanvasContextText(canvasContext);
4638
const historicalContext = historicalData ? buildHistoricalContext(historicalData) : '';
4739

@@ -74,34 +66,45 @@ ${historicalContext ? `### Historical Learning Context\n${historicalContext}` :
7466
7567
## Template Generation Guidelines
7668
77-
### 1. Natural Language Conversion
69+
### 1. Language Consistency (CRITICAL)
70+
- **MUST maintain the same language as used in Canvas Nodes and Prompts**
71+
- If Canvas Nodes contain Chinese text, generate templates in Chinese
72+
- If Canvas Nodes contain English text, generate templates in English
73+
- If Canvas Nodes contain mixed languages, follow the primary language pattern
74+
- **Language Detection**: Analyze the Canvas Nodes content to determine the user's preferred language
75+
- **Consistency Requirement**: All template fields (title, description, content) must use the same language as the Canvas Nodes
76+
77+
### 2. Natural Language Conversion
7878
- Convert technical workflow descriptions into user-friendly language
7979
- Use clear, actionable language that explains what the workflow does
8080
- Focus on user benefits and outcomes
81+
- **Maintain language consistency with Canvas Nodes**
8182
82-
### 2. Variable Integration
83+
### 3. Variable Integration
8384
- **CRITICAL**: Only include variables that are actually used in Canvas Nodes and Prompts
8485
- Replace specific values with {{variable_name}} placeholders
8586
- Ensure all variables are properly represented in the template
8687
- Maintain semantic meaning while making it parameterizable
8788
- **Variable Usage Validation**: Only variables that appear in {{variable_name}} format within the Canvas Nodes should be included in the template
8889
89-
### 3. Template Structure
90+
### 4. Template Structure
9091
- Start with a clear description of what the workflow accomplishes
9192
- Explain what inputs are needed (variables)
9293
- Describe the expected output or result
9394
- Use conversational, helpful tone
95+
- **Maintain language consistency with Canvas Nodes**
9496
95-
### 4. Variable Type Handling
97+
### 5. Variable Type Handling
9698
- **string**: Use descriptive placeholders like "{{topic}}" or "{{style}}"
9799
- **resource**: Use file-related placeholders like "{{upload_file}}" or "{{document}}"
98100
- **option**: Use selection-related placeholders like "{{format}}" or "{{mode}}"
99101
100-
### 5. Quality Standards
102+
### 6. Quality Standards
101103
- Templates should be self-explanatory
102104
- Variables should have clear, descriptive names
103105
- Maintain workflow functionality while improving usability
104106
- Ensure consistency with existing variable names
107+
- **Language consistency is mandatory - all output must match Canvas Nodes language**
105108
106109
## Output Format Requirements
107110
@@ -145,17 +148,19 @@ ${historicalContext ? `### Historical Learning Context\n${historicalContext}` :
145148
\`\`\`
146149
147150
## Key Principles
148-
1. **Clarity**: Users should immediately understand what the workflow does
149-
2. **Simplicity**: Avoid technical jargon, use everyday language
150-
3. **Completeness**: Include all necessary variables and context
151-
4. **Actionability**: Users should know exactly what to provide and expect
152-
5. **Professionalism**: Maintain a helpful, trustworthy tone
153-
6. **Variable Usage Validation**: Only include variables that are actually referenced in Canvas Nodes with {{variable_name}} format
151+
1. **Language Consistency**: **CRITICAL** - All template fields must use the same language as Canvas Nodes
152+
2. **Clarity**: Users should immediately understand what the workflow does
153+
3. **Simplicity**: Avoid technical jargon, use everyday language
154+
4. **Completeness**: Include all necessary variables and context
155+
5. **Actionability**: Users should know exactly what to provide and expect
156+
6. **Professionalism**: Maintain a helpful, trustworthy tone
157+
7. **Variable Usage Validation**: Only include variables that are actually referenced in Canvas Nodes with {{variable_name}} format
154158
155159
## Critical Focus: Workflow Publishing Template String
156160
157161
The **"content"** field in the template object is the most important output - this is the **workflow publishing template string** that will be used by users. It must:
158162
163+
- **Language Consistency**: **CRITICAL** - Must use the same language as Canvas Nodes
159164
- **Be Natural and Conversational**: Sound like a helpful assistant explaining what they'll do
160165
- **Include Only Used Variables**: Only variables that are actually referenced in Canvas Nodes with {{variable_name}} format should be included
161166
- **Maintain Original Intent**: Preserve the user's original goal and requirements
@@ -205,43 +210,10 @@ ${APP_PUBLISH_EXAMPLES}
205210
- Only variables that are actually used in Canvas Nodes should be included
206211
- Templates should maintain the original workflow intent
207212
- Language should be professional yet approachable
213+
- **Language Consistency**: **CRITICAL** - All template fields must match the language used in Canvas Nodes
208214
- **Variable Usage Validation**: Verify that all {{variable_name}} placeholders in the template correspond to variables actually referenced in Canvas Nodes`;
209215
}
210216

211-
/**
212-
* Analyze which variables are actually used in canvas nodes
213-
* Returns a set of variable names that are referenced in node content
214-
*/
215-
function analyzeVariableUsage(nodes: CanvasNode[], variables: WorkflowVariable[]): Set<string> {
216-
const usedVariables = new Set<string>();
217-
218-
if (!nodes?.length || !variables?.length) {
219-
return usedVariables;
220-
}
221-
222-
// Get all variable names
223-
const variableNames = variables.map((v) => v.name);
224-
225-
// Check each node for variable references
226-
for (const node of nodes) {
227-
const content = node.data?.content || node.content || '';
228-
if (typeof content === 'string' && content.length > 0) {
229-
// Check for {{variable_name}} pattern
230-
const variablePattern = /\{\{([^}]+)\}\}/g;
231-
let match: RegExpExecArray | null = variablePattern.exec(content);
232-
while (match !== null) {
233-
const variableName = match[1]?.trim();
234-
if (variableName && variableNames.includes(variableName)) {
235-
usedVariables.add(variableName);
236-
}
237-
match = variablePattern.exec(content);
238-
}
239-
}
240-
}
241-
242-
return usedVariables;
243-
}
244-
245217
/**
246218
* Build nodes text - format canvas nodes into readable description
247219
*/

packages/ai-workspace-common/src/components/canvas/top-toolbar/share-settings.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,13 @@ const ShareSettings = React.memo(({ canvasId, canvasTitle }: ShareSettingsProps)
393393
{t('shareContent.publishTemplate')}
394394
</div>
395395
<Tooltip
396-
title={toolbarLoading ? t('shareContent.waitForAgentsToFinish') : undefined}
396+
title={
397+
toolbarLoading
398+
? t('shareContent.waitForAgentsToFinish')
399+
: !skillResponseNodes?.length
400+
? t('shareContent.noSkillResponseNodes')
401+
: undefined
402+
}
397403
placement="top"
398404
>
399405
<Button

packages/ai-workspace-common/src/components/canvas/workflow-run/workflow-run-form.tsx

Lines changed: 67 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { WorkflowVariable, WorkflowExecutionStatus } from '@refly/openapi-schema';
22
import { useTranslation } from 'react-i18next';
3-
import { Button, Input, Select, Form, Typography } from 'antd';
3+
import { Button, Input, Select, Form, Typography, message } from 'antd';
44
import { Play, Copy } from 'refly-icons';
55
import { IconShare } from '@refly-packages/ai-workspace-common/components/common/icon';
66
import { useState, useEffect, useCallback, useMemo } from 'react';
@@ -276,6 +276,29 @@ export const WorkflowRunForm = ({
276276
[refreshFile, variableValues, handleValueChange, form, workflowVariables],
277277
);
278278

279+
// Initialize template variables when templateContent changes
280+
useEffect(() => {
281+
if (templateContent) {
282+
// Extract variables from template content
283+
const variableRegex = /\{\{([^}]+)\}\}/g;
284+
const templateVariableNames = new Set<string>();
285+
let match: RegExpExecArray | null;
286+
287+
match = variableRegex.exec(templateContent);
288+
while (match !== null) {
289+
templateVariableNames.add(match[1].trim());
290+
match = variableRegex.exec(templateContent);
291+
}
292+
293+
// Filter workflowVariables to only include those mentioned in template
294+
const relevantVariables = workflowVariables.filter((variable) =>
295+
templateVariableNames.has(variable.name),
296+
);
297+
298+
setTemplateVariables(relevantVariables);
299+
}
300+
}, [templateContent, workflowVariables]);
301+
279302
// Update form values when workflowVariables change
280303
useEffect(() => {
281304
const newValues = convertVariableToFormValue();
@@ -297,12 +320,48 @@ export const WorkflowRunForm = ({
297320
}
298321

299322
try {
300-
// Validate form before running
301-
await form.validateFields();
323+
let newVariables: WorkflowVariable[] = [];
324+
325+
if (templateContent) {
326+
// Validate templateVariables values
327+
const hasInvalidValues = templateVariables.some((variable) => {
328+
if (!variable.value || variable.value.length === 0) {
329+
return true;
330+
}
331+
332+
return variable.value.every((val) => {
333+
if (variable.variableType === 'string') {
334+
return !val.text || val.text.trim() === '';
335+
}
336+
if (variable.variableType === 'option') {
337+
return !val.text || val.text.trim() === '';
338+
}
339+
if (variable.variableType === 'resource') {
340+
return !val.resource || !val.resource.storageKey;
341+
}
342+
return true;
343+
});
344+
});
302345

303-
// If validation passes, proceed with running
304-
const newVariables = convertFormValueToVariable();
305-
console.log('newVariables', newVariables);
346+
if (hasInvalidValues) {
347+
// Show validation error message
348+
message.warning(
349+
t(
350+
'canvas.workflow.run.validationError',
351+
'Please fill in all required fields before running the workflow',
352+
),
353+
);
354+
return;
355+
}
356+
357+
newVariables = templateVariables;
358+
} else {
359+
// Validate form before running
360+
await form.validateFields();
361+
362+
// If validation passes, proceed with running
363+
newVariables = convertFormValueToVariable();
364+
}
306365

307366
// Set running state - use external callback if provided, otherwise use internal state
308367
if (onRunningChange) {
@@ -475,7 +534,7 @@ export const WorkflowRunForm = ({
475534
}, []);
476535

477536
return (
478-
<div className={cn('w-full h-full gap-3 flex flex-col', className)}>
537+
<div className={cn('w-full h-full gap-3 flex flex-col rounded-2xl', className)}>
479538
{
480539
<>
481540
{templateContent ? (
@@ -534,7 +593,7 @@ export const WorkflowRunForm = ({
534593
: t('canvas.workflow.run.run') || 'Run'}
535594
</Button>
536595

537-
{onCopyWorkflow && (
596+
{onCopyWorkflow && workflowApp?.remixEnabled && (
538597
<Button
539598
className="h-9 sm:h-10 text-sm sm:text-base"
540599
type="default"

packages/i18n/src/en-US/ui.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -896,6 +896,7 @@ const translations = {
896896
publish: 'Publish',
897897
publishTemplateTooltip: 'Publish canvas as template',
898898
waitForAgentsToFinish: 'Please wait for all Agents to finish running before publishing',
899+
noSkillResponseNodes: 'Please add Agent nodes to the canvas before publishing',
899900
latestPublishedApp: 'Latest Published App',
900901
linkShare: 'Link Share',
901902
updateCanvasPermissionSuccess: 'Update canvas permission successfully',

packages/i18n/src/zh-Hans/ui.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -891,6 +891,7 @@ const translations = {
891891
publish: '发布',
892892
publishTemplateTooltip: '将画布发布为模板',
893893
waitForAgentsToFinish: '请等待所有 Agent 运行结束后再发布',
894+
noSkillResponseNodes: '请先在画布中添加 Agent 节点后再发布',
894895
latestPublishedApp: '最新发布的应用',
895896
linkShare: '链接分享',
896897
updateCanvasPermissionSuccess: '更新画布权限成功',

0 commit comments

Comments
 (0)