context_spook 1.3.0 → 1.5.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: a00a3e36535b351b630e539a1dfae938bb2325c2f639e3d0b318f1cac0e8c14f
4
- data.tar.gz: 3c7976d1672dd67d6b0b07d64350e3baf211d6e8752b83631de9f5a17ae642f3
3
+ metadata.gz: 5cca218e18443bf3698be556f93b822253a9f0dd4c93322d1ee9c826d1a26dc3
4
+ data.tar.gz: d8c48e20203cbc5c1c0741e93805480aa7fbe9987821fe2b9839447902879149
5
5
  SHA512:
6
- metadata.gz: 82bf0afffa28eab0b379ec94c9a7a7cd34406ca82ccf4a7e78d26103082b8610ce3461a06a26772381fe59d6cfa401516eed532d33c6742cff980d08dea5508d
7
- data.tar.gz: f969059b0b7ca9490ceb6560c5735da343c4ee5ee5ff856bae919da5ab66f02886e55a7096ad33b91241a147d78f5b5a82ec652ce25800658d46e4dc6a87bbc2
6
+ metadata.gz: a7f1fb4f2b26f9c59dc6a48be8db0a2ffc4381250334a401c6ad2944fe398cb18bcc0154df6111d26ceac1a9bcad7ac4386626aeb681bbe20f1286310fbe58f0
7
+ data.tar.gz: 990b7df25449551007c8e986ec479bdf5656195e47ef6d7243603849179a5fac6edaa6e245bbfaa99768115b3b46eeffc5baf6f37e542c8a4b729dc443ba8b13
data/Rakefile CHANGED
@@ -38,7 +38,7 @@ GemHadar do
38
38
  dependency 'mime-types', '~> 3.0'
39
39
  dependency 'yaml', '~> 0.4'
40
40
  dependency 'pathname', '~> 0.4'
41
- dependency 'ruby-json-toon', '~> 1.0'
41
+ dependency 'toon-ruby', '>= 0.1'
42
42
  development_dependency 'all_images', '~> 0.6'
43
43
  development_dependency 'rspec', '~> 3.2'
44
44
  development_dependency 'debug'
@@ -1,9 +1,9 @@
1
1
  # -*- encoding: utf-8 -*-
2
- # stub: context_spook 1.3.0 ruby lib
2
+ # stub: context_spook 1.5.0 ruby lib
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "context_spook".freeze
6
- s.version = "1.3.0".freeze
6
+ s.version = "1.5.0".freeze
7
7
 
8
8
  s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
9
9
  s.require_paths = ["lib".freeze]
@@ -13,7 +13,7 @@ Gem::Specification.new do |s|
13
13
  s.email = "flori@ping.de".freeze
14
14
  s.executables = ["context_spook".freeze]
15
15
  s.extra_rdoc_files = ["README.md".freeze, "lib/context_spook.rb".freeze, "lib/context_spook/generator.rb".freeze, "lib/context_spook/output_context.rb".freeze, "lib/context_spook/toon.rb".freeze, "lib/context_spook/utils.rb".freeze, "lib/context_spook/verbose_puts.rb".freeze, "lib/context_spook/version.rb".freeze]
16
- s.files = [".contexts/project.rb".freeze, "Gemfile".freeze, "LICENSE".freeze, "README.md".freeze, "Rakefile".freeze, "bin/context_spook".freeze, "context_spook.gemspec".freeze, "hello_world.json".freeze, "hey_world.yaml".freeze, "lib/context_spook.rb".freeze, "lib/context_spook/generator.rb".freeze, "lib/context_spook/output_context.rb".freeze, "lib/context_spook/toon.rb".freeze, "lib/context_spook/utils.rb".freeze, "lib/context_spook/verbose_puts.rb".freeze, "lib/context_spook/version.rb".freeze, "spec/context_spook/generator_spec.rb".freeze, "spec/context_spook/toon_spec.rb".freeze, "spec/spec_helper.rb".freeze]
16
+ s.files = [".contexts/project.rb".freeze, "Gemfile".freeze, "LICENSE".freeze, "README.md".freeze, "Rakefile".freeze, "bin/context_spook".freeze, "context_spook.gemspec".freeze, "hello_world.json".freeze, "hey_world.yaml".freeze, "lib/context_spook.rb".freeze, "lib/context_spook/generator.rb".freeze, "lib/context_spook/output_context.rb".freeze, "lib/context_spook/toon.rb".freeze, "lib/context_spook/toon/example.md".freeze, "lib/context_spook/utils.rb".freeze, "lib/context_spook/verbose_puts.rb".freeze, "lib/context_spook/version.rb".freeze, "spec/context_spook/generator_spec.rb".freeze, "spec/context_spook/toon_spec.rb".freeze, "spec/spec_helper.rb".freeze]
17
17
  s.homepage = "https://github.com/flori/context_spook".freeze
