active_harness 0.3.9 → 0.3.10
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/lib/active_harness/agent.rb +1 -1
- data/lib/active_harness/tool.rb +12 -18
- data/lib/active_harness.rb +1 -1
- data/lib/generators/active_harness/install/templates/concerns/agent_tracing.rb +1 -1
- data/lib/generators/active_harness/install/templates/tools/ls_tool.rb +4 -3
- data/lib/generators/active_harness/install/templates/tools/read_file_tool.rb +2 -1
- data/lib/generators/active_harness/tool/templates/tool.rb.tt +4 -2
- 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: a3cdd2394f02350ed7562926bffc2107880d7830feef4280b2e4e438b60253bd
|
|
4
|
+
data.tar.gz: e585c386a7ad6725f8608c6356b1ca8c76789a02656f2f70d2cdc38de379929a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 869af984c65a9519d3f3122f582233f7296aff8646ca5df573d0d3260b6abec2315b536a690493f9253361f953280b55ae435fa6a9a166e647d08df04820b53b
|
|
7
|
+
data.tar.gz: acf051bd40ba5e6e10c1bd3e9222673e85ebd07cc89c89f9822559db53b65b4421d75605387060e50d70d756c9613ca66e33acce17d50997bc501e0bbadd45ff
|
data/lib/active_harness/agent.rb
CHANGED
|
@@ -263,7 +263,7 @@ module ActiveHarness
|
|
|
263
263
|
body << " answer: #{res.output.to_s[0, 80].inspect}" if turn.tool_calls.empty? && res
|
|
264
264
|
([head] + body).join("\n")
|
|
265
265
|
end
|
|
266
|
-
lines << format("stop %s %d turns, %d tool calls (%d
|
|
266
|
+
lines << format("stop %s %d turns, %d tool calls (%d refused or failed), $%.4f",
|
|
267
267
|
@state.stop_reason, @turns.size, tool_calls.size, denied_calls.size,
|
|
268
268
|
@state.usage&.cost&.total.to_f)
|
|
269
269
|
lines.join("\n")
|
data/lib/active_harness/tool.rb
CHANGED
|
@@ -43,7 +43,8 @@ module ActiveHarness
|
|
|
43
43
|
# call passes through your checks first.
|
|
44
44
|
#
|
|
45
45
|
# class LsTool < ActiveHarness::Tool
|
|
46
|
-
#
|
|
46
|
+
# tool_scope :os
|
|
47
|
+
# tool_name "ls"
|
|
47
48
|
# description "List files in a directory"
|
|
48
49
|
# param :path, "Directory to list"
|
|
49
50
|
#
|
|
@@ -94,20 +95,22 @@ module ActiveHarness
|
|
|
94
95
|
class << self
|
|
95
96
|
# --- what the model sees ---
|
|
96
97
|
|
|
97
|
-
# Required namespace: :os, :web, :ruby ... Full name is "
|
|
98
|
-
|
|
99
|
-
|
|
98
|
+
# Required namespace: :os, :web, :ruby ... Full name is "tool_scope::tool_name".
|
|
99
|
+
# Both are explicit on purpose: the name the model sees must not change when a class is renamed.
|
|
100
|
+
def tool_scope(value = nil)
|
|
101
|
+
value ? @tool_scope = value.to_sym : @tool_scope
|
|
100
102
|
end
|
|
101
103
|
|
|
102
|
-
#
|
|
104
|
+
# Required: "ls", "fetch_url" ...
|
|
103
105
|
def tool_name(value = nil)
|
|
104
|
-
value ? @tool_name = value.to_s :
|
|
106
|
+
value ? @tool_name = value.to_s : @tool_name
|
|
105
107
|
end
|
|
106
108
|
|
|
107
109
|
def full_name
|
|
108
|
-
raise ArgumentError, "#{name || 'Tool'} must declare a
|
|
110
|
+
raise ArgumentError, "#{name || 'Tool'} must declare a tool_scope (e.g. `tool_scope :os`)" unless tool_scope
|
|
111
|
+
raise ArgumentError, "#{name || 'Tool'} must declare a tool_name (e.g. `tool_name \"ls\"`)" unless tool_name
|
|
109
112
|
|
|
110
|
-
"#{
|
|
113
|
+
"#{tool_scope}::#{tool_name}"
|
|
111
114
|
end
|
|
112
115
|
|
|
113
116
|
# Name on the wire: providers allow only [a-zA-Z0-9_-] in function names.
|
|
@@ -227,7 +230,7 @@ module ActiveHarness
|
|
|
227
230
|
|
|
228
231
|
def inherited(subclass)
|
|
229
232
|
super
|
|
230
|
-
subclass.instance_variable_set(:@
|
|
233
|
+
subclass.instance_variable_set(:@tool_scope, @tool_scope)
|
|
231
234
|
subclass.instance_variable_set(:@steps, steps.dup)
|
|
232
235
|
subclass.instance_variable_set(:@params, params.map(&:dup))
|
|
233
236
|
subclass.instance_variable_set(:@hooks, hooks.each_with_object({}) { |(k, v), h| h[k] = v.dup })
|
|
@@ -238,15 +241,6 @@ module ActiveHarness
|
|
|
238
241
|
def call(input:, context: {})
|
|
239
242
|
new(context: context).call(input)
|
|
240
243
|
end
|
|
241
|
-
|
|
242
|
-
private
|
|
243
|
-
|
|
244
|
-
def default_name
|
|
245
|
-
return nil unless name
|
|
246
|
-
|
|
247
|
-
base = name.split("::").last.sub(/Tool\z/, "")
|
|
248
|
-
base.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').gsub(/([a-z\d])([A-Z])/, '\1_\2').downcase
|
|
249
|
-
end
|
|
250
244
|
end
|
|
251
245
|
|
|
252
246
|
include Core::HookRunner
|
data/lib/active_harness.rb
CHANGED
|
@@ -29,7 +29,7 @@ module AgentTracing
|
|
|
29
29
|
|
|
30
30
|
base.on(:complete) do |result|
|
|
31
31
|
usage = result.usage
|
|
32
|
-
trace_log "#{status}/#{stop_reason} — #{turns.size} turns, #{tool_calls.size} tool calls (#{denied_calls.size} refused), " \
|
|
32
|
+
trace_log "#{status}/#{stop_reason} — #{turns.size} turns, #{tool_calls.size} tool calls (#{denied_calls.size} refused or failed), " \
|
|
33
33
|
"#{usage&.tokens&.total.to_i} tokens#{format(", $%.6f", usage.cost.total) if usage&.cost}, #{result.execution_time}s"
|
|
34
34
|
end
|
|
35
35
|
end
|
|
@@ -5,9 +5,10 @@ class LsTool < ActiveHarness::Tool
|
|
|
5
5
|
include ActiveHarness::Tool::PathPolicy # safe_path!: resolves symlinks and ".." and checks ALLOWED_PATHS
|
|
6
6
|
include ToolTracing # logs every step; see app/ai/concerns/
|
|
7
7
|
|
|
8
|
-
# `
|
|
9
|
-
#
|
|
10
|
-
|
|
8
|
+
# `tool_scope` namespaces the tool (os::ls vs web::ls) and lets you allow or log a whole group;
|
|
9
|
+
# `tool_name` is the name the model sees. Both are explicit: renaming the class changes nothing for the model.
|
|
10
|
+
tool_scope :os
|
|
11
|
+
tool_name "ls"
|
|
11
12
|
|
|
12
13
|
# What the model reads when it decides whether to call this tool — write it for the model.
|
|
13
14
|
description "List files in a directory inside the workspace"
|
|
@@ -6,7 +6,8 @@ class ReadFileTool < ActiveHarness::Tool
|
|
|
6
6
|
include ActiveHarness::Tool::PathPolicy
|
|
7
7
|
include ToolTracing
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
tool_scope :os # full name: os::read_file
|
|
10
|
+
tool_name "read_file"
|
|
10
11
|
description "Read the first lines of a text file inside the workspace"
|
|
11
12
|
|
|
12
13
|
param :path, "Absolute path of the file"
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
class <%= class_name %>Tool < ActiveHarness::Tool
|
|
2
|
-
#
|
|
3
|
-
|
|
2
|
+
# Namespace + name the model sees: <%= file_name %> becomes app::<%= file_name %> (wire name app__<%= file_name %>).
|
|
3
|
+
# Both are explicit, so renaming this class never changes what the model calls. Use :os, :web, :ruby ... per area.
|
|
4
|
+
tool_scope :app
|
|
5
|
+
tool_name "<%= file_name %>"
|
|
4
6
|
|
|
5
7
|
# Written for the model: when to call this tool.
|
|
6
8
|
description "Describe what this tool does for the model"
|