context_spook 0.1.0 → 0.2.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: 8061fffaf039f19b3b37a0df7ce5ce62624c04c303fd525a6b2a96b74bbf0fd4
4
- data.tar.gz: 72b878f810bd5695aa0a09144fb3eb66475d7e12d73ba1cd1b17694e54a89c00
3
+ metadata.gz: 4088e8a4f8de00062dcea1b56b696dd1190731c0c30944a95c60a14cad995fa9
4
+ data.tar.gz: 996fb30d8a2542a387451416ece827dd1b8062344317ef798db803c216d39e17
5
5
  SHA512:
6
- metadata.gz: f5f21ce7d81d9488732ebbe27e2b17096fa6c92afcd2e9dadf0427cad36a33eb48e4e114a7bd687a0fb60a37351297b8cbbcc035e4a6644c530a3007ee2aedc3
7
- data.tar.gz: 38bc4a4e00193b70fce74115e8ba8d230dbb06d3c6179cebb1c889b83fb10310fe3d9699f8bbc26ef4d16fbd9c646c080274ea738e56d94fe08381250c7c1a96
6
+ metadata.gz: df6ce1080b5b98a1e279f945cb0e5934592ea586c15abc24234b1c44aaa0d5aac55308227c2966a1e2e9912f620f4d13a5bda0940726028f589aa0ee522dc3fd
7
+ data.tar.gz: 2b787ae025a227d47f7d6ab53d850bc0c2084a6872e16bb2b60d122965d3dcdb17531fc4118371de82da0edcdd29b7a4ebe143b55019d3116bb424117edb85f4
data/README.md CHANGED
@@ -32,8 +32,46 @@ $ gem install context_spook
32
32
 
33
33
  ## Usage
34
34
 
35
- Create a `contexts/project.rb` file that describes your project context using
36
- the DSL in a context definition file:
35
+ ### Programmatic Usage
36
+
37
+ #### Directly in Ruby
38
+
39
+ Now you can generate context from a block directly in Ruby using the DSL:
40
+
41
+ ```ruby
42
+ context = ContextSpook::generate_context do
43
+ context do
44
+ variable branch: `git rev-parse --abbrev-ref HEAD`.chomp
45
+
46
+ namespace "structure" do
47
+ command "tree", tags: %w[ project_structure ]
48
+ end
49
+
50
+ namespace "lib" do
51
+ Dir['lib/**/*.rb'].each do |filename|
52
+ file filename, tags: 'lib'
53
+ end
54
+ end
55
+
56
+ # ... rest of your context definition, see below for full example
57
+ end
58
+ end
59
+ ```
60
+
61
+ This approach can be used to dynamically generate a context when it is not
62
+ configurable via a user context definition file, or as a fallback when users
63
+ have not yet created such files.
64
+
65
+ Afterwards you can store the context as JSON in Ruby or send it to another
66
+ application.
67
+
68
+ ```ruby
69
+ File.write 'context.json', context.to_json
70
+ ```
71
+
72
+ #### From a context definition file
73
+
74
+ Alternatively store the block's content above to a file `contexts/project.rb`:
37
75
 
38
76
  ```ruby
39
77
  # contexts/project.rb
@@ -41,7 +79,7 @@ context do
41
79
  variable branch: `git rev-parse --abbrev-ref HEAD`.chomp
42
80
 
43
81
  namespace "structure" do
44
- command "tree lib", tags: %w[ project_structure ]
82
+ command "tree", tags: %w[ project_structure ]
45
83
  end
46
84
 
47
85
  namespace "lib" do
@@ -72,9 +110,8 @@ context do
72
110
  end
73
111
  ```
74
112
 
75
- ### Programmatic Usage
76
-
77
- Now you can generate the context from the file, and store it as JSON in Ruby.
113
+ Now you can generate the context from the file, and store it as JSON in Ruby or
114
+ send it to another application.
78
115
 
