context_spook 0.5.0 → 0.6.1
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 +4 -4
- data/.contexts/project.rb +4 -0
- data/Rakefile +1 -0
- data/context_spook.gemspec +4 -3
- data/hey_world.yaml +2 -0
- data/lib/context_spook/generator.rb +74 -31
- data/lib/context_spook/version.rb +1 -1
- data/spec/context_spook/generator_spec.rb +33 -1
- metadata +16 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 58670ead7c97c0681f39da47670f4afeb1ac08d1dc3ab8ddcb740fa2bf679a00
|
|
4
|
+
data.tar.gz: 48db4e54b8a5bbdfe2dcd3e58196d0f42801ada41668d4e43338adb68a9acd82
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c6f4d3fc5143082767f5bd361575a130d37710eeeb36965a2d5cb578ddcea5716047b17f6220d4a2a82ad857685d58dae7ae77e53bb355f1c7e54807b941b0d8
|
|
7
|
+
data.tar.gz: e50fe54b405153348f1936023c81330b67bfe0f7dc620cf9d85cb929cb7558383c6a2ec65b37e4502a7fd5608ec8028935f56e229a4f9e0c4734948ce3176f77
|
data/.contexts/project.rb
CHANGED
data/Rakefile
CHANGED
|
@@ -36,6 +36,7 @@ GemHadar do
|
|
|
36
36
|
dependency 'term-ansicolor', '~> 1.11'
|
|
37
37
|
dependency 'mize', '~> 0.6'
|
|
38
38
|
dependency 'mime-types', '~> 3.0'
|
|
39
|
+
dependency 'yaml', '~> 0.4'
|
|
39
40
|
development_dependency 'all_images', '~> 0.6'
|
|
40
41
|
development_dependency 'rspec', '~> 3.2'
|
|
41
42
|
development_dependency 'debug'
|
data/context_spook.gemspec
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
|
2
|
-
# stub: context_spook 0.
|
|
2
|
+
# stub: context_spook 0.6.1 ruby lib
|
|
3
3
|
|
|
4
4
|
Gem::Specification.new do |s|
|
|
5
5
|
s.name = "context_spook".freeze
|
|
6
|
-
s.version = "0.
|
|
6
|
+
s.version = "0.6.1".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/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, "lib/context_spook.rb".freeze, "lib/context_spook/generator.rb".freeze, "lib/context_spook/version.rb".freeze, "spec/context_spook/generator_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/version.rb".freeze, "spec/context_spook/generator_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]
|
|
@@ -34,4 +34,5 @@ Gem::Specification.new do |s|
|
|
|
34
34
|
s.add_runtime_dependency(%q<term-ansicolor>.freeze, ["~> 1.11".freeze])
|
|
35
35
|
s.add_runtime_dependency(%q<mize>.freeze, ["~> 0.6".freeze])
|
|
36
36
|
s.add_runtime_dependency(%q<mime-types>.freeze, ["~> 3.0".freeze])
|
|
37
|
+
s.add_runtime_dependency(%q<yaml>.freeze, ["~> 0.4".freeze])
|
|
37
38
|
end
|
data/hey_world.yaml
ADDED
|
@@ -3,12 +3,37 @@ require 'term/ansicolor'
|
|
|
3
3
|
require 'json'
|
|
4
4
|
require 'mize'
|
|
5
5
|
require 'mime-types'
|
|
6
|
+
require 'yaml'
|
|
6
7
|
|
|
7
8
|
# The ContextSpook module serves as a namespace container for collecting and
|
|
8
9
|
# organizing project information for AI assistance.
|
|
9
10
|
module ContextSpook
|
|
10
11
|
include DSLKit::Interpreter
|
|
11
12
|
|
|
13
|
+
# The VerbosePuts module provides a conditional output mechanism for
|
|
14
|
+
# displaying status or debug messages.
|
|
15
|
+
#
|
|
16
|
+
# This module includes a method that outputs messages to standard error only
|
|
17
|
+
# when a verbose flag is enabled. It is designed to be included in classes
|
|
18
|
+
# that need to conditionally emit verbose logging information during
|
|
19
|
+
# processing.
|
|
20
|
+
module VerbosePuts
|
|
21
|
+
# The verbose_puts method outputs the given arguments to standard error
|
|
22
|
+
# only if verbose mode is enabled.
|
|
23
|
+
#
|
|
24
|
+
# This method serves as a conditional output mechanism, allowing debug or
|
|
25
|
+
# status messages to be displayed based on the verbosity setting of the
|
|
26
|
+
# object.
|
|
27
|
+
#
|
|
28
|
+
# @param a [ Array ] the arguments to be printed to standard error
|
|
29
|
+
#
|
|
30
|
+
# @return [ nil ] always returns nil after attempting to output
|
|
31
|
+
def verbose_puts(*a)
|
|
32
|
+
@verbose or return
|
|
33
|
+
STDERR.puts(a)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
12
37
|
# The generate_context method processes a context definition file or block
|
|
13
38
|
# and returns the resulting context object.
|
|
14
39
|
#
|
|
@@ -32,10 +57,11 @@ module ContextSpook
|
|
|
32
57
|
# @raise [ ArgumentError ] if neither a filename nor a block is provided
|
|
33
58
|
# @raise [ ArgumentError ] if both a filename and a block are provided
|
|
34
59
|
def self.generate_context(filename = nil, verbose: false, &block)
|
|
60
|
+
verbose = !!verbose
|
|
35
61
|
filename.present? ^ block or
|
|
36
62
|
raise ArgumentError, 'need either a filename or a &block argument'
|
|
37
63
|
generator = if filename
|
|
38
|
-
|
|
64
|
+
Generator.send(:new, verbose:).send(:parse, File.read(filename))
|
|
39
65
|
else
|
|
40
66
|
Generator.send(:new, verbose:, &block)
|
|
41
67
|
end
|
|
@@ -48,6 +74,8 @@ module ContextSpook
|
|
|
48
74
|
# project metadata, file contents, command outputs, and variables for AI
|
|
49
75
|
# assistance.
|
|
50
76
|
class Generator
|
|
77
|
+
include VerbosePuts
|
|
78
|
+
|
|
51
79
|
private_class_method :new
|
|
52
80
|
|
|
53
81
|
# The initialize method sets up the object by evaluating the provided block
|
|
@@ -58,7 +86,7 @@ module ContextSpook
|
|
|
58
86
|
# @param block [ Proc ] a block of code to be evaluated within the object's context
|
|
59
87
|
# If no block is given, the method does nothing.
|
|
60
88
|
def initialize(verbose: false, &block)
|
|
61
|
-
@verbose = verbose
|
|
89
|
+
@verbose = !!verbose
|
|
62
90
|
block and instance_eval(&block)
|
|
63
91
|
end
|
|
64
92
|
|
|
@@ -70,7 +98,7 @@ module ContextSpook
|
|
|
70
98
|
def context(&block)
|
|
71
99
|
if block
|
|
72
100
|
@context and raise ArgumentError, "only one context allowed"
|
|
73
|
-
@context = Context.new(&block)
|
|
101
|
+
@context = Context.new(verbose: @verbose, &block)
|
|
74
102
|
else
|
|
75
103
|
@context
|
|
76
104
|
end
|
|
@@ -87,24 +115,27 @@ module ContextSpook
|
|
|
87
115
|
json_content_size = Tins::Unit.format(
|
|
88
116
|
context_size, format: '%.2f %U', unit: ?b, prefix: 1024
|
|
89
117
|
)
|
|
90
|
-
|
|
91
|
-
STDERR.puts "Built #{json_content_size} of JSON context in total."
|
|
92
|
-
end
|
|
118
|
+
verbose_puts "Built #{json_content_size} of JSON context in total."
|
|
93
119
|
end
|
|
94
120
|
|
|
95
121
|
# The Context class represents and manages project context data, providing
|
|
96
122
|
# structured storage for file contents, command outputs, variables, and
|
|
97
123
|
# metadata that can be serialized to JSON for AI assistance.
|
|
98
124
|
class Context
|
|
125
|
+
include VerbosePuts
|
|
99
126
|
include Tins::Scope
|
|
100
127
|
include Tins::DSLAccessor
|
|
101
128
|
include Term::ANSIColor
|
|
102
129
|
|
|
103
|
-
# The initialize method sets up the object by evaluating
|
|
104
|
-
# object's context.
|
|
130
|
+
# The initialize method sets up the object by evaluating the provided block
|
|
131
|
+
# in the object's context.
|
|
105
132
|
#
|
|
106
|
-
# @param
|
|
107
|
-
|
|
133
|
+
# @param verbose [ TrueClass, FalseClass ] flag to enable verbose output
|
|
134
|
+
# during processing, defaults to false.
|
|
135
|
+
# @param block [ Proc ] a block of code to be evaluated within the object's context
|
|
136
|
+
# If no block is given, the method does nothing.
|
|
137
|
+
def initialize(verbose: false, &block)
|
|
138
|
+
@verbose = !!verbose
|
|
108
139
|
block and instance_eval(&block)
|
|
109
140
|
end
|
|
110
141
|
|
|
@@ -173,14 +204,34 @@ module ContextSpook
|
|
|
173
204
|
file_size = Tins::Unit.format(
|
|
174
205
|
File.size(filename), format: '%.2f %U', unit: ?b, prefix: 1024
|
|
175
206
|
)
|
|
176
|
-
|
|
177
|
-
STDERR.puts "Read #{filename.inspect} as JSON (%s) for context." % file_size
|
|
178
|
-
end
|
|
207
|
+
verbose_puts "Read #{filename.inspect} as JSON (%s) for context." % file_size
|
|
179
208
|
JSON.load_file(filename)
|
|
180
|
-
rescue Errno::ENOENT => e
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
209
|
+
rescue Errno::ENOENT, JSON::ParserError => e
|
|
210
|
+
verbose_puts color(208) { "Reading #{filename.inspect} as JSON caused #{e.class}: #{e}" }
|
|
211
|
+
nil
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
# The yaml method reads and parses a YAML file, returning the resulting
|
|
215
|
+
# data structure.
|
|
216
|
+
#
|
|
217
|
+
# This method attempts to load a YAML file from the specified path and
|
|
218
|
+
# returns the resulting Ruby data structure. It provides verbose output
|
|
219
|
+
# about the file size when successfully reading the file. In case of file
|
|
220
|
+
# not found errors or YAML syntax errors, it outputs a colored warning
|
|
221
|
+
# message to standard error and returns nil.
|
|
222
|
+
#
|
|
223
|
+
# @param filename [ String ] the path to the YAML file to be read and parsed
|
|
224
|
+
#
|
|
225
|
+
# @return [ Object, nil ] the parsed YAML data structure or nil if the
|
|
226
|
+
# file cannot be read
|
|
227
|
+
def yaml(filename)
|
|
228
|
+
file_size = Tins::Unit.format(
|
|
229
|
+
File.size(filename), format: '%.2f %U', unit: ?b, prefix: 1024
|
|
230
|
+
)
|
|
231
|
+
verbose_puts "Read #{filename.inspect} as YAML (%s) for context." % file_size
|
|
232
|
+
YAML.load_file(filename)
|
|
233
|
+
rescue Errno::ENOENT, Psych::SyntaxError => e
|
|
234
|
+
verbose_puts color(208) { "Reading #{filename.inspect} as YAML caused #{e.class}: #{e}" }
|
|
184
235
|
nil
|
|
185
236
|
end
|
|
186
237
|
|
|
@@ -214,14 +265,10 @@ module ContextSpook
|
|
|
214
265
|
file_size = Tins::Unit.format(
|
|
215
266
|
content.size, format: '%.2f %U', unit: ?b, prefix: 1024
|
|
216
267
|
)
|
|
217
|
-
|
|
218
|
-
STDERR.puts "Read #{filename.inspect} (%s) for context." % file_size
|
|
219
|
-
end
|
|
268
|
+
verbose_puts "Read #{filename.inspect} (%s) for context." % file_size
|
|
220
269
|
nil
|
|
221
270
|
rescue Errno::ENOENT => e
|
|
222
|
-
|
|
223
|
-
STDERR.puts color(208) { "Reading #{filename.inspect} caused #{e.class}: #{e}" }
|
|
224
|
-
end
|
|
271
|
+
verbose_puts color(208) { "Reading #{filename.inspect} caused #{e.class}: #{e}" }
|
|
225
272
|
end
|
|
226
273
|
|
|
227
274
|
# The commands method sets up a DSL accessor for provided command outputs.
|
|
@@ -244,11 +291,9 @@ module ContextSpook
|
|
|
244
291
|
output = `#{shell_command}`
|
|
245
292
|
exit_code = $?&.exitstatus.to_i
|
|
246
293
|
if exit_code != 0
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
}
|
|
251
|
-
end
|
|
294
|
+
verbose_puts color(208) {
|
|
295
|
+
"Executing #{shell_command.inspect} resulted in exit code #{exit_code}."
|
|
296
|
+
}
|
|
252
297
|
end
|
|
253
298
|
commands[shell_command] = {
|
|
254
299
|
namespace: scope_top,
|
|
@@ -260,9 +305,7 @@ module ContextSpook
|
|
|
260
305
|
output_size = Tins::Unit.format(
|
|
261
306
|
output.size, format: '%.2f %U', unit: ?b, prefix: 1024
|
|
262
307
|
)
|
|
263
|
-
|
|
264
|
-
STDERR.puts "Executed #{shell_command.inspect} with output (%s) for context." % output_size
|
|
265
|
-
end
|
|
308
|
+
verbose_puts "Executed #{shell_command.inspect} with output (%s) for context." % output_size
|
|
266
309
|
nil
|
|
267
310
|
end
|
|
268
311
|
|
|
@@ -2,7 +2,7 @@ require 'spec_helper'
|
|
|
2
2
|
|
|
3
3
|
describe ContextSpook::Generator do
|
|
4
4
|
let :context do
|
|
5
|
-
ContextSpook.generate_context('.contexts/project.rb')
|
|
5
|
+
ContextSpook.generate_context('.contexts/project.rb', verbose: true)
|
|
6
6
|
end
|
|
7
7
|
|
|
8
8
|
it 'context can be generated from block' do
|
|
@@ -76,5 +76,37 @@ describe ContextSpook::Generator do
|
|
|
76
76
|
it 'can have metada' do
|
|
77
77
|
expect(context.metadata[:ruby]).to eq RUBY_DESCRIPTION
|
|
78
78
|
end
|
|
79
|
+
|
|
80
|
+
it 'can have json metadata' do
|
|
81
|
+
expect(context.metadata[:hello_world]).to eq("hello" => "world")
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
it 'can have yaml metadata' do
|
|
85
|
+
expect(context.metadata[:hey_world]).to eq("hey" => "world")
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
it 'handles missing json files gracefully' do
|
|
89
|
+
expect(context.json('nixda.json')).to be_nil
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
it 'handles invalid json content gracefully' do
|
|
93
|
+
Tempfile.create('invalid.json') do |f|
|
|
94
|
+
f.write('{ invalid json }')
|
|
95
|
+
f.close
|
|
96
|
+
expect(context.json(f.path)).to be_nil
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
it 'handles missing yaml files gracefully' do
|
|
101
|
+
expect(context.yaml('nixda.yaml')).to be_nil
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
it 'handles invalid yaml content gracefully' do
|
|
105
|
+
Tempfile.create('invalid.yaml') do |f|
|
|
106
|
+
f.write('invalid: [yaml')
|
|
107
|
+
f.close
|
|
108
|
+
expect(context.yaml(f.path)).to be_nil
|
|
109
|
+
end
|
|
110
|
+
end
|
|
79
111
|
end
|
|
80
112
|
end
|
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.
|
|
4
|
+
version: 0.6.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Florian Frank
|
|
@@ -149,6 +149,20 @@ dependencies:
|
|
|
149
149
|
- - "~>"
|
|
150
150
|
- !ruby/object:Gem::Version
|
|
151
151
|
version: '3.0'
|
|
152
|
+
- !ruby/object:Gem::Dependency
|
|
153
|
+
name: yaml
|
|
154
|
+
requirement: !ruby/object:Gem::Requirement
|
|
155
|
+
requirements:
|
|
156
|
+
- - "~>"
|
|
157
|
+
- !ruby/object:Gem::Version
|
|
158
|
+
version: '0.4'
|
|
159
|
+
type: :runtime
|
|
160
|
+
prerelease: false
|
|
161
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
162
|
+
requirements:
|
|
163
|
+
- - "~>"
|
|
164
|
+
- !ruby/object:Gem::Version
|
|
165
|
+
version: '0.4'
|
|
152
166
|
description: |
|
|
153
167
|
context_spook is a library that collects and organizes project
|
|
154
168
|
information to help AI assistants understand codebases better.
|
|
@@ -170,6 +184,7 @@ files:
|
|
|
170
184
|
- bin/context_spook
|
|
171
185
|
- context_spook.gemspec
|
|
172
186
|
- hello_world.json
|
|
187
|
+
- hey_world.yaml
|
|
173
188
|
- lib/context_spook.rb
|
|
174
189
|
- lib/context_spook/generator.rb
|
|
175
190
|
- lib/context_spook/version.rb
|