openclacky 1.3.5 → 1.3.7
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/CHANGELOG.md +42 -0
- data/lib/clacky/agent/message_compressor.rb +32 -8
- data/lib/clacky/agent/message_compressor_helper.rb +113 -12
- data/lib/clacky/agent.rb +8 -4
- data/lib/clacky/agent_profile.rb +121 -53
- data/lib/clacky/brand_config.rb +309 -6
- data/lib/clacky/cli.rb +4 -58
- data/lib/clacky/default_extensions/coding/ext.yml +18 -0
- data/lib/clacky/default_extensions/ext-studio/agents/ext-developer/system_prompt.md +95 -0
- data/lib/clacky/default_extensions/ext-studio/api/handler.rb +254 -0
- data/lib/clacky/default_extensions/ext-studio/ext.yml +32 -0
- data/lib/clacky/default_extensions/ext-studio/panels/studio/view.js +1269 -0
- data/lib/clacky/default_extensions/ext-studio/skills/ext-debug/SKILL.md +71 -0
- data/lib/clacky/default_extensions/ext-studio/skills/ext-publish/SKILL.md +74 -0
- data/lib/clacky/default_extensions/ext-studio/skills/ext-scaffold/SKILL.md +65 -0
- data/lib/clacky/default_extensions/general/ext.yml +18 -0
- data/lib/clacky/default_extensions/git/ext.yml +12 -0
- data/lib/clacky/{default_agents/_panels/git/panel.js → default_extensions/git/panels/git/view.js} +1 -2
- data/lib/clacky/default_extensions/meeting/{handler.rb → api/handler.rb} +78 -26
- data/lib/clacky/default_extensions/meeting/ext.yml +15 -0
- data/lib/clacky/default_extensions/meeting/{meeting.js → panels/meeting/view.js} +266 -89
- data/lib/clacky/default_extensions/meeting/skills/meeting-summarizer/SKILL.md +2 -1
- data/lib/clacky/default_extensions/time_machine/ext.yml +12 -0
- data/lib/clacky/{default_agents/_panels/time_machine/panel.js → default_extensions/time_machine/panels/time_machine/view.js} +58 -47
- data/lib/clacky/default_skills/channel-manager/discord_setup.rb +1 -1
- data/lib/clacky/default_skills/extend-openclacky/SKILL.md +83 -18
- data/lib/clacky/{api_extension.rb → extension/api_extension.rb} +27 -11
- data/lib/clacky/extension/api_loader.rb +136 -0
- data/lib/clacky/extension/cli_commands.rb +226 -0
- data/lib/clacky/{server/api_extension_dispatcher.rb → extension/dispatcher.rb} +22 -9
- data/lib/clacky/extension/hook_loader.rb +77 -0
- data/lib/clacky/extension/loader.rb +483 -0
- data/lib/clacky/extension/packager.rb +226 -0
- data/lib/clacky/{patch_loader.rb → extension/patch_loader.rb} +45 -0
- data/lib/clacky/extension/scaffold/template_renderer.rb +64 -0
- data/lib/clacky/extension/scaffold/templates/full/README.md.erb +48 -0
- data/lib/clacky/extension/scaffold/templates/full/agents/designer.md +5 -0
- data/lib/clacky/extension/scaffold/templates/full/api/handler.rb.erb +16 -0
- data/lib/clacky/extension/scaffold/templates/full/channels/noop.rb.erb +40 -0
- data/lib/clacky/extension/scaffold/templates/full/ext.yml.erb +41 -0
- data/lib/clacky/extension/scaffold/templates/full/hooks/audit.rb +9 -0
- data/lib/clacky/extension/scaffold/templates/full/panels/dashboard/view.js.erb +194 -0
- data/lib/clacky/extension/scaffold/templates/full/patches/audit.rb +15 -0
- data/lib/clacky/extension/scaffold/templates/full/skills/__slug__-skill/SKILL.md.erb +8 -0
- data/lib/clacky/extension/scaffold/templates/hello/api/handler.rb.erb +9 -0
- data/lib/clacky/extension/scaffold/templates/hello/ext.yml.erb +12 -0
- data/lib/clacky/extension/scaffold/templates/hello/panels/hello/view.js.erb +31 -0
- data/lib/clacky/extension/scaffold.rb +55 -0
- data/lib/clacky/extension/verifier.rb +196 -0
- data/lib/clacky/identity.rb +70 -0
- data/lib/clacky/locales/en.rb +19 -1
- data/lib/clacky/locales/zh.rb +19 -1
- data/lib/clacky/platform_http_client.rb +18 -15
- data/lib/clacky/server/channel/extension_adapter_loader.rb +32 -0
- data/lib/clacky/server/channel.rb +6 -0
- data/lib/clacky/server/http_server.rb +435 -263
- data/lib/clacky/server/session_registry.rb +59 -3
- data/lib/clacky/session_manager.rb +35 -4
- data/lib/clacky/skill_loader.rb +28 -1
- data/lib/clacky/ui2/layout_manager.rb +0 -5
- data/lib/clacky/ui2/progress_handle.rb +0 -3
- data/lib/clacky/ui2/ui_controller.rb +9 -15
- data/lib/clacky/version.rb +1 -1
- data/lib/clacky/web/app.css +782 -554
- data/lib/clacky/web/app.js +63 -15
- data/lib/clacky/web/auth.js +2 -0
- data/lib/clacky/web/components/notify.js +2 -0
- data/lib/clacky/web/components/sidebar.js +2 -8
- data/lib/clacky/web/core/ext.js +316 -79
- data/lib/clacky/web/features/backup/store.js +24 -0
- data/lib/clacky/web/features/backup/view.js +49 -23
- data/lib/clacky/web/features/brand/view.js +13 -5
- data/lib/clacky/web/features/extensions/store.js +184 -0
- data/lib/clacky/web/features/extensions/view.js +389 -0
- data/lib/clacky/web/features/new-session/store.js +186 -0
- data/lib/clacky/web/features/new-session/view.js +319 -0
- data/lib/clacky/web/features/share/view.js +63 -14
- data/lib/clacky/web/features/skills/store.js +3 -1
- data/lib/clacky/web/features/skills/view.js +1 -1
- data/lib/clacky/web/features/tasks/view.js +88 -27
- data/lib/clacky/web/features/trash/store.js +24 -6
- data/lib/clacky/web/features/trash/view.js +46 -9
- data/lib/clacky/web/features/workspace/store.js +2 -0
- data/lib/clacky/web/features/workspace/view.js +0 -1
- data/lib/clacky/web/i18n.js +140 -108
- data/lib/clacky/web/index.html +190 -214
- data/lib/clacky/web/sessions.js +99 -304
- data/lib/clacky/web/settings.js +1 -1
- data/lib/clacky/web/skills.js +2 -0
- data/lib/clacky/web/theme.js +2 -0
- data/lib/clacky/web/ws-dispatcher.js +2 -1
- data/lib/clacky/web/ws.js +2 -0
- data/lib/clacky.rb +21 -10
- metadata +55 -24
- data/benchmark/runner.rb +0 -441
- data/lib/clacky/api_extension_loader.rb +0 -168
- data/lib/clacky/default_agents/SOUL.md +0 -3
- data/lib/clacky/default_agents/USER.md +0 -1
- data/lib/clacky/default_agents/coding/profile.yml +0 -5
- data/lib/clacky/default_agents/coding/webui/.gitkeep +0 -0
- data/lib/clacky/default_agents/general/profile.yml +0 -2
- data/lib/clacky/default_extensions/meeting/meta.yml +0 -3
- data/lib/clacky/web/features/creator/store.js +0 -81
- data/lib/clacky/web/features/creator/view.js +0 -380
- /data/lib/clacky/{default_agents → default_extensions/coding/agents}/coding/system_prompt.md +0 -0
- /data/lib/clacky/{default_agents → default_extensions/general/agents}/general/system_prompt.md +0 -0
- /data/lib/clacky/{default_agents/base_prompt.md → prompts/base.md} +0 -0
|
@@ -49,6 +49,7 @@ module Clacky
|
|
|
49
49
|
agent: nil,
|
|
50
50
|
ui: nil,
|
|
51
51
|
thread: nil,
|
|
52
|
+
epoch: 0,
|
|
52
53
|
idle_timer: nil,
|
|
53
54
|
pending_task: nil,
|
|
54
55
|
pending_working_dir: nil
|
|
@@ -116,8 +117,15 @@ module Clacky
|
|
|
116
117
|
src = (session_data[:source] || "manual").to_s
|
|
117
118
|
next if counts[src] >= n
|
|
118
119
|
next if exist?(session_data[:session_id])
|
|
119
|
-
|
|
120
|
-
|
|
120
|
+
begin
|
|
121
|
+
@session_restorer.call(session_data)
|
|
122
|
+
counts[src] += 1
|
|
123
|
+
rescue => e
|
|
124
|
+
Clacky::Logger.warn(
|
|
125
|
+
"[SessionRegistry] skip session #{session_data[:session_id]}: " \
|
|
126
|
+
"#{e.class}: #{e.message}"
|
|
127
|
+
)
|
|
128
|
+
end
|
|
121
129
|
end
|
|
122
130
|
end
|
|
123
131
|
|
|
@@ -138,6 +146,40 @@ module Clacky
|
|
|
138
146
|
end
|
|
139
147
|
end
|
|
140
148
|
|
|
149
|
+
# Atomically bump the session's task epoch and return the new value.
|
|
150
|
+
# Each user message that starts a task claims a fresh epoch; a stale task
|
|
151
|
+
# thread (interrupted but not yet dead) compares its epoch against the
|
|
152
|
+
# current one and discards any side effects (status writes, broadcasts)
|
|
153
|
+
# once it has been superseded.
|
|
154
|
+
def claim_epoch(session_id)
|
|
155
|
+
@mutex.synchronize do
|
|
156
|
+
session = @sessions[session_id]
|
|
157
|
+
return nil unless session
|
|
158
|
+
|
|
159
|
+
session[:epoch] = session[:epoch].to_i + 1
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# Current task epoch for a session (0 if none / unknown).
|
|
164
|
+
def current_epoch(session_id)
|
|
165
|
+
@mutex.synchronize { @sessions[session_id]&.fetch(:epoch, 0).to_i }
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
# Update fields only if the caller still owns the current epoch. Returns
|
|
169
|
+
# true if the update was applied, false if the epoch was stale (a newer
|
|
170
|
+
# task has taken over) or the session is gone.
|
|
171
|
+
def update_if_epoch(session_id, epoch, **fields)
|
|
172
|
+
@mutex.synchronize do
|
|
173
|
+
session = @sessions[session_id]
|
|
174
|
+
return false unless session
|
|
175
|
+
return false unless session[:epoch].to_i == epoch.to_i
|
|
176
|
+
|
|
177
|
+
fields[:updated_at] = Time.now
|
|
178
|
+
session.merge!(fields)
|
|
179
|
+
true
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
|
|
141
183
|
# Return a session list from disk enriched with live registry status.
|
|
142
184
|
# Sorted by created_at descending (newest first).
|
|
143
185
|
#
|
|
@@ -161,7 +203,7 @@ module Clacky
|
|
|
161
203
|
# [ ...all_pinned_matching (newest-first), ...non_pinned (newest-first, limited) ]
|
|
162
204
|
#
|
|
163
205
|
# source and profile are orthogonal — either can be nil independently.
|
|
164
|
-
def list(limit: nil, before: nil, q: nil, q_scope: "name", date: nil, type: nil, include_pinned: true)
|
|
206
|
+
def list(limit: nil, before: nil, q: nil, q_scope: "name", date: nil, type: nil, exclude_type: nil, include_pinned: true)
|
|
165
207
|
return [] unless @session_manager
|
|
166
208
|
|
|
167
209
|
live = @mutex.synchronize do
|
|
@@ -196,6 +238,12 @@ module Clacky
|
|
|
196
238
|
end
|
|
197
239
|
end
|
|
198
240
|
|
|
241
|
+
# ── exclude_type filter ───────────────────────────────────────────────
|
|
242
|
+
if exclude_type
|
|
243
|
+
excluded = Array(exclude_type)
|
|
244
|
+
all = all.reject { |s| excluded.include?(s_source(s)) }
|
|
245
|
+
end
|
|
246
|
+
|
|
199
247
|
# ── date filter (YYYY-MM-DD, matches created_at prefix) ──────────────
|
|
200
248
|
all = all.select { |s| s[:created_at].to_s.start_with?(date) } if date
|
|
201
249
|
|
|
@@ -349,6 +397,14 @@ module Clacky
|
|
|
349
397
|
@session_manager.all_sessions.count { |s| s_source(s) == "cron" }
|
|
350
398
|
end
|
|
351
399
|
|
|
400
|
+
# Count + latest updated_at for cron sessions (used by sidebar virtual entry).
|
|
401
|
+
def cron_stats
|
|
402
|
+
return { count: 0, latest_updated_at: nil } unless @session_manager
|
|
403
|
+
cron_all = @session_manager.all_sessions.select { |s| s_source(s) == "cron" }
|
|
404
|
+
latest = cron_all.map { |s| s[:updated_at] || s[:created_at] }.compact.max
|
|
405
|
+
{ count: cron_all.size, latest_updated_at: latest }
|
|
406
|
+
end
|
|
407
|
+
|
|
352
408
|
# Delete a session from registry (and interrupt its thread).
|
|
353
409
|
def delete(session_id)
|
|
354
410
|
@mutex.synchronize do
|
|
@@ -35,7 +35,7 @@ module Clacky
|
|
|
35
35
|
|
|
36
36
|
# Keep only the most recent 200 sessions (best-effort, never block save)
|
|
37
37
|
begin
|
|
38
|
-
cleanup_by_count(keep: 200)
|
|
38
|
+
cleanup_by_count(keep: 200, keep_cron: 200)
|
|
39
39
|
rescue Exception # rubocop:disable Lint/RescueException
|
|
40
40
|
# Cleanup is non-critical; swallow all errors (including AgentInterrupted)
|
|
41
41
|
end
|
|
@@ -163,6 +163,33 @@ module Clacky
|
|
|
163
163
|
chunk_path
|
|
164
164
|
end
|
|
165
165
|
|
|
166
|
+
# Read the raw markdown of a chunk file. Returns nil if missing.
|
|
167
|
+
def read_chunk(chunk_path)
|
|
168
|
+
return nil unless chunk_path && File.exist?(chunk_path)
|
|
169
|
+
File.read(chunk_path)
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
# Split raw chunk markdown into [front_matter_hash, body_string].
|
|
173
|
+
# front_matter_hash preserves insertion order; body is everything after
|
|
174
|
+
# the closing "---". Returns [nil, raw] when there is no leading block.
|
|
175
|
+
def split_chunk_md(raw)
|
|
176
|
+
return [nil, raw.to_s] unless raw.to_s.start_with?("---")
|
|
177
|
+
|
|
178
|
+
fm_end = raw.index("\n---\n", 4)
|
|
179
|
+
return [nil, raw] unless fm_end
|
|
180
|
+
|
|
181
|
+
fm_text = raw[4...fm_end]
|
|
182
|
+
body = raw[(fm_end + 5)..] || ""
|
|
183
|
+
|
|
184
|
+
fm = {}
|
|
185
|
+
fm_text.each_line do |line|
|
|
186
|
+
k, _, v = line.chomp.partition(":")
|
|
187
|
+
next if k.strip.empty?
|
|
188
|
+
fm[k.strip] = v.strip
|
|
189
|
+
end
|
|
190
|
+
[fm, body]
|
|
191
|
+
end
|
|
192
|
+
|
|
166
193
|
# All sessions from disk, newest-first (sorted by last activity / updated_at,
|
|
167
194
|
# falling back to created_at for legacy sessions without updated_at).
|
|
168
195
|
# Optional filters:
|
|
@@ -305,11 +332,15 @@ module Clacky
|
|
|
305
332
|
# are soft-deleted (moved to the session trash, recoverable). Pinned
|
|
306
333
|
# sessions are never deleted and do not count toward the cap.
|
|
307
334
|
# Returns count of soft-deleted sessions.
|
|
308
|
-
def cleanup_by_count(keep:)
|
|
335
|
+
def cleanup_by_count(keep:, keep_cron: 200)
|
|
309
336
|
non_pinned = all_sessions.reject { |s| s[:pinned] } # already sorted newest-first
|
|
310
|
-
return 0 if non_pinned.size <= keep
|
|
311
337
|
|
|
312
|
-
|
|
338
|
+
cron, regular = non_pinned.partition { |s| s[:source].to_s == "cron" }
|
|
339
|
+
|
|
340
|
+
victims = []
|
|
341
|
+
victims += regular[keep..] if regular.size > keep
|
|
342
|
+
victims += cron[keep_cron..] if cron.size > keep_cron
|
|
343
|
+
|
|
313
344
|
victims.each { |session| soft_delete(session[:session_id]) }
|
|
314
345
|
victims.size
|
|
315
346
|
end
|
data/lib/clacky/skill_loader.rb
CHANGED
|
@@ -12,6 +12,7 @@ module Clacky
|
|
|
12
12
|
# Skill discovery locations (in priority order: lower index = lower priority)
|
|
13
13
|
LOCATIONS = [
|
|
14
14
|
:default, # gem's built-in default skills (lowest priority)
|
|
15
|
+
:extension, # contributes.skills declared in ext.yml containers
|
|
15
16
|
:global_clacky, # ~/.clacky/skills/
|
|
16
17
|
:project_clacky, # .clacky/skills/ (highest priority among plain skills)
|
|
17
18
|
:brand # ~/.clacky/brand_skills/ (encrypted, license-gated)
|
|
@@ -62,6 +63,7 @@ module Clacky
|
|
|
62
63
|
clear
|
|
63
64
|
|
|
64
65
|
load_default_skills
|
|
66
|
+
load_extension_skills
|
|
65
67
|
load_global_clacky_skills
|
|
66
68
|
|
|
67
69
|
# Only load project-level skills when working_dir is explicitly provided.
|
|
@@ -401,7 +403,7 @@ module Clacky
|
|
|
401
403
|
# @return [Skill, nil] nil when the skill was rejected (duplicate/limit)
|
|
402
404
|
private def register_skill(skill, source:)
|
|
403
405
|
id = skill.identifier
|
|
404
|
-
priority_order = %i[default global_clacky project_clacky brand]
|
|
406
|
+
priority_order = %i[default extension global_clacky project_clacky brand]
|
|
405
407
|
|
|
406
408
|
# --- duplicate check ---
|
|
407
409
|
if (existing = @skills[id])
|
|
@@ -472,5 +474,30 @@ module Clacky
|
|
|
472
474
|
end
|
|
473
475
|
end
|
|
474
476
|
end
|
|
477
|
+
|
|
478
|
+
# Load skills declared via `contributes.skills` in ext.yml containers.
|
|
479
|
+
# Protected (encrypted) units are skipped here — they are listed by
|
|
480
|
+
# ExtensionLoader for display/management but their decryption still flows
|
|
481
|
+
# through the legacy brand_skill chain (see load_brand_skills).
|
|
482
|
+
private def load_extension_skills
|
|
483
|
+
result = Clacky::ExtensionLoader.last_result
|
|
484
|
+
return unless result&.skills
|
|
485
|
+
|
|
486
|
+
result.skills.each do |unit|
|
|
487
|
+
next if unit.spec["protected"] || unit.spec["encrypted"]
|
|
488
|
+
|
|
489
|
+
skill_dir_abs = unit.spec["skill_dir_abs"]
|
|
490
|
+
next unless File.directory?(skill_dir_abs) && File.file?(File.join(skill_dir_abs, "SKILL.md"))
|
|
491
|
+
|
|
492
|
+
begin
|
|
493
|
+
skill = Skill.new(Pathname.new(skill_dir_abs))
|
|
494
|
+
register_skill(skill, source: :extension)
|
|
495
|
+
rescue Clacky::AgentError => e
|
|
496
|
+
@errors << "Error loading extension skill '#{unit.id}' from #{skill_dir_abs}: #{e.message}"
|
|
497
|
+
rescue StandardError => e
|
|
498
|
+
@errors << "Unexpected error loading extension skill '#{unit.id}' from #{skill_dir_abs}: #{e.message}"
|
|
499
|
+
end
|
|
500
|
+
end
|
|
501
|
+
end
|
|
475
502
|
end
|
|
476
503
|
end
|
|
@@ -120,28 +120,23 @@ module Clacky
|
|
|
120
120
|
@render_mutex.synchronize do
|
|
121
121
|
entry = @buffer.entry_by_id(id)
|
|
122
122
|
if entry.nil?
|
|
123
|
-
Clacky::Logger.warn("[ph_debug] replace_entry_nil", id: id, content: content.to_s[0, 120])
|
|
124
123
|
return
|
|
125
124
|
end
|
|
126
125
|
if entry.committed
|
|
127
|
-
Clacky::Logger.warn("[ph_debug] replace_entry_committed", id: id, content: content.to_s[0, 120])
|
|
128
126
|
return
|
|
129
127
|
end
|
|
130
128
|
if (entry.committed_line_offset || 0) > 0
|
|
131
|
-
Clacky::Logger.warn("[ph_debug] replace_entry_partial", id: id, offset: entry.committed_line_offset, content: content.to_s[0, 120])
|
|
132
129
|
return
|
|
133
130
|
end
|
|
134
131
|
|
|
135
132
|
old_lines = entry.lines.dup
|
|
136
133
|
new_lines = wrap_content_to_lines(content)
|
|
137
134
|
if old_lines == new_lines
|
|
138
|
-
Clacky::Logger.warn("[ph_debug] replace_entry_same", id: id)
|
|
139
135
|
screen.flush
|
|
140
136
|
return
|
|
141
137
|
end
|
|
142
138
|
@buffer.replace(id, new_lines)
|
|
143
139
|
is_tail = @buffer.live_entries.last&.id == id
|
|
144
|
-
Clacky::Logger.warn("[ph_debug] replace_entry_paint", id: id, is_tail: is_tail, old_n: old_lines.length, new_n: new_lines.length, content: content.to_s[0, 120])
|
|
145
140
|
|
|
146
141
|
unless @fullscreen_mode
|
|
147
142
|
# repaint_entry_in_place relies on the entry being the tail of
|
|
@@ -182,7 +182,6 @@ module Clacky
|
|
|
182
182
|
# @param final_message [String, nil] Optional override for the last
|
|
183
183
|
# frame. If nil, the handle composes "<message>… (<elapsed>s)".
|
|
184
184
|
def finish(final_message: nil)
|
|
185
|
-
Clacky::Logger.warn("[ph_debug] finish_entry", oid: object_id, state: @state, unreg: @unregistered, msg: @message, eid: @entry_id)
|
|
186
185
|
snapshot = @monitor.synchronize do
|
|
187
186
|
return if @unregistered
|
|
188
187
|
first_close = @state == :running
|
|
@@ -201,10 +200,8 @@ module Clacky
|
|
|
201
200
|
else
|
|
202
201
|
compose_final_frame(snapshot[:message], snapshot[:elapsed])
|
|
203
202
|
end
|
|
204
|
-
Clacky::Logger.warn("[ph_debug] finish_unregister", oid: object_id, eid: @entry_id, first_close: snapshot[:first_close], final_frame: final_frame.to_s[0, 200])
|
|
205
203
|
@owner.unregister_progress(self, final_frame: final_frame)
|
|
206
204
|
@monitor.synchronize { @unregistered = true }
|
|
207
|
-
Clacky::Logger.warn("[ph_debug] finish_done", oid: object_id)
|
|
208
205
|
end
|
|
209
206
|
alias_method :cancel, :finish
|
|
210
207
|
|
|
@@ -664,22 +664,13 @@ module Clacky
|
|
|
664
664
|
|
|
665
665
|
# Called by ProgressHandle#finish.
|
|
666
666
|
def unregister_progress(handle, final_frame:)
|
|
667
|
-
Clacky::Logger.warn("[ph_debug] unreg_entry", oid: handle.object_id, eid: handle.entry_id, top: @progress_stack.last == handle, stack_size: @progress_stack.size, ff: final_frame.to_s[0, 200])
|
|
668
667
|
@progress_mutex.synchronize do
|
|
669
|
-
# If this handle still holds its entry (it's currently top), we
|
|
670
|
-
# render one last frame there and release the id. If it was
|
|
671
|
-
# previously detached (someone above is still active), its entry
|
|
672
|
-
# is already gone and the final_frame is simply dropped.
|
|
673
668
|
if handle.entry_id
|
|
674
669
|
if final_frame && !final_frame.to_s.strip.empty?
|
|
675
|
-
Clacky::Logger.warn("[ph_debug] unreg_update_entry", oid: handle.object_id, eid: handle.entry_id)
|
|
676
670
|
update_entry(handle.entry_id, @renderer.render_progress(final_frame))
|
|
677
671
|
else
|
|
678
|
-
Clacky::Logger.warn("[ph_debug] unreg_remove_entry", oid: handle.object_id, eid: handle.entry_id)
|
|
679
672
|
remove_entry(handle.entry_id)
|
|
680
673
|
end
|
|
681
|
-
else
|
|
682
|
-
Clacky::Logger.warn("[ph_debug] unreg_no_entry_id", oid: handle.object_id)
|
|
683
674
|
end
|
|
684
675
|
|
|
685
676
|
@progress_stack.delete(handle)
|
|
@@ -1094,12 +1085,15 @@ module Clacky
|
|
|
1094
1085
|
queue.push(:timeout) unless session[:intervened]
|
|
1095
1086
|
end
|
|
1096
1087
|
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1088
|
+
begin
|
|
1089
|
+
result = queue.pop
|
|
1090
|
+
ensure
|
|
1091
|
+
session[:watchdog].kill if session[:watchdog]&.alive?
|
|
1092
|
+
@feedback_countdown = nil
|
|
1093
|
+
@layout.remove_entry(entry_id) if entry_id
|
|
1094
|
+
@layout.recalculate_layout
|
|
1095
|
+
@layout.render_all
|
|
1096
|
+
end
|
|
1103
1097
|
|
|
1104
1098
|
if result == :timeout
|
|
1105
1099
|
append_output(theme.format_text(" No response — continuing automatically.", :thinking))
|
data/lib/clacky/version.rb
CHANGED