79
116
  ```ruby
80
117
  context = ContextSpook::generate_context('contexts/project.rb')
@@ -129,11 +166,13 @@ assistants understand:
129
166
  "content": "...",
130
167
  "size": 1234,
131
168
  "lines": 56,
132
- "tags": ["lib"]
169
+ "tags": [
170
+ "lib"
171
+ ]
133
172
  }
134
173
  },
135
174
  "commands": {
136
- "tree lib": {
175
+ "tree": {
137
176
  "namespace": "structure",
138
177
  "output": "lib\n├── context_spook\n│ └── generator.rb\n└── context_spook.rb\n\n2 directories, 3 files",
139
178
  "exit_code": 0,
@@ -142,7 +181,7 @@ assistants understand:
142
181
  },
143
182
  "metadata": {
144
183
  "ruby": "ruby 3.1.0 ...",
145
- "code_coverage": { ... }
184
+ "code_coverage": {}
146
185
  },
147
186
  "variables": {
148
187
  "branch": "main"
data/Rakefile CHANGED
@@ -29,6 +29,7 @@ GemHadar do
29
29
  dependency 'tins', '~>1.39'
30
30
  dependency 'json', '~>2.0'
31
31
  dependency 'term-ansicolor', '~> 1.11'
32
+ dependency 'mize', '~> 0.6'
32
33
  development_dependency 'all_images', '~> 0.6'
33
34
  development_dependency 'rspec', '~> 3.2'
34
35
  development_dependency 'debug'
data/bin/context_spook CHANGED
@@ -4,8 +4,4 @@ require 'context_spook'
4
4
 
5
5
  filename = ARGV.shift or fail 'require context definition file as first argument'
6
6
  context_json = ContextSpook.generate_context(filename).to_json
7
- context_json_size = Tins::Unit.format(
8
- context_json.size, format: '%.2f %U', unit: ?b, prefix: 1024
9
- )
10
- STDERR.puts "Now outputting #{context_json_size} of JSON context in total."
11
7
  puts context_json
@@ -1,9 +1,9 @@
1
1
  # -*- encoding: utf-8 -*-
2
- # stub: context_spook 0.1.0 ruby lib
2
+ # stub: context_spook 0.2.0 ruby lib
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "context_spook".freeze
6
- s.version = "0.1.0".freeze
6
+ s.version = "0.2.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]
@@ -32,4 +32,5 @@ Gem::Specification.new do |s|
32
32
  s.add_runtime_dependency(%q<tins>.freeze, ["~> 1.39".freeze])
33
33
  s.add_runtime_dependency(%q<json>.freeze, ["~> 2.0".freeze])
34
34
  s.add_runtime_dependency(%q<term-ansicolor>.freeze, ["~> 1.11".freeze])
35
+ s.add_runtime_dependency(%q<mize>.freeze, ["~> 0.6".freeze])
35
36
  end
data/contexts/project.rb CHANGED
@@ -2,7 +2,7 @@ context do
2
2
  variable branch: `git rev-parse --abbrev-ref HEAD`.chomp
3
3
 
4
4
  namespace "structure" do
5
- command "tree lib", tags: %w[ project_structure ]
5
+ command "tree", tags: %w[ project_structure ]
6
6
  end
7
7
 
8
8
  namespace "lib" do
@@ -1,7 +1,7 @@
1
1
  require 'tins/xt'
2
2
  require 'term/ansicolor'
3
3
  require 'json'
4
-
4
+ require 'mize'
5
5
 
6
6
  # The ContextSpook module serves as a namespace container for collecting and
7
7
  # organizing project information for AI assistance.
@@ -19,8 +19,16 @@ module ContextSpook
19
19
  #
20
20
  # @return [ ContextSpook::Generator::Context ] the context object generated
21
21
  # from the file contents
22
- def self.generate_context(filename)
23
- Generator.send(:new).send(:parse, File.read(filename)).context
22
+ def self.generate_context(filename = nil, &block)
23
+ filename.present? ^ block or
24
+ raise ArgumentError, 'need either a filename or a &block argument'
25
+ generator = if filename
26
+ Generator.send(:new).send(:parse, File.read(filename))
27
+ else
28
+ Generator.send(:new, &block)
29
+ end
30
+ generator.output_context_size
31
+ generator.context
24
32
  end
25
33
 
26
34
  # The Generator class provides a DSL parser that interprets context
@@ -52,6 +60,20 @@ module ContextSpook
52
60
  end
53
61
  end
54
62
 
63
+ # The output_context_size method prints the total size of the generated
64
+ # context JSON representation.
65
+ #
66
+ # This method calculates the size of the context object when serialized to
67
+ # JSON, formats it using binary units (KiB, MiB, etc.), and outputs the
68
+ # result to standard error.
69
+ def output_context_size
70
+ context_size = @context&.size.to_i
71
+ json_content_size = Tins::Unit.format(
72
+ context_size, format: '%.2f %U', unit: ?b, prefix: 1024
73
+ )
74
+ STDERR.puts "Built #{json_content_size} of JSON context in total."
75
+ end
76
+
55
77
  # The Context class represents and manages project context data, providing
56
78
  # structured storage for file contents, command outputs, variables, and
57
79
  # metadata that can be serialized to JSON for AI assistance.
@@ -214,6 +236,7 @@ module ContextSpook
214
236
  # The to_json method converts the object to a JSON representation by
215
237
  # first generating its hash form and then serializing that hash into JSON
216
238
  # format.
239
+ memoize method:
217
240
  def to_json(*)
218
241
  as_json.to_json(*)
219
242
  end
@@ -230,6 +253,19 @@ module ContextSpook
230
253
  variables:
231
254
  }
232
255
  end
256
+
257
+ # The size method calculates and returns the byte size of the JSON
258
+ # representation of the context.
259
+ #
260
+ # This method determines the size in bytes of the JSON-serialized version
261
+ # of the context object, which is useful for understanding the total data
262
+ # payload being sent to an AI assistant.
263
+ #
264
+ # @return [ Integer ] the size in bytes of the JSON representation of the
265
+ # context
266
+ def size
267
+ to_json.size
268
+ end
233
269
  end
234
270
 
235
271
  private
@@ -1,6 +1,6 @@
1
1
  module ContextSpook
2
2
  # ContextSpook version
3
- VERSION = '0.1.0'
3
+ VERSION = '0.2.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:
@@ -5,19 +5,46 @@ describe ContextSpook::Generator do
5
5
  ContextSpook.generate_context('contexts/project.rb')
6
6
  end
7
7
 
8
- it 'context can be generated' do
8
+ it 'context can be generated from block' do
9
+ expect_any_instance_of(described_class).to\
10
+ receive(:output_context_size).and_call_original
11
+ context = ContextSpook.generate_context do
12
+ context do
13
+ variable foo: 'bar'
14
+ metadata version: '1.0'
15
+ end
16
+ end
17
+ expect(context).to be_a described_class::Context
18
+ expect(context.variables[:foo]).to eq 'bar'
19
+ expect(context.metadata[:version]).to eq '1.0'
20
+ end
21
+
22
+ it 'context can be generated from filename' do
23
+ expect_any_instance_of(described_class).to\
24
+ receive(:output_context_size).and_call_original
9
25
  expect(context).to be_a described_class::Context
10
26
  expect(context.metadata[:ruby]).to eq RUBY_DESCRIPTION
11
27
  end
12
28
 
29
+ it 'could handle premature output_context_size calls' do
30
+ expect_any_instance_of(described_class).to\
31
+ receive(:output_context_size).and_call_original
32
+ described_class.send(:new).output_context_size
33
+ end
34
+
35
+ it 'cannot do from block and filename' do
36
+ expect {
37
+ ContextSpook.generate_context('contexts/project.rb') { }
38
+ }.to raise_error(ArgumentError, /need either a filename or a &block/)
39
+ end
40
+
13
41
  it 'context be transformed to JSON if loaded' do
14
42
  context_as_json = context.to_json
15
- expect(context_as_json.size).to be > 1024
43
+ expect(context.size).to be > 1024
16
44
  expect(JSON(context_as_json)).to be_a Hash
17
45
  end
18
46
 
19
47
  describe 'Context' do
20
-
21
48
  it 'can have variables' do
22
49
  expect(context.variables[:branch]).to be_present
23
50
  end
@@ -33,7 +60,7 @@ describe ContextSpook::Generator do
33
60
  end
34
61
 
35
62
  it 'can have commands' do
36
- command = context.commands['tree lib']
63
+ command = context.commands['tree']
37
64
  expect(command).to be_present
38
65
  expect(command[:working_directory]).to eq Dir.pwd
39
66
  expect(command[:exit_code]).to be_present
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: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Florian Frank
@@ -121,6 +121,20 @@ dependencies:
121
121
  - - "~>"
122
122
  - !ruby/object:Gem::Version
123
123
  version: '1.11'
124
+ - !ruby/object:Gem::Dependency
125
+ name: mize
126
+ requirement: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - "~>"
129
+ - !ruby/object:Gem::Version
130
+ version: '0.6'
131
+ type: :runtime
132
+ prerelease: false
133
+ version_requirements: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - "~>"
136
+ - !ruby/object:Gem::Version
137
+ version: '0.6'
124
138
  description: |
125
139
  context_spook is a library that collects and organizes project
126
140
  information to help AI assistants understand codebases better.