clag 0.0.5 → 0.0.6
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/clag.gemspec +1 -0
- data/exe/clag +1 -3
- data/lib/clag/commands/generate.rb +1 -1
- data/lib/clag/generators/command_line_command_generator.rb +29 -0
- data/lib/clag/version.rb +1 -1
- data/lib/clag.rb +19 -1
- metadata +17 -23
- data/vendor/gems/sublayer/.gitignore +0 -16
- data/vendor/gems/sublayer/Gemfile +0 -6
- data/vendor/gems/sublayer/LICENSE +0 -21
- data/vendor/gems/sublayer/README.md +0 -52
- data/vendor/gems/sublayer/Rakefile +0 -8
- data/vendor/gems/sublayer/lib/sublayer/agents/generate_code_given_description_agent.rb +0 -35
- data/vendor/gems/sublayer/lib/sublayer/agents/generate_command_agent.rb +0 -37
- data/vendor/gems/sublayer/lib/sublayer/agents/json_fixing_agent.rb +0 -32
- data/vendor/gems/sublayer/lib/sublayer/agents/modify_file_contents_agent.rb +0 -38
- data/vendor/gems/sublayer/lib/sublayer/agents/save_file_contents_agent.rb +0 -18
- data/vendor/gems/sublayer/lib/sublayer/capabilities/human_assistance.rb +0 -23
- data/vendor/gems/sublayer/lib/sublayer/capabilities/llm_assistance.rb +0 -253
- data/vendor/gems/sublayer/lib/sublayer/components/output_function.rb +0 -22
- data/vendor/gems/sublayer/lib/sublayer/components/output_function_formats/list_of_objects.rb +0 -30
- data/vendor/gems/sublayer/lib/sublayer/components/output_function_formats/single_string.rb +0 -40
- data/vendor/gems/sublayer/lib/sublayer/enhancements/json.rb +0 -9
- data/vendor/gems/sublayer/lib/sublayer/version.rb +0 -5
- data/vendor/gems/sublayer/lib/sublayer.rb +0 -47
- data/vendor/gems/sublayer/spec/components/output_function_spec.rb +0 -73
- data/vendor/gems/sublayer/spec/spec_helper.rb +0 -15
- data/vendor/gems/sublayer/sublayer.gemspec +0 -38
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f27cc2c8372c73257a2455613a3f5db566301ce249dc5e0b8d6812a16795f1ea
|
|
4
|
+
data.tar.gz: 2886e0b99f0d5443c66bc19087a96584674927e320de67eea79115a9f734015d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1efa37ed3818cb1b5778e76c5eaccebbb732529cafe66da308964abf3be10047fec073b232e0134b41188b748090752b95d7d542b6d82bb6cd3bc2c841be29fe
|
|
7
|
+
data.tar.gz: 40619d05e7bd9fc2c3f17aa42f615914d2e2f8fb569304ebaf04f04bdfaa056a844a3dceb489d39769faa14c104de927319b0ecb3b28ae938f6bbfabea40374d
|
data/clag.gemspec
CHANGED
data/exe/clag
CHANGED
|
@@ -8,10 +8,8 @@ unshift_path = ->(path) {
|
|
|
8
8
|
$LOAD_PATH.unshift(p) unless $LOAD_PATH.include?(p)
|
|
9
9
|
}
|
|
10
10
|
unshift_path.call('lib')
|
|
11
|
-
require 'bundler/setup'
|
|
12
|
-
|
|
13
|
-
unshift_path.call('vendor/gems/sublayer/lib')
|
|
14
11
|
|
|
12
|
+
require 'bundler/setup'
|
|
15
13
|
require 'clag'
|
|
16
14
|
|
|
17
15
|
exit(Clag::ErrorHandler.call do
|
|
@@ -17,7 +17,7 @@ module Clag
|
|
|
17
17
|
return
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
-
results =
|
|
20
|
+
results = Clag::CommandLineCommandGenerator.new(description: input).generate
|
|
21
21
|
|
|
22
22
|
if results == 'unknown'
|
|
23
23
|
puts CLI::UI.fmt("{{yellow:Unable to generate command. Please try again or provide more information.}}")
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module Clag
|
|
2
|
+
class CommandLineCommandGenerator < Sublayer::Generators::Base
|
|
3
|
+
llm_output_adapter type: :single_string,
|
|
4
|
+
name: "command",
|
|
5
|
+
description: "The command line command for the user to run or 'unknown'"
|
|
6
|
+
|
|
7
|
+
def initialize(description:)
|
|
8
|
+
@description = description
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def generate
|
|
12
|
+
super
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def prompt
|
|
16
|
+
<<-PROMPT
|
|
17
|
+
You are an expert in command line operations.
|
|
18
|
+
|
|
19
|
+
You are tasked with finding or crafting a command line command to achieve the following:
|
|
20
|
+
|
|
21
|
+
#{@description}
|
|
22
|
+
|
|
23
|
+
Considering best practices, what should be run on the command line to achieve this.
|
|
24
|
+
|
|
25
|
+
If no command is possible, respond with 'unknown'
|
|
26
|
+
PROMPT
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
data/lib/clag/version.rb
CHANGED
data/lib/clag.rb
CHANGED
|
@@ -11,7 +11,7 @@ module Clag
|
|
|
11
11
|
|
|
12
12
|
autoload(:EntryPoint, 'clag/entry_point')
|
|
13
13
|
autoload(:Commands, 'clag/commands')
|
|
14
|
-
|
|
14
|
+
load 'clag/generators/command_line_command_generator.rb'
|
|
15
15
|
|
|
16
16
|
Config = CLI::Kit::Config.new(tool_name: TOOL_NAME)
|
|
17
17
|
Command = CLI::Kit::BaseCommand
|
|
@@ -23,4 +23,22 @@ module Clag
|
|
|
23
23
|
)
|
|
24
24
|
|
|
25
25
|
ErrorHandler = CLI::Kit::ErrorHandler.new(log_file: LOG_FILE)
|
|
26
|
+
|
|
27
|
+
case ENV["CLAG_LLM"]
|
|
28
|
+
when "gemini"
|
|
29
|
+
Sublayer.configuration.ai_provider = Sublayer::Providers::Gemini
|
|
30
|
+
Sublayer.configuration.ai_model = "gemini-pro"
|
|
31
|
+
when "claude"
|
|
32
|
+
Sublayer.configuration.ai_provider = Sublayer::Providers::Claude
|
|
33
|
+
Sublayer.configuration.ai_model ="claude-3-opus-20240229"
|
|
34
|
+
when "groq"
|
|
35
|
+
Sublayer.configuration.ai_provider = Sublayer::Providers::Groq
|
|
36
|
+
Sublayer.configuration.ai_model = "mixtral-8x7b-32768"
|
|
37
|
+
when "local"
|
|
38
|
+
Sublayer.configuration.ai_provider = Sublayer::Providers::Local
|
|
39
|
+
Sublayer.configuration.ai_model = "LLaMA_CPP"
|
|
40
|
+
else
|
|
41
|
+
Sublayer.configuration.ai_provider = Sublayer::Providers::OpenAI
|
|
42
|
+
Sublayer.configuration.ai_model = "gpt-4-turbo-preview"
|
|
43
|
+
end
|
|
26
44
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: clag
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.6
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Scott Werner
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2024-03-
|
|
11
|
+
date: 2024-03-15 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: cli-kit
|
|
@@ -122,6 +122,20 @@ dependencies:
|
|
|
122
122
|
- - ">="
|
|
123
123
|
- !ruby/object:Gem::Version
|
|
124
124
|
version: '0'
|
|
125
|
+
- !ruby/object:Gem::Dependency
|
|
126
|
+
name: sublayer
|
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
|
128
|
+
requirements:
|
|
129
|
+
- - ">="
|
|
130
|
+
- !ruby/object:Gem::Version
|
|
131
|
+
version: '0'
|
|
132
|
+
type: :runtime
|
|
133
|
+
prerelease: false
|
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
135
|
+
requirements:
|
|
136
|
+
- - ">="
|
|
137
|
+
- !ruby/object:Gem::Version
|
|
138
|
+
version: '0'
|
|
125
139
|
- !ruby/object:Gem::Dependency
|
|
126
140
|
name: rake
|
|
127
141
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -158,30 +172,10 @@ files:
|
|
|
158
172
|
- lib/clag/commands/generate.rb
|
|
159
173
|
- lib/clag/commands/help.rb
|
|
160
174
|
- lib/clag/entry_point.rb
|
|
175
|
+
- lib/clag/generators/command_line_command_generator.rb
|
|
161
176
|
- lib/clag/version.rb
|
|
162
177
|
- test/example_test.rb
|
|
163
178
|
- test/test_helper.rb
|
|
164
|
-
- vendor/gems/sublayer/.gitignore
|
|
165
|
-
- vendor/gems/sublayer/Gemfile
|
|
166
|
-
- vendor/gems/sublayer/LICENSE
|
|
167
|
-
- vendor/gems/sublayer/README.md
|
|
168
|
-
- vendor/gems/sublayer/Rakefile
|
|
169
|
-
- vendor/gems/sublayer/lib/sublayer.rb
|
|
170
|
-
- vendor/gems/sublayer/lib/sublayer/agents/generate_code_given_description_agent.rb
|
|
171
|
-
- vendor/gems/sublayer/lib/sublayer/agents/generate_command_agent.rb
|
|
172
|
-
- vendor/gems/sublayer/lib/sublayer/agents/json_fixing_agent.rb
|
|
173
|
-
- vendor/gems/sublayer/lib/sublayer/agents/modify_file_contents_agent.rb
|
|
174
|
-
- vendor/gems/sublayer/lib/sublayer/agents/save_file_contents_agent.rb
|
|
175
|
-
- vendor/gems/sublayer/lib/sublayer/capabilities/human_assistance.rb
|
|
176
|
-
- vendor/gems/sublayer/lib/sublayer/capabilities/llm_assistance.rb
|
|
177
|
-
- vendor/gems/sublayer/lib/sublayer/components/output_function.rb
|
|
178
|
-
- vendor/gems/sublayer/lib/sublayer/components/output_function_formats/list_of_objects.rb
|
|
179
|
-
- vendor/gems/sublayer/lib/sublayer/components/output_function_formats/single_string.rb
|
|
180
|
-
- vendor/gems/sublayer/lib/sublayer/enhancements/json.rb
|
|
181
|
-
- vendor/gems/sublayer/lib/sublayer/version.rb
|
|
182
|
-
- vendor/gems/sublayer/spec/components/output_function_spec.rb
|
|
183
|
-
- vendor/gems/sublayer/spec/spec_helper.rb
|
|
184
|
-
- vendor/gems/sublayer/sublayer.gemspec
|
|
185
179
|
homepage: https://github.com/sublayerapp/clag
|
|
186
180
|
licenses:
|
|
187
181
|
- MIT
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2023 Sublayer
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
# Sublayer
|
|
2
|
-
|
|
3
|
-
An AI agent framework
|
|
4
|
-
|
|
5
|
-
## Installation
|
|
6
|
-
|
|
7
|
-
Install the gem by running the following commands:
|
|
8
|
-
|
|
9
|
-
$ bundle
|
|
10
|
-
$ gem build sublayer.gemspec
|
|
11
|
-
$ gem install sublayer-0.0.1.gem
|
|
12
|
-
|
|
13
|
-
Your OpenAI API key needs to be accessible in your environment at OPENAI\_API\_KEY
|
|
14
|
-
|
|
15
|
-
Your default editor for your environment is also used.
|
|
16
|
-
|
|
17
|
-
## Usage
|
|
18
|
-
|
|
19
|
-
### * Interactive CLI
|
|
20
|
-
|
|
21
|
-
You can use the gem by running the command `sublayer` in any project directory.
|
|
22
|
-
This will open an interactive shell where all file operations are run relative
|
|
23
|
-
to that root project directory.
|
|
24
|
-
|
|
25
|
-
In the interactive shell, you're able to create new agents specific to your
|
|
26
|
-
project, generate code, modify existing files, and save the resulting code from
|
|
27
|
-
those agent commands.
|
|
28
|
-
|
|
29
|
-
### * Simple TDD Pair (experimental / dangerous)
|
|
30
|
-
|
|
31
|
-
**Warning:** This will generate code from GPT4 and run it as called from your
|
|
32
|
-
tests. Use at your own risk.
|
|
33
|
-
|
|
34
|
-
Usage: `sublayer_simple_tdd_pair "TEST_RUN_COMMAND" "FILE_UNDER_TEST"`
|
|
35
|
-
|
|
36
|
-
This command will run the TEST_RUN_COMMAND, send the test output, the tests, and
|
|
37
|
-
the FILE\_UNDER\_TEST to GPT4 and will attempt to edit FILE\_UNDER\_TEST and
|
|
38
|
-
rerun the tests until they pass.
|
|
39
|
-
|
|
40
|
-
To do use it like in [this
|
|
41
|
-
loom](https://www.loom.com/share/6970b51856b04a91b792f14e848e9b6d) you'll need
|
|
42
|
-
to install entr: `brew install entr`
|
|
43
|
-
|
|
44
|
-
The command I'm running there is: `ls ./day3/*.rb | entr sublayer_simple_tdd_pair "rspec ./day3/santa_spec.rb" "./day3/santa.rb"`
|
|
45
|
-
|
|
46
|
-
## Development
|
|
47
|
-
|
|
48
|
-
TBD
|
|
49
|
-
|
|
50
|
-
## Contributing
|
|
51
|
-
|
|
52
|
-
TBD
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
module Sublayer
|
|
2
|
-
module Agents
|
|
3
|
-
class GenerateCodeGivenDescriptionAgent
|
|
4
|
-
include Sublayer::Capabilities::LLMAssistance
|
|
5
|
-
include Sublayer::Capabilities::HumanAssistance
|
|
6
|
-
|
|
7
|
-
attr_reader :description, :technologies, :results
|
|
8
|
-
|
|
9
|
-
llm_result_format type: :single_string,
|
|
10
|
-
name: "generated_code",
|
|
11
|
-
description: "The generated code in the requested language"
|
|
12
|
-
|
|
13
|
-
def initialize(description:, technologies:)
|
|
14
|
-
@description = description
|
|
15
|
-
@technologies = technologies
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def execute
|
|
19
|
-
@results = human_assistance_with(llm_generate)
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def prompt
|
|
23
|
-
<<-PROMPT
|
|
24
|
-
You are an expert programmer in #{technologies.join(", ")}.
|
|
25
|
-
|
|
26
|
-
You are tasked with writing code using the following technologies: #{technologies.join(", ")}.
|
|
27
|
-
|
|
28
|
-
The description of the task is #{description}
|
|
29
|
-
|
|
30
|
-
Take a deep breath and think step by step before you start coding.
|
|
31
|
-
PROMPT
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
end
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
module Sublayer
|
|
2
|
-
module Agents
|
|
3
|
-
class GenerateCommandLineCommandAgent
|
|
4
|
-
include Sublayer::Capabilities::LLMAssistance
|
|
5
|
-
include Sublayer::Capabilities::HumanAssistance
|
|
6
|
-
|
|
7
|
-
attr_reader :description, :results
|
|
8
|
-
|
|
9
|
-
llm_result_format type: :single_string,
|
|
10
|
-
name: "command",
|
|
11
|
-
description: "The command line command for the user to run or 'unknown'"
|
|
12
|
-
|
|
13
|
-
def initialize(description:)
|
|
14
|
-
@description = description
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def execute
|
|
18
|
-
@results = llm_generate
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def prompt
|
|
22
|
-
<<-PROMPT
|
|
23
|
-
You are an expert in command line operations.
|
|
24
|
-
|
|
25
|
-
You are tasked with finding or crafting a command line command to achieve the following:
|
|
26
|
-
|
|
27
|
-
#{description}
|
|
28
|
-
|
|
29
|
-
Considering best practices, what should be run on the command line to achieve this.
|
|
30
|
-
|
|
31
|
-
If no command is possible, respond with 'unknown'
|
|
32
|
-
|
|
33
|
-
PROMPT
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
end
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
module Sublayer
|
|
2
|
-
module Agents
|
|
3
|
-
class JSONFixingAgent
|
|
4
|
-
include Sublayer::Capabilities::LLMAssistance
|
|
5
|
-
include Sublayer::Capabilities::HumanAssistance
|
|
6
|
-
|
|
7
|
-
attr_reader :invalid_json, :results
|
|
8
|
-
|
|
9
|
-
llm_result_format type: :single_string,
|
|
10
|
-
name: "valid_json",
|
|
11
|
-
description: "The valid JSON string"
|
|
12
|
-
|
|
13
|
-
def initialize(invalid_json:)
|
|
14
|
-
@invalid_json = invalid_json
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def execute
|
|
18
|
-
@results = llm_generate
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def prompt
|
|
22
|
-
<<-PROMPT
|
|
23
|
-
You are an expert in JSON parsing.
|
|
24
|
-
|
|
25
|
-
The given string is not a valid JSON: #{invalid_json}
|
|
26
|
-
|
|
27
|
-
Please fix this and produce a valid JSON.
|
|
28
|
-
PROMPT
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
end
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
module Sublayer
|
|
2
|
-
module Agents
|
|
3
|
-
class ModifyFileContentsAgent
|
|
4
|
-
include Sublayer::Capabilities::LLMAssistance
|
|
5
|
-
include Sublayer::Capabilities::HumanAssistance
|
|
6
|
-
|
|
7
|
-
attr_reader :file_path, :description, :technologies, :results
|
|
8
|
-
|
|
9
|
-
llm_result_format type: :single_string,
|
|
10
|
-
name: "modified_file_contents",
|
|
11
|
-
description: "The modified file contents"
|
|
12
|
-
|
|
13
|
-
def initialize(file_path:, description:, technologies:)
|
|
14
|
-
@file_path = file_path
|
|
15
|
-
@description = description
|
|
16
|
-
@technologies = technologies
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def execute
|
|
20
|
-
@results = human_assistance_with(llm_generate)
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def prompt
|
|
24
|
-
<<-PROMPT
|
|
25
|
-
You are an expert programmer in #{technologies.join(", ")}.
|
|
26
|
-
|
|
27
|
-
Here are the original file contents:
|
|
28
|
-
|
|
29
|
-
#{File.read(@file_path)}
|
|
30
|
-
|
|
31
|
-
The description of the changes to make is: #{description}
|
|
32
|
-
|
|
33
|
-
Please make the necessary changes to this file.
|
|
34
|
-
PROMPT
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
end
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
module Sublayer
|
|
2
|
-
module Agents
|
|
3
|
-
class SaveFileContentsAgent
|
|
4
|
-
attr_reader :file_contents, :file_path
|
|
5
|
-
|
|
6
|
-
def initialize(file_contents:, file_path:)
|
|
7
|
-
@file_contents = file_contents
|
|
8
|
-
@file_path = file_path
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
def execute
|
|
12
|
-
File.open(file_path, "w") do |file|
|
|
13
|
-
file.write(file_contents)
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
end
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
require "tempfile"
|
|
2
|
-
|
|
3
|
-
module Sublayer
|
|
4
|
-
module Capabilities
|
|
5
|
-
module HumanAssistance
|
|
6
|
-
def human_assistance_with(string_to_assist_with)
|
|
7
|
-
tempfile = Tempfile.new("some_tempfile_to_assist_with")
|
|
8
|
-
tempfile.write(string_to_assist_with)
|
|
9
|
-
tempfile.close
|
|
10
|
-
|
|
11
|
-
system("$EDITOR #{tempfile.path}")
|
|
12
|
-
|
|
13
|
-
tempfile.open
|
|
14
|
-
results = tempfile.read
|
|
15
|
-
|
|
16
|
-
tempfile.close
|
|
17
|
-
tempfile.unlink
|
|
18
|
-
|
|
19
|
-
results.chomp
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
end
|
|
@@ -1,253 +0,0 @@
|
|
|
1
|
-
require "openai"
|
|
2
|
-
require "pry"
|
|
3
|
-
require "httparty"
|
|
4
|
-
require "nokogiri"
|
|
5
|
-
|
|
6
|
-
module Sublayer
|
|
7
|
-
module Capabilities
|
|
8
|
-
module LLMAssistance
|
|
9
|
-
def self.included(base)
|
|
10
|
-
base.extend(ClassMethods)
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
module ClassMethods
|
|
14
|
-
def llm_result_format(type:, name:, description:)
|
|
15
|
-
output_function = Sublayer::Components::OutputFunction.create(type: type, name: name, description: description)
|
|
16
|
-
const_set(:OUTPUT_FUNCTION, output_function)
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def llm_generate
|
|
21
|
-
case ENV["CLAG_LLM"]
|
|
22
|
-
when "gemini"
|
|
23
|
-
generate_with_gemini
|
|
24
|
-
when "claude"
|
|
25
|
-
generate_with_claude
|
|
26
|
-
when "groq"
|
|
27
|
-
generate_with_groq
|
|
28
|
-
when "local"
|
|
29
|
-
generate_with_local_model
|
|
30
|
-
else
|
|
31
|
-
generate_with_openai
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
private
|
|
36
|
-
|
|
37
|
-
def generate_with_local_model
|
|
38
|
-
system_prompt = <<-PROMPT
|
|
39
|
-
In this environment you have access to a set of tools you can use to answer the user's question.
|
|
40
|
-
|
|
41
|
-
You may call them like this:
|
|
42
|
-
<function_calls>
|
|
43
|
-
<invoke>
|
|
44
|
-
<tool_name>$TOOL_NAME</tool_name>
|
|
45
|
-
<parameters>
|
|
46
|
-
<command>value</command>
|
|
47
|
-
...
|
|
48
|
-
</parameters>
|
|
49
|
-
</invoke>
|
|
50
|
-
</function_calls>
|
|
51
|
-
|
|
52
|
-
Here are the tools available:
|
|
53
|
-
<tools>
|
|
54
|
-
#{self.class::OUTPUT_FUNCTION.to_xml}
|
|
55
|
-
</tools>
|
|
56
|
-
|
|
57
|
-
Respond only with valid xml.
|
|
58
|
-
The entire response should be wrapped in a <response> tag.
|
|
59
|
-
Any additional information not inside a tool call should go in a <scratch> tag.
|
|
60
|
-
PROMPT
|
|
61
|
-
|
|
62
|
-
response = HTTParty.post(
|
|
63
|
-
"http://localhost:8080/v1/chat/completions",
|
|
64
|
-
headers: {
|
|
65
|
-
"Authorization": "Bearer no-key",
|
|
66
|
-
"Content-Type": "application/json"
|
|
67
|
-
},
|
|
68
|
-
body: {
|
|
69
|
-
"model": "LLaMA_CPP",
|
|
70
|
-
"messages": [
|
|
71
|
-
{ "role": "system", "content": system_prompt },
|
|
72
|
-
{ "role": "user", "content": prompt }
|
|
73
|
-
]
|
|
74
|
-
}.to_json
|
|
75
|
-
)
|
|
76
|
-
|
|
77
|
-
text_containing_xml = JSON.parse(response.body).dig("choices", 0, "message", "content")
|
|
78
|
-
xml = text_containing_xml.match(/\<response\>(.*?)\<\/response\>/m).to_s
|
|
79
|
-
response_xml = Nokogiri::XML(xml)
|
|
80
|
-
function_output = response_xml.at_xpath("//parameters/command").children.to_s
|
|
81
|
-
|
|
82
|
-
return function_output
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
def generate_with_groq
|
|
86
|
-
system_prompt = <<-PROMPT
|
|
87
|
-
In this environment you have access to a set of tools you can use to answer the user's question.
|
|
88
|
-
|
|
89
|
-
You may call them like this:
|
|
90
|
-
<function_calls>
|
|
91
|
-
<invoke>
|
|
92
|
-
<tool_name>$TOOL_NAME</tool_name>
|
|
93
|
-
<parameters>
|
|
94
|
-
<command>value</command>
|
|
95
|
-
...
|
|
96
|
-
</parameters>
|
|
97
|
-
</invoke>
|
|
98
|
-
</function_calls>
|
|
99
|
-
|
|
100
|
-
Here are the tools available:
|
|
101
|
-
<tools>
|
|
102
|
-
#{self.class::OUTPUT_FUNCTION.to_xml}
|
|
103
|
-
</tools>
|
|
104
|
-
|
|
105
|
-
Respond only with valid xml.
|
|
106
|
-
The entire response should be wrapped in a <response> tag.
|
|
107
|
-
Any additional information not inside a tool call should go in a <scratch> tag.
|
|
108
|
-
PROMPT
|
|
109
|
-
|
|
110
|
-
response = HTTParty.post(
|
|
111
|
-
"https://api.groq.com/openai/v1/chat/completions",
|
|
112
|
-
headers: {
|
|
113
|
-
"Authorization": "Bearer #{ENV["GROQ_API_KEY"]}",
|
|
114
|
-
"Content-Type": "application/json"
|
|
115
|
-
},
|
|
116
|
-
body: {
|
|
117
|
-
"messages": [{"role": "user", "content": "#{system_prompt}\n#{prompt}"}],
|
|
118
|
-
"model": "mixtral-8x7b-32768"
|
|
119
|
-
}.to_json
|
|
120
|
-
)
|
|
121
|
-
|
|
122
|
-
text_containing_xml = JSON.parse(response.body).dig("choices", 0, "message", "content")
|
|
123
|
-
xml = text_containing_xml.match(/\<response\>(.*?)\<\/response\>/m).to_s
|
|
124
|
-
response_xml = Nokogiri::XML(xml)
|
|
125
|
-
function_output = response_xml.at_xpath("//response/function_calls/invoke/parameters/command").children.to_s
|
|
126
|
-
|
|
127
|
-
return function_output
|
|
128
|
-
end
|
|
129
|
-
|
|
130
|
-
def generate_with_claude
|
|
131
|
-
system_prompt = <<-PROMPT
|
|
132
|
-
In this environment you have access to a set of tools you can use to answer the user's question.
|
|
133
|
-
|
|
134
|
-
You may call them like this:
|
|
135
|
-
<function_calls>
|
|
136
|
-
<invoke>
|
|
137
|
-
<tool_name>$TOOL_NAME</tool_name>
|
|
138
|
-
<parameters>
|
|
139
|
-
<$PARAMETER_NAME>$PARAMETER_VALUE</$PARAMETER_NAME>
|
|
140
|
-
...
|
|
141
|
-
</parameters>
|
|
142
|
-
</invoke>
|
|
143
|
-
</function_calls>
|
|
144
|
-
|
|
145
|
-
Here are the tools available:
|
|
146
|
-
<tools>
|
|
147
|
-
#{self.class::OUTPUT_FUNCTION.to_xml}
|
|
148
|
-
</tools>
|
|
149
|
-
|
|
150
|
-
Respond only with valid xml. The entire response should be wrapped in a <response> tag. Any additional information not inside a tool call should go in a <scratch> tag.
|
|
151
|
-
PROMPT
|
|
152
|
-
|
|
153
|
-
response = HTTParty.post(
|
|
154
|
-
"https://api.anthropic.com/v1/messages",
|
|
155
|
-
headers: {
|
|
156
|
-
"x-api-key": ENV["ANTHROPIC_API_KEY"],
|
|
157
|
-
"anthropic-version": "2023-06-01",
|
|
158
|
-
"content-type": "application/json"
|
|
159
|
-
},
|
|
160
|
-
body: {
|
|
161
|
-
model: "claude-3-opus-20240229",
|
|
162
|
-
max_tokens: 1337,
|
|
163
|
-
system: system_prompt,
|
|
164
|
-
messages: [
|
|
165
|
-
{ "role": "user", "content": prompt }
|
|
166
|
-
]
|
|
167
|
-
}.to_json
|
|
168
|
-
)
|
|
169
|
-
|
|
170
|
-
# raise an error if the response is not a 200
|
|
171
|
-
raise "Error generating with Claude, error: #{response.body}" unless response.code == 200
|
|
172
|
-
|
|
173
|
-
text_containing_xml = JSON.parse(response.body).dig("content", 0, "text")
|
|
174
|
-
|
|
175
|
-
# Extract the xml from the respons contained in <response> tags the content of the string looksl ike this:
|
|
176
|
-
xml = text_containing_xml.match(/\<response\>(.*?)\<\/response\>/m).to_s
|
|
177
|
-
|
|
178
|
-
# Parse the xml and extract the response
|
|
179
|
-
response_xml = Nokogiri::XML(xml)
|
|
180
|
-
|
|
181
|
-
# Extract the response from the xml
|
|
182
|
-
function_output = response_xml.at_xpath("//response/function_calls/invoke/parameters/command").children.to_s
|
|
183
|
-
|
|
184
|
-
return function_output
|
|
185
|
-
end
|
|
186
|
-
|
|
187
|
-
def generate_with_gemini
|
|
188
|
-
gemini_prompt = adapt_prompt_for_gemini
|
|
189
|
-
|
|
190
|
-
response = HTTParty.post("https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=#{ENV['GEMINI_API_KEY']}", body: gemini_prompt.to_json, headers: { 'Content-Type' => 'application/json' })
|
|
191
|
-
|
|
192
|
-
function_output = extract_function_output_from_gemini_response(response)
|
|
193
|
-
|
|
194
|
-
return function_output
|
|
195
|
-
end
|
|
196
|
-
|
|
197
|
-
def adapt_prompt_for_gemini
|
|
198
|
-
return({ tools: { function_declarations: [ self.class::OUTPUT_FUNCTION.to_hash ] }, contents: { role: "user", parts: { text: prompt } } })
|
|
199
|
-
end
|
|
200
|
-
|
|
201
|
-
def extract_function_output_from_gemini_response(response)
|
|
202
|
-
candidates = response.dig('candidates')
|
|
203
|
-
if candidates && candidates.size > 0
|
|
204
|
-
content = candidates[0].dig('content')
|
|
205
|
-
if content && content['parts'] && content['parts'].size > 0
|
|
206
|
-
part = content['parts'][0]
|
|
207
|
-
|
|
208
|
-
# Check if the part contains a function call
|
|
209
|
-
if part.key?('functionCall')
|
|
210
|
-
function_name = part['functionCall']['name']
|
|
211
|
-
args = part['functionCall']['args']
|
|
212
|
-
|
|
213
|
-
# Assuming the agent expects a single string parameter:
|
|
214
|
-
if args && args.key?(self.class::OUTPUT_FUNCTION.name)
|
|
215
|
-
return args[self.class::OUTPUT_FUNCTION.name]
|
|
216
|
-
end
|
|
217
|
-
else
|
|
218
|
-
# If it's not a function call, check for a direct string response
|
|
219
|
-
return part['text'] if part.key?('text')
|
|
220
|
-
end
|
|
221
|
-
end
|
|
222
|
-
end
|
|
223
|
-
end
|
|
224
|
-
|
|
225
|
-
def generate_with_openai
|
|
226
|
-
client = OpenAI::Client.new(access_token: ENV["OPENAI_API_KEY"])
|
|
227
|
-
|
|
228
|
-
response = client.chat(
|
|
229
|
-
parameters: {
|
|
230
|
-
model: "gpt-4-turbo-preview",
|
|
231
|
-
messages: [
|
|
232
|
-
{
|
|
233
|
-
"role": "user",
|
|
234
|
-
"content": prompt
|
|
235
|
-
}
|
|
236
|
-
],
|
|
237
|
-
function_call: { name: self.class::OUTPUT_FUNCTION.name },
|
|
238
|
-
functions: [
|
|
239
|
-
self.class::OUTPUT_FUNCTION.to_hash
|
|
240
|
-
]
|
|
241
|
-
}
|
|
242
|
-
)
|
|
243
|
-
|
|
244
|
-
message = response.dig("choices", 0, "message")
|
|
245
|
-
raise "No function called" unless message["function_call"]
|
|
246
|
-
|
|
247
|
-
function_name = message.dig("function_call", self.class::OUTPUT_FUNCTION.name)
|
|
248
|
-
args_from_llm = message.dig("function_call", "arguments")
|
|
249
|
-
JSON.parse(args_from_llm)[self.class::OUTPUT_FUNCTION.name]
|
|
250
|
-
end
|
|
251
|
-
end
|
|
252
|
-
end
|
|
253
|
-
end
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
module Sublayer
|
|
2
|
-
module Components
|
|
3
|
-
class OutputFunction
|
|
4
|
-
include Sublayer::Components
|
|
5
|
-
|
|
6
|
-
attr_reader :name
|
|
7
|
-
|
|
8
|
-
def self.create(options)
|
|
9
|
-
("Sublayer::Components::"+options[:type].to_s.camelize).constantize.new(options)
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def to_hash
|
|
13
|
-
# Raise not implemented error
|
|
14
|
-
raise NotImplementedError
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def to_xml
|
|
18
|
-
raise NotImplementedError
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
end
|
data/vendor/gems/sublayer/lib/sublayer/components/output_function_formats/list_of_objects.rb
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
module Sublayer
|
|
2
|
-
module Components
|
|
3
|
-
class ListOfObjects < OutputFunction
|
|
4
|
-
def initialize(options)
|
|
5
|
-
@name = options[:name]
|
|
6
|
-
@description = options[:description]
|
|
7
|
-
@structure = options[:structure]
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
def to_hash
|
|
11
|
-
{
|
|
12
|
-
name: @name,
|
|
13
|
-
description: @description,
|
|
14
|
-
parameters: {
|
|
15
|
-
type: "object",
|
|
16
|
-
properties: {
|
|
17
|
-
@name.to_sym => {
|
|
18
|
-
type: "array",
|
|
19
|
-
items: {
|
|
20
|
-
type: "object",
|
|
21
|
-
properties: @structure.transform_values { |desc| { type: "string", description: desc.capitalize } }
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
end
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
module Sublayer
|
|
2
|
-
module Components
|
|
3
|
-
class SingleString < OutputFunction
|
|
4
|
-
def initialize(options)
|
|
5
|
-
@name = options[:name]
|
|
6
|
-
@description = options[:description]
|
|
7
|
-
end
|
|
8
|
-
|
|
9
|
-
def to_hash
|
|
10
|
-
{
|
|
11
|
-
name: @name,
|
|
12
|
-
description: @description,
|
|
13
|
-
parameters: {
|
|
14
|
-
type: "object",
|
|
15
|
-
properties: {
|
|
16
|
-
@name => {
|
|
17
|
-
type: "string",
|
|
18
|
-
description: @description
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def to_xml
|
|
26
|
-
<<-XML
|
|
27
|
-
<tool_description>
|
|
28
|
-
<tool_name>#{@name}</tool_name>
|
|
29
|
-
<tool_description>#{@description}</tool_description>
|
|
30
|
-
<parameters>
|
|
31
|
-
<name>#{@name}</name>
|
|
32
|
-
<type>string</type>
|
|
33
|
-
<description>#{@description}</description>
|
|
34
|
-
</parameters>
|
|
35
|
-
</tool_description>
|
|
36
|
-
XML
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
end
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'active_support'
|
|
4
|
-
require 'active_support/core_ext/hash/indifferent_access'
|
|
5
|
-
require 'active_support/inflector'
|
|
6
|
-
require_relative "sublayer/version"
|
|
7
|
-
|
|
8
|
-
if !File.directory?(File.join(Dir.pwd, ".sublayer", "agents"))
|
|
9
|
-
Dir.mkdir(File.join(Dir.pwd, ".sublayer"))
|
|
10
|
-
Dir.mkdir(File.join(Dir.pwd, ".sublayer", "agents"))
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
# List of directories to load files from
|
|
14
|
-
LOAD_PATHS = [
|
|
15
|
-
File.join(__dir__, 'sublayer', 'components'),
|
|
16
|
-
File.join(__dir__, 'sublayer', 'components', 'output_function_formats'),
|
|
17
|
-
File.join(__dir__, 'sublayer', 'capabilities'),
|
|
18
|
-
File.join(__dir__, 'sublayer', 'agents'),
|
|
19
|
-
File.join(Dir.pwd, '.sublayer', 'agents')
|
|
20
|
-
]
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
# Load files from each directory in the list
|
|
24
|
-
LOAD_PATHS.each do |load_path|
|
|
25
|
-
Dir.glob(File.join(load_path, '*.rb')).each do |file|
|
|
26
|
-
require_relative file
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
require_relative "sublayer/enhancements/json.rb"
|
|
31
|
-
|
|
32
|
-
module Sublayer
|
|
33
|
-
class Error < StandardError; end
|
|
34
|
-
|
|
35
|
-
# Defines a method to reload all the agents
|
|
36
|
-
def self.reload_agents
|
|
37
|
-
LOAD_PATHS.each do |load_path|
|
|
38
|
-
Dir.glob(File.join(load_path, '*.rb')) do |file|
|
|
39
|
-
load file
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def self.cwd
|
|
45
|
-
Dir.pwd
|
|
46
|
-
end
|
|
47
|
-
end
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
require "spec_helper"
|
|
2
|
-
|
|
3
|
-
RSpec.describe Sublayer::Components::OutputFunction do
|
|
4
|
-
describe "#to_hash" do
|
|
5
|
-
context "type: :single_string" do
|
|
6
|
-
it "formats the hash output correctly" do
|
|
7
|
-
output_function = Sublayer::Components::OutputFunction.create(type: :single_string, name: "modified_file_contents", description: "The modified file contents")
|
|
8
|
-
expect(output_function.to_hash).to eq(
|
|
9
|
-
{
|
|
10
|
-
name: "modified_file_contents",
|
|
11
|
-
description: "The modified file contents",
|
|
12
|
-
parameters: {
|
|
13
|
-
type: "object",
|
|
14
|
-
properties: {
|
|
15
|
-
"modified_file_contents" => {
|
|
16
|
-
type: "string",
|
|
17
|
-
description: "The modified file contents"
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
)
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
context "type: :list_of_objects" do
|
|
27
|
-
it "formats the hash output correctly" do
|
|
28
|
-
output_function = Sublayer::Components::OutputFunction.create(
|
|
29
|
-
type: :list_of_objects,
|
|
30
|
-
name: "retrieved_steps",
|
|
31
|
-
description: "The retrieved steps for performing the given coding task",
|
|
32
|
-
structure: {
|
|
33
|
-
category: "The category of the step",
|
|
34
|
-
command: "The command to run on the command line",
|
|
35
|
-
description: "The description of what the command is for"
|
|
36
|
-
}
|
|
37
|
-
)
|
|
38
|
-
|
|
39
|
-
expect(output_function.to_hash).to eq(
|
|
40
|
-
{
|
|
41
|
-
name: "retrieved_steps",
|
|
42
|
-
description: "The retrieved steps for performing the given coding task",
|
|
43
|
-
parameters: {
|
|
44
|
-
type: "object",
|
|
45
|
-
properties: {
|
|
46
|
-
retrieved_steps: {
|
|
47
|
-
type: "array",
|
|
48
|
-
items: {
|
|
49
|
-
type: "object",
|
|
50
|
-
properties: {
|
|
51
|
-
category: {
|
|
52
|
-
type: "string",
|
|
53
|
-
description: "The category of the step"
|
|
54
|
-
},
|
|
55
|
-
command: {
|
|
56
|
-
type: "string",
|
|
57
|
-
description: "The command to run on the command line"
|
|
58
|
-
},
|
|
59
|
-
description: {
|
|
60
|
-
type: "string",
|
|
61
|
-
description: "The description of what the command is for"
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
)
|
|
70
|
-
end
|
|
71
|
-
end
|
|
72
|
-
end
|
|
73
|
-
end
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "sublayer"
|
|
4
|
-
|
|
5
|
-
RSpec.configure do |config|
|
|
6
|
-
# Enable flags like --only-failures and --next-failure
|
|
7
|
-
config.example_status_persistence_file_path = ".rspec_status"
|
|
8
|
-
|
|
9
|
-
# Disable RSpec exposing methods globally on `Module` and `main`
|
|
10
|
-
config.disable_monkey_patching!
|
|
11
|
-
|
|
12
|
-
config.expect_with :rspec do |c|
|
|
13
|
-
c.syntax = :expect
|
|
14
|
-
end
|
|
15
|
-
end
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative "lib/sublayer/version"
|
|
4
|
-
|
|
5
|
-
Gem::Specification.new do |spec|
|
|
6
|
-
spec.name = "sublayer"
|
|
7
|
-
spec.version = Sublayer::VERSION
|
|
8
|
-
spec.authors = ["Scott Werner"]
|
|
9
|
-
spec.email = ["scott@sublayer.com"]
|
|
10
|
-
spec.license = "MIT"
|
|
11
|
-
|
|
12
|
-
spec.summary = "A ruby library for interacting with and orchestrating AI agents"
|
|
13
|
-
spec.description = "A command line framework for building, generating, and orchestrating AI agents."
|
|
14
|
-
spec.homepage = "https://www.sublayer.com"
|
|
15
|
-
spec.required_ruby_version = ">= 2.6.0"
|
|
16
|
-
|
|
17
|
-
spec.metadata["homepage_uri"] = spec.homepage
|
|
18
|
-
|
|
19
|
-
# Specify which files should be added to the gem when it is released.
|
|
20
|
-
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
|
21
|
-
spec.files = Dir.chdir(__dir__) do
|
|
22
|
-
`git ls-files -z`.split("\x0").reject do |f|
|
|
23
|
-
(File.expand_path(f) == __FILE__) ||
|
|
24
|
-
f.start_with?(*%w[bin/ test/ spec/ features/ .git .circleci appveyor Gemfile])
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
spec.executables << "sublayer"
|
|
29
|
-
spec.executables << "sublayer_simple_tdd_pair"
|
|
30
|
-
spec.require_paths = ["lib"]
|
|
31
|
-
|
|
32
|
-
spec.add_dependency "ruby-openai"
|
|
33
|
-
spec.add_dependency "colorize"
|
|
34
|
-
spec.add_dependency "activesupport"
|
|
35
|
-
|
|
36
|
-
spec.add_development_dependency "rspec", "~> 3.12"
|
|
37
|
-
spec.add_development_dependency "pry", " ~> 0.14"
|
|
38
|
-
end
|