roast-ai 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8ab27704514fc6ddfa09003464d2aa324b852379b0548619e2f0023bebe793ae
4
- data.tar.gz: 18c0936f2b5dc2b54ef420be2ac089b8252f64a02227ab33d98db9d2e6249136
3
+ metadata.gz: db58f659180113d7a2bb1bface8da2898be6717033107247156a464b4d14159d
4
+ data.tar.gz: f14c2caae89fab3353b66ae3eb4457c56975e65c464037a2d401cfca30840d81
5
5
  SHA512:
6
- metadata.gz: 50552385cdb280592a1e331c4a3ec5de2924fa05636af5deb742b96f2fde229e3448e61e6516e570c02a8dc0f416a3b9a3c3d884a800eb89987c90c856a0258d
7
- data.tar.gz: 8feeb510d87e6e6256c46cbca3e13fbc65701ceb28b049452e5bea2f44815f7770e688f8422487b431a85c5f459beffadcce590e7b860cde8a1ab4ee939ff50e
6
+ metadata.gz: 88c3f83651c535077bdfe29408a19b874f66f19d8b7e743dd4933922f82fd7aee53ee215968e3d10c0207e92d4c53018a0b190475ba7ac4b70d15cda07a634ff
7
+ data.tar.gz: 5ebae3dcc5d7d775a3f19ab79ead81d7c11f53fc31b5b20f1db4781a950032e693a2d331fdc4509eb0661c04072f421defcd56d15b9d6ce74f7bfc12357ee1b0
data/CHANGELOG.md CHANGED
@@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.2.1]
9
+
10
+ ### Added
11
+ - Smart coercion defaults for boolean expressions based on step type
12
+ - Ruby expressions (`{{expr}}`) default to regular boolean coercion
13
+ - Bash commands (`$(cmd)`) default to exit code interpretation
14
+ - Inline prompts and regular steps default to "smart" LLM-powered interpretation (looks for truthy or falsy language)
15
+ - Direct syntax for step configuration - `coerce_to` and other options are now specified directly on iteration steps
16
+
8
17
  ## [0.2.0] - 2025-05-26
9
18
 
10
19
  ### Added
data/CLAUDE_NOTES.md ADDED
@@ -0,0 +1,68 @@
1
+ # Important Notes for Claude
2
+
3
+ ## Roast Workflow Syntax
4
+
5
+ ### IMPORTANT: No inline configuration for steps!
6
+
7
+ Roast workflows DO NOT support inline configuration syntax like this:
8
+ ```yaml
9
+ # WRONG - This syntax does NOT exist:
10
+ steps:
11
+ - step_name:
12
+ prompt: "some prompt"
13
+ output: variable_name
14
+ ```
15
+
16
+ The correct syntax is:
17
+ ```yaml
18
+ # CORRECT - Steps are just names or hash assignments:
19
+ steps:
20
+ - step_name
21
+ - variable_name: step_name
22
+ - variable_name: $(command)
23
+ ```
24
+
25
+ ### Control flow structures
26
+
27
+ Only control flow structures (if/unless, case/when/else, each, repeat) support nested configuration:
28
+
29
+ ```yaml
30
+ steps:
31
+ # Simple step - just the name
32
+ - detect_language
33
+
34
+ # Variable assignment
35
+ - my_var: detect_language
36
+
37
+ # Command execution with assignment
38
+ - env_type: $(echo $ENVIRONMENT)
39
+
40
+ # Control flow - these DO have nested structure
41
+ - if: "{{ condition }}"
42
+ then:
43
+ - step1
44
+ - step2
45
+
46
+ - case: "{{ expression }}"
47
+ when:
48
+ value1:
49
+ - step1
50
+ value2:
51
+ - step2
52
+ else:
53
+ - step3
54
+ ```
55
+
56
+ ### Step Configuration
57
+
58
+ Step configuration (prompts, outputs, etc.) is handled through:
59
+ 1. File naming conventions (step_name/prompt.md, step_name/output.txt)
60
+ 2. The workflow configuration file itself (tools, target, etc.)
61
+
62
+ NOT through inline step configuration in the steps array.
63
+
64
+ ## Remember:
65
+ - Steps array contains step names, not step configurations
66
+ - Only control flow structures have nested configuration
67
+ - Variable assignment uses hash syntax: `var_name: step_name`
68
+ - Commands use $() syntax: `var_name: $(command)`
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- roast-ai (0.2.0)
4
+ roast-ai (0.2.1)
5
5
  activesupport (~> 8.0)
6
6
  cli-ui
7
7
  diff-lcs (~> 1.5)
data/README.md CHANGED
@@ -4,6 +4,18 @@
4
4
 
5
5
  A convention-oriented framework for creating structured AI workflows, maintained by the Augmented Engineering team at Shopify.
6
6
 
7
+ ## Installation
8
+
9
+ ```bash
10
+ $ gem install roast-ai
11
+ ```
12
+
13
+ Or add to your Gemfile:
14
+
15
+ ```ruby
16
+ gem 'roast-ai'
17
+ ```
18
+
7
19
  ## Why you should use Roast
8
20
 
9
21
  Roast provides a structured, declarative approach to building AI workflows with:
@@ -64,6 +76,42 @@ steps:
64
76
  - Summarize the changes made to {{File.basename(file)}}.
65
77
  ```
66
78
 
79
+ ## Try it
80
+
81
+ If you don’t have one already, get an OpenAI key from [here](https://platform.openai.com/settings/organization/api-keys). You will need an account with a credit card, make sure that a basic completion works.
82
+
83
+ ```bash
84
+ export OPENAI_API_KEY=sk-proj-....
85
+
86
+ curl -H "Content-Type: application/json" \
87
+ -H "Authorization: Bearer $API_TOKEN" \
88
+ -d '{"model":"gpt-4.1-mini","messages":[{"role":"user","content":"What is 1+1?"}]}' \
89
+ https://api.openai.com/v1/chat/completions
90
+ ```
91
+
92
+ The [test grading workflow](examples/grading/workflow.md) in this repository is a senior software engineer and testing expert that evaluates the quality of a test based on guidelines.
93
+
94
+ Try the workflow.
95
+
96
+ ```bash
97
+ ./exe/roast execute examples/grading/workflow.yml test/roast/resources_test.rb
98
+
99
+ 🔥🔥🔥 Everyone loves a good roast 🔥🔥🔥
100
+ ...
101
+ ```
102
+
103
+ This will output a test grade.
104
+
105
+ ```
106
+ ========== TEST GRADE REPORT ==========
107
+ Test file: test/roast/resources_test.rb
108
+
109
+ FINAL GRADE:
110
+ Score: 80/100
111
+ Letter Grade: B
112
+ ```
113
+ Note that you may also need `shadowenv` and `rg`, on MacOS run `brew install shadowenv` and `brew install rg`.
114
+
67
115
  ## How to use Roast
68
116
 
69
117
  1. Create a workflow YAML file defining your steps and tools
@@ -178,7 +226,37 @@ Roast supports several types of steps:
178
226
  - Until conditions: `until: "{{condition}}"`
179
227
  - Maximum iterations: `max_iterations: 10`
180
228
 
181
- 6. **Raw prompt step**: Simple text prompts for the model without tools
229
+ 6. **Case/when/else steps**: Select different execution paths based on a value (similar to Ruby's case statement)
230
+ ```yaml
231
+ steps:
232
+ - detect_language
233
+
234
+ - case: "{{ workflow.output.detect_language }}"
235
+ when:
236
+ ruby:
237
+ - lint_with_rubocop
238
+ - test_with_rspec
239
+ javascript:
240
+ - lint_with_eslint
241
+ - test_with_jest
242
+ python:
243
+ - lint_with_pylint
244
+ - test_with_pytest
245
+ else:
246
+ - analyze_generic
247
+ - generate_basic_report
248
+ ```
249
+
250
+ Case expressions can be:
251
+ - Workflow outputs: `case: "{{ workflow.output.variable }}"`
252
+ - Ruby expressions: `case: "{{ count > 10 ? 'high' : 'low' }}"`
253
+ - Bash commands: `case: "$(echo $ENVIRONMENT)"`
254
+ - Direct values: `case: "production"`
255
+
256
+ The value is compared against each key in the `when` clause, and matching steps are executed.
257
+ If no match is found, the `else` steps are executed (if provided).
258
+
259
+ 7. **Raw prompt step**: Simple text prompts for the model without tools
182
260
  ```yaml
