shared_tools 0.3.1 → 0.4.2

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 (76) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +53 -14
  3. data/README.md +259 -262
  4. data/lib/shared_tools/browser_tool.rb +5 -0
  5. data/lib/shared_tools/calculator_tool.rb +4 -0
  6. data/lib/shared_tools/clipboard_tool.rb +4 -0
  7. data/lib/shared_tools/composite_analysis_tool.rb +4 -0
  8. data/lib/shared_tools/computer_tool.rb +5 -0
  9. data/lib/shared_tools/cron_tool.rb +4 -0
  10. data/lib/shared_tools/current_date_time_tool.rb +4 -0
  11. data/lib/shared_tools/data_science_kit.rb +4 -0
  12. data/lib/shared_tools/database.rb +4 -0
  13. data/lib/shared_tools/database_query_tool.rb +4 -0
  14. data/lib/shared_tools/database_tool.rb +5 -0
  15. data/lib/shared_tools/disk_tool.rb +5 -0
  16. data/lib/shared_tools/dns_tool.rb +4 -0
  17. data/lib/shared_tools/doc_tool.rb +5 -0
  18. data/lib/shared_tools/error_handling_tool.rb +4 -0
  19. data/lib/shared_tools/eval_tool.rb +5 -0
  20. data/lib/shared_tools/mcp/brave_search_client.rb +37 -0
  21. data/lib/shared_tools/mcp/chart_client.rb +32 -0
  22. data/lib/shared_tools/mcp/github_client.rb +38 -0
  23. data/lib/shared_tools/mcp/hugging_face_client.rb +43 -0
  24. data/lib/shared_tools/mcp/memory_client.rb +33 -0
  25. data/lib/shared_tools/mcp/notion_client.rb +40 -0
  26. data/lib/shared_tools/mcp/playwright_client.rb +34 -0
  27. data/lib/shared_tools/mcp/sequential_thinking_client.rb +33 -0
  28. data/lib/shared_tools/mcp/slack_client.rb +54 -0
  29. data/lib/shared_tools/mcp/streamable_http_patch.rb +42 -0
  30. data/lib/shared_tools/mcp/tavily_client.rb +41 -0
  31. data/lib/shared_tools/mcp.rb +45 -16
  32. data/lib/shared_tools/system_info_tool.rb +4 -0
  33. data/lib/shared_tools/tools/browser/base_tool.rb +8 -12
  34. data/lib/shared_tools/tools/browser/click_tool.rb +4 -2
  35. data/lib/shared_tools/tools/browser/ferrum_driver.rb +119 -0
  36. data/lib/shared_tools/tools/browser/inspect_tool.rb +4 -2
  37. data/lib/shared_tools/tools/browser/page_inspect_tool.rb +4 -2
  38. data/lib/shared_tools/tools/browser/page_screenshot_tool.rb +19 -7
  39. data/lib/shared_tools/tools/browser/selector_inspect_tool.rb +4 -2
  40. data/lib/shared_tools/tools/browser/text_field_area_set_tool.rb +4 -2
  41. data/lib/shared_tools/tools/browser/visit_tool.rb +4 -2
  42. data/lib/shared_tools/tools/browser.rb +31 -2
  43. data/lib/shared_tools/tools/browser_tool.rb +6 -0
  44. data/lib/shared_tools/tools/clipboard_tool.rb +69 -144
  45. data/lib/shared_tools/tools/composite_analysis_tool.rb +60 -4
  46. data/lib/shared_tools/tools/computer/mac_driver.rb +37 -4
  47. data/lib/shared_tools/tools/cron_tool.rb +237 -379
  48. data/lib/shared_tools/tools/current_date_time_tool.rb +54 -120
  49. data/lib/shared_tools/tools/data_science_kit.rb +63 -13
  50. data/lib/shared_tools/tools/dns_tool.rb +335 -269
  51. data/lib/shared_tools/tools/doc/docx_reader_tool.rb +107 -0
  52. data/lib/shared_tools/tools/doc/spreadsheet_reader_tool.rb +171 -0
  53. data/lib/shared_tools/tools/doc/text_reader_tool.rb +57 -0
  54. data/lib/shared_tools/tools/doc.rb +3 -0
  55. data/lib/shared_tools/tools/doc_tool.rb +101 -6
  56. data/lib/shared_tools/tools/docker/compose_run_tool.rb +1 -1
  57. data/lib/shared_tools/tools/enabler.rb +42 -0
  58. data/lib/shared_tools/tools/error_handling_tool.rb +3 -1
  59. data/lib/shared_tools/tools/notification/base_driver.rb +51 -0
  60. data/lib/shared_tools/tools/notification/linux_driver.rb +115 -0
  61. data/lib/shared_tools/tools/notification/mac_driver.rb +66 -0
  62. data/lib/shared_tools/tools/notification/null_driver.rb +29 -0
  63. data/lib/shared_tools/tools/notification.rb +12 -0
  64. data/lib/shared_tools/tools/notification_tool.rb +99 -0
  65. data/lib/shared_tools/tools/system_info_tool.rb +130 -343
  66. data/lib/shared_tools/tools/workflow_manager_tool.rb +32 -0
  67. data/lib/shared_tools/utilities.rb +193 -0
  68. data/lib/shared_tools/version.rb +1 -1
  69. data/lib/shared_tools/weather_tool.rb +4 -0
  70. data/lib/shared_tools/workflow_manager_tool.rb +4 -0
  71. data/lib/shared_tools.rb +28 -38
  72. metadata +75 -9
  73. data/lib/shared_tools/mcp/github_mcp_server.rb +0 -58
  74. data/lib/shared_tools/mcp/imcp.rb +0 -28
  75. data/lib/shared_tools/mcp/tavily_mcp_server.rb +0 -44
  76. data/lib/shared_tools/tools/devops_toolkit.rb +0 -420
