collavre_openclaw 0.6.0 → 0.6.1

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: ff18cc7843b54de3c5e86de861f69b9225aa47dd7e57aae94cd612d7698d1d55
4
- data.tar.gz: 8b83ffc51769d3946de8660b0583ccc672079f08d80db9b93178c12c1c374279
3
+ metadata.gz: '09c2c291bce3fdf441d7c93dacf44883ca47804db6abb38d78b3ea70a412deaf'
4
+ data.tar.gz: 8bd10b6c57adedb5e655b23688088a1be0d8c2e97dca6300ef7470b1a28c8c33
5
5
  SHA512:
6
- metadata.gz: 54bf09a092ed87b269621100c55edadd8fd0591f41f25270672f27cf6837d3767dff33a3cff6bb6fe4315c90cbb5d596805b6ce6d2ec055eb5d0cd0f73e7d5d6
7
- data.tar.gz: b967fc6beb11b41889b0574b937b94532910acba29e9b349e2ec40289fcb57bd9096ea4cf06756a5db05acdc5f9a13a51c1c3474fb8fe85709e1c68fafe703dc
6
+ metadata.gz: ba347bb7844c93e96b5601f728267df346ba28b78458d77e0ea8a8f83ceb77fc83127ddad0dd164704f8bad95701df1838ac636e8c59aaa356bab07c63e5d58d
7
+ data.tar.gz: 90b4555d3b69f2f0489dff54e6f326b4ee57404989e1ef7068a2b91d8761541ddf42be7154ed6e0a7b8e5f536d6408441b3412997731c3868c603fb3e25a7122
@@ -23,7 +23,7 @@ module CollavreOpenclaw
23
23
 
24
24
  def authenticated?
25
25
  respond_to?(:current_user, true) && current_user.present?
26
- rescue
26
+ rescue StandardError
27
27
  false
28
28
  end
29
29
  end
@@ -12,8 +12,8 @@ module CollavreOpenclaw
12
12
  end
13
13
  end
14
14
 
15
- # @param messages_input [Hash, Array] Hash { messages:, first_message:, context_changed: }
16
- # from MessageBuilder, or a plain Array from standalone callers (e.g., CompressJob).
15
+ # @param messages_input [Hash, Array] Hash { messages:, first_message:, context_changed:, system_prompt: }
16
+ # from SessionContextResolver, or a plain Array from standalone callers (e.g., CompressJob).
17
17
  def chat(messages_input, tools: [], &block)
18
18
  normalized_vendor = vendor.to_s.downcase
19
19
  messages_data = normalize_messages_input(messages_input)
@@ -23,10 +23,13 @@ module CollavreOpenclaw
23
23
 
24
24
  if adapter_class
25
25
  # Use the custom adapter (tools not supported for OpenClaw)
26
+ # Prefer resolved system_prompt from SessionContextResolver over instance default.
27
+ # key?(:system_prompt) distinguishes "not provided" (Array input) from "explicitly nil" (incremental session).
28
+ resolved_system_prompt = messages_data.key?(:system_prompt) ? messages_data[:system_prompt] : system_prompt
26
29
  user = context&.dig(:user)
27
30
  adapter = adapter_class.new(
28
31
  user: user,
29
- system_prompt: system_prompt,
32
+ system_prompt: resolved_system_prompt,
30
33
  context: context
31
34
  )
32
35
 
@@ -205,7 +205,7 @@ module CollavreOpenclaw
205
205
  next unless @idle_check_counter >= 60 # Run check every ~60 seconds
206
206
  @idle_check_counter = 0
207
207
  check_idle_connections!
208
- rescue => e
208
+ rescue StandardError => e
209
209
  Rails.logger.error("[CollavreOpenclaw::ConnectionManager] Idle checker error: #{e.message}")
210
210
  end
211
211
  end
@@ -3,9 +3,11 @@ require "json"
3
3
 
4
4
  module CollavreOpenclaw
5
5
  class OpenclawAdapter
6
- # Adapter for OpenClaw AI Gateway
6
+ # Pure transport adapter for OpenClaw AI Gateway.
7
+ # Session context filtering (full vs incremental) is handled upstream
8
+ # by SessionContextResolver — this adapter sends exactly what it receives.
7
9
  #
8
- # Supports two transport modes:
10
+ # Transport modes:
9
11
  # 1. WebSocket (primary) - via faye-websocket + EventMachine
10
12
  # 2. HTTP (fallback) - via Faraday POST /v1/chat/completions
11
13
  #
@@ -72,27 +74,12 @@ module CollavreOpenclaw
72
74
 
73
75
  private
74
76
 
75
- CONTEXT_KINDS = %i[creative_context context_creative referenced_creative].freeze
76
-
77
77
  def parse_messages_data!(data)
78
78
  @all_messages = data[:messages] || []
79
79
  @first_message = data[:first_message]
80
80
  @context_changed = data[:context_changed]
81
81
  end
82
82
 
83
- def context_messages
84
- @all_messages.select { |m| CONTEXT_KINDS.include?(m[:kind]) }
85
- end
86
-
87
- def trigger_message
88
- @all_messages.find { |m| m[:kind] == :trigger }
89
- end
90
-
91
- # Send system prompt and context on first message or when they changed.
92
- def include_full_context?
93
- @first_message || @context_changed
94
- end
95
-
96
83
  # ─────────────────────────────────────────────
97
84
  # WebSocket transport
98
85
  # ─────────────────────────────────────────────
@@ -159,42 +146,24 @@ module CollavreOpenclaw
159
146
  end
160
147
  end
161
148
 
162
- # Build WebSocket chat.send payload.
163
- #
164
- # Token optimization: only includes system prompt and creative context on
165
- # the first message or when context has changed. The Gateway maintains its
166
- # own session history, so chat history is never sent — only the trigger.
167
149
  def build_ws_chat_payload
168
- trigger = trigger_message
169
150
  {
170
151
  message: format_message_for_ws,
171
- attachments: trigger ? extract_ws_attachments([ trigger ]).presence : nil
152
+ attachments: extract_ws_attachments(@all_messages).presence
172
153
  }
173
154
  end
174
155
 
175
- # Format messages for WebSocket chat.send text payload.
176
- #
177
- # On first message (or context change):
178
- # [system prompt] + [creative context] + [trigger]
179
- # On subsequent messages:
180
- # [trigger only]
181
- #
182
- # Chat history is NOT included — the Gateway's SessionManager tracks
183
- # conversation turns automatically.
156
+ # SessionContextResolver already decided what to include.
157
+ # We just format and send everything we received.
184
158
  def format_message_for_ws
185
159
  parts = []
160
+ parts << @system_prompt if @system_prompt.present?
186
161
 
187
- if include_full_context?
188
- parts << @system_prompt if @system_prompt.present?
189
- context_messages.each do |m|
190
- text = extract_message_text(m)
191
- parts << text if text.present?
192
- end
162
+ @all_messages.each do |m|
163
+ text = extract_message_text(m)
164
+ parts << text if text.present?
193
165
  end
194
166
 
195
- trigger = trigger_message
196
- parts << extract_message_text(trigger) if trigger
197
-
198
167
  parts.join("\n\n")
199
168
  end
200
169
 
@@ -347,28 +316,14 @@ module CollavreOpenclaw
347
316
  # HTTP payload building
348
317
  # ─────────────────────────────────────────────
349
318
 
350
- # Build HTTP payload with token optimization.
351
- #
352
- # On first message (or context change):
353
- # system prompt + creative context + trigger
354
- # On subsequent messages:
355
- # trigger only
356
- #
357
- # Chat history is NOT included — the Gateway's SessionManager tracks
358
- # conversation turns via the stable session key.
319
+ # SessionContextResolver already decided what to include.
359
320
  def build_payload
360
321
  agent_id = extract_agent_id_from_email
361
322
  model_value = agent_id.present? ? "openclaw:#{agent_id}" : "openclaw"
362
323
 
363
324
  formatted = []
364
-
365
- if include_full_context?
366
- formatted << { role: "system", content: @system_prompt } if @system_prompt.present?
367
- context_messages.each { |m| formatted << format_single_message(m) }
368
- end
369
-
370
- trigger = trigger_message
371
- formatted << format_single_message(trigger) if trigger
325
+ formatted << { role: "system", content: @system_prompt } if @system_prompt.present?
326
+ @all_messages.each { |m| formatted << format_single_message(m) }
372
327
 
373
328
  {
374
329
  model: model_value,
@@ -94,7 +94,7 @@ module CollavreOpenclaw
94
94
  EmReactor.next_tick do
95
95
  begin
96
96
  do_connect!(queue)
97
- rescue => e
97
+ rescue StandardError => e
98
98
  queue.push({ error: e.message })
99
99
  end
100
100
  end
@@ -659,7 +659,7 @@ module CollavreOpenclaw
659
659
  schedule_reconnect!
660
660
  end
661
661
  end
662
- rescue => e
662
+ rescue StandardError => e
663
663
  Rails.logger.error("[CollavreOpenclaw::WS] RECONNECT gateway=#{url} state=fail reason=#{e.message}")
664
664
  schedule_reconnect!
665
665
  end
@@ -27,7 +27,11 @@ module CollavreOpenclaw
27
27
 
28
28
  def initialize
29
29
  @open_timeout = ENV.fetch("OPENCLAW_OPEN_TIMEOUT", 10).to_i
30
- @read_timeout = ENV.fetch("OPENCLAW_READ_TIMEOUT", 180).to_i # 3 minutes for AI responses
30
+ @read_timeout = begin
31
+ Collavre::SystemSetting.llm_request_timeout_seconds
32
+ rescue StandardError
33
+ 1800
34
+ end
31
35
  @max_retries = ENV.fetch("OPENCLAW_MAX_RETRIES", 2).to_i
32
36
  @ws_idle_timeout = ENV.fetch("OPENCLAW_WS_IDLE_TIMEOUT", 1800).to_i # 30 minutes
33
37
  @ws_reconnect_max = ENV.fetch("OPENCLAW_WS_RECONNECT_MAX", 10).to_i
@@ -50,7 +50,7 @@ module CollavreOpenclaw
50
50
  ConnectionManager.instance.disconnect_all
51
51
  end
52
52
  EmReactor.stop! if EmReactor.running?
53
- rescue => e
53
+ rescue StandardError => e
54
54
  Rails.logger.warn("[CollavreOpenclaw] Shutdown cleanup error: #{e.message}")
55
55
  end
56
56
  end
@@ -1,3 +1,3 @@
1
1
  module CollavreOpenclaw
2
- VERSION = "0.6.0"
2
+ VERSION = "0.6.1"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: collavre_openclaw
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.6.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Collavre