active_harness 0.2.2 → 0.2.4

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: 5069843133cbccc04bc676a51e83c4739ebd0642ae1db2bf3899c9b53b56e442
4
- data.tar.gz: 7346b4a9b1c9a1de93e2b413a8d444e563cbca18ff2b57b65c35f27824bf67a0
3
+ metadata.gz: 78572139b0f913adcfd708045581ad90989413a1a31535af37b723a7919c407b
4
+ data.tar.gz: 0b04931f1fec80dfd30e6f642b594ab7b1a26ba07a4722a7af79b44b48301e15
5
5
  SHA512:
6
- metadata.gz: 467bc7fff77cec34ded8f8015a535862ced7d5eb9b7ac6204ee263b4d747ae54b224717ef8fed5a77d4b3c57346e60103804b1bb6871973eeaf89d372c5f2cd8
7
- data.tar.gz: eee493ed814365a5fed2d02e2c2a5fb50fb4879adc39373644aa969ccd65ded88ce39cc5b2ab4fddc0e874fc2d955aeea4e2d35b8199a9eefc1d0713d1218262
6
+ metadata.gz: 79a7c9b4d7e803e5565cad3e3148c123ec5c28dff5cd09340ca613b1e69ed7a1523d737d9d7bff2acf01e08c4c827f489f5f4442d00b7925ade2a5be9ea0100f
7
+ data.tar.gz: 98a0c42415e8538d82f50579abd7720585da3bf990e59f53d49f5ab95fb93e7cff9a8dc0614d709a067028d1a77d9b57cd6aa5ce3fb89054d5ab79f4bd2bf2c8
@@ -28,8 +28,13 @@ module ActiveHarness
28
28
  # -------------------------------------------------------------------------
29
29
  # Instance API
30
30
  # -------------------------------------------------------------------------
31
- attr_accessor :input
32
- attr_reader :context, :result
31
+ attr_accessor :input, :context
32
+ attr_reader :result
33
+
34
+ def models=(list)
35
+ @models_override = Array(list)
36
+ @model_list_proxy = nil
37
+ end
33
38
 
34
39
  def initialize(input: nil, context: {}, models: nil, memory: nil, stream: nil)
35
40
  @input = input
@@ -64,7 +69,7 @@ module ActiveHarness
64
69
  save_to_memory(result)
65
70
  run_hook(:after_call, result)
66
71
  @result = result
67
- return result
72
+ return self
68
73
  rescue *RETRYABLE_ERRORS => e
69
74
  elapsed = (Process.clock_gettime(Process::CLOCK_MONOTONIC) - t0).round(3)
70
75
  attempts << attempt_entry(entry, e, elapsed)
@@ -122,6 +122,12 @@ module ActiveHarness
122
122
  # -------------------------------------------------------------------------
123
123
  attr_reader :original_input, :output, :stopped_at, :stop_reason,
124
124
  :execution_time, :step_results, :context
125
+ attr_writer :context
126
+
127
+ def input=(value)
128
+ @original_input = value
129
+ @payload = value
130
+ end
125
131
 
126
132
  def initialize(input:, context: {}, memory: nil)
127
133
  @original_input = input
@@ -94,7 +94,7 @@ module ActiveHarness
94
94
  end
95
95
  end
96
96
 
97
- attr_accessor :input
97
+ attr_accessor :input, :context
98
98
  attr_reader :results, :errors, :verdict, :execution_time, :agent_execution_times
99
99
 
100
100
  def initialize(input: nil, context: {}, agents: nil, timeout: 7)
@@ -17,21 +17,21 @@ module ActiveHarness
17
17
  end
18
18
 
19
19
  def copy_controller
20
- target = File.join(destination_root, "app", "controllers", "ai_test_support_controller.rb")
20
+ target = File.join(destination_root, "app", "controllers", "ai_support_controller.rb")
21
21
  return if File.exist?(target)
22
22
 
23
23
  copy_file "controllers/ai_controller.rb",
24
- "app/controllers/ai_test_support_controller.rb"
24
+ "app/controllers/ai_support_controller.rb"
25
25
  end
26
26
 
27
27
  def inject_routes
28
28
  route <<~ROUTES.strip
29
- # ActiveHarness — AI test support endpoints
30
- post "ai/agent", to: "ai_test_support#agent"
31
- post "ai/agent_memory", to: "ai_test_support#agent_memory"
32
- post "ai/tribunal", to: "ai_test_support#tribunal"
33
- post "ai/pipeline", to: "ai_test_support#pipeline"
34
- get "ai/agent_stream", to: "ai_test_support#agent_stream"
29
+ # ActiveHarness — AI support endpoints
30
+ post "ai/agent", to: "ai_support#agent"
31
+ post "ai/agent_memory", to: "ai_support#agent_memory"
32
+ post "ai/tribunal", to: "ai_support#tribunal"
33
+ post "ai/pipeline", to: "ai_support#pipeline"
34
+ get "ai/agent_stream", to: "ai_support#agent_stream"
35
35
  ROUTES
36
36
  end
37
37
 
@@ -1,7 +1,7 @@
1
- require_relative "../prompts/test_support_prompt"
1
+ require_relative "../prompts/support_prompt"
2
2
 
3
- class TestSupportAgent < ActiveHarness::Agent
4
- system_prompt TestSupportPrompt
3
+ class SupportAgent < ActiveHarness::Agent
4
+ system_prompt SupportPrompt
5
5
 
6
6
  model do
7
7
  use provider: :openrouter, model: "mistralai/mistral-nemo"
@@ -1,7 +1,7 @@
1
- require_relative "../prompts/test_support_guard_prompt"
1
+ require_relative "../prompts/support_guard_prompt"
2
2
 
3
- class TestSupportGuardAgent < ActiveHarness::Agent
4
- system_prompt TestSupportGuardPrompt
3
+ class SupportGuardAgent < ActiveHarness::Agent
4
+ system_prompt SupportGuardPrompt
5
5
  format :json
6
6
 
7
7
  model do
@@ -1,4 +1,4 @@
1
- class AiTestSupportController < ApplicationController
1
+ class AiSupportController < ApplicationController
2
2
  include ActionController::Live
3
3
 
4
4
  # ---------------------------------------------------------------------------
@@ -6,7 +6,7 @@ class AiTestSupportController < ApplicationController
6
6
  # body: { input: "What is your return policy?" }
7
7
  # ---------------------------------------------------------------------------
8
8
  def agent
9
- result = TestSupportAgent.call(input: params.require(:input))
9
+ result = SupportAgent.call(input: params.require(:input))
10
10
 