18
18
  s.licenses = ["MIT".freeze]
19
19
  s.rdoc_options = ["--title".freeze, "ContextSpook - context_spook collects project context for AI".freeze, "--main".freeze, "README.md".freeze]
@@ -36,5 +36,5 @@ Gem::Specification.new do |s|
36
36
  s.add_runtime_dependency(%q<mime-types>.freeze, ["~> 3.0".freeze])
37
37
  s.add_runtime_dependency(%q<yaml>.freeze, ["~> 0.4".freeze])
38
38
  s.add_runtime_dependency(%q<pathname>.freeze, ["~> 0.4".freeze])
39
- s.add_runtime_dependency(%q<ruby-json-toon>.freeze, ["~> 1.0".freeze])
39
+ s.add_runtime_dependency(%q<toon-ruby>.freeze, [">= 0.1".freeze])
40
40
  end
@@ -13,28 +13,30 @@ require 'context_spook/output_context'
13
13
  module ContextSpook
14
14
  include DSLKit::Interpreter
15
15
 
16
- # The generate_context method processes a context definition file or block
17
- # and returns the resulting context object.
16
+ # The generate_context method creates a context object by either evaluating a
17
+ # block or parsing a file
18
18
  #
19
- # This method serves as the primary entry point for generating project
20
- # context data. It accepts either a filename pointing to a context definition
21
- # file or a block containing the context definition, but not both.
22
- # When a filename is provided, it reads and parses the file content. When a
23
- # block is provided, it evaluates the block within the generator's context.
24
- # The method ensures that only one context definition mechanism is used.
19
+ # This method serves as the primary entry point for generating context data.
20
+ # It accepts either a filename pointing to a context definition file or a
21
+ # block containing the context definition. The method handles the creation of
22
+ # a generator instance, processes the context definition, and returns the
23
+ # resulting context object.
25
24
  #
26
- # @param filename [ String, nil ] the path to the context definition file to
27
- # be processed
25
+ # @param filename [ String, nil ] the path to a context definition file, or
26
+ # nil if using a block
28
27
  # @param verbose [ TrueClass, FalseClass ] flag to enable verbose output
29
- # during processing, defaults to false.
30
- # @param block [ Proc ] a block containing the context definition to be
31
- # evaluated
28
+ # during processing
29
+ # @param format [ String, nil ] the output format for the context, either
30
+ # 'JSON' or 'TOON'
31
+ # @param block [ Proc ] a block containing the context definition, used if
32
+ # filename is nil
32
33
  #
33
- # @return [ ContextSpook::Generator::Context ] the context object generated
34
- # from the file contents or block
34
+ # @return [ ContextSpook::Generator::Context ] the generated context object containing
35
+ # project metadata, file contents, command outputs, and variables
35
36
  #
36
37
  # @raise [ ArgumentError ] if neither a filename nor a block is provided
37
- # @raise [ ArgumentError ] if both a filename and a block are provided
38
+ # @raise [ ArgumentError ] if an invalid format is specified
39
+ # @raise [ ArgumentError ] if the context definition file cannot be read or parsed
38
40
  def self.generate_context(filename = nil, verbose: false, format: nil, &block)
39
41
  verbose = !!verbose
40
42
  filename.present? ^ block or
@@ -56,8 +58,18 @@ module ContextSpook
56
58
  include VerbosePuts
57
59
  include OutputContext
58
60
 
61
+ # The verbose method returns the verbose flag indicating whether verbose
62
+ # output is enabled.
63
+ #
64
+ # @return [ TrueClass, FalseClass ] true if verbose output is enabled,
65
+ # false otherwise
59
66
  attr_reader :verbose
60
67
 
