sublayer 0.1.0.pre.alpha.2 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: aaff1cafef6e0987bf8da2abdd710698579dcdc6dad6342ff3c96a0c4c3658c9
4
- data.tar.gz: cadcfea3f989a281a24727789e8d5fce6f3353c88a0a06763c75e1cb19873a44
3
+ metadata.gz: 8254634ae1c2de3daa2f3a1fddf102df81ee82e79e345c1ef4a9256ea35553e2
4
+ data.tar.gz: 7a2eb512a983ae642858af5c395d3651b69449359204975be9468b30736c6c40
5
5
  SHA512:
6
- metadata.gz: 35fbfcaf0a12f16f596ae254f40c0cc694253e4f26a42b0a8356e720700e2032be60b9b62e9728c66b5bd81c5e466e745a3d4336999ebe9ec85541a4dde6d35b
7
- data.tar.gz: ad74821c9ac29108fa6969729427d9bd6d6f359119f1456fe942bc944594a2eba0824a106a6623f77708341f8b2d6a020bbef5145b8f168aa8549d6fce2160f9
6
+ metadata.gz: ea8183fce2be4f378a581d079a124df8c82b03165186575b6152576e76ca26fd93a925df6a108d1e348bdd393a71206d3e79ce832b000c9607224c9ea5fc46df
7
+ data.tar.gz: a52f4942386fabe647fe97ee060747fa02e6f93c1261a33336bb14012383907419ad92e385c7fe4973df313dad8cc818f772063c8637ca81e318ba0b273430bb
@@ -1,6 +1,57 @@
1
1
  module Sublayer
2
2
  module Agents
3
3
  class Base
4
+ class << self
5
+ attr_reader :triggers, :goal_condition_block, :check_status_block, :step_block, :listeners
6
+
7
+ def trigger(trigger_instance = nil)
8
+ @triggers ||= []
9
+
10
+ if trigger_instance
11
+ @triggers << trigger_instance
12
+ else
13
+ raise ArgumentError, "Either a trigger instance or a block must be provided"
14
+ end
15
+ end
16
+
17
+ def trigger_on_files_changed(&block)
18
+ trigger(Triggers::FileChange.new(&block))
19
+ end
20
+
21
+ def goal_condition(&block)
22
+ @goal_condition_block = block
23
+ end
24
+
25
+ def check_status(&block)
26
+ @check_status_block = block
27
+ end
28
+
29
+ def step(&block)
30
+ @step_block = block
31
+ end
32
+ end
33
+
34
+ def run
35
+ setup_triggers
36
+ take_step
37
+ sleep
38
+ end
39
+
40
+ private
41
+
42
+ def setup_triggers
43
+ @listeners = []
44
+
45
+ self.class.triggers.each do |trigger|
46
+ listener = trigger.setup(self)
47
+ @listeners << listener if listener
48
+ end
49
+ end
50
+
51
+ def take_step
52
+ instance_eval(&self.class.check_status_block)
53
+ instance_eval(&self.class.step_block) unless instance_eval(&self.class.goal_condition_block)
54
+ end
4
55
  end
5
56
  end
6
57
  end
@@ -0,0 +1,13 @@
1
+ module Sublayer
2
+ module Triggers
3
+ class Base
4
+ def setup(agent)
5
+ raise NotImplementedError, "Subclasses must implement setup method"
6
+ end
7
+
8
+ def activate(agent)
9
+ agent.send(:take_step)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,20 @@
1
+ module Sublayer
2
+ module Triggers
3
+ class FileChange < Base
4
+ def initialize(&block)
5
+ @block = block
6
+ end
7
+
8
+ def setup(agent)
9
+ files_to_watch = agent.instance_eval(&@block)
10
+ folders = files_to_watch.map { |file| File.dirname(File.expand_path(file)) }.uniq
11
+
12
+ Listen.to(*folders) do |modified, added, removed|
13
+ if files_to_watch.any? { |file| modified.include?(File.expand_path(file)) }
14
+ activate(agent)
15
+ end
16
+ end.start
17
+ end
18
+ end
19
+ end
20
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sublayer
4
- VERSION = "0.1.0-alpha.2"
4
+ VERSION = "0.1.0"
5
5
  end
