conductor_ruby 0.1.0

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.
Files changed (143) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +142 -0
  3. data/LICENSE +190 -0
  4. data/README.md +517 -0
  5. data/examples/agentic_workflows/llm_chat.rb +106 -0
  6. data/examples/dynamic_workflow.rb +177 -0
  7. data/examples/event_handler.rb +94 -0
  8. data/examples/event_listener_examples.rb +430 -0
  9. data/examples/helloworld/greetings_worker.rb +24 -0
  10. data/examples/helloworld/helloworld.rb +99 -0
  11. data/examples/kitchensink.rb +213 -0
  12. data/examples/metadata_journey.rb +189 -0
  13. data/examples/metrics_example.rb +284 -0
  14. data/examples/new_dsl_demo.rb +141 -0
  15. data/examples/orkes/http_poll.rb +83 -0
  16. data/examples/orkes/secrets_example.rb +69 -0
  17. data/examples/orkes/wait_for_webhook.rb +90 -0
  18. data/examples/prompt_journey.rb +245 -0
  19. data/examples/rag_workflow.rb +167 -0
  20. data/examples/schedule_journey.rb +244 -0
  21. data/examples/simple_worker.rb +125 -0
  22. data/examples/simple_workflow.rb +89 -0
  23. data/examples/task_context_example.rb +257 -0
  24. data/examples/task_listener_example.rb +192 -0
  25. data/examples/worker_configuration_example.rb +282 -0
  26. data/examples/workflow_dsl.rb +316 -0
  27. data/examples/workflow_ops.rb +305 -0
  28. data/lib/conductor/client/authorization_client.rb +238 -0
  29. data/lib/conductor/client/integration_client.rb +108 -0
  30. data/lib/conductor/client/metadata_client.rb +139 -0
  31. data/lib/conductor/client/prompt_client.rb +58 -0
  32. data/lib/conductor/client/scheduler_client.rb +132 -0
  33. data/lib/conductor/client/schema_client.rb +32 -0
  34. data/lib/conductor/client/secret_client.rb +48 -0
  35. data/lib/conductor/client/task_client.rb +168 -0
  36. data/lib/conductor/client/workflow_client.rb +242 -0
  37. data/lib/conductor/configuration/authentication_settings.rb +17 -0
  38. data/lib/conductor/configuration.rb +103 -0
  39. data/lib/conductor/exceptions.rb +86 -0
  40. data/lib/conductor/http/api/application_resource_api.rb +107 -0
  41. data/lib/conductor/http/api/authorization_resource_api.rb +56 -0
  42. data/lib/conductor/http/api/event_resource_api.rb +133 -0
  43. data/lib/conductor/http/api/gateway_auth_resource_api.rb +48 -0
  44. data/lib/conductor/http/api/group_resource_api.rb +76 -0
  45. data/lib/conductor/http/api/integration_resource_api.rb +145 -0
  46. data/lib/conductor/http/api/metadata_resource_api.rb +231 -0
  47. data/lib/conductor/http/api/prompt_resource_api.rb +81 -0
  48. data/lib/conductor/http/api/role_resource_api.rb +60 -0
  49. data/lib/conductor/http/api/scheduler_resource_api.rb +211 -0
  50. data/lib/conductor/http/api/schema_resource_api.rb +82 -0
  51. data/lib/conductor/http/api/secret_resource_api.rb +134 -0
  52. data/lib/conductor/http/api/task_resource_api.rb +321 -0
  53. data/lib/conductor/http/api/token_resource_api.rb +42 -0
  54. data/lib/conductor/http/api/user_resource_api.rb +59 -0
  55. data/lib/conductor/http/api/workflow_bulk_resource_api.rb +91 -0
  56. data/lib/conductor/http/api/workflow_resource_api.rb +451 -0
  57. data/lib/conductor/http/api_client.rb +437 -0
  58. data/lib/conductor/http/models/authentication_config.rb +67 -0
  59. data/lib/conductor/http/models/authorization_request.rb +39 -0
  60. data/lib/conductor/http/models/base_model.rb +162 -0
  61. data/lib/conductor/http/models/bulk_response.rb +39 -0
  62. data/lib/conductor/http/models/conductor_application.rb +39 -0
  63. data/lib/conductor/http/models/conductor_user.rb +53 -0
  64. data/lib/conductor/http/models/create_or_update_application_request.rb +24 -0
  65. data/lib/conductor/http/models/create_or_update_role_request.rb +27 -0
  66. data/lib/conductor/http/models/event_handler.rb +130 -0
  67. data/lib/conductor/http/models/generate_token_request.rb +27 -0
  68. data/lib/conductor/http/models/group.rb +36 -0
  69. data/lib/conductor/http/models/integration.rb +70 -0
  70. data/lib/conductor/http/models/integration_api.rb +53 -0
  71. data/lib/conductor/http/models/integration_api_update.rb +43 -0
  72. data/lib/conductor/http/models/integration_update.rb +36 -0
  73. data/lib/conductor/http/models/permission.rb +24 -0
  74. data/lib/conductor/http/models/poll_data.rb +33 -0
  75. data/lib/conductor/http/models/prompt_template.rb +59 -0
  76. data/lib/conductor/http/models/prompt_template_test_request.rb +43 -0
  77. data/lib/conductor/http/models/rerun_workflow_request.rb +37 -0
  78. data/lib/conductor/http/models/role.rb +27 -0
  79. data/lib/conductor/http/models/schema_def.rb +59 -0
  80. data/lib/conductor/http/models/search_result.rb +187 -0
  81. data/lib/conductor/http/models/skip_task_request.rb +27 -0
  82. data/lib/conductor/http/models/start_workflow_request.rb +68 -0
  83. data/lib/conductor/http/models/subject_ref.rb +35 -0
  84. data/lib/conductor/http/models/tag_object.rb +36 -0
  85. data/lib/conductor/http/models/target_ref.rb +39 -0
  86. data/lib/conductor/http/models/task.rb +156 -0
  87. data/lib/conductor/http/models/task_def.rb +95 -0
  88. data/lib/conductor/http/models/task_exec_log.rb +30 -0
  89. data/lib/conductor/http/models/task_result.rb +115 -0
  90. data/lib/conductor/http/models/task_result_status.rb +24 -0
  91. data/lib/conductor/http/models/token.rb +33 -0
  92. data/lib/conductor/http/models/upsert_group_request.rb +30 -0
  93. data/lib/conductor/http/models/upsert_user_request.rb +39 -0
  94. data/lib/conductor/http/models/workflow.rb +202 -0
  95. data/lib/conductor/http/models/workflow_def.rb +73 -0
  96. data/lib/conductor/http/models/workflow_schedule.rb +100 -0
  97. data/lib/conductor/http/models/workflow_state_update.rb +30 -0
  98. data/lib/conductor/http/models/workflow_status_constants.rb +57 -0
  99. data/lib/conductor/http/models/workflow_task.rb +169 -0
  100. data/lib/conductor/http/models/workflow_test_request.rb +67 -0
  101. data/lib/conductor/http/rest_client.rb +211 -0
  102. data/lib/conductor/orkes/models/access_key.rb +56 -0
  103. data/lib/conductor/orkes/models/granted_permission.rb +27 -0
  104. data/lib/conductor/orkes/models/metadata_tag.rb +15 -0
  105. data/lib/conductor/orkes/models/rate_limit_tag.rb +15 -0
  106. data/lib/conductor/orkes/orkes_clients.rb +69 -0
  107. data/lib/conductor/version.rb +5 -0
  108. data/lib/conductor/worker/events/conductor_event.rb +40 -0
  109. data/lib/conductor/worker/events/global_dispatcher.rb +37 -0
  110. data/lib/conductor/worker/events/http_events.rb +25 -0
  111. data/lib/conductor/worker/events/listener_registry.rb +40 -0
  112. data/lib/conductor/worker/events/listeners.rb +34 -0
  113. data/lib/conductor/worker/events/sync_event_dispatcher.rb +78 -0
  114. data/lib/conductor/worker/events/task_runner_events.rb +271 -0
  115. data/lib/conductor/worker/events/workflow_events.rb +49 -0
  116. data/lib/conductor/worker/fiber_executor.rb +532 -0
  117. data/lib/conductor/worker/ractor_task_runner.rb +501 -0
  118. data/lib/conductor/worker/task_context.rb +114 -0
  119. data/lib/conductor/worker/task_definition_registrar.rb +322 -0
  120. data/lib/conductor/worker/task_handler.rb +360 -0
  121. data/lib/conductor/worker/task_in_progress.rb +60 -0
  122. data/lib/conductor/worker/task_runner.rb +538 -0
  123. data/lib/conductor/worker/telemetry/metrics_collector.rb +196 -0
  124. data/lib/conductor/worker/telemetry/prometheus_backend.rb +224 -0
  125. data/lib/conductor/worker/worker.rb +355 -0
  126. data/lib/conductor/worker/worker_config.rb +154 -0
  127. data/lib/conductor/worker/worker_registry.rb +71 -0
  128. data/lib/conductor/workflow/dsl/input_ref.rb +37 -0
  129. data/lib/conductor/workflow/dsl/output_ref.rb +44 -0
  130. data/lib/conductor/workflow/dsl/parallel_builder.rb +49 -0
  131. data/lib/conductor/workflow/dsl/switch_builder.rb +74 -0
  132. data/lib/conductor/workflow/dsl/task_ref.rb +178 -0
  133. data/lib/conductor/workflow/dsl/workflow_builder.rb +1016 -0
  134. data/lib/conductor/workflow/dsl/workflow_definition.rb +150 -0
  135. data/lib/conductor/workflow/llm/chat_message.rb +47 -0
  136. data/lib/conductor/workflow/llm/embedding_model.rb +19 -0
  137. data/lib/conductor/workflow/llm/tool_call.rb +43 -0
  138. data/lib/conductor/workflow/llm/tool_spec.rb +46 -0
  139. data/lib/conductor/workflow/task_type.rb +68 -0
  140. data/lib/conductor/workflow/timeout_policy.rb +31 -0
  141. data/lib/conductor/workflow/workflow_executor.rb +373 -0
  142. data/lib/conductor.rb +192 -0
  143. metadata +359 -0
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Conductor
4
+ module Workflow
5
+ module Dsl
6
+ # ParallelBuilder collects tasks defined in a parallel block.
7
+ # It proxies all method calls to the parent WorkflowBuilder and
8
+ # organizes the resulting tasks into parallel branches.
9
+ #
10
+ # @example
11
+ # parallel do
12
+ # simple :task1
13
+ # simple :task2
14
+ # end
15
+ #
16
+ class ParallelBuilder
17
+ def initialize(parent_builder)
18
+ @parent = parent_builder
19
+ @branches = []
20
+ @current_branch = []
21
+ end
22
+
23
+ # Finalize the parallel block and return branches
24
+ # @return [Array<Array<TaskRef>>] Array of task branches
25
+ def finalize
26
+ # Add current branch if it has tasks
27
+ @branches << @current_branch unless @current_branch.empty?
28
+ @branches
29
+ end
30
+
31
+ # Delegate all method calls to the parent builder
32
+ # and collect resulting TaskRefs
33
+ def method_missing(name, *args, **kwargs, &block)
34
+ if @parent.respond_to?(name, true)
35
+ task_ref = @parent.send(name, *args, **kwargs, &block)
36
+ @current_branch << task_ref if task_ref.is_a?(TaskRef)
37
+ task_ref
38
+ else
39
+ super
40
+ end
41
+ end
42
+
43
+ def respond_to_missing?(name, include_private = false)
44
+ @parent.respond_to?(name, include_private) || super
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Conductor
4
+ module Workflow
5
+ module Dsl
6
+ # SwitchBuilder collects switch cases defined in a decide block.
7
+ # It provides on() and otherwise() methods for defining case branches.
8
+ #
9
+ # @example
10
+ # decide user[:country] do
11
+ # on 'US' do
12
+ # simple :us_flow
13
+ # end
14
+ # on 'UK' do
15
+ # simple :uk_flow
16
+ # end
17
+ # otherwise do
18
+ # simple :default_flow
19
+ # end
20
+ # end
21
+ #
22
+ class SwitchBuilder
23
+ attr_reader :expression, :cases, :default
24
+
25
+ def initialize(expression, parent_builder)
26
+ @expression = expression
27
+ @parent = parent_builder
28
+ @cases = {}
29
+ @default = []
30
+ end
31
+
32
+ # Define a case branch
33
+ # @param value [String, Symbol] The case value to match
34
+ # @yield Block containing tasks for this case
35
+ def on(value, &block)
36
+ tasks = []
37
+ collector = TaskCollector.new(@parent, tasks)
38
+ collector.instance_eval(&block)
39
+ @cases[value.to_s] = tasks
40
+ end
41
+
42
+ # Define the default case (executed if no cases match)
43
+ # @yield Block containing tasks for the default case
44
+ def otherwise(&block)
45
+ collector = TaskCollector.new(@parent, @default)
46
+ collector.instance_eval(&block)
47
+ end
48
+ end
49
+
50
+ # TaskCollector is a helper that collects tasks created in a block.
51
+ # It delegates method calls to the parent builder and stores the results.
52
+ class TaskCollector
53
+ def initialize(parent_builder, task_array)
54
+ @parent = parent_builder
55
+ @tasks = task_array
56
+ end
57
+
58
+ def method_missing(name, *args, **kwargs, &block)
59
+ if @parent.respond_to?(name, true)
60
+ task_ref = @parent.send(name, *args, **kwargs, &block)
61
+ @tasks << task_ref if task_ref.is_a?(TaskRef)
62
+ task_ref
63
+ else
64
+ super
65
+ end
66
+ end
67
+
68
+ def respond_to_missing?(name, include_private = false)
69
+ @parent.respond_to?(name, include_private) || super
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,178 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Conductor
4
+ module Workflow
5
+ module Dsl
6
+ # TaskRef is a lightweight proxy returned by DSL task methods
7
+ # Enables [] syntax for output references and stores task metadata
8
+ class TaskRef
9
+ attr_reader :ref_name, :task_name, :task_type, :input_parameters, :options
10
+ alias inputs input_parameters
11
+
12
+ # @param ref_name [String] Auto-generated reference name
13
+ # @param task_name [String] The task definition name
14
+ # @param task_type [String] Conductor task type (SIMPLE, HTTP, etc.)
15
+ # @param input_parameters [Hash] Input parameters for the task
16
+ # @param options [Hash] Additional options (optional, cache, retry, etc.)
17
+ def initialize(ref_name:, task_name:, task_type:, input_parameters: {}, options: {})
18
+ @ref_name = ref_name
19
+ @task_name = task_name
20
+ @task_type = task_type
21
+ @input_parameters = input_parameters
22
+ @options = options
23
+ end
24
+
25
+ # Access task output by field name using [] syntax
26
+ # @param field [String, Symbol] The output field name
27
+ # @return [OutputRef] An OutputRef pointing to this task's output
28
+ # @example
29
+ # user = simple :get_user, id: 1
30
+ # user[:email] # => "${get_user_ref.output.email}"
31
+ # user[:profile][:name] # => "${get_user_ref.output.profile.name}"
32
+ def [](field)
33
+ OutputRef.new("#{@ref_name}.output.#{field}")
34
+ end
35
+
36
+ # Access task's full output (no specific field)
37
+ # @return [OutputRef] An OutputRef pointing to all task output
38
+ def output
39
+ OutputRef.new("#{@ref_name}.output")
40
+ end
41
+
42
+ # Access task input (for dynamic references)
43
+ # @param field [String, Symbol, nil] Optional field name
44
+ # @return [OutputRef] An OutputRef pointing to task input
45
+ def input(field = nil)
46
+ if field
47
+ OutputRef.new("#{@ref_name}.input.#{field}")
48
+ else
49
+ OutputRef.new("#{@ref_name}.input")
50
+ end
51
+ end
52
+
53
+ # Convert to WorkflowTask model for serialization
54
+ # @return [Conductor::Http::Models::WorkflowTask]
55
+ def to_workflow_task
56
+ wf_task = Conductor::Http::Models::WorkflowTask.new(
57
+ name: @task_name,
58
+ task_reference_name: @ref_name,
59
+ type: @task_type,
60
+ input_parameters: @input_parameters
61
+ )
62
+
63
+ # Apply options
64
+ wf_task.description = @options[:description] if @options[:description]
65
+ wf_task.optional = @options[:optional] if @options[:optional]
66
+
67
+ # Cache config
68
+ if @options[:cache_key] && @options[:cache_ttl]
69
+ wf_task.cache_config = Conductor::Http::Models::CacheConfig.new(
70
+ key: @options[:cache_key],
71
+ ttl_in_second: @options[:cache_ttl]
72
+ )
73
+ end
74
+
75
+ # Task-specific fields
76
+ apply_task_specific_fields(wf_task)
77
+
78
+ wf_task
79
+ end
80
+
81
+ private
82
+
83
+ def apply_task_specific_fields(wf_task)
84
+ case @task_type
85
+ when Conductor::Workflow::TaskType::SWITCH
86
+ apply_switch_fields(wf_task)
87
+ when Conductor::Workflow::TaskType::FORK_JOIN
88
+ apply_fork_join_fields(wf_task)
89
+ when Conductor::Workflow::TaskType::JOIN
90
+ apply_join_fields(wf_task)
91
+ when Conductor::Workflow::TaskType::DO_WHILE
92
+ apply_do_while_fields(wf_task)
93
+ when Conductor::Workflow::TaskType::SUB_WORKFLOW
94
+ apply_sub_workflow_fields(wf_task)
95
+ when Conductor::Workflow::TaskType::FORK_JOIN_DYNAMIC
96
+ apply_dynamic_fork_fields(wf_task)
97
+ when Conductor::Workflow::TaskType::DYNAMIC
98
+ wf_task.dynamic_task_name_param = @options[:dynamic_task_name_param]
99
+ when Conductor::Workflow::TaskType::EVENT
100
+ wf_task.sink = @options[:sink]
101
+ when Conductor::Workflow::TaskType::INLINE
102
+ wf_task.expression = @options[:expression]
103
+ wf_task.evaluator_type = @options[:evaluator_type] || 'javascript'
104
+ when Conductor::Workflow::TaskType::JSON_JQ_TRANSFORM
105
+ wf_task.expression = @options[:query_expression]
106
+ wf_task.evaluator_type = 'graaljs' if @options[:query_expression]
107
+ end
108
+ end
109
+
110
+ def apply_switch_fields(wf_task)
111
+ wf_task.evaluator_type = 'value-param'
112
+ wf_task.expression = @options[:expression]
113
+
114
+ # Convert decision_cases from TaskRef arrays to WorkflowTask arrays
115
+ if @options[:decision_cases]
116
+ wf_task.decision_cases = @options[:decision_cases].transform_values do |task_refs|
117
+ task_refs.map { |tr| tr.is_a?(TaskRef) ? tr.to_workflow_task : tr }
118
+ end
119
+ end
120
+
121
+ # Convert default_case from TaskRef array to WorkflowTask array
122
+ return unless @options[:default_case] && !@options[:default_case].empty?
123
+
124
+ wf_task.default_case = @options[:default_case].map do |tr|
125
+ tr.is_a?(TaskRef) ? tr.to_workflow_task : tr
126
+ end
127
+ end
128
+
129
+ def apply_fork_join_fields(wf_task)
130
+ # Convert fork_branches from TaskRef arrays to WorkflowTask arrays
131
+ return unless @options[:fork_branches]
132
+
133
+ wf_task.fork_tasks = @options[:fork_branches].map do |branch|
134
+ branch.map { |tr| tr.is_a?(TaskRef) ? tr.to_workflow_task : tr }
135
+ end
136
+ end
137
+
138
+ def apply_join_fields(wf_task)
139
+ wf_task.join_on = @options[:join_on]
140
+ wf_task.expression = @options[:expression] if @options[:expression]
141
+ wf_task.evaluator_type = @options[:evaluator_type] if @options[:evaluator_type]
142
+ end
143
+
144
+ def apply_do_while_fields(wf_task)
145
+ wf_task.loop_condition = @options[:loop_condition]
146
+
147
+ # Convert loop_over from TaskRef array to WorkflowTask array
148
+ return unless @options[:loop_over]
149
+
150
+ wf_task.loop_over = @options[:loop_over].map do |tr|
151
+ tr.is_a?(TaskRef) ? tr.to_workflow_task : tr
152
+ end
153
+ end
154
+
155
+ def apply_sub_workflow_fields(wf_task)
156
+ # Handle inline workflow definition
157
+ if @options[:inline_workflow_def]
158
+ wf_task.sub_workflow_param = Conductor::Http::Models::SubWorkflowParams.new(
159
+ name: @options[:inline_workflow_def].name,
160
+ version: @options[:inline_workflow_def].version,
161
+ workflow_definition: @options[:inline_workflow_def]
162
+ )
163
+ elsif @options[:sub_workflow_name]
164
+ wf_task.sub_workflow_param = Conductor::Http::Models::SubWorkflowParams.new(
165
+ name: @options[:sub_workflow_name],
166
+ version: @options[:sub_workflow_version]
167
+ )
168
+ end
169
+ end
170
+
171
+ def apply_dynamic_fork_fields(wf_task)
172
+ wf_task.dynamic_fork_join_tasks_param = @options[:dynamic_fork_tasks_param]
173
+ wf_task.dynamic_fork_tasks_input_param_name = @options[:dynamic_fork_tasks_input_param]
174
+ end
175
+ end
176
+ end
177
+ end
178
+ end