active_harness 0.2.39 → 0.2.40

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: 656a10b468592b8e0c53c2c93a8fbf7b8536420f94bd0cb7a61255d432ee78ed
4
- data.tar.gz: 29de2c821b23ba363ef1596fb545035fbd1191ca6487161f6b9f30b39fe960db
3
+ metadata.gz: 4246d31550942e31c26ec9a708f49aae5b2e0f385a32aeaa06d6d6a75f2849ee
4
+ data.tar.gz: d7f12a75e7f72e3d004bfd3b64a094e99a082992fd0077e69253bddf97b919f0
5
5
  SHA512:
6
- metadata.gz: 9d0d4c4114ed028a603a783841c5205163f1f02203e7c010d5c806a8e673644b391cbfb636bbb1c4d77eb40a807907e63380213b087ab3c5515491c1c2c64fcf
7
- data.tar.gz: 84b154cb18717e6183337d728a6eb3ec9d34753856d6acc8fbf96c90e06a6e0db799b961b3f8d5bd7dc3984797bed401429a3110573243379eb471fcd84f160b
6
+ metadata.gz: 81cf0f7cb7f5f54c2a996097e34461f724bd66da920db0cee57cc84f558f8430bc83ad1e914c62a56f3493e890c993c9f2dd9408c161563ae8c161f5ac03e4d5
7
+ data.tar.gz: e144ed04675d274af6d66157a2f733e1cb65342adc7312b10428e9afc3c135b64af616218d6bb9ddbfb36948efd0e83b817f36654523f910c51d4797e07674e6
@@ -7,6 +7,10 @@ module ActiveHarness
7
7
  # image true
8
8
  # size "1024x1024"
9
9
  #
10
+ # # Optional: base style/formatting guidance, prepended to @input
11
+ # # to form the final image prompt (see Agent#build_image_prompt).
12
+ # system_prompt "Watercolor style, soft pastel colors, no text overlays."
13
+ #
10
14
  # model do
11
15
  # use provider: :openrouter, model: "openai/gpt-5-image-mini"
12
16
  # fallback provider: :openai, model: "gpt-image-1"
@@ -47,7 +47,7 @@ module ActiveHarness
47
47
 
48
48
  def attempt_model(entry, system_prompt)
49
49
  return attempt_via_custom_llm(entry, system_prompt) if @config[:custom_llm_backend]
50
- return attempt_image_model(entry) if @config[:image]
50
+ return attempt_image_model(entry, system_prompt) if @config[:image]
51
51
 
52
52
  provider = resolve_provider(entry[:provider])
53
53
  messages = build_messages(system_prompt, @input)
@@ -58,17 +58,26 @@ module ActiveHarness
58
58
  provider.call(**opts)
59
59
  end
60
60
 
61
- def attempt_image_model(entry)
61
+ def attempt_image_model(entry, system_prompt)
62
62
  factory = IMAGE_PROVIDERS[entry[:provider].to_sym]
63
63
  raise ArgumentError, "Provider #{entry[:provider].inspect} does not support image generation. " \
64
64
  "Supported image providers: #{IMAGE_PROVIDERS.keys.join(', ')}" unless factory
65
65
 
66
66
  size = entry[:size] || @config[:image_size] || "1024x1024"
67
- opts = { model: entry[:model], prompt: @input.to_s, size: size }
67
+ opts = { model: entry[:model], prompt: build_image_prompt(system_prompt, @input.to_s), size: size }
68
68
  opts[:quality] = entry[:quality] if entry[:quality]
69
69
  factory.call.call(**opts)
70
70
  end
71
71
 
72
+ # Image APIs take a single prompt string (no system/user role split), so the
73
+ # system prompt — e.g. base style/formatting guidance — is prepended to the
74
+ # user's input rather than sent as a separate message.
75
+ def build_image_prompt(system_prompt, input)
76
+ return input if system_prompt.nil? || system_prompt.to_s.strip.empty?
77
+
78
+ "#{system_prompt}\n\n#{input}"
79
+ end
80
+
72
81
  def resolve_provider(name)
73
82
  factory = PROVIDERS[name.to_sym]
74
83
  raise ArgumentError, "Unknown provider: #{name.inspect}. Supported: #{PROVIDERS.keys.join(', ')}" unless factory
@@ -10,14 +10,21 @@ module ActiveHarness
10
10
  # It does NOT automatically inject history into LLM messages.
11
11
  # Injection is always manual — you control when and how context is used.
12
12
  #
13
- # --- Recording (automatic) ---
13
+ # --- Recording ---
14
14
  #
15
- # When a Memory object is passed to an agent, the agent automatically
16
- # saves each successful turn (request + response) after the call.
15
+ # Passing a Memory object to Agent.call(memory:) does NOT by itself save
16
+ # anything Agent never calls #load or #record on it. Loading and
17
+ # recording turns for a bare agent call is entirely manual (e.g. via
18
+ # before_call/after_call hooks calling @memory.load / @memory.record).
19
+ #
20
+ # Pipeline is the one place recording is automatic: when a Memory is
21
+ # passed to Pipeline#call, the pipeline itself calls #load before running
22
+ # steps and #record after a successful run — independent of any hooks the
23
+ # individual agents define.
17
24
  #
18
25
  # memory = ActiveHarness::Memory.new(session_id: "u42", depth: 8)
19
26
  # SupportAgent.call(input: "Hello", memory: memory)
20
- # # => turn is saved to storage/ai/memory/u42.json
27
+ # # => nothing is saved unless SupportAgent's own hooks record it
21
28
  #
22
29
  # --- Manual injection patterns ---
23
30
  #
@@ -25,7 +25,7 @@ pipeline.call
25
25
 
26
26
  pipeline.output # => final payload string (nil if stopped)
27
27
  pipeline.stopped? # => false
28
- pipeline.step_results # => { translate: <Result>, injection_guard: <Result>, ... }
28
+ pipeline.steps.to_a # => [[:translate, <TranslationAgent>, <Result>], [:injection_guard, <InjectionGuardAgent>, <Result>], ...]
29
29
  ```
30
30
 
31
31
  ## Step types
@@ -32,7 +32,7 @@ require_relative "active_harness/pipeline"
32
32
  require_relative "active_harness/railtie" if defined?(Rails::Railtie)
33
33
 
34
34
  module ActiveHarness
35
- VERSION = "0.2.39"
35
+ VERSION = "0.2.40"
36
36
 
37
37
  class << self
38
38
  # Configure ActiveHarness.
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.39
4
+ version: 0.2.40
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-06-15 00:00:00.000000000 Z
11
+ date: 2026-07-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby