agent_status_bulb 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c2183f0e22cc7a3779f409df20894bdf032f6e2c2a342c72553f838e00d27c76
4
- data.tar.gz: 0def7cc82dcf2aaa15b031c9275c01da270d939841b59e7ca0a6c3b018544f94
3
+ metadata.gz: 926cc8a1e54b9ad64f98b0be63c4340343c8c560af83c3c1b1e1cfdd6975296b
4
+ data.tar.gz: 2700ad1bc86a4a5bef790c1821a3748056741bc6e3fe3e2ba76869873fdf5c86
5
5
  SHA512:
6
- metadata.gz: 517a923a5b5011fd1dccce4c9e53aec9610ce278f485b148000cf99660162867ff8e53868d89e792ac7ff1b7d5feaadf709ab929bdb2000d1f0f6354124a33c4
7
- data.tar.gz: 6c7cd63f36191263c4ef9b7f0527e76b672bd8cf3ce2757e8f4fbfef21f584d461161698bdf8cf95239210acbbe0f8081d9f7f70732e826b787b7ab360526d62
6
+ metadata.gz: fb0a80dc7f123fd52525dd0787e1273271c9ef192c3d09f96cdda78c841d7605f20c1ddbe155385a20bec2ff59410822195803b3de71ecc69a51ed7b16930d33
7
+ data.tar.gz: 36b57bd8fb3a83191af52dde0107a0f142da019f51eab8ba16cc0f662623f9f56aa2947ed4a6b1f4148ab8d5147d9ec3e058d2803dff09fe0af6be1f9b5a1c8a
data/.rubocop.yml CHANGED
@@ -8,3 +8,9 @@ plugins:
8
8
 
9
9
  Style/Documentation:
10
10
  Enabled: false
11
+
12
+ RSpec/ExampleLength:
13
+ Max: 9
14
+
15
+ RSpec/MultipleExpectations:
16
+ Max: 2
data/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.3.0] - 2025-11-29
4
+
5
+ - Added `version` CLI command to print the current version
6
+ - CLI commands now ignore unknown options instead of exiting with an error
7
+
8
+ ## [0.2.0] - 2025-11-19
9
+
10
+ - Introduced `AgentStatusBulb::Bulb` to wrap SwitchBot integration and provide run/wait/idle/off color APIs with automatic power control
11
+ - Rebuilt the CLI on top of Thor and routed every command through `handle_error` to normalize error handling
12
+ - Simplified configuration input/save/load flows by driving them from a single field definition list
13
+ - Added RSpec coverage for CLI, Configure, and Bulb to document expected behaviour
14
+ - Added RuboCop configuration to keep coding style consistent
15
+
3
16
  ## [0.1.0] - 2025-11-18
4
17
 
5
18
  - Initial release
data/exe/asb CHANGED
@@ -3,4 +3,10 @@
3
3
 
4
4
  require 'agent_status_bulb/cli'
5
5
 
6
- exit AgentStatusBulb::Cli.start(ARGV)
6
+ begin
7
+ AgentStatusBulb::Cli.start(ARGV)
8
+ exit 0
9
+ rescue StandardError => e
10
+ warn e.message
11
+ exit 1
12
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'switchbot'
4
+
5
+ module AgentStatusBulb
6
+ class Bulb
7
+ def self.from_config(config)
8
+ client = Switchbot::Client.new(config.fetch(:token), config.fetch(:secret))
9
+ new(client.color_bulb(config.fetch(:device_id)))
10
+ end
11
+
12
+ def initialize(device)
13
+ @device = device
14
+ end
15
+
16
+ def blue
17
+ apply_color('0:0:255')
18
+ end
19
+
20
+ def orange
21
+ apply_color('255:125:0')
22
+ end
23
+
24
+ def green
25
+ apply_color('0:255:0')
26
+ end
27
+
28
+ def off
29
+ @device.off
30
+ end
31
+
32
+ private
33
+
34
+ def apply_color(value)
35
+ turn_on_if_needed
36
+ @device.color(value)
37
+ end
38
+
39
+ def turn_on_if_needed
40
+ @device.on if @device.off?
41
+ end
42
+ end
43
+ end
@@ -1,78 +1,65 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'thor'
3
4
  require 'agent_status_bulb'
