brainiac 0.0.6 → 0.0.8
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 +136 -6
- data/bin/brainiac +472 -44
- data/bin/brainiac-completion.bash +1 -1
- data/lib/brainiac/agents.rb +27 -74
- data/lib/brainiac/brain.rb +6 -6
- data/lib/brainiac/config.rb +40 -76
- data/lib/brainiac/handlers/discord/api.rb +196 -0
- data/lib/brainiac/handlers/discord/config.rb +134 -0
- data/lib/brainiac/handlers/discord/delivery.rb +196 -0
- data/lib/brainiac/handlers/discord/gateway.rb +212 -0
- data/lib/brainiac/handlers/discord/message.rb +933 -0
- data/lib/brainiac/handlers/discord/reactions.rb +215 -0
- data/lib/brainiac/handlers/discord.rb +14 -1892
- data/lib/brainiac/handlers/github.rb +134 -317
- data/lib/brainiac/handlers/shared/git.rb +190 -0
- data/lib/brainiac/handlers/shared/inline_tags.rb +89 -0
- data/lib/brainiac/handlers/zoho.rb +103 -153
- data/lib/brainiac/helpers.rb +43 -455
- data/lib/brainiac/hooks.rb +86 -0
- data/lib/brainiac/plugins.rb +154 -0
- data/lib/brainiac/prompts.rb +34 -172
- data/lib/brainiac/restart.rb +112 -0
- data/lib/brainiac/routes/api.rb +411 -0
- data/lib/brainiac/users.rb +1 -7
- data/lib/brainiac/version.rb +1 -1
- data/lib/brainiac/zoho_mail_api.rb +2 -1
- data/lib/brainiac.rb +8 -1
- data/monitor/daemon.rb +4 -27
- data/monitor/shared.rb +247 -0
- data/monitor/{waybar-deploy-env.rb → waybar/deploy_env.rb} +17 -89
- data/monitor/waybar/setup.rb +232 -0
- data/monitor/waybar/status.rb +51 -0
- data/monitor/{view-logs-rofi.rb → waybar/view_logs.rb} +21 -88
- data/monitor/{deploy-env-macos.rb → xbar/deploy_env.rb} +3 -2
- data/monitor/xbar/plugin.rb +149 -0
- data/monitor/{setup-menubar.rb → xbar/setup.rb} +14 -30
- data/receiver.rb +44 -551
- data/templates/agents.json.example +1 -2
- data/templates/brainiac.json.example +8 -0
- data/templates/cli-providers/kiro.json.example +8 -2
- data/templates/plugins.json.example +3 -0
- data/templates/users.json.example +0 -3
- metadata +25 -23
- data/lib/brainiac/card_index.rb +0 -389
- data/lib/brainiac/deployments.rb +0 -258
- data/lib/brainiac/handlers/fizzy.rb +0 -1292
- data/lib/brainiac/planning.rb +0 -237
- data/lib/user_registry.rb +0 -159
- data/monitor/menubar.rb +0 -295
- data/monitor/setup-waybar-deploy-envs.rb +0 -121
- data/monitor/setup-waybar-deployments.rb +0 -96
- data/monitor/setup-waybar-module.rb +0 -113
- data/monitor/setup-xbar-plugin.rb +0 -35
- data/monitor/view-logs.rb +0 -119
- data/monitor/waybar-config-updater.rb +0 -56
- data/monitor/waybar-deployments.rb +0 -239
- data/monitor/waybar.rb +0 -146
- data/monitor/xbar.3s.rb +0 -179
- data/templates/fizzy.json.example +0 -24
- /data/monitor/{open-action.sh → xbar/open_action.sh} +0 -0
- /data/monitor/{view-logs-macos.rb → xbar/view_logs.rb} +0 -0
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
# frozen_string_literal: true
|
|
3
|
-
|
|
4
|
-
# One-time setup: replaces the single brainiac-deployments module
|
|
5
|
-
# with per-environment modules so each dot gets its own border/click.
|
|
6
|
-
|
|
7
|
-
require "json"
|
|
8
|
-
require "fileutils"
|
|
9
|
-
|
|
10
|
-
WAYBAR_CONFIG = File.expand_path("~/.config/waybar/config.jsonc")
|
|
11
|
-
DEPLOY_SCRIPT = File.expand_path("~/.brainiac/bin/waybar-deploy-env")
|
|
12
|
-
DEPLOYMENTS_CONFIG = File.expand_path("~/.brainiac/deployments.json")
|
|
13
|
-
WAYBAR_STYLE = File.expand_path("~/.config/waybar/style.css")
|
|
14
|
-
|
|
15
|
-
# Create wrapper script that resolves from server.root
|
|
16
|
-
wrapper_dir = File.expand_path("~/.brainiac/bin")
|
|
17
|
-
FileUtils.mkdir_p(wrapper_dir)
|
|
18
|
-
File.write(DEPLOY_SCRIPT, <<~SCRIPT)
|
|
19
|
-
#!/usr/bin/env ruby
|
|
20
|
-
root_file = File.expand_path("~/.brainiac/server.root")
|
|
21
|
-
if File.exist?(root_file)
|
|
22
|
-
server_root = File.read(root_file).strip
|
|
23
|
-
script = File.join(server_root, "monitor", "waybar-deploy-env.rb")
|
|
24
|
-
if File.exist?(script)
|
|
25
|
-
ARGV.unshift if ARGV.empty?
|
|
26
|
-
load script
|
|
27
|
-
exit
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
require "json"
|
|
31
|
-
puts({ text: "", tooltip: "Brainiac server root not found", class: "error" }.to_json)
|
|
32
|
-
SCRIPT
|
|
33
|
-
File.chmod(0o755, DEPLOY_SCRIPT)
|
|
34
|
-
|
|
35
|
-
def load_config
|
|
36
|
-
content = File.read(WAYBAR_CONFIG)
|
|
37
|
-
json_content = content.lines.reject { |line| line.strip.start_with?("//") }.join
|
|
38
|
-
JSON.parse(json_content)
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
def save_config(config)
|
|
42
|
-
File.write(WAYBAR_CONFIG, JSON.pretty_generate(config))
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
deployments = JSON.parse(File.read(DEPLOYMENTS_CONFIG))
|
|
46
|
-
envs = deployments["environments"].keys
|
|
47
|
-
|
|
48
|
-
config = load_config
|
|
49
|
-
|
|
50
|
-
# Remove old single deployments module from all bar positions
|
|
51
|
-
%w[modules-left modules-center modules-right].each do |pos|
|
|
52
|
-
next unless config[pos]
|
|
53
|
-
|
|
54
|
-
config[pos].reject! { |m| m.to_s.include?("brainiac-deploy") }
|
|
55
|
-
end
|
|
56
|
-
config.delete("custom/brainiac-deployments")
|
|
57
|
-
|
|
58
|
-
# Remove any existing per-env modules
|
|
59
|
-
config.each_key do |key|
|
|
60
|
-
config.delete(key) if key.start_with?("custom/brainiac-deploy-")
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
# Insert per-env modules into modules-center, before custom/brainiac
|
|
64
|
-
center = config["modules-center"] || []
|
|
65
|
-
zc_idx = center.index("custom/brainiac") || center.length
|
|
66
|
-
envs.each_with_index do |env, i|
|
|
67
|
-
mod_name = "custom/brainiac-deploy-#{env}"
|
|
68
|
-
center.insert(zc_idx + i, mod_name) unless center.include?(mod_name)
|
|
69
|
-
end
|
|
70
|
-
config["modules-center"] = center
|
|
71
|
-
|
|
72
|
-
# Add module configs for each env
|
|
73
|
-
envs.each do |env|
|
|
74
|
-
mod_name = "custom/brainiac-deploy-#{env}"
|
|
75
|
-
config[mod_name] = {
|
|
76
|
-
"exec" => "#{DEPLOY_SCRIPT} #{env}",
|
|
77
|
-
"return-type" => "json",
|
|
78
|
-
"interval" => 30,
|
|
79
|
-
"format" => "{}",
|
|
80
|
-
"tooltip" => true,
|
|
81
|
-
"escape" => false,
|
|
82
|
-
"on-click" => "#{DEPLOY_SCRIPT} #{env} --click",
|
|
83
|
-
"on-click-right" => "#{DEPLOY_SCRIPT} #{env} --deploy"
|
|
84
|
-
}
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
save_config(config)
|
|
88
|
-
puts "✓ Added per-environment deploy modules: #{envs.map { |e| "custom/brainiac-deploy-#{e}" }.join(", ")}"
|
|
89
|
-
|
|
90
|
-
# Update CSS — remove old single-module styles, add per-env styles
|
|
91
|
-
style = File.read(WAYBAR_STYLE)
|
|
92
|
-
|
|
93
|
-
# Remove old block
|
|
94
|
-
style.gsub!(%r{/\* Brainiac deployment environment dots \*/.*?(?=\n\n|\n/\*|\z)}m, "")
|
|
95
|
-
style.gsub!(/\n*#custom-brainiac-deployments[^{]*\{[^}]*\}\n*/m, "")
|
|
96
|
-
|
|
97
|
-
# Add new per-env styles
|
|
98
|
-
unless style.include?("#custom-brainiac-deploy-")
|
|
99
|
-
css = <<~CSS
|
|
100
|
-
|
|
101
|
-
/* Brainiac per-environment deploy dots */
|
|
102
|
-
[id^="custom-brainiac-deploy-"] {
|
|
103
|
-
font-size: 28px;
|
|
104
|
-
padding: 0 6px;
|
|
105
|
-
border-radius: 8px;
|
|
106
|
-
border: 2px solid transparent;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
[id^="custom-brainiac-deploy-"].deploy-recent {
|
|
110
|
-
border: 2px solid #4488ff;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
[id^="custom-brainiac-deploy-"].deploy-failed {
|
|
114
|
-
border: 2px solid #ff4444;
|
|
115
|
-
}
|
|
116
|
-
CSS
|
|
117
|
-
File.write(WAYBAR_STYLE, "#{style.strip}\n#{css}")
|
|
118
|
-
puts "✓ Updated waybar CSS with per-environment border styles"
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
puts "✓ Restart waybar to apply: omarchy restart waybar"
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
# frozen_string_literal: true
|
|
3
|
-
|
|
4
|
-
# One-time setup: adds Brainiac deployments module to waybar config
|
|
5
|
-
# and repositions the agent session module with more breathing room.
|
|
6
|
-
|
|
7
|
-
require "json"
|
|
8
|
-
|
|
9
|
-
WAYBAR_CONFIG = File.expand_path("~/.config/waybar/config.jsonc")
|
|
10
|
-
DEPLOY_SCRIPT = File.expand_path("~/Code/brainiac/monitor/waybar-deployments.rb")
|
|
11
|
-
WAYBAR_STYLE = File.expand_path("~/.config/waybar/style.css")
|
|
12
|
-
|
|
13
|
-
def load_config
|
|
14
|
-
content = File.read(WAYBAR_CONFIG)
|
|
15
|
-
json_content = content.lines.reject { |line| line.strip.start_with?("//") }.join
|
|
16
|
-
JSON.parse(json_content)
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def save_config(config)
|
|
20
|
-
File.write(WAYBAR_CONFIG, JSON.pretty_generate(config))
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
config = load_config
|
|
24
|
-
|
|
25
|
-
# Remove any existing deployment module
|
|
26
|
-
config["modules-center"]&.reject! { |m| m.to_s.include?("brainiac-deploy") }
|
|
27
|
-
config["modules-right"]&.reject! { |m| m.to_s.include?("brainiac-deploy") }
|
|
28
|
-
config.delete("custom/brainiac-deployments")
|
|
29
|
-
|
|
30
|
-
# Move agent session module from modules-right to modules-center (after indicators)
|
|
31
|
-
if config["modules-right"]&.delete("custom/brainiac")
|
|
32
|
-
config["modules-center"] ||= []
|
|
33
|
-
config["modules-center"] << "custom/brainiac" unless config["modules-center"].include?("custom/brainiac")
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
# Add deployments module right before agent sessions in modules-center
|
|
37
|
-
center = config["modules-center"] || []
|
|
38
|
-
zc_idx = center.index("custom/brainiac")
|
|
39
|
-
if zc_idx
|
|
40
|
-
center.insert(zc_idx, "custom/brainiac-deployments") unless center.include?("custom/brainiac-deployments")
|
|
41
|
-
else
|
|
42
|
-
center << "custom/brainiac-deployments" unless center.include?("custom/brainiac-deployments")
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
# Add module config
|
|
46
|
-
config["custom/brainiac-deployments"] = {
|
|
47
|
-
"exec" => DEPLOY_SCRIPT,
|
|
48
|
-
"return-type" => "json",
|
|
49
|
-
"interval" => 30,
|
|
50
|
-
"format" => "{}",
|
|
51
|
-
"tooltip" => true,
|
|
52
|
-
"format-alt" => "{}",
|
|
53
|
-
"escape" => false,
|
|
54
|
-
"on-click" => "#{DEPLOY_SCRIPT} --click",
|
|
55
|
-
"on-click-right" => "#{DEPLOY_SCRIPT} --deploy"
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
save_config(config)
|
|
59
|
-
|
|
60
|
-
# Add CSS for the deployments module
|
|
61
|
-
style = File.read(WAYBAR_STYLE)
|
|
62
|
-
unless style.include?("#custom-brainiac-deployments")
|
|
63
|
-
css = <<~CSS
|
|
64
|
-
|
|
65
|
-
/* Brainiac deployment environment dots */
|
|
66
|
-
#custom-brainiac-deployments {
|
|
67
|
-
margin-left: 100px;
|
|
68
|
-
margin-right: 40px;
|
|
69
|
-
font-size: 14px;
|
|
70
|
-
}
|
|
71
|
-
CSS
|
|
72
|
-
File.write(WAYBAR_STYLE, style + css)
|
|
73
|
-
puts "✓ Added deployment styles to waybar CSS"
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
# Add padding-right to agent sessions module
|
|
77
|
-
unless style.include?("padding-right") && style.include?("#custom-brainiac")
|
|
78
|
-
updated_style = File.read(WAYBAR_STYLE)
|
|
79
|
-
if updated_style.include?("#custom-brainiac {")
|
|
80
|
-
updated_style.sub!(/(#custom-brainiac\s*\{[^}]*)(\})/) do
|
|
81
|
-
block = Regexp.last_match(1)
|
|
82
|
-
close = Regexp.last_match(2)
|
|
83
|
-
if block.include?("padding-right")
|
|
84
|
-
"#{block}#{close}"
|
|
85
|
-
else
|
|
86
|
-
"#{block}\n padding-right: 100px;\n#{close}"
|
|
87
|
-
end
|
|
88
|
-
end
|
|
89
|
-
File.write(WAYBAR_STYLE, updated_style)
|
|
90
|
-
puts "✓ Added padding-right to agent session module"
|
|
91
|
-
end
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
puts "✓ Deployments module added to waybar config"
|
|
95
|
-
puts " Positioned: [deploy-dots] [agent-sessions] in center bar"
|
|
96
|
-
puts " Restart waybar to apply: omarchy restart waybar"
|
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
# frozen_string_literal: true
|
|
3
|
-
|
|
4
|
-
# One-time setup script to add Brainiac module to waybar config
|
|
5
|
-
# Run this once, then the module will update dynamically without config rewrites
|
|
6
|
-
|
|
7
|
-
require "json"
|
|
8
|
-
require "fileutils"
|
|
9
|
-
|
|
10
|
-
WAYBAR_CONFIG = File.expand_path("~/.config/waybar/config.jsonc")
|
|
11
|
-
WAYBAR_SCRIPT = File.expand_path("~/.brainiac/bin/waybar-status")
|
|
12
|
-
|
|
13
|
-
# Create a wrapper script that resolves the running server's waybar.rb dynamically
|
|
14
|
-
wrapper_dir = File.expand_path("~/.brainiac/bin")
|
|
15
|
-
FileUtils.mkdir_p(wrapper_dir)
|
|
16
|
-
wrapper_path = File.join(wrapper_dir, "waybar-status")
|
|
17
|
-
File.write(wrapper_path, <<~SCRIPT)
|
|
18
|
-
#!/usr/bin/env ruby
|
|
19
|
-
# Resolves the running Brainiac server's waybar module dynamically.
|
|
20
|
-
# This allows worktrees / branches to work without reconfiguring waybar.
|
|
21
|
-
|
|
22
|
-
root_file = File.expand_path("~/.brainiac/server.root")
|
|
23
|
-
if File.exist?(root_file)
|
|
24
|
-
server_root = File.read(root_file).strip
|
|
25
|
-
waybar_script = File.join(server_root, "monitor", "waybar.rb")
|
|
26
|
-
if File.exist?(waybar_script)
|
|
27
|
-
load waybar_script
|
|
28
|
-
exit
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
# Fallback: no server root known, try the API directly
|
|
33
|
-
require "json"
|
|
34
|
-
require "net/http"
|
|
35
|
-
|
|
36
|
-
begin
|
|
37
|
-
uri = URI("http://localhost:4567/api/status")
|
|
38
|
-
response = Net::HTTP.get_response(uri)
|
|
39
|
-
if response.is_a?(Net::HTTPSuccess)
|
|
40
|
-
data = JSON.parse(response.body)
|
|
41
|
-
sessions = data["sessions"] || []
|
|
42
|
-
if sessions.empty?
|
|
43
|
-
puts({ text: "💤", tooltip: "No active agent sessions", class: "idle" }.to_json)
|
|
44
|
-
else
|
|
45
|
-
puts({ text: "🟢 \#{sessions.size}", tooltip: sessions.map { |s| s["agent"] }.join(", "), class: "working" }.to_json)
|
|
46
|
-
end
|
|
47
|
-
else
|
|
48
|
-
puts({ text: "⚠️", tooltip: "Brainiac Error: HTTP \#{response.code}", class: "error" }.to_json)
|
|
49
|
-
end
|
|
50
|
-
rescue StandardError => e
|
|
51
|
-
puts({ text: "⚠️", tooltip: "Brainiac Error: \#{e.message}", class: "error" }.to_json)
|
|
52
|
-
end
|
|
53
|
-
SCRIPT
|
|
54
|
-
File.chmod(0o755, wrapper_path)
|
|
55
|
-
|
|
56
|
-
def load_config
|
|
57
|
-
content = File.read(WAYBAR_CONFIG)
|
|
58
|
-
# Strip comments for JSON parsing
|
|
59
|
-
json_content = content.lines.reject { |line| line.strip.start_with?("//") }.join
|
|
60
|
-
JSON.parse(json_content)
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
def save_config(config)
|
|
64
|
-
File.write(WAYBAR_CONFIG, JSON.pretty_generate(config))
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
# Load current config
|
|
68
|
-
config = load_config
|
|
69
|
-
|
|
70
|
-
# Remove old brainiac modules if they exist (from all module arrays)
|
|
71
|
-
%w[modules-left modules-center modules-right].each do |section|
|
|
72
|
-
next unless config[section].is_a?(Array)
|
|
73
|
-
|
|
74
|
-
config[section].reject! { |m| ["custom/brainiac", "group/brainiac-agents"].include?(m.to_s) }
|
|
75
|
-
end
|
|
76
|
-
config.each_key do |key|
|
|
77
|
-
config.delete(key) if ["custom/brainiac", "group/brainiac-agents"].include?(key.to_s)
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
# Add single dynamic module at the end of modules-center (after deploy envs)
|
|
81
|
-
config["modules-center"] ||= []
|
|
82
|
-
config["modules-center"].push("custom/brainiac")
|
|
83
|
-
|
|
84
|
-
# Add module config
|
|
85
|
-
config["custom/brainiac"] = {
|
|
86
|
-
"exec" => WAYBAR_SCRIPT,
|
|
87
|
-
"return-type" => "json",
|
|
88
|
-
"interval" => 3,
|
|
89
|
-
"format" => "{}",
|
|
90
|
-
"tooltip" => true,
|
|
91
|
-
"on-click" => File.expand_path("~/.brainiac/bin/waybar-logs").to_s
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
# Create on-click wrapper too
|
|
95
|
-
logs_wrapper = File.expand_path("~/.brainiac/bin/waybar-logs")
|
|
96
|
-
File.write(logs_wrapper, <<~SCRIPT)
|
|
97
|
-
#!/usr/bin/env ruby
|
|
98
|
-
root_file = File.expand_path("~/.brainiac/server.root")
|
|
99
|
-
if File.exist?(root_file)
|
|
100
|
-
server_root = File.read(root_file).strip
|
|
101
|
-
script = File.join(server_root, "monitor", "view-logs-rofi.rb")
|
|
102
|
-
exec("ruby", script) if File.exist?(script)
|
|
103
|
-
end
|
|
104
|
-
warn "Brainiac server root not found"
|
|
105
|
-
SCRIPT
|
|
106
|
-
File.chmod(0o755, logs_wrapper)
|
|
107
|
-
|
|
108
|
-
# Save updated config
|
|
109
|
-
save_config(config)
|
|
110
|
-
|
|
111
|
-
puts "✓ Brainiac module added to waybar config"
|
|
112
|
-
puts " Module will update every 3 seconds without config rewrites"
|
|
113
|
-
puts " Restart waybar to apply: omarchy restart waybar"
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
# frozen_string_literal: true
|
|
3
|
-
|
|
4
|
-
# One-time setup: symlinks the Brainiac xbar plugin into xbar's plugin directory
|
|
5
|
-
# Run this once on macOS after installing xbar
|
|
6
|
-
|
|
7
|
-
require "fileutils"
|
|
8
|
-
|
|
9
|
-
XBAR_PLUGIN_DIR = File.expand_path("~/Library/Application Support/xbar/plugins")
|
|
10
|
-
PLUGIN_SOURCE = File.expand_path("xbar.3s.rb", __dir__)
|
|
11
|
-
PLUGIN_DEST = File.join(XBAR_PLUGIN_DIR, "brainiac.3s.rb")
|
|
12
|
-
|
|
13
|
-
unless RUBY_PLATFORM.match?(/darwin/i)
|
|
14
|
-
puts "⚠ This script is for macOS only (xbar doesn't run on Linux)"
|
|
15
|
-
exit 1
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
unless File.directory?(XBAR_PLUGIN_DIR)
|
|
19
|
-
puts "⚠ xbar plugin directory not found: #{XBAR_PLUGIN_DIR}"
|
|
20
|
-
puts " Install xbar first: https://xbarapp.com"
|
|
21
|
-
exit 1
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
if File.exist?(PLUGIN_DEST)
|
|
25
|
-
puts "Removing existing plugin at #{PLUGIN_DEST}"
|
|
26
|
-
File.delete(PLUGIN_DEST)
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
File.symlink(PLUGIN_SOURCE, PLUGIN_DEST)
|
|
30
|
-
File.chmod(0o755, PLUGIN_SOURCE)
|
|
31
|
-
|
|
32
|
-
puts "✓ Brainiac xbar plugin installed"
|
|
33
|
-
puts " #{PLUGIN_SOURCE} → #{PLUGIN_DEST}"
|
|
34
|
-
puts " Refresh interval: 3 seconds"
|
|
35
|
-
puts " Restart xbar to activate"
|
data/monitor/view-logs.rb
DELETED
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
# frozen_string_literal: true
|
|
3
|
-
|
|
4
|
-
# Brainiac Log Viewer
|
|
5
|
-
# Shows a rofi menu to select which agent log to tail
|
|
6
|
-
|
|
7
|
-
require "json"
|
|
8
|
-
require "net/http"
|
|
9
|
-
require "socket"
|
|
10
|
-
|
|
11
|
-
SOCKET_PATH = "/tmp/brainiac-monitor.sock"
|
|
12
|
-
API_URL = "http://localhost:4567/api/status"
|
|
13
|
-
CONFIG_PATH = File.expand_path("~/.brainiac/waybar.json")
|
|
14
|
-
|
|
15
|
-
# Load agent configuration from JSON
|
|
16
|
-
def load_agent_config
|
|
17
|
-
config = JSON.parse(File.read(CONFIG_PATH))
|
|
18
|
-
agents = {}
|
|
19
|
-
config["agents"].each do |agent|
|
|
20
|
-
agents[agent["name"].downcase] = agent["emoji"]
|
|
21
|
-
end
|
|
22
|
-
default_emoji = config["default_emoji"] || "❓"
|
|
23
|
-
[agents, default_emoji]
|
|
24
|
-
rescue StandardError => e
|
|
25
|
-
warn "Failed to load waybar.json: #{e.message}"
|
|
26
|
-
[{}, "❓"]
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
AGENTS, DEFAULT_EMOJI = load_agent_config
|
|
30
|
-
|
|
31
|
-
def fetch_state_from_socket
|
|
32
|
-
socket = UNIXSocket.new(SOCKET_PATH)
|
|
33
|
-
data = socket.read
|
|
34
|
-
socket.close
|
|
35
|
-
JSON.parse(data)
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
def fetch_state_from_api
|
|
39
|
-
uri = URI(API_URL)
|
|
40
|
-
response = Net::HTTP.get_response(uri)
|
|
41
|
-
return nil unless response.is_a?(Net::HTTPSuccess)
|
|
42
|
-
|
|
43
|
-
JSON.parse(response.body)
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
def fetch_state
|
|
47
|
-
# Prefer socket (daemon mode) — faster, no HTTP overhead
|
|
48
|
-
fetch_state_from_socket
|
|
49
|
-
rescue Errno::ENOENT, Errno::ECONNREFUSED
|
|
50
|
-
# Daemon not running — fall back to direct API call
|
|
51
|
-
data = fetch_state_from_api
|
|
52
|
-
unless data
|
|
53
|
-
puts "Error: Server not reachable"
|
|
54
|
-
exit 1
|
|
55
|
-
end
|
|
56
|
-
data
|
|
57
|
-
rescue StandardError => e
|
|
58
|
-
puts "Error: #{e.message}"
|
|
59
|
-
exit 1
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
def format_elapsed(seconds)
|
|
63
|
-
return "#{seconds}s" if seconds < 60
|
|
64
|
-
|
|
65
|
-
minutes = seconds / 60
|
|
66
|
-
return "#{minutes}m" if minutes < 60
|
|
67
|
-
|
|
68
|
-
hours = minutes / 60
|
|
69
|
-
"#{hours}h"
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
state = fetch_state
|
|
73
|
-
sessions = state["sessions"] || []
|
|
74
|
-
|
|
75
|
-
if sessions.empty?
|
|
76
|
-
system("notify-send", "Brainiac", "No active agent sessions")
|
|
77
|
-
exit 0
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
# If only one session, open it directly
|
|
81
|
-
if sessions.size == 1
|
|
82
|
-
log_file = sessions[0]["log_file"]
|
|
83
|
-
exec("alacritty", "-e", "tail", "-f", log_file) if log_file
|
|
84
|
-
exit 0
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
# Multiple sessions: use fzf if available, otherwise just open the first one
|
|
88
|
-
if system("which fzf > /dev/null 2>&1")
|
|
89
|
-
# Build fzf menu
|
|
90
|
-
options = sessions.map do |s|
|
|
91
|
-
agent = s["agent"]
|
|
92
|
-
elapsed = format_elapsed(s["elapsed_seconds"])
|
|
93
|
-
|
|
94
|
-
card_key = s["card_key"]
|
|
95
|
-
context = if card_key.start_with?("discord-")
|
|
96
|
-
"Discord chat"
|
|
97
|
-
elsif card_key.start_with?("card-")
|
|
98
|
-
card_key.split("-")[1]
|
|
99
|
-
else
|
|
100
|
-
card_key
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
emoji = AGENTS[agent.downcase] || DEFAULT_EMOJI
|
|
104
|
-
|
|
105
|
-
"#{emoji} #{agent}: #{context} (#{elapsed})|#{s["log_file"]}"
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
menu_text = options.join("\n")
|
|
109
|
-
selected = `echo "#{menu_text}" | fzf --prompt="Agent Logs: "`.strip
|
|
110
|
-
|
|
111
|
-
unless selected.empty?
|
|
112
|
-
log_file = selected.split("|").last
|
|
113
|
-
exec("alacritty", "-e", "tail", "-f", log_file)
|
|
114
|
-
end
|
|
115
|
-
else
|
|
116
|
-
# No menu system, just open the first log
|
|
117
|
-
log_file = sessions[0]["log_file"]
|
|
118
|
-
exec("alacritty", "-e", "tail", "-f", log_file) if log_file
|
|
119
|
-
end
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
# frozen_string_literal: true
|
|
3
|
-
|
|
4
|
-
# Brainiac Waybar Config Updater
|
|
5
|
-
# Dynamically updates waybar config with per-agent modules
|
|
6
|
-
|
|
7
|
-
require "json"
|
|
8
|
-
|
|
9
|
-
WAYBAR_CONFIG = File.expand_path("~/.config/waybar/config.jsonc")
|
|
10
|
-
WAYBAR_SCRIPT = File.expand_path("~/Code/brainiac/monitor/waybar.rb")
|
|
11
|
-
|
|
12
|
-
def load_config
|
|
13
|
-
content = File.read(WAYBAR_CONFIG)
|
|
14
|
-
# Strip comments for JSON parsing
|
|
15
|
-
json_content = content.lines.reject { |line| line.strip.start_with?("//") }.join
|
|
16
|
-
JSON.parse(json_content)
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def save_config(config)
|
|
20
|
-
File.write(WAYBAR_CONFIG, JSON.pretty_generate(config))
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def brainiac_modules
|
|
24
|
-
output = `#{WAYBAR_SCRIPT} --config`
|
|
25
|
-
JSON.parse(output)
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
# Load current config
|
|
29
|
-
config = load_config
|
|
30
|
-
|
|
31
|
-
# Get dynamic Brainiac modules
|
|
32
|
-
brainiac_data = brainiac_modules
|
|
33
|
-
modules = brainiac_data["modules"]
|
|
34
|
-
module_configs = brainiac_data["config"]
|
|
35
|
-
|
|
36
|
-
# Remove old brainiac modules and groups from modules-right
|
|
37
|
-
config["modules-right"].reject! { |m| m.to_s.start_with?("custom/brainiac") || m.to_s == "group/brainiac-agents" }
|
|
38
|
-
|
|
39
|
-
# Insert new modules at the beginning of modules-right
|
|
40
|
-
config["modules-right"] = modules + config["modules-right"]
|
|
41
|
-
|
|
42
|
-
# Remove old brainiac module configs and groups
|
|
43
|
-
config.each_key do |key|
|
|
44
|
-
config.delete(key) if key.to_s.start_with?("custom/brainiac") || key.to_s == "group/brainiac-agents"
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
# Add new module configs
|
|
48
|
-
module_configs.each do |name, cfg|
|
|
49
|
-
config[name] = cfg
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
# Save updated config
|
|
53
|
-
save_config(config)
|
|
54
|
-
|
|
55
|
-
# Reload waybar
|
|
56
|
-
system("killall", "-SIGUSR2", "waybar")
|