circuit_breaker-wf 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.
- checksums.yaml +7 -0
- data/.gitignore +4 -0
- data/CHANGELOG.md +52 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +116 -0
- data/LICENSE +21 -0
- data/README.md +324 -0
- data/examples/document/README.md +150 -0
- data/examples/document/document_assistant.rb +535 -0
- data/examples/document/document_rules.rb +60 -0
- data/examples/document/document_token.rb +83 -0
- data/examples/document/document_workflow.rb +114 -0
- data/examples/document/mock_executor.rb +80 -0
- data/lib/circuit_breaker/executors/README.md +664 -0
- data/lib/circuit_breaker/executors/agent_executor.rb +187 -0
- data/lib/circuit_breaker/executors/assistant_executor.rb +245 -0
- data/lib/circuit_breaker/executors/base_executor.rb +56 -0
- data/lib/circuit_breaker/executors/docker_executor.rb +56 -0
- data/lib/circuit_breaker/executors/dsl.rb +97 -0
- data/lib/circuit_breaker/executors/llm/memory.rb +82 -0
- data/lib/circuit_breaker/executors/llm/tools.rb +94 -0
- data/lib/circuit_breaker/executors/nats_executor.rb +230 -0
- data/lib/circuit_breaker/executors/serverless_executor.rb +25 -0
- data/lib/circuit_breaker/executors/step_executor.rb +47 -0
- data/lib/circuit_breaker/history.rb +81 -0
- data/lib/circuit_breaker/rules.rb +251 -0
- data/lib/circuit_breaker/templates/mermaid.html.erb +51 -0
- data/lib/circuit_breaker/templates/plantuml.html.erb +55 -0
- data/lib/circuit_breaker/token.rb +486 -0
- data/lib/circuit_breaker/visualizer.rb +173 -0
- data/lib/circuit_breaker/workflow_dsl.rb +359 -0
- data/lib/circuit_breaker.rb +236 -0
- data/workflow-editor/.gitignore +24 -0
- data/workflow-editor/README.md +106 -0
- data/workflow-editor/eslint.config.js +28 -0
- data/workflow-editor/index.html +13 -0
- data/workflow-editor/package-lock.json +6864 -0
- data/workflow-editor/package.json +50 -0
- data/workflow-editor/postcss.config.js +6 -0
- data/workflow-editor/public/vite.svg +1 -0
- data/workflow-editor/src/App.css +42 -0
- data/workflow-editor/src/App.tsx +365 -0
- data/workflow-editor/src/assets/react.svg +1 -0
- data/workflow-editor/src/components/AddNodeButton.tsx +68 -0
- data/workflow-editor/src/components/EdgeDetails.tsx +175 -0
- data/workflow-editor/src/components/NodeDetails.tsx +177 -0
- data/workflow-editor/src/components/ResizablePanel.tsx +74 -0
- data/workflow-editor/src/components/SaveButton.tsx +45 -0
- data/workflow-editor/src/config/change_workflow.yaml +59 -0
- data/workflow-editor/src/config/constants.ts +11 -0
- data/workflow-editor/src/config/flowConfig.ts +189 -0
- data/workflow-editor/src/config/uiConfig.ts +77 -0
- data/workflow-editor/src/config/workflow.yaml +58 -0
- data/workflow-editor/src/hooks/useKeyPress.ts +29 -0
- data/workflow-editor/src/index.css +34 -0
- data/workflow-editor/src/main.tsx +10 -0
- data/workflow-editor/src/server/saveWorkflow.ts +81 -0
- data/workflow-editor/src/utils/saveWorkflow.ts +92 -0
- data/workflow-editor/src/utils/workflowLoader.ts +26 -0
- data/workflow-editor/src/utils/workflowTransformer.ts +91 -0
- data/workflow-editor/src/vite-env.d.ts +1 -0
- data/workflow-editor/src/yaml.d.ts +4 -0
- data/workflow-editor/tailwind.config.js +15 -0
- data/workflow-editor/tsconfig.app.json +26 -0
- data/workflow-editor/tsconfig.json +7 -0
- data/workflow-editor/tsconfig.node.json +24 -0
- data/workflow-editor/vite.config.ts +8 -0
- metadata +267 -0
@@ -0,0 +1,114 @@
|
|
1
|
+
require_relative '../../lib/circuit_breaker'
|
2
|
+
require_relative 'document_token'
|
3
|
+
require_relative 'document_rules'
|
4
|
+
require_relative 'mock_executor'
|
5
|
+
|
6
|
+
# Example of a document workflow using a more declarative DSL approach
|
7
|
+
module Examples
|
8
|
+
module Document
|
9
|
+
module Workflow
|
10
|
+
class DSL
|
11
|
+
def self.run
|
12
|
+
puts "Starting Document Workflow Example (DSL Version)..."
|
13
|
+
puts "================================================\n"
|
14
|
+
|
15
|
+
# Create a document token
|
16
|
+
token = DocumentToken.new
|
17
|
+
puts "Initial Document State:"
|
18
|
+
puts "======================"
|
19
|
+
puts "State: #{token.state}\n\n"
|
20
|
+
puts token.to_json(true)
|
21
|
+
|
22
|
+
puts "\nWorkflow Definition:"
|
23
|
+
puts "===================\n"
|
24
|
+
|
25
|
+
# Initialize document-specific rules and assistant
|
26
|
+
rules = Rules.define
|
27
|
+
mock = MockExecutor.new
|
28
|
+
|
29
|
+
workflow = CircuitBreaker::WorkflowBuilder::DSL.define(rules: rules) do
|
30
|
+
# Define all possible document states
|
31
|
+
# The first state listed becomes the initial state
|
32
|
+
states :draft, # Initial state when document is created
|
33
|
+
:pending_review, # Document submitted and awaiting review
|
34
|
+
:reviewed, # Document has been reviewed with comments
|
35
|
+
:approved, # Document has been approved by approver
|
36
|
+
:rejected # Document was rejected and needs revision
|
37
|
+
|
38
|
+
# Define transitions with required rules
|
39
|
+
flow :draft >> :pending_review, :submit do
|
40
|
+
actions do
|
41
|
+
execute mock, :analyze_document, :analysis
|
42
|
+
execute mock, :analyze_clarity, :clarity
|
43
|
+
execute mock, :analyze_completeness, :completeness
|
44
|
+
end
|
45
|
+
policy all: [:valid_word_count, :valid_clarity, :valid_completeness]
|
46
|
+
end
|
47
|
+
|
48
|
+
flow :pending_review >> :reviewed, :review do
|
49
|
+
actions do
|
50
|
+
execute mock, :review_document, :review
|
51
|
+
end
|
52
|
+
policy all: [:valid_review_metrics],
|
53
|
+
any: [:is_high_priority, :is_urgent]
|
54
|
+
end
|
55
|
+
|
56
|
+
flow :reviewed >> :approved, :approve do
|
57
|
+
actions do
|
58
|
+
execute mock, :final_review, :final
|
59
|
+
end
|
60
|
+
policy all: [:valid_approver, :approved_status]
|
61
|
+
end
|
62
|
+
|
63
|
+
flow :reviewed >> :rejected, :reject do
|
64
|
+
actions do
|
65
|
+
execute mock, :explain_rejection, :rejection
|
66
|
+
end
|
67
|
+
policy all: [:has_rejection_reasons]
|
68
|
+
end
|
69
|
+
|
70
|
+
# Simple transition without requirements
|
71
|
+
flow :rejected >> :draft, :revise
|
72
|
+
end
|
73
|
+
|
74
|
+
puts "\nWorkflow Definition:"
|
75
|
+
puts "==================="
|
76
|
+
workflow.pretty_print
|
77
|
+
|
78
|
+
puts "\nExecuting workflow steps...\n\n"
|
79
|
+
|
80
|
+
# Try each transition
|
81
|
+
begin
|
82
|
+
puts "\nTrying draft -> pending_review transition..."
|
83
|
+
token = workflow.transition!(token, :submit)
|
84
|
+
puts "Success! New state: #{token.state}"
|
85
|
+
|
86
|
+
puts "\nTrying pending_review -> reviewed transition..."
|
87
|
+
token = workflow.transition!(token, :review)
|
88
|
+
puts "Success! New state: #{token.state}"
|
89
|
+
|
90
|
+
puts "\nTrying reviewed -> approved transition..."
|
91
|
+
token = workflow.transition!(token, :approve)
|
92
|
+
puts "Success! New state: #{token.state}"
|
93
|
+
rescue => e
|
94
|
+
puts "Error: #{e.message}"
|
95
|
+
end
|
96
|
+
|
97
|
+
puts "\nFinal Document State:"
|
98
|
+
puts "===================="
|
99
|
+
puts "State: #{token.state}\n\n"
|
100
|
+
puts token.to_json(true)
|
101
|
+
|
102
|
+
puts "\nDocument History:"
|
103
|
+
puts "----------------"
|
104
|
+
token.history.each do |event|
|
105
|
+
puts "#{event[:timestamp]}: #{event[:transition]} from #{event[:from]} to #{event[:to]}"
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
# Run the example
|
113
|
+
Examples::Document::Workflow::DSL.run if __FILE__ == $0
|
114
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module Examples
|
2
|
+
class MockExecutor
|
3
|
+
def initialize(model = nil)
|
4
|
+
@model = model
|
5
|
+
end
|
6
|
+
|
7
|
+
def analyze_document(token)
|
8
|
+
text = token.content.to_s
|
9
|
+
{
|
10
|
+
word_count: text.split.size,
|
11
|
+
char_count: text.size,
|
12
|
+
avg_word_length: text.empty? ? 0 : (text.size.to_f / text.split.size).round(2)
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
def analyze_clarity(token)
|
17
|
+
text = token.content.to_s
|
18
|
+
words = text.split
|
19
|
+
return { score: 100, long_words: 0, suggestion: "Good clarity" } if words.empty?
|
20
|
+
|
21
|
+
long_words = words.count { |word| word.length > 8 }
|
22
|
+
{
|
23
|
+
score: ((1 - (long_words.to_f / words.size)) * 100).round(2),
|
24
|
+
long_words: long_words,
|
25
|
+
suggestion: long_words > 3 ? "Consider using simpler words" : "Good clarity"
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
def analyze_completeness(token)
|
30
|
+
text = token.content.to_s
|
31
|
+
required_sections = ["introduction", "background", "conclusion"]
|
32
|
+
found_sections = required_sections.select { |section| text.downcase.include?(section) }
|
33
|
+
{
|
34
|
+
score: ((found_sections.size.to_f / required_sections.size) * 100).round(2),
|
35
|
+
missing_sections: required_sections - found_sections,
|
36
|
+
complete: found_sections.size == required_sections.size
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
def review_document(token)
|
41
|
+
analysis = analyze_document(token)
|
42
|
+
clarity = analyze_clarity(token)
|
43
|
+
completeness = analyze_completeness(token)
|
44
|
+
|
45
|
+
{
|
46
|
+
approved: analysis[:word_count] > 50 && clarity[:score] > 70 && completeness[:score] > 80,
|
47
|
+
metrics: {
|
48
|
+
word_count: analysis[:word_count],
|
49
|
+
clarity_score: clarity[:score],
|
50
|
+
completeness_score: completeness[:score]
|
51
|
+
},
|
52
|
+
feedback: [
|
53
|
+
clarity[:suggestion],
|
54
|
+
completeness[:complete] ? "All sections present" : "Missing sections: #{completeness[:missing_sections].join(', ')}"
|
55
|
+
],
|
56
|
+
comments: []
|
57
|
+
}
|
58
|
+
end
|
59
|
+
|
60
|
+
def final_review(token)
|
61
|
+
review = review_document(token)
|
62
|
+
{
|
63
|
+
status: review[:approved] ? "APPROVED" : "REJECTED",
|
64
|
+
metrics: review[:metrics],
|
65
|
+
comments: review[:comments]
|
66
|
+
}
|
67
|
+
end
|
68
|
+
|
69
|
+
def explain_rejection(token)
|
70
|
+
review = review_document(token)
|
71
|
+
reasons = []
|
72
|
+
reasons << "Word count too low" if review[:metrics][:word_count] <= 50
|
73
|
+
reasons << "Clarity score too low" if review[:metrics][:clarity_score] <= 70
|
74
|
+
reasons << "Completeness score too low" if review[:metrics][:completeness_score] <= 80
|
75
|
+
{
|
76
|
+
reasons: reasons
|
77
|
+
}
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|