Skip to content

Commit 441b276

Browse files
authored
Merge pull request #1446 from refly-ai/fix/app-input-form
fix: make workflow execution form compatible for variables and template content
2 parents 845c89b + 2267395 commit 441b276

File tree

5 files changed

+355
-100
lines changed

5 files changed

+355
-100
lines changed

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

Lines changed: 58 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,16 @@ 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+
3543
const nodesText = buildNodesText(canvasData.nodes);
36-
const variablesText = buildVariablesText(canvasData.variables);
44+
const variablesText = buildVariablesText(filteredVariables);
3745
const canvasContextText = buildCanvasContextText(canvasContext);
3846
const historicalContext = historicalData ? buildHistoricalContext(historicalData) : '';
3947

@@ -72,9 +80,11 @@ ${historicalContext ? `### Historical Learning Context\n${historicalContext}` :
7280
- Focus on user benefits and outcomes
7381
7482
### 2. Variable Integration
83+
- **CRITICAL**: Only include variables that are actually used in Canvas Nodes and Prompts
7584
- Replace specific values with {{variable_name}} placeholders
76-
- Ensure all variables are properly represented
85+
- Ensure all variables are properly represented in the template
7786
- Maintain semantic meaning while making it parameterizable
87+
- **Variable Usage Validation**: Only variables that appear in {{variable_name}} format within the Canvas Nodes should be included in the template
7888
7989
### 3. Template Structure
8090
- Start with a clear description of what the workflow accomplishes
@@ -140,16 +150,18 @@ ${historicalContext ? `### Historical Learning Context\n${historicalContext}` :
140150
3. **Completeness**: Include all necessary variables and context
141151
4. **Actionability**: Users should know exactly what to provide and expect
142152
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
143154
144155
## Critical Focus: Workflow Publishing Template String
145156
146157
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:
147158
148159
- **Be Natural and Conversational**: Sound like a helpful assistant explaining what they'll do
149-
- **Include All Variables**: Every extracted variable must be represented with {{variable_name}} placeholders
160+
- **Include Only Used Variables**: Only variables that are actually referenced in Canvas Nodes with {{variable_name}} format should be included
150161
- **Maintain Original Intent**: Preserve the user's original goal and requirements
151162
- **Be Self-Contained**: Users should understand the complete workflow from this single template
152163
- **Use Proper Variable Format**: All placeholders must use {{variable_name}} format exactly
164+
- **Variable Usage Validation**: If Canvas Nodes don't contain any {{variable_name}} references, the template should not include any variable placeholders
153165
154166
### Template String Examples:
155167
@@ -161,6 +173,9 @@ The **"content"** field in the template object is the most important output - th
161173
162174
**After (User-friendly)**: "I'll create a personalized travel plan for your trip to {{destination}} from {{departure_city}} during {{dates}}. I'll arrange {{accommodation}} accommodations and {{food}} dining options, maintaining a {{pace}} pace with {{daily_routes}} for your {{goal}}."
163175
176+
**Example with No Variables Used**: If Canvas Nodes contain no {{variable_name}} references, the template should be:
177+
"I'll help you create a comprehensive travel itinerary based on your preferences and requirements. I'll analyze your destination, dates, and specific needs to provide a detailed plan with accommodations, dining options, and daily activities."
178+
164179
${APP_PUBLISH_EXAMPLES}
165180
166181
## Key Learning Points from Examples
@@ -172,10 +187,12 @@ ${APP_PUBLISH_EXAMPLES}
172187
- End with clear expectations of what will be delivered
173188
174189
2. **Variable Integration**:
190+
- **CRITICAL**: Only include variables that are actually referenced in Canvas Nodes with {{variable_name}} format
175191
- Replace specific values with descriptive placeholders
176192
- Maintain the original semantic meaning
177-
- Ensure all extracted variables are represented
193+
- Ensure all used variables are represented
178194
- Use consistent naming conventions
195+
- **No Variables Case**: If no variables are used in Canvas Nodes, create a template without any {{variable_name}} placeholders
179196
180197
3. **User Experience Focus**:
181198
- Templates should be immediately understandable
@@ -185,9 +202,44 @@ ${APP_PUBLISH_EXAMPLES}
185202
186203
4. **Quality Assurance**:
187204
- Every template string must be complete and self-contained
188-
- All variables must be properly integrated
205+
- Only variables that are actually used in Canvas Nodes should be included
189206
- Templates should maintain the original workflow intent
190-
- Language should be professional yet approachable`;
207+
- Language should be professional yet approachable
208+
- **Variable Usage Validation**: Verify that all {{variable_name}} placeholders in the template correspond to variables actually referenced in Canvas Nodes`;
209+
}
210+
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;
191243
}
192244

193245
/**

apps/api/src/modules/variable-extraction/variable-extraction.service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -385,7 +385,7 @@ export class VariableExtractionService {
385385
this.prisma.variableExtractionHistory.findMany({
386386
where: { uid, status: 'applied' },
387387
orderBy: { createdAt: 'desc' },
388-
take: 20,
388+
take: 3,
389389
}),
390390
this.getRecentVariablePatterns(canvasId),
391391
]);

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

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,9 @@ const ShareSettings = React.memo(({ canvasId, canvasTitle }: ShareSettingsProps)
158158
if (access === 'off') return;
159159
// Copy link to clipboard immediately for better UX
160160
const newShareLink = getShareLink('canvas', shareRecord?.shareId ?? '');
161+
161162
await navigator.clipboard.writeText(newShareLink);
163+
162164
setLinkCopied(true);
163165
// Reset copied state after 3 seconds
164166
setTimeout(() => setLinkCopied(false), 3000);
@@ -176,6 +178,8 @@ const ShareSettings = React.memo(({ canvasId, canvasTitle }: ShareSettingsProps)
176178
}, [workflowAppLink, t]);
177179

178180
const handlePublishToCommunity = useCallback(() => {
181+
if (toolbarLoading || !skillResponseNodes?.length) return;
182+
179183
setCreateTemplateModalVisible(true);
180184
setOpen(false);
181185
}, []);
@@ -278,7 +282,8 @@ const ShareSettings = React.memo(({ canvasId, canvasTitle }: ShareSettingsProps)
278282
return { total, executing, finished, failed, waiting };
279283
}, [nodeExecutions]);
280284

281-
const { isLoading: skillResponseLoading } = useSkillResponseLoadingStatus(canvasId);
285+
const { isLoading: skillResponseLoading, skillResponseNodes } =
286+
useSkillResponseLoadingStatus(canvasId);
282287

283288
const toolbarLoading =
284289
executionStats.executing > 0 || executionStats.waiting > 0 || skillResponseLoading;
@@ -394,7 +399,7 @@ const ShareSettings = React.memo(({ canvasId, canvasTitle }: ShareSettingsProps)
394399
placement="top"
395400
>
396401
<Button
397-
disabled={toolbarLoading}
402+
disabled={toolbarLoading || !skillResponseNodes?.length}
398403
loading={toolbarLoading}
399404
type="primary"
400405
size="small"

0 commit comments

Comments
 (0)