context_spook 1.5.0 → 1.6.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: 5cca218e18443bf3698be556f93b822253a9f0dd4c93322d1ee9c826d1a26dc3
4
- data.tar.gz: d8c48e20203cbc5c1c0741e93805480aa7fbe9987821fe2b9839447902879149
3
+ metadata.gz: 6b21e74b5db171841cc7af7c0e5204f252cb7474de2f45512c3597f61774ffcb
4
+ data.tar.gz: 3068b2faa4a58ef85722f9e756b712d89e45127eff52d7ca9695535611e04670
5
5
  SHA512:
6
- metadata.gz: a7f1fb4f2b26f9c59dc6a48be8db0a2ffc4381250334a401c6ad2944fe398cb18bcc0154df6111d26ceac1a9bcad7ac4386626aeb681bbe20f1286310fbe58f0
7
- data.tar.gz: 990b7df25449551007c8e986ec479bdf5656195e47ef6d7243603849179a5fac6edaa6e245bbfaa99768115b3b46eeffc5baf6f37e542c8a4b729dc443ba8b13
6
+ metadata.gz: 41f8ac31162e123cf27b6ad109bcd7cc58c6b1e687ac1e4f3af57e6e446c1ebc07ab4a4290af659e7f5e8cd3026f2342a53c109550628bb4f2cf536ec1aea646
7
+ data.tar.gz: dde406feb3c651bd99ea4a0aa4c10342690459604fb27c7e1d2d3df0302326dbabb83ef78350f860b23773bbd5d56ef31fcb66841b595be937006ae29160dbd8
data/Rakefile CHANGED
@@ -31,14 +31,14 @@ GemHadar do
31
31
 
32
32
  required_ruby_version '>= 3.1'
33
33
 
34
- dependency 'tins', '~>1.46'
35
- dependency 'json', '~>2.0'
36
- dependency 'term-ansicolor', '~> 1.11'
37
- dependency 'mize', '~> 0.6'
38
- dependency 'mime-types', '~> 3.0'
39
- dependency 'yaml', '~> 0.4'
40
- dependency 'pathname', '~> 0.4'
41
- dependency 'toon-ruby', '>= 0.1'
34
+ dependency 'tins', '~> 1.46'
35
+ dependency 'json', '~> 2.0'
36
+ dependency 'term-ansicolor', '~> 1.11'
37
+ dependency 'mize', '~> 0.6'
38
+ dependency 'mime-types', '~> 3.0'
39
+ dependency 'yaml', '~> 0.4'
40
+ dependency 'pathname', '~> 0.4'
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.5.0 ruby lib
2
+ # stub: context_spook 1.6.0 ruby lib
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "context_spook".freeze
6
- s.version = "1.5.0".freeze
6
+ s.version = "1.6.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 = "4.0.3".freeze
21
+ s.rubygems_version = "4.0.10".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/context_spook/toon_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.17.0".freeze])
27
+ s.add_development_dependency(%q<gem_hadar>.freeze, [">= 2.17.1".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])
@@ -72,6 +72,13 @@ module ContextSpook
72
72
 
73
73
  private_class_method :new
74
74
 
75
+ # The token_estimator attribute allows setting the logic used to estimate
76
+ # the number of tokens in a serialized context.
77
+ #
78
+ # It expects an object that responds to #call(text), where text is the
79
+ # serialized context string.
80
+ attr_writer :token_estimator
81
+
75
82
  # The initialize method sets up the object by evaluating the provided block
76
83
  # in the object's context.
77
84
  #
@@ -85,6 +92,7 @@ module ContextSpook
85
92
  %w[ TOON JSON ].include?(@format) or
86
93
  raise ArgumentError,
87
94
  "format needs to be either JSON or TOON, was #{@format.inspect}"
95
+ self.token_estimator = ContextSpook::Utils.method(:estimate_tokens)
88
96
  block and instance_eval(&block)
89
97
  end
90
98
 
@@ -272,7 +280,9 @@ module ContextSpook
272
280
  # The commands method sets up a DSL accessor for provided command outputs.
273
281
  #
274
282
  # @param value [ Hash ] the hash of commands to be set
275
- dsl_accessor :commands, {}
283
+ dsl_accessor :commands do
284
+ {}
285
+ end
276
286
 
277
287
  # The command method executes a shell command and stores its result.
278
288
  #
@@ -5,16 +5,21 @@
5
5
  # functionality for generated context objects.
6
6
  module ContextSpook::OutputContext
7
7
  # The output_context_size method prints the total size of the generated
8
- # context JSON representation.
8
+ # context representation and an estimated token count.
9
9
  #
10
10
  # This method calculates the size of the context object when serialized to
11
- # JSON, formats it using binary units (KiB, MiB, etc.), and outputs the
12
- # result to standard error.
11
+ # JSON (or TOON), formats it using binary units, estimates the token count
12
+ # based on bytes, and outputs the result to standard error.
13
13
  def output_context_size
14
- context_size =
15
- (@format == 'TOON' ? @context&.toon_size : @context&.size).to_i
16
- context_size = ContextSpook::Utils.format_size(context_size)
17
- verbose_puts "Built #{context_size} of #@format context in total."
14
+ context = ''
15
+ if @context
16
+ context = @format == 'TOON' ? @context.to_toon : @context.to_json
17
+ end
18
+ formatted_size = ContextSpook::Utils.format_size(context.size)
19
+ tokens = @token_estimator.call(context)
20
+ formatted_tokens = ContextSpook::Utils.format_tokens(tokens)
21
+
22
+ verbose_puts "Built #{formatted_size} (#{formatted_tokens} tokens) of #@format context in total."
18
23
  end
