agent_gateway 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.md +137 -0
- data/app/controllers/agent_gateway/briefings_controller.rb +74 -0
- data/config/routes.rb +3 -0
- data/lando.jpeg +0 -0
- data/lib/agent_gateway/configuration.rb +35 -0
- data/lib/agent_gateway/engine.rb +18 -0
- data/lib/agent_gateway/query_runner.rb +81 -0
- data/lib/agent_gateway/resource_config.rb +72 -0
- data/lib/agent_gateway/version.rb +3 -0
- data/lib/agent_gateway.rb +5 -0
- metadata +83 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 3517469f438cc1b6f649f04a3efefd74dde4ba8a03fde7ba9453e7f26ec3036d
|
|
4
|
+
data.tar.gz: ba5c6952bdaff79502367cf2463e8bcf6fa2281169b091d831a0ca81b12cb0be
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 9c5898a3d51db11fd25a2c159f14a3c856f67da2afa359d0c6c519a366342de2f0fd3f9811d4324281920ee3b2032ad9ac1106fd87a7d78e066725585e4d6fe8
|
|
7
|
+
data.tar.gz: 0577e6232671783e4c0595edb3807e840c95ed68ffa10b2401817068142a60e2e5fc5bf95110f970a30de4a822316e7aa63231697d588bbec1e05f6804efdbec
|
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Jesse Waites
|
|
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.
|
data/README.md
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+

|
|
2
|
+
|
|
3
|
+
# Agent Gateway
|
|
4
|
+
|
|
5
|
+
A mountable Rails engine that exposes a single authenticated JSON endpoint for AI agents to consume your app's data.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
Add to your Gemfile:
|
|
10
|
+
|
|
11
|
+
```ruby
|
|
12
|
+
gem "agent_gateway"
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Then mount the engine in `config/routes.rb`:
|
|
16
|
+
|
|
17
|
+
```ruby
|
|
18
|
+
mount AgentGateway::Engine => "/agent-gateway"
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Configuration
|
|
22
|
+
|
|
23
|
+
Create an initializer `config/initializers/agent_gateway.rb`:
|
|
24
|
+
|
|
25
|
+
```ruby
|
|
26
|
+
AgentGateway.configure do |c|
|
|
27
|
+
c.app_name = "MyApp"
|
|
28
|
+
c.auth_token = ENV["AGENT_GATEWAY_TOKEN"] # required — raises at boot if blank
|
|
29
|
+
c.path_secret = ENV["AGENT_GATEWAY_SECRET"] # auto-generated + logged if omitted
|
|
30
|
+
c.default_period = "7d" # 1d, 7d, 30d, 90d, 1y, all
|
|
31
|
+
|
|
32
|
+
c.expose :users, model: "User" do
|
|
33
|
+
count
|
|
34
|
+
latest 5
|
|
35
|
+
attributes :email, :name, :created_at
|
|
36
|
+
scope :active
|
|
37
|
+
date_column :created_at
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
c.expose :orders, model: "Order" do
|
|
41
|
+
count
|
|
42
|
+
sum :total
|
|
43
|
+
avg :total
|
|
44
|
+
latest 3
|
|
45
|
+
attributes :id, :total, :status, :created_at
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### DSL Reference
|
|
51
|
+
|
|
52
|
+
| Method | Description |
|
|
53
|
+
|--------|-------------|
|
|
54
|
+
| `count` | Include record count |
|
|
55
|
+
| `latest N` | Include N most recent records |
|
|
56
|
+
| `attributes :col1, :col2` | Allowlist fields on latest records |
|
|
57
|
+
| `sum :column` | Sum a numeric column (call multiple times for multiple columns) |
|
|
58
|
+
| `avg :column` | Average a numeric column (call multiple times) |
|
|
59
|
+
| `scope :name` | Apply a named scope to all queries |
|
|
60
|
+
| `date_column :name` | Column used for period filtering (default: `created_at`) |
|
|
61
|
+
|
|
62
|
+
## Endpoint
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
GET /<mount_path>/<path_secret>/briefing
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Authentication
|
|
69
|
+
|
|
70
|
+
Two-layer auth:
|
|
71
|
+
1. **Path secret** — wrong value returns `404` (endpoint appears nonexistent)
|
|
72
|
+
2. **Bearer token** — wrong/missing value returns `401`
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
curl -H "Authorization: Bearer $TOKEN" \
|
|
76
|
+
https://myapp.com/agent-gateway/$SECRET/briefing
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Query Parameters
|
|
80
|
+
|
|
81
|
+
| Param | Description | Example |
|
|
82
|
+
|-------|-------------|---------|
|
|
83
|
+
| `period` | Time window: `1d`, `7d`, `30d`, `90d`, `1y`, `all` | `?period=30d` |
|
|
84
|
+
| `resources` | Comma-separated resource keys to include | `?resources=users,orders` |
|
|
85
|
+
| `latest` | Override latest count for all resources | `?latest=10` |
|
|
86
|
+
|
|
87
|
+
### Response
|
|
88
|
+
|
|
89
|
+
```json
|
|
90
|
+
{
|
|
91
|
+
"app_name": "MyApp",
|
|
92
|
+
"generated_at": "2026-02-20T12:00:00Z",
|
|
93
|
+
"period": {
|
|
94
|
+
"from": "2026-02-13",
|
|
95
|
+
"to": "2026-02-20",
|
|
96
|
+
"days": 7
|
|
97
|
+
},
|
|
98
|
+
"data": {
|
|
99
|
+
"users": {
|
|
100
|
+
"count": 142,
|
|
101
|
+
"latest": [
|
|
102
|
+
{ "email": "new@example.com", "name": "New User", "created_at": "2026-02-20" }
|
|
103
|
+
]
|
|
104
|
+
},
|
|
105
|
+
"orders": {
|
|
106
|
+
"count": 89,
|
|
107
|
+
"sum": { "total": 12450.00 },
|
|
108
|
+
"avg": { "total": 139.89 },
|
|
109
|
+
"latest": [
|
|
110
|
+
{ "id": 501, "total": "250.00", "status": "paid", "created_at": "2026-02-20" }
|
|
111
|
+
]
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Security Notes
|
|
118
|
+
|
|
119
|
+
- `path_secret` is compared using `ActiveSupport::SecurityUtils.secure_compare` (timing-safe)
|
|
120
|
+
- Bearer token is also compared with `secure_compare`
|
|
121
|
+
- If no `path_secret` is configured, one is auto-generated and printed to STDOUT at boot
|
|
122
|
+
- Missing `auth_token` raises at boot — the engine won't start without one
|
|
123
|
+
|
|
124
|
+
## Using with AI Agents
|
|
125
|
+
|
|
126
|
+
Point your AI agent at the briefing endpoint with the bearer token. The response is a single JSON payload designed for LLM consumption — structured, filterable, and concise.
|
|
127
|
+
|
|
128
|
+
Example system prompt snippet:
|
|
129
|
+
|
|
130
|
+
```
|
|
131
|
+
Fetch app data from: GET https://myapp.com/agent-gateway/<secret>/briefing
|
|
132
|
+
Header: Authorization: Bearer <token>
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## License
|
|
136
|
+
|
|
137
|
+
MIT
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
module AgentGateway
|
|
2
|
+
class BriefingsController < ActionController::API
|
|
3
|
+
before_action :verify_path_secret
|
|
4
|
+
before_action :authenticate_token
|
|
5
|
+
|
|
6
|
+
def show
|
|
7
|
+
resources = build_resources
|
|
8
|
+
period_info = build_period_info
|
|
9
|
+
|
|
10
|
+
render json: {
|
|
11
|
+
app_name: AgentGateway.configuration.app_name,
|
|
12
|
+
generated_at: Time.current.iso8601,
|
|
13
|
+
period: period_info,
|
|
14
|
+
data: resources
|
|
15
|
+
}
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
def verify_path_secret
|
|
21
|
+
unless ActiveSupport::SecurityUtils.secure_compare(
|
|
22
|
+
params[:path_secret].to_s,
|
|
23
|
+
AgentGateway.configuration.path_secret.to_s
|
|
24
|
+
)
|
|
25
|
+
head :not_found
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def authenticate_token
|
|
30
|
+
token = request.headers["Authorization"].to_s.sub(/\ABearer\s+/, "")
|
|
31
|
+
unless ActiveSupport::SecurityUtils.secure_compare(token, AgentGateway.configuration.auth_token.to_s)
|
|
32
|
+
head :unauthorized
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def build_resources
|
|
37
|
+
configs = AgentGateway.configuration.resources
|
|
38
|
+
requested = params[:resources]&.split(",")&.map(&:strip)&.map(&:to_sym)
|
|
39
|
+
|
|
40
|
+
selected = if requested
|
|
41
|
+
configs.slice(*requested)
|
|
42
|
+
else
|
|
43
|
+
configs
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
selected.each_with_object({}) do |(key, config), hash|
|
|
47
|
+
runner = QueryRunner.new(key, config, period: period_param, latest_override: latest_override)
|
|
48
|
+
hash[key] = runner.call
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def build_period_info
|
|
53
|
+
days = resolve_display_period
|
|
54
|
+
if days
|
|
55
|
+
{ from: days.days.ago.to_date.iso8601, to: Date.current.iso8601, days: days }
|
|
56
|
+
else
|
|
57
|
+
{ from: nil, to: Date.current.iso8601, days: "all" }
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def resolve_display_period
|
|
62
|
+
period_key = period_param || AgentGateway.configuration.default_period
|
|
63
|
+
QueryRunner::PERIODS.fetch(period_key) { QueryRunner::PERIODS.fetch(AgentGateway.configuration.default_period, 7) }
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def period_param
|
|
67
|
+
params[:period].presence
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def latest_override
|
|
71
|
+
params[:latest]&.to_i&.then { |n| n > 0 ? n : nil }
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
data/config/routes.rb
ADDED
data/lando.jpeg
ADDED
|
Binary file
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module AgentGateway
|
|
2
|
+
class Configuration
|
|
3
|
+
attr_accessor :app_name, :path_secret, :auth_token, :default_period
|
|
4
|
+
attr_reader :resources
|
|
5
|
+
|
|
6
|
+
def initialize
|
|
7
|
+
@app_name = "App"
|
|
8
|
+
@path_secret = nil
|
|
9
|
+
@auth_token = nil
|
|
10
|
+
@default_period = "7d"
|
|
11
|
+
@resources = {}
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def expose(key, model: nil, &block)
|
|
15
|
+
model_name = model || key.to_s.classify
|
|
16
|
+
config = ResourceConfig.new(model_name)
|
|
17
|
+
config.instance_eval(&block) if block
|
|
18
|
+
@resources[key.to_sym] = config
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
class << self
|
|
23
|
+
def configuration
|
|
24
|
+
@configuration ||= Configuration.new
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def configure
|
|
28
|
+
yield(configuration)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def reset_configuration!
|
|
32
|
+
@configuration = Configuration.new
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module AgentGateway
|
|
2
|
+
class Engine < ::Rails::Engine
|
|
3
|
+
isolate_namespace AgentGateway
|
|
4
|
+
|
|
5
|
+
config.after_initialize do
|
|
6
|
+
cfg = AgentGateway.configuration
|
|
7
|
+
|
|
8
|
+
if cfg.auth_token.nil? || cfg.auth_token.to_s.strip.empty?
|
|
9
|
+
raise "AgentGateway: auth_token must be configured. Set it via AgentGateway.configure { |c| c.auth_token = 'your-token' }"
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
if cfg.path_secret.nil? || cfg.path_secret.to_s.strip.empty?
|
|
13
|
+
cfg.path_secret = SecureRandom.uuid
|
|
14
|
+
puts "[AgentGateway] path_secret auto-generated: #{cfg.path_secret}"
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
module AgentGateway
|
|
2
|
+
class QueryRunner
|
|
3
|
+
PERIODS = {
|
|
4
|
+
"1d" => 1,
|
|
5
|
+
"7d" => 7,
|
|
6
|
+
"30d" => 30,
|
|
7
|
+
"90d" => 90,
|
|
8
|
+
"1y" => 365,
|
|
9
|
+
"all" => nil
|
|
10
|
+
}.freeze
|
|
11
|
+
|
|
12
|
+
def initialize(resource_key, config, period: nil, latest_override: nil)
|
|
13
|
+
@resource_key = resource_key
|
|
14
|
+
@config = config
|
|
15
|
+
@period = period
|
|
16
|
+
@latest_override = latest_override
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def call
|
|
20
|
+
model = @config.model_name.constantize
|
|
21
|
+
relation = base_relation(model)
|
|
22
|
+
|
|
23
|
+
result = {}
|
|
24
|
+
result[:count] = relation.count if @config.count_enabled?
|
|
25
|
+
result[:sum] = compute_sums(relation) unless @config.sum_columns.empty?
|
|
26
|
+
result[:avg] = compute_avgs(relation) unless @config.avg_columns.empty?
|
|
27
|
+
result[:latest] = fetch_latest(relation) if latest_count
|
|
28
|
+
|
|
29
|
+
result
|
|
30
|
+
rescue NameError
|
|
31
|
+
{ error: "Model not found: #{@config.model_name}" }
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
def base_relation(model)
|
|
37
|
+
relation = @config.scope_name ? model.public_send(@config.scope_name) : model.all
|
|
38
|
+
apply_period_filter(relation)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def apply_period_filter(relation)
|
|
42
|
+
days = resolve_period
|
|
43
|
+
return relation unless days
|
|
44
|
+
|
|
45
|
+
date_col = @config.date_column_name
|
|
46
|
+
relation.where(date_col => days.days.ago..)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def resolve_period
|
|
50
|
+
period_key = @period || AgentGateway.configuration.default_period
|
|
51
|
+
return nil if period_key == "all"
|
|
52
|
+
|
|
53
|
+
PERIODS.fetch(period_key) { PERIODS.fetch(AgentGateway.configuration.default_period, 7) }
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def compute_sums(relation)
|
|
57
|
+
@config.sum_columns.each_with_object({}) do |col, hash|
|
|
58
|
+
hash[col] = (relation.sum(col.to_sym) || 0).round(2)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def compute_avgs(relation)
|
|
63
|
+
@config.avg_columns.each_with_object({}) do |col, hash|
|
|
64
|
+
hash[col] = (relation.average(col.to_sym) || 0).to_f.round(2)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def latest_count
|
|
69
|
+
@latest_override || @config.latest_count
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def fetch_latest(relation)
|
|
73
|
+
records = relation.order(created_at: :desc).limit(latest_count)
|
|
74
|
+
if @config.attributes_list.any?
|
|
75
|
+
records.map { |r| @config.attributes_list.each_with_object({}) { |a, h| h[a] = r.public_send(a) } }
|
|
76
|
+
else
|
|
77
|
+
records.map { |r| { "id" => r.id } }
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
module AgentGateway
|
|
2
|
+
class ResourceConfig
|
|
3
|
+
attr_reader :model_name
|
|
4
|
+
|
|
5
|
+
def initialize(model_name)
|
|
6
|
+
@model_name = model_name
|
|
7
|
+
@attributes_list = []
|
|
8
|
+
@count_enabled = false
|
|
9
|
+
@latest_count = nil
|
|
10
|
+
@sum_columns = []
|
|
11
|
+
@avg_columns = []
|
|
12
|
+
@scope_name = nil
|
|
13
|
+
@date_column_name = :created_at
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def attributes(*attrs)
|
|
17
|
+
@attributes_list = attrs.map(&:to_s)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def attributes_list
|
|
21
|
+
@attributes_list
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def count(enabled = true)
|
|
25
|
+
@count_enabled = enabled
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def count_enabled?
|
|
29
|
+
@count_enabled
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def latest(n)
|
|
33
|
+
@latest_count = n
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def latest_count
|
|
37
|
+
@latest_count
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def sum(column)
|
|
41
|
+
@sum_columns << column.to_s
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def sum_columns
|
|
45
|
+
@sum_columns
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def avg(column)
|
|
49
|
+
@avg_columns << column.to_s
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def avg_columns
|
|
53
|
+
@avg_columns
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def scope(name)
|
|
57
|
+
@scope_name = name
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def scope_name
|
|
61
|
+
@scope_name
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def date_column(name)
|
|
65
|
+
@date_column_name = name.to_sym
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def date_column_name
|
|
69
|
+
@date_column_name
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: agent_gateway
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Jesse Waites
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2026-02-20 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: railties
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '7.0'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ">="
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '7.0'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: activerecord
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - ">="
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '7.0'
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - ">="
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '7.0'
|
|
41
|
+
description: A mountable Rails engine that provides a configured, authenticated JSON
|
|
42
|
+
briefing endpoint for AI agents to consume app data.
|
|
43
|
+
email:
|
|
44
|
+
- jesse@example.com
|
|
45
|
+
executables: []
|
|
46
|
+
extensions: []
|
|
47
|
+
extra_rdoc_files: []
|
|
48
|
+
files:
|
|
49
|
+
- LICENSE
|
|
50
|
+
- README.md
|
|
51
|
+
- app/controllers/agent_gateway/briefings_controller.rb
|
|
52
|
+
- config/routes.rb
|
|
53
|
+
- lando.jpeg
|
|
54
|
+
- lib/agent_gateway.rb
|
|
55
|
+
- lib/agent_gateway/configuration.rb
|
|
56
|
+
- lib/agent_gateway/engine.rb
|
|
57
|
+
- lib/agent_gateway/query_runner.rb
|
|
58
|
+
- lib/agent_gateway/resource_config.rb
|
|
59
|
+
- lib/agent_gateway/version.rb
|
|
60
|
+
homepage: https://github.com/jessewaites/agent_gateway
|
|
61
|
+
licenses:
|
|
62
|
+
- MIT
|
|
63
|
+
metadata: {}
|
|
64
|
+
post_install_message:
|
|
65
|
+
rdoc_options: []
|
|
66
|
+
require_paths:
|
|
67
|
+
- lib
|
|
68
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
69
|
+
requirements:
|
|
70
|
+
- - ">="
|
|
71
|
+
- !ruby/object:Gem::Version
|
|
72
|
+
version: '3.0'
|
|
73
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
74
|
+
requirements:
|
|
75
|
+
- - ">="
|
|
76
|
+
- !ruby/object:Gem::Version
|
|
77
|
+
version: '0'
|
|
78
|
+
requirements: []
|
|
79
|
+
rubygems_version: 3.5.16
|
|
80
|
+
signing_key:
|
|
81
|
+
specification_version: 4
|
|
82
|
+
summary: Rails engine exposing app data as a single AI-agent-friendly JSON endpoint
|
|
83
|
+
test_files: []
|