simple-agent-extension 0.2.1 → 0.2.2

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: d5b57957c947b2f4c126dca54b41f69e67d8d2cbfc3a9447a31bea468b03cf76
4
- data.tar.gz: 2aafa730f3def389acfd18c2cec0807dfcd78aa1148199ca7a6129ab93fe7c49
3
+ metadata.gz: 9ab373fc18955bd0baacc40937dcb56758ef1868b628761e9f718c0f92b85f8f
4
+ data.tar.gz: e059df069d89a8097aa6f08acc9f2dff02c32ebd2adce5b083e34fe0fcd722a3
5
5
  SHA512:
6
- metadata.gz: 6bcc677fcc9c6afe8f01f67e77b7a65e86fda1a45ea951a21a362eb88e8b3650ec34e90399292cb3b9b0dacdb082e8c8a5ea3bc0033dbf13f3476366ed4491f2
7
- data.tar.gz: f86cf67049dbc0bb7c16ed8c708ebb2e4b6c903240f1f260a2d88eb4be75e8a60c3922550ac1c99962393f5dcacee17c6c6c2ea72780a890f304b4e6d9c78bbd
6
+ metadata.gz: a88591dbccfda4b2e5abf84fcb2861cd35151dea90574e93b081d0c568a3eb11e6357df7726c3dd857fd4de6bf49f0eaf5651ad1c24bee910120ac32794647a3
7
+ data.tar.gz: 4df63619203ce861896717301521835f0261a38b97b466ed4f4ee1a3a4cb2c0ffc3a3993b6b8d75d8e5482e4f9c376ed973f1045252dd9c8a9cacc3f327dd516
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## [0.2.2] 2026-10-04
2
+
3
+ - fix: make the causes of errors easier to read
4
+ - chore: add gem package task
5
+ - docs: install from rubygems.org or run with rvx
6
+
1
7
  ## [0.2.1] 2026-10-02
2
8
 
3
9
  - feat: support Claude Code
data/README.md CHANGED
@@ -4,14 +4,14 @@
4
4
 
5
5
  ## Installation
6
6
 
7
- Requires Ruby 3.3 or later.
7
+ Requires Ruby 3.3 or later (not needed beforehand when running with `rvx`, which provides Ruby itself).
8
8
 
9
- The gem is not published to RubyGems.org yet, so install it from GitHub with Bundler:
9
+ Add the gem to your Gemfile:
10
10
 
11
11
  ```ruby
12
12
  # Gemfile
13
13
  group :development do
14
- gem "simple-agent-extension", github: "colorfulcompany/simple-agent-extension"
14
+ gem "simple-agent-extension"
15
15
  end
16
16
  ```
17
17
 
@@ -25,16 +25,12 @@ Then run the CLI through Bundler:
25
25
  bundle exec simple-agent-extension packages
26
26
  ```
27
27
 
28
- Pin a release with `tag:` so the checkout does not move:
28
+ Or run it without a Gemfile with [rv](https://github.com/spinel-coop/rv)'s `rvx`, which installs the gem on first use:
29
29
 
30
- ```ruby
31
- gem "simple-agent-extension",
32
- github: "colorfulcompany/simple-agent-extension",
33
- tag: "v0.1.0"
30
+ ```sh
31
+ rvx simple-agent-extension packages
34
32
  ```
35
33
 
36
- `branch:` and `ref:` are also available; note that `branch:` follows new commits rather than pinning.
37
-
38
34
  ## Usage
39
35
 
40
36
  ### Defining a package
@@ -1,7 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SimpleAgentExtension
4
- class InvalidAgentDirectory < Error; end
4
+ class AgentDirectoryNotFound < Error; end
5
+ class AgentDirectoryNotDirectory < Error; end
6
+ class AgentDirectoryNotReadable < Error; end
5
7
  class MissingAgentRegistration < Error; end
6
8
  class UnloadableAgentRegistration < Error; end
7
9
 
@@ -28,12 +30,15 @@ module SimpleAgentExtension
28
30
  @directories.map { |directory| canonical_directory(directory) }.uniq
29
31
  end
30
32
 
33
+ # The error class names the condition, so the message carries the path
34
+ # alone.
31
35
  def canonical_directory(directory)
32
36
  path = File.expand_path(directory)
33
- raise InvalidAgentDirectory, "invalid agent directory: #{path}" unless File.directory?(path)
37
+ raise AgentDirectoryNotFound, path unless File.exist?(path)
38
+ raise AgentDirectoryNotDirectory, path unless File.directory?(path)
34
39
 
35
40
  path = File.realpath(path)
36
- raise InvalidAgentDirectory, "invalid agent directory: #{path}" unless File.readable?(path)
41
+ raise AgentDirectoryNotReadable, path unless File.readable?(path)
37
42
 
38
43
  path
39
44
  end
@@ -6,6 +6,13 @@ require "simple_agent_extension"
6
6
  module SimpleAgentExtension
7
7
  # Command-line adapter for public package compilation and deployment.
8
8
  class CLI
9
+ # The command line itself was written wrong. The message describes the
10
+ # mistake in full, so where it was raised tells the caller nothing.
11
+ class UsageError < Error; end
12
+
13
+ # No command was resolved, so the caller still needs the vocabulary.
14
+ class CommandError < UsageError; end
15
+
9
16
  COMMANDS = {
10
17
  "packages" => "List package names under the source root",
11
18
  "build" => "Compile artifacts into the build root",
@@ -22,6 +29,12 @@ module SimpleAgentExtension
22
29
  @error = error
23
30
  end
24
31
 
32
+ # Only errors this CLI defines, and the one OptionParser raises for a
33
+ # misspelled option, are reduced to a message. Everything else passes
34
+ # through with its class, origin, and backtrace intact.
35
+ #
36
+ # CommandError has to be listed first: it is a UsageError, so the wider
37
+ # clause would take it otherwise.
25
38
  def run(arguments)
26
39
  arguments = arguments.dup
27
40
  options = default_options
@@ -35,9 +48,10 @@ module SimpleAgentExtension
35
48
  AgentDirectoryLoader.new(options[:agent_directories]).load
36
49
  run_command(command, options)
37
50
  0
38
- rescue OptionParser::ParseError, Error, ArgumentError, KeyError => error
39
- @error.puts error.message
40
- 1
51
+ rescue CommandError => error
52
+ report_failure(error, usage: parser)
53
+ rescue OptionParser::ParseError, UsageError => error
54
+ report_failure(error)
41
55
  end
42
56
 
43
57
  # Aligns the name column alone. Columns an Agent does not declare are
@@ -55,6 +69,16 @@ module SimpleAgentExtension
55
69
 
56
70
  private
57
71
 
72
+ # @param [Exception] error
73
+ # @param [OptionParser, nil] usage printed when the caller still needs the
74
+ # command vocabulary
75
+ # @return [Integer] exit status the run reports as a failure
76
+ def report_failure(error, usage: nil)
77
+ @error.puts error.message
78
+ @error.puts usage if usage
79
+ 1
80
+ end
81
+
58
82
  def default_options
59
83
  {
60
84
  source_root: File.expand_path("packages"),
@@ -105,9 +129,9 @@ module SimpleAgentExtension
105
129
 
106
130
  def command(arguments)
107
131
  command = arguments.shift
108
- raise ArgumentError, "missing command" unless command
109
- raise ArgumentError, "unknown command: #{command}" unless COMMANDS.key?(command)
110
- raise ArgumentError, "unexpected arguments: #{arguments.join(" ")}" unless arguments.empty?
132
+ raise CommandError, "missing command" unless command
133
+ raise CommandError, "unknown command: #{command}" unless COMMANDS.key?(command)
134
+ raise CommandError, "unexpected arguments: #{arguments.join(" ")}" unless arguments.empty?
111
135
 
112
136
  command
113
137
  end
@@ -115,7 +139,7 @@ module SimpleAgentExtension
115
139
  def validate_options(command, options)
116
140
  return unless options[:force] && command != "deploy"
117
141
 
118
- raise ArgumentError, "--force is only valid for deploy"
142
+ raise UsageError, "--force is only valid for deploy"
119
143
  end
120
144
 
121
145
  def run_command(command, options)
@@ -1,5 +1,8 @@
1
1
  module SimpleAgentExtension
2
2
  module Extensions
3
+ class EntrypointDocumentNotFound < Error; end
4
+ class InvalidEntrypointFrontmatter < Error; end
5
+
3
6
  EntrypointDocument = Data.define(:metadata, :body)
4
7
 
5
8
  # An extension that owns loading metadata from its directory.
@@ -48,6 +51,12 @@ module SimpleAgentExtension
48
51
  metadata, body = Frontmatter.parse(File.read(entrypoint_path))
49
52
 
50
53
  EntrypointDocument.new(metadata, body)
54
+ rescue Errno::ENOENT => e
55
+ not_found = EntrypointDocumentNotFound.new("entrypoint of package `#{@package}' / type `#{type}', #{entrypoint_path} not found.")
56
+ not_found.set_backtrace(e.backtrace)
57
+ raise not_found, cause: nil
58
+ rescue Psych::SyntaxError => e
59
+ raise InvalidEntrypointFrontmatter, "#{entrypoint_path}: #{[e.problem, e.context].compact.join(" ")} at line #{e.line + Frontmatter::METADATA_START_LINE_OFFSET} column #{e.column}", cause: nil
51
60
  end
52
61
 
53
62
  # @return [MetadataLoader] source YAML reader
@@ -13,6 +13,8 @@ module SimpleAgentExtension
13
13
  module Frontmatter
14
14
  DELIMITER = "---".freeze
15
15
  PATTERN = /\A---\r?\n(.*?)^---[ \t]*\r?\n?/m
16
+ # Metadata starts after the opening delimiter line.
17
+ METADATA_START_LINE_OFFSET = 1
16
18
 
17
19
  class InvalidFrontmatter < Error; end
18
20
 
@@ -8,15 +8,23 @@ module SimpleAgentExtension
8
8
  # reader exposes adaptive, common static, and Agent-specific static fragment
9
9
  # collections without defining their field vocabulary.
10
10
  class MetadataLoader
11
+ class InvalidMetadata < Error; end
12
+
11
13
  FILENAME = "metadata.yaml".freeze
12
14
 
15
+ # Psych does not know which file it parsed, so the path is attached here.
16
+ # Its backtrace points into Psych itself, so it is dropped.
17
+ #
13
18
  # @param [String] dir
14
19
  # @return [MetadataLoader] empty when +metadata.yaml+ is absent, never nil
20
+ # @raise [InvalidMetadata] when +metadata.yaml+ has a YAML syntax error
15
21
  def self.load(dir)
16
22
  path = File.join(dir, FILENAME)
17
23
  return new(Metadata.new) unless File.exist?(path)
18
24
 
19
25
  new(Metadata.from(YAML.safe_load(File.read(path)) || {})) # rubocop:disable Style/YAMLFileRead
26
+ rescue Psych::SyntaxError => e
27
+ raise InvalidMetadata, "#{path}: #{[e.problem, e.context].compact.join(" ")} at line #{e.line} column #{e.column}", cause: nil
20
28
  end
21
29
 
22
30
  # @param [Metadata] metadata source YAML mapping
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SimpleAgentExtension
4
- VERSION = "0.2.1"
4
+ VERSION = "0.2.2"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simple-agent-extension
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - ''
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-10-02 00:00:00.000000000 Z
11
+ date: 2026-10-04 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: 'Coding Agent Extension Utility with Simple DSL and Rule Translating
14
14
  and Deploying '