4
- require 'switchbot'
5
5
  require 'agent_status_bulb/configure'
6
+ require 'agent_status_bulb/bulb'
6
7
 
7
8
  module AgentStatusBulb
8
- class Cli
9
- def self.start(argv)
10
- new(argv).run
11
- end
9
+ class Cli < Thor
10
+ map 'run' => :run_command
11
+ map 'wait' => :wait_command
12
+ map 'idle' => :idle_command
13
+ map 'off' => :off_command
12
14
 
13
- def initialize(argv, io: $stdin, out: $stdout, err: $stderr)
14
- @argv = argv.dup
15
- @io = io
16
- @out = out
17
- @err = err
15
+ desc 'configure', 'Save Token/Secret/Device ID'
16
+ def configure(*_args)
17
+ handle_error { configurator.configure! }
18
18
  end
19
19
 
20
- def run
21
- command = @argv.shift
22
- handle_command(command)
23
- rescue StandardError => e
24
- @err.puts(e.message)
25
- 1
20
+ desc 'version', 'Print the current version'
21
+ def version(*_args)
22
+ puts AgentStatusBulb::VERSION
26
23
  end
27
24
 
28
- private
29
-
30
- def handle_command(command)
31
- return configure! if command == 'configure'
32
- return apply!(command) if status_colors.key?(command) || command == 'off'
33
-
34
- @err.puts usage
35
- 1
25
+ desc 'run', 'Set color to running (blue)'
26
+ def run_command(*_args)
27
+ handle_error { bulb.blue }
36
28
  end
37
29
 
38
- def configure!
39
- configurator.configure!
40
- 0
30
+ desc 'wait', 'Set color to waiting (orange)'
31
+ def wait_command(*_args)
32
+ handle_error { bulb.orange }
41
33
  end
42
34
 
43
- def apply!(command)
44
- bulb = build_bulb(configurator.load!)
45
- apply_status(bulb, command)
46
- 0
35
+ desc 'idle', 'Set color to idle (green)'
36
+ def idle_command(*_args)
37
+ handle_error { bulb.green }
47
38
  end
48
39
 
49
- def build_bulb(config)
50
- client = Switchbot::Client.new(config[:token], config[:secret])
51
- bulb = client.color_bulb(config[:device_id])
52
- bulb.on if bulb.off?
53
- bulb
40
+ desc 'off', 'Turn off the bulb'
41
+ def off_command(*_args)
42
+ handle_error { bulb.off }
54
43
  end
55
44
 
56
- def apply_status(bulb, command)
57
- return bulb.off if command == 'off'
45
+ no_commands do
46
+ def handle_error
47
+ yield
48
+ rescue StandardError => e
49
+ raise Thor::Error, e.message
50
+ end
58
51
 
59
- bulb.color(status_colors.fetch(command))
60
- end
61
-
62
- def usage
63
- "Usage: #{File.basename($PROGRAM_NAME)} [run|wait|idle|off|configure]"
64
- end
52
+ def bulb
53
+ @bulb ||= AgentStatusBulb::Bulb.from_config(configurator.load!)
54
+ end
65
55
 
66
- def configurator
67
- @configurator ||= AgentStatusBulb::Configure.new(io: @io, out: @out)
56
+ def configurator
57
+ @configurator ||= AgentStatusBulb::Configure.new
58
+ end
68
59
  end
69
60
 
70
- def status_colors
71
- {
72
- 'idle' => '0:255:0',
73
- 'run' => '0:0:255',
74
- 'wait' => '255:125:0'
75
- }
61
+ def self.exit_on_failure?
62
+ true
76
63
  end
77
64
  end
78
65
  end
@@ -7,44 +7,59 @@ require 'io/console'
7
7
  module AgentStatusBulb
8
8
  class Configure
9
9
  DEFAULT_PATH = File.expand_path('~/.config/agent_status_bulb.yml').freeze