@@ -18,12 +18,22 @@ module SharedTools
18
18
  DESCRIPTION
19
19
 
20
20
  params do
21
- string :data_source, description: <<~DESC.strip, required: true
21
+ string :data_source, description: <<~DESC.strip, required: false
22
22
  Primary data source to analyze. Can be either a local file path or a web URL.
23
23
  For files: Use relative or absolute paths to CSV, JSON, XML, or text files.
24
24
  For URLs: Use complete HTTP/HTTPS URLs to accessible data endpoints or web pages.
25
25
  The tool automatically detects the source type and uses appropriate fetching methods.
26
26
  Examples: './data/sales.csv', '/home/user/data.json', 'https://api.example.com/data'
27
+ Either data_source or data must be provided.
28
+ DESC
29
+
30
+ string :data, description: <<~DESC.strip, required: false
31
+ Inline data to analyze, provided directly as a string. Accepts:
32
+ - Pipe-delimited markdown tables (header row with | separators)
33
+ - CSV text (comma-separated rows, first row treated as headers)
34
+ - JSON text (object or array)
35
+ - Plain text (one item per line)
36
+ Either data or data_source must be provided.
27
37
  DESC
28
38
 
29
39
  string :analysis_type, description: <<~DESC.strip, required: false
@@ -48,16 +58,23 @@ module SharedTools
48
58
  @logger = logger || RubyLLM.logger
49
59
  end
50
60
 
51
- def execute(data_source:, analysis_type: "standard", **options)
61
+ def execute(data_source: nil, data: nil, analysis_type: "standard", **options)
62
+ if data_source.nil? && data.nil?
63
+ return { success: false, error: "Either data_source or data must be provided." }
64
+ end
65
+
52
66
  results = {}
53
67
  analysis_start = Time.now
54
68
 
55
69
  begin
56
- @logger.info("CompositeAnalysisTool#execute data_source=#{data_source} analysis_type=#{analysis_type}")
70
+ @logger.info("CompositeAnalysisTool#execute data_source=#{data_source.inspect} analysis_type=#{analysis_type}")
57
71
 
58
72
  # Step 1: Fetch data using appropriate method
59
73
  @logger.debug("Fetching data from source...")
60
- if data_source.start_with?('http://', 'https://')
74
+ if data
75
+ results[:data] = parse_inline_data(data)
76
+ results[:source_type] = 'inline'
77
+ elsif data_source.start_with?('http://', 'https://')
61
78
  results[:data] = fetch_web_data(data_source)
62
79
  results[:source_type] = 'web'
63
80
  else
@@ -116,6 +133,45 @@ module SharedTools
116
133
 
117
134
  private
118
135
 