data/lib/sublayer.rb CHANGED
@@ -8,6 +8,8 @@ require 'ostruct'
8
8
  require "httparty"
9
9
  require "openai"
10
10
  require "nokogiri"
11
+ require "listen"
12
+
11
13
  require_relative "sublayer/version"
12
14
 
13
15
  loader = Zeitwerk::Loader.for_gem
data/sublayer.gemspec CHANGED
@@ -36,6 +36,7 @@ Gem::Specification.new do |spec|
36
36
  spec.add_dependency "zeitwerk"
37
37
  spec.add_dependency "nokogiri", "~> 1.16.5"
38
38
  spec.add_dependency "httparty"
39
+ spec.add_dependency "listen"
39
40
 
40
41
  spec.add_development_dependency "rspec", "~> 3.12"
41
42
  spec.add_development_dependency "pry", "~> 0.14"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sublayer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0.pre.alpha.2
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Scott Werner
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-05-17 00:00:00.000000000 Z
11
+ date: 2024-07-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ruby-openai
@@ -94,6 +94,20 @@ dependencies:
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: listen
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
97
111
  - !ruby/object:Gem::Dependency
98
112
  name: rspec
99
113
  requirement: !ruby/object:Gem::Requirement
@@ -182,16 +196,12 @@ files:
182
196
  - lib/sublayer/components/output_adapters/single_string.rb
183
197
  - lib/sublayer/components/output_adapters/string_selection_from_list.rb
184
198
  - lib/sublayer/generators/base.rb
185
- - lib/sublayer/generators/examples/code_from_blueprint_generator.rb
186
- - lib/sublayer/generators/examples/code_from_description_generator.rb
187
- - lib/sublayer/generators/examples/description_from_code_generator.rb
188
- - lib/sublayer/generators/examples/invalid_to_valid_json_generator.rb
189
- - lib/sublayer/generators/examples/route_selection_from_user_intent_generator.rb
190
- - lib/sublayer/generators/examples/sentiment_from_text_generator.rb
191
199
  - lib/sublayer/providers/claude.rb
192
200
  - lib/sublayer/providers/gemini.rb
193
201
  - lib/sublayer/providers/open_ai.rb
194
202
  - lib/sublayer/tasks/base.rb
203
+ - lib/sublayer/triggers/base.rb
204
+ - lib/sublayer/triggers/file_change.rb
195
205
  - lib/sublayer/version.rb
196
206
  - sublayer.gemspec
197
207
  homepage: https://docs.sublayer.com
@@ -213,9 +223,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
213
223
  version: 2.6.0
214
224
  required_rubygems_version: !ruby/object:Gem::Requirement
215
225
  requirements:
216
- - - ">"
226
+ - - ">="
217
227
  - !ruby/object:Gem::Version
218
- version: 1.3.1
228
+ version: '0'
219
229
  requirements: []
220
230
  rubygems_version: 3.3.26
221
231
  signing_key:
@@ -1,30 +0,0 @@
1
- class CodeFromBlueprintGenerator < Sublayer::Generators::Base
2
- llm_output_adapter type: :single_string,
3
- name: "generated_code",
4
- description: "The generated code for the description"
5
-
6
- def initialize(blueprint_description:, blueprint_code:, description:)
7
- @blueprint_description = blueprint_description
8
- @blueprint_code = blueprint_code
9
- @description = description
10
- end
11
-
12
- def generate
13
- super
14
- end
15
-
16
- def prompt
17
- <<-PROMPT
18
- You are an expert programmer and are great at looking at and understanding existing patterns and applying them to new situations.
19
-
20
- The blueprint we're working with is: #{@blueprint_description}.
21
- The code for that blueprint is:
22
- #{@blueprint_code}
23
-
24
- You need to use the blueprint above and modify it so that it satisfied the following description:
25
- #{@description}
26
-
27
- Take a deep breath and think step by step before you start coding.
28
- PROMPT
29
- end
30
- end
@@ -1,26 +0,0 @@
1
- class CodeFromDescriptionGenerator < Sublayer::Generators::Base
2
- llm_output_adapter type: :single_string,
3
- name: "generated_code",
4
- description: "The generated code in the requested language"
5
-
6
- def initialize(description:, technologies:)
7
- @description = description
8
- @technologies = technologies
9
- end
10
-
11
- def generate
12
- super
13
- end
14
-
15
- def prompt
16
- <<-PROMPT
17
- You are an expert programmer in #{@technologies.join(", ")}.
18
-
19
- You are tasked with writing code using the following technologies: #{@technologies.join(", ")}.
20
-
21
- The description of the task is #{@description}
22
-
23
- Take a deep breath and think step by step before you start coding.
24
- PROMPT
25
- end
26
- end
@@ -1,23 +0,0 @@
1
- class DescriptionFromCodeGenerator < Sublayer::Generators::Base
2
- llm_output_adapter type: :single_string,
3
- name: "code_description",
4
- description: "A description of what the code in the file does"
5
-
6
- def initialize(code:)
7
- @code = code
8
- end
9
-
10
- def generate
11
- super
12
- end
13
-
14
- def prompt
15
- <<-PROMPT
16
- You are an experienced software engineer. Below is a chunk of code:
17
-
18
- #{@code}
19
-
20
- Please read the code carefully and provide a high-level description of what this code does, including its purpose, functionalities, and any noteworthy details.
21
- PROMPT
22
- end
23
- end
@@ -1,23 +0,0 @@
1
- class InvalidToValidJsonGenerator < Sublayer::Generators::Base
2
- llm_output_adapter type: :single_string,
3
- name: "valid_json",
4
- description: "The valid JSON string"
5
-
6
- def initialize(invalid_json:)
7
- @invalid_json = invalid_json
8
- end
9
-
10
- def generate
11
- super
12
- end
13
-
14
- def prompt
15
- <<-PROMPT
16
- You are an expert in JSON parsing.
17
-
18
- The given string is not a valid JSON: #{@invalid_json}
19
-
20
- Please fix this and produce a valid JSON.
21
- PROMPT
22
- end
23
- end
@@ -1,29 +0,0 @@
1
- class RouteSelectionFromUserIntentGenerator < Sublayer::Generators::Base
2
- llm_output_adapter type: :string_selection_from_list,
3
- name: "route",
4
- description: "A route selected from the list",
5
- options: :available_routes
6
-
7
- def initialize(user_intent:)
8
- @user_intent = user_intent
9
- end
10
-
11
- def generate
12
- super
13
- end
14
-
15
- def available_routes
16
- ["GET /", "GET /users", "GET /users/:id", "POST /users", "PUT /users/:id", "DELETE /users/:id"]
17
- end
18
-
19
- def prompt
20
- <<-PROMPT
21
- You are skilled at selecting routes based on user intent.
22
-
23
- Your task is to choose a route based on the following intent:
24
-
25
- The user's intent is:
26
- #{@user_intent}
27
- PROMPT
28
- end
29
- end
@@ -1,26 +0,0 @@
1
- class SentimentFromTextGenerator < Sublayer::Generators::Base
2
- llm_output_adapter type: :string_selection_from_list,
3
- name: "sentiment_value",
4
- description: "A sentiment value from the list",
5
- options: -> { @sentiment_options }
6
-
7
- def initialize(text:, sentiment_options:)
8
- @text = text
9
- @sentiment_options = sentiment_options
10
- end
11
-
12
- def generate
13
- super
14
- end
15
-
16
- def prompt
17
- <<-PROMPT
18
- You are an expert at determining sentiment from text.
19
-
20
- You are tasked with analyzing the following text and determining its sentiment value.
21
-
22
- The text is:
23
- #{@text}
24
- PROMPT
25
- end
26
- end