klue-langcraft 0.1.1 → 0.3.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.
Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +30 -3
  3. data/CHANGELOG.md +21 -0
  4. data/bin/dsl_watcher.rb +10 -0
  5. data/bin/langcraft.rb +177 -0
  6. data/docs/dsl-class-diagram.md +97 -0
  7. data/docs/dsl-examples.md +9 -0
  8. data/docs/dsl-upgrade-plan.md +266 -0
  9. data/lib/base_process.rb +41 -0
  10. data/lib/dsl_folder_watcher.rb +50 -0
  11. data/lib/dsl_interpreter.rb +112 -0
  12. data/lib/dsl_process_data.rb +31 -0
  13. data/lib/klue/langcraft/dsl/interpreter.rb +114 -0
  14. data/lib/klue/langcraft/dsl/klue_runner.rb +68 -0
  15. data/lib/klue/langcraft/dsl/process_data_pipeline.rb +65 -0
  16. data/lib/klue/langcraft/dsl/process_matcher.rb +59 -0
  17. data/lib/klue/langcraft/dsl/processor_config.rb +35 -0
  18. data/lib/klue/langcraft/dsl/processors/file_collector_processor.rb +30 -0
  19. data/lib/klue/langcraft/dsl/processors/full_name_processor.rb +34 -0
  20. data/lib/klue/langcraft/dsl/processors/processor.rb +43 -0
  21. data/lib/klue/langcraft/dsl/watcher.rb +88 -0
  22. data/lib/klue/langcraft/dsl/webhook.rb +57 -0
  23. data/lib/klue/langcraft/version.rb +1 -1
  24. data/lib/klue/langcraft.rb +29 -2
  25. data/lib/process_file_collector.rb +92 -0
  26. data/package-lock.json +2 -2
  27. data/package.json +1 -1
  28. metadata +39 -7
  29. data/docs/dsl-samples/index.md +0 -4
  30. /data/lib/klue/langcraft/{-brief.md → tokenizer-old-needs-revisit/-brief.md} +0 -0
  31. /data/lib/klue/langcraft/{parser.rb → tokenizer-old-needs-revisit/parser.rb} +0 -0
  32. /data/lib/klue/langcraft/{sample_usage.rb → tokenizer-old-needs-revisit/sample_usage.rb} +0 -0
  33. /data/lib/klue/langcraft/{tokenizer.rb → tokenizer-old-needs-revisit/tokenizer.rb} +0 -0
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'listen'
4
+
5
+ module Klue
6
+ module Langcraft
7
+ module DSL
8
+ # Watcher class for monitoring file changes in specified directories.
9
+ # This class sets up a file system listener to watch for changes to files
10
+ # with specified extensions, and processes those files using a KlueRunner.
11
+ class Watcher
12
+ def initialize(directories, **options)
13
+ @directories = directories.map { |dir| File.expand_path(dir) }
14
+ @options = options
15
+ @klue_runner = Klue::Langcraft::DSL::KlueRunner.new
16
+ @extensions = options[:extensions] || ['.klue']
17
+ end
18
+
19
+ def start
20
+ listener = create_listener
21
+ log_watcher_info
22
+ listener.start
23
+ sleep
24
+ end
25
+
26
+ private
27
+
28
+ def create_listener
29
+ extension_regex = create_extension_regex
30
+ Listen.to(*@directories, only: extension_regex) do |modified, added, _removed|
31
+ process_changed_files(modified + added)
32
+ end
33
+ end
34
+
35
+ def create_extension_regex
36
+ Regexp.union(@extensions.map { |ext| /#{Regexp.escape(ext)}$/ })
37
+ end
38
+
39
+ def process_changed_files(files)
40
+ files.each { |file| process_file(file) }
41
+ end
42
+
43
+ def process_file(file)
44
+ log_info('Processing file', file)
45
+ options = create_file_options(file)
46
+ run_klue_runner(options)
47
+ rescue StandardError => e
48
+ log_error('Error processing file', "#{file}: #{e.message}")
49
+ end
50
+
51
+ def create_file_options(file)
52
+ options = @options.dup
53
+ options[:input_file] = file
54
+ options[:basic_output_file] = file.sub(/#{File.extname(file)}$/, '.json') if @options[:create_basic_json]
55
+ options[:enhanced_output_file] = file.sub(/#{File.extname(file)}$/, '.enhanced.json') if @options[:create_enhanced_json]
56
+ options
57
+ end
58
+
59
+ def run_klue_runner(options)
60
+ @klue_runner.run(
61
+ input_file: options[:input_file],
62
+ basic_output_file: options[:basic_output_file],
63
+ enhanced_output_file: options[:enhanced_output_file],
64
+ webhook_url: options[:webhook_url],
65
+ log_level: options[:log_level]
66
+ )
67
+ end
68
+
69
+ def log_watcher_info
70
+ log_info('Watching directories', @directories.join(', '))
71
+ log_info('Watching file extensions', @extensions.join(', '))
72
+ log_info('Create basic JSON', @options[:create_basic_json])
73
+ log_info('Create enhanced JSON', @options[:create_enhanced_json])
74
+ log_info('Webhook URL', @options[:webhook_url])
75
+ log_info('Log level', @options[:log_level])
76
+ end
77
+
78
+ def log_info(label, value)
79
+ puts "#{label.ljust(30)}: #{value}" if %i[info detailed].include?(@options[:log_level])
80
+ end
81
+
82
+ def log_error(label, value)
83
+ puts "#{label.ljust(30)}: #{value}"
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'net/http'
4
+ require 'json'
5
+ require 'uri'
6
+
7
+ module Klue
8
+ module Langcraft
9
+ module DSL
10
+ # Webhook class for handling HTTP POST requests to specified URLs.
11
+ # This class is responsible for sending processed data to external services
12
+ # via webhooks, handling the delivery process, and logging the results.
13
+ class Webhook
14
+ def deliver(webhook_url, data)
15
+ klue_type = extract_klue_type(data)
16
+ uri = build_uri(webhook_url, klue_type)
17
+ response = send_request(uri, build_payload(klue_type, data))
18
+ log_response(response, uri)
19
+ response
20
+ end
21
+
22
+ private
23
+
24
+ def extract_klue_type(data)
25
+ data.keys.first.to_s
26
+ end
27
+
28
+ def build_uri(webhook_url, klue_type)
29
+ URI.parse("#{webhook_url}?klue-type=#{klue_type}")
30
+ end
31
+
32
+ def build_payload(klue_type, data)
33
+ { klue_type: klue_type, data: data }
34
+ end
35
+
36
+ def send_request(uri, payload)
37
+ http = Net::HTTP.new(uri.host, uri.port)
38
+ request = Net::HTTP::Post.new(uri.path, { 'Content-Type' => 'application/json' })
39
+ request.body = payload.to_json
40
+ http.request(request)
41
+ end
42
+
43
+ def log_response(response, uri)
44
+ puts "Response: #{response.code} - #{response.message}"
45
+ puts "Endpoint: #{uri}"
46
+ log_response_body(response)
47
+ end
48
+
49
+ def log_response_body(response)
50
+ body = JSON.parse(response.body)
51
+ puts "DSL Type: #{body['type']}"
52
+ # puts JSON.pretty_generate(body['data'])
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Klue
4
4
  module Langcraft
5
- VERSION = '0.1.1'
5
+ VERSION = '0.3.0'
6
6
  end
7
7
  end
@@ -1,6 +1,33 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'json'
4
+ require 'net/http'
5
+ require 'uri'
6
+ require 'listen'
7
+ require 'pry'
8
+
9
+ require 'appydave/tools'
10
+
3
11
  require 'klue/langcraft/version'
12
+ require 'klue/langcraft/dsl/processor_config'
13
+
14
+ ProcessorConfigDefault = Klue::Langcraft::DSL::ProcessorConfig.new
15
+
16
+ require 'klue/langcraft/dsl/processors/processor'
17
+ require 'klue/langcraft/dsl/processors/file_collector_processor'
18
+ require 'klue/langcraft/dsl/processors/full_name_processor'
19
+ require 'klue/langcraft/dsl/interpreter'
20
+ require 'klue/langcraft/dsl/process_matcher'
21
+ require 'klue/langcraft/dsl/process_data_pipeline'
22
+ require 'klue/langcraft/dsl/webhook'
23
+ require 'klue/langcraft/dsl/watcher'
24
+ require 'klue/langcraft/dsl/klue_runner'
25
+
26
+ require 'base_process'
27
+ require 'process_file_collector'
28
+ require 'dsl_interpreter'
29
+ require 'dsl_folder_watcher'
30
+ require 'dsl_process_data'
4
31
 
5
32
  module Klue
6
33
  module Langcraft
@@ -12,8 +39,8 @@ module Klue
12
39
  end
13
40
 
14
41
  if ENV.fetch('KLUE_DEBUG', 'false').downcase == 'true'
15
- namespace = 'KlueLangcraft::Version'
42
+ namespace = 'Klue::Langcraft::Version'
16
43
  file_path = $LOADED_FEATURES.find { |f| f.include?('klue-langcraft/version') }
17
- version = KlueLangcraft::VERSION.ljust(9)
44
+ version = Klue::Langcraft::VERSION.ljust(9)
18
45
  puts "#{namespace.ljust(35)} : #{version.ljust(9)} : #{file_path}"
19
46
  end
@@ -0,0 +1,92 @@
1
+ # frozen_string_literal: true
2
+
3
+ # file: lib/process_file_collector.rb
4
+
5
+ class ProcessFileCollector < BaseProcess
6
+ def initialize(key)
7
+ super
8
+ @found = nil
9
+ # @matcher = ->(key, value) { key.to_s == 'file_collector' && value.is_a?(Hash) }
10
+ @matcher = lambda do |key, value|
11
+ if key.to_s == 'file_collector'
12
+ if value.is_a?(Array)
13
+ value.any? { |v| v.is_a?(Hash) }
14
+ else
15
+ value.is_a?(Hash)
16
+ end
17
+ else
18
+ false
19
+ end
20
+ end
21
+ end
22
+
23
+ def match?(input)
24
+ @found = deep_match(input, @matcher)
25
+ !@found.empty?
26
+ end
27
+
28
+ def execute(_input)
29
+ # Iterate over each `file_collector` found and process individually
30
+ results = {}
31
+
32
+ @found.each do |data|
33
+ next unless data.is_a?(Hash)
34
+
35
+ # Extract the `as` key if present
36
+ as_key = data['as']
37
+
38
+ working_directory = File.expand_path(data['root'])
39
+
40
+ options = Appydave::Tools::GptContext::Options.new(
41
+ working_directory: working_directory,
42
+ include_patterns: extract_patterns(data.dig('files', 'include')),
43
+ exclude_patterns: extract_patterns(data.dig('files', 'exclude')),
44
+ format: 'json',
45
+ line_limit: data['line_length']
46
+ )
47
+
48
+ collector = Appydave::Tools::GptContext::FileCollector.new(options)
49
+ json = collector.build
50
+
51
+ # Structuring the result under `process-data` with `as` as key
52
+ result_data = {
53
+ type: 'file_collector',
54
+ data: {
55
+ working_directory: working_directory,
56
+ files: JSON.parse(json)
57
+ }
58
+ }
59
+
60
+ # If `as` key exists, use it to store under process-data with that identifier
61
+ if as_key
62
+ results[as_key] = result_data
63
+ else
64
+ # Generate a unique key if no `as` key is defined
65
+ unique_key = "file_collector_#{results.size + 1}"
66
+ results[unique_key] = result_data
67
+ end
68
+ end
69
+
70
+ results
71
+ rescue SyntaxError, NameError, NoMethodError => e
72
+ puts "Ruby evaluation error in ProcessFileCollector: #{e.message}"
73
+ puts "Error occurred at: #{e.backtrace.first}"
74
+ {}
75
+ rescue StandardError => e
76
+ puts "Unexpected error in ProcessFileCollector: #{e.message}"
77
+ puts e.backtrace.join("\n")
78
+ {}
79
+ end
80
+
81
+ private
82
+
83
+ def extract_patterns(files_data)
84
+ if files_data.is_a?(Hash)
85
+ [files_data['param1']]
86
+ elsif files_data.is_a?(Array)
87
+ files_data.map { |entry| entry['param1'] }
88
+ else
89
+ []
90
+ end
91
+ end
92
+ end
data/package-lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "klue-langcraft",
3
- "version": "0.1.1",
3
+ "version": "0.3.0",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "klue-langcraft",
9
- "version": "0.1.1",
9
+ "version": "0.3.0",
10
10
  "devDependencies": {
11
11
  "@klueless-js/semantic-release-rubygem": "github:klueless-js/semantic-release-rubygem",
12
12
  "@semantic-release/changelog": "^6.0.3",
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "klue-langcraft",
3
- "version": "0.1.1",
3
+ "version": "0.3.0",
4
4
  "description": "Domain Specific Language Crafting",
5
5
  "scripts": {
6
6
  "release": "semantic-release"
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: klue-langcraft
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Cruwys
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-09-22 00:00:00.000000000 Z
11
+ date: 2024-10-26 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: appydave-tools
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: k_log
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -47,27 +61,45 @@ files:
47
61
  - README.md
48
62
  - Rakefile
49
63
  - bin/console
64
+ - bin/dsl_watcher.rb
65
+ - bin/langcraft.rb
50
66
  - bin/setup
67
+ - docs/dsl-class-diagram.md
51
68
  - docs/dsl-examples.md
52
69
  - docs/dsl-rules.md
53
- - docs/dsl-samples/index.md
54
70
  - docs/dsl-samples/youtube-launch-optimizer-old.klue
55
71
  - docs/dsl-samples/youtube-launch-optimizer-strawberry.json
56
72
  - docs/dsl-samples/youtube-launch-optimizer-strawberry.klue
57
73
  - docs/dsl-samples/youtube-launch-optimizer.defn.klue
58
74
  - docs/dsl-samples/youtube-launch-optimizer.json
59
75
  - docs/dsl-samples/youtube-launch-optimizer.klue
76
+ - docs/dsl-upgrade-plan.md
60
77
  - docs/project-plan/project-plan.md
61
78
  - docs/project-plan/project.drawio
62
79
  - docs/project-plan/project_done.svg
63
80
  - docs/project-plan/project_in_progress.svg
64
81
  - docs/project-plan/project_todo.svg
82
+ - lib/base_process.rb
83
+ - lib/dsl_folder_watcher.rb
84
+ - lib/dsl_interpreter.rb
85
+ - lib/dsl_process_data.rb
65
86
  - lib/klue/langcraft.rb
66
- - lib/klue/langcraft/-brief.md
67
- - lib/klue/langcraft/parser.rb
68
- - lib/klue/langcraft/sample_usage.rb
69
- - lib/klue/langcraft/tokenizer.rb
87
+ - lib/klue/langcraft/dsl/interpreter.rb
88
+ - lib/klue/langcraft/dsl/klue_runner.rb
89
+ - lib/klue/langcraft/dsl/process_data_pipeline.rb
90
+ - lib/klue/langcraft/dsl/process_matcher.rb
91
+ - lib/klue/langcraft/dsl/processor_config.rb
92
+ - lib/klue/langcraft/dsl/processors/file_collector_processor.rb
93
+ - lib/klue/langcraft/dsl/processors/full_name_processor.rb
94
+ - lib/klue/langcraft/dsl/processors/processor.rb
95
+ - lib/klue/langcraft/dsl/watcher.rb
96
+ - lib/klue/langcraft/dsl/webhook.rb
97
+ - lib/klue/langcraft/tokenizer-old-needs-revisit/-brief.md
98
+ - lib/klue/langcraft/tokenizer-old-needs-revisit/parser.rb
99
+ - lib/klue/langcraft/tokenizer-old-needs-revisit/sample_usage.rb
100
+ - lib/klue/langcraft/tokenizer-old-needs-revisit/tokenizer.rb
70
101
  - lib/klue/langcraft/version.rb
102
+ - lib/process_file_collector.rb
71
103
  - package-lock.json
72
104
  - package.json
73
105
  - sig/klue/langcraft.rbs
@@ -1,4 +0,0 @@
1
- Printspeak DSL
2
- Project Plan
3
- Agent As Code
4
- Make Chapters out of my recordings using a folder and glob pattern geared to my naming convention