10
+ CREDENTIAL_FIELDS = [
11
+ { key: :token, label: 'Token', conceal: true },
12
+ { key: :secret, label: 'Secret', conceal: true },
13
+ { key: :device_id, label: 'Device ID', conceal: false }
14
+ ].freeze
10
15
 
11
- def initialize(path: DEFAULT_PATH, io: $stdin, out: $stdout)
16
+ def initialize(path = DEFAULT_PATH)
12
17
  @path = path
13
- @io = io
14
- @out = out
15
18
  end
16
19
 
17
20
  def configure!
18
- token = prompt('Token', conceal: true)
19
- secret = prompt('Secret', conceal: true)
20
- device_id = prompt('Device ID')
21
-
22
- FileUtils.mkdir_p(File.dirname(@path))
23
- File.write(@path, { 'token' => token, 'secret' => secret, 'device_id' => device_id }.to_yaml)
24
- @out.puts "Saved config to: #{@path}"
21
+ credentials = gather_credentials
22
+ write_config(credentials)
23
+ $stdout.puts "Saved config to: #{@path}"
25
24
  end
26
25
 
27
26
  def load!
28
- raise "Config file not found: #{@path}" unless File.file?(@path)
27
+ data = read_config
28
+ CREDENTIAL_FIELDS.each_with_object({}) do |field, result|
29
+ value = data.fetch(field[:key].to_s, '').to_s.strip
30
+ raise missing_config_error if value.empty?
31
+
32
+ result[field[:key]] = value
33
+ end
34
+ end
29
35
 
30
- data = YAML.safe_load_file(@path, permitted_classes: [], aliases: false) || {}
31
- token = data['token'].to_s
32
- secret = data['secret'].to_s
33
- device_id = data['device_id'].to_s
36
+ private
34
37
 
35
- if token.empty? || secret.empty? || device_id.empty?
36
- raise "Config must contain token, secret, and device_id: #{@path}"
38
+ def gather_credentials
39
+ CREDENTIAL_FIELDS.each_with_object({}) do |field, result|
40
+ result[field[:key]] = prompt(field[:label], conceal: field[:conceal])
37
41
  end
42
+ end
38
43
 
39
- { token: token, secret: secret, device_id: device_id }
44
+ def write_config(credentials)
45
+ FileUtils.mkdir_p(File.dirname(@path))
46
+ File.write(@path, credentials.transform_keys(&:to_s).to_yaml)
40
47
  end
41
48
 
42
- private
49
+ def read_config
50
+ raise "Config file not found: #{@path}" unless File.file?(@path)
51
+
52
+ YAML.safe_load_file(@path, permitted_classes: [], aliases: false) || {}
53
+ end
54
+
55
+ def missing_config_error
56
+ "Config must contain token, secret, and device_id: #{@path}"
57
+ end
43
58
 
44
59
  def prompt(label, conceal: false)
45
- @out.print "#{label}: "
46
- input = conceal ? @io.noecho(&:gets) : @io.gets
47
- @out.puts if conceal
60
+ $stdout.print "#{label}: "
61
+ input = conceal ? $stdin.noecho(&:gets) : $stdin.gets
62
+ $stdout.puts if conceal
48
63
  input.to_s.strip
49
64
  end
50
65
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AgentStatusBulb
4
- VERSION = '0.1.0'
4
+ VERSION = '0.3.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: agent_status_bulb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yoshiki Takagi
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-11-18 00:00:00.000000000 Z
11
+ date: 2025-11-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: switchbot
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: thor
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
27
41
  description: Provides simple commands (asb run, asb wait, asb idle) to visualize the
28
42
  state of any agent or task through color changes.
29
43
  email:
@@ -42,6 +56,7 @@ files:
42
56
  - Rakefile
43
57
  - exe/asb
44
58
  - lib/agent_status_bulb.rb
59
+ - lib/agent_status_bulb/bulb.rb
45
60
  - lib/agent_status_bulb/cli.rb
46
61
  - lib/agent_status_bulb/configure.rb
47
62
  - lib/agent_status_bulb/version.rb