19
24
 
20
25
  # The output_context method writes the generated context to the specified
@@ -16,4 +16,26 @@ module ContextSpook::Utils
16
16
  def format_size(context_size)
17
17
  Tins::Unit.format(context_size, format: '%.2f %U', unit: ?b, prefix: 1024)
18
18
  end
19
+
20
+ # The format_tokens method converts a token count into a human-readable
21
+ # string using SI prefixes (e.g., 1.2 kT).
22
+ #
23
+ # @param tokens [ Integer ] the number of tokens to be formatted
24
+ #
25
+ # @return [ String ] the formatted token string
26
+ def format_tokens(tokens)
27
+ Tins::Unit.format(tokens, unit: ?T, prefix: :si_uc, format: '%.1f %U')
28
+ end
29
+
30
+ # The estimate_tokens method provides a crude estimation of token counts
31
+ # based on the byte size of the input content.
32
+ #
33
+ # This follows a heuristic where one token is roughly equivalent to 3.5 bytes.
34
+ #
35
+ # @param text [ String ] the content to be estimated
36
+ #
37
+ # @return [ Integer ] the estimated number of tokens
38
+ def estimate_tokens(text)
39
+ (text.size.to_f / 3.5).ceil
40
+ end
19
41
  end
@@ -1,6 +1,6 @@
1
1
  module ContextSpook
2
2
  # ContextSpook version
3
- VERSION = '1.5.0'
3
+ VERSION = '1.6.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:
@@ -9,7 +9,10 @@ describe ContextSpook::Generator do
9
9
  it 'context can be generated from block' do
10
10
  expect_any_instance_of(described_class).to\
11
11
  receive(:output_context_size).and_call_original
12
+ expect_any_instance_of(described_class).to receive(:verbose_puts).
13
+ with(/Built.*?31.0 T tokens.*?of JSON context in total/)
12
14
  my_context = ContextSpook.generate_context do
15
+ self.token_estimator = -> text { (text.size.to_f / Math::PI).ceil }
13
16
  context do
14
17
  variable foo: 'bar'
15
18
  metadata version: '1.0'
@@ -89,7 +92,7 @@ describe ContextSpook::Generator do
89
92
  expect_any_instance_of(described_class).to receive(:output_context_size).
90
93
  and_call_original
91
94
  expect_any_instance_of(described_class).to receive(:verbose_puts).
92
- with(/Built.*of JSON context in total/)
95
+ with(/Built.*?Kb.*?KT.*?of JSON context in total/)
93
96
  allow_any_instance_of(described_class::Context).to receive(:verbose_puts)
94
97
  my_context
95
98
  end
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe ContextSpook::TOON do
4
- let(:context) do
4
+ let(:my_context) do
5
5
  ContextSpook.generate_context do
6
6
  context do
7
7
  variable foo: 'bar'
@@ -13,13 +13,13 @@ describe ContextSpook::TOON do
13
13
 
14
14
  describe '#to_toon' do
15
15
  it 'converts context to TOON format' do
16
- toon_output = context.to_toon
16
+ toon_output = my_context.to_toon
17
17
  expect(toon_output).to be_a(String)
18
18
  expect(toon_output).to_not be_empty
19
19
  end
20
20
 
21
21
  it 'produces valid TOON output' do
22
- toon_output = context.to_toon
22
+ toon_output = my_context.to_toon
23
23
  expect(toon_output).to match(
24
24
  %r{
25
25
  \Afiles:\n
@@ -41,26 +41,26 @@ describe ContextSpook::TOON do
41
41
 
42
42
  describe '#toon_size' do
43
43
  it 'returns the size of TOON representation in bytes' do
44
- size = context.toon_size
44
+ size = my_context.toon_size
45
45
  expect(size).to be_a(Integer)
46
46
  expect(size).to be > 0
47
47
  end
48
48
 
49
49
  it 'matches the size of the TOON output' do
50
- size = context.toon_size
51
- toon_output = context.to_toon
50
+ size = my_context.toon_size
51
+ toon_output = my_context.to_toon
52
52
  expect(size).to eq(toon_output.size)
53
53
  end
54
54
  end
55
55
 
56
56
  describe 'integration with ContextSpook::Generator::Context' do
57
57
  it 'is included in Context class' do
58
- expect(context).to respond_to(:to_toon)
59
- expect(context).to respond_to(:toon_size)
58
+ expect(my_context).to respond_to(:to_toon)
59
+ expect(my_context).to respond_to(:toon_size)
60
60
  end
61
61
 
62
62
  it 'works with context data' do
63
- toon_output = context.to_toon
63
+ toon_output = my_context.to_toon
64
64
  expect(toon_output).to include('variables:')
65
65
  expect(toon_output).to include('metadata:')
66
66
  expect(toon_output).to include('files:')
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.5.0
4
+ version: 1.6.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.17.0
18
+ version: 2.17.1
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.17.0
25
+ version: 2.17.1
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: all_images
28
28
  requirement: !ruby/object:Gem::Requirement
@@ -250,7 +250,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
250
250
  - !ruby/object:Gem::Version
251
251
  version: '0'
252
252
  requirements: []
253
- rubygems_version: 4.0.3
253
+ rubygems_version: 4.0.10
254
254
  specification_version: 4
255
255
  summary: context_spook collects project context for AI
256
256
  test_files: