ask-rails 0.6.0 → 0.7.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: 87296c9e940bcd34d48e640c3a13c3e3d634b57abf253c434d0919b1dc3388bc
4
- data.tar.gz: b8edd3def1dfa96b41d6af0dd842bebb724ac9909c8728d5c8a193a3956e83be
3
+ metadata.gz: 805ea4f5713b8cfacc7f25c54b6229b788199ddba9ab1dc5a50c4719a834f256
4
+ data.tar.gz: da2648a6027373d0c65f37786c347e6fda211d6f43a38378042acb8dae1a7ca8
5
5
  SHA512:
6
- metadata.gz: 4533e9675014317d48c973bcfa23dd30a996d24f9f5e734060c37250735cdf0569df6b38ed2bb60c3a6c6d0dfdb8cf814869d5b628a9f0e37a8f5f91616f8347
7
- data.tar.gz: 13fc4f80420ad209ab5e531d254883858acb6e8ac28d7806bac514afcc58c278df79a3c7026dfa69a49f20fbd70fa7ef0ac5ecada3255afedb3d23c338dcff2d
6
+ metadata.gz: 02e6b7d1dca1617b4070e9068cb6be162040756119ef1dbdab793ec27b1cb1aaa33a46eb88d7dcc9c9734e3b3c570172f816290f2629be0a09c8cdef041a88e9
7
+ data.tar.gz: bedabfd712c7397baf254aecaf8c2c2316dfb47964303d4b91437e9ef53dcf187a31fccdc406e8b5434de5029d657179845d31044de8e2ee148abff0baef8063
data/CHANGELOG.md CHANGED
@@ -1,3 +1,68 @@
1
+ ## [0.7.0] — 2026-07-31
2
+
3
+ ### Added
4
+
5
+ - **`ask:workflow NAME` generator** — scaffolds a workflow module under `app/workflows/<name>/` with `workflow.rb` and `steps/` directory. Requires ask-graph; aborts with a helpful message if it's not installed.
6
+
7
+ - **`ask:agent NAME` generator** — scaffolds an individual agent under `app/agents/`.
8
+
9
+ - **ask-graph support in install generator** — `ask:install` now creates `app/workflows/application_workflow.rb` and the workflows directory when ask-graph is installed. Pass `--skip-graph` to skip. The initializer's graph configuration block is only generated when ask-graph is present:
10
+
11
+ ```ruby
12
+ if defined?(Ask::Graph)
13
+ Ask::Graph.storage = ASK_STATE
14
+ end
15
+ ```
16
+
17
+ ### Changed
18
+
19
+ - Shared `ask_state` table is explicitly documented as serving both agent sessions and workflow checkpoints.
20
+
21
+ ### Tested
22
+
23
+ - 11 generator tests, 51 assertions, 0 failures.
24
+
25
+ ## [0.7.0] — 2026-07-31
26
+
27
+ ### Added
28
+
29
+ - **`ask:agent NAME` generator** — scaffolds an individual agent under `app/agents/`:
30
+
31
+ ```bash
32
+ rails generate ask:agent support_bot
33
+ ```
34
+
35
+ - **`ask:workflow NAME` generator** — scaffolds a workflow module under `app/workflows/<name>/` with `workflow.rb` and `steps/` directory. Requires ask-graph; aborts with a helpful message if it's not installed:
36
+
37
+ ```bash
38
+ rails generate ask:workflow notify_customer
39
+ ```
40
+
41
+ - **`Ask::Rails::State`** — ActiveRecord-backed state adapter for the `ask_state` table. Used by ask-graph for workflow checkpoints. Works with any database adapter (PostgreSQL, MySQL, SQLite). Implements key-value storage plus ordered lists (for agent session indexes).
42
+
43
+ - **ask-graph support in install generator** — `ask:install` now creates `app/workflows/application_workflow.rb` and the workflows directory when ask-graph is installed. Pass `--skip-graph` to skip. The initializer's graph block is only generated when ask-graph is present:
44
+
45
+ ```ruby
46
+ if defined?(Ask::Graph)
47
+ Ask::Graph.storage = Ask::Rails::State.new
48
+ end
49
+ ```
50
+
51
+ ### Changed
52
+
53
+ - **Generators consolidated under `lib/generators/ask/`** — all three generators (`ask:install`, `ask:agent`, `ask:workflow`) now live at the standard Rails discovery path. The old railtie-registered `ask:rails:*` names and the duplicate `lib/generators/ask/install_generator.rb` were removed. No duplicated work between generators: `ask:install` owns one-time setup, `ask:agent`/`ask:workflow` own per-component scaffolding.
54
+
55
+ - **Initializer fixed to use real APIs** — removed references to non-existent `Ask::State::PostgreSQL` and `config.state`. The agent block now only configures what ask-agent supports (audit log, default model).
56
+
57
+ - **State migration uses `t.json` instead of `t.jsonb`** — works on PostgreSQL, MySQL, and SQLite.
58
+
59
+ - **`migration_version` fix** — generated migrations now produce `ActiveRecord::Migration[8.1]` instead of the broken `Migration[[8.1]]`.
60
+
61
+ ### Tested
62
+
63
+ - 24 tests, 67 assertions, 0 failures — including 13 tests for `Ask::Rails::State` against an in-memory SQLite database.
64
+ - End-to-end smoke test in a fresh Rails app: `ask:install`, `ask:agent`, `ask:workflow` all run; migrations execute; a workflow checkpoint survives a second run via `Ask::Rails::State`.
65
+
1
66
  ## [0.6.0] — 2026-07-29
2
67
 
3
68
  ### Added
data/README.md CHANGED
@@ -1,36 +1,99 @@
1
1
  # ask-rails
2
2
 
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.
3
+ Rails integration for the [ask-rb](https://github.com/ask-rb) ecosystem. Provides generators, file conventions, and a railtie for building agents and workflows in your Rails app.
4
4
 
5
5
  ## Installation
6
6
 
7
+ Add to your Gemfile:
8
+
9
+ ```ruby
10
+ gem "ask-rails"
11
+ gem "ask-graph" # optional — add only if you use workflows
12
+ ```
13
+
14
+ Run the installer:
15
+
7
16
  ```bash
8
- bundle add ask-rails
17
+ bundle install
9
18
  rails generate ask:install
10
19
  ```
11
20
 
12
21
  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
22
 
17
- ## Usage
23
+ | File | Purpose |
24
+ |---|---|
25
+ | `config/initializers/ask.rb` | Agent + workflow configuration (graph block only generated when ask-graph is installed) |
26
+ | `app/agents/application_agent.rb` | Base class for your agents |
27
+ | `app/workflows/application_workflow.rb` | Base class for your workflows (only with ask-graph) |
28
+ | `db/migrate/*_create_ask_state.rb` | Shared key-value state table — workflow checkpoints and agent session indexes |
29
+ | `db/migrate/*_create_ask_audit_logs.rb` | Agent session audit log |
18
30
 
19
- Define an agent:
31
+ The `ask_state` table is backed by `Ask::Rails::State` — an ActiveRecord adapter that works with any database (PostgreSQL, MySQL, SQLite). Workflow checkpoints and agent session persistence share the same table, keyed by convention.
32
+
33
+ ## Generators
34
+
35
+ ### `ask:agent NAME`
36
+
37
+ Scaffolds a new agent:
38
+
39
+ ```bash
40
+ rails generate ask:agent support_bot
41
+ ```
42
+
43
+ Creates `app/agents/support_bot.rb`:
20
44
 
21
45
  ```ruby
22
- # app/agents/support_bot.rb
23
- class Agents::SupportBot < ApplicationAgent
24
- model "gpt-4o"
25
- system_prompt "You help users with support questions."
46
+ module Agents
47
+ class SupportBot < ApplicationAgent
48
+ system_prompt "You are a helpful assistant."
49
+ end
50
+ end
51
+ ```
52
+
53
+ ### `ask:workflow NAME`
54
+
55
+ Scaffolds a new workflow (requires ask-graph):
26
56
 
27
- tool :bash
28
- tool :read
29
- tool :grep
57
+ ```bash
58
+ rails generate ask:workflow notify_customer
59
+ ```
60
+
61
+ Creates `app/workflows/notify_customer/workflow.rb` and `app/workflows/notify_customer/steps/`:
62
+
63
+ ```ruby
64
+ module NotifyCustomer
65
+ class Workflow < ApplicationWorkflow
66
+ # step SomeStep
67
+ end
30
68
  end
31
69
  ```
32
70
 
33
- Run it:
71
+ ### Skipping workflow scaffolding
72
+
73
+ If you don't use ask-graph, install with:
74
+
75
+ ```bash
76
+ rails generate ask:install --skip-graph
77
+ ```
78
+
79
+ The initializer still works — the graph block is omitted when ask-graph isn't installed.
80
+
81
+ ## Usage
82
+
83
+ ### Agents
84
+
85
+ ```ruby
86
+ # app/agents/support_bot.rb
87
+ module Agents
88
+ class SupportBot < ApplicationAgent
89
+ model "gpt-4o"
90
+ system_prompt "You help users with support questions."
91
+
92
+ tool :bash
93
+ tool :read
94
+ end
95
+ end
96
+ ```
34
97
 
35
98
  ```ruby
36
99
  agent = Ask::Agent.new("support_bot")
@@ -38,12 +101,37 @@ response = agent.run("Find all open issues in the codebase")
38
101
  puts response
39
102
  ```
40
103
 
41
- Or use `Ask.chat` for one-off conversations:
104
+ ### Workflows
42
105
 
43
106
  ```ruby
44
- Ask.chat("Summarize this article: #{text}")
107
+ # app/workflows/order_fulfillment/workflow.rb
108
+ module OrderFulfillment
109
+ class Workflow < ApplicationWorkflow
110
+ step ValidatePayment
111
+ step NotifyCustomer
112
+ step ShipOrder
113
+ end
114
+ end
45
115
  ```
46
116
 
117
+ ```ruby
118
+ # app/workflows/order_fulfillment/steps/validate_payment.rb
119
+ module OrderFulfillment
120
+ class ValidatePayment
121
+ def call(context)
122
+ context.payment = PaymentService.charge(context.input[:order])
123
+ end
124
+ end
125
+ end
126
+ ```
127
+
128
+ ```ruby
129
+ result = OrderFulfillment::Workflow.call(order: order)
130
+ result.payment
131
+ ```
132
+
133
+ Checkpoints are saved to the shared `ask_state` table, so workflows resume after crashes.
134
+
47
135
  ## Configuration
48
136
 
49
137
  API keys are resolved automatically by `Ask::Auth`:
@@ -3,9 +3,6 @@
3
3
  module Ask
4
4
  module Rails
5
5
  class Railtie < ::Rails::Railtie
6
- generators do
7
- require_relative "generators/install/install_generator"
8
- end
9
6
  end
10
7
  end
11
8
  end
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_record"
4
+
5
+ module Ask
6
+ module Rails
7
+ # ActiveRecord-backed state adapter for the ask_state table.
8
+ #
9
+ # Used by ask-graph (workflow checkpoints) and any other ask component
10
+ # that needs durable key-value storage in the Rails database. Works with
11
+ # any Rails database adapter — PostgreSQL, MySQL, SQLite — because the
12
+ # +value+ column is a portable JSON type.
13
+ #
14
+ # @example
15
+ # store = Ask::Rails::State.new
16
+ # store.set("checkpoint:1", { completed: true })
17
+ # store.get("checkpoint:1") # => { "completed" => true }
18
+ class State < ::Ask::State::Adapter
19
+ class Record < ::ActiveRecord::Base
20
+ self.table_name = "ask_state"
21
+ end
22
+
23
+ def get(key)
24
+ record = Record.find_by(key: key)
25
+ return nil unless record
26
+ return nil if record.expires_at && record.expires_at <= Time.current
27
+
28
+ record.value
29
+ end
30
+
31
+ def set(key, value, ttl: nil)
32
+ record = Record.find_or_initialize_by(key: key)
33
+ record.value = value
34
+ record.expires_at = ttl ? Time.current + ttl : nil
35
+ record.save!
36
+ value
37
+ end
38
+
39
+ def delete(key)
40
+ Record.where(key: key).delete_all
41
+ end
42
+
43
+ def clear
44
+ Record.delete_all
45
+ end
46
+
47
+ def keys(pattern: nil)
48
+ scope = Record.all
49
+ if pattern
50
+ like = self.class.glob_to_like(pattern)
51
+ scope = scope.where("key LIKE ?", like)
52
+ end
53
+ scope.pluck(:key)
54
+ end
55
+
56
+ def set_if_not_exists(key, value, ttl: nil)
57
+ return false if exists?(key)
58
+
59
+ set(key, value, ttl: ttl)
60
+ true
61
+ end
62
+
63
+ # Ordered lists — stored as an array in the value column.
64
+ # Required by Ask::Agent::Persistence::Base for session indexes.
65
+
66
+ def list_append(key, value, max_length: nil)
67
+ entries = list_range(key)
68
+ entries << value
69
+ entries = entries.last(max_length) if max_length
70
+ set(key, entries)
71
+ end
72
+
73
+ def list_range(key, start = 0, stop = -1)
74
+ entries = get(key)
75
+ return [] unless entries.is_a?(Array)
76
+
77
+ entries[start..stop] || []
78
+ end
79
+
80
+ def list_remove(key, value)
81
+ entries = get(key)
82
+ return 0 unless entries.is_a?(Array)
83
+
84
+ before = entries.size
85
+ entries.delete(value)
86
+ set(key, entries)
87
+ before - entries.size
88
+ end
89
+ end
90
+ end
91
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Ask
4
4
  module Rails
5
- VERSION = "0.6.0"
5
+ VERSION = "0.7.0"
6
6
  end
7
7
  end
data/lib/ask/rails.rb CHANGED
@@ -8,4 +8,5 @@ module Ask
8
8
  end
9
9
 
10
10
  require_relative "rails/version"
11
+ require_relative "rails/state"
11
12
  require_relative "rails/railtie" if defined?(::Rails::Railtie)
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ # <%= class_name %> agent.
4
+ #
5
+ # Run it:
6
+ # agent = Ask::Agent.new("<%= file_name %>")
7
+ # response = agent.run("Hello")
8
+ #
9
+ module Agents
10
+ class <%= class_name %> < ApplicationAgent
11
+ # model "gpt-4o"
12
+ system_prompt "You are a helpful assistant."
13
+
14
+ # tool :bash
15
+ # tool :read
16
+ # tool :grep
17
+ end
18
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators"
4
+
5
+ module Ask
6
+ module Generators
7
+ class AgentGenerator < ::Rails::Generators::NamedBase
8
+ source_root File.expand_path("agent/templates", __dir__)
9
+
10
+ desc "Creates an agent under app/agents — subclass ApplicationAgent with a model and system prompt"
11
+
12
+ def create_agent
13
+ template "agent.rb", "app/agents/#{file_name}.rb"
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Base class for your application's workflows.
4
+ #
5
+ # Subclass this to define workflows:
6
+ #
7
+ # module OrderFulfillment
8
+ # class Workflow < ApplicationWorkflow
9
+ # step ValidatePayment
10
+ # step NotifyCustomer
11
+ # step ShipOrder
12
+ # end
13
+ # end
14
+ #
15
+ # Then run:
16
+ # result = OrderFulfillment::Workflow.call({ order: order })
17
+ #
18
+ class ApplicationWorkflow < Ask::Graph
19
+ # Shared defaults — uncomment as needed:
20
+ # step_timeout 30
21
+ # workflow_timeout 60
22
+ # storage PostgresStore.new
23
+ end
@@ -1,6 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class CreateAskAuditLogs < ActiveRecord::Migration[8.1]
3
+ # Migration for ask-agent's audit log table.
4
+ # This table records session events (tool calls, errors, token usage, etc.)
5
+ # from every agent that has audit_log configured.
6
+ class CreateAskAuditLogs < ActiveRecord::Migration[<%= migration_version %>]
4
7
  def change
5
8
  create_table :ask_audit_logs, if_not_exists: true do |t|
6
9
  t.string :session_id, null: false
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # Ask Agent Configuration
4
- # ========================
3
+ # Ask Configuration
4
+ # =================
5
5
  #
6
6
  # API keys are resolved automatically by Ask::Auth:
7
7
  # - Environment variables: OPENAI_API_KEY, ANTHROPIC_API_KEY, etc.
@@ -10,10 +10,24 @@
10
10
  #
11
11
  # See https://github.com/ask-rb/ask-auth for details.
12
12
 
13
+ # Agents
13
14
  Ask::Agent.configure do |config|
14
- # Enable audit logging to the ask_audit_logs table
15
+ # Audit log for session events (ask_audit_logs table)
15
16
  # config.audit_log = { adapter: :active_record }
16
17
 
17
- # Optional: set a default model
18
18
  # config.default_model = "gpt-4o"
19
19
  end
20
+
21
+ # Workflows (ask-graph)
22
+ #
23
+ # The graph block is only generated when ask-graph is installed.
24
+ # Run `bundle add ask-graph` then `rails generate ask:install` to add it.
25
+ if defined?(Ask::Graph)
26
+ # Checkpoint storage for workflow crash recovery — backed by the
27
+ # ask_state table (created by the migration) in your Rails database.
28
+ # Works with any database adapter: PostgreSQL, MySQL, SQLite.
29
+ Ask::Graph.storage = Ask::Rails::State.new
30
+
31
+ # Ask::Graph.default_step_timeout 30
32
+ # Ask::Graph.default_workflow_timeout 60
33
+ end
@@ -1,10 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class CreateAskState < ActiveRecord::Migration[8.1]
3
+ # Migration for ask-rb's shared key-value state table.
4
+ # Used by ask-agent (session persistence) and ask-graph (workflow checkpoints).
5
+ # This single table serves both components — keys are namespaced by convention.
6
+ # The json column type works on PostgreSQL, MySQL, and SQLite.
7
+ class CreateAskState < ActiveRecord::Migration[<%= migration_version %>]
4
8
  def change
5
9
  create_table :ask_state do |t|
6
10
  t.string :key, null: false
7
- t.jsonb :value, null: false, default: {}
11
+ t.json :value, null: false, default: {}
8
12
  t.datetime :expires_at
9
13
  t.timestamps
10
14
 
@@ -6,34 +6,54 @@ require "rails/generators/active_record"
6
6
  module Ask
7
7
  module Generators
8
8
  class InstallGenerator < ::Rails::Generators::Base
9
- include ::Rails::Generators::Migration
9
+ include ::ActiveRecord::Generators::Migration
10
10
 
11
11
  source_root File.expand_path("install/templates", __dir__)
12
12
 
13
- desc "Sets up ask-rb for Rails — creates initializer, state and audit log migrations"
13
+ desc "Sets up ask-rb for Rails — creates initializer, agents and workflows directories, and shared state migrations"
14
+
15
+ class_option :skip_graph, type: :boolean, default: false,
16
+ desc: "Skip workflow scaffolding even if ask-graph is installed"
14
17
 
15
18
  def create_initializer
16
19
  template "initializer.rb", "config/initializers/ask.rb"
17
20
  end
18
21
 
22
+ def create_agents_directory
23
+ empty_directory "app/agents"
24
+ end
25
+
26
+ def create_application_agent
27
+ template "application_agent.rb", "app/agents/application_agent.rb"
28
+ end
29
+
30
+ def create_workflows_directory
31
+ return if skip_graph?
32
+ empty_directory "app/workflows"
33
+ end
34
+
35
+ def create_application_workflow
36
+ return if skip_graph?
37
+ template "application_workflow.rb", "app/workflows/application_workflow.rb"
38
+ end
39
+
19
40
  def create_state_migration
20
- template "state_migration.rb", "db/migrate/#{next_migration_number}_create_ask_state.rb"
41
+ migration_template "state_migration.rb", "db/migrate/create_ask_state.rb"
21
42
  end
22
43
 
23
44
  def create_audit_log_migration
24
- template "audit_log_migration.rb", "db/migrate/#{next_migration_number}_create_ask_audit_logs.rb"
45
+ migration_template "audit_log_migration.rb", "db/migrate/create_ask_audit_logs.rb"
25
46
  end
26
47
 
27
48
  private
28
49
 
29
- def next_migration_number
30
- # Rails requires exactly YYYYMMDDHHMMSS format
31
- @migration_suffix ||= 0
32
- now = Time.now.utc.strftime("%Y%m%d%H%M")
33
- "#{now}#{format('%02d', @migration_suffix)}"
34
- ensure
35
- @migration_suffix = (@migration_suffix || 0) + 1
50
+ def skip_graph?
51
+ options[:skip_graph] || !defined?(Ask::Graph)
36
52
  end
53
+
54
+ def migration_version
55
+ ActiveRecord::Migration.current_version
56
+ end
37
57
  end
38
58
  end
39
59
  end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ # <%= class_name %> workflow.
4
+ #
5
+ # Define steps as plain Ruby classes in steps/ — each responds to call(context).
6
+ # Compose other workflows via Workflow.call(context) inside a step.
7
+ #
8
+ # module <%= class_name %>
9
+ # class Workflow < ApplicationWorkflow
10
+ # step SomeStep
11
+ # step OtherStep, if: :condition?
12
+ #
13
+ # private
14
+ #
15
+ # def condition?
16
+ # context.some_flag
17
+ # end
18
+ # end
19
+ # end
20
+ #
21
+ # Run it:
22
+ # result = <%= class_name %>::Workflow.call({ input: value })
23
+ #
24
+ module <%= class_name %>
25
+ class Workflow < ApplicationWorkflow
26
+ # step SomeStep
27
+ end
28
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators"
4
+
5
+ module Ask
6
+ module Generators
7
+ class WorkflowGenerator < ::Rails::Generators::NamedBase
8
+ source_root File.expand_path("workflow/templates", __dir__)
9
+
10
+ desc "Creates a workflow under app/workflows — module directory, Workflow class, and steps directory"
11
+
12
+ def verify_ask_graph
13
+ return if defined?(Ask::Graph)
14
+
15
+ raise ::Thor::Error, <<~MSG.strip
16
+ ask-graph is not installed. Add it to your Gemfile and run `bundle install` first:
17
+
18
+ gem "ask-graph"
19
+ MSG
20
+ end
21
+
22
+ def create_workflow_directory
23
+ empty_directory "app/workflows/#{file_name}"
24
+ end
25
+
26
+ def create_workflow
27
+ template "workflow.rb", "app/workflows/#{file_name}/workflow.rb"
28
+ end
29
+
30
+ def create_steps_directory
31
+ empty_directory "app/workflows/#{file_name}/steps"
32
+ end
33
+ end
34
+ end
35
+ end
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.6.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kaka Ruto
@@ -79,6 +79,20 @@ dependencies:
79
79
  - - "~>"
80
80
  - !ruby/object:Gem::Version
81
81
  version: '13.0'
82
+ - !ruby/object:Gem::Dependency
83
+ name: sqlite3
84
+ requirement: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '1.4'
89
+ type: :development
90
+ prerelease: false
91
+ version_requirements: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '1.4'
82
96
  description: Rails generators, file conventions, and railtie for using ask-agent in
83
97
  Rails apps.
84
98
  email:
@@ -92,17 +106,19 @@ files:
92
106
  - README.md
93
107
  - lib/ask-rails.rb
94
108
  - lib/ask/rails.rb
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/audit_log_migration.rb
98
- - lib/ask/rails/generators/install/templates/initializer.rb
99
- - lib/ask/rails/generators/install/templates/state_migration.rb
100
109
  - lib/ask/rails/railtie.rb
110
+ - lib/ask/rails/state.rb
101
111
  - lib/ask/rails/version.rb
112
+ - lib/generators/ask/agent/templates/agent.rb
113
+ - lib/generators/ask/agent_generator.rb
114
+ - lib/generators/ask/install/templates/application_agent.rb
115
+ - lib/generators/ask/install/templates/application_workflow.rb
102
116
  - lib/generators/ask/install/templates/audit_log_migration.rb
103
117
  - lib/generators/ask/install/templates/initializer.rb
104
118
  - lib/generators/ask/install/templates/state_migration.rb
105
119
  - lib/generators/ask/install_generator.rb
120
+ - lib/generators/ask/workflow/templates/workflow.rb
121
+ - lib/generators/ask/workflow_generator.rb
106
122
  homepage: https://github.com/ask-rb/ask-rails
107
123
  licenses:
108
124
  - MIT
@@ -1,45 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "rails/generators"
4
- require "rails/generators/active_record"
5
-
6
- module Ask
7
- module Rails
8
- module Generators
9
- class InstallGenerator < ::Rails::Generators::Base
10
- include ::Rails::Generators::Migration
11
-
12
- source_root File.expand_path("templates", __dir__)
13
-
14
- desc "Sets up ask-rb for Rails — creates initializer, agents directory, state and audit log migrations"
15
-
16
- def create_initializer
17
- template "initializer.rb", "config/initializers/ask.rb"
18
- end
19
-
20
- def create_application_agent
21
- template "application_agent.rb", "app/agents/application_agent.rb"
22
- end
23
-
24
- def create_agents_directory
25
- empty_directory "app/agents"
26
- create_file "app/agents/.keep", "" unless options[:skip_keep]
27
- end
28
-
29
- def create_state_migration
30
- migration_template "state_migration.rb", "db/migrate/create_ask_state.rb"
31
- end
32
-
33
- def create_audit_log_migration
34
- migration_template "audit_log_migration.rb", "db/migrate/create_ask_audit_logs.rb"
35
- end
36
-
37
- private
38
-
39
- def migration_version
40
- "[#{ActiveRecord::Migration.current_version}]"
41
- end
42
- end
43
- end
44
- end
45
- end
@@ -1,19 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Migration for ask-agent's audit log table.
4
- # This table records session events (tool calls, errors, token usage, etc.)
5
- # from every agent that has audit_log configured.
6
- class CreateAskAuditLogs < ActiveRecord::Migration[<%= migration_version %>]
7
- def change
8
- create_table :ask_audit_logs, if_not_exists: true do |t|
9
- t.string :session_id, null: false
10
- t.string :event_type, null: false
11
- t.jsonb :data, default: {}
12
- t.datetime :timestamp, null: false
13
- t.timestamps
14
-
15
- t.index [:session_id, :event_type]
16
- t.index :timestamp
17
- end
18
- end
19
- end
@@ -1,27 +0,0 @@
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
- # Shared key-value state store for agent sessions and graph checkpoints.
14
- # Uses the ask_state table created by the migration.
15
- ASK_STATE = Ask::State::PostgreSQL.new(
16
- table_name: :ask_state
17
- )
18
-
19
- Ask::Agent.configure do |config|
20
- # State persistence for agent sessions
21
- config.state = ASK_STATE
22
-
23
- # Audit log for session events
24
- config.audit_log = { adapter: :active_record }
25
-
26
- # config.default_model = "gpt-4o"
27
- end
@@ -1,18 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Migration for ask-rb's shared key-value state table.
4
- # Used by ask-agent (session persistence) and ask-graph (workflow checkpoints).
5
- # This single table serves both components — keys are namespaced by convention.
6
- class CreateAskState < ActiveRecord::Migration[<%= migration_version %>]
7
- def change
8
- create_table :ask_state do |t|
9
- t.string :key, null: false
10
- t.jsonb :value, null: false, default: {}
11
- t.datetime :expires_at
12
- t.timestamps
13
-
14
- t.index :key, unique: true
15
- t.index :expires_at
16
- end
17
- end
18
- end