brainiac 0.0.10 → 0.0.12
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/Gemfile.lock +2 -2
- data/README.md +134 -151
- data/bin/brainiac +181 -109
- data/brainiac.gemspec +4 -3
- data/docs/waybar-config.md +7 -27
- data/lib/brainiac/agents.rb +5 -5
- data/lib/brainiac/config.rb +0 -36
- data/lib/brainiac/cron.rb +15 -17
- data/lib/brainiac/helpers.rb +58 -31
- data/lib/brainiac/hooks.rb +1 -1
- data/lib/brainiac/notifications.rb +2 -2
- data/lib/brainiac/prompts.rb +11 -133
- data/lib/brainiac/restart.rb +0 -3
- data/lib/brainiac/routes/api.rb +6 -32
- data/lib/brainiac/sessions.rb +1 -2
- data/lib/brainiac/version.rb +1 -1
- data/monitor/shared.rb +1 -1
- data/receiver.rb +2 -227
- data/templates/agents.json.example +2 -2
- data/templates/brainiac.json.example +1 -6
- data/templates/testflight.json.example +1 -1
- data/templates/users.json.example +20 -82
- metadata +5 -9
- data/lib/brainiac/handlers/github.rb +0 -390
- data/lib/brainiac/handlers/zoho.rb +0 -429
- data/lib/brainiac/zoho_mail_api.rb +0 -110
- data/templates/github.json.example +0 -4
- data/templates/zoho.json.example +0 -27
data/receiver.rb
CHANGED
|
@@ -34,17 +34,7 @@ module Brainiac
|
|
|
34
34
|
end
|
|
35
35
|
end
|
|
36
36
|
|
|
37
|
-
# ---
|
|
38
|
-
|
|
39
|
-
if handler_enabled?("github")
|
|
40
|
-
require_relative "lib/brainiac/handlers/github"
|
|
41
|
-
LOG.info "[Handlers] GitHub handler enabled"
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
if handler_enabled?("zoho")
|
|
45
|
-
require_relative "lib/brainiac/handlers/zoho"
|
|
46
|
-
LOG.info "[Handlers] Zoho handler enabled"
|
|
47
|
-
end
|
|
37
|
+
# --- Custom handlers + plugins ---
|
|
48
38
|
|
|
49
39
|
# Reload hook registry — custom handlers register callbacks here
|
|
50
40
|
module ReloadHooks
|
|
@@ -63,15 +53,11 @@ def register_reload_hook(name, &)
|
|
|
63
53
|
ReloadHooks.register(name, &)
|
|
64
54
|
end
|
|
65
55
|
|
|
66
|
-
# Load custom handlers from ~/.brainiac/handlers/ (plugin system)
|
|
56
|
+
# Load custom handlers from ~/.brainiac/handlers/ (legacy plugin system)
|
|
67
57
|
CUSTOM_HANDLERS_DIR = File.join(BRAINIAC_DIR, "handlers")
|
|
68
58
|
if Dir.exist?(CUSTOM_HANDLERS_DIR)
|
|
69
59
|
Dir.glob(File.join(CUSTOM_HANDLERS_DIR, "*.rb")).each do |handler|
|
|
70
60
|
handler_name = File.basename(handler, ".rb")
|
|
71
|
-
unless handler_enabled?(handler_name)
|
|
72
|
-
LOG.info "[Handlers] Skipping custom handler (disabled): #{handler_name}"
|
|
73
|
-
next
|
|
74
|
-
end
|
|
75
61
|
LOG.info "[Handlers] Loading custom handler: #{handler_name}"
|
|
76
62
|
require handler
|
|
77
63
|
end
|
|
@@ -136,211 +122,9 @@ end
|
|
|
136
122
|
before "/api/*" do
|
|
137
123
|
# Skip auth for all localhost requests (CLI, waybar, daemon, etc.)
|
|
138
124
|
pass if localhost_request?
|
|
139
|
-
# Skip auth for webhook-related routes that have their own verification
|
|
140
|
-
pass if request.path_info == "/api/discord"
|
|
141
125
|
authenticate_dashboard!
|
|
142
126
|
end
|
|
143
127
|
|
|
144
|
-
post "/github" do
|
|
145
|
-
content_type :json
|
|
146
|
-
request.body.rewind
|
|
147
|
-
payload_body = request.body.read
|
|
148
|
-
|
|
149
|
-
verify_github_signature!(request, payload_body)
|
|
150
|
-
|
|
151
|
-
payload = JSON.parse(payload_body)
|
|
152
|
-
event = request.env["HTTP_X_GITHUB_EVENT"]
|
|
153
|
-
|
|
154
|
-
reload_projects!
|
|
155
|
-
reload_agent_registry!
|
|
156
|
-
reload_github_config!
|
|
157
|
-
|
|
158
|
-
action = payload["action"]
|
|
159
|
-
|
|
160
|
-
case event
|
|
161
|
-
when "pull_request"
|
|
162
|
-
if action == "closed" && payload.dig("pull_request", "merged")
|
|
163
|
-
status_code, body = handle_github_pr_merged(payload)
|
|
164
|
-
halt status_code, body
|
|
165
|
-
elsif action == "opened"
|
|
166
|
-
track_pr_in_work_items(payload)
|
|
167
|
-
halt 200, { status: "processed", action: "pr_tracked" }.to_json
|
|
168
|
-
elsif action == "synchronize"
|
|
169
|
-
status_code, body = handle_github_pr_synchronized(payload)
|
|
170
|
-
halt status_code, body
|
|
171
|
-
else
|
|
172
|
-
halt 200, { status: "ignored", reason: "pull_request action: #{action}" }.to_json
|
|
173
|
-
end
|
|
174
|
-
when "pull_request_review"
|
|
175
|
-
if action == "submitted"
|
|
176
|
-
status_code, body = handle_github_pr_review_submitted(payload)
|
|
177
|
-
halt status_code, body
|
|
178
|
-
else
|
|
179
|
-
halt 200, { status: "ignored", reason: "pull_request_review action: #{action}" }.to_json
|
|
180
|
-
end
|
|
181
|
-
when "issue_comment"
|
|
182
|
-
if action == "created"
|
|
183
|
-
status_code, body = handle_github_issue_comment(payload)
|
|
184
|
-
halt status_code, body
|
|
185
|
-
else
|
|
186
|
-
halt 200, { status: "ignored", reason: "issue_comment action: #{action}" }.to_json
|
|
187
|
-
end
|
|
188
|
-
when "issues"
|
|
189
|
-
if action == "opened"
|
|
190
|
-
status_code, body = handle_github_issue_opened(payload)
|
|
191
|
-
halt status_code, body
|
|
192
|
-
else
|
|
193
|
-
halt 200, { status: "ignored", reason: "issues action: #{action}" }.to_json
|
|
194
|
-
end
|
|
195
|
-
when "workflow_run"
|
|
196
|
-
if action == "completed"
|
|
197
|
-
status_code, body = handle_github_workflow_run(payload)
|
|
198
|
-
halt status_code, body
|
|
199
|
-
else
|
|
200
|
-
halt 200, { status: "ignored", reason: "workflow_run action: #{action}" }.to_json
|
|
201
|
-
end
|
|
202
|
-
when "ping"
|
|
203
|
-
halt 200, { status: "pong" }.to_json
|
|
204
|
-
else
|
|
205
|
-
halt 200, { status: "ignored", event: event }.to_json
|
|
206
|
-
end
|
|
207
|
-
rescue JSON::ParserError => e
|
|
208
|
-
LOG.error "Invalid JSON: #{e.message}"
|
|
209
|
-
halt 400, { error: "Invalid JSON" }.to_json
|
|
210
|
-
rescue StandardError => e
|
|
211
|
-
LOG.error "Unhandled error: #{e.message}\n#{e.backtrace.first(5).join("\n")}"
|
|
212
|
-
halt 500, { error: e.message }.to_json
|
|
213
|
-
end
|
|
214
|
-
|
|
215
|
-
# --- Zoho Mail webhook route ---
|
|
216
|
-
|
|
217
|
-
if handler_enabled?("zoho")
|
|
218
|
-
post "/zoho" do
|
|
219
|
-
content_type :json
|
|
220
|
-
request.body.rewind
|
|
221
|
-
payload_body = request.body.read
|
|
222
|
-
|
|
223
|
-
# Zoho sends X-Hook-Secret on the very first request — capture and store it
|
|
224
|
-
hook_secret = request.env["HTTP_X_HOOK_SECRET"]
|
|
225
|
-
if hook_secret
|
|
226
|
-
save_zoho_hook_secret(hook_secret)
|
|
227
|
-
LOG.info "[Zoho] Received and stored hook_secret from initial handshake"
|
|
228
|
-
halt 200, { status: "hook_secret_received" }.to_json
|
|
229
|
-
end
|
|
230
|
-
|
|
231
|
-
verify_zoho_signature!(request, payload_body)
|
|
232
|
-
|
|
233
|
-
email = JSON.parse(payload_body)
|
|
234
|
-
LOG.info "[Zoho] Received email: subject=#{email["subject"]}, from=#{email["fromAddress"]}, to=#{email["toAddress"]}"
|
|
235
|
-
LOG.info "[Zoho] Payload keys: #{email.keys.sort.join(", ")}"
|
|
236
|
-
LOG.info "[Zoho] summary=#{email["summary"].to_s[0..200].inspect}, html=#{email["html"].to_s[0..200].inspect}, content=#{email["content"].to_s[0..200].inspect}"
|
|
237
|
-
|
|
238
|
-
# Dump raw payload for debugging (last 5 kept)
|
|
239
|
-
zoho_debug_dir = File.join(BRAINIAC_DIR, "tmp", "zoho", "payloads")
|
|
240
|
-
FileUtils.mkdir_p(zoho_debug_dir)
|
|
241
|
-
File.write(File.join(zoho_debug_dir, "#{Time.now.strftime("%Y%m%d-%H%M%S")}.json"), JSON.pretty_generate(email))
|
|
242
|
-
|
|
243
|
-
reload_zoho_config!
|
|
244
|
-
rule = match_zoho_rule(email)
|
|
245
|
-
|
|
246
|
-
if rule
|
|
247
|
-
LOG.info "[Zoho] Matched rule: #{rule["label"]}"
|
|
248
|
-
if rule["dispatch_agent"]
|
|
249
|
-
dispatch_zoho_triage(email, rule)
|
|
250
|
-
halt 200, { status: "triage_dispatched", rule: rule["label"], agent: rule["dispatch_agent"] }.to_json
|
|
251
|
-
else
|
|
252
|
-
notify_zoho_match(email, rule)
|
|
253
|
-
halt 200, { status: "matched", rule: rule["label"] }.to_json
|
|
254
|
-
end
|
|
255
|
-
else
|
|
256
|
-
LOG.info "[Zoho] No rules matched"
|
|
257
|
-
halt 200, { status: "no_match" }.to_json
|
|
258
|
-
end
|
|
259
|
-
rescue JSON::ParserError => e
|
|
260
|
-
LOG.error "[Zoho] Invalid JSON: #{e.message}"
|
|
261
|
-
halt 400, { error: "Invalid JSON" }.to_json
|
|
262
|
-
rescue StandardError => e
|
|
263
|
-
LOG.error "[Zoho] Unhandled error: #{e.message}\n#{e.backtrace.first(5).join("\n")}"
|
|
264
|
-
halt 500, { error: e.message }.to_json
|
|
265
|
-
end
|
|
266
|
-
end
|
|
267
|
-
|
|
268
|
-
# --- Zoho OAuth routes ---
|
|
269
|
-
|
|
270
|
-
if handler_enabled?("zoho")
|
|
271
|
-
ZOHO_AUTH_SCOPES = "ZohoMail.messages.READ,ZohoMail.accounts.READ,ZohoMail.folders.READ".freeze
|
|
272
|
-
|
|
273
|
-
get "/zoho/auth" do
|
|
274
|
-
reload_zoho_config!
|
|
275
|
-
api = ZOHO_CONFIG["api"] || {}
|
|
276
|
-
halt 500, "Missing client_id in zoho.json api section" unless api["client_id"]
|
|
277
|
-
|
|
278
|
-
redirect_uri = "#{request.base_url}/zoho/callback"
|
|
279
|
-
params = URI.encode_www_form(
|
|
280
|
-
scope: ZOHO_AUTH_SCOPES,
|
|
281
|
-
client_id: api["client_id"],
|
|
282
|
-
response_type: "code",
|
|
283
|
-
access_type: "offline",
|
|
284
|
-
redirect_uri: redirect_uri,
|
|
285
|
-
prompt: "consent"
|
|
286
|
-
)
|
|
287
|
-
redirect "https://accounts.zoho.com/oauth/v2/auth?#{params}"
|
|
288
|
-
end
|
|
289
|
-
|
|
290
|
-
get "/zoho/callback" do
|
|
291
|
-
content_type :html
|
|
292
|
-
code = params["code"]
|
|
293
|
-
halt 400, "No authorization code received" unless code
|
|
294
|
-
|
|
295
|
-
reload_zoho_config!
|
|
296
|
-
api = ZOHO_CONFIG["api"] || {}
|
|
297
|
-
redirect_uri = "#{request.base_url}/zoho/callback"
|
|
298
|
-
|
|
299
|
-
uri = URI(ZOHO_TOKEN_URL)
|
|
300
|
-
res = Net::HTTP.post_form(uri, {
|
|
301
|
-
"grant_type" => "authorization_code",
|
|
302
|
-
"client_id" => api["client_id"],
|
|
303
|
-
"client_secret" => api["client_secret"],
|
|
304
|
-
"code" => code,
|
|
305
|
-
"redirect_uri" => redirect_uri
|
|
306
|
-
})
|
|
307
|
-
|
|
308
|
-
data = JSON.parse(res.body)
|
|
309
|
-
if data["refresh_token"]
|
|
310
|
-
ZOHO_CONFIG["api"] ||= {}
|
|
311
|
-
ZOHO_CONFIG["api"]["refresh_token"] = data["refresh_token"]
|
|
312
|
-
@zoho_access_token = data["access_token"]
|
|
313
|
-
@zoho_token_expires_at = Time.now + 3300
|
|
314
|
-
File.write(ZOHO_CONFIG_FILE, JSON.pretty_generate(ZOHO_CONFIG))
|
|
315
|
-
LOG.info "[Zoho:OAuth] Stored refresh_token and access_token"
|
|
316
|
-
|
|
317
|
-
# Auto-fetch account_id if not set
|
|
318
|
-
unless ZOHO_CONFIG.dig("api", "account_id")
|
|
319
|
-
acct_uri = URI(ZOHO_MAIL_API_BASE.to_s)
|
|
320
|
-
http = Net::HTTP.new(acct_uri.host, acct_uri.port)
|
|
321
|
-
http.use_ssl = true
|
|
322
|
-
req = Net::HTTP::Get.new(acct_uri)
|
|
323
|
-
req["Authorization"] = "Zoho-oauthtoken #{@zoho_access_token}"
|
|
324
|
-
acct_res = http.request(req)
|
|
325
|
-
acct_data = JSON.parse(acct_res.body)
|
|
326
|
-
if (account_id = acct_data.dig("data", 0, "accountId"))
|
|
327
|
-
ZOHO_CONFIG["api"]["account_id"] = account_id
|
|
328
|
-
File.write(ZOHO_CONFIG_FILE, JSON.pretty_generate(ZOHO_CONFIG))
|
|
329
|
-
LOG.info "[Zoho:OAuth] Auto-fetched account_id: #{account_id}"
|
|
330
|
-
end
|
|
331
|
-
end
|
|
332
|
-
|
|
333
|
-
"<h1>✅ Zoho OAuth Complete</h1><p>Refresh token and account_id saved to zoho.json. You can close this tab.</p>"
|
|
334
|
-
else
|
|
335
|
-
LOG.error "[Zoho:OAuth] Token exchange failed: #{data}"
|
|
336
|
-
"<h1>❌ OAuth Failed</h1><pre>#{data.to_json}</pre>"
|
|
337
|
-
end
|
|
338
|
-
rescue StandardError => e
|
|
339
|
-
LOG.error "[Zoho:OAuth] Error: #{e.message}"
|
|
340
|
-
"<h1>❌ Error</h1><pre>#{e.message}</pre>"
|
|
341
|
-
end
|
|
342
|
-
end
|
|
343
|
-
|
|
344
128
|
# --- Admin API routes ---
|
|
345
129
|
require_relative "lib/brainiac/routes/api"
|
|
346
130
|
|
|
@@ -364,15 +148,6 @@ get "/dashboard" do
|
|
|
364
148
|
erb :dashboard, layout: false
|
|
365
149
|
end
|
|
366
150
|
|
|
367
|
-
# --- Discord fallback (plugin handles startup when installed) ---
|
|
368
|
-
|
|
369
|
-
unless Brainiac.channel_prompts[:discord]
|
|
370
|
-
get "/api/discord" do
|
|
371
|
-
content_type :json
|
|
372
|
-
{ enabled: false, reason: "brainiac-discord plugin not installed" }.to_json
|
|
373
|
-
end
|
|
374
|
-
end
|
|
375
|
-
|
|
376
151
|
start_brainiac_restart_monitor
|
|
377
152
|
|
|
378
153
|
LOG.info "[Cron] Starting cron thread..."
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"signing_secret": "YOUR_APPLE_WEBHOOK_SIGNING_SECRET",
|
|
3
3
|
"discord_channel_id": "CHANNEL_ID_FOR_TESTFLIGHT_NOTIFICATIONS",
|
|
4
|
-
"notify_as": "
|
|
4
|
+
"notify_as": "merlin",
|
|
5
5
|
"api_key_path": "~/.appstoreconnect/AuthKey_6VBGCK56SQ.p8",
|
|
6
6
|
"api_key_id": "6VBGCK56SQ",
|
|
7
7
|
"issuer_id": "337a9282-6778-4fe4-bdbb-fd2845ef0c19"
|
|
@@ -1,118 +1,56 @@
|
|
|
1
1
|
{
|
|
2
2
|
"users": [
|
|
3
3
|
{
|
|
4
|
-
"canonical_name": "
|
|
4
|
+
"canonical_name": "Jane Smith",
|
|
5
5
|
"identities": {
|
|
6
6
|
"discord": {
|
|
7
|
-
"username": "
|
|
8
|
-
"user_id": "
|
|
9
|
-
"display_name": "
|
|
7
|
+
"username": "janesmith",
|
|
8
|
+
"user_id": "123456789012345678",
|
|
9
|
+
"display_name": "janesmith"
|
|
10
10
|
},
|
|
11
11
|
"github": {
|
|
12
|
-
"username": "
|
|
13
|
-
},
|
|
14
|
-
},
|
|
15
|
-
"aliases": ["Andy"],
|
|
16
|
-
"relationships": {
|
|
17
|
-
"spouse": "Larissa"
|
|
18
|
-
},
|
|
19
|
-
"notes": "Primary user"
|
|
20
|
-
},
|
|
21
|
-
{
|
|
22
|
-
"canonical_name": "Andy Davis",
|
|
23
|
-
"identities": {
|
|
24
|
-
"discord": {
|
|
25
|
-
"username": "ardavis",
|
|
26
|
-
"user_id": "397928984232591361",
|
|
27
|
-
"display_name": "ardavis"
|
|
28
|
-
},
|
|
29
|
-
"github": {
|
|
30
|
-
"username": "ardavis"
|
|
31
|
-
}
|
|
32
|
-
},
|
|
33
|
-
"aliases": [],
|
|
34
|
-
"relationships": {},
|
|
35
|
-
"notes": "Works with Adam on brainiac development"
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
"canonical_name": "Kaylee",
|
|
39
|
-
"identities": {
|
|
40
|
-
"discord": {
|
|
41
|
-
"username": "kaylee",
|
|
42
|
-
"user_id": "1475961955125825687",
|
|
43
|
-
"display_name": "Kaylee"
|
|
12
|
+
"username": "jsmith"
|
|
44
13
|
}
|
|
45
14
|
},
|
|
46
|
-
"aliases": [],
|
|
47
|
-
"
|
|
48
|
-
"notes": "AI agent - cheerful, optimistic, loves fixing things"
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
"canonical_name": "Sleeper Service",
|
|
52
|
-
"identities": {
|
|
53
|
-
"discord": {
|
|
54
|
-
"username": "sleeper_service",
|
|
55
|
-
"user_id": "1476572591220199514",
|
|
56
|
-
"display_name": "Sleeper Service"
|
|
57
|
-
}
|
|
58
|
-
},
|
|
59
|
-
"aliases": [],
|
|
60
|
-
"relationships": {},
|
|
61
|
-
"notes": "AI agent - dry wit, cosmic perspective, understated"
|
|
62
|
-
},
|
|
63
|
-
{
|
|
64
|
-
"canonical_name": "Avon",
|
|
65
|
-
"identities": {
|
|
66
|
-
"discord": {
|
|
67
|
-
"username": "avon",
|
|
68
|
-
"user_id": "1476683857922228386",
|
|
69
|
-
"display_name": "Avon"
|
|
70
|
-
}
|
|
71
|
-
},
|
|
72
|
-
"aliases": [],
|
|
73
|
-
"relationships": {},
|
|
74
|
-
"notes": "AI agent - iOS specialist, pragmatic, competence-driven"
|
|
15
|
+
"aliases": ["Jane"],
|
|
16
|
+
"notes": "Primary user"
|
|
75
17
|
},
|
|
76
18
|
{
|
|
77
|
-
"canonical_name": "
|
|
19
|
+
"canonical_name": "Sherlock",
|
|
78
20
|
"identities": {
|
|
79
21
|
"discord": {
|
|
80
|
-
"username": "
|
|
81
|
-
"user_id": "
|
|
82
|
-
"display_name": "
|
|
22
|
+
"username": "sherlock",
|
|
23
|
+
"user_id": "234567890123456789",
|
|
24
|
+
"display_name": "Sherlock"
|
|
83
25
|
}
|
|
84
26
|
},
|
|
85
27
|
"aliases": [],
|
|
86
|
-
"relationships": {},
|
|
87
28
|
"notes": "AI agent"
|
|
88
29
|
},
|
|
89
30
|
{
|
|
90
|
-
"canonical_name": "
|
|
31
|
+
"canonical_name": "Robin",
|
|
91
32
|
"identities": {
|
|
92
33
|
"discord": {
|
|
93
|
-
"username": "
|
|
94
|
-
"user_id": "
|
|
95
|
-
"display_name": "
|
|
34
|
+
"username": "robin",
|
|
35
|
+
"user_id": "345678901234567890",
|
|
36
|
+
"display_name": "Robin"
|
|
96
37
|
}
|
|
97
38
|
},
|
|
98
39
|
"aliases": [],
|
|
99
|
-
"relationships": {},
|
|
100
40
|
"notes": "AI agent"
|
|
101
41
|
},
|
|
102
42
|
{
|
|
103
|
-
"canonical_name": "
|
|
43
|
+
"canonical_name": "Merlin",
|
|
104
44
|
"identities": {
|
|
105
45
|
"discord": {
|
|
106
|
-
"username": "
|
|
107
|
-
"user_id": "
|
|
108
|
-
"display_name": "
|
|
46
|
+
"username": "merlin",
|
|
47
|
+
"user_id": "456789012345678901",
|
|
48
|
+
"display_name": "Merlin"
|
|
109
49
|
}
|
|
110
50
|
},
|
|
111
51
|
"aliases": [],
|
|
112
|
-
"relationships": {},
|
|
113
52
|
"notes": "AI agent"
|
|
114
53
|
}
|
|
115
54
|
],
|
|
116
|
-
"schema_version": "1.0"
|
|
117
|
-
"last_updated": "2026-02-27T13:52:22-05:00"
|
|
55
|
+
"schema_version": "1.0"
|
|
118
56
|
}
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: brainiac
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.12
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Andy Davis
|
|
@@ -107,8 +107,9 @@ dependencies:
|
|
|
107
107
|
- - "~>"
|
|
108
108
|
- !ruby/object:Gem::Version
|
|
109
109
|
version: '1.25'
|
|
110
|
-
description:
|
|
111
|
-
|
|
110
|
+
description: 'Core orchestration engine that manages AI agent identity, long-term
|
|
111
|
+
memory (brain), prompt construction, and dispatch. Communication channels are provided
|
|
112
|
+
by plugins: brainiac-discord, brainiac-fizzy, brainiac-github, and more.'
|
|
112
113
|
executables:
|
|
113
114
|
- brainiac
|
|
114
115
|
extensions: []
|
|
@@ -128,10 +129,8 @@ files:
|
|
|
128
129
|
- lib/brainiac/brain.rb
|
|
129
130
|
- lib/brainiac/config.rb
|
|
130
131
|
- lib/brainiac/cron.rb
|
|
131
|
-
- lib/brainiac/handlers/github.rb
|
|
132
132
|
- lib/brainiac/handlers/shared/git.rb
|
|
133
133
|
- lib/brainiac/handlers/shared/inline_tags.rb
|
|
134
|
-
- lib/brainiac/handlers/zoho.rb
|
|
135
134
|
- lib/brainiac/helpers.rb
|
|
136
135
|
- lib/brainiac/hooks.rb
|
|
137
136
|
- lib/brainiac/notifications.rb
|
|
@@ -143,7 +142,6 @@ files:
|
|
|
143
142
|
- lib/brainiac/skills.rb
|
|
144
143
|
- lib/brainiac/users.rb
|
|
145
144
|
- lib/brainiac/version.rb
|
|
146
|
-
- lib/brainiac/zoho_mail_api.rb
|
|
147
145
|
- monitor/daemon.rb
|
|
148
146
|
- monitor/shared.rb
|
|
149
147
|
- monitor/waybar/deploy_env.rb
|
|
@@ -161,14 +159,12 @@ files:
|
|
|
161
159
|
- templates/brainiac.json.example
|
|
162
160
|
- templates/cli-providers/grok.json.example
|
|
163
161
|
- templates/cli-providers/kiro.json.example
|
|
164
|
-
- templates/github.json.example
|
|
165
162
|
- templates/plugins.json.example
|
|
166
163
|
- templates/roles/code-reviewer.md.example
|
|
167
164
|
- templates/roles/general-engineer.md.example
|
|
168
165
|
- templates/roles/test-engineer.md.example
|
|
169
166
|
- templates/testflight.json.example
|
|
170
167
|
- templates/users.json.example
|
|
171
|
-
- templates/zoho.json.example
|
|
172
168
|
- views/dashboard.erb
|
|
173
169
|
homepage: https://github.com/stowzilla/brainiac
|
|
174
170
|
licenses:
|
|
@@ -191,5 +187,5 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
191
187
|
requirements: []
|
|
192
188
|
rubygems_version: 3.6.9
|
|
193
189
|
specification_version: 4
|
|
194
|
-
summary:
|
|
190
|
+
summary: Multi-agent orchestration layer for developer workflows
|
|
195
191
|
test_files: []
|