Skip to content

Conversation

@AaronGoldsmith
Copy link
Contributor

@AaronGoldsmith AaronGoldsmith commented Jun 29, 2025

This pull request introduces enhancements to support recipe parameters in the desktop UI, including parameter substitution, validation, and serialization. The changes span multiple files, adding functionality for parameter handling in recipes, improving user interaction, and enabling serialization of parameters to YAML format.

✨ What's New

Recipe Parameters - Transform your recipes into flexible, reusable templates with dynamic parameter substitution! 🎯

This PR introduces a powerful new parameter system that allows recipes to accept user input at runtime, making them adaptable to different projects, environments, and use cases.

🚀 Key Features

🔧 Parameter Definition

  • Flexible Parameter Types - Support for both required and optional parameters
  • Rich Metadata - Each parameter includes name, description, and requirement status
  • Template Syntax - Use {{parameter_name}} placeholders in instructions and prompts
  • Type Safety - Full TypeScript interface support for parameter definitions

🎨 Interactive Parameter Collection

  • Smart Modal Interface - Beautiful parameter input modal with validation
  • Real-time Validation - Visual feedback for required fields with error states
  • User-friendly UX - Clear labels, descriptions, and intuitive form design
  • Flexible Cancel Flow - Options to return to form or start fresh chat

⚡ Dynamic Substitution

  • Runtime Replacement - Parameters are substituted when recipe is executed
  • Robust Parsing - Enhanced regex-based substitution with special character support
  • Debug Support - Console logging for troubleshooting parameter substitution

🎁 User Experience Enhancements

  • Dynamic, parameterized recipes
  • Reusable templates across projects
  • Interactive setup with guided parameter collection
  • Smart validation and error handling

🔧 Technical Implementation

Core Components

  • Parameter Interface - Type-safe parameter definitions
  • ParameterInputModal - React component for parameter collection
  • substituteParameters - Enhanced substitution engine with debugging
  • Recipe Integration - Seamless parameter flow from editor to execution

Parameter Flow

  1. Recipe Definition - Author defines parameters in recipe metadata
  2. Parameter Collection - Modal prompts user for required/optional values
  3. Template Substitution - Parameters replaced in instructions and prompts
  4. Chat Execution - Recipe runs with personalized content

🎨 UI/UX Features

  • Validation States - Red borders and error messages for invalid inputs
  • Smart Buttons - "Start Recipe" CTA with proper validation
  • Cancel Options - Flexible cancel flow with clear choices
  • Rounded Design - Consistent button styling with theme support
  • Backdrop Effects - Subtle blur overlay for modal focus

🔧 Development Notes

Force Push Required: Local git hooks were automatically running linting and including formatting changes in merge commits. A force push was necessary to maintain clean commit history and separate linting changes from feature implementation.

✅ Testing

  • ✅ TypeScript compilation passes
  • ✅ ESLint checks pass (0 warnings)
  • ✅ Parameter substitution verified with test recipes
  • ✅ Modal validation tested for required/optional parameters
  • ✅ Cancel flow tested for all scenarios
  • ✅ Template syntax parsing verified with special characters

📁 Files Changed

  • ui/desktop/src/types/recipe/index.ts - Parameter interface definitions
  • ui/desktop/src/components/ParameterInputModal.tsx - Parameter collection UI
  • ui/desktop/src/components/RecipeEditor.tsx - Recipe parameter integration
  • ui/desktop/src/main.ts - Parameter substitution and chat window creation
  • ui/desktop/src/utils/parameterSubstitution.ts - Template processing engine

Result: Recipes are now powerful, reusable templates that adapt to any context. Users can create once and reuse everywhere with personalized parameter values! 🎉

Comment on lines 80 to 83
// Escape special characters in the key (parameter) and match optional whitespace
const regex = new RegExp(`{{\\s*${key.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\s*}}`, 'g');
const beforeSubstitution = substitutedPrompt;
substitutedPrompt = substitutedPrompt.replace(regex, params[key]);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Treat the parameter as literal text, to avoid regex injection and unintended matching.

For example, without santization

// matches {{user_name}}, {{user-name}}, etc
substitutedPrompt.replace(new RegExp('{{user.name}}'), value) 

with sanitization

// matches exactly {{user.name}}
substitutedPrompt.replace(new RegExp('{{user\.name}}'), value)

…rompt' and remove unused options in ParameterInput

