brainiac 0.0.4 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3753442d24d4e39a70b7fd537ebb1e62495a826a42d2a52d16311bf300c1fc9c
4
- data.tar.gz: 4e44dd38c7d78a51a8b2c73884353e5df911b8a6d28550328d6b906e432f0f5d
3
+ metadata.gz: '084de313577f21e900e3f3641ba12774c29b54e7489738d8c411c8acefacd2dd'
4
+ data.tar.gz: b4e6c118a4c62ea455e75cd935d003a07d9abe4eff14c7cd8e43f7d4b4c42cfe
5
5
  SHA512:
6
- metadata.gz: 5dda943f8c6f67ff425ab6850d11e0b131c190441a5f52f1415b39cc42947a00756f19e6416b503a0b6c3f9229eb0dc4ac1cd4a987b0758d373e0be220ab5969
7
- data.tar.gz: b95eae03330676be88800817be77af1c40b79edf4ab9ac574cfabeba7e0c82b8cd57318905fd150041cc3396f81d6817c4285f8188da266a43724571660f20ee
6
+ metadata.gz: 5f974d1842a76ab7eaaaadafe797f28d9a365b8afb02d02d81bc4fd459fbadf93dbe6e71d85d2f456db63784a6a09e92efebcec15f7f0ae2f1baf7eaf92ab539
7
+ data.tar.gz: e37da56e9b89d8d0afc5511590023e08532f63d382c66f29482c772e58ce68e62f85bf958ab46ab1848f5c8f6d9af4bdaf2c1e1dc747ba68a6de693bcee7777c
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- brainiac (0.0.4)
4
+ brainiac (0.0.6)
5
5
  puma (~> 7.2)
6
6
  rackup (~> 2.3)
7
7
  sinatra (~> 4.1)
@@ -90,7 +90,7 @@ DEPENDENCIES
90
90
  CHECKSUMS
91
91
  ast (2.4.3) sha256=954615157c1d6a382bc27d690d973195e79db7f55e9765ac7c481c60bdb4d383
92
92
  base64 (0.3.0) sha256=27337aeabad6ffae05c265c450490628ef3ebd4b67be58257393227588f5a97b
93
- brainiac (0.0.4)
93
+ brainiac (0.0.6)
94
94
  event_emitter (0.2.6) sha256=c72697bd5cce9d36594be1972c17f1c9a573236f44303a4d1d548080364e1391
95
95
  json (2.19.9) sha256=9b9025b7cdddafa38d316eca0b2358488e42d417045c1b90d216a9fefe46b79a
96
96
  language_server-protocol (3.17.0.5) sha256=fd1e39a51a28bf3eec959379985a72e296e9f9acfce46f6a79d31ca8760803cc
data/bin/brainiac CHANGED
@@ -1436,23 +1436,179 @@ when "agent"
1436
1436
  end
1437
1437
  end
1438
1438
 
1439
+ when "create", "add"
1440
+ name = ARGV.shift
1441
+ unless name
1442
+ puts "Usage: brainiac agent create <name> [options]"
1443
+ puts ""
1444
+ puts "Options:"
1445
+ puts " --local Mark agent as local (dispatches on this machine)"
1446
+ puts " --role <role> Assign a role (repeatable)"
1447
+ puts " --cli <provider> Set CLI provider (default: kiro)"
1448
+ puts " --persona <text> Create a persona style file with this description"
1449
+ puts ""
1450
+ puts "If no options are given and stdin is a terminal, interactive mode is used."
1451
+ puts ""
1452
+ puts "Examples:"
1453
+ puts " brainiac agent create SecurityBot --local --role code-reviewer"
1454
+ puts " brainiac agent create Jane --role general-engineer --cli grok"
1455
+ puts " brainiac agent create Avon --persona \"Dry wit, sardonic, brilliant\""
1456
+ puts " brainiac agent create MyAgent # interactive"
1457
+ exit 1
1458
+ end
1459
+
1460
+ agent_key = name.downcase.gsub(/[^a-z0-9-]/, "-")
1461
+ registry = File.exist?(agent_registry_file) ? JSON.parse(File.read(agent_registry_file)) : {}
1462
+
1463
+ if registry[agent_key]
1464
+ puts "Agent '#{name}' already exists. Use 'brainiac agent #{agent_key} show' to view."
1465
+ exit 1
1466
+ end
1467
+
1468
+ local = false
1469
+ roles = []
1470
+ cli_provider = nil
1471
+ persona_text = nil
1472
+
1473
+ if ARGV.any?
1474
+ # Flag mode
1475
+ while ARGV.any?
1476
+ case ARGV[0]
1477
+ when "--local"
1478
+ ARGV.shift
1479
+ local = true
1480
+ when "--role"
1481
+ ARGV.shift
1482
+ roles << ARGV.shift
1483
+ when "--cli"
1484
+ ARGV.shift
1485
+ cli_provider = ARGV.shift
1486
+ when "--persona"
1487
+ ARGV.shift
1488
+ persona_text = ARGV.shift
1489
+ else
1490
+ puts "Unknown option: #{ARGV[0]}"
1491
+ exit 1
1492
+ end
1493
+ end
1494
+ elsif $stdin.tty?
1495
+ # Interactive mode
1496
+ puts "Creating agent '#{name}' (#{agent_key})"
1497
+ puts ""
1498
+
1499
+ print "Local (dispatches on this machine)? [y/N]: "
1500
+ local = $stdin.gets.chomp.downcase.start_with?("y")
1501
+
1502
+ # Show available CLI providers
1503
+ providers_dir = File.join(BRAINIAC_DIR, "cli-providers")
1504
+ available_providers = Dir.exist?(providers_dir) ? Dir.glob(File.join(providers_dir, "*.json")).map { |f| File.basename(f, ".json") } : []
1505
+ hint = available_providers.any? ? " (#{available_providers.join(", ")})" : ""
1506
+ print "CLI provider#{hint} [kiro]: "
1507
+ input = $stdin.gets.chomp
1508
+ cli_provider = input.empty? ? nil : input
1509
+
1510
+ # Show available roles
1511
+ roles_dir = File.join(BRAINIAC_DIR, "roles")
1512
+ available_roles = Dir.exist?(roles_dir) ? Dir.glob(File.join(roles_dir, "*.md")).map { |f| File.basename(f, ".md") } : []
1513
+ hint = available_roles.any? ? " (#{available_roles.join(", ")})" : ""
1514
+ print "Roles#{hint} (comma-separated) []: "
1515
+ input = $stdin.gets.chomp
1516
+ roles = input.empty? ? [] : input.split(",").map(&:strip)
1517
+
1518
+ print "Persona description (tone/style, or blank to skip) []: "
1519
+ input = $stdin.gets.chomp
1520
+ persona_text = input.empty? ? nil : input
1521
+ end
1522
+
1523
+ entry = { "fizzy_name" => name }
1524
+ entry["local"] = true if local
1525
+ entry["cli_provider"] = cli_provider if cli_provider
1526
+ entry["role"] = roles.size == 1 ? roles.first : roles if roles.any?
1527
+
1528
+ registry[agent_key] = entry
1529
+ File.write(agent_registry_file, JSON.pretty_generate(registry))
1530
+ puts "✓ Created agent '#{name}' (#{agent_key})"
1531
+ puts " Local: #{local}" if local
1532
+ puts " Role: #{roles.join(", ")}" if roles.any?
1533
+ puts " CLI: #{cli_provider}" if cli_provider
1534
+
1535
+ # Create persona directory and style file if requested
1536
+ if persona_text
1537
+ persona_dir = File.join(BRAINIAC_DIR, "brain", "persona", agent_key)
1538
+ FileUtils.mkdir_p(persona_dir)
1539
+ persona_file = File.join(persona_dir, "style.md")
1540
+ unless File.exist?(persona_file)
1541
+ File.write(persona_file, <<~MD)
1542
+ ---
1543
+ name: #{agent_key}-style
1544
+ description: Persona voice for #{name}.
1545
+ ---
1546
+ # #{name} — Persona
1547
+ #{persona_text}
1548
+ MD
1549
+ puts " Persona: #{persona_file}"
1550
+ end
1551
+ end
1552
+
1553
+ # Initialize brain (qmd collections) for local agents
1554
+ if local
1555
+ puts ""
1556
+ brain_init(name)
1557
+ end
1558
+
1559
+ when "remove", "delete", "rm"
1560
+ name = ARGV.shift
1561
+ unless name
1562
+ puts "Usage: brainiac agent remove <name>"
1563
+ exit 1
1564
+ end
1565
+
1566
+ agent_key = name.downcase.gsub(/[^a-z0-9-]/, "-")
1567
+ registry = File.exist?(agent_registry_file) ? JSON.parse(File.read(agent_registry_file)) : {}
1568
+
1569
+ unless registry[agent_key]
1570
+ puts "Agent '#{name}' not found in registry."
1571
+ exit 1
1572
+ end
1573
+
1574
+ display = registry[agent_key]["fizzy_name"] || name
1575
+ registry.delete(agent_key)
1576
+ File.write(agent_registry_file, JSON.pretty_generate(registry))
1577
+ puts "✓ Removed agent '#{display}' (#{agent_key}) from registry"
1578
+ puts " Note: Persona files at ~/.brainiac/brain/persona/#{agent_key}/ were not deleted."
1579
+
1439
1580
  when nil
1440
1581
  puts <<~HELP
1441
1582
  Usage: brainiac agent <name> <command> [args]
1442
1583
  brainiac agent list
1584
+ brainiac agent create <name> [options]
1585
+ brainiac agent remove <name>
1443
1586
 
1444
1587
  Commands:
1445
1588
  list List all agents in the registry
1589
+ create <name> [options] Add a new agent to the registry
1590
+ remove <name> Remove an agent from the registry
1446
1591
  <name> show Show agent configuration (tokens redacted)
1592
+ <name> set <field> <value> Update a config field (local, cli, role, persona, fizzy_name)
1447
1593
  <name> env <KEY> <VALUE> Set an env var for an agent
1448
1594
  <name> env List env vars for an agent
1449
1595
  <name> env --delete <KEY> Remove an env var from an agent
1450
1596
 
1597
+ Create options (or interactive if no flags given):
1598
+ --local Mark agent as local (dispatches on this machine)
1599
+ --role <role> Assign a role (repeatable)
1600
+ --cli <provider> Set CLI provider (default: kiro)
1601
+ --persona <text> Create a persona style file
1602
+
1451
1603
  Examples:
1604
+ brainiac agent create SecurityBot --local --role code-reviewer
1605
+ brainiac agent create Jane --cli grok
1606
+ brainiac agent create MyAgent # interactive mode
1607
+ brainiac agent remove SecurityBot
1608
+ brainiac agent galen set local true
1609
+ brainiac agent galen set persona "Dry, sardonic"
1610
+ brainiac agent galen set role code-reviewer,general-engineer
1452
1611
  brainiac agent galen env FIZZY_TOKEN fizzy_abc123
1453
- brainiac agent galen env DISCORD_BOT_TOKEN Bot_xyz789
1454
- brainiac agent galen env
1455
- brainiac agent galen env --delete DISCORD_BOT_TOKEN
1456
1612
  brainiac agent galen show
1457
1613
  HELP
1458
1614
 
@@ -1522,9 +1678,93 @@ when "agent"
1522
1678
  puts "✓ Set #{var_name} for #{agent_cmd}"
1523
1679
  end
1524
1680
 
1681
+ when "set"
1682
+ field = ARGV.shift
1683
+ value = ARGV.shift
1684
+ unless field
1685
+ puts "Usage: brainiac agent #{agent_cmd} set <field> <value>"
1686
+ puts ""
1687
+ puts "Fields:"
1688
+ puts " local <true|false> Set local dispatch flag"
1689
+ puts " cli <provider> Set CLI provider"
1690
+ puts " role <roles> Set roles (comma-separated, or 'none' to clear)"
1691
+ puts " persona <text> Set/update persona style file"
1692
+ puts " fizzy_name <name> Set display name for Fizzy @mentions"
1693
+ exit 1
1694
+ end
1695
+
1696
+ registry = File.exist?(agent_registry_file) ? JSON.parse(File.read(agent_registry_file)) : {}
1697
+ unless registry[agent_key]
1698
+ puts "Agent '#{agent_cmd}' not found in registry."
1699
+ exit 1
1700
+ end
1701
+
1702
+ case field
1703
+ when "local"
1704
+ if value == "true"
1705
+ registry[agent_key]["local"] = true
1706
+ else
1707
+ registry[agent_key].delete("local")
1708
+ end
1709
+ File.write(agent_registry_file, JSON.pretty_generate(registry))
1710
+ puts "✓ Set local=#{value} for #{agent_cmd}"
1711
+
1712
+ when "cli"
1713
+ unless value
1714
+ puts "Usage: brainiac agent #{agent_cmd} set cli <provider>"
1715
+ exit 1
1716
+ end
1717
+ registry[agent_key]["cli_provider"] = value
1718
+ File.write(agent_registry_file, JSON.pretty_generate(registry))
1719
+ puts "✓ Set cli_provider=#{value} for #{agent_cmd}"
1720
+
1721
+ when "role"
1722
+ unless value
1723
+ puts "Usage: brainiac agent #{agent_cmd} set role <roles|none>"
1724
+ exit 1
1725
+ end
1726
+ roles = value == "none" ? [] : value.split(",").map(&:strip)
1727
+ resolved_role = roles.one? ? roles.first : roles
1728
+ roles.empty? ? registry[agent_key].delete("role") : registry[agent_key]["role"] = resolved_role
1729
+ File.write(agent_registry_file, JSON.pretty_generate(registry))
1730
+ puts "✓ Set role for #{agent_cmd}"
1731
+
1732
+ when "persona"
1733
+ unless value
1734
+ puts "Usage: brainiac agent #{agent_cmd} set persona <text>"
1735
+ exit 1
1736
+ end
1737
+ persona_dir = File.join(BRAINIAC_DIR, "brain", "persona", agent_key)
1738
+ FileUtils.mkdir_p(persona_dir)
1739
+ persona_file = File.join(persona_dir, "style.md")
1740
+ display = registry[agent_key]["fizzy_name"] || agent_cmd.capitalize
1741
+ File.write(persona_file, <<~MD)
1742
+ ---
1743
+ name: #{agent_key}-style
1744
+ description: Persona voice for #{display}.
1745
+ ---
1746
+ # #{display} — Persona
1747
+ #{value}
1748
+ MD
1749
+ puts "✓ Wrote persona to #{persona_file}"
1750
+
1751
+ when "fizzy_name"
1752
+ unless value
1753
+ puts "Usage: brainiac agent #{agent_cmd} set fizzy_name <name>"
1754
+ exit 1
1755
+ end
1756
+ registry[agent_key]["fizzy_name"] = value
1757
+ File.write(agent_registry_file, JSON.pretty_generate(registry))
1758
+ puts "✓ Set fizzy_name=#{value} for #{agent_cmd}"
1759
+
1760
+ else
1761
+ puts "Unknown field '#{field}'. Available: local, cli, role, persona, fizzy_name"
1762
+ exit 1
1763
+ end
1764
+
1525
1765
  else
1526
1766
  puts "Unknown subcommand '#{sub}' for agent '#{agent_cmd}'."
1527
- puts "Available: show, env"
1767
+ puts "Available: show, env, set"
1528
1768
  exit 1
1529
1769
  end
1530
1770
  end
@@ -73,13 +73,19 @@ _brainiac() {
73
73
  agent)
74
74
  case $cword in
75
75
  2)
76
- COMPREPLY=($(compgen -W "list $(_brainiac_agents)" -- "$cur"))
76
+ COMPREPLY=($(compgen -W "list create remove $(_brainiac_agents)" -- "$cur"))
77
77
  ;;
78
78
  3)
79
79
  local agent_name="${words[2]}"
80
- if [[ "$agent_name" != "list" ]]; then
81
- COMPREPLY=($(compgen -W "show env" -- "$cur"))
82
- fi
80
+ case "$agent_name" in
81
+ list|remove|delete|rm) ;;
82
+ create|add)
83
+ COMPREPLY=($(compgen -W "--local --role --cli --persona" -- "$cur"))
84
+ ;;
85
+ *)
86
+ COMPREPLY=($(compgen -W "show env" -- "$cur"))
87
+ ;;
88
+ esac
83
89
  ;;
84
90
  4)
85
91
  local subcmd="${words[3]}"
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Brainiac
4
4
  # @return [String] the current gem version
5
- VERSION = "0.0.4"
5
+ VERSION = "0.0.6"
6
6
  end
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
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andy Davis