ad-agent_architecture 0.0.7 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 25616fff163424e27ea21bf76cabec403e7113c7b018e791ed42fe523e7964aa
4
- data.tar.gz: a34ad7c9d1275dc3db2394623874408225b67ab6a1a6d39bf0f2b46fafc7608f
3
+ metadata.gz: b1afc432b8e4a84cec6f099987e20ccb1abd19b278a1f299fdd3cd822e47b6f2
4
+ data.tar.gz: fd1b6e9054740f005c083712e3cd67b1872cc0cd8d66eadaa2c9541fb3f33c9c
5
5
  SHA512:
6
- metadata.gz: f2acf82a7726aa7168e595cac40238e79e634a2a396c93899ab30394494bae8ba3d96e1a843e27a4a826e18c96fefbc290cd34ae4592dbdd24a83a7a12ec0734
7
- data.tar.gz: 6f7948ae17ac536b0608e5063d6b61411ea74408d5cbdc8007772e6dab32d372b5c714f5a31ff19043958513094a5e9322661bbff41fca466f81ee86e21eacc8
6
+ metadata.gz: 7af0666287aaef19e10bc414c160066ff2ab0dde2f55f2ae758790454028bccc5bb33ee48fb1ff63ca307a98ab25a82a16a896d2dbf256090151870519e5cb78
7
+ data.tar.gz: ae03bbcc49b5f4a0f467852a6f2c411c5d45484ba86eeac3251f75ce97379b2f04e8790530248ad997e5b8fee776174c5ef6ec36b128d89dfc693c52e09de874
data/.rubocop.yml CHANGED
@@ -14,7 +14,7 @@ AllCops:
14
14
  Exclude:
15
15
  - ".builders/**/*"
16
16
  - "spec/samples/**/*"
17
- - "lib/ad/agent_architecture/db/*"
17
+ - "lib/ad/agent_architecture/database/*"
18
18
 
19
19
  Metrics/BlockLength:
20
20
  Exclude:
@@ -43,7 +43,7 @@ Metrics/BlockLength:
43
43
  Metrics/MethodLength:
44
44
  Max: 25
45
45
  Exclude:
46
- - "lib/ad/agent_architecture/dsl/*"
46
+ - "lib/ad/agent_architecture/**/*"
47
47
 
48
48
  Layout/LineLength:
49
49
  Max: 200
@@ -91,7 +91,7 @@ Style/AccessorGrouping:
91
91
  Enabled: false
92
92
  Metrics/AbcSize:
93
93
  Exclude:
94
- - "lib/ad/agent_architecture/dsl/*"
94
+ - "lib/ad/agent_architecture/**/*"
95
95
  Metrics/NoExpectationExample:
96
96
  Exclude:
97
97
  - "spec/ad/agent_architecture/dsl/*"
data/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ ## [0.0.8](https://github.com/appydave/ad-agent_architecture/compare/v0.0.7...v0.0.8) (2024-06-29)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * add basic reports ([82d89e1](https://github.com/appydave/ad-agent_architecture/commit/82d89e164744f9100f92ca8ec677447ee1c083cb))
7
+
8
+ ## [0.0.7](https://github.com/appydave/ad-agent_architecture/compare/v0.0.6...v0.0.7) (2024-06-29)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * add basic support for database persistence to DSL ([632c815](https://github.com/appydave/ad-agent_architecture/commit/632c815133b2cd31ab95dccb3c0b8564e25aa605))
14
+
1
15
  ## [0.0.6](https://github.com/appydave/ad-agent_architecture/compare/v0.0.5...v0.0.6) (2024-06-28)
2
16
 
3
17
 
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ad
4
+ module AgentArchitecture
5
+ module Database
6
+ class SQLQuery
7
+ SQL_DIR = File.expand_path('../sql', __dir__)
8
+
9
+ def self.query(sql_filename, params = {})
10
+ sql_path = File.join(SQL_DIR, "#{sql_filename}.sql")
11
+
12
+ # puts "SQL_DIR: #{SQL_DIR}"
13
+ # puts "SQL Path: #{sql_path}"
14
+ raise "SQL file not found: #{sql_path}" unless File.exist?(sql_path)
15
+
16
+ sql = File.read(sql_path)
17
+ DB.fetch(sql, params)
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ad
4
+ module AgentArchitecture
5
+ module Dsl
6
+ module Actions
7
+ # Save workflow graph to database
8
+ class SaveDatabase
9
+ def initialize(workflow_hash)
10
+ @workflow_hash = workflow_hash
11
+ end
12
+
13
+ def save
14
+ DB.transaction do
15
+ # Save workflow
16
+ workflow_record = Ad::AgentArchitecture::Database::Workflow.create(name: @workflow_hash[:name])
17
+
18
+ # Save attributes
19
+ attribute_records = @workflow_hash[:attributes].map do |_name, attr|
20
+ Ad::AgentArchitecture::Database::Attribute.create(
21
+ name: attr[:name], type: attr[:type], is_array: attr[:is_array], workflow: workflow_record
22
+ )
23
+ end
24
+
25
+ attribute_map = attribute_records.to_h { |ar| [ar.name.to_sym, ar] }
26
+
27
+ # Save sections and steps
28
+ @workflow_hash[:sections].each do |section|
29
+ section_record = Ad::AgentArchitecture::Database::Section.create(
30
+ name: section[:name], order: section[:order], workflow: workflow_record
31
+ )
32
+
33
+ section[:steps].each do |step|
34
+ step_record = Ad::AgentArchitecture::Database::Step.create(
35
+ name: step[:name], order: step[:order], prompt: step[:prompt], section: section_record
36
+ )
37
+
38
+ step[:input_attributes].each do |attr_name|
39
+ Ad::AgentArchitecture::Database::InputAttribute.create(
40
+ step: step_record, attribute: attribute_map[attr_name.to_sym]
41
+ )
42
+ end
43
+
44
+ step[:output_attributes].each do |attr_name|
45
+ Ad::AgentArchitecture::Database::OutputAttribute.create(
46
+ step: step_record, attribute: attribute_map[attr_name.to_sym]
47
+ )
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module Ad
6
+ module AgentArchitecture
7
+ module Dsl
8
+ module Actions
9
+ # Save workflow graph to JSON file
10
+ class SaveJson
11
+ def initialize(workflow_hash)
12
+ @workflow_hash = workflow_hash
13
+ end
14
+
15
+ def save(file_name)
16
+ # Pretty JSON
17
+ File.write(file_name, JSON.pretty_generate(@workflow_hash))
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'yaml'
4
+
5
+ module Ad
6
+ module AgentArchitecture
7
+ module Dsl
8
+ module Actions
9
+ # Save workflow graph to YAML file
10
+ class SaveYaml
11
+ def initialize(workflow_hash)
12
+ @workflow_hash = workflow_hash
13
+ end
14
+
15
+ def save(file_name)
16
+ File.write(file_name, @workflow_hash.to_yaml)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -8,7 +8,6 @@ module Ad
8
8
  def self.create(name:, &block)
9
9
  new(name).tap do |dsl|
10
10
  dsl.instance_eval(&block) if block_given?
11
- dsl.save
12
11
  end
13
12
  end
14
13
 
@@ -53,43 +52,23 @@ module Ad
53
52
  end
54
53
 
55
54
  def save
56
- DB.transaction do
57
- # Save workflow
58
- workflow_record = Ad::AgentArchitecture::Database::Workflow.create(name: @workflow[:name])
55
+ Ad::AgentArchitecture::Dsl::Actions::SaveDatabase.new(@workflow).save
59
56
 
60
- # Save attributes
61
- attribute_records = @workflow[:attributes].map do |_name, attr|
62
- Ad::AgentArchitecture::Database::Attribute.create(
63
- name: attr[:name], type: attr[:type], is_array: attr[:is_array], workflow: workflow_record
64
- )
65
- end
66
- attribute_map = attribute_records.to_h { |ar| [ar.name.to_sym, ar] }
57
+ self
58
+ end
67
59
 
68
- # Save sections and steps
69
- @workflow[:sections].each do |section|
70
- section_record = Ad::AgentArchitecture::Database::Section.create(
71
- name: section[:name], order: section[:order], workflow: workflow_record
72
- )
60
+ def save_json(file_name: nil)
61
+ full_file_name = file_name || 'workflow.json'
62
+ Ad::AgentArchitecture::Dsl::Actions::SaveJson.new(@workflow).save(full_file_name)
73
63
 
74
- section[:steps].each do |step|
75
- step_record = Ad::AgentArchitecture::Database::Step.create(
76
- name: step[:name], order: step[:order], prompt: step[:prompt], section: section_record
77
- )
64
+ self
65
+ end
78
66
 
79
- step[:input_attributes].each do |attr_name|
80
- Ad::AgentArchitecture::Database::InputAttribute.create(
81
- step: step_record, attribute: attribute_map[attr_name.to_sym]
82
- )
83
- end
67
+ def save_yaml(file_name: nil)
68
+ full_file_name = file_name || 'workflow.yaml'
69
+ Ad::AgentArchitecture::Dsl::Actions::SaveYaml.new(@workflow).save(full_file_name)
84
70
 
85
- step[:output_attributes].each do |attr_name|
86
- Ad::AgentArchitecture::Database::OutputAttribute.create(
87
- step: step_record, attribute: attribute_map[attr_name.to_sym]
88
- )
89
- end
90
- end
91
- end
92
- end
71
+ self
93
72
  end
94
73
  end
95
74
  end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'k_log'
4
+
5
+ module Ad
6
+ module AgentArchitecture
7
+ module Report
8
+ # Print workflow details
9
+ class WorkflowDetailReport
10
+ include KLog::Logging
11
+
12
+ def print(workflow)
13
+ log.section_heading 'Workflow Details Report'
14
+ log.kv 'Name', workflow.name
15
+ log.kv 'Description', workflow.description
16
+
17
+ workflow.sections.each do |section|
18
+ log.section_heading "Section: #{section.name}"
19
+ log.kv 'Order', section.order
20
+ section.steps.each do |step|
21
+ log.section_heading "Step: #{step.name}"
22
+ log.kv 'Order', step.order
23
+ log.kv 'Prompt', step.prompt
24
+ log.kv 'Input Attributes', step.input_attributes.map { |ia| ia.attribute.name }.join(', ')
25
+ log.kv 'Output Attributes', step.output_attributes.map { |oa| oa.attribute.name }.join(', ')
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'k_log'
4
+
5
+ module Ad
6
+ module AgentArchitecture
7
+ module Report
8
+ # Print workflow details
9
+ class WorkflowListReport
10
+ include KLog::Logging
11
+
12
+ def print
13
+ # tp query, :workflow_name, :workflow_description, :section_name, :section_description, :section_order, :step_name, :step_order, :step_prompt, :inputs, :outputs
14
+ tp query, :workflow_name, :section_name, :step_name, :step_prompt, :inputs, :outputs
15
+ end
16
+
17
+ def query
18
+ Ad::AgentArchitecture::Database::SQLQuery.query(:workflow_details).map do |row|
19
+ row[:inputs] = JSON.parse(row[:inputs]) if row[:inputs]
20
+ row[:outputs] = JSON.parse(row[:outputs]) if row[:outputs]
21
+ row
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,35 @@
1
+ SELECT
2
+ workflows.id AS workflow_id,
3
+ workflows.name AS workflow_name,
4
+ workflows.description AS workflow_description,
5
+ sections.id AS section_id,
6
+ sections.name AS section_name,
7
+ sections.description AS section_description,
8
+ sections."order" AS section_order,
9
+ steps.id AS step_id,
10
+ steps.name AS step_name,
11
+ steps."order" AS step_order,
12
+ steps.prompt AS step_prompt,
13
+ json_group_array(
14
+ json_object(
15
+ 'name', input_attr.name,
16
+ 'type', input_attr.type,
17
+ 'is_array', input_attr.is_array
18
+ )
19
+ ) AS inputs,
20
+ json_group_array(
21
+ json_object(
22
+ 'name', output_attr.name,
23
+ 'type', output_attr.type,
24
+ 'is_array', output_attr.is_array
25
+ )
26
+ ) AS outputs
27
+ FROM workflows
28
+ LEFT JOIN sections ON workflows.id = sections.workflow_id
29
+ LEFT JOIN steps ON sections.id = steps.section_id
30
+ LEFT JOIN input_attributes ON steps.id = input_attributes.step_id
31
+ LEFT JOIN attributes AS input_attr ON input_attributes.attribute_id = input_attr.id
32
+ LEFT JOIN output_attributes ON steps.id = output_attributes.step_id
33
+ LEFT JOIN attributes AS output_attr ON output_attributes.attribute_id = output_attr.id
34
+ GROUP BY workflows.id, sections.id, steps.id
35
+ ORDER BY workflows.name, sections."order", steps."order";
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Ad
4
4
  module AgentArchitecture
5
- VERSION = '0.0.7'
5
+ VERSION = '0.0.9'
6
6
  end
7
7
  end
@@ -2,16 +2,23 @@
2
2
 
3
3
  require 'sequel'
4
4
  require 'sqlite3'
5
+ require 'k_log'
5
6
 
6
7
  require 'ad/agent_architecture/version'
7
- require 'ad/agent_architecture/db/create_schema'
8
+ require 'ad/agent_architecture/database/create_schema'
8
9
 
9
10
  DB = Sequel.sqlite
10
11
 
11
12
  Ad::AgentArchitecture::Database::CreateSchema.new(DB).execute
12
13
 
13
- require 'ad/agent_architecture/db/models'
14
+ require 'ad/agent_architecture/database/models'
15
+ require 'ad/agent_architecture/database/sql_query'
14
16
  require 'ad/agent_architecture/dsl/agent_workflow_dsl'
17
+ require 'ad/agent_architecture/dsl/actions/save_database'
18
+ require 'ad/agent_architecture/dsl/actions/save_json'
19
+ require 'ad/agent_architecture/dsl/actions/save_yaml'
20
+ require 'ad/agent_architecture/report/workflow_detail_report'
21
+ require 'ad/agent_architecture/report/workflow_list_report'
15
22
 
16
23
  module Ad
17
24
  module AgentArchitecture
data/package-lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "ad-agent_architecture",
3
- "version": "0.0.7",
3
+ "version": "0.0.9",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "ad-agent_architecture",
9
- "version": "0.0.7",
9
+ "version": "0.0.9",
10
10
  "devDependencies": {
11
11
  "@klueless-js/semantic-release-rubygem": "github:klueless-js/semantic-release-rubygem",
12
12
  "@semantic-release/changelog": "^6.0.3",
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ad-agent_architecture",
3
- "version": "0.0.7",
3
+ "version": "0.0.9",
4
4
  "description": "Architecture/Schema for AI Agents",
5
5
  "scripts": {
6
6
  "release": "semantic-release"
data/workflow.json ADDED
@@ -0,0 +1,99 @@
1
+ {
2
+ "name": "YouTube Transcript to Medium Article",
3
+ "sections": [
4
+ {
5
+ "name": "Analysis",
6
+ "order": 1,
7
+ "steps": [
8
+ {
9
+ "name": "Generate Outline",
10
+ "order": 1,
11
+ "input_attributes": [
12
+ "transcript"
13
+ ],
14
+ "output_attributes": [
15
+ "outline"
16
+ ],
17
+ "prompt": "Analyze [transcript] and generate a preliminary outline for a blog post."
18
+ },
19
+ {
20
+ "name": "Write First Draft",
21
+ "order": 2,
22
+ "input_attributes": [
23
+ "outline"
24
+ ],
25
+ "output_attributes": [
26
+ "first_draft"
27
+ ],
28
+ "prompt": "Write a blog post based on [outline]."
29
+ },
30
+ {
31
+ "name": "Generate Intros",
32
+ "order": 3,
33
+ "input_attributes": [
34
+ "first_draft"
35
+ ],
36
+ "output_attributes": [
37
+ "intro_variations"
38
+ ],
39
+ "prompt": "Create 5 introduction variations for [first_draft]."
40
+ },
41
+ {
42
+ "name": "SEO Analysis",
43
+ "order": 4,
44
+ "input_attributes": [
45
+ "first_draft"
46
+ ],
47
+ "output_attributes": [
48
+ "seo_analysis"
49
+ ],
50
+ "prompt": "Analyze the blog post for SEO."
51
+ }
52
+ ]
53
+ },
54
+ {
55
+ "name": "Editing",
56
+ "order": 2,
57
+ "steps": [
58
+ {
59
+ "name": "Edit Draft",
60
+ "order": 1,
61
+ "input_attributes": [
62
+ "first_draft"
63
+ ],
64
+ "output_attributes": [
65
+ "first_draft"
66
+ ],
67
+ "prompt": "Edit [first_draft] for grammar, style, and clarity."
68
+ }
69
+ ]
70
+ }
71
+ ],
72
+ "attributes": {
73
+ "transcript": {
74
+ "name": "transcript",
75
+ "type": "string",
76
+ "is_array": false
77
+ },
78
+ "outline": {
79
+ "name": "outline",
80
+ "type": "string",
81
+ "is_array": false
82
+ },
83
+ "first_draft": {
84
+ "name": "first_draft",
85
+ "type": "string",
86
+ "is_array": false
87
+ },
88
+ "intro_variations": {
89
+ "name": "intro_variations",
90
+ "type": "array",
91
+ "is_array": false
92
+ },
93
+ "seo_analysis": {
94
+ "name": "seo_analysis",
95
+ "type": "string",
96
+ "is_array": false
97
+ }
98
+ }
99
+ }
data/workflow.yaml ADDED
@@ -0,0 +1,65 @@
1
+ ---
2
+ :name: YouTube Transcript to Medium Article
3
+ :sections:
4
+ - :name: Analysis
5
+ :order: 1
6
+ :steps:
7
+ - :name: Generate Outline
8
+ :order: 1
9
+ :input_attributes:
10
+ - :transcript
11
+ :output_attributes:
12
+ - :outline
13
+ :prompt: Analyze [transcript] and generate a preliminary outline for a blog post.
14
+ - :name: Write First Draft
15
+ :order: 2
16
+ :input_attributes:
17
+ - :outline
18
+ :output_attributes:
19
+ - :first_draft
20
+ :prompt: Write a blog post based on [outline].
21
+ - :name: Generate Intros
22
+ :order: 3
23
+ :input_attributes:
24
+ - :first_draft
25
+ :output_attributes:
26
+ - :intro_variations
27
+ :prompt: Create 5 introduction variations for [first_draft].
28
+ - :name: SEO Analysis
29
+ :order: 4
30
+ :input_attributes:
31
+ - :first_draft
32
+ :output_attributes:
33
+ - :seo_analysis
34
+ :prompt: Analyze the blog post for SEO.
35
+ - :name: Editing
36
+ :order: 2
37
+ :steps:
38
+ - :name: Edit Draft
39
+ :order: 1
40
+ :input_attributes:
41
+ - :first_draft
42
+ :output_attributes:
43
+ - :first_draft
44
+ :prompt: Edit [first_draft] for grammar, style, and clarity.
45
+ :attributes:
46
+ :transcript:
47
+ :name: :transcript
48
+ :type: :string
49
+ :is_array: false
50
+ :outline:
51
+ :name: :outline
52
+ :type: :string
53
+ :is_array: false
54
+ :first_draft:
55
+ :name: :first_draft
56
+ :type: :string
57
+ :is_array: false
58
+ :intro_variations:
59
+ :name: :intro_variations
60
+ :type: :array
61
+ :is_array: false
62
+ :seo_analysis:
63
+ :name: :seo_analysis
64
+ :type: :string
65
+ :is_array: false
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ad-agent_architecture
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.0.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Cruwys
@@ -80,14 +80,22 @@ files:
80
80
  - docs/requirements.md
81
81
  - docs/structure-youtube-script.yaml
82
82
  - lib/ad/agent_architecture.rb
83
- - lib/ad/agent_architecture/db/create_schema.rb
84
- - lib/ad/agent_architecture/db/models.rb
85
- - lib/ad/agent_architecture/db/save_workflow_graph.rb
83
+ - lib/ad/agent_architecture/database/create_schema.rb
84
+ - lib/ad/agent_architecture/database/models.rb
85
+ - lib/ad/agent_architecture/database/sql_query.rb
86
+ - lib/ad/agent_architecture/dsl/actions/save_database.rb
87
+ - lib/ad/agent_architecture/dsl/actions/save_json.rb
88
+ - lib/ad/agent_architecture/dsl/actions/save_yaml.rb
86
89
  - lib/ad/agent_architecture/dsl/agent_workflow_dsl.rb
90
+ - lib/ad/agent_architecture/report/workflow_detail_report.rb
91
+ - lib/ad/agent_architecture/report/workflow_list_report.rb
92
+ - lib/ad/agent_architecture/sql/workflow_details.sql
87
93
  - lib/ad/agent_architecture/version.rb
88
94
  - package-lock.json
89
95
  - package.json
90
96
  - sig/ad/agent_architecture.rbs
97
+ - workflow.json
98
+ - workflow.yaml
91
99
  homepage: http://appydave.com/gems/ad-agent_architecture
92
100
  licenses:
93
101
  - MIT
@@ -1,53 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Ad
4
- module AgentArchitecture
5
- module Database
6
- class SaveWorkflowGraph
7
- def initialize(workflow_hash)
8
- @workflow_hash = workflow_hash
9
- end
10
-
11
- def save
12
- DB.transaction do
13
- # Save workflow
14
- workflow_record = Ad::AgentArchitecture::Database::Workflow.create(name: @workflow_hash[:name])
15
-
16
- # Save attributes
17
- attribute_records = @workflow_hash[:attributes].map do |_name, attr|
18
- Ad::AgentArchitecture::Database::Attribute.create(
19
- name: attr[:name], type: attr[:type], is_array: attr[:is_array], workflow: workflow_record
20
- )
21
- end
22
- attribute_map = attribute_records.to_h { |ar| [ar.name.to_sym, ar] }
23
-
24
- # Save sections and steps
25
- @workflow_hash[:sections].each do |section|
26
- section_record = Ad::AgentArchitecture::Database::Section.create(
27
- name: section[:name], order: section[:order], workflow: workflow_record
28
- )
29
-
30
- section[:steps].each do |step|
31
- step_record = Ad::AgentArchitecture::Database::Step.create(
32
- name: step[:name], order: step[:order], prompt: step[:prompt], section: section_record
33
- )
34
-
35
- step[:input_attributes].each do |attr_name|
36
- Ad::AgentArchitecture::Database::InputAttribute.create(
37
- step: step_record, attribute: attribute_map[attr_name.to_sym]
38
- )
39
- end
40
-
41
- step[:output_attributes].each do |attr_name|
42
- Ad::AgentArchitecture::Database::OutputAttribute.create(
43
- step: step_record, attribute: attribute_map[attr_name.to_sym]
44
- )
45
- end
46
- end
47
- end
48
- end
49
- end
50
- end
51
- end
52
- end
53
- end