refactor: simplify onClose handler in ParameterInputModal and clean up styling comments
@AaronGoldsmith AaronGoldsmith marked this pull request as ready for review June 30, 2025 01:06
* main:
  return missign npx/uvx (block#3148)
  docs: add more instructions about resuming a session for cli users (block#3146)

// Log each substitution for debugging
if (beforeSubstitution !== substitutedPrompt) {
console.log(`Replaced {{${key}}} with "${params[key]}"`);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rm logging.

}
}

console.log('Final substituted prompt:', substitutedPrompt);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

""


// Log each substitution for debugging
if (beforeSubstitution !== substitutedText) {
console.log(`Replaced {{${key}}} with "${params[key]}" in instructions`);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

more logging.

Copy link
Collaborator

@katzdave katzdave left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Took another look + tested some more with recipes with various types of params. I think looks good.


// Create and send the user message
const userMessage = createUserMessage(recipeConfig.prompt);
console.log('Auto-sending substituted prompt for scheduled execution:', finalPrompt);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can remove?

console.log('Final config extensions:', config.extensions);

const yamlString = serializeParametersToYAML(parameters);
console.log('Serialized Parameters to YAML:', yamlString);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can remove?

const originalInstructions = (recipeConfig as { instructions?: string })?.instructions;

if (!originalInstructions) {
console.log('No instructions to substitute parameters in');
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can remove?


if (!response.ok) {
console.warn(`Failed to update system prompt with parameters: ${response.statusText}`);
} else {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can remove the else clause?

Comment on lines 287 to 291
# Move the built binary to the expected location (inside container)
mkdir -p ../target/x86_64-pc-windows-gnu/release
mv temporal-service.exe ../target/x86_64-pc-windows-gnu/release/temporal-service.exe
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gah, sorry – I have automatic linting on, and it linted all the changed files from the merge. Let me know if I should revert the whitespace issues.

* main: (37 commits)
  fix: fix desktop recipe url generation (block#3209)
  feat: improve UX for saving recipes (block#3214)
  fix: Pass Google AI API key in HTTP header, not query param (block#3192)
  docs: add linter to CONTRIBUTING.md (block#3168)
  feat: Structured output for recipes (block#3188)
  Fix cost tracking accuracy and OpenRouter model pricing (block#3189)
  docs: update cli install instructions for windows (block#3205)
  Docs: Cost tracking on the desktop app (block#3204)
  feat: Adding streamable-http transport support for backend, desktop and cli (block#2942)
  fix: use the correct `contains` syntax on create-recipe-pr.yml (block#3193)
  Temporarily Remove GH Copilot Provider  (block#3199)
  docs: fix tab navigation (block#3201)
  feat: use tiktoken-rs instead of tokenizers, single global tokenizer (block#3115)
  add playwright-mcp server to extensions list (block#3010)
  Add `/extension` path for extension installation (block#3011)
  feat(desktop): Prioritize suffix when truncating path in header (block#3110)
  chore(release): release version 1.0.31 (block#3185)
  feat: additional sub recipes via command line (block#3163)
  Add Internal Recipes To Recipes Cookbook (block#3179)
  pipe the argument to storage (block#3184)
  ...
@AaronGoldsmith
Copy link
Contributor Author

I'm going to need to force push to reset the branch back to a healthy state. I'll re-request reviews

@AaronGoldsmith AaronGoldsmith force-pushed the ag/feat-desktop-recipe-params branch from 6ad0a3a to e314a58 Compare July 2, 2025 17:19
@AaronGoldsmith AaronGoldsmith requested a review from angiejones July 2, 2025 17:19
@angiejones angiejones merged commit 2e97621 into block:main Jul 2, 2025
9 of 10 checks passed
wpfleger96 added a commit to wpfleger96/goose that referenced this pull request Jul 2, 2025
* main:
  Defend against invalid sessions (block#3229)
  Clean up session file optionality for --no-session (block#3230)
  Feat: Support Recipe Parameters in Goose desktop app (block#3155)
  docs: update recipe example (block#3222)
  Add native OAuth 2.0 authentication support to MCP client (block#3213)
  build: Check in Cargo.lock changes (block#3220)
  fix: fix desktop recipe url generation (block#3209)
  feat: improve UX for saving recipes (block#3214)
baxen added a commit to Developerayo/goose that referenced this pull request Jul 2, 2025
* main: (150 commits)
  Defend against invalid sessions (block#3229)
  Clean up session file optionality for --no-session (block#3230)
  Feat: Support Recipe Parameters in Goose desktop app (block#3155)
  docs: update recipe example (block#3222)
  Add native OAuth 2.0 authentication support to MCP client (block#3213)
  build: Check in Cargo.lock changes (block#3220)
  fix: fix desktop recipe url generation (block#3209)
  feat: improve UX for saving recipes (block#3214)
  fix: Pass Google AI API key in HTTP header, not query param (block#3192)
  docs: add linter to CONTRIBUTING.md (block#3168)
  feat: Structured output for recipes (block#3188)
  Fix cost tracking accuracy and OpenRouter model pricing (block#3189)
  docs: update cli install instructions for windows (block#3205)
  Docs: Cost tracking on the desktop app (block#3204)
  feat: Adding streamable-http transport support for backend, desktop and cli (block#2942)
  fix: use the correct `contains` syntax on create-recipe-pr.yml (block#3193)
  Temporarily Remove GH Copilot Provider  (block#3199)
  docs: fix tab navigation (block#3201)
  feat: use tiktoken-rs instead of tokenizers, single global tokenizer (block#3115)
  add playwright-mcp server to extensions list (block#3010)
  ...
jsibbison-square added a commit that referenced this pull request Jul 2, 2025
…x-turns

* origin/main:
  Defend against invalid sessions (#3229)
  Clean up session file optionality for --no-session (#3230)
  Feat: Support Recipe Parameters in Goose desktop app (#3155)
  docs: update recipe example (#3222)
  Add native OAuth 2.0 authentication support to MCP client (#3213)
  build: Check in Cargo.lock changes (#3220)
  fix: fix desktop recipe url generation (#3209)
  feat: improve UX for saving recipes (#3214)
  fix: Pass Google AI API key in HTTP header, not query param (#3192)
  docs: add linter to CONTRIBUTING.md (#3168)
atarantino pushed a commit to atarantino/goose that referenced this pull request Jul 14, 2025
s-soroosh pushed a commit to s-soroosh/goose that referenced this pull request Jul 18, 2025
kwsantiago pushed a commit to kwsantiago/goose that referenced this pull request Jul 19, 2025
cbruyndoncx pushed a commit to cbruyndoncx/goose that referenced this pull request Jul 20, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants