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.
Files changed (68) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +4 -0
  3. data/CHANGELOG.md +52 -0
  4. data/Gemfile +10 -0
  5. data/Gemfile.lock +116 -0
  6. data/LICENSE +21 -0
  7. data/README.md +324 -0
  8. data/examples/document/README.md +150 -0
  9. data/examples/document/document_assistant.rb +535 -0
  10. data/examples/document/document_rules.rb +60 -0
  11. data/examples/document/document_token.rb +83 -0
  12. data/examples/document/document_workflow.rb +114 -0
  13. data/examples/document/mock_executor.rb +80 -0
  14. data/lib/circuit_breaker/executors/README.md +664 -0
  15. data/lib/circuit_breaker/executors/agent_executor.rb +187 -0
  16. data/lib/circuit_breaker/executors/assistant_executor.rb +245 -0
  17. data/lib/circuit_breaker/executors/base_executor.rb +56 -0
  18. data/lib/circuit_breaker/executors/docker_executor.rb +56 -0
  19. data/lib/circuit_breaker/executors/dsl.rb +97 -0
  20. data/lib/circuit_breaker/executors/llm/memory.rb +82 -0
  21. data/lib/circuit_breaker/executors/llm/tools.rb +94 -0
  22. data/lib/circuit_breaker/executors/nats_executor.rb +230 -0
  23. data/lib/circuit_breaker/executors/serverless_executor.rb +25 -0
  24. data/lib/circuit_breaker/executors/step_executor.rb +47 -0
  25. data/lib/circuit_breaker/history.rb +81 -0
  26. data/lib/circuit_breaker/rules.rb +251 -0
  27. data/lib/circuit_breaker/templates/mermaid.html.erb +51 -0
  28. data/lib/circuit_breaker/templates/plantuml.html.erb +55 -0
  29. data/lib/circuit_breaker/token.rb +486 -0
  30. data/lib/circuit_breaker/visualizer.rb +173 -0
  31. data/lib/circuit_breaker/workflow_dsl.rb +359 -0
  32. data/lib/circuit_breaker.rb +236 -0
  33. data/workflow-editor/.gitignore +24 -0
  34. data/workflow-editor/README.md +106 -0
  35. data/workflow-editor/eslint.config.js +28 -0
  36. data/workflow-editor/index.html +13 -0
  37. data/workflow-editor/package-lock.json +6864 -0
  38. data/workflow-editor/package.json +50 -0
  39. data/workflow-editor/postcss.config.js +6 -0
  40. data/workflow-editor/public/vite.svg +1 -0
  41. data/workflow-editor/src/App.css +42 -0
  42. data/workflow-editor/src/App.tsx +365 -0
  43. data/workflow-editor/src/assets/react.svg +1 -0
  44. data/workflow-editor/src/components/AddNodeButton.tsx +68 -0
  45. data/workflow-editor/src/components/EdgeDetails.tsx +175 -0
  46. data/workflow-editor/src/components/NodeDetails.tsx +177 -0
  47. data/workflow-editor/src/components/ResizablePanel.tsx +74 -0
  48. data/workflow-editor/src/components/SaveButton.tsx +45 -0
  49. data/workflow-editor/src/config/change_workflow.yaml +59 -0
  50. data/workflow-editor/src/config/constants.ts +11 -0
  51. data/workflow-editor/src/config/flowConfig.ts +189 -0
  52. data/workflow-editor/src/config/uiConfig.ts +77 -0
  53. data/workflow-editor/src/config/workflow.yaml +58 -0
  54. data/workflow-editor/src/hooks/useKeyPress.ts +29 -0
  55. data/workflow-editor/src/index.css +34 -0
  56. data/workflow-editor/src/main.tsx +10 -0
  57. data/workflow-editor/src/server/saveWorkflow.ts +81 -0
  58. data/workflow-editor/src/utils/saveWorkflow.ts +92 -0
  59. data/workflow-editor/src/utils/workflowLoader.ts +26 -0
  60. data/workflow-editor/src/utils/workflowTransformer.ts +91 -0
  61. data/workflow-editor/src/vite-env.d.ts +1 -0
  62. data/workflow-editor/src/yaml.d.ts +4 -0
  63. data/workflow-editor/tailwind.config.js +15 -0
  64. data/workflow-editor/tsconfig.app.json +26 -0
  65. data/workflow-editor/tsconfig.json +7 -0
  66. data/workflow-editor/tsconfig.node.json +24 -0
  67. data/workflow-editor/vite.config.ts +8 -0
  68. 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