ask-rails 0.2.5 → 0.4.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/CHANGELOG.md +4 -32
- data/README.md +38 -13
- data/lib/ask/rails/generators/install/install_generator.rb +28 -0
- data/lib/ask/rails/generators/install/templates/application_agent.rb +26 -0
- data/lib/ask/rails/generators/install/templates/initializer.rb +15 -0
- data/lib/ask/rails/railtie.rb +1 -18
- data/lib/ask/rails/version.rb +1 -1
- data/lib/ask/rails.rb +1 -70
- metadata +7 -78
- data/lib/ask/rails/configuration.rb +0 -19
- data/lib/ask/rails/engine.rb +0 -11
- data/lib/ask/rails/persistence.rb +0 -35
- data/lib/ask/rails/service_discovery.rb +0 -48
- data/lib/ask/rails/tool.rb +0 -11
- data/lib/ask/rails/tools/query_database.rb +0 -72
- data/lib/ask/rails/tools/read_file.rb +0 -24
- data/lib/ask/rails/tools/read_log.rb +0 -118
- data/lib/ask/rails/tools/read_model.rb +0 -73
- data/lib/ask/rails/tools/read_routes.rb +0 -21
- data/lib/ask/rails/tools/run_command.rb +0 -20
- data/lib/ask/rails/tools/search_codebase.rb +0 -22
- data/lib/ask/skills/rails.db_debug/SKILL.md +0 -118
- data/lib/ask/skills/rails.deploy_pipeline/SKILL.md +0 -125
- data/lib/ask/skills/rails.route_trouble/SKILL.md +0 -127
- data/lib/generators/ask/rails/install/install_generator.rb +0 -29
- data/lib/generators/ask/rails/install/templates/initializer.rb +0 -5
- data/lib/generators/ask/rails/install/templates/migration.rb +0 -12
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1a8258ca96d9513529bc1c0c9c54bd8e2492a110e48d90c9af3f53ca3aa24d9f
|
|
4
|
+
data.tar.gz: 4a776f46230d7a87719d5a6e12154e90987f71f60af63707da686ba2cce20377
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 894f5146923889fd014f1ac770c52eba2cfdc6d84fd546062c05ac85473f6e716e70a298761f25a19ea1b00ba60461aae3ab38889c05a95698d891320879cc86
|
|
7
|
+
data.tar.gz: d58b94569c064b58493bd0a929cfb1dde3310a43c110c92474947c57e711f5a4e6d57ca596c389e73fcb4ee6bddeff7e8797bc5915ca8e4cbf94eadaf5f2353d
|
data/CHANGELOG.md
CHANGED
|
@@ -1,35 +1,7 @@
|
|
|
1
|
-
## [0.
|
|
2
|
-
|
|
3
|
-
### Changed
|
|
4
|
-
- Expanded tests: Persistence(7t), Configuration(7t), ServiceDiscovery(5t), Engine(7t), InstallGenerator(7t), Tools(24t with live DB). Infrastructure: rubocop, overcommit, CI matrix, Appraisals, gemspec.
|
|
5
|
-
## 0.2.4 (2026-06-21)
|
|
1
|
+
## [0.1.0] — 2026-07-26
|
|
6
2
|
|
|
7
3
|
### Added
|
|
8
|
-
- `Ask::Rails::Engine` — Rails engine for autoloading and generator discovery
|
|
9
|
-
- Skills directory with methodology skills (rails.db_debug, rails.deploy_pipeline, rails.route_trouble)
|
|
10
|
-
- Gemspec metadata for Rubygems discovery
|
|
11
|
-
|
|
12
|
-
# Changelog
|
|
13
4
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
- `Ask::Rails::QueryDatabase` — read-only SQL queries via ActiveRecord with auto-LIMIT,
|
|
18
|
-
binary column handling, and production write guards
|
|
19
|
-
- `Ask::Rails::ReadModel` — structured model introspection returning columns, associations,
|
|
20
|
-
validators, and primary keys; supports detail filtering
|
|
21
|
-
- `Ask::Rails::ReadLog` — filtered log reading that tail-reads from end of file, supports
|
|
22
|
-
level filtering (ERROR/WARN/INFO/DEBUG), case-insensitive search, and automatically
|
|
23
|
-
detects log rotation files
|
|
24
|
-
|
|
25
|
-
## 0.1.0 (2026-06-10)
|
|
26
|
-
|
|
27
|
-
### Added
|
|
28
|
-
- Railtie — `Ask::Rails::Railtie` configures and discovers tools/services on boot
|
|
29
|
-
- Configuration — `Ask::Rails::Configuration` with `default_model`, `max_turns`, `system_prompt`, `tool_concurrency`
|
|
30
|
-
- Session Factory — `Ask::Rails.agent_session` creates pre-configured `Ask::Agent::Session`
|
|
31
|
-
- Service Discovery — auto-discovers installed `ask-*` service gems, injects context into system prompt
|
|
32
|
-
- AR Persistence — `Ask::Rails::Persistence` saves/loads session state to database
|
|
33
|
-
- Rails Tools — `ReadFile`, `RunCommand`, `SearchCodebase`, `ReadRoutes` (Rails.root-aware)
|
|
34
|
-
- Generators — `rails generate ask_rails:install` creates migration, initializer, `app/tools/`
|
|
35
|
-
- Dependencies: rails >= 7.1, ask-tools, ask-tools-shell, ask-agent, ask-auth
|
|
5
|
+
- Initial release of `ask-rails` — Rails integration for the ask-rb ecosystem.
|
|
6
|
+
- **Install generator** — `rails generate ask:install` creates `config/initializers/ask.rb`, `app/agents/application_agent.rb`, and `app/agents/` directory.
|
|
7
|
+
- **Railtie** — Wires `Ask::Agent.logger` to `Rails.logger`, discovers agent definitions in `app/agents/`.
|
data/README.md
CHANGED
|
@@ -1,34 +1,59 @@
|
|
|
1
1
|
# ask-rails
|
|
2
2
|
|
|
3
|
-
Rails integration for the ask-rb ecosystem.
|
|
4
|
-
the ask-rb stack — provides a Railtie, AR session persistence, a session factory,
|
|
5
|
-
automatic service gem discovery, and generators.
|
|
3
|
+
Rails integration for the [ask-rb](https://github.com/ask-rb) ecosystem. Provides generators, file conventions, and railtie for using AI agents in your Rails app.
|
|
6
4
|
|
|
7
5
|
## Installation
|
|
8
6
|
|
|
9
7
|
```bash
|
|
10
8
|
bundle add ask-rails
|
|
11
|
-
rails generate
|
|
9
|
+
rails generate ask:install
|
|
12
10
|
```
|
|
13
11
|
|
|
12
|
+
This creates:
|
|
13
|
+
- `config/initializers/ask.rb` — agent configuration
|
|
14
|
+
- `app/agents/application_agent.rb` — base class for your agents
|
|
15
|
+
- `app/agents/` — directory for agent definitions
|
|
16
|
+
|
|
14
17
|
## Usage
|
|
15
18
|
|
|
19
|
+
Define an agent:
|
|
20
|
+
|
|
16
21
|
```ruby
|
|
17
|
-
#
|
|
18
|
-
|
|
19
|
-
|
|
22
|
+
# app/agents/support_bot.rb
|
|
23
|
+
class Agents::SupportBot < ApplicationAgent
|
|
24
|
+
model "gpt-4o"
|
|
25
|
+
system_prompt "You help users with support questions."
|
|
26
|
+
|
|
27
|
+
tool :bash
|
|
28
|
+
tool :read
|
|
29
|
+
tool :grep
|
|
30
|
+
end
|
|
20
31
|
```
|
|
21
32
|
|
|
22
|
-
|
|
23
|
-
|
|
33
|
+
Run it:
|
|
34
|
+
|
|
35
|
+
```ruby
|
|
36
|
+
agent = Ask::Agent.new("support_bot")
|
|
37
|
+
response = agent.run("Find all open issues in the codebase")
|
|
38
|
+
puts response
|
|
39
|
+
```
|
|
24
40
|
|
|
25
|
-
|
|
41
|
+
Or use `Ask.chat` for one-off conversations:
|
|
26
42
|
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
bundle exec rake test
|
|
43
|
+
```ruby
|
|
44
|
+
Ask.chat("Summarize this article: #{text}")
|
|
30
45
|
```
|
|
31
46
|
|
|
47
|
+
## Configuration
|
|
48
|
+
|
|
49
|
+
API keys are resolved automatically by `Ask::Auth`:
|
|
50
|
+
|
|
51
|
+
- **Environment variables:** `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, etc.
|
|
52
|
+
- **Rails credentials:** `rails credentials:edit` → add `ask.openai`, `ask.anthropic`
|
|
53
|
+
- **File:** `~/.ask/credentials.yml`
|
|
54
|
+
|
|
55
|
+
No manual credential setup is required.
|
|
56
|
+
|
|
32
57
|
## License
|
|
33
58
|
|
|
34
59
|
MIT
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rails/generators"
|
|
4
|
+
|
|
5
|
+
module Ask
|
|
6
|
+
module Rails
|
|
7
|
+
module Generators
|
|
8
|
+
class InstallGenerator < ::Rails::Generators::Base
|
|
9
|
+
source_root File.expand_path("templates", __dir__)
|
|
10
|
+
|
|
11
|
+
desc "Sets up ask-rb for Rails — creates initializer and app/agents/ directory"
|
|
12
|
+
|
|
13
|
+
def create_initializer
|
|
14
|
+
template "initializer.rb", "config/initializers/ask.rb"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def create_application_agent
|
|
18
|
+
template "application_agent.rb", "app/agents/application_agent.rb"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def create_agents_directory
|
|
22
|
+
empty_directory "app/agents"
|
|
23
|
+
create_file "app/agents/.keep", "" unless options[:skip_keep]
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Base class for your application's AI agents.
|
|
4
|
+
#
|
|
5
|
+
# Subclass this to define agents:
|
|
6
|
+
#
|
|
7
|
+
# class Agents::SupportBot < ApplicationAgent
|
|
8
|
+
# model "gpt-4o"
|
|
9
|
+
# system_prompt "You help users with support questions."
|
|
10
|
+
#
|
|
11
|
+
# tool :search_knowledge_base
|
|
12
|
+
# end
|
|
13
|
+
#
|
|
14
|
+
# Then run:
|
|
15
|
+
# agent = Ask::Agent.new("support_bot")
|
|
16
|
+
# agent.run("How do I reset my password?")
|
|
17
|
+
#
|
|
18
|
+
class ApplicationAgent < Ask::Agent::Definition
|
|
19
|
+
# Default instructions — override in subclasses
|
|
20
|
+
system_prompt "You are a helpful assistant."
|
|
21
|
+
|
|
22
|
+
# Uncomment to add built-in tools:
|
|
23
|
+
# tool :bash
|
|
24
|
+
# tool :read
|
|
25
|
+
# tool :grep
|
|
26
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Ask Agent Configuration
|
|
4
|
+
# ========================
|
|
5
|
+
#
|
|
6
|
+
# API keys are resolved automatically by Ask::Auth:
|
|
7
|
+
# - Environment variables: OPENAI_API_KEY, ANTHROPIC_API_KEY, etc.
|
|
8
|
+
# - Rails credentials: rails credentials:edit → ask.openai, ask.anthropic
|
|
9
|
+
# - ~/.ask/credentials.yml
|
|
10
|
+
#
|
|
11
|
+
# See https://github.com/ask-rb/ask-auth for details.
|
|
12
|
+
|
|
13
|
+
Ask::Agent.configure do |config|
|
|
14
|
+
# config.default_model = "gpt-4o"
|
|
15
|
+
end
|
data/lib/ask/rails/railtie.rb
CHANGED
|
@@ -3,25 +3,8 @@
|
|
|
3
3
|
module Ask
|
|
4
4
|
module Rails
|
|
5
5
|
class Railtie < ::Rails::Railtie
|
|
6
|
-
rake_tasks do
|
|
7
|
-
# Load rake tasks if any
|
|
8
|
-
end
|
|
9
|
-
|
|
10
6
|
generators do
|
|
11
|
-
require_relative "
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
initializer "ask_rails.configure" do |app|
|
|
15
|
-
Ask::Rails.configuration.default_model ||= ENV["ASK_DEFAULT_MODEL"] || "gpt-4o"
|
|
16
|
-
Ask::Rails.configuration.max_turns ||= (ENV["ASK_MAX_TURNS"] || 25).to_i
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
initializer "ask_rails.discover_tools", after: :eager_load_most do
|
|
20
|
-
Ask::Rails.discover_tools!
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
initializer "ask_rails.discover_services", after: :eager_load_most do
|
|
24
|
-
Ask::Rails::ServiceDiscovery.discover!
|
|
7
|
+
require_relative "generators/install/install_generator"
|
|
25
8
|
end
|
|
26
9
|
end
|
|
27
10
|
end
|
data/lib/ask/rails/version.rb
CHANGED
data/lib/ask/rails.rb
CHANGED
|
@@ -1,80 +1,11 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "rails"
|
|
4
3
|
require "ask/agent"
|
|
5
|
-
require "ask/auth"
|
|
6
4
|
|
|
7
5
|
module Ask
|
|
8
6
|
module Rails
|
|
9
|
-
class << self
|
|
10
|
-
def configure
|
|
11
|
-
yield configuration
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def configuration
|
|
15
|
-
@configuration ||= Configuration.new
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def agent_session(**extra)
|
|
19
|
-
tools = configuration.tools.map { |t| t.is_a?(Class) ? t.new : t }
|
|
20
|
-
prompt = extra.delete(:system_prompt) || configuration.system_prompt || default_system_prompt
|
|
21
|
-
|
|
22
|
-
Ask::Agent::Session.new(
|
|
23
|
-
model: configuration.default_model,
|
|
24
|
-
max_turns: configuration.max_turns,
|
|
25
|
-
system_prompt: prompt,
|
|
26
|
-
tools: tools,
|
|
27
|
-
persistence: configuration.persistence_adapter,
|
|
28
|
-
**extra
|
|
29
|
-
)
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
def discover_tools!
|
|
33
|
-
self.configuration.tools = Ask::Tools::Shell::TOOLS.map(&:new) + discovered_rails_tools
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def root
|
|
37
|
-
@root ||= Pathname.new(File.expand_path("..", __dir__))
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
private
|
|
41
|
-
|
|
42
|
-
def discovered_rails_tools
|
|
43
|
-
tools = []
|
|
44
|
-
files = Dir[::Rails.root.join("app", "tools", "*.rb")]
|
|
45
|
-
files.each do |f|
|
|
46
|
-
require f
|
|
47
|
-
klass = File.basename(f, ".rb").camelize.constantize rescue next
|
|
48
|
-
tools << klass if klass < Ask::Rails::Tool
|
|
49
|
-
end
|
|
50
|
-
tools
|
|
51
|
-
rescue
|
|
52
|
-
tools
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
def default_system_prompt
|
|
56
|
-
<<~PROMPT
|
|
57
|
-
You are a Ruby on Rails software engineer.
|
|
58
|
-
You have direct access to the application's code, database, and runtime.
|
|
59
|
-
Use your tools to inspect and modify the codebase.
|
|
60
|
-
Once you have enough information, stop calling tools and give your answer.
|
|
61
|
-
PROMPT
|
|
62
|
-
end
|
|
63
|
-
end
|
|
64
7
|
end
|
|
65
8
|
end
|
|
66
9
|
|
|
67
10
|
require_relative "rails/version"
|
|
68
|
-
require_relative "rails/
|
|
69
|
-
require_relative "rails/configuration"
|
|
70
|
-
require_relative "rails/railtie"
|
|
71
|
-
require_relative "rails/persistence"
|
|
72
|
-
require_relative "rails/service_discovery"
|
|
73
|
-
require_relative "rails/tool"
|
|
74
|
-
require_relative "rails/tools/read_file"
|
|
75
|
-
require_relative "rails/tools/run_command"
|
|
76
|
-
require_relative "rails/tools/search_codebase"
|
|
77
|
-
require_relative "rails/tools/read_routes"
|
|
78
|
-
require_relative "rails/tools/query_database"
|
|
79
|
-
require_relative "rails/tools/read_model"
|
|
80
|
-
require_relative "rails/tools/read_log"
|
|
11
|
+
require_relative "rails/railtie" if defined?(::Rails::Railtie)
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ask-rails
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Kaka Ruto
|
|
@@ -23,34 +23,6 @@ dependencies:
|
|
|
23
23
|
- - ">="
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
25
|
version: '7.1'
|
|
26
|
-
- !ruby/object:Gem::Dependency
|
|
27
|
-
name: ask-tools
|
|
28
|
-
requirement: !ruby/object:Gem::Requirement
|
|
29
|
-
requirements:
|
|
30
|
-
- - ">="
|
|
31
|
-
- !ruby/object:Gem::Version
|
|
32
|
-
version: '0.1'
|
|
33
|
-
type: :runtime
|
|
34
|
-
prerelease: false
|
|
35
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
-
requirements:
|
|
37
|
-
- - ">="
|
|
38
|
-
- !ruby/object:Gem::Version
|
|
39
|
-
version: '0.1'
|
|
40
|
-
- !ruby/object:Gem::Dependency
|
|
41
|
-
name: ask-tools-shell
|
|
42
|
-
requirement: !ruby/object:Gem::Requirement
|
|
43
|
-
requirements:
|
|
44
|
-
- - ">="
|
|
45
|
-
- !ruby/object:Gem::Version
|
|
46
|
-
version: '0.1'
|
|
47
|
-
type: :runtime
|
|
48
|
-
prerelease: false
|
|
49
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
-
requirements:
|
|
51
|
-
- - ">="
|
|
52
|
-
- !ruby/object:Gem::Version
|
|
53
|
-
version: '0.1'
|
|
54
26
|
- !ruby/object:Gem::Dependency
|
|
55
27
|
name: ask-agent
|
|
56
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -65,34 +37,6 @@ dependencies:
|
|
|
65
37
|
- - ">="
|
|
66
38
|
- !ruby/object:Gem::Version
|
|
67
39
|
version: '0.1'
|
|
68
|
-
- !ruby/object:Gem::Dependency
|
|
69
|
-
name: ask-auth
|
|
70
|
-
requirement: !ruby/object:Gem::Requirement
|
|
71
|
-
requirements:
|
|
72
|
-
- - ">="
|
|
73
|
-
- !ruby/object:Gem::Version
|
|
74
|
-
version: '0.1'
|
|
75
|
-
type: :runtime
|
|
76
|
-
prerelease: false
|
|
77
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
78
|
-
requirements:
|
|
79
|
-
- - ">="
|
|
80
|
-
- !ruby/object:Gem::Version
|
|
81
|
-
version: '0.1'
|
|
82
|
-
- !ruby/object:Gem::Dependency
|
|
83
|
-
name: sqlite3
|
|
84
|
-
requirement: !ruby/object:Gem::Requirement
|
|
85
|
-
requirements:
|
|
86
|
-
- - ">="
|
|
87
|
-
- !ruby/object:Gem::Version
|
|
88
|
-
version: '2.0'
|
|
89
|
-
type: :development
|
|
90
|
-
prerelease: false
|
|
91
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
92
|
-
requirements:
|
|
93
|
-
- - ">="
|
|
94
|
-
- !ruby/object:Gem::Version
|
|
95
|
-
version: '2.0'
|
|
96
40
|
- !ruby/object:Gem::Dependency
|
|
97
41
|
name: minitest
|
|
98
42
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -135,8 +79,8 @@ dependencies:
|
|
|
135
79
|
- - "~>"
|
|
136
80
|
- !ruby/object:Gem::Version
|
|
137
81
|
version: '13.0'
|
|
138
|
-
description:
|
|
139
|
-
|
|
82
|
+
description: Rails generators, file conventions, and railtie for using ask-agent in
|
|
83
|
+
Rails apps.
|
|
140
84
|
email:
|
|
141
85
|
- kaka@myrrlabs.com
|
|
142
86
|
executables: []
|
|
@@ -148,33 +92,18 @@ files:
|
|
|
148
92
|
- README.md
|
|
149
93
|
- lib/ask-rails.rb
|
|
150
94
|
- lib/ask/rails.rb
|
|
151
|
-
- lib/ask/rails/
|
|
152
|
-
- lib/ask/rails/
|
|
153
|
-
- lib/ask/rails/
|
|
95
|
+
- lib/ask/rails/generators/install/install_generator.rb
|
|
96
|
+
- lib/ask/rails/generators/install/templates/application_agent.rb
|
|
97
|
+
- lib/ask/rails/generators/install/templates/initializer.rb
|
|
154
98
|
- lib/ask/rails/railtie.rb
|
|
155
|
-
- lib/ask/rails/service_discovery.rb
|
|
156
|
-
- lib/ask/rails/tool.rb
|
|
157
|
-
- lib/ask/rails/tools/query_database.rb
|
|
158
|
-
- lib/ask/rails/tools/read_file.rb
|
|
159
|
-
- lib/ask/rails/tools/read_log.rb
|
|
160
|
-
- lib/ask/rails/tools/read_model.rb
|
|
161
|
-
- lib/ask/rails/tools/read_routes.rb
|
|
162
|
-
- lib/ask/rails/tools/run_command.rb
|
|
163
|
-
- lib/ask/rails/tools/search_codebase.rb
|
|
164
99
|
- lib/ask/rails/version.rb
|
|
165
|
-
- lib/ask/skills/rails.db_debug/SKILL.md
|
|
166
|
-
- lib/ask/skills/rails.deploy_pipeline/SKILL.md
|
|
167
|
-
- lib/ask/skills/rails.route_trouble/SKILL.md
|
|
168
|
-
- lib/generators/ask/rails/install/install_generator.rb
|
|
169
|
-
- lib/generators/ask/rails/install/templates/initializer.rb
|
|
170
|
-
- lib/generators/ask/rails/install/templates/migration.rb
|
|
171
100
|
homepage: https://github.com/ask-rb/ask-rails
|
|
172
101
|
licenses:
|
|
173
102
|
- MIT
|
|
174
103
|
metadata:
|
|
175
104
|
homepage_uri: https://github.com/ask-rb/ask-rails
|
|
176
105
|
source_code_uri: https://github.com/ask-rb/ask-rails
|
|
177
|
-
changelog_uri: https://github.com/ask-rb/ask-rails/blob/
|
|
106
|
+
changelog_uri: https://github.com/ask-rb/ask-rails/blob/main/CHANGELOG.md
|
|
178
107
|
rdoc_options: []
|
|
179
108
|
require_paths:
|
|
180
109
|
- lib
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Ask
|
|
4
|
-
module Rails
|
|
5
|
-
class Configuration
|
|
6
|
-
attr_accessor :default_model, :max_turns, :system_prompt,
|
|
7
|
-
:tool_concurrency, :persistence_adapter, :tools
|
|
8
|
-
|
|
9
|
-
def initialize
|
|
10
|
-
@default_model = "gpt-4o"
|
|
11
|
-
@max_turns = 25
|
|
12
|
-
@system_prompt = nil
|
|
13
|
-
@tool_concurrency = 5
|
|
14
|
-
@persistence_adapter = nil
|
|
15
|
-
@tools = []
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
end
|
data/lib/ask/rails/engine.rb
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Ask
|
|
4
|
-
module Rails
|
|
5
|
-
class Persistence
|
|
6
|
-
def initialize(model_class: nil)
|
|
7
|
-
@model_class = model_class
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
def save(session_id, data)
|
|
11
|
-
record = model_class.find_or_initialize_by(session_id: session_id)
|
|
12
|
-
record.update!(data: data)
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def load(session_id)
|
|
16
|
-
record = model_class.find_by(session_id: session_id)
|
|
17
|
-
record&.data
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def delete(session_id)
|
|
21
|
-
model_class.where(session_id: session_id).delete_all
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def list
|
|
25
|
-
model_class.pluck(:session_id)
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
private
|
|
29
|
-
|
|
30
|
-
def model_class
|
|
31
|
-
@model_class || (raise "No model class configured. Use Persistence.new(model_class: MyModel)")
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
end
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Ask
|
|
4
|
-
module Rails
|
|
5
|
-
module ServiceDiscovery
|
|
6
|
-
SERVICE_GEMS_PATTERN = /\Aask-(?!tools|tools-shell|agent|rails|core|auth|schema|llm)/
|
|
7
|
-
|
|
8
|
-
module_function
|
|
9
|
-
|
|
10
|
-
def discover!
|
|
11
|
-
service_gems = Gem.loaded_specs.keys.select { |name| name.match?(SERVICE_GEMS_PATTERN) }
|
|
12
|
-
contexts = []
|
|
13
|
-
|
|
14
|
-
service_gems.each do |name|
|
|
15
|
-
begin
|
|
16
|
-
require "#{name.tr("-", "/")}/context"
|
|
17
|
-
mod = name.split("-").map(&:capitalize).join.constantize
|
|
18
|
-
contexts << mod if mod.respond_to?(:const_defined?) && mod.const_defined?(:DESCRIPTION)
|
|
19
|
-
rescue LoadError, NameError
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
unless contexts.empty?
|
|
24
|
-
prompt = build_system_prompt(contexts)
|
|
25
|
-
existing = Ask::Rails.configuration.system_prompt
|
|
26
|
-
Ask::Rails.configuration.system_prompt = [existing, prompt].compact.join("\n\n")
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
contexts
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
def build_system_prompt(contexts)
|
|
33
|
-
sections = ["## Available Services"]
|
|
34
|
-
|
|
35
|
-
contexts.each do |mod|
|
|
36
|
-
name = mod.respond_to?(:name) ? mod.name.to_s.split("::").last || "Unknown" : "Unknown"
|
|
37
|
-
sections << "### #{name}"
|
|
38
|
-
sections << mod::DESCRIPTION if mod.const_defined?(:DESCRIPTION)
|
|
39
|
-
sections << "Documentation: #{mod::DOCS_URL}" if mod.const_defined?(:DOCS_URL)
|
|
40
|
-
sections << "Authentication: #{mod::AUTH_HOW}" if mod.const_defined?(:AUTH_HOW)
|
|
41
|
-
sections << ""
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
sections.join("\n")
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
end
|
data/lib/ask/rails/tool.rb
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Ask
|
|
4
|
-
module Rails
|
|
5
|
-
module Tools
|
|
6
|
-
class QueryDatabase < Ask::Rails::Tool
|
|
7
|
-
description "Run a read-only SQL query against the application database. " \
|
|
8
|
-
"Returns columns and rows. Only SELECT queries are allowed in production."
|
|
9
|
-
|
|
10
|
-
param :sql, type: :string, desc: "SQL query (SELECT only in production)", required: true
|
|
11
|
-
param :limit, type: :integer, desc: "Max rows to return (default 50)", required: false
|
|
12
|
-
|
|
13
|
-
WRITE_STATEMENTS = /\A\s*(INSERT|UPDATE|DELETE|DROP|TRUNCATE|ALTER|CREATE|GRANT|REVOKE)\b/i
|
|
14
|
-
|
|
15
|
-
def execute(sql:, limit: 50)
|
|
16
|
-
sql = sql.strip
|
|
17
|
-
|
|
18
|
-
if WRITE_STATEMENTS.match?(sql)
|
|
19
|
-
return Ask::Result.failure(
|
|
20
|
-
"Only SELECT queries are allowed. Write statements (#{sql.match(WRITE_STATEMENTS)[1]}) are rejected in all environments."
|
|
21
|
-
)
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
if ::Rails.env.production? && !sql.match?(/\A\s*SELECT\b/i)
|
|
25
|
-
return Ask::Result.failure(
|
|
26
|
-
"Only SELECT queries are allowed in the production environment."
|
|
27
|
-
)
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
pool = ActiveRecord::Base.connection_pool
|
|
31
|
-
pool.with_connection do |conn|
|
|
32
|
-
limited_sql = sql.match?(/\bLIMIT\b/i) ? sql : "#{sql.chomp(';')} LIMIT #{limit.to_i}"
|
|
33
|
-
result = conn.exec_query(limited_sql)
|
|
34
|
-
columns = result.columns
|
|
35
|
-
rows = result.rows.first(limit.to_i).map { |row| build_row(row, columns) }
|
|
36
|
-
{
|
|
37
|
-
columns: columns,
|
|
38
|
-
rows: rows,
|
|
39
|
-
count: rows.size,
|
|
40
|
-
truncated: result.rows.size > limit.to_i
|
|
41
|
-
}
|
|
42
|
-
end
|
|
43
|
-
rescue ActiveRecord::StatementInvalid => e
|
|
44
|
-
Ask::Result.failure("SQL error: #{e.message}")
|
|
45
|
-
rescue ActiveRecord::ConnectionNotEstablished => e
|
|
46
|
-
Ask::Result.failure("Database not connected: #{e.message}. Verify the database is running and Rails is connected.")
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
private
|
|
50
|
-
|
|
51
|
-
def build_row(row, columns)
|
|
52
|
-
columns.each_with_index.each_with_object({}) do |(col, i), hash|
|
|
53
|
-
value = row[i]
|
|
54
|
-
hash[col] = sanitize_value(value)
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
def sanitize_value(value)
|
|
59
|
-
return "[BINARY DATA]" if binary_value?(value)
|
|
60
|
-
return value.iso8601 if value.respond_to?(:iso8601)
|
|
61
|
-
value
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
def binary_value?(value)
|
|
65
|
-
value.is_a?(String) && value.encoding == Encoding::ASCII_8BIT && value.bytesize > 0
|
|
66
|
-
rescue
|
|
67
|
-
false
|
|
68
|
-
end
|
|
69
|
-
end
|
|
70
|
-
end
|
|
71
|
-
end
|
|
72
|
-
end
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Ask
|
|
4
|
-
module Rails
|
|
5
|
-
module Tools
|
|
6
|
-
class ReadFile < Ask::Rails::Tool
|
|
7
|
-
description "Read a file from the Rails app. Paths are relative to Rails.root."
|
|
8
|
-
|
|
9
|
-
param :path, type: :string, desc: "Relative path from Rails.root", required: true
|
|
10
|
-
|
|
11
|
-
def execute(path:)
|
|
12
|
-
full_path = rails_root.join(path)
|
|
13
|
-
return Ask::Result.error(message: "File not found: #{path}") unless full_path.exist?
|
|
14
|
-
|
|
15
|
-
content = full_path.read
|
|
16
|
-
Ask::Result.success(
|
|
17
|
-
data: { path: path, content: content, size: content.length },
|
|
18
|
-
metadata: { path: path, size: content.length }
|
|
19
|
-
)
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
end
|