136
+ # Parse inline data string into a Ruby structure.
137
+ # Handles pipe-delimited markdown tables, CSV, JSON, and plain text.
138
+ def parse_inline_data(raw)
139
+ raw = raw.strip
140
+
141
+ # JSON
142
+ if raw.start_with?('{', '[')
143
+ begin
144
+ return JSON.parse(raw)
145
+ rescue JSON::ParserError
146
+ # fall through
147
+ end
148
+ end
149
+
150
+ lines = raw.lines.map(&:strip).reject(&:empty?)
151
+
152
+ # Pipe-delimited markdown table: "Col A | Col B | Col C"
153
+ if lines.first&.include?('|')
154
+ headers = lines.first.split('|').map(&:strip).reject(&:empty?)
155
+ data_lines = lines.drop(1).reject { |l| l.match?(/^\|?[-:\s|]+$/) }
156
+ return data_lines.map do |line|
157
+ values = line.split('|').map(&:strip).reject(&:empty?)
158
+ headers.zip(values).to_h
159
+ end
160
+ end
161
+
162
+ # CSV (comma-separated)
163
+ if lines.first&.include?(',')
164
+ headers = lines.first.split(',').map(&:strip)
165
+ return lines.drop(1).map do |line|
166
+ values = line.split(',').map(&:strip)
167
+ headers.zip(values).to_h
168
+ end
169
+ end
170
+
171
+ # Plain text — return as array of lines
172
+ lines
173
+ end
174
+
119
175
  # Fetch data from web URL
120
176
  def fetch_web_data(url)
121
177
  @logger.debug("Fetching web data from: #{url}")
@@ -21,7 +21,15 @@ module SharedTools
21
21
  # @param text [String]
22
22
  # @param duration [Integer]
23
23
  def hold_key(text:, duration:)
24
- raise NotImplementedError, "#{self.class.name}##{__method__} undefined"
24
+ options = text.to_s.split('+')
25
+ key = options.pop
26
+ mask = options.reduce(0) { |m, opt| m | Library::CoreGraphics::EventFlags.find(opt) }
27
+
28
+ @keyboard.key_down(key, mask: mask)
29
+ Kernel.sleep(duration.to_f)
30
+ @keyboard.key_up(key, mask: mask)
31
+
32
+ { success: true, key: text, duration: duration }
25
33
  end
26
34
 
27
35
  # @return [Hash<{ x: Integer, y: Integer }>]
@@ -86,10 +94,35 @@ module SharedTools
86
94
  @keyboard.type(text)
87
95
  end
88
96
 
89
- # @param amount [Integer]
90
- # @param direction [String] e.g. "up", "down", "left", "right"
97
+ # @param amount [Integer] number of scroll units
98
+ # @param direction [String] "up", "down", "left", or "right"
91
99
  def scroll(amount:, direction:)
92
- raise NotImplementedError, "#{self.class.name}##{__method__} undefined"
100
+ # Attach CGEventCreateScrollWheelEvent2 if not already done
101
+ unless Library::CoreGraphics.respond_to?(:CGEventCreateScrollWheelEvent2)
102
+ Library::CoreGraphics.module_eval do
103
+ attach_function :CGEventCreateScrollWheelEvent2,
104
+ [:pointer, :uint32, :uint32, :int32, :int32, :int32],
105
+ :pointer
106
+ end
107
+ end
108
+
109
+ amt = amount.to_i
110
+ # kCGScrollEventUnitLine = 1; wheel_count = 2 (vertical + horizontal)
111
+ delta_y, delta_x = case direction.to_s.downcase
112
+ when 'up' then [ amt, 0]
113
+ when 'down' then [-amt, 0]
114
+ when 'left' then [0, -amt]
115
+ when 'right' then [0, amt]
116
+ else [0, 0]
117
+ end
118
+
119
+ event = Library::CoreGraphics.CGEventCreateScrollWheelEvent2(nil, 1, 2, delta_y, delta_x, 0)
120
+ Library::CoreGraphics.CGEventPost(
121
+ Library::CoreGraphics::EventTapLocation::HID_EVENT_TAP, event
122
+ )
123
+ Library::CoreGraphics.CFRelease(event)
124
+
125
+ { success: true, direction: direction, amount: amt }
93
126
  end
94
127
 
95
128
  # @yield [file]