68
+ # The format method returns the format identifier for the context output.
69
+ #
70
+ # @return [ String ] the format identifier, either 'JSON' or 'TOON'
71
+ attr_reader :format
72
+
61
73
  private_class_method :new
62
74
 
63
75
  # The initialize method sets up the object by evaluating the provided block
@@ -70,6 +82,9 @@ module ContextSpook
70
82
  def initialize(verbose: false, format: nil, &block)
71
83
  @verbose = !!verbose
72
84
  @format = (format || 'JSON').upcase
85
+ %w[ TOON JSON ].include?(@format) or
86
+ raise ArgumentError,
87
+ "format needs to be either JSON or TOON, was #{@format.inspect}"
73
88
  block and instance_eval(&block)
74
89
  end
75
90
 
@@ -107,8 +122,17 @@ module ContextSpook
107
122
  def initialize(generator:, &block)
108
123
  @generator = generator
109
124
  block and instance_eval(&block)
125
+ meta(format: generator.format)
126
+ if generator.format == 'TOON'
127
+ meta(toon_example: toon_example)
128
+ end
110
129
  end
111
130
 
131
+ # The generator method returns the generator object associated with this
132
+ # context.
133
+ #
134
+ # @return [ ContextSpook::Generator ] the generator instance that created
135
+ # this context
112
136
  attr_reader :generator
113
137
 
114
138
  delegate :verbose, to: :generator
@@ -0,0 +1,69 @@
1
+ # TOON (Token-Oriented Object Notation)
2
+
3
+ It is a compact, human-readable serialization format that reduces JSON token
4
+ count by 30-40% while maintaining lossless data fidelity. It uses CSV-style
5
+ tabular arrays for uniform data structures and YAML-like indentation for nested
6
+ objects, making it ideal for LLM input where token efficiency and parsing
7
+ reliability matter.
8
+
9
+ Key benefit: Same data, fewer tokens, better LLM understanding.
10
+
11
+ **Original JSON:**
12
+ ```json
13
+ {
14
+ "database": {
15
+ "name": "user_management",
16
+ "tables": [
17
+ {
18
+ "name": "users",
19
+ "columns": [
20
+ {
21
+ "name": "id",
22
+ "type": "integer",
23
+ "primary_key": true
24
+ },
25
+ {
26
+ "name": "email",
27
+ "type": "string",
28
+ "unique": true
29
+ }
30
+ ],
31
+ "row_count": 1000
32
+ },
33
+ {
34
+ "name": "orders",
35
+ "columns": [
36
+ {
37
+ "name": "id",
38
+ "type": "integer",
39
+ "primary_key": true
40
+ },
41
+ {
42
+ "name": "user_id",
43
+ "type": "integer"
44
+ }
45
+ ],
46
+ "row_count": 5000
47
+ }
48
+ ]
49
+ }
50
+ }
51
+ ```
52
+
53
+ **TOON equivalent:**
54
+ ```
55
+ database:
56
+ name: user_management
57
+ tables[2]{name,row_count}:
58
+ users,1000
59
+ orders,5000
60
+ tables[2]{name,columns}:
61
+ users:
62
+ columns[2]{name,type,primary_key}:
63
+ id,integer,true
64
+ email,string,true
65
+ orders:
66
+ columns[2]{name,type}:
67
+ id,integer,true
68
+ user_id,integer,false
69
+ ```
@@ -1,4 +1,4 @@
1
- require 'ruby_json_toon'
1
+ require 'toon'
2
2
 
3
3
  # The ContextSpook::TOON module provides TOON (Token-Oriented Object Notation)
4
4
  # serialization functionality for context objects.
@@ -7,7 +7,7 @@ module ContextSpook::TOON
7
7
  #
8
8
  # @return [String] the TOON-encoded representation of the context
9
9
  def to_toon
10
- RubyJsonToon.encode(as_json)
10
+ ::Toon.encode(as_json)
11
11
  end
12
12
  memoize method: :to_toon
13
13
 
@@ -17,4 +17,17 @@ module ContextSpook::TOON
17
17
  def toon_size
18
18
  to_toon.size
19
19
  end
