cpee-llm 1.1.0 → 1.2.2

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 (65) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +668 -159
  3. data/cpee-llm.gemspec +3 -3
  4. data/lib/cpee/llm/dataflow.rb +3 -3
  5. data/lib/cpee/llm/functions.rb +16 -16
  6. data/lib/cpee/llm/implementation.rb +4 -4
  7. data/lib/cpee/llm/implementation.xml +7 -6
  8. data/lib/cpee/llm/prompts/system/adapt_mermaid.txt +12 -0
  9. data/lib/cpee/llm/prompts/system/{adapt_docxml_description.txt → adapt_xml_documentation.txt} +11 -11
  10. data/lib/cpee/llm/prompts/system/adapt_xml_endpoints.txt +10 -12
  11. data/lib/cpee/llm/prompts/system/dataflow.txt +13 -25
  12. data/lib/cpee/llm/prompts/system/fragments/cpee_xml/arguments.txt +8 -0
  13. data/lib/cpee/llm/prompts/system/fragments/cpee_xml/color_palette.txt +10 -0
  14. data/lib/cpee/llm/prompts/system/fragments/cpee_xml/description.txt +3 -0
  15. data/lib/cpee/llm/prompts/system/{cpee_xml_documentation_modelling.txt → fragments/cpee_xml/documentation.txt} +1 -1
  16. data/lib/cpee/llm/prompts/system/fragments/cpee_xml/exclusive_gateway.txt +7 -0
  17. data/lib/cpee/llm/prompts/system/fragments/cpee_xml/finalize.txt +2 -0
  18. data/lib/cpee/llm/prompts/system/fragments/cpee_xml/inclusive_gateway.txt +2 -0
  19. data/lib/cpee/llm/prompts/system/fragments/cpee_xml/loop.txt +7 -0
  20. data/lib/cpee/llm/prompts/system/fragments/cpee_xml/method.txt +6 -0
  21. data/lib/cpee/llm/prompts/system/fragments/cpee_xml/parallel_gateway.txt +6 -0
  22. data/lib/cpee/llm/prompts/system/fragments/cpee_xml/pause.txt +4 -0
  23. data/lib/cpee/llm/prompts/system/fragments/cpee_xml/pause_insertion.txt +3 -0
  24. data/lib/cpee/llm/prompts/system/fragments/cpee_xml/script_task.txt +5 -0
  25. data/lib/cpee/llm/prompts/system/fragments/cpee_xml/sequence.txt +2 -0
  26. data/lib/cpee/llm/prompts/system/fragments/cpee_xml/service_task.txt +20 -0
  27. data/lib/cpee/llm/prompts/system/fragments/cpee_xml/variables.txt +3 -0
  28. data/lib/cpee/llm/prompts/system/fragments/cpee_xml.txt +15 -0
  29. data/lib/cpee/llm/prompts/system/fragments/data_references.txt +14 -0
  30. data/lib/cpee/llm/prompts/system/fragments/endpoint_naming.txt +1 -0
  31. data/lib/cpee/llm/prompts/system/fragments/mermaid/structure_rules.txt +29 -0
  32. data/lib/cpee/llm/prompts/system/fragments/mermaid/syntax.txt +22 -0
  33. data/lib/cpee/llm/prompts/system/fragments/numeric_conversion.txt +5 -0
  34. data/lib/cpee/llm/prompts/system/fragments/service_registry.txt +6 -0
  35. data/lib/cpee/llm/prompts/system/fragments/unmatched_tasks.txt +4 -0
  36. data/lib/cpee/llm/prompts/system/generate_mermaid.txt +40 -0
  37. data/lib/cpee/llm/prompts/system/generate_mermaid_endpoints.txt +82 -0
  38. data/lib/cpee/llm/prompts/system/intent.txt +3 -3
  39. data/lib/cpee/llm/prompts/system/validate_xml.txt +15 -0
  40. data/lib/cpee/llm/prompts/user/describe_text.txt +4 -0
  41. data/lib/cpee/llm/prompts/user/intent.txt +3 -3
  42. data/lib/cpee/llm/prompts/user/validate_xml.txt +5 -0
  43. data/lib/cpee/llm/rubyllm_requests.rb +13 -9
  44. data/server/{cpee-llm → llm} +4 -3
  45. data/tools/cpee-llm +3 -3
  46. data/tools/cpee-llm-tool +3 -3
  47. metadata +39 -23
  48. data/lib/cpee/llm/prompts/system/apply.txt +0 -32
  49. data/lib/cpee/llm/prompts/system/cpee_xml.txt +0 -99
  50. data/lib/cpee/llm/prompts/system/derive.txt +0 -28
  51. data/lib/cpee/llm/prompts/system/gemini-request.json +0 -18
  52. data/lib/cpee/llm/prompts/system/generate1.txt +0 -90
  53. data/lib/cpee/llm/prompts/system/generate_enpoints.txt +0 -132
  54. data/lib/cpee/llm/prompts/system/generate_enpoints1.txt +0 -155
  55. data/lib/cpee/llm/prompts/system/identify.txt +0 -25
  56. data/lib/cpee/llm/prompts/system/validate_mermaid.xml +0 -74
  57. data/lib/cpee/llm/prompts/user/cpee_repair.txt +0 -5
  58. data/lib/cpee/llm/prompts/user/process_model_text.txt +0 -4
  59. data/lib/cpee/llm/prompts/user/repair.txt +0 -5
  60. /data/lib/cpee/llm/prompts/system/{describe.txt → describe_text.txt} +0 -0
  61. /data/lib/cpee/llm/prompts/user/{process_model_adapt.txt → adapt.txt} +0 -0
  62. /data/lib/cpee/llm/prompts/user/{process_model_adapt_api.txt → adapt_xml_endpoints.txt} +0 -0
  63. /data/lib/cpee/llm/prompts/user/{process_description.txt → generate_mermaid.txt} +0 -0
  64. /data/lib/cpee/llm/prompts/user/{process_description_endpoints.txt → generate_mermaid_endpoints.txt} +0 -0
  65. /data/server/{cpee-llm.conf → llm.conf} +0 -0
data/cpee-llm.gemspec CHANGED
@@ -1,13 +1,13 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "cpee-llm"
3
- s.version = "1.1.0"
3
+ s.version = "1.2.2"
4
4
  s.platform = Gem::Platform::RUBY
5
- s.license = "LGPL-3.0-or-later"
5
+ s.license = "GPL-3.0-or-later"
6
6
  s.summary = "CPEE Conversational Agents"
7
7
 
8
8
  s.description = "see http://cpee.org"
9
9
 
10
- s.files = Dir['{server/*,tools/**/*,lib/**/*}'] + %w(LICENSE Rakefile cpee-llm.gemspec README.md AUTHORS)
10
+ s.files = Dir['{server/*,tools/**/*,lib/**/*}'] - Dir['lib/cpee/llm/prompts/legacy{,/**/*}'] + %w(LICENSE Rakefile cpee-llm.gemspec README.md AUTHORS)
11
11
  s.require_path = 'lib'
12
12
  s.extra_rdoc_files = ['README.md']
13
13
  s.bindir = 'tools'
@@ -1,16 +1,16 @@
1
1
  # This file is part of CPEE-LLM.
2
2
  #
3
3
  # CPEE-LLM is free software: you can redistribute it and/or modify it under the
4
- # terms of the GNU Lesser General Public License as published by the Free
4
+ # terms of the GNU General Public License as published by the Free
5
5
  # Software Foundation, either version 3 of the License, or (at your option) any
6
6
  # later version.
7
7
  #
8
8
  # CPEE-LLM is distributed in the hope that it will be useful, but WITHOUT ANY
9
9
  # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
10
- # A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
10
+ # A PARTICULAR PURPOSE. See the GNU General Public License for more
11
11
  # details.
12
12
  #
13
- # You should have received a copy of the GNU Lesser General Public License
13
+ # You should have received a copy of the GNU General Public License
14
14
  # along with CPEE-LLM (file LICENSE in the main directory). If not, see
15
15
  # <http://www.gnu.org/licenses/>.
16
16
 
@@ -1,16 +1,16 @@
1
1
  # This file is part of CPEE-LLM.
2
2
  #
3
3
  # CPEE-LLM is free software: you can redistribute it and/or modify it under the
4
- # terms of the GNU Lesser General Public License as published by the Free
4
+ # terms of the GNU General Public License as published by the Free
5
5
  # Software Foundation, either version 3 of the License, or (at your option) any
6
6
  # later version.
7
7
  #
8
8
  # CPEE-LLM is distributed in the hope that it will be useful, but WITHOUT ANY
9
9
  # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
10
- # A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
10
+ # A PARTICULAR PURPOSE. See the GNU General Public License for more
11
11
  # details.
12
12
  #
13
- # You should have received a copy of the GNU Lesser General Public License
13
+ # You should have received a copy of the GNU General Public License
14
14
  # along with CPEE-LLM (file LICENSE in the main directory). If not, see
15
15
  # <http://www.gnu.org/licenses/>.
16
16
 
@@ -59,8 +59,8 @@ module CPEE
59
59
 
60
60
  def generate_model(myllm,user_input,temperature,llms) #{{{
61
61
  error_handler do
62
- system_prompt = build_system_prompt("generate1.txt")
63
- user_prompt = build_user_prompt("process_description.txt", user_input:)
62
+ system_prompt = build_system_prompt("generate_mermaid.txt")
63
+ user_prompt = build_user_prompt("generate_mermaid.txt", user_input:)
64
64
  llm_response = generate_content(myllm,system_prompt,user_prompt,4000,temperature,llms)
65
65
  # raise exceptions if response is empty for some reason
66
66
  if llm_response.nil? || llm_response.empty?
@@ -75,8 +75,8 @@ module CPEE
75
75
  input_cpee = doc.to_s()
76
76
  input_mermaid = cpee_to_mermaid(doc.to_s())
77
77
  error_handler do
78
- system_prompt = build_system_prompt("apply.txt")
79
- user_prompt = build_user_prompt("process_model_adapt.txt", user_input:, process_model: input_mermaid)
78
+ system_prompt = build_system_prompt("adapt_mermaid.txt")
79
+ user_prompt = build_user_prompt("adapt.txt", user_input:, process_model: input_mermaid)
80
80
  llm_response = generate_content(myllm,system_prompt,user_prompt,4000,0,llms)
81
81
  # raise exceptions if response is empty for some reason
82
82
  if llm_response.nil? || llm_response.empty?
@@ -90,8 +90,8 @@ module CPEE
90
90
  def adapt_doccpee_description(myllm,doc,user_input,llms) #{{{
91
91
  input_cpee = doc.to_s()
92
92
  error_handler do
93
- system_prompt = build_system_prompt("adapt_docxml_description.txt")
94
- user_prompt = build_user_prompt("process_model_adapt.txt", user_input:, process_model: input_cpee)
93
+ system_prompt = build_system_prompt("adapt_xml_documentation.txt")
94
+ user_prompt = build_user_prompt("adapt.txt", user_input:, process_model: input_cpee)
95
95
  llm_response = generate_content(myllm,system_prompt,user_prompt,16000,0,llms)
96
96
  # raise exceptions if response is empty for some reason
97
97
  if llm_response.nil? || llm_response.empty?
@@ -120,7 +120,7 @@ module CPEE
120
120
 
121
121
  error_handler do
122
122
  system_prompt = build_system_prompt("adapt_xml_endpoints.txt")
123
- user_prompt = build_user_prompt("process_model_adapt_api.txt", user_input:, process_model: testset, api_specification: endpoints)
123
+ user_prompt = build_user_prompt("adapt_xml_endpoints.txt", user_input:, process_model: testset, api_specification: endpoints)
124
124
  llm_response = generate_content(myllm,system_prompt,user_prompt,15000,0,llms)
125
125
  # raise exceptions if response is empty for some reason
126
126
  if llm_response.nil? || llm_response.empty?
@@ -144,8 +144,8 @@ module CPEE
144
144
  input_cpee = doc.to_s()
145
145
  input_mermaid = cpee_to_mermaid(doc.to_s())
146
146
  error_handler do
147
- system_prompt = build_system_prompt("describe.txt")
148
- user_prompt = build_user_prompt("process_model_text.txt", user_input: input_mermaid)
147
+ system_prompt = build_system_prompt("describe_text.txt")
148
+ user_prompt = build_user_prompt("describe_text.txt", user_input: input_mermaid)
149
149
  llm_response = generate_content(myllm,system_prompt,user_prompt,4000,0,llms)
150
150
  # raise exceptions if response is empty for some reason
151
151
  if llm_response.nil? || llm_response.empty?
@@ -195,8 +195,8 @@ module CPEE
195
195
 
196
196
  def generate_endpoint_model(myllm,user_input,endpoints,llms) #{{{
197
197
  error_handler do
198
- system_prompt = build_system_prompt("generate_enpoints.txt")
199
- user_prompt = build_user_prompt("process_description_endpoints.txt", user_input:, endpoints:)
198
+ system_prompt = build_system_prompt("generate_mermaid_endpoints.txt")
199
+ user_prompt = build_user_prompt("generate_mermaid_endpoints.txt", user_input:, endpoints:)
200
200
  llm_response = generate_content(myllm,system_prompt,user_prompt,4000,0.1,llms)
201
201
  # raise exceptions if response is empty for some reason
202
202
  if llm_response.nil? || llm_response.empty?
@@ -210,7 +210,7 @@ module CPEE
210
210
  def validate_cpee_model(myllm,cpee_model,llms) #{{{
211
211
  error_handler do
212
212
  system_prompt = build_system_prompt("validate_xml.txt")
213
- user_prompt = build_user_prompt("cpee_repair.txt", cpee_model:)
213
+ user_prompt = build_user_prompt("validate_xml.txt", cpee_model:)
214
214
  llm_response = generate_content(myllm,system_prompt,user_prompt,0,0.1,llms)
215
215
  if llm_response.nil? || llm_response.empty?
216
216
  raise LLMError.new("Something went wrong and your content was not generated!", 500)
@@ -224,7 +224,7 @@ module CPEE
224
224
  begin
225
225
  XML::Smart.string(llm_response)
226
226
  rescue Nokogiri::XML::SyntaxError => e
227
- raise LLMError.new("Something went wrong and llm was not able to generate valid xml model", llm_response)
227
+ raise LLMError.new("Something went wrong and llm was not able to generate valid xml model", 500)
228
228
  end
229
229
  return llm_response
230
230
  end
@@ -1,16 +1,16 @@
1
1
  # This file is part of CPEE-LLM.
2
2
  #
3
3
  # CPEE-LLM is free software: you can redistribute it and/or modify it under the
4
- # terms of the GNU Lesser General Public License as published by the Free
4
+ # terms of the GNU General Public License as published by the Free
5
5
  # Software Foundation, either version 3 of the License, or (at your option) any
6
6
  # later version.
7
7
  #
8
8
  # CPEE-LLM is distributed in the hope that it will be useful, but WITHOUT ANY
9
9
  # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
10
- # A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
10
+ # A PARTICULAR PURPOSE. See the GNU General Public License for more
11
11
  # details.
12
12
  #
13
- # You should have received a copy of the GNU Lesser General Public License
13
+ # You should have received a copy of the GNU General Public License
14
14
  # along with CPEE-LLM (file LICENSE in the main directory). If not, see
15
15
  # <http://www.gnu.org/licenses/>.
16
16
 
@@ -199,7 +199,7 @@ module CPEE
199
199
  llm_response = validate_cpee_model(myllm,input_cpee,llms)
200
200
  rescue LLMError => e
201
201
  @status = e.http_response
202
- return Riddl::Parameter::Complex.new("generic_out","application/json",{:error => e.message}.to_json())
202
+ return Riddl::Parameter::Complex.new("llm_out","application/json",{:error => e.message}.to_json())
203
203
  end
204
204
 
205
205
  return(Riddl::Parameter::Complex.new("llm_out","application/json",{:used_llm => myllm, :output_cpee => llm_response, :status => "Success"}.to_json()))
@@ -2,16 +2,17 @@
2
2
  This file is part of CPEE-LLM.
3
3
 
4
4
  CPEE-LLM is free software: you can redistribute it and/or modify it under the
5
- terms of the GNU General Public License as published by the Free Software
6
- Foundation, either version 3 of the License, or (at your option) any later
7
- version.
5
+ terms of the GNU General Public License as published by the Free
6
+ Software Foundation, either version 3 of the License, or (at your option) any
7
+ later version.
8
8
 
9
9
  CPEE-LLM is distributed in the hope that it will be useful, but WITHOUT ANY
10
10
  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11
- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
11
+ A PARTICULAR PURPOSE. See the GNU General Public License for more
12
+ details.
12
13
 
13
- You should have received a copy of the GNU General Public License along with
14
- CPEE-LLM (file LICENSE in the main directory). If not, see
14
+ You should have received a copy of the GNU General Public License
15
+ along with CPEE-LLM (file LICENSE in the main directory). If not, see
15
16
  <http://www.gnu.org/licenses/>.
16
17
  -->
17
18
 
@@ -0,0 +1,12 @@
1
+ You are an expert in BPMN modeling, specifically in Mermaid.js format.
2
+ Your task is to validate and transform BPMN models based on user-provided modifications, ensuring compliance with BPMN rules and Mermaid.js syntax.
3
+ You are allowed to adjust only those parts of the process model mentioned in the user-provided modification. Other parts of the model have to stay unchanged.
4
+
5
+ %%%fragments/mermaid/syntax.txt
6
+
7
+ The provided process model may contain nodes whose ids are not integers (e.g., a1, g0s) and nodes of type script (e.g., a3:script:(Compute Total)). Keep these ids and types unchanged. Only new nodes get new unique integer ids.
8
+
9
+ All gateways must have both a split and a merge point.
10
+ Each gateway that initiates a split must be properly closed by a merge gateway of the same type (e.g., an exclusive gateway must be merged by another exclusive gateway).
11
+
12
+ Return only mermaid.js as text without any additional information! Give me just the raw Mermaid.js code without markdown formatting.
@@ -14,17 +14,17 @@ Never introduce additional behavior that was not requested.
14
14
  Editing Workflow
15
15
  Internally perform the following steps:
16
16
  1. Parse the existing CPEE XML description.
17
- 3. Parse the workflow contained in the description element.
18
- 4. Understand the user's requested modifications.
19
- 5. Determine which workflow elements are affected.
20
- 6. Apply only the requested changes.
21
- 7. Update documentation flow if necessary.
22
- 8. Generate the complete updated CPEE XML description.
17
+ 2. Parse the workflow contained in the description element.
18
+ 3. Understand the user's requested modifications.
19
+ 4. Determine which workflow elements are affected.
20
+ 5. Apply only the requested changes.
21
+ 6. Update documentation flow if necessary.
22
+ 7. Generate the complete updated CPEE XML description.
23
23
 
24
- %%%cpee_xml.txt
25
- %%%cpee_xml_documentation_modelling.txt
24
+ %%%fragments/cpee_xml.txt
25
+ %%%fragments/cpee_xml/documentation.txt
26
26
 
27
- For the purpose of modelling, arguments can be ignored and dont have to cary anny values. Code also can be left empty.
27
+ For the purpose of modelling, arguments can be ignored and don't have to carry any values. Code also can be left empty. If an argument is given a value that refers to process data, it must use the !data.some_value syntax described above.
28
28
 
29
29
  # Handling Ambiguity
30
30
  If the user's request is sufficiently precise, perform the modification directly.
@@ -34,8 +34,8 @@ If multiple valid interpretations exist and the missing information affects the
34
34
  If user deletes a single task in a branch, remove task but leave the branch. Use default branch.
35
35
  eid attributes are IDs. All eid attributes have to be unique for the whole XML and start with an e followed by a number, e.g., "e1".
36
36
  id attributes are IDs. All id attributes have to be unique for the whole XML and start with an a followed by a number, e.g., "a1".
37
- Don't change ANY existing id's or eid's. Only genereate new unique id's or eid's for new nodes which have id's or eid's.
38
- Don't change existing nodes, even when you move them. For example dont add documentation if it is not there.
37
+ Don't change ANY existing id's or eid's. Only generate new unique id's or eid's for new nodes which have id's or eid's.
38
+ Don't change existing nodes, even when you move them. For example don't add documentation if it is not there.
39
39
 
40
40
  # Output Requirements
41
41
  Return the complete updated CPEE XML process model.
@@ -5,12 +5,8 @@ The user will always provide:
5
5
  * one or more textual modification requests;
6
6
  * a list of available API endpoints (service registry).
7
7
 
8
- Service Registry maps each task label to one service specification. Each service specification includes:
9
- - service url
10
- - service description
11
- - service functionality
12
- - input (RelaxNG schema)
13
- - optional output
8
+ %%%fragments/service_registry.txt
9
+ The service registry is keyed by service url. Each value lists description, functionality, input and output in this order.
14
10
 
15
11
  Core Objective
16
12
  Your task is to produce a modified CPEE XML process model that implements the requested changes.
@@ -47,24 +43,26 @@ Endpoint Rules:
47
43
  - URLs are stored only in <endpoints>.
48
44
  - Update URLs in <endpoints>; update endpoint attributes only when the endpoint name changes.
49
45
  - Do not modify unrelated endpoints.
46
+ %%%fragments/endpoint_naming.txt
50
47
 
51
48
  # Service Registry Usage for Newly Added Tasks
52
49
  When the user's modification request introduces one or more new tasks, first determine whether the task exists in the Service Registry.
53
50
  If the task exists in the Service Registry:
54
51
  - Create a <call> element using the corresponding service specification.
55
- - Set the endpoint attribute to the endpoint defined for the service.
56
- - If the endpoint is not already present in the <endpoints> section, add it using the URL from the Service Registry.
52
+ - Set the endpoint attribute to the endpoint name derived from the task label (see Endpoint Rules).
53
+ - If the endpoint is not already present in the <endpoints> section, add it using the service url from the Service Registry.
57
54
  - Define the task according to the service specification.
58
55
  - Define the <arguments> section with the required input parameters, assigning values from the existing process context whenever possible.
59
56
  - If the service specification defines outputs, generate the appropriate <finalize> code to store the returned values in workflow variables (data.*) for later use.
60
57
  - Integrate the task into the existing workflow without modifying unrelated behavior.
61
58
  If the task does not exist in the Service Registry:
62
- - Create an empty <call> element as a placeholder.
63
- - Do not invent an endpoint, service URL, input parameters, output mappings, or implementation details.
64
- - Leave the task unconfigured except for information explicitly requested by the user.
59
+ %%%fragments/unmatched_tasks.txt
60
+ - A script task is a <manipulate> element (see Script Task below).
61
+ - An unconfigured service task is an empty <call> element without endpoint, used as a placeholder. Leave it unconfigured except for information explicitly requested by the user.
65
62
  Always use the Service Registry whenever a matching service specification is available.
66
63
 
67
- %%%cpee_xml.txt
64
+ The CPEE XML model must follow these rules:
65
+ %%%fragments/cpee_xml.txt
68
66
 
69
67
  # Handling Ambiguity
70
68
  If the user's request is sufficiently precise, perform the modification directly.
@@ -9,15 +9,8 @@ INPUT DESCRIPTION
9
9
  - gateways
10
10
  Tasks define process steps.
11
11
  Gateways define branching logic based on data produced by tasks.
12
- 2. Service Registry maps each task label to one service specification.
13
- Each service specification includes:
14
- - task id
15
- - task label
16
- - service url
17
- - service description
18
- - service functionality
19
- - input (RelaxNG schema)
20
- - optional output
12
+ 2. Service Registry is keyed by the task id from the process model. Each entry contains the task label from the process model (label) and the matching service.
13
+ %%%fragments/service_registry.txt
21
14
 
22
15
  OUTPUT FORMAT
23
16
  Return a JSON object with exactly two top-level fields:
@@ -32,11 +25,10 @@ For each task in the process model include:
32
25
  - label: original task label from the process model
33
26
 
34
27
  Based on the task types additional information is provided:
35
- (a) Script tasks if no matching service exist, but the step is purely data transformation or computation and no external system interaction is implied
28
+ (a) Script tasks
29
+ %%%fragments/unmatched_tasks.txt
36
30
  - url: is always "script"
37
31
  - script: <ruby code>
38
- The script must be generated in simple Ruby. Example: assign from another variable: data.total = data.amount + data.tax
39
- Script tasks participate in process data flow exactly like service tasks and may create or update data.* variables used by downstream tasks and gateways.
40
32
  (b) Service tasks if a matching service exists in the registry:
41
33
  - url: service endpoint
42
34
  - input: required parameters with concrete values if derivable from process logic
@@ -44,12 +36,13 @@ Based on the task types additional information is provided:
44
36
 
45
37
  INPUT RULES
46
38
  Each input value MUST follow exactly one of the following formats:
47
- 1. Literal value (no change)
39
+ 1. Literal value (no change, no leading !)
48
40
  If the value is constant:
49
41
  "intensity": 90
50
- 2. Value from previous task output
51
- If the value comes from another task’s output:
52
- "sample_id": "data.sample_id"
42
+ 2. Value from previous task output or script
43
+ If the value comes from another task’s output or from a script:
44
+ "sample_id": "!data.sample_id"
45
+ %%%fragments/data_references.txt
53
46
 
54
47
  OUTPUT RULES
55
48
  Include output only if required. Otherwise omit it.
@@ -67,16 +60,11 @@ Value sources
67
60
  (b) Nested field access is used when the required value is located inside a specific key within result.
68
61
  "data.ambient_light_lumens": "result['some_key']"
69
62
  Required conversions
70
- All output values are STRING by default.
71
- If the operation description specifies a numeric type or the semantic meaning implies a numeric type, a conversion MUST be applied.
72
- Type rules:
73
- - If the value is defined as or implied to be a float ALWAYS use .to_f
74
- - If the value is defined as or implied to be an integer ALWAYS use .to_i
63
+ %%%fragments/numeric_conversion.txt
75
64
  Examples:
76
65
  "data.ambient_light_lux": "result.to_f"
77
66
  "data.temperature": "result['value'].to_f"
78
67
  "data.count": "result.to_i"
79
- Do NOT omit a conversion!!!
80
68
 
81
69
  Tasks that are not script or service tasks are ignored!!!
82
70
 
@@ -143,11 +131,11 @@ OUTPUT STRUCTURE EXAMPLE (SCHEMA ONLY)
143
131
  "url": "...",
144
132
  "input": {
145
133
  "param1": "value",
146
- "param2": "data.some_output"
134
+ "param2": "!data.some_output"
147
135
  },
148
136
  "output": {
149
- "data.some_output": "result['dome_key']",
150
- "data.some_output": "result.to_i"
137
+ "data.some_output": "result['some_key']",
138
+ "data.other_output": "result.to_i"
151
139
  }
152
140
  },
