Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add quick_script template #78

Merged
merged 1 commit into from
Aug 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 18 additions & 6 deletions lib/sublayer/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,16 @@ def generate_config_file(project_path, project_name, project_type, ai_provider,
ai_model: ai_model
}

TTY::File.create_file(File.join(project_path, "lib", project_name, "config", "sublayer.yml"), YAML.dump(config))
TTY::File.create_file(File.join(project_path, "lib", project_name, "config", "sublayer.yml"), YAML.dump(config)) if project_type == "CLI"

if project_type == "Quick Script"
config_lines = <<~CONFIG
Sublayer.configuration.ai_provider = Sublayer::Providers::#{config[:ai_provider]}
Sublayer.configuration.ai_model = "#{config[:ai_model]}"
CONFIG
project_file = File.join(project_path, "#{project_name}.rb")
File.write(project_file, File.read(project_file) + config_lines)
end
end

def project_type_instructions(project_type)
Expand All @@ -109,7 +118,7 @@ def project_type_instructions(project_type)

def replace_placeholders(project_path, project_name)
# First rename the lib/PROJECT_NAME directory to lib/project_name
FileUtils.mv(File.join(project_path, "lib", "PROJECT_NAME"), File.join(project_path, "lib", project_name.gsub("-", "_").downcase))
FileUtils.mv(File.join(project_path, "lib", "PROJECT_NAME"), File.join(project_path, "lib", project_name.gsub("-", "_").downcase)) if File.directory?(File.join(project_path, "lib", "PROJECT_NAME"))

# Then walk through each file in the project and replace the placeholder content and filenames
Dir.glob("#{project_path}/**/*", File::FNM_DOTMATCH).each do |file_path|
Expand Down Expand Up @@ -147,10 +156,12 @@ def replace_placeholders(project_path, project_name)
end

# replace the sublayer version in the gemspec file with Sublayer::VERSION
gemspec_path = File.join(project_path, "#{project_name}.gemspec")
gemspec_content = File.read(gemspec_path)
gemspec_content.gsub!("SUBLAYER_VERSION", Sublayer::VERSION)
File.write(gemspec_path, gemspec_content)
if File.exist?(File.join(project_path, "#{project_name}.gemspec"))
gemspec_path = File.join(project_path, "#{project_name}.gemspec")
gemspec_content = File.read(gemspec_path)
gemspec_content.gsub!("SUBLAYER_VERSION", Sublayer::VERSION)
File.write(gemspec_path, gemspec_content)
end
end

def finalize_project(project_path, project_type)
Expand All @@ -167,6 +178,7 @@ def finalize_project(project_path, project_type)
puts "To get started, run:"
puts " cd #{File.basename(project_path)}"
puts " ./bin/#{File.basename(project_path)}" if project_type == "CLI"
puts " ruby #{File.basename(project_path)}.rb" if project_type == "Quick Script"
end

def display_help
Expand Down
3 changes: 1 addition & 2 deletions lib/sublayer/templates/cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ $ bin/PROJECT_NAME
```

Available commands:
- `example`: Run the example agent
- `generate`: Run the example generator
- `example`: Run the example generator
- `help`: Display the help message

16 changes: 16 additions & 0 deletions lib/sublayer/templates/quick_script/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# ProjectName

Welcome to your new Sublayer quick script project!

There are example Agents, Generators, and Actions in the respective folders.

## Usage

Create your own custom agents, generators, and actions and use them in
`project_name.rb`

Run your script:

```
$ ruby project_name.rb
```
11 changes: 11 additions & 0 deletions lib/sublayer/templates/quick_script/actions/example_action.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# frozen_string_literal: true

class ExampleAction < Sublayer::Actions::Base
def initialize(input:)
@input = input
end

def call
puts "Performing action with input: #{@input}"
end
end
17 changes: 17 additions & 0 deletions lib/sublayer/templates/quick_script/agents/example_agent.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# frozen_string_literal: true

class ExampleAgent < Sublayer::Agents::Base
trigger_on_files_changed { ["example_file.txt"] }

goal_condition { @goal_reached }

check_status do
@status_checked = true
end

step do
@step_taken = true
@goal_reached = true
puts "Example agent step executed"
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# frozen_string_literal: true

class ExampleGenerator < Sublayer::Generators::Base
llm_output_adapter type: :single_string,
name: "generated_text",
description: "A simple generated text"

def initialize(input:)
@input = input
end

def generate
super
end

def prompt
<<-PROMPT
Generate a simple story based on this input: #{@input}
PROMPT
end
end
7 changes: 7 additions & 0 deletions lib/sublayer/templates/quick_script/project_name.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
require "yaml"
require "sublayer"

Dir[File.join(__dir__, "actions", "*.rb")].each { |file| require file }
Dir[File.join(__dir__, "agents", "*.rb")].each { |file| require file }
Dir[File.join(__dir__, "generators", "*.rb")].each { |file| require file }

4 changes: 2 additions & 2 deletions spec/cli_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
before do
allow(TTY::Prompt).to receive(:new).and_return(prompt)
allow(prompt).to receive(:ask).and_return("test_project")
allow(prompt).to receive(:select).and_return("Web Service", "OpenAI")
allow(prompt).to receive(:select).and_return("CLI", "OpenAI")
allow(prompt).to receive(:yes?).and_return(false)
end

Expand All @@ -32,7 +32,7 @@

describe "#create_new_project" do
it "creates a new project with the given name" do
expect(FileUtils).to receive(:mkdir_p)
expect(FileUtils).to receive(:mkdir_p).twice
expect(FileUtils).to receive(:cp_r)
expect(TTY::File).to receive(:create_file)
expect(cli).to receive(:replace_placeholders)
Expand Down
45 changes: 45 additions & 0 deletions spec/integration/quick_script_creation_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
require "spec_helper"
require "fileutils"
require "open3"
require "tmpdir"

TMP_DIR = ENV['RUNNER_TEMP'] || Dir.tmpdir

RSpec.describe "Quick Script Project Creation" do
let(:project_name) { "test_project" }
let(:project_path) { File.join(TMP_DIR, project_name) }

before(:all) do
FileUtils.mkdir_p(TMP_DIR)
end

after(:all) do
FileUtils.rm_rf(TMP_DIR)
end

after(:each) do
FileUtils.rm_rf(project_path)
end

it "creates a new project with all the expected files and structures" do
command = "ruby -I lib #{File.dirname(__FILE__)}/../../bin/sublayer new #{project_name}"
input = "\e[B\n\n\nn\n\n"

output, status = Open3.capture2e(command, chdir: TMP_DIR, stdin_data: input)

expect(status.success?).to be true
expect(output).to include("Sublayer project '#{project_name}' created successfully!")

expect(Dir.exist?(project_path)).to be true

%w[
test_project.rb
agents/example_agent.rb
generators/example_generator.rb
actions/example_action.rb
README.md
].each do |file|
expect(File.exist?(File.join(project_path, file))).to be true
end
end
end
Loading