11
11
  render json: {
12
12
  output: result.output,
@@ -23,8 +23,8 @@ class AiTestSupportController < ApplicationController
23
23
  # across multiple requests.
24
24
  # ---------------------------------------------------------------------------
25
25
  def agent_memory
26
- memory = TestSupportMemory.new(session_id: params.require(:session_id))
27
- result = TestSupportAgent.call(input: params.require(:input), memory: memory)
26
+ memory = AppMemory.new(session_id: params.require(:session_id))
27
+ result = SupportAgent.call(input: params.require(:input), memory: memory)
28
28
 
29
29
  render json: {
30
30
  output: result.output,
@@ -41,7 +41,7 @@ class AiTestSupportController < ApplicationController
41
41
  # Returns verdict: true (safe) or false (rejected).
42
42
  # ---------------------------------------------------------------------------
43
43
  def tribunal
44
- result = TestSupportGuardTribunal.call(input: params.require(:input))
44
+ result = SupportGuardTribunal.call(input: params.require(:input))
45
45
 
46
46
  render json: {
47
47
  verdict: result.verdict,
@@ -57,7 +57,7 @@ class AiTestSupportController < ApplicationController
57
57
  # If a guard step stops the pipeline early, stopped: true is returned.
58
58
  # ---------------------------------------------------------------------------
59
59
  def pipeline
60
- pipe = TestSupportPipeline.new(input: params.require(:input))
60
+ pipe = SupportPipeline.new(input: params.require(:input))
61
61
  pipe.call
62
62
 
63
63
  if pipe.stopped?
@@ -91,7 +91,7 @@ class AiTestSupportController < ApplicationController
91
91
 
92
92
  sse = ActionController::Live::SSE.new(response.stream, event: "message")
93
93
 
94
- TestSupportAgent.call(
94
+ SupportAgent.call(
95
95
  input: input,
96
96
  stream: ->(token) { sse.write({ token: token }.to_json) }
97
97
  )
@@ -1,5 +1,5 @@
1
- class TestSupportMemory < ActiveHarness::Memory
2
- # Usage: TestSupportMemory.new(session_id: "user_42")
1
+ class AppMemory < ActiveHarness::Memory
2
+ # Usage: AppMemory.new(session_id: "user_42")
3
3
  #
4
4
  # Wraps ActiveHarness::Memory with project defaults so callers
5
5
  # only need to pass a session_id.
@@ -1,17 +1,17 @@
1
- require_relative "../tribunals/test_support_guard_tribunal"
2
- require_relative "../agents/test_support_agent"
1
+ require_relative "../tribunals/support_guard_tribunal"
2
+ require_relative "../agents/support_agent"
3
3
 
4
4
  # Two-step pipeline: spam guard → answer.
5
5
  # Add more steps between them as needed.
6
- class TestSupportPipeline < ActiveHarness::Pipeline
6
+ class SupportPipeline < ActiveHarness::Pipeline
7
7
  # Step 1 — GUARD: reject spam before spending tokens on an answer
8
8
  step :spam_guard do
9
- use TestSupportGuardTribunal
9
+ use SupportGuardTribunal
10
10
  stop_if ->(result) { result.verdict == false }
11
11
  end
12
12
 
13
13
  # Step 2 — RESPOND: generate the actual answer
14
- step :respond, TestSupportAgent
14
+ step :respond, SupportAgent
15
15
 
16
16
  before :step do |step_name, _payload|
17
17
  puts "[pipeline] → :#{step_name}"
@@ -1,4 +1,4 @@
1
- class TestSupportGuardPrompt
1
+ class SupportGuardPrompt
2
2
  def call
3
3
  <<~PROMPT.strip
4
4
  You are a spam detection filter.
@@ -1,4 +1,4 @@
1
- class TestSupportPrompt
1
+ class SupportPrompt
2
2
  def call
3
3
  "You are a concise and helpful assistant. Answer in 1-2 sentences."
4
4
  end
@@ -0,0 +1,11 @@
1
+ require_relative "../agents/support_guard_agent"
2
+
3
+ # Runs SupportGuardAgent in parallel (single agent here, extendable).
4
+ # Verdict is true (safe) when no spam is detected.
5
+ class SupportGuardTribunal < ActiveHarness::Tribunal
6
+ agents SupportGuardAgent
7
+
8
+ process do |results|
9
+ results.none? { |r| r.parsed["spam"] == true }
10
+ end
11
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_harness
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - the-teacher
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-05-20 00:00:00.000000000 Z
11
+ date: 2026-05-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -59,14 +59,14 @@ files:
59
59
  - lib/generators/active_harness/agent/agent_generator.rb
60
60
  - lib/generators/active_harness/agent/templates/agent.rb.tt
61
61
  - lib/generators/active_harness/install/install_generator.rb
62
- - lib/generators/active_harness/install/templates/agents/test_support_agent.rb
63
- - lib/generators/active_harness/install/templates/agents/test_support_guard_agent.rb
62
+ - lib/generators/active_harness/install/templates/agents/support_agent.rb
63
+ - lib/generators/active_harness/install/templates/agents/support_guard_agent.rb
64
64
  - lib/generators/active_harness/install/templates/controllers/ai_controller.rb
65
- - lib/generators/active_harness/install/templates/memory/test_support_memory.rb
66
- - lib/generators/active_harness/install/templates/pipelines/test_support_pipeline.rb
67
- - lib/generators/active_harness/install/templates/prompts/test_support_guard_prompt.rb
68
- - lib/generators/active_harness/install/templates/prompts/test_support_prompt.rb
69
- - lib/generators/active_harness/install/templates/tribunals/test_support_guard_tribunal.rb
65
+ - lib/generators/active_harness/install/templates/memory/app_memory.rb
66
+ - lib/generators/active_harness/install/templates/pipelines/support_pipeline.rb
67
+ - lib/generators/active_harness/install/templates/prompts/support_guard_prompt.rb
68
+ - lib/generators/active_harness/install/templates/prompts/support_prompt.rb
69
+ - lib/generators/active_harness/install/templates/tribunals/support_guard_tribunal.rb
70
70
  - lib/generators/active_harness/memory/memory_generator.rb
71
71
  - lib/generators/active_harness/memory/templates/memory.rb.tt
72
72
  - lib/generators/active_harness/pipeline/pipeline_generator.rb
@@ -1,11 +0,0 @@
1
- require_relative "../agents/test_support_guard_agent"
2
-
3
- # Runs TestSupportGuardAgent in parallel (single agent here, extendable).
4
- # Verdict is true (safe) when no spam is detected.
5
- class TestSupportGuardTribunal < ActiveHarness::Tribunal
6
- agents TestSupportGuardAgent
7
-
8
- process do |results|
9
- results.none? { |r| r.parsed["spam"] == true }
10
- end
11
- end