language-operator 0.1.31 → 0.1.35
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 +4 -4
- data/.rubocop.yml +7 -8
- data/CHANGELOG.md +14 -0
- data/CI_STATUS.md +56 -0
- data/Gemfile.lock +2 -2
- data/Makefile +22 -6
- data/lib/language_operator/agent/base.rb +10 -6
- data/lib/language_operator/agent/executor.rb +19 -97
- data/lib/language_operator/agent/safety/ast_validator.rb +62 -43
- data/lib/language_operator/agent/safety/safe_executor.rb +27 -2
- data/lib/language_operator/agent/scheduler.rb +60 -0
- data/lib/language_operator/agent/task_executor.rb +548 -0
- data/lib/language_operator/agent.rb +90 -27
- data/lib/language_operator/cli/base_command.rb +117 -0
- data/lib/language_operator/cli/commands/agent.rb +339 -407
- data/lib/language_operator/cli/commands/cluster.rb +274 -290
- data/lib/language_operator/cli/commands/install.rb +110 -119
- data/lib/language_operator/cli/commands/model.rb +284 -184
- data/lib/language_operator/cli/commands/persona.rb +218 -284
- data/lib/language_operator/cli/commands/quickstart.rb +4 -5
- data/lib/language_operator/cli/commands/status.rb +31 -35
- data/lib/language_operator/cli/commands/system.rb +221 -233
- data/lib/language_operator/cli/commands/tool.rb +356 -422
- data/lib/language_operator/cli/commands/use.rb +19 -22
- data/lib/language_operator/cli/helpers/resource_dependency_checker.rb +0 -18
- data/lib/language_operator/cli/wizards/quickstart_wizard.rb +0 -1
- data/lib/language_operator/client/config.rb +20 -21
- data/lib/language_operator/config.rb +115 -3
- data/lib/language_operator/constants.rb +54 -0
- data/lib/language_operator/dsl/agent_context.rb +7 -7
- data/lib/language_operator/dsl/agent_definition.rb +111 -26
- data/lib/language_operator/dsl/config.rb +30 -66
- data/lib/language_operator/dsl/main_definition.rb +114 -0
- data/lib/language_operator/dsl/schema.rb +84 -43
- data/lib/language_operator/dsl/task_definition.rb +315 -0
- data/lib/language_operator/dsl.rb +0 -1
- data/lib/language_operator/instrumentation/task_tracer.rb +285 -0
- data/lib/language_operator/logger.rb +4 -4
- data/lib/language_operator/synthesis_test_harness.rb +324 -0
- data/lib/language_operator/templates/examples/agent_synthesis.tmpl +26 -8
- data/lib/language_operator/templates/schema/CHANGELOG.md +26 -0
- data/lib/language_operator/templates/schema/agent_dsl_openapi.yaml +1 -1
- data/lib/language_operator/templates/schema/agent_dsl_schema.json +84 -42
- data/lib/language_operator/type_coercion.rb +250 -0
- data/lib/language_operator/ux/base.rb +81 -0
- data/lib/language_operator/ux/concerns/README.md +155 -0
- data/lib/language_operator/ux/concerns/headings.rb +90 -0
- data/lib/language_operator/ux/concerns/input_validation.rb +146 -0
- data/lib/language_operator/ux/concerns/provider_helpers.rb +167 -0
- data/lib/language_operator/ux/create_agent.rb +252 -0
- data/lib/language_operator/ux/create_model.rb +267 -0
- data/lib/language_operator/ux/quickstart.rb +594 -0
- data/lib/language_operator/version.rb +1 -1
- data/lib/language_operator.rb +2 -0
- data/requirements/ARCHITECTURE.md +1 -0
- data/requirements/SCRATCH.md +153 -0
- data/requirements/dsl.md +0 -0
- data/requirements/features +1 -0
- data/requirements/personas +1 -0
- data/requirements/proposals +1 -0
- data/requirements/tasks/iterate.md +14 -15
- data/requirements/tasks/optimize.md +13 -4
- data/synth/001/Makefile +90 -0
- data/synth/001/agent.rb +26 -0
- data/synth/001/agent.yaml +7 -0
- data/synth/001/output.log +44 -0
- data/synth/Makefile +39 -0
- data/synth/README.md +342 -0
- metadata +37 -10
- data/lib/language_operator/dsl/workflow_definition.rb +0 -259
- data/test_agent_dsl.rb +0 -108
|
@@ -4,8 +4,11 @@ module LanguageOperator
|
|
|
4
4
|
module Dsl
|
|
5
5
|
# Configuration helper for managing environment variables
|
|
6
6
|
#
|
|
7
|
-
#
|
|
8
|
-
#
|
|
7
|
+
# This class delegates to LanguageOperator::Config for all functionality.
|
|
8
|
+
# It exists for backwards compatibility with existing code that uses
|
|
9
|
+
# Dsl::Config.
|
|
10
|
+
#
|
|
11
|
+
# @deprecated Use LanguageOperator::Config directly instead
|
|
9
12
|
#
|
|
10
13
|
# @example Basic usage
|
|
11
14
|
# Config.get('SMTP_HOST', 'MAIL_HOST', default: 'localhost')
|
|
@@ -13,92 +16,45 @@ module LanguageOperator
|
|
|
13
16
|
# Config.get_bool('USE_TLS', default: true)
|
|
14
17
|
class Config
|
|
15
18
|
# Get environment variable with multiple fallback keys
|
|
16
|
-
#
|
|
17
|
-
# @param keys [Array<String>] Environment variable names to try
|
|
18
|
-
# @param default [Object, nil] Default value if none found
|
|
19
|
-
# @return [String, nil] The first non-nil value or default
|
|
19
|
+
# Delegates to LanguageOperator::Config.get
|
|
20
20
|
def self.get(*keys, default: nil)
|
|
21
|
-
keys
|
|
22
|
-
value = ENV.fetch(key.to_s, nil)
|
|
23
|
-
return value if value
|
|
24
|
-
end
|
|
25
|
-
default
|
|
21
|
+
LanguageOperator::Config.get(*keys, default: default)
|
|
26
22
|
end
|
|
27
23
|
|
|
28
24
|
# Get required environment variable with fallback keys
|
|
29
|
-
#
|
|
30
|
-
# @param keys [Array<String>] Environment variable names to try
|
|
31
|
-
# @return [String] The first non-nil value
|
|
32
|
-
# @raise [ArgumentError] If none of the keys are set
|
|
25
|
+
# Delegates to LanguageOperator::Config.require
|
|
33
26
|
def self.require(*keys)
|
|
34
|
-
|
|
35
|
-
raise ArgumentError, "Missing required configuration: #{keys.join(' or ')}" unless value
|
|
36
|
-
|
|
37
|
-
value
|
|
27
|
+
LanguageOperator::Config.require(*keys)
|
|
38
28
|
end
|
|
39
29
|
|
|
40
30
|
# Get environment variable as integer
|
|
41
|
-
#
|
|
42
|
-
# @param keys [Array<String>] Environment variable names to try
|
|
43
|
-
# @param default [Integer, nil] Default value if none found
|
|
44
|
-
# @return [Integer, nil] The value converted to integer, or default
|
|
31
|
+
# Delegates to LanguageOperator::Config.get_int
|
|
45
32
|
def self.get_int(*keys, default: nil)
|
|
46
|
-
|
|
47
|
-
return default if value.nil?
|
|
48
|
-
|
|
49
|
-
value.to_i
|
|
33
|
+
LanguageOperator::Config.get_int(*keys, default: default)
|
|
50
34
|
end
|
|
51
35
|
|
|
52
36
|
# Get environment variable as boolean
|
|
53
|
-
#
|
|
54
|
-
# Treats 'true', '1', 'yes', 'on' as true (case insensitive).
|
|
55
|
-
#
|
|
56
|
-
# @param keys [Array<String>] Environment variable names to try
|
|
57
|
-
# @param default [Boolean] Default value if none found
|
|
58
|
-
# @return [Boolean] The value as boolean
|
|
37
|
+
# Delegates to LanguageOperator::Config.get_bool
|
|
59
38
|
def self.get_bool(*keys, default: false)
|
|
60
|
-
|
|
61
|
-
return default if value.nil?
|
|
62
|
-
|
|
63
|
-
value.to_s.downcase.match?(/^(true|1|yes|on)$/)
|
|
39
|
+
LanguageOperator::Config.get_bool(*keys, default: default)
|
|
64
40
|
end
|
|
65
41
|
|
|
66
|
-
# Get environment variable as array
|
|
67
|
-
#
|
|
68
|
-
# @param keys [Array<String>] Environment variable names to try
|
|
69
|
-
# @param default [Array] Default value if none found
|
|
70
|
-
# @param separator [String] Character to split on (default: ',')
|
|
71
|
-
# @return [Array<String>] The value split into array
|
|
42
|
+
# Get environment variable as array
|
|
43
|
+
# Delegates to LanguageOperator::Config.get_array
|
|
72
44
|
def self.get_array(*keys, default: [], separator: ',')
|
|
73
|
-
|
|
74
|
-
return default if value.nil? || value.empty?
|
|
75
|
-
|
|
76
|
-
value.split(separator).map(&:strip).reject(&:empty?)
|
|
45
|
+
LanguageOperator::Config.get_array(*keys, default: default, separator: separator)
|
|
77
46
|
end
|
|
78
47
|
|
|
79
|
-
# Check if
|
|
80
|
-
#
|
|
81
|
-
# @param keys [Array<String>] Environment variable names to check
|
|
82
|
-
# @return [Array<String>] Array of missing keys (empty if all present)
|
|
83
|
-
def self.check_required(*keys)
|
|
84
|
-
keys.reject { |key| ENV.fetch(key.to_s, nil) }
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
# Check if environment variable is set (even if empty string)
|
|
88
|
-
#
|
|
89
|
-
# @param keys [Array<String>] Environment variable names to check
|
|
90
|
-
# @return [Boolean] True if any key is set
|
|
48
|
+
# Check if environment variable is set
|
|
49
|
+
# Delegates to LanguageOperator::Config.set?
|
|
91
50
|
def self.set?(*keys)
|
|
92
|
-
|
|
51
|
+
LanguageOperator::Config.set?(*keys)
|
|
93
52
|
end
|
|
94
53
|
|
|
95
54
|
# Get all environment variables matching a prefix
|
|
96
|
-
#
|
|
97
|
-
# @param prefix [String] Prefix to match
|
|
98
|
-
# @return [Hash<String, String>] Hash with prefix removed from keys
|
|
55
|
+
# Delegates to LanguageOperator::Config.with_prefix
|
|
99
56
|
def self.with_prefix(prefix)
|
|
100
|
-
|
|
101
|
-
.transform_keys { |key| key.sub(prefix, '') }
|
|
57
|
+
LanguageOperator::Config.with_prefix(prefix)
|
|
102
58
|
end
|
|
103
59
|
|
|
104
60
|
# Build a configuration hash from environment variables
|
|
@@ -109,11 +65,19 @@ module LanguageOperator
|
|
|
109
65
|
config = {}
|
|
110
66
|
mappings.each do |config_key, env_keys|
|
|
111
67
|
env_keys = [env_keys] unless env_keys.is_a?(Array)
|
|
112
|
-
value = get(*env_keys)
|
|
68
|
+
value = LanguageOperator::Config.get(*env_keys)
|
|
113
69
|
config[config_key] = value if value
|
|
114
70
|
end
|
|
115
71
|
config
|
|
116
72
|
end
|
|
73
|
+
|
|
74
|
+
# Check if all required keys are present
|
|
75
|
+
#
|
|
76
|
+
# @param keys [Array<String>] Environment variable names to check
|
|
77
|
+
# @return [Array<String>] Array of missing keys (empty if all present)
|
|
78
|
+
def self.check_required(*keys)
|
|
79
|
+
keys.reject { |key| ENV.fetch(key.to_s, nil) }
|
|
80
|
+
end
|
|
117
81
|
end
|
|
118
82
|
end
|
|
119
83
|
end
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../loggable'
|
|
4
|
+
|
|
5
|
+
module LanguageOperator
|
|
6
|
+
module Dsl
|
|
7
|
+
# Main execution block for agents (DSL v1)
|
|
8
|
+
#
|
|
9
|
+
# Defines the imperative entry point for agent execution. The main block receives
|
|
10
|
+
# agent inputs and returns agent outputs. Within the block, agents can call tasks
|
|
11
|
+
# using execute_task(), use standard Ruby control flow (if/else, loops), and handle
|
|
12
|
+
# errors with standard Ruby exceptions.
|
|
13
|
+
#
|
|
14
|
+
# This replaces the declarative workflow/step model with an imperative programming
|
|
15
|
+
# model centered on organic functions (tasks).
|
|
16
|
+
#
|
|
17
|
+
# @example Simple main block
|
|
18
|
+
# main do |inputs|
|
|
19
|
+
# result = execute_task(:fetch_data, inputs: inputs)
|
|
20
|
+
# execute_task(:process_data, inputs: result)
|
|
21
|
+
# end
|
|
22
|
+
#
|
|
23
|
+
# @example Main block with control flow
|
|
24
|
+
# main do |inputs|
|
|
25
|
+
# data = execute_task(:fetch_data, inputs: inputs)
|
|
26
|
+
#
|
|
27
|
+
# if data[:count] > 100
|
|
28
|
+
# execute_task(:send_alert, inputs: { count: data[:count] })
|
|
29
|
+
# end
|
|
30
|
+
#
|
|
31
|
+
# execute_task(:save_results, inputs: data)
|
|
32
|
+
# end
|
|
33
|
+
#
|
|
34
|
+
# @example Main block with error handling
|
|
35
|
+
# main do |inputs|
|
|
36
|
+
# begin
|
|
37
|
+
# result = execute_task(:risky_operation, inputs: inputs)
|
|
38
|
+
# { success: true, result: result }
|
|
39
|
+
# rescue => e
|
|
40
|
+
# logger.error("Operation failed: #{e.message}")
|
|
41
|
+
# { success: false, error: e.message }
|
|
42
|
+
# end
|
|
43
|
+
# end
|
|
44
|
+
class MainDefinition
|
|
45
|
+
include LanguageOperator::Loggable
|
|
46
|
+
|
|
47
|
+
attr_reader :execute_block
|
|
48
|
+
|
|
49
|
+
# Initialize a new main definition
|
|
50
|
+
def initialize
|
|
51
|
+
@execute_block = nil
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Define the main execution block
|
|
55
|
+
#
|
|
56
|
+
# @yield [inputs] Block that receives agent inputs and returns agent outputs
|
|
57
|
+
# @yieldparam inputs [Hash] Agent input parameters
|
|
58
|
+
# @yieldreturn [Object] Agent output (typically a Hash)
|
|
59
|
+
# @return [void]
|
|
60
|
+
# @example
|
|
61
|
+
# execute do |inputs|
|
|
62
|
+
# result = execute_task(:my_task, inputs: inputs)
|
|
63
|
+
# result
|
|
64
|
+
# end
|
|
65
|
+
def execute(&block)
|
|
66
|
+
raise ArgumentError, 'Main block is required' unless block
|
|
67
|
+
|
|
68
|
+
@execute_block = block
|
|
69
|
+
logger.debug('Main block defined', arity: block.arity)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Execute the main block with given inputs
|
|
73
|
+
#
|
|
74
|
+
# @param inputs [Hash] Agent input parameters
|
|
75
|
+
# @param context [Object] Execution context that provides execute_task method
|
|
76
|
+
# @return [Object] Result from main block
|
|
77
|
+
# @raise [RuntimeError] If main block is not defined
|
|
78
|
+
# @raise [ArgumentError] If inputs is not a Hash
|
|
79
|
+
def call(inputs, context)
|
|
80
|
+
raise 'Main block not defined. Use execute { |inputs| ... } to define it.' unless @execute_block
|
|
81
|
+
raise ArgumentError, "inputs must be a Hash, got #{inputs.class}" unless inputs.is_a?(Hash)
|
|
82
|
+
|
|
83
|
+
logger.info('Executing main block', inputs_keys: inputs.keys)
|
|
84
|
+
|
|
85
|
+
result = logger.timed('Main execution') do
|
|
86
|
+
# Execute block in context to provide access to execute_task
|
|
87
|
+
context.instance_exec(inputs, &@execute_block)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
logger.info('Main block completed')
|
|
91
|
+
result
|
|
92
|
+
rescue StandardError => e
|
|
93
|
+
logger.error('Main block execution failed',
|
|
94
|
+
error: e.class.name,
|
|
95
|
+
message: e.message,
|
|
96
|
+
backtrace: e.backtrace&.first(5))
|
|
97
|
+
raise
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# Check if main block is defined
|
|
101
|
+
#
|
|
102
|
+
# @return [Boolean] True if execute block is set
|
|
103
|
+
def defined?
|
|
104
|
+
!@execute_block.nil?
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
private
|
|
108
|
+
|
|
109
|
+
def logger_component
|
|
110
|
+
'Main'
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative '../version'
|
|
4
|
+
require_relative '../constants'
|
|
4
5
|
|
|
5
6
|
module LanguageOperator
|
|
6
7
|
module Dsl
|
|
@@ -164,7 +165,7 @@ module LanguageOperator
|
|
|
164
165
|
mode: {
|
|
165
166
|
type: 'string',
|
|
166
167
|
description: 'Execution mode for the agent',
|
|
167
|
-
enum:
|
|
168
|
+
enum: Constants::PRIMARY_MODES
|
|
168
169
|
},
|
|
169
170
|
objectives: {
|
|
170
171
|
type: 'array',
|
|
@@ -174,9 +175,19 @@ module LanguageOperator
|
|
|
174
175
|
},
|
|
175
176
|
minItems: 0
|
|
176
177
|
},
|
|
177
|
-
|
|
178
|
-
|
|
178
|
+
# DSL v1 (task/main model)
|
|
179
|
+
tasks: {
|
|
180
|
+
type: 'array',
|
|
181
|
+
description: 'Task definitions (organic functions with stable contracts)',
|
|
182
|
+
items: {
|
|
183
|
+
'$ref': '#/definitions/TaskDefinition'
|
|
184
|
+
}
|
|
179
185
|
},
|
|
186
|
+
main: {
|
|
187
|
+
'$ref': '#/definitions/MainDefinition',
|
|
188
|
+
description: 'Main execution block (imperative entry point)'
|
|
189
|
+
},
|
|
190
|
+
# Common properties
|
|
180
191
|
constraints: {
|
|
181
192
|
'$ref': '#/definitions/ConstraintsDefinition'
|
|
182
193
|
},
|
|
@@ -204,8 +215,11 @@ module LanguageOperator
|
|
|
204
215
|
# @return [Hash] Schema definitions for nested types
|
|
205
216
|
def self.all_definitions
|
|
206
217
|
{
|
|
207
|
-
|
|
208
|
-
|
|
218
|
+
# DSL v1 (task/main model)
|
|
219
|
+
TaskDefinition: task_definition_schema,
|
|
220
|
+
MainDefinition: main_definition_schema,
|
|
221
|
+
TypeSchema: type_schema_definition,
|
|
222
|
+
# Common definitions
|
|
209
223
|
ConstraintsDefinition: constraints_definition_schema,
|
|
210
224
|
OutputDefinition: output_definition_schema,
|
|
211
225
|
WebhookDefinition: webhook_definition_schema,
|
|
@@ -217,62 +231,89 @@ module LanguageOperator
|
|
|
217
231
|
}
|
|
218
232
|
end
|
|
219
233
|
|
|
220
|
-
#
|
|
234
|
+
# Task definition schema (DSL v1)
|
|
221
235
|
#
|
|
222
|
-
# @return [Hash] Schema for
|
|
223
|
-
def self.
|
|
236
|
+
# @return [Hash] Schema for task definitions (organic functions)
|
|
237
|
+
def self.task_definition_schema
|
|
224
238
|
{
|
|
225
239
|
type: 'object',
|
|
226
|
-
description: '
|
|
240
|
+
description: 'Organic function with stable contract (inputs/outputs) and evolving implementation',
|
|
227
241
|
properties: {
|
|
228
|
-
|
|
229
|
-
type: '
|
|
230
|
-
description: '
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
242
|
+
name: {
|
|
243
|
+
type: 'string',
|
|
244
|
+
description: 'Task identifier (symbol)',
|
|
245
|
+
pattern: '^[a-z_][a-z0-9_]*$'
|
|
246
|
+
},
|
|
247
|
+
inputs: {
|
|
248
|
+
'$ref': '#/definitions/TypeSchema',
|
|
249
|
+
description: 'Input contract (parameter types)'
|
|
250
|
+
},
|
|
251
|
+
outputs: {
|
|
252
|
+
'$ref': '#/definitions/TypeSchema',
|
|
253
|
+
description: 'Output contract (return value types)'
|
|
254
|
+
},
|
|
255
|
+
instructions: {
|
|
256
|
+
type: 'string',
|
|
257
|
+
description: 'Natural language instructions for neural implementation (optional)'
|
|
258
|
+
},
|
|
259
|
+
implementation_type: {
|
|
260
|
+
type: 'string',
|
|
261
|
+
description: 'Implementation approach',
|
|
262
|
+
enum: %w[neural symbolic hybrid undefined]
|
|
234
263
|
}
|
|
235
|
-
}
|
|
264
|
+
},
|
|
265
|
+
required: %w[name inputs outputs]
|
|
236
266
|
}
|
|
237
267
|
end
|
|
238
268
|
|
|
239
|
-
#
|
|
269
|
+
# Main definition schema (DSL v1)
|
|
240
270
|
#
|
|
241
|
-
# @return [Hash] Schema for
|
|
242
|
-
def self.
|
|
271
|
+
# @return [Hash] Schema for main execution block
|
|
272
|
+
def self.main_definition_schema
|
|
243
273
|
{
|
|
244
274
|
type: 'object',
|
|
245
|
-
description: '
|
|
275
|
+
description: 'Imperative entry point for agent execution',
|
|
246
276
|
properties: {
|
|
247
|
-
|
|
277
|
+
type: {
|
|
248
278
|
type: 'string',
|
|
249
|
-
description: '
|
|
279
|
+
description: 'Block type',
|
|
280
|
+
enum: ['main']
|
|
250
281
|
},
|
|
251
|
-
|
|
282
|
+
description: {
|
|
252
283
|
type: 'string',
|
|
253
|
-
description: '
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
},
|
|
270
|
-
prompt: {
|
|
284
|
+
description: 'Main block executes tasks using execute_task() with Ruby control flow'
|
|
285
|
+
}
|
|
286
|
+
},
|
|
287
|
+
additionalProperties: false
|
|
288
|
+
}
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
# Type schema definition (DSL v1)
|
|
292
|
+
#
|
|
293
|
+
# @return [Hash] Schema for type schemas used in task inputs/outputs
|
|
294
|
+
def self.type_schema_definition
|
|
295
|
+
{
|
|
296
|
+
type: 'object',
|
|
297
|
+
description: 'Type schema for task contract validation',
|
|
298
|
+
patternProperties: {
|
|
299
|
+
'^[a-z_][a-z0-9_]*$': {
|
|
271
300
|
type: 'string',
|
|
272
|
-
description: '
|
|
301
|
+
description: 'Parameter type',
|
|
302
|
+
enum: %w[string integer number boolean array hash any]
|
|
273
303
|
}
|
|
274
304
|
},
|
|
275
|
-
|
|
305
|
+
additionalProperties: false,
|
|
306
|
+
examples: [
|
|
307
|
+
{
|
|
308
|
+
user_id: 'integer',
|
|
309
|
+
name: 'string',
|
|
310
|
+
active: 'boolean'
|
|
311
|
+
},
|
|
312
|
+
{
|
|
313
|
+
data: 'array',
|
|
314
|
+
metadata: 'hash'
|
|
315
|
+
}
|
|
316
|
+
]
|
|
276
317
|
}
|
|
277
318
|
end
|
|
278
319
|
|