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 +4 -4
- data/lib/sublayer/agents/base.rb +51 -0
- data/lib/sublayer/triggers/base.rb +13 -0
- data/lib/sublayer/triggers/file_change.rb +20 -0
- data/lib/sublayer/version.rb +1 -1
- data/lib/sublayer.rb +2 -0
- data/sublayer.gemspec +1 -0
- metadata +20 -10
- data/lib/sublayer/generators/examples/code_from_blueprint_generator.rb +0 -30
- data/lib/sublayer/generators/examples/code_from_description_generator.rb +0 -26
- data/lib/sublayer/generators/examples/description_from_code_generator.rb +0 -23
- data/lib/sublayer/generators/examples/invalid_to_valid_json_generator.rb +0 -23
- data/lib/sublayer/generators/examples/route_selection_from_user_intent_generator.rb +0 -29
- data/lib/sublayer/generators/examples/sentiment_from_text_generator.rb +0 -26
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8254634ae1c2de3daa2f3a1fddf102df81ee82e79e345c1ef4a9256ea35553e2
|
4
|
+
data.tar.gz: 7a2eb512a983ae642858af5c395d3651b69449359204975be9468b30736c6c40
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ea8183fce2be4f378a581d079a124df8c82b03165186575b6152576e76ca26fd93a925df6a108d1e348bdd393a71206d3e79ce832b000c9607224c9ea5fc46df
|
7
|
+
data.tar.gz: a52f4942386fabe647fe97ee060747fa02e6f93c1261a33336bb14012383907419ad92e385c7fe4973df313dad8cc818f772063c8637ca81e318ba0b273430bb
|
data/lib/sublayer/agents/base.rb
CHANGED
@@ -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,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
|
data/lib/sublayer/version.rb
CHANGED
data/lib/sublayer.rb
CHANGED
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
|
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-
|
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:
|
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
|