ollama_chat 0.0.66 → 0.0.67
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/CHANGES.md +13 -0
- data/lib/ollama_chat/tools/directory_structure.rb +15 -4
- data/lib/ollama_chat/utils/analyze_directory.rb +140 -58
- data/lib/ollama_chat/version.rb +1 -1
- data/ollama_chat.gemspec +2 -2
- data/spec/ollama_chat/tools/directory_structure_spec.rb +3 -0
- data/spec/ollama_chat/utils/analyze_directory_spec.rb +20 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3eb8ee4b480c19b26ba27b6d112da4038ed16615881425ba4f7142483d329a79
|
|
4
|
+
data.tar.gz: 85a7d64b19b3e751d51d7ada7af2ff536e578f3425218394b0aa3efcd5301626
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f374a3d58183068936222115a61e090ee3e45efd637401ffd97cebc147286b971025730d6393e95dc2b5eeb2e89cacc65d33a3dc76f6467fb23e1aedfe13fffd
|
|
7
|
+
data.tar.gz: fefa35f2e685dab9c4f3e8b97487f4a4a072f3b2b982864ae423b8d4aaba29ea3e46dc4065dedb7db3908f3192c56c922f92e123163272ef186771b862b7ffc4
|
data/CHANGES.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# Changes
|
|
2
2
|
|
|
3
|
+
## 2026-02-18 v0.0.67
|
|
4
|
+
|
|
5
|
+
- Added `max_depth` option to directory listing tool
|
|
6
|
+
- Updated `OllamaChat::Tools::DirectoryStructure#execute` to accept `max_depth` parameter
|
|
7
|
+
- Enhanced `OllamaChat::Utils::AnalyzeDirectory#generate_structure` to handle `max_depth` limit
|
|
8
|
+
- Implemented depth and height computation for directory entries
|
|
9
|
+
- Added depth pruning functionality to remove children beyond the specified depth limit
|
|
10
|
+
- Attached `:depth` and `:height` metadata to each directory entry in JSON output
|
|
11
|
+
- Refactored internal helper method `recurse_generate_structure` to track entry depth
|
|
12
|
+
- Updated documentation comments to reflect new behavior
|
|
13
|
+
- Added comprehensive test coverage for `max_depth` functionality
|
|
14
|
+
- Added depth-pruning test cases in specification files
|
|
15
|
+
|
|
3
16
|
## 2026-02-16 v0.0.66
|
|
4
17
|
|
|
5
18
|
- Updated `OllamaChat::Tools::GetCurrentWeather.execute` to return a JSON
|
|
@@ -24,7 +24,10 @@ class OllamaChat::Tools::DirectoryStructure
|
|
|
24
24
|
type: 'function',
|
|
25
25
|
function: Tool::Function.new(
|
|
26
26
|
name:,
|
|
27
|
-
description:
|
|
27
|
+
description: <<~EOT,
|
|
28
|
+
Retrieve the directory structure and file hierarchy for a given path,
|
|
29
|
+
for depth of max_depth (if given).
|
|
30
|
+
EOT
|
|
28
31
|
parameters: Tool::Function::Parameters.new(
|
|
29
32
|
type: 'object',
|
|
30
33
|
properties: {
|
|
@@ -32,6 +35,13 @@ class OllamaChat::Tools::DirectoryStructure
|
|
|
32
35
|
type: 'string',
|
|
33
36
|
description: 'Path to directory to list (defaults to current directory)'
|
|
34
37
|
),
|
|
38
|
+
max_depth: Tool::Function::Parameters::Property.new(
|
|
39
|
+
type: 'integer',
|
|
40
|
+
description: <<~EOT,
|
|
41
|
+
Maximum depth of directory structure to return upto the total
|
|
42
|
+
height of the directory structure (defaults to disabled)
|
|
43
|
+
EOT
|
|
44
|
+
),
|
|
35
45
|
},
|
|
36
46
|
required: []
|
|
37
47
|
)
|
|
@@ -52,10 +62,11 @@ class OllamaChat::Tools::DirectoryStructure
|
|
|
52
62
|
# @raise [StandardError] if there's an issue with directory traversal or JSON
|
|
53
63
|
# serialization
|
|
54
64
|
def execute(tool_call, **opts)
|
|
55
|
-
config
|
|
56
|
-
path
|
|
65
|
+
config = opts[:config]
|
|
66
|
+
path = Pathname.new(tool_call.function.arguments.path || '.')
|
|
67
|
+
max_depth = tool_call.function.arguments.max_depth
|
|
57
68
|
|
|
58
|
-
structure = generate_structure(path, exclude: config.tools.directory_structure.exclude?)
|
|
69
|
+
structure = generate_structure(path, max_depth:, exclude: config.tools.directory_structure.exclude?)
|
|
59
70
|
structure.to_json
|
|
60
71
|
end
|
|
61
72
|
|
|
@@ -1,64 +1,146 @@
|
|
|
1
|
-
|
|
2
|
-
# generating file listings.
|
|
3
|
-
#
|
|
4
|
-
# The AnalyzeDirectory module offers methods to traverse directory hierarchies
|
|
5
|
-
# and create structured representations of file systems. It supports recursive
|
|
6
|
-
# directory traversal, filtering of hidden files and symbolic links, and
|
|
7
|
-
# generation of detailed file and directory information including paths, names,
|
|
8
|
-
# and metadata.
|
|
9
|
-
module OllamaChat::Utils::AnalyzeDirectory
|
|
10
|
-
module_function
|
|
1
|
+
require 'pathname'
|
|
11
2
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
#
|
|
43
|
-
|
|
3
|
+
module OllamaChat
|
|
4
|
+
module Utils
|
|
5
|
+
# The `OllamaChat::Utils::AnalyzeDirectory` module provides a small,
|
|
6
|
+
# dependency‑free helper for walking a directory tree and producing a
|
|
7
|
+
# nested hash representation of the file system.
|
|
8
|
+
#
|
|
9
|
+
# It supports:
|
|
10
|
+
#
|
|
11
|
+
# * Recursive traversal of directories
|
|
12
|
+
# * Skipping hidden files/directories and symbolic links
|
|
13
|
+
# * Excluding arbitrary paths via glob patterns
|
|
14
|
+
# * Limiting the depth of the returned tree
|
|
15
|
+
#
|
|
16
|
+
# Example
|
|
17
|
+
#
|
|
18
|
+
# require_relative 'analyze_directory'
|
|
19
|
+
#
|
|
20
|
+
# include OllamaChat::Utils::AnalyzeDirectory
|
|
21
|
+
#
|
|
22
|
+
# structure = generate_structure(
|
|
23
|
+
# '/path/to/dir',
|
|
24
|
+
# exclude: ['tmp', 'vendor'],
|
|
25
|
+
# max_depth: 3
|
|
26
|
+
# )
|
|
27
|
+
#
|
|
28
|
+
# puts structure.inspect
|
|
29
|
+
#
|
|
30
|
+
# @api public
|
|
31
|
+
module AnalyzeDirectory
|
|
32
|
+
# Generate a nested hash representation of a directory tree.
|
|
33
|
+
#
|
|
34
|
+
# @param path [String, Pathname] The root directory to walk.
|
|
35
|
+
# Defaults to the current working directory (`"."`).
|
|
36
|
+
# @param exclude [Array<String, Pathname>] Glob patterns (relative to
|
|
37
|
+
# +path+) that should be ignored during traversal.
|
|
38
|
+
# @param max_depth [Integer, nil] Optional depth limit. If `nil`,
|
|
39
|
+
# the entire tree is returned. When an integer is supplied, all
|
|
40
|
+
# entries deeper than that depth are pruned.
|
|
41
|
+
#
|
|
42
|
+
# @return [Array<Hash>] An array of entry hashes. Each hash contains:
|
|
43
|
+
# * `:type` – "file" or "directory"
|
|
44
|
+
# * `:name` – Base name of the file/directory
|
|
45
|
+
# * `:path` – Absolute path
|
|
46
|
+
# * `:depth` – Depth relative to the root (root = 0)
|
|
47
|
+
# * `:height` – The maximum depth found in the entire tree
|
|
48
|
+
# * `:children` – Array of child entry hashes (only for directories)
|
|
49
|
+
#
|
|
50
|
+
# @raise [StandardError] Any exception raised during traversal is
|
|
51
|
+
# rescued and returned as a hash with `:error` and `:message`
|
|
52
|
+
# keys.
|
|
53
|
+
#
|
|
54
|
+
# @example Basic usage
|
|
55
|
+
# generate_structure(
|
|
56
|
+
# '/tmp',
|
|
57
|
+
# exclude: ['cache', 'logs'],
|
|
58
|
+
# max_depth: 2
|
|
59
|
+
# )
|
|
60
|
+
#
|
|
61
|
+
# @api public
|
|
62
|
+
def generate_structure(path = '.', exclude: [], max_depth: nil)
|
|
63
|
+
entries = recurse_generate_structure(path, exclude:)
|
|
64
|
+
height = 0
|
|
44
65
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
66
|
+
structure_each_entry(entries) do |e|
|
|
67
|
+
height = e[:depth] if e[:depth] > height
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
structure_each_entry(entries) { |e| e[:height] = height }
|
|
71
|
+
|
|
72
|
+
if max_depth && max_depth < height
|
|
73
|
+
structure_each_entry(entries) do |e|
|
|
74
|
+
e[:children]&.reject! { |c| c[:depth] > max_depth }
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
entries
|
|
79
|
+
rescue => e
|
|
80
|
+
{ error: e.class, message: e.message }
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
private
|
|
84
|
+
|
|
85
|
+
# Recursively walk *path* and build the tree.
|
|
86
|
+
#
|
|
87
|
+
# @param path [String, Pathname] Directory to traverse.
|
|
88
|
+
# @param exclude [Array<Pathname>] List of absolute paths to skip.
|
|
89
|
+
# @param depth [Integer] Current depth (root = 0).
|
|
90
|
+
#
|
|
91
|
+
# @return [Array<Hash>] Array of entry hashes.
|
|
92
|
+
#
|
|
93
|
+
# @api private
|
|
94
|
+
def recurse_generate_structure(path = '.', exclude: [], depth: 0)
|
|
95
|
+
exclude = Array(exclude).map { |p| Pathname.new(p).expand_path }
|
|
96
|
+
path = Pathname.new(path).expand_path
|
|
97
|
+
entries = []
|
|
98
|
+
|
|
99
|
+
path.children.sort.each do |child|
|
|
100
|
+
# Skip hidden files/directories
|
|
101
|
+
next if child.basename.to_s.start_with?('.')
|
|
102
|
+
# Skip symlinks
|
|
103
|
+
next if child.symlink?
|
|
104
|
+
# Skip user‑excluded paths
|
|
105
|
+
next if exclude.any? { |e| child.fnmatch?(e.to_s, File::FNM_PATHNAME) }
|
|
106
|
+
|
|
107
|
+
if child.directory?
|
|
108
|
+
entries << {
|
|
109
|
+
type: 'directory',
|
|
110
|
+
name: child.basename.to_s,
|
|
111
|
+
path: child.expand_path.to_s,
|
|
112
|
+
children: recurse_generate_structure(child, exclude:, depth: depth + 1),
|
|
113
|
+
depth:
|
|
114
|
+
}
|
|
115
|
+
elsif child.file?
|
|
116
|
+
entries << {
|
|
117
|
+
type: 'file',
|
|
118
|
+
name: child.basename.to_s,
|
|
119
|
+
path: child.expand_path.to_s,
|
|
120
|
+
depth:
|
|
121
|
+
}
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
entries
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# Iterate over every entry in *entries* (depth‑first).
|
|
129
|
+
#
|
|
130
|
+
# @param entries [Array<Hash>] The root array of entries.
|
|
131
|
+
# @yield [Hash] Yields each entry hash.
|
|
132
|
+
#
|
|
133
|
+
# @return [Array<Hash>] The original +entries+ array.
|
|
134
|
+
#
|
|
135
|
+
# @api private
|
|
136
|
+
def structure_each_entry(entries, &block)
|
|
137
|
+
queue = entries.dup
|
|
138
|
+
while entry = queue.shift
|
|
139
|
+
block.(entry)
|
|
140
|
+
queue.concat(entry[:children]) if entry[:children]
|
|
141
|
+
end
|
|
142
|
+
entries
|
|
58
143
|
end
|
|
59
144
|
end
|
|
60
|
-
entries
|
|
61
|
-
rescue => e
|
|
62
|
-
{ error: e.class, message: e.message }
|
|
63
145
|
end
|
|
64
146
|
end
|
data/lib/ollama_chat/version.rb
CHANGED
data/ollama_chat.gemspec
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
|
2
|
-
# stub: ollama_chat 0.0.
|
|
2
|
+
# stub: ollama_chat 0.0.67 ruby lib
|
|
3
3
|
|
|
4
4
|
Gem::Specification.new do |s|
|
|
5
5
|
s.name = "ollama_chat".freeze
|
|
6
|
-
s.version = "0.0.
|
|
6
|
+
s.version = "0.0.67".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]
|
|
@@ -26,6 +26,7 @@ describe OllamaChat::Tools::DirectoryStructure do
|
|
|
26
26
|
name: 'directory_structure',
|
|
27
27
|
arguments: double(
|
|
28
28
|
path: 'spec/assets',
|
|
29
|
+
max_depth: nil,
|
|
29
30
|
)
|
|
30
31
|
)
|
|
31
32
|
)
|
|
@@ -45,6 +46,7 @@ describe OllamaChat::Tools::DirectoryStructure do
|
|
|
45
46
|
name: 'directory_structure',
|
|
46
47
|
arguments: double(
|
|
47
48
|
path: nil, # Should default to '.'
|
|
49
|
+
max_depth: nil,
|
|
48
50
|
)
|
|
49
51
|
)
|
|
50
52
|
)
|
|
@@ -64,6 +66,7 @@ describe OllamaChat::Tools::DirectoryStructure do
|
|
|
64
66
|
name: 'directory_structure',
|
|
65
67
|
arguments: double(
|
|
66
68
|
path: '/nonexistent/path',
|
|
69
|
+
max_depth: nil,
|
|
67
70
|
)
|
|
68
71
|
)
|
|
69
72
|
)
|
|
@@ -3,7 +3,11 @@ require 'tmpdir'
|
|
|
3
3
|
require 'fileutils'
|
|
4
4
|
|
|
5
5
|
describe OllamaChat::Utils::AnalyzeDirectory do
|
|
6
|
-
let
|
|
6
|
+
let :generate do
|
|
7
|
+
obj = double
|
|
8
|
+
obj.extend(described_class)
|
|
9
|
+
obj.method(:generate_structure)
|
|
10
|
+
end
|
|
7
11
|
|
|
8
12
|
context 'basic directory structure' do
|
|
9
13
|
before do
|
|
@@ -28,9 +32,24 @@ describe OllamaChat::Utils::AnalyzeDirectory do
|
|
|
28
32
|
expect(result.map { |e| e[:name] }).to contain_exactly('a.txt', 'b.rb', 'sub')
|
|
29
33
|
|
|
30
34
|
sub = result.find { |e| e[:name] == 'sub' }
|
|
35
|
+
expect(sub[:depth]).to eq 0
|
|
31
36
|
expect(sub[:type]).to eq('directory')
|
|
32
37
|
expect(sub[:children]).to be_an(Array)
|
|
33
38
|
expect(sub[:children].map { |e| e[:name] }).to contain_exactly('c.md')
|
|
39
|
+
expect(sub[:children].map { |e| e[:depth] }).to eq [ 1 ]
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it 'returns an array of entries with depth max_depth' do
|
|
43
|
+
result = generate.call(@tmp_dir, max_depth: 0)
|
|
44
|
+
|
|
45
|
+
expect(result).to be_an(Array)
|
|
46
|
+
expect(result.map { |e| e[:name] }).to contain_exactly('a.txt', 'b.rb', 'sub')
|
|
47
|
+
|
|
48
|
+
sub = result.find { |e| e[:name] == 'sub' }
|
|
49
|
+
expect(sub[:depth]).to eq 0
|
|
50
|
+
expect(sub[:type]).to eq('directory')
|
|
51
|
+
expect(sub[:children]).to be_an(Array)
|
|
52
|
+
expect(sub[:children]).to be_empty
|
|
34
53
|
end
|
|
35
54
|
end
|
|
36
55
|
|