183
261
  steps:
184
262
  - Summarize the changes made to the codebase.
@@ -668,18 +746,6 @@ your-project/
668
746
  └── ...
669
747
  ```
670
748
 
671
- ## Installation
672
-
673
- ```bash
674
- $ gem install roast-ai
675
- ```
676
-
677
- Or add to your Gemfile:
678
-
679
- ```ruby
680
- gem 'roast-ai'
681
- ```
682
-
683
749
  ## Development
684
750
 
685
751
  After checking out the repo, run `bundle install` to install dependencies. Then, run `bundle exec rake` to run the tests and linter. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -90,10 +90,38 @@ For defining prompts directly in the workflow:
90
90
 
91
91
  ## Type Coercion
92
92
 
93
- Values are automatically coerced to the appropriate types:
93
+ ### Smart Defaults
94
94
 
95
- - For `until` conditions: Values are coerced to booleans (using Ruby's truthiness rules)
96
- - For `each` collections: Values are coerced to iterables (converted to arrays of lines if needed)
95
+ Roast applies intelligent defaults for boolean coercion based on the type of expression:
96
+
97
+ - **Ruby expressions** (`{{expr}}`) → Regular boolean coercion (`!!value`)
98
+ - **Bash commands** (`$(cmd)`) → Exit code interpretation (0 = true, non-zero = false)
99
+ - **Inline prompts/step names** → LLM boolean interpretation (analyzes yes/no intent)
100
+
101
+ ### Manual Coercion
102
+
103
+ You can override the smart defaults by specifying `coerce_to` directly in the step:
104
+
105
+ ```yaml
106
+ # Override prompt to use regular boolean instead of LLM boolean
107
+ - repeat:
108
+ until: "check_condition"
109
+ coerce_to: boolean
110
+ steps:
111
+ - process_item
112
+
113
+ # Force a step result to be treated as iterable
114
+ - each: "get_items"
115
+ as: "item"
116
+ coerce_to: iterable
117
+ steps:
118
+ - process: "{{item}}"
119
+ ```
120
+
121
+ Available coercion types:
122
+ - `boolean` - Standard Ruby truthiness (`!!` operator)
123
+ - `llm_boolean` - Natural language yes/no interpretation
124
+ - `iterable` - Convert to array (splits strings on newlines)
97
125
 
98
126
  ## Migrating Existing Workflows
99
127
 
@@ -0,0 +1,58 @@
1
+ # Case/When/Else Example
2
+
3
+ This example demonstrates the use of `case/when/else` control flow in Roast workflows.
4
+
5
+ ## Overview
6
+
7
+ The `case/when/else` construct allows you to execute different steps based on the value of an expression, similar to Ruby's case statement or switch statements in other languages.
8
+
9
+ ## Syntax
10
+
11
+ ```yaml
12
+ - case: <expression>
13
+ when:
14
+ <value1>:
15
+ - <steps>
16
+ <value2>:
17
+ - <steps>
18
+ else:
19
+ - <steps>
20
+ ```
21
+
22
+ ## Features Demonstrated
23
+
24
+ 1. **Basic case/when/else**: Detect file language and execute language-specific analysis
25
+ 2. **Bash command evaluation**: Use environment variables to determine deployment strategy
26
+ 3. **Complex expressions**: Use Ruby expressions to categorize numeric values
27
+
28
+ ## Expression Types
29
+
30
+ The `case` expression can be:
31
+ - A simple string value
32
+ - An interpolated workflow output: `{{ workflow.output.variable }}`
33
+ - A Ruby expression: `{{ workflow.output.count > 10 ? 'high' : 'low' }}`
34
+ - A bash command: `$(echo $ENVIRONMENT)`
35
+ - A reference to a previous step's output
36
+
37
+ ## How It Works
38
+
39
+ 1. The `case` expression is evaluated to produce a value
40
+ 2. The value is compared against each key in the `when` clause
41
+ 3. If a match is found, the steps under that key are executed
42
+ 4. If no match is found and an `else` clause exists, those steps are executed
43
+ 5. If no match is found and no `else` clause exists, execution continues
44
+
45
+ ## Running the Example
46
+
47
+ ```bash
48
+ roast execute examples/case_when/workflow.yml
49
+ ```
50
+
51
+ This will process all Ruby, JavaScript, Python, and Go files in the current directory, detecting their language and running appropriate analysis steps.
52
+
53
+ ## Use Cases
54
+
55
+ - **Multi-language projects**: Different linting/testing for different file types
56
+ - **Environment-specific workflows**: Different deployment steps for prod/staging/dev
57
+ - **Conditional processing**: Different handling based on file size, complexity, or other metrics
58
+ - **Error handling**: Different recovery strategies based on error types
@@ -0,0 +1,16 @@
1
+ # Detect Programming Language
2
+
3
+ Based on the file extension and content, determine the primary programming language of this file:
4
+ - If it's a `.rb` file, return "ruby"
5
+ - If it's a `.js` file, return "javascript"
6
+ - If it's a `.py` file, return "python"
7
+ - If it's a `.go` file, return "go"
8
+ - Otherwise, return "unknown"
9
+
10
+ Return ONLY the language name in lowercase, nothing else.
11
+
12
+ File: {{ context.resource_uri }}
13
+ Content:
14
+ ```
15
+ {{ context.resource }}
16
+ ```
@@ -0,0 +1,58 @@
1
+ name: "Case/When/Else Example"
2
+
3
+ tools:
4
+ - Roast::Tools::Cmd
5
+ - Roast::Tools::ReadFile
6
+ - Roast::Tools::WriteFile
7
+
8
+ target: "**/*.{rb,js,py,go}"
9
+
10
+ steps:
11
+ - detect_language
12
+
13
+ - case: "{{ workflow.output.detect_language }}"
14
+ when:
15
+ ruby:
16
+ - analyze_ruby
17
+ - generate_ruby_report
18
+ javascript:
19
+ - analyze_javascript
20
+ - generate_js_report
21
+ python:
22
+ - analyze_python
23
+ - generate_python_report
24
+ go:
25
+ - analyze_go
26
+ - generate_go_report
27
+ else:
28
+ - analyze_generic
29
+ - generate_generic_report
30
+
31
+ # Another example using bash command for case expression
32
+ - get_environment: $(echo $ENVIRONMENT || echo "development")
33
+
34
+ - case: "{{ workflow.output.get_environment }}"
35
+ when:
36
+ production:
37
+ - production_checks
38
+ - deploy_production
39
+ staging:
40
+ - staging_checks
41
+ - deploy_staging
42
+ development:
43
+ - run_tests
44
+ - local_deploy
45
+ else:
46
+ - unknown_environment
47
+
48
+ # Example with numeric case values
49
+ - count_issues
50
+
51
+ - case: "{{ workflow.output.count_issues.to_i > 10 ? 'high' : workflow.output.count_issues.to_i > 5 ? 'medium' : 'low' }}"
52
+ when:
53
+ high:
54
+ - high_priority_alert
55
+ medium:
56
+ - medium_priority_notice
57
+ low:
58
+ - low_priority_info
@@ -0,0 +1,32 @@
1
+ # Direct Coerce Syntax
2
+
3
+ This example demonstrates the simplified syntax for specifying `coerce_to` and other configuration options directly on iteration steps.
4
+
5
+ ## Direct Syntax
6
+
7
+ Configuration options are specified directly on the step:
8
+
9
+ ```yaml
10
+ - repeat:
11
+ until: "condition"
12
+ coerce_to: boolean
13
+ print_response: true
14
+ model: "claude-3-haiku"
15
+ steps: [...]
16
+ ```
17
+
18
+ ## Benefits
19
+
20
+ 1. **Cleaner YAML** - No unnecessary nesting
21
+ 2. **More intuitive** - Configuration options are at the same level as other step properties
22
+ 3. **Consistent** - Matches how other step properties are specified
23
+
24
+ ## Supported Options
25
+
26
+ All step configuration options can be specified directly:
27
+ - `coerce_to` - Type coercion (boolean, llm_boolean, iterable)
28
+ - `print_response` - Whether to print LLM responses
29
+ - `loop` - Auto-loop behavior
30
+ - `json` - JSON response mode
31
+ - `params` - Additional parameters
32
+ - `model` - Model override
@@ -0,0 +1,36 @@
1
+ name: Direct Coerce Syntax Demo
2
+ description: Demonstrates the simplified coerce_to syntax without config blocks
3
+
4
+ steps:
5
+ # Example 1: Direct coerce_to on repeat
6
+ - repeat:
7
+ until: "check_api_ready"
8
+ coerce_to: boolean # Direct syntax - no config block needed
9
+ max_iterations: 5
10
+ steps:
11
+ - check_api_ready:
12
+ prompt: "Check if the API endpoint returns a 200 status"
13
+ - wait: 2
14
+
15
+ # Example 2: Direct coerce_to on each
16
+ - get_data_sources:
17
+ prompt: "List available data sources, one per line"
18
+
19
+ - each: "get_data_sources"
20
+ as: "source"
21
+ coerce_to: iterable # Direct syntax
22
+ steps:
23
+ - validate_source: "Validating {{source}}..."
24
+ - process_source:
25
+ prompt: "Process data from {{source}}"
26
+
27
+ # Example 3: Multiple configuration options
28
+ - repeat:
29
+ until: "all_tests_pass"
30
+ coerce_to: llm_boolean # Override default
31
+ print_response: true # Other options work too
32
+ max_iterations: 10
33
+ steps:
34
+ - run_tests: "$(rake test)"
35
+ - all_tests_pass:
36
+ prompt: "Did all tests pass successfully?"
@@ -1,5 +1,7 @@
1
1
  name: Test Grading
2
- model: anthropic:claude-opus-4
2
+ api_token: $(echo $OPENAI_API_KEY)
3
+ # model: anthropic:claude-opus-4
4
+ model: gpt-4.1-mini
3
5
 
4
6
  tools:
5
7
  - Roast::Tools::Grep
@@ -23,16 +25,16 @@ steps:
23
25
 
24
26
  # set non-default attributes for steps below
25
27
  analyze_coverage:
26
- model: gpt-4.1-mini
28
+ # model: gpt-4.1-mini
27
29
  auto_loop: false
28
30
  json: true
29
31
 
30
32
  generate_grades:
31
- model: o3
33
+ # model: o3
32
34
  json: true
33
35
 
34
36
  generate_recommendations:
35
- model: o3
37
+ # model: o3
36
38
  auto_loop: false
37
39
  json: true
38
40
  params:
@@ -0,0 +1,32 @@
1
+ # JSON Handling Example
2
+
3
+ This example demonstrates how Roast handles JSON responses from LLM steps.
4
+
5
+ ## Key Features
6
+
7
+ 1. **JSON Arrays**: When a step has `json: true` and returns an array, the result is `flatten.first` - the first element after flattening the array. This is useful when the LLM returns an array with a single object.
8
+
9
+ 2. **JSON Objects**: Hash/object responses are maintained as proper Ruby hashes in the workflow output.
10
+
11
+ 3. **Replay Support**: JSON data structures are properly serialized and deserialized when saving/loading workflow state for replay functionality.
12
+
13
+ ## Running the Example
14
+
15
+ ```bash
16
+ bin/roast examples/json_handling/workflow.yml
17
+ ```
18
+
19
+ ## How It Works
20
+
21
+ 1. The `fetch_users` step generates a JSON array of user objects
22
+ 2. The `fetch_metadata` step generates a JSON object with metadata
23
+ 3. The `process_data` step can access the structured data using `{{output.fetch_users}}` and `{{output.fetch_metadata}}`
24
+ 4. The structured data is preserved through the workflow, including during replay scenarios
25
+
26
+ ## Implementation Details
27
+
28
+ When `json: true` is set on a step:
29
+ - Array responses return `flatten.first` - the first element after flattening
30
+ - Object responses are preserved as hashes
31
+ - Non-JSON array responses (when `json: false`) are joined with newlines
32
+ - The data maintains its structure when saved to and loaded from workflow state files
@@ -0,0 +1,52 @@
1
+ name: JSON Data Handling Example
2
+ api_provider: openai
3
+ model: gpt-4
4
+
5
+ tools:
6
+ - type: write_file
7
+ allowed_paths:
8
+ - examples/json_handling/
9
+
10
+ steps:
11
+ - name: fetch_users
12
+ prompt: |
13
+ Generate a JSON array of 3 user objects. Each user should have:
14
+ - id (number)
15
+ - name (string)
16
+ - email (string)
17
+ - active (boolean)
18
+ json: true
19
+
20
+ - name: fetch_metadata
21
+ prompt: |
22
+ Generate a JSON object with metadata about a dataset:
23
+ - total_records (number)
24
+ - last_updated (ISO date string)
25
+ - categories (array of strings)
26
+ - filters (object with status and sort fields)
27
+ json: true
28
+
29
+ - name: process_data
30
+ prompt: |
31
+ Based on the users data: {{output.fetch_users}}
32
+ And metadata: {{output.fetch_metadata}}
33
+
34
+ Create a summary report describing:
35
+ 1. How many active users there are
36
+ 2. The categories available
37
+ 3. When the data was last updated
38
+
39
+ - name: save_report
40
+ tool: write_file
41
+ path: examples/json_handling/report.txt
42
+ content: |
43
+ # JSON Data Processing Report
44
+
45
+ ## Users Data
46
+ {{output.fetch_users}}
47
+
48
+ ## Metadata
49
+ {{output.fetch_metadata}}
50
+
51
+ ## Summary
52
+ {{output.process_data}}
@@ -0,0 +1,65 @@
1
+ # Smart Coercion Defaults
2
+
3
+ This example demonstrates how Roast applies intelligent defaults for boolean coercion based on the type of expression being evaluated.
4
+
5
+ ## Default Coercion Rules
6
+
7
+ When a step is used in a boolean context (like `if`, `unless`, or `until` conditions) and no explicit `coerce_to` is specified, Roast applies these smart defaults:
8
+
9
+ 1. **Ruby Expressions** (`{{expression}}`) → Regular boolean coercion (`!!value`)
10
+ - `nil` and `false` are falsy
11
+ - Everything else is truthy (including 0, empty arrays, etc.)
12
+
13
+ 2. **Bash Commands** (`$(command)`) → Exit code interpretation
14
+ - Exit code 0 = true (success)
15
+ - Non-zero exit code = false (failure)
16
+
17
+ 3. **Prompt/Step Names** → LLM boolean interpretation
18
+ - Analyzes natural language responses for yes/no intent
19
+ - "Yes", "True", "Affirmative" → true
20
+ - "No", "False", "Negative" → false
21
+
22
+ 4. **Non-string Values** → Regular boolean coercion
23
+
24
+ ## Examples
25
+
26
+ ### Ruby Expression (Regular Boolean)
27
+ ```yaml
28
+ - repeat:
29
+ until: "{{counter >= 5}}" # Uses !! coercion
30
+ steps:
31
+ - increment: counter
32
+ ```
33
+
34
+ ### Bash Command (Exit Code)
35
+ ```yaml
36
+ - repeat:
37
+ until: "$(test -f /tmp/done)" # True when file exists (exit 0)
38
+ steps:
39
+ - wait: 1
40
+ ```
41
+
42
+ ### Prompt Response (LLM Boolean)
43
+ ```yaml
44
+ - if: "Should we continue?" # Interprets "Yes, let's continue" as true
45
+ then:
46
+ - proceed: "Continuing..."
47
+ ```
48
+
49
+ ## Overriding Defaults
50
+
51
+ You can always override the default coercion by specifying `coerce_to` directly in the step:
52
+
53
+ ```yaml
54
+ - each: "get_items"
55
+ as: "item"
56
+ coerce_to: iterable # Override default to split into array
57
+ steps:
58
+ - process: "{{item}}"
59
+ ```
60
+
61
+ ## Supported Coercion Types
62
+
63
+ - `boolean` - Standard Ruby truthiness (!! operator)
64
+ - `llm_boolean` - Natural language yes/no interpretation
65
+ - `iterable` - Convert to array (splits strings on newlines)