153
141
  "task_id": {
@@ -0,0 +1,8 @@
1
+ Service input parameters are stored inside arguments (which in turn are always stored inside parameters, see structure above). Each argument is represented by its own child element.
2
+ <parameters>
3
+ <arguments>
4
+ <min>1</min>
5
+ <max>100</max>
6
+ </arguments>
7
+ </parameters>
8
+ %%%fragments/data_references.txt
@@ -0,0 +1,10 @@
1
+ Use only the following color palette:
2
+ * White — #ffffff
3
+ * Blue — #d4e1f1
4
+ * Green — #d8f0dd
5
+ * Yellow — #ffffcc
6
+ * Purple — #e4c3e4
7
+ * Pink — #f8a8c6
8
+ * Brown — #ded0c5
9
+ * Gray — #deddda
10
+ The same color palette also applies to the color attribute of <description> and to the color attribute of <manipulate>.
@@ -0,0 +1,3 @@
1
+ # CPEE XML Process Model Structure
2
+ The process model itself is contained entirely inside the <description color=""> element. Interpret the XML inside <description> using the following mapping.
3
+ The color attribute controls the color of the whole process model. Individual service task colors can be set (see below).
@@ -14,7 +14,7 @@ The documentation element may describe the service implementation as well as its
14
14
  The <description> elements contain optional textual information about the task's behavior, including the process variables consumed (<in>), produced (<out>), or implementation-specific details (<implementation>).
15
15
  Empty <description> elements indicate that no additional semantic information is provided.
16
16
 
17
- If a `<documentation>` element does not exist for a Service Task, append an empty `<documentation>` element. Empty `<documentation>` conmtains only <in> and <implementation>. Include <out> only in tasks, where output is defined.
17
+ If a `<documentation>` element does not exist for a Service Task, append an empty `<documentation>` element. Empty `<documentation>` contains only <in> and <implementation>. Include <out> only in tasks, where output is defined.
18
18
 
19
19
  #Outputs:
20
20
  Every new output created by the Service Task must be added to the <out><description> element.
@@ -0,0 +1,7 @@
1
+ ## Exclusive Gateway
2
+ An Exclusive Gateway is represented by <choose eid="..." mode="exclusive">
3
+ Each outgoing branch is represented by <alternative condition="..." eid="e.."> child.
4
+ The branch condition is stored in the **condition attribute**.
5
+ <alternative condition="data.temperature > 30" eid="e1">
6
+ Conditions must be valid Ruby expressions.
7
+ Default branch has no conditions. <otherwise eid="..."/>.
@@ -0,0 +1,2 @@
1
+ Returned service values are processed inside <finalize output="result">, where result is the variable containing the service response.
2
+ result can be a single value or an object. Inside <finalize>, assign result directly (<finalize output="result"> data.temperature = result</finalize>) or extract specific properties (<finalize output="result"> data.temperature = result["temperature"].to_f; data.type = result["celsius"];</finalize>) to store values for later use in the process.
@@ -0,0 +1,2 @@
1
+ ## Inclusive Gateway
2
+ An Inclusive Gateway differs from the Exclusive Gateway only by the attribute mode="inclusive".
@@ -0,0 +1,7 @@
1
+ ## Loop
2
+ A BPMN loop is represented by <loop eid="e.." mode="..." condition="...">
3
+ The loop condition is stored in the **condition attribute**. The loop execution mode is stored in the **mode attribute**.
4
+ pre_test is used for head controlled loops.
5
+ post_test is used for tail controlled loops.
6
+ <loop eid="e1" mode="pre_test" condition="data.counter < 10">
7
+ Loop conditions must be valid Ruby expressions.
@@ -0,0 +1,6 @@
1
+ The <method> field must strictly follow the Service Registry specification.
2
+ If the service specification defines a method, use exactly that value. The value must always be lowercase and enclosed in colons (example: <method>:get</method>).
3
+ Never invent, infer, or assume a method value that is not explicitly defined in the service specification:
4
+ <parameters>
5
+ <method/>
6
+ </parameters>
@@ -0,0 +1,6 @@
1
+ ## Parallel Gateway
2
+ Parallel execution is represented by <parallel eid="e.." wait="-1" cancel="last">
3
+ The attribute wait defines how many branches have to reach the cancel condition before other branches are considered invalid. A normal parallel has always wait="-1".
4
+ The attribute cancel defines the cancel condition, i.e., if the wait rules are evaluated after a branch fully finishes (attribute cancel has the value "last"), or if the wait rules are evaluated after the first task of a branch finishes ((attribute cancel has the value "first").
5
+ An event-based gateway (which is a special case of a parallel) has always wait="1" cancel="last".
6
+ Each concurrent branch is represented by <parallel_branch eid="e..">
@@ -0,0 +1,4 @@
1
+ ##Pause Task
2
+ A pause is represented by a <stop id="a.."> element.
3
+ A <stop> pauses the execution of the process (until it is manually resumed). It does not terminate the process.
4
+ <stop id="a5"/>
@@ -0,0 +1,3 @@
1
+ When the user requests to pause, hold, or stop the process, insert a <stop> element.
2
+ The id attribute must be unique within the process model. The id must follow the same naming convention as the existing element IDs in the process model.
3
+ Insert the <stop> element at the location specified or implied by the user's request. Otherwise, insert the <stop> element as the last element of the process.
@@ -0,0 +1,5 @@
1
+ ## Script Task
2
+ A BPMN Script Task is represented by <manipulate id="..." label="..." color="...">. The executable Ruby code is stored inside the <code> child element:
3
+ <manipulate id="a1" label="Increase Counter"><code>data.counter += 1</code></manipulate>
4
+ The label of the BPMN Script Task is stored in an attribute label in the <manipulate>.
5
+ The color of the BPMN Script Task is stored in an attribute color in the <manipulate>.
@@ -0,0 +1,2 @@
1
+ ## Sequential Flow
2
+ Sequential execution is represented by sibling XML elements appearing in order inside the same parent element.
@@ -0,0 +1,20 @@
1
+ ## Service Task
2
+ A BPMN Service Task is represented by a `<call id="..." endpoint="...">` element.
3
+ The endpoint of the service is stored in the **endpoint attribute**.
4
+ <call endpoint="measurelightingconditions">
5
+ The following child elements may appear inside `<call>`:
6
+ ├── parameters
7
+ │ ├── label
8
+ │ ├── color
9
+ │ ├── method
10
+ │ └── arguments
11
+ ├── code
12
+ │ ├── signal
13
+ │ ├── prepare
14
+ │ ├── finalize
15
+ │ ├── update
16
+ │ └── rescue
17
+ ├── annotations
18
+ └── documentation
19
+
20
+ The parameters element stores task metadata, such as its label and display color. The <label> is the task name. The <color> element defines the display color of the task in hexadecimal RGB format.
@@ -0,0 +1,3 @@
1
+ ## Variables
2
+ Variables are referenced as data.variable_name in code (script tasks, finalize) and in conditions. In service arguments they must be prefixed with !, i.e. !data.variable_name.
3
+ %%%fragments/numeric_conversion.txt
@@ -0,0 +1,15 @@
1
+ %%%fragments/cpee_xml/description.txt
2
+ %%%fragments/cpee_xml/sequence.txt
3
+ %%%fragments/cpee_xml/service_task.txt
4
+ %%%fragments/cpee_xml/color_palette.txt
5
+ %%%fragments/cpee_xml/method.txt
6
+ %%%fragments/cpee_xml/arguments.txt
7
+ %%%fragments/cpee_xml/finalize.txt
8
+ %%%fragments/cpee_xml/script_task.txt
9
+ %%%fragments/cpee_xml/exclusive_gateway.txt
10
+ %%%fragments/cpee_xml/inclusive_gateway.txt
11
+ %%%fragments/cpee_xml/loop.txt
12
+ %%%fragments/cpee_xml/parallel_gateway.txt
13
+ %%%fragments/cpee_xml/pause.txt
14
+ %%%fragments/cpee_xml/pause_insertion.txt
15
+ %%%fragments/cpee_xml/variables.txt
@@ -0,0 +1,14 @@
1
+ If a service argument (input parameter) depends on a previously computed or returned value, i.e. on process data, it must be provided using the !data.some_value syntax. A Ruby expression over process data is also allowed, e.g. !data.minutes * 60.
2
+ The leading ! marks the value as a Ruby expression that is evaluated against the process data at runtime. It is NOT a boolean negation and must never be removed.
3
+ Without the leading ! the value is passed as a literal string, i.e. data.timeout_duration would send the text "data.timeout_duration" instead of its value.
4
+ Use the leading ! ONLY when the value references process data (data.*). Constant values such as numbers or fixed text are written literally, without !, e.g. 300 and not !300.
5
+ Example (XML):
6
+ <parameters>
7
+ <arguments>
8
+ <timeout>!data.timeout_duration</timeout>
9
+ <unit>seconds</unit>
10
+ <retries>3</retries>
11
+ </arguments>
12
+ </parameters>
13
+ Example (JSON):
14
+ "timeout": "!data.timeout_duration", "unit": "seconds", "retries": 3
@@ -0,0 +1 @@
1
+ Endpoint names are derived from the task label: remove all characters except letters and digits, and convert the result to lowercase, e.g. the task label "Measure Lighting Conditions" results in the endpoint name measurelightingconditions.
@@ -0,0 +1,29 @@
1
+ Hard Structural Rules:
2
+ Tasks:
3
+ A Task represents a real business or system action that produces an external or domain-relevant effect.
4
+ Some process descriptions imply internal process-control logic that is not explicitly mentioned in the text (loop counters, variables initialization, math operations, etc.)
5
+ When necessary to create a complete and executable process model, additional tasks may be introduced to generate, initialize, update, or transform process data required by gateways, loops, routing decisions, or downstream activities. Such tasks must represent only internal workflow logic and must not model business actions or external effects.
6
+ No empty tasks are allowed: every task node must have a descriptive label.
7
+ “Default branches” between gateways are allowed — i.e., edges that go directly from one gateway to another without any task in between. These represent “nothing happens”.
8
+
9
+ Gateways:
10
+ Every split gateway must be matched with a corresponding merge gateway of the same type.
11
+ No implicit merges are allowed — merges must always be explicit.
12
+ No split gateway is permitted without a matching merge.
13
+ Any variable used in a loop condition MUST be derived from a task.
14
+
15
+ Loop Abstraction:
16
+ If a process contains repetitive behavior, it MUST NOT be unrolled into repeated tasks.
17
+ Instead, it MUST be modeled as a loop using an exclusive gateway for loop control.
18
+ The gateway branches either back to the loop body or to the exit path.
19
+ For time-based loops, timer or wait tasks may directly provide the loop termination condition. Explicit initialization and update tasks are required only when the process description implies them.
20
+
21
+ Parallel Logic:
22
+ Create a parallel gateway when two or more activities must occur concurrently or when one activity controls the duration of another. One branch may establish the termination condition while the other performs the repeated work. Merge parallel branches with a matching parallel gateway.
23
+
24
+ Flow correctness:
25
+ Each path/branch must start from the start event and lead to the end event.
26
+ Each incoming node must have its own separate edge to the target node.
27
+
28
+ Simplification Rule:
29
+ If you cannot generate a model that fully meets all requirements due to the complexity of the description, you must simplify the model until it fully satisfies every requirement.
@@ -0,0 +1,22 @@
1
+ Mermaid.js BPMN Syntax:
2
+ The graph must use the LR (Left to Right) direction.
3
+ Each Mermaid.js node must have the following structure:
4
+ id:type:shape and label
5
+ id: a unique identifier. New nodes use a unique integer from 0 to n.
6
+ type: BPMN element type → startevent, endevent, task, exclusivegateway, inclusivegateway, parallelgateway.
7
+ Shapes and labels:
8
+ Start event → id:startevent:((startevent))
9
+ End event → id:endevent:(((endevent)))
10
+ Task → id:task:(Task Label)
11
+ Exclusive gateway → id:exclusivegateway:{x}
12
+ Parallel gateway → id:parallelgateway:{AND}
13
+ Inclusive gateway → id:inclusivegateway:{O}
14
+
15
+ Reused nodes:
16
+ If a node occurs more than once, reference it by repeating the full node declaration like this - id:type:shape and label (e.g., 2:task:(do something)).
17
+ It is strictly prohibited to use only the ID (e.g., 2) without type and to use other short versions like id:type (e.g., 2:task or 2:task:).
18
+
19
+ Edges:
20
+ All nodes must be connected with -->.
21
+ Edge labels (for conditions/annotations) must be written as |text| between nodes.
22
+ Edge label is always located between 2 nodes: id:exclusivegateway:{x} --> |condition or annotation|id:task:(task label)
@@ -0,0 +1,5 @@
1
+ Service outputs are returned as strings unless otherwise specified.
2
+ If the service specification defines a numeric type, or the semantic meaning implies a numeric type, a conversion MUST be applied before the value is assigned to a workflow variable:
3
+ - If the value is defined as or implied to be a float ALWAYS use .to_f, e.g. data.temperature = result["temperature"].to_f
4
+ - If the value is defined as or implied to be an integer ALWAYS use .to_i, e.g. data.count = result.to_i
5
+ Do NOT omit a conversion!!!
@@ -0,0 +1,6 @@
1
+ Each service in the service registry is described by:
2
+ - service url: the URL of the service
3
+ - description: one or more alternative task labels for the service, separated by ";"
4
+ - functionality: what the service does
5
+ - input: the input parameters of the service (RelaxNG schema)
6
+ - output: optional, the values the service returns
@@ -0,0 +1,4 @@
1
+ If no matching service exists for a task, but the step is purely data transformation or computation and no external system interaction is implied, implement it as a script task.
2
+ The script must be generated in simple Ruby. Example: assign from another variable: data.total = data.amount + data.tax
3
+ Script tasks participate in process data flow exactly like service tasks and may create or update data.* variables used by downstream tasks and gateways.
4
+ If no matching service exists and the step is not pure computation, the task stays an unconfigured service task: do not invent a service url, input parameters, output mappings, or implementation details.