Class: LanguageOperator::Dsl::TaskDefinition

Inherits:
Object
  • Object
show all
Includes:
Loggable
Defined in:
lib/language_operator/dsl/task_definition.rb

Overview

Task definition for organic functions (DSL v1)

Represents an organic function with a stable contract (inputs/outputs) where the implementation can evolve from neural (instructions-based) to symbolic (explicit code) without breaking callers.

Examples:

Neural task (LLM-based)

task :analyze_data,
  instructions: "Analyze the data for anomalies",
  inputs: { data: 'array' },
  outputs: { issues: 'array', summary: 'string' }

Symbolic task (explicit code)

task :calculate_total,
  inputs: { items: 'array' },
  outputs: { total: 'number' }
do |inputs|
  { total: inputs[:items].sum { |i| i['amount'] } }
end

Hybrid task (both instructions and code)

task :fetch_user,
  instructions: "Fetch user data from database",
  inputs: { user_id: 'integer' },
  outputs: { user: 'hash', preferences: 'hash' }
do |inputs|
  execute_tool('database', 'get_user', id: inputs[:user_id])
end

Constant Summary collapse

SUPPORTED_TYPES =

Supported types for input/output validation

%w[string integer number boolean array hash any].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Loggable

#logger

Constructor Details

#initialize(name) ⇒ TaskDefinition

Initialize a new task definition

Parameters:

  • name (Symbol)

    Task name



48
49
50
51
52
53
54
# File 'lib/language_operator/dsl/task_definition.rb', line 48

def initialize(name)
  @name = name
  @inputs_schema = {}
  @outputs_schema = {}
  @instructions_text = nil
  @execute_block = nil
end

Instance Attribute Details

#execute_blockObject (readonly)

Returns the value of attribute execute_block.



40
41
42
# File 'lib/language_operator/dsl/task_definition.rb', line 40

def execute_block
  @execute_block
end

#inputs_schemaObject (readonly)

Returns the value of attribute inputs_schema.



40
41
42
# File 'lib/language_operator/dsl/task_definition.rb', line 40

def inputs_schema
  @inputs_schema
end

#instructions_textObject (readonly)

Returns the value of attribute instructions_text.



40
41
42
# File 'lib/language_operator/dsl/task_definition.rb', line 40

def instructions_text
  @instructions_text
end

#nameObject (readonly)

Returns the value of attribute name.



40
41
42
# File 'lib/language_operator/dsl/task_definition.rb', line 40

def name
  @name
end

#outputs_schemaObject (readonly)

Returns the value of attribute outputs_schema.



40
41
42
# File 'lib/language_operator/dsl/task_definition.rb', line 40

def outputs_schema
  @outputs_schema
end

Instance Method Details

#call(input_params, context = nil) ⇒ Hash

Execute the task with given inputs

Parameters:

  • input_params (Hash)

    Input parameters

  • context (Object, nil) (defaults to: nil)

    Execution context (optional)

Returns:

  • (Hash)

    Validated output matching outputs schema

Raises:

  • (ArgumentError)

    If inputs or outputs don't match schema



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/language_operator/dsl/task_definition.rb', line 127

def call(input_params, context = nil)
  # Validate and coerce inputs
  validated_inputs = validate_inputs(input_params)

  # Execute based on implementation type
  result = if symbolic?
             # Symbolic execution (explicit code)
             logger.debug('Executing symbolic task', task: @name)
             execute_symbolic(validated_inputs, context)
           elsif neural?
             # Neural execution (LLM-based)
             logger.debug('Executing neural task', task: @name, instructions: @instructions_text)
             execute_neural(validated_inputs, context)
           else
             raise "Task #{@name} has no implementation (neither neural nor symbolic)"
           end

  # Validate outputs
  validate_outputs(result)
end

#execute {|inputs| ... } ⇒ Object

Define the symbolic implementation

Examples:

execute do |inputs|
  { total: inputs[:items].sum { |i| i['amount'] } }
end

Yields:

  • (inputs)

    Block that receives validated inputs and returns outputs

Yield Parameters:

  • inputs (Hash)

    Validated and coerced input parameters

Yield Returns:

  • (Hash)

    Output values matching the outputs schema



103
104
105
# File 'lib/language_operator/dsl/task_definition.rb', line 103

def execute(&block)
  @execute_block = block if block
end

#inputs(schema = nil) ⇒ Hash

Define or retrieve the input contract

Examples:

inputs { user_id: 'integer', filter: 'string' }

Parameters:

  • schema (Hash, nil) (defaults to: nil)

    Input schema (param_name => type_string)

Returns:

  • (Hash)

    Current input schema



62
63
64
65
66
67
# File 'lib/language_operator/dsl/task_definition.rb', line 62

def inputs(schema = nil)
  return @inputs_schema if schema.nil?

  validate_schema!(schema, 'inputs')
  @inputs_schema = schema
end

#instructions(text = nil) ⇒ String?

Define or retrieve the instructions (neural implementation)

Examples:

instructions "Fetch user data from the database"

Parameters:

  • text (String, nil) (defaults to: nil)

    Natural language instructions

Returns:

  • (String, nil)

    Current instructions



88
89
90
91
92
# File 'lib/language_operator/dsl/task_definition.rb', line 88

def instructions(text = nil)
  return @instructions_text if text.nil?

  @instructions_text = text
end

#neural?Boolean

Check if this is a neural task (instructions-based)

Returns:

  • (Boolean)

    True if instructions are defined



110
111
112
# File 'lib/language_operator/dsl/task_definition.rb', line 110

def neural?
  !@instructions_text.nil?
end

#outputs(schema = nil) ⇒ Hash

Define or retrieve the output contract

Examples:

outputs { user: 'hash', success: 'boolean' }

Parameters:

  • schema (Hash, nil) (defaults to: nil)

    Output schema (field_name => type_string)

Returns:

  • (Hash)

    Current output schema



75
76
77
78
79
80
# File 'lib/language_operator/dsl/task_definition.rb', line 75

def outputs(schema = nil)
  return @outputs_schema if schema.nil?

  validate_schema!(schema, 'outputs')
  @outputs_schema = schema
end

#symbolic?Boolean

Check if this is a symbolic task (code-based)

Returns:

  • (Boolean)

    True if execute block is defined



117
118
119
# File 'lib/language_operator/dsl/task_definition.rb', line 117

def symbolic?
  !@execute_block.nil?
end

#to_schemaHash

Export task as JSON schema

Returns:

  • (Hash)

    JSON Schema representation



209
210
211
212
213
214
215
216
217
# File 'lib/language_operator/dsl/task_definition.rb', line 209

def to_schema
  {
    'name' => @name.to_s,
    'type' => implementation_type,
    'instructions' => @instructions_text,
    'inputs' => schema_to_json(@inputs_schema),
    'outputs' => schema_to_json(@outputs_schema)
  }
end

#validate_inputs(params) ⇒ Hash

Validate input parameters against schema

Parameters:

  • params (Hash)

    Input parameters

Returns:

  • (Hash)

    Validated and coerced parameters

Raises:



153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/language_operator/dsl/task_definition.rb', line 153

def validate_inputs(params)
  params = params.transform_keys(&:to_sym)
  validated = {}

  @inputs_schema.each do |key, type|
    key_sym = key.to_sym
    value = params[key_sym]

    if value.nil?
      original_error = ArgumentError.new("Missing required input parameter: #{key}")
      raise LanguageOperator::Agent::TaskValidationError.new(@name,
                                                              "Missing required input parameter: #{key}",
                                                              original_error)
    end

    validated[key_sym] = coerce_value(value, type, "input parameter '#{key}'")
  end

  # Check for unexpected parameters
  extra_keys = params.keys - @inputs_schema.keys.map(&:to_sym)
  logger.warn('Unexpected input parameters', task: @name, extra: extra_keys) unless extra_keys.empty?

  validated
end

#validate_outputs(result) ⇒ Hash

Validate output values against schema

Parameters:

  • result (Hash)

    Output values

Returns:

  • (Hash)

    Validated and coerced outputs

Raises:



183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
# File 'lib/language_operator/dsl/task_definition.rb', line 183

def validate_outputs(result)
  return result if @outputs_schema.empty? # No schema = no validation

  result = result.transform_keys(&:to_sym)
  validated = {}

  @outputs_schema.each do |key, type|
    key_sym = key.to_sym
    value = result[key_sym]

    if value.nil?
      original_error = ArgumentError.new("Missing required output field: #{key}")
      raise LanguageOperator::Agent::TaskValidationError.new(@name,
                                                              "Missing required output field: #{key}",
                                                              original_error)
    end

    validated[key_sym] = coerce_value(value, type, "output field '#{key}'")
  end

  validated
end