context_spook 0.4.0 → 0.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 +4 -4
- data/.contexts/project.rb +6 -0
- data/README.md +28 -2
- data/Rakefile +6 -1
- data/bin/context_spook +53 -3
- data/context_spook.gemspec +4 -4
- data/lib/context_spook/generator.rb +51 -20
- data/lib/context_spook/version.rb +1 -1
- data/spec/context_spook/generator_spec.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bf46500652e697db299ccdfe21d5dd4c02953b699ca528b21810f87348eddceb
|
|
4
|
+
data.tar.gz: ad41e6c9f6141ba5303c845aaf26c2d141125201d82575834a62efc05c2ae7b8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: edab814b82519dc36f9bb01c4e59dfb372aad6c2e1fa0d8ef7f487a288281ad6bf9bf1474d09a7ff7b818c1a6140ef08c0ba464b986e9bf56a34bd2720f9e778
|
|
7
|
+
data.tar.gz: 052e05ca7fc2825a75b43e1b9a8585344f9d4e8a6a805e3a5d826680d81bfed723d4359db7083d6451ce4afa6e35e82688a979dae0fcd0dcde401784d373b2de
|
data/.contexts/project.rb
CHANGED
|
@@ -5,6 +5,12 @@ context do
|
|
|
5
5
|
command "tree", tags: %w[ project_structure ]
|
|
6
6
|
end
|
|
7
7
|
|
|
8
|
+
namespace "bin" do
|
|
9
|
+
Dir['bin/**/*'].each do |filename|
|
|
10
|
+
file filename, tags: 'bin'
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
8
14
|
namespace "lib" do
|
|
9
15
|
Dir['lib/**/*.rb'].each do |filename|
|
|
10
16
|
file filename, tags: 'lib'
|
data/README.md
CHANGED
|
@@ -12,6 +12,10 @@ information. The `.contexts/project.rb` example below demonstrates how to
|
|
|
12
12
|
describe a Ruby project, but the same principles apply across many different
|
|
13
13
|
domains.
|
|
14
14
|
|
|
15
|
+
## Documentation
|
|
16
|
+
|
|
17
|
+
Complete API documentation is available at: [GitHub.io](https://flori.github.io/context_spook/)
|
|
18
|
+
|
|
15
19
|
## Installation
|
|
16
20
|
|
|
17
21
|
Add this line to your application's Gemfile:
|
|
@@ -128,13 +132,35 @@ Generate context and save to file:
|
|
|
128
132
|
|
|
129
133
|
Or pipe directly to another tool:
|
|
130
134
|
|
|
131
|
-
```
|
|
135
|
+
```bash
|
|
132
136
|
./bin/context_spook .contexts/project.rb | ollama_chat_send
|
|
133
137
|
```
|
|
134
138
|
|
|
135
|
-
|
|
139
|
+
|
|
140
|
+
The CLI tool also supports verbose output:
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
# Generate context with verbose output
|
|
144
|
+
./bin/context_spook .contexts/project.rb -v
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Now you can see two orange warning messages, that demonstrates how errors like
|
|
136
148
|
missing files or commands with failing exit codes are handled.
|
|
137
149
|
|
|
150
|
+
The CLI tool also supports file redirection:
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
# Generate context and save to file
|
|
154
|
+
./bin/context_spook .contexts/project.rb -o context.json
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
This is how you can show the usage message:
|
|
158
|
+
|
|
159
|
+
```
|
|
160
|
+
# Show help
|
|
161
|
+
./bin/context_spook -h
|
|
162
|
+
```
|
|
163
|
+
|
|
138
164
|
## What Gets Collected
|
|
139
165
|
|
|
140
166
|
The DSL collects various types of project information:
|
data/Rakefile
CHANGED
|
@@ -9,7 +9,6 @@ GemHadar do
|
|
|
9
9
|
email 'flori@ping.de'
|
|
10
10
|
homepage "https://github.com/flori/context_spook"
|
|
11
11
|
summary "#{name} collects project context for AI"
|
|
12
|
-
executables 'context_spook'
|
|
13
12
|
|
|
14
13
|
description <<~EOT
|
|
15
14
|
#{name} is a library that collects and organizes project
|
|
@@ -24,6 +23,12 @@ GemHadar do
|
|
|
24
23
|
'.rspec', '.github'
|
|
25
24
|
readme 'README.md'
|
|
26
25
|
|
|
26
|
+
executables 'context_spook'
|
|
27
|
+
|
|
28
|
+
github_workflows(
|
|
29
|
+
'static.yml' => {}
|
|
30
|
+
)
|
|
31
|
+
|
|
27
32
|
required_ruby_version '~> 3.1'
|
|
28
33
|
|
|
29
34
|
dependency 'tins', '~>1.39'
|
data/bin/context_spook
CHANGED
|
@@ -1,7 +1,57 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
2
|
|
|
3
3
|
require 'context_spook'
|
|
4
|
+
require 'tins/go'
|
|
5
|
+
include Tins::GO
|
|
6
|
+
require 'json'
|
|
4
7
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
+
# The usage method displays the command-line interface help text and example
|
|
9
|
+
# usage patterns for the ContextSpook tool.
|
|
10
|
+
#
|
|
11
|
+
# This method outputs a formatted help message that includes the tool's usage
|
|
12
|
+
# syntax, available options, and practical examples.
|
|
13
|
+
#
|
|
14
|
+
# @see ContextSpook::generate_context
|
|
15
|
+
# @see ContextSpook::Generator
|
|
16
|
+
# @see ContextSpook::Generator::Context
|
|
17
|
+
def usage
|
|
18
|
+
puts <<~EOT
|
|
19
|
+
|
|
20
|
+
Usage: #{File.basename($0)} [options] <context_definition_file>
|
|
21
|
+
|
|
22
|
+
Options:
|
|
23
|
+
-o FILE Write output to FILE instead of stdout
|
|
24
|
+
-v Verbose output
|
|
25
|
+
-h Show this help message
|
|
26
|
+
|
|
27
|
+
Examples:
|
|
28
|
+
# Generate context and output to stdout
|
|
29
|
+
#{File.basename($0)} .contexts/project.rb
|
|
30
|
+
|
|
31
|
+
# Generate context and save to file
|
|
32
|
+
#{File.basename($0)} .contexts/project.rb -o context.json
|
|
33
|
+
|
|
34
|
+
# Generate context with verbose output
|
|
35
|
+
#{File.basename($0)} .contexts/project.rb -v
|
|
36
|
+
|
|
37
|
+
# Generate context and pipe to another tool
|
|
38
|
+
#{File.basename($0)} .contexts/project.rb | ollama_chat_send
|
|
39
|
+
|
|
40
|
+
EOT
|
|
41
|
+
exit 0
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
opts = go 'o:pvh'
|
|
45
|
+
opts[?h] and usage
|
|
46
|
+
filename = ARGV.shift or fail 'require context definition file as an argument'
|
|
47
|
+
output = nil
|
|
48
|
+
context = ContextSpook.generate_context(filename, verbose: opts[?v])
|
|
49
|
+
if output_filename = opts[?o]
|
|
50
|
+
if File.exist?(output_filename)
|
|
51
|
+
fail "Filename #{output_filename.inspect} already exists!"
|
|
52
|
+
end
|
|
53
|
+
output = File.new output_filename, ?w
|
|
54
|
+
else
|
|
55
|
+
output = STDOUT
|
|
56
|
+
end
|
|
57
|
+
JSON.dump(context.as_json, output)
|
data/context_spook.gemspec
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
|
2
|
-
# stub: context_spook 0.
|
|
2
|
+
# stub: context_spook 0.5.0 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.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]
|
|
@@ -18,13 +18,13 @@ Gem::Specification.new do |s|
|
|
|
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]
|
|
20
20
|
s.required_ruby_version = Gem::Requirement.new("~> 3.1".freeze)
|
|
21
|
-
s.rubygems_version = "3.
|
|
21
|
+
s.rubygems_version = "3.7.2".freeze
|
|
22
22
|
s.summary = "context_spook collects project context for AI".freeze
|
|
23
23
|
s.test_files = ["spec/context_spook/generator_spec.rb".freeze, "spec/spec_helper.rb".freeze]
|
|
24
24
|
|
|
25
25
|
s.specification_version = 4
|
|
26
26
|
|
|
27
|
-
s.add_development_dependency(%q<gem_hadar>.freeze, ["~> 2.
|
|
27
|
+
s.add_development_dependency(%q<gem_hadar>.freeze, ["~> 2.8".freeze])
|
|
28
28
|
s.add_development_dependency(%q<all_images>.freeze, ["~> 0.6".freeze])
|
|
29
29
|
s.add_development_dependency(%q<rspec>.freeze, ["~> 3.2".freeze])
|
|
30
30
|
s.add_development_dependency(%q<debug>.freeze, [">= 0".freeze])
|
|
@@ -9,24 +9,35 @@ require 'mime-types'
|
|
|
9
9
|
module ContextSpook
|
|
10
10
|
include DSLKit::Interpreter
|
|
11
11
|
|
|
12
|
-
# The generate_context method processes a context definition file
|
|
13
|
-
# the resulting context object.
|
|
12
|
+
# The generate_context method processes a context definition file or block
|
|
13
|
+
# and returns the resulting context object.
|
|
14
14
|
#
|
|
15
|
-
# This method
|
|
16
|
-
#
|
|
17
|
-
#
|
|
15
|
+
# This method serves as the primary entry point for generating project
|
|
16
|
+
# context data. It accepts either a filename pointing to a context definition
|
|
17
|
+
# file or a block containing the context definition, but not both.
|
|
18
|
+
# When a filename is provided, it reads and parses the file content. When a
|
|
19
|
+
# block is provided, it evaluates the block within the generator's context.
|
|
20
|
+
# The method ensures that only one context definition mechanism is used.
|
|
18
21
|
#
|
|
19
|
-
# @param filename [ String ] the path to the context definition file to
|
|
22
|
+
# @param filename [ String, nil ] the path to the context definition file to
|
|
23
|
+
# be processed
|
|
24
|
+
# @param verbose [ TrueClass, FalseClass ] flag to enable verbose output
|
|
25
|
+
# during processing, defaults to false.
|
|
26
|
+
# @param block [ Proc ] a block containing the context definition to be
|
|
27
|
+
# evaluated
|
|
20
28
|
#
|
|
21
29
|
# @return [ ContextSpook::Generator::Context ] the context object generated
|
|
22
|
-
#
|
|
23
|
-
|
|
30
|
+
# from the file contents or block
|
|
31
|
+
#
|
|
32
|
+
# @raise [ ArgumentError ] if neither a filename nor a block is provided
|
|
33
|
+
# @raise [ ArgumentError ] if both a filename and a block are provided
|
|
34
|
+
def self.generate_context(filename = nil, verbose: false, &block)
|
|
24
35
|
filename.present? ^ block or
|
|
25
36
|
raise ArgumentError, 'need either a filename or a &block argument'
|
|
26
37
|
generator = if filename
|
|
27
|
-
Generator.send(:new).send(:parse, File.read(filename))
|
|
38
|
+
Generator.send(:new, verbose:).send(:parse, File.read(filename))
|
|
28
39
|
else
|
|
29
|
-
Generator.send(:new, &block)
|
|
40
|
+
Generator.send(:new, verbose:, &block)
|
|
30
41
|
end
|
|
31
42
|
generator.output_context_size
|
|
32
43
|
generator.context
|
|
@@ -39,11 +50,15 @@ module ContextSpook
|
|
|
39
50
|
class Generator
|
|
40
51
|
private_class_method :new
|
|
41
52
|
|
|
42
|
-
# The initialize method sets up the object by evaluating the provided block
|
|
53
|
+
# The initialize method sets up the object by evaluating the provided block
|
|
54
|
+
# in the object's context.
|
|
43
55
|
#
|
|
44
|
-
# @param
|
|
56
|
+
# @param verbose [ TrueClass, FalseClass ] flag to enable verbose
|
|
57
|
+
# output during processing, defaults to lfalse.
|
|
58
|
+
# @param block [ Proc ] a block of code to be evaluated within the object's context
|
|
45
59
|
# If no block is given, the method does nothing.
|
|
46
|
-
def initialize(&block)
|
|
60
|
+
def initialize(verbose: false, &block)
|
|
61
|
+
@verbose = verbose
|
|
47
62
|
block and instance_eval(&block)
|
|
48
63
|
end
|
|
49
64
|
|
|
@@ -72,7 +87,9 @@ module ContextSpook
|
|
|
72
87
|
json_content_size = Tins::Unit.format(
|
|
73
88
|
context_size, format: '%.2f %U', unit: ?b, prefix: 1024
|
|
74
89
|
)
|
|
75
|
-
|
|
90
|
+
if @verbose
|
|
91
|
+
STDERR.puts "Built #{json_content_size} of JSON context in total."
|
|
92
|
+
end
|
|
76
93
|
end
|
|
77
94
|
|
|
78
95
|
# The Context class represents and manages project context data, providing
|
|
@@ -156,10 +173,14 @@ module ContextSpook
|
|
|
156
173
|
file_size = Tins::Unit.format(
|
|
157
174
|
File.size(filename), format: '%.2f %U', unit: ?b, prefix: 1024
|
|
158
175
|
)
|
|
159
|
-
|
|
176
|
+
if @verbose
|
|
177
|
+
STDERR.puts "Read #{filename.inspect} as JSON (%s) for context." % file_size
|
|
178
|
+
end
|
|
160
179
|
JSON.load_file(filename)
|
|
161
180
|
rescue Errno::ENOENT => e
|
|
162
|
-
|
|
181
|
+
if @verbose
|
|
182
|
+
STDERR.puts color(208) { "Reading #{filename.inspect} as JSON caused #{e.class}: #{e}" }
|
|
183
|
+
end
|
|
163
184
|
nil
|
|
164
185
|
end
|
|
165
186
|
|
|
@@ -193,10 +214,14 @@ module ContextSpook
|
|
|
193
214
|
file_size = Tins::Unit.format(
|
|
194
215
|
content.size, format: '%.2f %U', unit: ?b, prefix: 1024
|
|
195
216
|
)
|
|
196
|
-
|
|
217
|
+
if @verbose
|
|
218
|
+
STDERR.puts "Read #{filename.inspect} (%s) for context." % file_size
|
|
219
|
+
end
|
|
197
220
|
nil
|
|
198
221
|
rescue Errno::ENOENT => e
|
|
199
|
-
|
|
222
|
+
if @verbose
|
|
223
|
+
STDERR.puts color(208) { "Reading #{filename.inspect} caused #{e.class}: #{e}" }
|
|
224
|
+
end
|
|
200
225
|
end
|
|
201
226
|
|
|
202
227
|
# The commands method sets up a DSL accessor for provided command outputs.
|
|
@@ -219,7 +244,11 @@ module ContextSpook
|
|
|
219
244
|
output = `#{shell_command}`
|
|
220
245
|
exit_code = $?&.exitstatus.to_i
|
|
221
246
|
if exit_code != 0
|
|
222
|
-
|
|
247
|
+
if @verbose
|
|
248
|
+
STDERR.puts color(208) {
|
|
249
|
+
"Executing #{shell_command.inspect} resulted in exit code #{exit_code}."
|
|
250
|
+
}
|
|
251
|
+
end
|
|
223
252
|
end
|
|
224
253
|
commands[shell_command] = {
|
|
225
254
|
namespace: scope_top,
|
|
@@ -231,7 +260,9 @@ module ContextSpook
|
|
|
231
260
|
output_size = Tins::Unit.format(
|
|
232
261
|
output.size, format: '%.2f %U', unit: ?b, prefix: 1024
|
|
233
262
|
)
|
|
234
|
-
|
|
263
|
+
if @verbose
|
|
264
|
+
STDERR.puts "Executed #{shell_command.inspect} with output (%s) for context." % output_size
|
|
265
|
+
end
|
|
235
266
|
nil
|
|
236
267
|
end
|
|
237
268
|
|
|
@@ -64,7 +64,7 @@ describe ContextSpook::Generator do
|
|
|
64
64
|
command = context.commands['tree']
|
|
65
65
|
expect(command).to be_present
|
|
66
66
|
expect(command[:working_directory]).to eq Dir.pwd
|
|
67
|
-
expect(command[:exit_code]).
|
|
67
|
+
expect(command[:exit_code]).not_to be_nil
|
|
68
68
|
if command[:exit_code] == 0
|
|
69
69
|
expect(command[:output]).to be_present
|
|
70
70
|
else
|
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.5.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Florian Frank
|
|
@@ -15,14 +15,14 @@ dependencies:
|
|
|
15
15
|
requirements:
|
|
16
16
|
- - "~>"
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: '2.
|
|
18
|
+
version: '2.8'
|
|
19
19
|
type: :development
|
|
20
20
|
prerelease: false
|
|
21
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
22
|
requirements:
|
|
23
23
|
- - "~>"
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
|
-
version: '2.
|
|
25
|
+
version: '2.8'
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
27
|
name: all_images
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -197,7 +197,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
197
197
|
- !ruby/object:Gem::Version
|
|
198
198
|
version: '0'
|
|
199
199
|
requirements: []
|
|
200
|
-
rubygems_version: 3.
|
|
200
|
+
rubygems_version: 3.7.2
|
|
201
201
|
specification_version: 4
|
|
202
202
|
summary: context_spook collects project context for AI
|
|
203
203
|
test_files:
|