20
+
21
+ # The toon_example method reads and returns the content of an example
22
+ # Markdown file that demonstrates the TOON (Token-Oriented Object Notation)
23
+ # format.
24
+ #
25
+ # This method is used to provide a sample representation of how context data
26
+ # can be formatted in TOON, which is an alternative serialization format
27
+ # supported by the ContextSpook library.
28
+ #
29
+ # @return [ String ] the content of the TOON example Markdown file
30
+ def toon_example
31
+ File.read(Pathname.new(__dir__) + 'toon/example.md')
32
+ end
20
33
  end
@@ -1,6 +1,6 @@
1
1
  module ContextSpook
2
2
  # ContextSpook version
3
- VERSION = '1.3.0'
3
+ VERSION = '1.5.0'
4
4
  VERSION_ARRAY = VERSION.split('.').map(&:to_i) # :nodoc:
5
5
  VERSION_MAJOR = VERSION_ARRAY[0] # :nodoc:
6
6
  VERSION_MINOR = VERSION_ARRAY[1] # :nodoc:
@@ -33,6 +33,21 @@ describe ContextSpook::Generator do
33
33
  described_class.send(:new).output_context_size
34
34
  end
35
35
 
36
+ context 'can handle formats' do
37
+ it 'raises exceptions for invalid formats' do
38
+ generator = described_class.send(:new, format: 'TOON')
39
+ expect(generator.format).to eq 'TOON'
40
+ end
41
+
42
+ it 'raises exceptions for invalid formats' do
43
+ expect {
44
+ described_class.send(:new, format: 'YAML')
45
+ }.to raise_error(
46
+ ArgumentError, /format needs to be either JSON or TOON, was "YAML"/
47
+ )
48
+ end
49
+ end
50
+
36
51
  it 'cannot do from block and filename' do
37
52
  expect {
38
53
  ContextSpook.generate_context('.contexts/project.rb') { }
@@ -20,8 +20,22 @@ describe ContextSpook::TOON do
20
20
 
21
21
  it 'produces valid TOON output' do
22
22
  toon_output = context.to_toon
23
- # TOON should be a valid string representation
24
- expect { RubyJsonToon.decode(toon_output) }.not_to raise_error
23
+ expect(toon_output).to match(
24
+ %r{
25
+ \Afiles:\n
26
+ ^[ ]{2}"lib/context_spook\.rb":\n
27
+ ^[ ]{4}content:[ ]"[^"]+"\n
28
+ ^[ ]{4}size:[ ]120\n
29
+ ^[ ]{4}lines:[ ]5\n
30
+ ^[ ]{4}content_types\[2\]:[ ]application/x-ruby,text/x-ruby\n
31
+ ^commands:\n
32
+ ^metadata:\n
33
+ ^[ ]{2}version:[ ]"1\.0"\n
34
+ ^[ ]{2}format:[ ]JSON\n
35
+ ^variables:\n
36
+ ^[ ]{2}foo:[ ]bar\z
37
+ }x
38
+ )
25
39
  end
26
40
  end
27
41
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: context_spook
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Florian Frank
@@ -178,19 +178,19 @@ dependencies:
178
178
  - !ruby/object:Gem::Version
179
179
  version: '0.4'
180
180
  - !ruby/object:Gem::Dependency
181
- name: ruby-json-toon
181
+ name: toon-ruby
182
182
  requirement: !ruby/object:Gem::Requirement
183
183
  requirements:
184
- - - "~>"
184
+ - - ">="
185
185
  - !ruby/object:Gem::Version
186
- version: '1.0'
186
+ version: '0.1'
187
187
  type: :runtime
188
188
  prerelease: false
189
189
  version_requirements: !ruby/object:Gem::Requirement
190
190
  requirements:
191
- - - "~>"
191
+ - - ">="
192
192
  - !ruby/object:Gem::Version
193
- version: '1.0'
193
+ version: '0.1'
194
194
  description: |
195
195
  context_spook is a library that collects and organizes project
196
196
  information to help AI assistants understand codebases better.
@@ -221,6 +221,7 @@ files:
221
221
  - lib/context_spook/generator.rb
222
222
  - lib/context_spook/output_context.rb
223
223
  - lib/context_spook/toon.rb
224
+ - lib/context_spook/toon/example.md
224
225
  - lib/context_spook/utils.rb
225
226
  - lib/context_spook/verbose_puts.rb
226
227
  - lib/context_spook/version.rb