rails-agent-stack 0.1.1
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/.github/workflows/README.md +16 -0
- data/.github/workflows/ci.yml +32 -0
- data/.gitignore +8 -0
- data/.rspec +3 -0
- data/AGENTS.md +18 -0
- data/CHANGELOG.md +40 -0
- data/Gemfile +15 -0
- data/MIT-LICENSE +21 -0
- data/README.md +228 -0
- data/Rakefile +8 -0
- data/app/assets/images/rails_agents/kip-logo.png +0 -0
- data/app/assets/images/rails_agents/kip-waving.png +0 -0
- data/app/assets/stylesheets/rails_agents/application.css +411 -0
- data/app/controllers/rails_agents/application_controller.rb +25 -0
- data/app/controllers/rails_agents/connect_controller.rb +36 -0
- data/app/controllers/rails_agents/dashboard_controller.rb +70 -0
- data/app/controllers/rails_agents/handshake_controller.rb +55 -0
- data/app/controllers/rails_agents/open_wire_inbound_controller.rb +153 -0
- data/app/controllers/rails_agents/pulls_controller.rb +42 -0
- data/app/controllers/rails_agents/registrations_controller.rb +96 -0
- data/app/controllers/rails_agents/schema_controller.rb +123 -0
- data/app/controllers/rails_agents/sessions_controller.rb +76 -0
- data/app/controllers/rails_agents/tool_bridge_controller.rb +67 -0
- data/app/views/layouts/rails_agents/application.html.erb +18 -0
- data/app/views/rails_agents/dashboard/show.html.erb +139 -0
- data/app/views/rails_agents/registrations/new.html.erb +83 -0
- data/app/views/rails_agents/sessions/new.html.erb +73 -0
- data/app/views/rails_agents/shared/_auth_brand.html.erb +20 -0
- data/config/routes.rb +34 -0
- data/docs/AGENTS.md +220 -0
- data/docs/PRD.md +89 -0
- data/docs/assets/hero-banner.png +0 -0
- data/examples/support/agent.rb +14 -0
- data/examples/support/channels/.keep +0 -0
- data/examples/support/evals/smoke.yml +4 -0
- data/examples/support/knowledge/shipping.md +1 -0
- data/examples/support/memory.rb +3 -0
- data/examples/support/prompt.md +9 -0
- data/examples/support/skills/.keep +0 -0
- data/examples/support/tools/.keep +0 -0
- data/exe/rails-agents +6 -0
- data/lib/generators/rails_agents/agent/agent_generator.rb +80 -0
- data/lib/generators/rails_agents/agent/templates/agent.rb.tt +14 -0
- data/lib/generators/rails_agents/agent/templates/agent_database.rb.tt +42 -0
- data/lib/generators/rails_agents/agent/templates/channels/slack.rb.tt +8 -0
- data/lib/generators/rails_agents/agent/templates/evals/smoke.yml.tt +4 -0
- data/lib/generators/rails_agents/agent/templates/imports.yml.tt +9 -0
- data/lib/generators/rails_agents/agent/templates/memory.rb.tt +6 -0
- data/lib/generators/rails_agents/agent/templates/prompt.md.tt +10 -0
- data/lib/generators/rails_agents/agent/templates/prompt_database.md.tt +14 -0
- data/lib/generators/rails_agents/install/INSTALL +10 -0
- data/lib/generators/rails_agents/install/install_generator.rb +72 -0
- data/lib/generators/rails_agents/install/templates/AGENTS.md.tt +46 -0
- data/lib/generators/rails_agents/install/templates/initializer.rb.tt +8 -0
- data/lib/generators/rails_agents/install/templates/library_README.md.tt +28 -0
- data/lib/generators/rails_agents/install/templates/library_manifest.yml.tt +5 -0
- data/lib/generators/rails_agents/install/templates/rails_agents_autoload.rb.tt +10 -0
- data/lib/rails-agent-stack.rb +4 -0
- data/lib/rails_agents/background_agent.rb +15 -0
- data/lib/rails_agents/base.rb +294 -0
- data/lib/rails_agents/chat_agent.rb +15 -0
- data/lib/rails_agents/cli.rb +245 -0
- data/lib/rails_agents/client.rb +216 -0
- data/lib/rails_agents/configuration.rb +41 -0
- data/lib/rails_agents/creation_agent.rb +10 -0
- data/lib/rails_agents/credentials_writer.rb +38 -0
- data/lib/rails_agents/engine.rb +19 -0
- data/lib/rails_agents/knowledge_agent.rb +10 -0
- data/lib/rails_agents/library_imports.rb +163 -0
- data/lib/rails_agents/local_auth.rb +56 -0
- data/lib/rails_agents/local_sync.rb +113 -0
- data/lib/rails_agents/monitoring_agent.rb +10 -0
- data/lib/rails_agents/open_wire_adapter.rb +31 -0
- data/lib/rails_agents/operations_agent.rb +10 -0
- data/lib/rails_agents/railtie.rb +14 -0
- data/lib/rails_agents/tasks.rake +8 -0
- data/lib/rails_agents/version.rb +5 -0
- data/lib/rails_agents/workflow_agent.rb +11 -0
- data/lib/rails_agents.rb +57 -0
- data/rails-agent-stack.gemspec +49 -0
- data/rails-agents.code-workspace +25 -0
- data/spec/generators/agent_generator_spec.rb +36 -0
- data/spec/rails_agents/base_spec.rb +202 -0
- data/spec/rails_agents/client_spec.rb +121 -0
- data/spec/rails_agents/configuration_spec.rb +55 -0
- data/spec/rails_agents/library_imports_spec.rb +80 -0
- data/spec/rails_agents/local_sync_spec.rb +63 -0
- data/spec/rails_agents/taxonomy_spec.rb +52 -0
- data/spec/spec_helper.rb +27 -0
- metadata +229 -0
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
<div class="rails-agents-embed-shell">
|
|
2
|
+
<span id="rails-agents-sync-status" class="rails-agents-sync-status rails-agents-sync-status--sr" aria-live="polite"></span>
|
|
3
|
+
<iframe
|
|
4
|
+
id="rails-agents-dashboard-frame"
|
|
5
|
+
class="rails-agents-embed"
|
|
6
|
+
src="<%= @dashboard_url %>"
|
|
7
|
+
title="Agents dashboard"
|
|
8
|
+
allow="clipboard-write"
|
|
9
|
+
></iframe>
|
|
10
|
+
</div>
|
|
11
|
+
|
|
12
|
+
<script>
|
|
13
|
+
(function () {
|
|
14
|
+
var SCHEMA_URL = <%= raw rails_agents.schema_path.to_json %>;
|
|
15
|
+
var DASHBOARD_PATH = <%= raw rails_agents.dashboard_path.to_json %>;
|
|
16
|
+
var frame = document.getElementById("rails-agents-dashboard-frame");
|
|
17
|
+
var cloudOrigin = frame ? new URL(frame.src).origin : null;
|
|
18
|
+
var CSRF = document.querySelector('meta[name="csrf-token"]');
|
|
19
|
+
var statusEl = document.getElementById("rails-agents-sync-status");
|
|
20
|
+
var ALLOWED = {
|
|
21
|
+
"https://cloud.rails-agent.com": true,
|
|
22
|
+
"https://rails-agent.com": true,
|
|
23
|
+
"http://localhost:3000": true,
|
|
24
|
+
"http://127.0.0.1:3000": true,
|
|
25
|
+
"http://localhost:3001": true,
|
|
26
|
+
"http://127.0.0.1:3001": true,
|
|
27
|
+
"http://localhost:8080": true,
|
|
28
|
+
"http://127.0.0.1:8080": true
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
function setStatus(text, isError) {
|
|
32
|
+
if (!statusEl) return;
|
|
33
|
+
statusEl.textContent = text || "";
|
|
34
|
+
statusEl.classList.toggle("rails-agents-sync-status--error", !!isError);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function headers() {
|
|
38
|
+
var h = {
|
|
39
|
+
"Accept": "application/json",
|
|
40
|
+
"Content-Type": "application/json"
|
|
41
|
+
};
|
|
42
|
+
if (CSRF) h["X-CSRF-Token"] = CSRF.getAttribute("content");
|
|
43
|
+
return h;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async function fetchSchema() {
|
|
47
|
+
var res = await fetch(SCHEMA_URL, {
|
|
48
|
+
method: "GET",
|
|
49
|
+
credentials: "same-origin",
|
|
50
|
+
headers: headers()
|
|
51
|
+
});
|
|
52
|
+
var json = {};
|
|
53
|
+
try { json = await res.json(); } catch (e) { json = {}; }
|
|
54
|
+
if (!res.ok || json.ok === false) {
|
|
55
|
+
throw new Error(json.error || ("Schema failed (" + res.status + ")"));
|
|
56
|
+
}
|
|
57
|
+
return json;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function syncBrowserUrl(data) {
|
|
61
|
+
if (!data.path || data.path.indexOf("/dashboard") !== 0) return;
|
|
62
|
+
var suffix = data.path.slice("/dashboard".length);
|
|
63
|
+
var next = DASHBOARD_PATH + suffix;
|
|
64
|
+
if (data.search) next += "?" + data.search;
|
|
65
|
+
if (data.hash) next += data.hash;
|
|
66
|
+
var current = window.location.pathname + window.location.search + window.location.hash;
|
|
67
|
+
if (next !== current) {
|
|
68
|
+
window.history.replaceState({ railsAgentsDashboard: true }, "", next);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function syncFrameFromBrowser() {
|
|
73
|
+
if (!frame || !frame.contentWindow || !cloudOrigin) return;
|
|
74
|
+
if (window.location.pathname.indexOf(DASHBOARD_PATH) !== 0) return;
|
|
75
|
+
var suffix = window.location.pathname.slice(DASHBOARD_PATH.length);
|
|
76
|
+
frame.contentWindow.postMessage({
|
|
77
|
+
type: "rails-agents:navigate-to",
|
|
78
|
+
path: "/dashboard" + suffix,
|
|
79
|
+
search: window.location.search.replace(/^\?/, ""),
|
|
80
|
+
hash: window.location.hash
|
|
81
|
+
}, cloudOrigin);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
window.addEventListener("popstate", syncFrameFromBrowser);
|
|
85
|
+
|
|
86
|
+
window.addEventListener("message", function (event) {
|
|
87
|
+
if (!ALLOWED[event.origin]) return;
|
|
88
|
+
var data = event.data || {};
|
|
89
|
+
|
|
90
|
+
if (data.type === "rails-agents:navigate") {
|
|
91
|
+
syncBrowserUrl(data);
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (data.type === "rails-agents:schema") {
|
|
96
|
+
fetchSchema()
|
|
97
|
+
.then(function (result) {
|
|
98
|
+
if (event.source && event.source.postMessage) {
|
|
99
|
+
event.source.postMessage({
|
|
100
|
+
type: "rails-agents:schema-result",
|
|
101
|
+
requestId: data.requestId,
|
|
102
|
+
ok: true,
|
|
103
|
+
tables: result.tables || [],
|
|
104
|
+
adapter: result.adapter,
|
|
105
|
+
databases: result.databases || [],
|
|
106
|
+
configFiles: result.config_files || []
|
|
107
|
+
}, event.origin);
|
|
108
|
+
}
|
|
109
|
+
})
|
|
110
|
+
.catch(function (err) {
|
|
111
|
+
if (event.source && event.source.postMessage) {
|
|
112
|
+
event.source.postMessage({
|
|
113
|
+
type: "rails-agents:schema-result",
|
|
114
|
+
requestId: data.requestId,
|
|
115
|
+
ok: false,
|
|
116
|
+
error: err.message || "Schema failed",
|
|
117
|
+
tables: []
|
|
118
|
+
}, event.origin);
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Deprecated: cloud-to-local authoring pull. Use `rails-agents sync` (local → cloud)
|
|
125
|
+
// or scaffold agents with `rails generate rails_agents:agent`. See AGENTS.md.
|
|
126
|
+
if (data.type === "rails-agents:pull") {
|
|
127
|
+
if (event.source && event.source.postMessage) {
|
|
128
|
+
event.source.postMessage({
|
|
129
|
+
type: "rails-agents:pull-result",
|
|
130
|
+
requestId: data.requestId,
|
|
131
|
+
ok: false,
|
|
132
|
+
error: "Cloud pull is deprecated. Build agents locally (see AGENTS.md) and run rails-agents sync."
|
|
133
|
+
}, event.origin);
|
|
134
|
+
}
|
|
135
|
+
setStatus("Cloud pull deprecated — edit app/agents/ locally", true);
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
})();
|
|
139
|
+
</script>
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
<%
|
|
2
|
+
@step ||= :email
|
|
3
|
+
@workspace ||= (Rails.application.class.module_parent_name rescue "MyApp")
|
|
4
|
+
@github_url ||= "#"
|
|
5
|
+
%>
|
|
6
|
+
<div class="rails-agents-connect">
|
|
7
|
+
<%= render "rails_agents/shared/auth_brand" %>
|
|
8
|
+
|
|
9
|
+
<section class="rails-agents-connect__form-pane">
|
|
10
|
+
<div class="rails-agents-connect__card">
|
|
11
|
+
<% if notice.present? %>
|
|
12
|
+
<div class="rails-agents-flash"><%= notice %></div>
|
|
13
|
+
<% end %>
|
|
14
|
+
<% if alert.present? %>
|
|
15
|
+
<div class="rails-agents-flash rails-agents-flash--alert"><%= alert %></div>
|
|
16
|
+
<% end %>
|
|
17
|
+
|
|
18
|
+
<h2>Create workspace</h2>
|
|
19
|
+
<p class="rails-agents-lede">
|
|
20
|
+
Links this Rails app to your company workspace — build agents in
|
|
21
|
+
<code>app/agents/</code>, attach BYOK credentials in the cloud dashboard.
|
|
22
|
+
</p>
|
|
23
|
+
|
|
24
|
+
<% if @step.to_sym == :code %>
|
|
25
|
+
<p class="rails-agents-muted" style="margin-top:1.25rem">
|
|
26
|
+
Enter the code we sent to <strong><%= @email %></strong>
|
|
27
|
+
</p>
|
|
28
|
+
<% if @dev_code.present? %>
|
|
29
|
+
<p class="rails-agents-flash" style="margin-top:0.75rem">
|
|
30
|
+
Dev code: <code><%= @dev_code %></code>
|
|
31
|
+
</p>
|
|
32
|
+
<% end %>
|
|
33
|
+
|
|
34
|
+
<%= form_with url: rails_agents.signup_verify_path, method: :post, local: true, class: "rails-agents-form", html: { style: "margin-top:1rem" } do %>
|
|
35
|
+
<label>
|
|
36
|
+
Code
|
|
37
|
+
<input type="text" name="code" inputmode="numeric" pattern="\d{4}" maxlength="4" required autofocus autocomplete="one-time-code" placeholder="0000" />
|
|
38
|
+
</label>
|
|
39
|
+
<button type="submit" class="rails-agents-btn rails-agents-btn--primary">
|
|
40
|
+
Verify & connect →
|
|
41
|
+
</button>
|
|
42
|
+
<% end %>
|
|
43
|
+
|
|
44
|
+
<p class="rails-agents-connect__foot">
|
|
45
|
+
<%= link_to "Use a different email", rails_agents.signup_path %>
|
|
46
|
+
</p>
|
|
47
|
+
<% else %>
|
|
48
|
+
<a class="rails-agents-btn rails-agents-btn--ghost rails-agents-btn--spaced"
|
|
49
|
+
href="<%= @github_url %>">
|
|
50
|
+
<svg class="rails-agents-github-icon" viewBox="0 0 16 16" aria-hidden="true">
|
|
51
|
+
<path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/>
|
|
52
|
+
</svg>
|
|
53
|
+
Continue with GitHub
|
|
54
|
+
</a>
|
|
55
|
+
|
|
56
|
+
<div class="rails-agents-divider">or email</div>
|
|
57
|
+
|
|
58
|
+
<%= form_with url: rails_agents.signup_path, method: :post, local: true, class: "rails-agents-form" do %>
|
|
59
|
+
<label>
|
|
60
|
+
Workspace
|
|
61
|
+
<input type="text" name="workspace" value="<%= @workspace %>" autocomplete="organization" />
|
|
62
|
+
</label>
|
|
63
|
+
<label>
|
|
64
|
+
Your name <span>(optional)</span>
|
|
65
|
+
<input type="text" name="name" value="<%= @name %>" autocomplete="name" />
|
|
66
|
+
</label>
|
|
67
|
+
<label>
|
|
68
|
+
Email
|
|
69
|
+
<input type="email" name="email" value="<%= @email %>" required autocomplete="email" placeholder="you@company.com" />
|
|
70
|
+
</label>
|
|
71
|
+
<button type="submit" class="rails-agents-btn rails-agents-btn--primary">
|
|
72
|
+
Continue with email
|
|
73
|
+
</button>
|
|
74
|
+
<% end %>
|
|
75
|
+
|
|
76
|
+
<p class="rails-agents-connect__foot">
|
|
77
|
+
Already have an account?
|
|
78
|
+
<%= link_to "Sign in", rails_agents.signin_path %>
|
|
79
|
+
</p>
|
|
80
|
+
<% end %>
|
|
81
|
+
</div>
|
|
82
|
+
</section>
|
|
83
|
+
</div>
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
<%
|
|
2
|
+
@step ||= :email
|
|
3
|
+
@github_url ||= "#"
|
|
4
|
+
%>
|
|
5
|
+
<div class="rails-agents-connect">
|
|
6
|
+
<%= render "rails_agents/shared/auth_brand" %>
|
|
7
|
+
|
|
8
|
+
<section class="rails-agents-connect__form-pane">
|
|
9
|
+
<div class="rails-agents-connect__card">
|
|
10
|
+
<% if notice.present? %>
|
|
11
|
+
<div class="rails-agents-flash"><%= notice %></div>
|
|
12
|
+
<% end %>
|
|
13
|
+
<% if alert.present? %>
|
|
14
|
+
<div class="rails-agents-flash rails-agents-flash--alert"><%= alert %></div>
|
|
15
|
+
<% end %>
|
|
16
|
+
|
|
17
|
+
<h2>Sign in</h2>
|
|
18
|
+
<p class="rails-agents-lede">
|
|
19
|
+
Jump back into your workspace — nothing to reinstall.
|
|
20
|
+
</p>
|
|
21
|
+
|
|
22
|
+
<% if @step.to_sym == :code %>
|
|
23
|
+
<p class="rails-agents-muted" style="margin-top:1.25rem">
|
|
24
|
+
Enter the code we sent to <strong><%= @email %></strong>
|
|
25
|
+
</p>
|
|
26
|
+
<% if @dev_code.present? %>
|
|
27
|
+
<p class="rails-agents-flash" style="margin-top:0.75rem">
|
|
28
|
+
Dev code: <code><%= @dev_code %></code>
|
|
29
|
+
</p>
|
|
30
|
+
<% end %>
|
|
31
|
+
|
|
32
|
+
<%= form_with url: rails_agents.signin_verify_path, method: :post, local: true, class: "rails-agents-form", html: { style: "margin-top:1rem" } do %>
|
|
33
|
+
<label>
|
|
34
|
+
Code
|
|
35
|
+
<input type="text" name="code" inputmode="numeric" pattern="\d{4}" maxlength="4" required autofocus autocomplete="one-time-code" placeholder="0000" />
|
|
36
|
+
</label>
|
|
37
|
+
<button type="submit" class="rails-agents-btn rails-agents-btn--primary">
|
|
38
|
+
Verify & connect →
|
|
39
|
+
</button>
|
|
40
|
+
<% end %>
|
|
41
|
+
|
|
42
|
+
<p class="rails-agents-connect__foot">
|
|
43
|
+
<%= link_to "Use a different email", rails_agents.signin_path %>
|
|
44
|
+
</p>
|
|
45
|
+
<% else %>
|
|
46
|
+
<a class="rails-agents-btn rails-agents-btn--ghost rails-agents-btn--spaced"
|
|
47
|
+
href="<%= @github_url %>">
|
|
48
|
+
<svg class="rails-agents-github-icon" viewBox="0 0 16 16" aria-hidden="true">
|
|
49
|
+
<path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/>
|
|
50
|
+
</svg>
|
|
51
|
+
Continue with GitHub
|
|
52
|
+
</a>
|
|
53
|
+
|
|
54
|
+
<div class="rails-agents-divider">or email</div>
|
|
55
|
+
|
|
56
|
+
<%= form_with url: rails_agents.signin_path, method: :post, local: true, class: "rails-agents-form" do %>
|
|
57
|
+
<label>
|
|
58
|
+
Email
|
|
59
|
+
<input type="email" name="email" value="<%= @email %>" required autocomplete="email" placeholder="you@company.com" />
|
|
60
|
+
</label>
|
|
61
|
+
<button type="submit" class="rails-agents-btn rails-agents-btn--primary">
|
|
62
|
+
Continue with email
|
|
63
|
+
</button>
|
|
64
|
+
<% end %>
|
|
65
|
+
|
|
66
|
+
<p class="rails-agents-connect__foot">
|
|
67
|
+
New here?
|
|
68
|
+
<%= link_to "Create workspace", rails_agents.signup_path %>
|
|
69
|
+
</p>
|
|
70
|
+
<% end %>
|
|
71
|
+
</div>
|
|
72
|
+
</section>
|
|
73
|
+
</div>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<aside class="rails-agents-connect__brand">
|
|
2
|
+
<a class="rails-agents-logo-lockup" href="https://rails-agent.com" target="_blank" rel="noopener">
|
|
3
|
+
<span class="rails-agents-logo-mark" aria-hidden="true">RA</span>
|
|
4
|
+
<span class="rails-agents-logo-word">Rails <em>Agent</em></span>
|
|
5
|
+
</a>
|
|
6
|
+
|
|
7
|
+
<div class="rails-agents-connect__copy">
|
|
8
|
+
<h1>Fullstack agents for <em>Rails</em>.</h1>
|
|
9
|
+
<p>
|
|
10
|
+
Connect your company workspace, build agents in <code>app/agents/</code>
|
|
11
|
+
with your editor or external coding agent, then test, deploy, and monitor at
|
|
12
|
+
<code>/agents</code>.
|
|
13
|
+
</p>
|
|
14
|
+
<p class="rails-agents-muted">
|
|
15
|
+
Start with <strong>AGENTS.md</strong> in your repo — first step: a database Knowledge agent.
|
|
16
|
+
</p>
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
<p class="rails-agents-connect__meta">rails-agent.com</p>
|
|
20
|
+
</aside>
|
data/config/routes.rb
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
RailsAgents::Engine.routes.draw do
|
|
2
|
+
# First-run default: create workspace. Already connected → signup redirects to dashboard.
|
|
3
|
+
root to: "registrations#new"
|
|
4
|
+
|
|
5
|
+
get "signup", to: "registrations#new", as: :signup
|
|
6
|
+
post "signup", to: "registrations#create"
|
|
7
|
+
post "signup/verify", to: "registrations#verify", as: :signup_verify
|
|
8
|
+
|
|
9
|
+
get "signin", to: "sessions#new", as: :signin
|
|
10
|
+
post "signin", to: "sessions#create"
|
|
11
|
+
post "signin/verify", to: "sessions#verify", as: :signin_verify
|
|
12
|
+
delete "signout", to: "sessions#destroy", as: :signout
|
|
13
|
+
|
|
14
|
+
post "handshake", to: "handshake#create", as: :handshake
|
|
15
|
+
get "connect", to: "connect#show", as: :connect
|
|
16
|
+
|
|
17
|
+
# Deprecated compatibility: cloud-to-local pull (prefer local scaffold + `rails-agents sync`)
|
|
18
|
+
post "pull", to: "pulls#create", as: :pull
|
|
19
|
+
|
|
20
|
+
# ActiveRecord schema for Knowledge agents / database connector in dashboard
|
|
21
|
+
get "schema", to: "schema#show", as: :schema
|
|
22
|
+
|
|
23
|
+
# Production runtime → Rails tool execution. The bearer token is
|
|
24
|
+
# introspected against Rails Agent Cloud before any local code runs.
|
|
25
|
+
post "bridge/:agent/tools/:tool", to: "tool_bridge#create", as: :tool_bridge
|
|
26
|
+
|
|
27
|
+
# Open-Wire reverse path (channel → agent). No separate OpenWire::Engine mount.
|
|
28
|
+
# Gateway POSTs message.inbound here; gem open-wire verifies + parses.
|
|
29
|
+
post "open_wire/inbound", to: "open_wire_inbound#create", as: :open_wire_inbound
|
|
30
|
+
post "open_wire/inbound/:agent", to: "open_wire_inbound#create", as: :open_wire_inbound_agent
|
|
31
|
+
|
|
32
|
+
get "dashboard", to: "dashboard#show", as: :dashboard
|
|
33
|
+
get "dashboard/*path", to: "dashboard#proxy", as: :dashboard_proxy
|
|
34
|
+
end
|
data/docs/AGENTS.md
ADDED
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
# AGENTS.md — Rails Agent onboarding
|
|
2
|
+
|
|
3
|
+
Guide for **external coding agents** (Cursor, Claude Code, Codex, etc.) and humans building on Rails Agent.
|
|
4
|
+
|
|
5
|
+
## What this platform is
|
|
6
|
+
|
|
7
|
+
Rails Agent is a **fullstack agent platform for Rails**: you write agents as Ruby directories under `app/agents/`, connect provider credentials (BYOK) in the cloud dashboard, then **test, deploy, and monitor** at `/agents`.
|
|
8
|
+
|
|
9
|
+
Billing: **fixed company subscription** + **metered usage at provider/infrastructure cost** + **transparent 1% service fee**.
|
|
10
|
+
|
|
11
|
+
## Agent taxonomy (pick one)
|
|
12
|
+
|
|
13
|
+
| Type | Main purpose | Example |
|
|
14
|
+
|------|--------------|---------|
|
|
15
|
+
| **Knowledge** | Understand and answer | Order support from Rails data and policy docs |
|
|
16
|
+
| **Workflow** | Execute predictable processes | Verify → approve → refund → notify |
|
|
17
|
+
| **Operations** | Coordinate unpredictable real-world work | Incident or customer escalation coordination |
|
|
18
|
+
| **Monitoring** | Observe changes and respond | Inventory, error, or SLA watcher |
|
|
19
|
+
|
|
20
|
+
Use the matching base class: `RailsAgents::KnowledgeAgent`,
|
|
21
|
+
`WorkflowAgent`, `OperationsAgent`, or `MonitoringAgent`.
|
|
22
|
+
|
|
23
|
+
Legacy aliases (deprecated): `ChatAgent` → Knowledge, `BackgroundAgent` → Operations.
|
|
24
|
+
|
|
25
|
+
## Run response schema (integrate into product)
|
|
26
|
+
|
|
27
|
+
Every provider (OpenAI, Anthropic, Gateway, OSS) normalizes to one shape.
|
|
28
|
+
Your app should not branch on provider-specific payloads.
|
|
29
|
+
|
|
30
|
+
| Field | Use |
|
|
31
|
+
|-------|-----|
|
|
32
|
+
| `result.output_text` | Final Markdown answer for chat / email / Slack |
|
|
33
|
+
| `result.output` | Legacy alias for `output_text` |
|
|
34
|
+
| `result.output_data` | Optional structured Hash for Rails branching (`nil` if text-only) |
|
|
35
|
+
| `result.items` | Typed turn: `message` (+ `result` when `output_data` present) |
|
|
36
|
+
| `result.format` | Always `"markdown"` for message content |
|
|
37
|
+
| `result.trace` | Tools / debug — Monitor, not the product answer |
|
|
38
|
+
|
|
39
|
+
```ruby
|
|
40
|
+
result = StoreAssistant.run("Where is ORD-1001?", session_id: "user-1")
|
|
41
|
+
puts result.output_text
|
|
42
|
+
payload = result.output_data # Hash or nil
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Consumption by taxonomy:
|
|
46
|
+
|
|
47
|
+
- **Knowledge** — render Markdown (`output_text`); tables for catalogs
|
|
48
|
+
- **Workflow** — show `output_text`; branch on `output_data` (status, ids)
|
|
49
|
+
- **Operations** — post `output_text`; handoff via `output_data`
|
|
50
|
+
- **Monitoring** — alert with `output_text`; automate from `output_data`
|
|
51
|
+
|
|
52
|
+
Public docs: https://rails-agent.com/docs/run-response
|
|
53
|
+
|
|
54
|
+
## Progressive path
|
|
55
|
+
|
|
56
|
+
### 1. Connect workspace
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
bundle add rails-agent-stack
|
|
60
|
+
bin/rails generate rails_agents:install
|
|
61
|
+
bin/dev # open http://localhost:3000/agents
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Sign up / connect at `/agents`. Platform API key is written to `config/rails_agents_credentials.yml` — **not** your OpenAI/Anthropic keys.
|
|
65
|
+
|
|
66
|
+
### 2. First agent: database Knowledge (fastest win)
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
bin/rails generate rails_agents:agent store_assistant --type knowledge --database
|
|
70
|
+
bin/rails db:seed # if demo data exists
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Edit `app/agents/store_assistant/agent.rb` — tools call your ActiveRecord models. Attach BYOK in cloud dashboard → **Settings → Providers** (reference name e.g. `:company_openai`).
|
|
74
|
+
|
|
75
|
+
```ruby
|
|
76
|
+
class StoreAssistant < RailsAgents::KnowledgeAgent
|
|
77
|
+
model :gpt_5_mini, provider: :openai, credential: :company_openai
|
|
78
|
+
memory :conversation, provider: :mem0, recall: 5
|
|
79
|
+
|
|
80
|
+
tool :lookup_order do |order_number:|
|
|
81
|
+
# wire to your models
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Test locally:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
bundle exec rails-agents run store_assistant "Where is order ORD-DEMO-1001?"
|
|
90
|
+
bundle exec rails-agents sync store_assistant
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Dashboard uses `GET /agents/schema` to discover tables for database setup — keep that endpoint available.
|
|
94
|
+
|
|
95
|
+
### 3. Tools
|
|
96
|
+
|
|
97
|
+
Add Ruby tool blocks in `agent.rb` or files under `tools/`. Tools run in your Rails app context.
|
|
98
|
+
Start with one read-only tool and test it before adding side effects.
|
|
99
|
+
|
|
100
|
+
### Workspace Library (share only when reuse is real)
|
|
101
|
+
|
|
102
|
+
Agent-specific capabilities stay under `app/agents/<slug>/`. Capabilities used
|
|
103
|
+
by multiple agents have one canonical source under:
|
|
104
|
+
|
|
105
|
+
```text
|
|
106
|
+
app/agents_library/
|
|
107
|
+
├── tools/
|
|
108
|
+
├── skills/
|
|
109
|
+
├── packages/
|
|
110
|
+
├── knowledge/
|
|
111
|
+
└── connectors/
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Attach shared sources through `app/agents/<slug>/imports.yml`:
|
|
115
|
+
|
|
116
|
+
```yaml
|
|
117
|
+
version: 1
|
|
118
|
+
imports:
|
|
119
|
+
- kind: skill
|
|
120
|
+
slug: triage
|
|
121
|
+
from: library/skills/triage.rb
|
|
122
|
+
- kind: knowledge
|
|
123
|
+
slug: shipping_policy
|
|
124
|
+
from: library/knowledge/shipping_policy.md
|
|
125
|
+
- kind: package
|
|
126
|
+
slug: frontend_design
|
|
127
|
+
from: library/packages/frontend_design
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
`bundle exec rails-agents sync NAME` safely resolves these paths and includes
|
|
131
|
+
them in the agent bundle. It fails on path traversal, missing sources, or a
|
|
132
|
+
conflict with an agent-local file. This keeps the Library canonical without
|
|
133
|
+
duplicating generated copies in Git.
|
|
134
|
+
|
|
135
|
+
Shared Ruby tool files are organization boundaries, not a new DSL. Register the
|
|
136
|
+
tool in `agent.rb` using the normal `tool` block and call the shared module or
|
|
137
|
+
service from that block.
|
|
138
|
+
|
|
139
|
+
### 4. Connectors
|
|
140
|
+
|
|
141
|
+
Add external SaaS integrations via Connect in the cloud dashboard (OAuth-managed actions). Use a local Ruby tool for your own database; use a connector for systems such as Notion, Sheets, or HubSpot.
|
|
142
|
+
|
|
143
|
+
### 5. Skills
|
|
144
|
+
|
|
145
|
+
Composable behaviors in `skills/` — reference with `skill :name, from: "skills/name.rb"`.
|
|
146
|
+
|
|
147
|
+
### 5b. Packages (agentic package manager)
|
|
148
|
+
|
|
149
|
+
**Package** is the installable primitive. Search Skills.sh, Microsoft APM, and
|
|
150
|
+
Smithery from the dashboard (**Library → Packages** or agent **Build → Packages**),
|
|
151
|
+
or via CLI:
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
bundle exec rails-agents packages "refund"
|
|
155
|
+
bundle exec rails-agents add-package skills_sh:owner/repo/skill \
|
|
156
|
+
--registry skills_sh --agent store_assistant --source owner/repo
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Rails Agent downloads the upstream package, converts it into:
|
|
160
|
+
|
|
161
|
+
```text
|
|
162
|
+
app/agents/<slug>/packages/<name>/package.yml
|
|
163
|
+
app/agents/<slug>/packages/<name>/SKILL.md
|
|
164
|
+
app/agents/<slug>/skills/<name>.rb # capability ready immediately
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
and can save it to the workspace Library like tools/skills/plugins.
|
|
168
|
+
|
|
169
|
+
| Primitive | Meaning |
|
|
170
|
+
|-----------|---------|
|
|
171
|
+
| **Tool** | One deterministic Ruby action |
|
|
172
|
+
| **Skill** | Multi-step playbook (how to do work) |
|
|
173
|
+
| **Package** | Installable capability from external registries |
|
|
174
|
+
| **Connector** | External SaaS (OAuth Connect) |
|
|
175
|
+
| **Knowledge** | Docs / DB sources for grounding |
|
|
176
|
+
| **Library** | Workspace reuse of any of the above |
|
|
177
|
+
|
|
178
|
+
### 6. Playbooks
|
|
179
|
+
|
|
180
|
+
Clone a Playbook when you want a proven starting structure, then customize the generated files locally. Playbooks can combine instructions, tools, and skills.
|
|
181
|
+
|
|
182
|
+
### 7. Channels
|
|
183
|
+
|
|
184
|
+
Scaffold stubs live in `channels/`. Install connectors from `/agents` dashboard (Slack, web chat, API, cron, etc.).
|
|
185
|
+
|
|
186
|
+
### 8. Evals
|
|
187
|
+
|
|
188
|
+
Add cases under `evals/*.yml`. Run on deploy from dashboard or `bundle exec rails-agents evals NAME`.
|
|
189
|
+
|
|
190
|
+
### 9. Deploy & monitor
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
bundle exec rails-agents deploy store_assistant
|
|
194
|
+
bundle exec rails-agents logs store_assistant
|
|
195
|
+
bundle exec rails-agents traces store_assistant
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
Use `/agents` for runs, cost, traces, and eval results.
|
|
199
|
+
|
|
200
|
+
## Model DSL (BYOK)
|
|
201
|
+
|
|
202
|
+
```ruby
|
|
203
|
+
# Explicit provider + cloud credential reference (no secrets in repo)
|
|
204
|
+
model :gpt_5_mini, provider: :openai, credential: :company_openai
|
|
205
|
+
|
|
206
|
+
# Legacy cloud-routed (still supported, not default in new scaffolds)
|
|
207
|
+
model :auto
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
Credential symbols map to encrypted records in Rails Agent Cloud — never commit API keys.
|
|
211
|
+
|
|
212
|
+
## Do not use (deprecated)
|
|
213
|
+
|
|
214
|
+
- **Chat authoring / cloud pull** — build locally; push with `rails-agents sync`. CLI `pull` remains for compatibility only.
|
|
215
|
+
|
|
216
|
+
## References
|
|
217
|
+
|
|
218
|
+
- Gem README: [README.md](README.md)
|
|
219
|
+
- Product spec: [docs/PRD.md](docs/PRD.md)
|
|
220
|
+
- Website: https://rails-agent.com/docs/getting-started
|
data/docs/PRD.md
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Rails Agent — Product Requirements Document
|
|
2
|
+
|
|
3
|
+
> **`rails-agent-stack` gem** (OSS, mounts into Rails) + **Rails Agent Cloud** (managed backend). Build agents locally with docs and external coding agents; test, deploy, and monitor at `/agents`.
|
|
4
|
+
|
|
5
|
+
## 1. Mission
|
|
6
|
+
|
|
7
|
+
Make Rails Agent the **fullstack agentic platform for Rails**: developers scaffold agents in `app/agents/`, attach **BYOK** model credentials in the cloud, and use `/agents` to test, deploy, and monitor — with clear docs (**AGENTS.md**) for humans and external coding agents.
|
|
8
|
+
|
|
9
|
+
## 2. Core Philosophy
|
|
10
|
+
|
|
11
|
+
1. **Documentation-first** — AGENTS.md progressive path; no chat-based authoring.
|
|
12
|
+
2. **Build in the repo** — Ruby agent directories, generators, external coding agents.
|
|
13
|
+
3. **BYOK models** — provider credentials stored encrypted in cloud; referenced from agent DSL.
|
|
14
|
+
4. **Four taxonomy types** — Knowledge, Workflow, Operations, Monitoring.
|
|
15
|
+
5. **Test → deploy → monitor in one place** — `/agents` dashboard embed.
|
|
16
|
+
6. **Transparent company billing** — fixed subscription + pass-through usage + 1% service fee.
|
|
17
|
+
|
|
18
|
+
## 3. Product Surface
|
|
19
|
+
|
|
20
|
+
### 3.1 `rails-agent-stack` gem
|
|
21
|
+
|
|
22
|
+
- Install: `bundle add rails-agent-stack` + `rails generate rails_agents:install`.
|
|
23
|
+
- Mountable engine at `/agents`: signup, connect, dashboard embed, **schema bridge** for DB setup.
|
|
24
|
+
- Agent-as-directory under `app/agents/<name>/`.
|
|
25
|
+
- **Product-facing taxonomy classes**: `KnowledgeAgent`, `WorkflowAgent`, `OperationsAgent`, `MonitoringAgent`.
|
|
26
|
+
- **DSL**:
|
|
27
|
+
|
|
28
|
+
```ruby
|
|
29
|
+
class StoreAssistant < RailsAgents::KnowledgeAgent
|
|
30
|
+
model :gpt_5_mini, provider: :openai, credential: :company_openai
|
|
31
|
+
memory :conversation
|
|
32
|
+
knowledge_from "knowledge/**/*"
|
|
33
|
+
|
|
34
|
+
tool :lookup_order do |order_number:|
|
|
35
|
+
Order.find_by(number: order_number).as_json
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
channel :web
|
|
39
|
+
end
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
- **CLI**: install, new, run, sync, deploy, logs, traces, evals. `pull` deprecated.
|
|
43
|
+
- **Generator**: `--type`, `--database` for first database Knowledge agent.
|
|
44
|
+
- Runtime: thin client to cloud for inference, deploys, observability. Tools execute in Rails app context.
|
|
45
|
+
|
|
46
|
+
### 3.2 Rails Agent Cloud
|
|
47
|
+
|
|
48
|
+
- Auth, workspaces (company-scoped), API keys.
|
|
49
|
+
- **Credential vault** for BYOK (OpenAI, Anthropic, etc.) — referenced by symbol from agents.
|
|
50
|
+
- Model gateway resolves agent model + credential ref.
|
|
51
|
+
- Deploys, channels, vector/RAG, evals, traces, billing.
|
|
52
|
+
- **Billing**: Stripe company subscription + metered usage at cost + 1% service fee.
|
|
53
|
+
- API: runs, deploys, knowledge sync, files sync, logs, traces, evals.
|
|
54
|
+
|
|
55
|
+
### 3.3 Dashboard
|
|
56
|
+
|
|
57
|
+
- Workspace: agents list, config (model/credential, tools, skills, memory, knowledge, channels, evals, deploy).
|
|
58
|
+
- **No Kip / chat authoring** — configuration and monitoring UI only.
|
|
59
|
+
- Schema discovery via parent page `GET /agents/schema`.
|
|
60
|
+
|
|
61
|
+
## 4. Pricing
|
|
62
|
+
|
|
63
|
+
- **Company subscription** — fixed monthly fee per workspace (production).
|
|
64
|
+
- **Metered usage** — provider tokens and infrastructure at **pass-through cost**.
|
|
65
|
+
- **Service fee** — **1%** on metered usage, shown transparently on invoices.
|
|
66
|
+
- Sandbox/dev tier for building (non-production traffic).
|
|
67
|
+
|
|
68
|
+
## 5. Non-Goals
|
|
69
|
+
|
|
70
|
+
- Chat-based agent authoring (removed).
|
|
71
|
+
- Storing provider API keys in the Rails app repo.
|
|
72
|
+
- Self-hosting / on-prem (cloud runtime).
|
|
73
|
+
- Non-Rails frameworks.
|
|
74
|
+
|
|
75
|
+
## 6. Milestones
|
|
76
|
+
|
|
77
|
+
1. **M1 — Gem + docs**: install, AGENTS.md, taxonomy, BYOK DSL, `--database` generator.
|
|
78
|
+
2. **M2 — Cloud BYOK + billing**: credential vault, company plans, usage metering + 1%.
|
|
79
|
+
3. **M3 — Channels + deploy**: Slack, web, API, cron end-to-end.
|
|
80
|
+
4. **M4 — GA**: evals, monitoring agents, plugins/skills/playbooks in dashboard.
|
|
81
|
+
|
|
82
|
+
## 7. SEO / Brand
|
|
83
|
+
|
|
84
|
+
- Name: **Rails Agent** / `rails-agent-stack`.
|
|
85
|
+
- Tone: confident, plainspoken, Rails-native.
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
**Instruction to implementers**: Gem and boilerplate follow this doc. Cloud dashboard must remove authoring chat and implement BYOK + company billing.
|
|
Binary file
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class Support < RailsAgents::KnowledgeAgent
|
|
4
|
+
model :gpt_5_mini, provider: :openai, credential: :company_openai
|
|
5
|
+
memory :conversation
|
|
6
|
+
knowledge_from "knowledge/**/*"
|
|
7
|
+
|
|
8
|
+
tool :lookup_order do |order_id:|
|
|
9
|
+
{ id: order_id, status: "shipped", note: "Example only � wire to your Order model." }
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
skill :triage, from: "skills/triage.rb"
|
|
13
|
+
channel :slack
|
|
14
|
+
end
|
|
File without changes
|