openclacky 1.2.8 → 1.2.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/CHANGELOG.md +35 -0
- data/lib/clacky/agent/llm_caller.rb +3 -0
- data/lib/clacky/agent/message_compressor_helper.rb +6 -5
- data/lib/clacky/agent/session_serializer.rb +4 -0
- data/lib/clacky/agent.rb +9 -0
- data/lib/clacky/agent_config.rb +111 -8
- data/lib/clacky/brand_config.rb +1 -0
- data/lib/clacky/cli.rb +49 -22
- data/lib/clacky/client.rb +6 -2
- data/lib/clacky/default_skills/channel-manager/SKILL.md +33 -110
- data/lib/clacky/default_skills/media-gen/SKILL.md +128 -0
- data/lib/clacky/idle_compression_timer.rb +38 -15
- data/lib/clacky/media/base.rb +68 -0
- data/lib/clacky/media/gemini.rb +36 -0
- data/lib/clacky/media/generator.rb +78 -0
- data/lib/clacky/media/openai_compat.rb +168 -0
- data/lib/clacky/providers.rb +89 -2
- data/lib/clacky/rich_ui_controller.rb +1549 -0
- data/lib/clacky/server/channel/adapters/weixin/adapter.rb +24 -2
- data/lib/clacky/server/channel/channel_manager.rb +89 -2
- data/lib/clacky/server/http_server.rb +334 -29
- data/lib/clacky/session_manager.rb +9 -8
- data/lib/clacky/telemetry.rb +26 -6
- data/lib/clacky/ui2/layout_manager.rb +11 -7
- data/lib/clacky/ui2/ui_controller.rb +2 -2
- data/lib/clacky/ui_interface.rb +1 -1
- data/lib/clacky/utils/model_pricing.rb +75 -53
- data/lib/clacky/version.rb +1 -1
- data/lib/clacky/web/app.css +393 -14
- data/lib/clacky/web/billing.js +1 -1
- data/lib/clacky/web/i18n.js +86 -4
- data/lib/clacky/web/index.html +23 -3
- data/lib/clacky/web/model-tester.js +58 -0
- data/lib/clacky/web/onboard.js +17 -30
- data/lib/clacky/web/sessions.js +443 -2
- data/lib/clacky/web/settings.js +372 -97
- data/lib/clacky/web/workspace.js +9 -1
- data/lib/clacky.rb +3 -0
- data/scripts/build/lib/network.sh +61 -30
- data/scripts/install.ps1 +16 -4
- data/scripts/install.sh +61 -30
- data/scripts/install_browser.sh +61 -30
- data/scripts/install_full.sh +61 -30
- data/scripts/install_rails_deps.sh +61 -30
- data/scripts/install_system_deps.sh +61 -30
- metadata +12 -3
- data/lib/clacky/default_skills/channel-manager/feishu_setup.rb +0 -574
|
@@ -179,16 +179,17 @@ module Clacky
|
|
|
179
179
|
deleted
|
|
180
180
|
end
|
|
181
181
|
|
|
182
|
-
# Keep only the most recent N sessions by created_at;
|
|
183
|
-
#
|
|
182
|
+
# Keep only the most recent N non-pinned sessions by created_at; the rest
|
|
183
|
+
# are soft-deleted (moved to the session trash, recoverable). Pinned
|
|
184
|
+
# sessions are never deleted and do not count toward the cap.
|
|
185
|
+
# Returns count of soft-deleted sessions.
|
|
184
186
|
def cleanup_by_count(keep:)
|
|
185
|
-
|
|
186
|
-
return 0 if
|
|
187
|
+
non_pinned = all_sessions.reject { |s| s[:pinned] } # already sorted newest-first
|
|
188
|
+
return 0 if non_pinned.size <= keep
|
|
187
189
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
end.size
|
|
190
|
+
victims = non_pinned[keep..]
|
|
191
|
+
victims.each { |session| soft_delete(session[:session_id]) }
|
|
192
|
+
victims.size
|
|
192
193
|
end
|
|
193
194
|
|
|
194
195
|
# ── Session trash (delegates to Tools::TrashManager) ──────────────
|
data/lib/clacky/telemetry.rb
CHANGED
|
@@ -23,6 +23,11 @@ module Clacky
|
|
|
23
23
|
# POST /api/v1/telemetry/startup
|
|
24
24
|
# POST /api/v1/telemetry/task
|
|
25
25
|
module Telemetry
|
|
26
|
+
LAUNCH_SOURCES = {
|
|
27
|
+
"installer" => "installer",
|
|
28
|
+
nil => "cli"
|
|
29
|
+
}.freeze
|
|
30
|
+
|
|
26
31
|
class << self
|
|
27
32
|
# Called on every CLI startup (agent and server mode).
|
|
28
33
|
# No local dedup — the server deduplicates by device_hash for unique
|
|
@@ -32,11 +37,13 @@ module Clacky
|
|
|
32
37
|
|
|
33
38
|
brand = Clacky::BrandConfig.load
|
|
34
39
|
payload = {
|
|
35
|
-
device_id:
|
|
36
|
-
version:
|
|
37
|
-
os:
|
|
38
|
-
ruby_version:
|
|
39
|
-
brand:
|
|
40
|
+
device_id: resolve_device_id(brand),
|
|
41
|
+
version: Clacky::VERSION,
|
|
42
|
+
os: RbConfig::CONFIG["host_os"],
|
|
43
|
+
ruby_version: RUBY_VERSION,
|
|
44
|
+
brand: brand.branded? ? brand.package_name : nil,
|
|
45
|
+
launch_source: LAUNCH_SOURCES.fetch(ENV["CLACKY_LAUNCHED_BY"], "cli"),
|
|
46
|
+
container: detect_container
|
|
40
47
|
}.compact
|
|
41
48
|
|
|
42
49
|
fire_and_forget("/api/v1/telemetry/startup", payload)
|
|
@@ -56,7 +63,8 @@ module Clacky
|
|
|
56
63
|
payload = {
|
|
57
64
|
device_id: resolve_device_id(brand),
|
|
58
65
|
version: Clacky::VERSION,
|
|
59
|
-
brand: brand.branded? ? brand.package_name : nil
|
|
66
|
+
brand: brand.branded? ? brand.package_name : nil,
|
|
67
|
+
container: detect_container
|
|
60
68
|
}
|
|
61
69
|
payload.merge!(extract_task_metrics(result)) if result.is_a?(Hash)
|
|
62
70
|
|
|
@@ -74,6 +82,18 @@ module Clacky
|
|
|
74
82
|
brand.device_id
|
|
75
83
|
end
|
|
76
84
|
|
|
85
|
+
private def detect_container
|
|
86
|
+
return "docker" if File.exist?("/.dockerenv")
|
|
87
|
+
|
|
88
|
+
begin
|
|
89
|
+
cgroup = File.read("/proc/1/cgroup")
|
|
90
|
+
return "docker" if cgroup.include?("docker") || cgroup.include?("containerd")
|
|
91
|
+
rescue Errno::ENOENT, Errno::EACCES
|
|
92
|
+
nil
|
|
93
|
+
end
|
|
94
|
+
nil
|
|
95
|
+
end
|
|
96
|
+
|
|
77
97
|
private def extract_task_metrics(result)
|
|
78
98
|
cache = result[:cache_stats] || {}
|
|
79
99
|
duration = result[:duration_seconds]
|
|
@@ -381,15 +381,19 @@ module Clacky
|
|
|
381
381
|
render_all
|
|
382
382
|
end
|
|
383
383
|
|
|
384
|
-
def cleanup_screen
|
|
384
|
+
def cleanup_screen(clear_screen: false)
|
|
385
385
|
@render_mutex.synchronize do
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
386
|
+
if clear_screen
|
|
387
|
+
screen.clear_screen(mode: :reset)
|
|
388
|
+
else
|
|
389
|
+
fixed_start = fixed_area_start_row
|
|
390
|
+
(fixed_start...screen.height).each do |row|
|
|
391
|
+
screen.move_cursor(row, 0)
|
|
392
|
+
screen.clear_line
|
|
393
|
+
end
|
|
394
|
+
screen.move_cursor([@output_row, 0].max, 0)
|
|
395
|
+
print "\r"
|
|
390
396
|
end
|
|
391
|
-
screen.move_cursor([@output_row, 0].max, 0)
|
|
392
|
-
print "\r"
|
|
393
397
|
screen.show_cursor
|
|
394
398
|
screen.flush
|
|
395
399
|
end
|
data/lib/clacky/ui_interface.rb
CHANGED
|
@@ -350,80 +350,104 @@ module Clacky
|
|
|
350
350
|
cache: { write: 0.30, read: 0.03 }
|
|
351
351
|
},
|
|
352
352
|
|
|
353
|
+
# M3 (released 2026-06-01) is MiniMax's multimodal flagship. Official
|
|
354
|
+
# pricing is tiered by context length (≤512K vs 512K–1M); per the
|
|
355
|
+
# project's "displayed ≤ actual" convention we record only the lowest
|
|
356
|
+
# (≤512K) tier as a flat rate — the global TIERED_PRICING_THRESHOLD is
|
|
357
|
+
# 200K, so applying the 512K–1M rate to the 200K–512K band would over-
|
|
358
|
+
# charge. Listed at original (non-promotional) prices: input $0.60,
|
|
359
|
+
# output $2.40, cache read $0.12 per 1M tokens.
|
|
360
|
+
"minimax-m3" => {
|
|
361
|
+
input: { default: 0.60, over_200k: 0.60 },
|
|
362
|
+
output: { default: 2.40, over_200k: 2.40 },
|
|
363
|
+
cache: { write: 0.60, read: 0.12 }
|
|
364
|
+
},
|
|
365
|
+
|
|
353
366
|
"minimax-m2.7" => {
|
|
354
367
|
input: { default: 0.30, over_200k: 0.30 },
|
|
355
368
|
output: { default: 1.20, over_200k: 1.20 },
|
|
356
369
|
cache: { write: 0.30, read: 0.06 }
|
|
357
370
|
},
|
|
358
371
|
|
|
359
|
-
# Qwen (Alibaba DashScope)
|
|
360
|
-
# Source: Alibaba Cloud Model Studio international
|
|
361
|
-
#
|
|
362
|
-
#
|
|
363
|
-
#
|
|
364
|
-
#
|
|
365
|
-
#
|
|
366
|
-
#
|
|
367
|
-
#
|
|
368
|
-
#
|
|
372
|
+
# Qwen (Alibaba DashScope) - USD per 1M tokens, international (Singapore) list price.
|
|
373
|
+
# Source: Alibaba Cloud Model Studio international console per-model pages.
|
|
374
|
+
#
|
|
375
|
+
# Pricing convention:
|
|
376
|
+
# - These rates are used for user-facing cost ESTIMATION, so we always use
|
|
377
|
+
# the standard LIST price and intentionally ignore any limited-time promo
|
|
378
|
+
# discounts. A promo lowers the user's actual bill, never raises it, so
|
|
379
|
+
# estimating at list price keeps the estimate a safe upper bound and avoids
|
|
380
|
+
# churn whenever a promo starts or ends.
|
|
381
|
+
# - We record the model's LOWEST context tier (e.g. input<=256k / <=128k) as a
|
|
382
|
+
# flat rate, since the global TIERED_PRICING_THRESHOLD is 200K and does not
|
|
383
|
+
# match Qwen's per-model breakpoints.
|
|
384
|
+
# - cache.write = official explicit-cache-create price.
|
|
385
|
+
# - cache.read = official explicit-cache-hit price.
|
|
386
|
+
# - When a model has NO published explicit-cache price (e.g. qwen3.6-27b,
|
|
387
|
+
# qwen-plus-latest), cache.write/read fall back to the input rate.
|
|
388
|
+
# qwen3.7-max: NOT tiered (single flat tier per Alibaba's definition).
|
|
389
|
+
# List price: input 2.5, output 7.5, explicit write 3.125, explicit read 0.25.
|
|
369
390
|
"qwen3.7-max" => {
|
|
370
|
-
input: { default:
|
|
371
|
-
output: { default:
|
|
372
|
-
cache: { write:
|
|
391
|
+
input: { default: 2.5, over_200k: 2.5 },
|
|
392
|
+
output: { default: 7.5, over_200k: 7.5 },
|
|
393
|
+
cache: { write: 3.125, read: 0.25 }
|
|
373
394
|
},
|
|
374
395
|
|
|
396
|
+
# qwen3.7-plus: list price (<=256k tier):
|
|
397
|
+
# input 0.4, output 1.6, explicit write 0.5, explicit read 0.04.
|
|
375
398
|
"qwen3.7-plus" => {
|
|
376
|
-
input: { default: 0.
|
|
377
|
-
output: { default:
|
|
378
|
-
cache: { write: 0.
|
|
379
|
-
},
|
|
380
|
-
|
|
381
|
-
"qwen3.7-flash" => {
|
|
382
|
-
input: { default: 0.15, over_200k: 0.15 },
|
|
383
|
-
output: { default: 0.90, over_200k: 0.90 },
|
|
384
|
-
cache: { write: 0.15, read: 0.03 }
|
|
399
|
+
input: { default: 0.4, over_200k: 0.4 },
|
|
400
|
+
output: { default: 1.6, over_200k: 1.6 },
|
|
401
|
+
cache: { write: 0.5, read: 0.04 }
|
|
385
402
|
},
|
|
386
403
|
|
|
404
|
+
# qwen3.6-plus: list price (<=256k tier). Official explicit-cache prices.
|
|
405
|
+
# input 0.50, output 3.00, explicit write 0.625, explicit read 0.05
|
|
387
406
|
"qwen3.6-plus" => {
|
|
388
|
-
input: { default: 0.
|
|
389
|
-
output: { default:
|
|
390
|
-
cache: { write: 0.
|
|
407
|
+
input: { default: 0.50, over_200k: 0.50 },
|
|
408
|
+
output: { default: 3.00, over_200k: 3.00 },
|
|
409
|
+
cache: { write: 0.625, read: 0.05 }
|
|
391
410
|
},
|
|
392
411
|
|
|
412
|
+
# qwen3.6-max (qwen3.6-max-preview): list price (<=128k tier).
|
|
413
|
+
# input 1.30, output 7.80, explicit write 1.625, explicit read 0.13
|
|
393
414
|
"qwen3.6-max" => {
|
|
394
|
-
input: { default: 1.
|
|
395
|
-
output: { default:
|
|
396
|
-
cache: { write: 1.
|
|
415
|
+
input: { default: 1.30, over_200k: 1.30 },
|
|
416
|
+
output: { default: 7.80, over_200k: 7.80 },
|
|
417
|
+
cache: { write: 1.625, read: 0.13 }
|
|
397
418
|
},
|
|
398
419
|
|
|
420
|
+
# qwen3.6-27b: list price, no explicit-cache pricing published.
|
|
421
|
+
# Cache write/read fall back to the input rate (no cache discount).
|
|
399
422
|
"qwen3.6-27b" => {
|
|
400
|
-
input: { default: 0.
|
|
401
|
-
output: { default:
|
|
402
|
-
cache: { write: 0.
|
|
423
|
+
input: { default: 0.60, over_200k: 0.60 },
|
|
424
|
+
output: { default: 3.60, over_200k: 3.60 },
|
|
425
|
+
cache: { write: 0.60, read: 0.60 }
|
|
403
426
|
},
|
|
404
427
|
|
|
428
|
+
# qwen3.6-flash: list price (<=256k tier).
|
|
429
|
+
# input 0.25, output 1.50, explicit write 0.3125, explicit read 0.025
|
|
405
430
|
"qwen3.6-flash" => {
|
|
406
|
-
input: { default: 0.
|
|
407
|
-
output: { default:
|
|
408
|
-
cache: { write: 0.
|
|
431
|
+
input: { default: 0.25, over_200k: 0.25 },
|
|
432
|
+
output: { default: 1.50, over_200k: 1.50 },
|
|
433
|
+
cache: { write: 0.3125, read: 0.025 }
|
|
409
434
|
},
|
|
410
435
|
|
|
436
|
+
# qwen-plus-latest: list price (<=256k tier), no explicit-cache pricing.
|
|
437
|
+
# Cache write/read fall back to the input rate (no cache discount).
|
|
411
438
|
"qwen-plus-latest" => {
|
|
412
439
|
input: { default: 0.40, over_200k: 0.40 },
|
|
413
440
|
output: { default: 1.20, over_200k: 1.20 },
|
|
414
|
-
cache: { write: 0.40, read: 0.
|
|
415
|
-
},
|
|
416
|
-
|
|
417
|
-
"qwen-vl-plus" => {
|
|
418
|
-
input: { default: 0.14, over_200k: 0.14 },
|
|
419
|
-
output: { default: 0.41, over_200k: 0.41 },
|
|
420
|
-
cache: { write: 0.14, read: 0.028 }
|
|
441
|
+
cache: { write: 0.40, read: 0.40 }
|
|
421
442
|
},
|
|
422
443
|
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
444
|
+
# qwen3-vl-plus: replaces the retiring qwen-vl-plus. List price
|
|
445
|
+
# (128k<input<=256k tier). input 0.60, output 4.80,
|
|
446
|
+
# explicit write 0.75, explicit read 0.06.
|
|
447
|
+
"qwen3-vl-plus" => {
|
|
448
|
+
input: { default: 0.60, over_200k: 0.60 },
|
|
449
|
+
output: { default: 4.80, over_200k: 4.80 },
|
|
450
|
+
cache: { write: 0.75, read: 0.06 }
|
|
427
451
|
},
|
|
428
452
|
|
|
429
453
|
}.freeze
|
|
@@ -583,6 +607,8 @@ module Clacky
|
|
|
583
607
|
"glm-4.7"
|
|
584
608
|
# MiniMax — model ids in providers.rb use capitalised "MiniMax-M2.x"
|
|
585
609
|
# but we match case-insensitively and map to the lowercased table key.
|
|
610
|
+
when /^minimax-m3$/i
|
|
611
|
+
"minimax-m3"
|
|
586
612
|
when /^minimax-m2\.5$/i
|
|
587
613
|
"minimax-m2.5"
|
|
588
614
|
when /^minimax-m2\.7$/i
|
|
@@ -591,14 +617,12 @@ module Clacky
|
|
|
591
617
|
# Qwen (Alibaba DashScope) — strict anchored match per registered
|
|
592
618
|
# model id in providers.rb. qwen3.7-* is the latest flagship line;
|
|
593
619
|
# qwen3.6-* are the previous generation; qwen-plus-latest is the
|
|
594
|
-
# rolling alias for the latest Qwen-Plus release;
|
|
595
|
-
# the multimodal
|
|
620
|
+
# rolling alias for the latest Qwen-Plus release; qwen3-vl-plus is
|
|
621
|
+
# the multimodal SKU (replaces the retired qwen-vl-plus/max).
|
|
596
622
|
when /^qwen3\.7-max$/i
|
|
597
623
|
"qwen3.7-max"
|
|
598
624
|
when /^qwen3\.7-plus$/i
|
|
599
625
|
"qwen3.7-plus"
|
|
600
|
-
when /^qwen3\.7-flash$/i
|
|
601
|
-
"qwen3.7-flash"
|
|
602
626
|
when /^qwen3\.6-plus$/i
|
|
603
627
|
"qwen3.6-plus"
|
|
604
628
|
when /^qwen3\.6-max$/i
|
|
@@ -609,10 +633,8 @@ module Clacky
|
|
|
609
633
|
"qwen3.6-flash"
|
|
610
634
|
when /^qwen-plus-latest$/i
|
|
611
635
|
"qwen-plus-latest"
|
|
612
|
-
when /^
|
|
613
|
-
"
|
|
614
|
-
when /^qwen-vl-max$/i
|
|
615
|
-
"qwen-vl-max"
|
|
636
|
+
when /^qwen3-vl-plus$/i
|
|
637
|
+
"qwen3-vl-plus"
|
|
616
638
|
|
|
617
639
|
# OpenAI GPT-5.x models — match various dashed/dotted/compact forms
|
|
618
640
|
# (e.g. "gpt-5.5", "gpt-5-5", "gpt5.5", "gpt55")
|
data/lib/clacky/version.rb
CHANGED