openclacky 1.1.0 → 1.1.2

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.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +37 -0
  3. data/README.md +28 -7
  4. data/lib/clacky/agent/llm_caller.rb +23 -1
  5. data/lib/clacky/agent/session_serializer.rb +6 -1
  6. data/lib/clacky/agent/skill_manager.rb +18 -5
  7. data/lib/clacky/agent.rb +14 -5
  8. data/lib/clacky/anthropic_stream_aggregator.rb +135 -0
  9. data/lib/clacky/bedrock_stream_aggregator.rb +137 -0
  10. data/lib/clacky/brand_config.rb +68 -15
  11. data/lib/clacky/cli.rb +18 -19
  12. data/lib/clacky/client.rb +146 -17
  13. data/lib/clacky/default_skills/onboard/SKILL.md +6 -2
  14. data/lib/clacky/default_skills/onboard/scripts/import_external_skills.rb +50 -6
  15. data/lib/clacky/openai_stream_aggregator.rb +130 -0
  16. data/lib/clacky/server/channel/adapters/weixin/adapter.rb +169 -6
  17. data/lib/clacky/server/channel/channel_ui_controller.rb +6 -0
  18. data/lib/clacky/server/http_server.rb +9 -3
  19. data/lib/clacky/server/web_ui_controller.rb +8 -4
  20. data/lib/clacky/tools/terminal.rb +11 -0
  21. data/lib/clacky/ui2/components/input_area.rb +10 -1
  22. data/lib/clacky/ui2/components/todo_area.rb +22 -2
  23. data/lib/clacky/ui2/layout_manager.rb +70 -14
  24. data/lib/clacky/ui2/progress_handle.rb +86 -15
  25. data/lib/clacky/ui2/ui_controller.rb +47 -7
  26. data/lib/clacky/utils/logger.rb +7 -0
  27. data/lib/clacky/version.rb +1 -1
  28. data/lib/clacky/web/app.css +6 -4
  29. data/lib/clacky/web/i18n.js +21 -6
  30. data/lib/clacky/web/index.html +8 -6
  31. data/lib/clacky/web/sessions.js +171 -58
  32. data/lib/clacky/web/vendor/katex/auto-render.min.js +1 -0
  33. data/lib/clacky/web/vendor/katex/fonts/KaTeX_AMS-Regular.woff2 +0 -0
  34. data/lib/clacky/web/vendor/katex/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
  35. data/lib/clacky/web/vendor/katex/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
  36. data/lib/clacky/web/vendor/katex/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
  37. data/lib/clacky/web/vendor/katex/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
  38. data/lib/clacky/web/vendor/katex/fonts/KaTeX_Main-Bold.woff2 +0 -0
  39. data/lib/clacky/web/vendor/katex/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
  40. data/lib/clacky/web/vendor/katex/fonts/KaTeX_Main-Italic.woff2 +0 -0
  41. data/lib/clacky/web/vendor/katex/fonts/KaTeX_Main-Regular.woff2 +0 -0
  42. data/lib/clacky/web/vendor/katex/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
  43. data/lib/clacky/web/vendor/katex/fonts/KaTeX_Math-Italic.woff2 +0 -0
  44. data/lib/clacky/web/vendor/katex/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
  45. data/lib/clacky/web/vendor/katex/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
  46. data/lib/clacky/web/vendor/katex/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
  47. data/lib/clacky/web/vendor/katex/fonts/KaTeX_Script-Regular.woff2 +0 -0
  48. data/lib/clacky/web/vendor/katex/fonts/KaTeX_Size1-Regular.woff2 +0 -0
  49. data/lib/clacky/web/vendor/katex/fonts/KaTeX_Size2-Regular.woff2 +0 -0
  50. data/lib/clacky/web/vendor/katex/fonts/KaTeX_Size3-Regular.woff2 +0 -0
  51. data/lib/clacky/web/vendor/katex/fonts/KaTeX_Size4-Regular.woff2 +0 -0
  52. data/lib/clacky/web/vendor/katex/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
  53. data/lib/clacky/web/vendor/katex/katex.min.css +1 -0
  54. data/lib/clacky/web/vendor/katex/katex.min.js +1 -0
  55. data/lib/clacky/web/ws-dispatcher.js +19 -4
  56. data/lib/clacky.rb +3 -0
  57. data/scripts/build/src/install.sh.cc +15 -5
  58. data/scripts/install.ps1 +14 -3
  59. data/scripts/install.sh +15 -5
  60. metadata +28 -2
@@ -184,15 +184,12 @@ WS.onEvent(ev => {
184
184
  break;
185
185
 
186
186
  case "progress":
187
- console.log("[DEBUG] progress event:", ev);
188
187
  if (ev.session_id !== Sessions.activeId) break;
189
188
  if (ev.phase === "active" || ev.status === "start") {
190
189
  const progress_type = ev.progress_type || "thinking";
191
190
  const metadata = ev.metadata || {};
192
- console.log("[DEBUG] calling showProgress:", { message: ev.message, progress_type, metadata, started_at: ev.started_at });
193
191
  Sessions.showProgress(ev.message, progress_type, metadata, ev.started_at || null);
194
192
  } else {
195
- console.log("[DEBUG] calling clearProgress:", ev.message);
196
193
  Sessions.clearProgress(ev.message);
197
194
  }
198
195
  break;
@@ -206,7 +203,25 @@ WS.onEvent(ev => {
206
203
  const costDisplay = (!costSource || costSource === "estimated")
207
204
  ? "N/A"
208
205
  : `$${(ev.cost || 0).toFixed(4)}`;
209
- Sessions.appendInfo(`✓ ${I18n.t("chat.done", { n: ev.iterations, cost: costDisplay })}`);
206
+ let mainLine = I18n.t("chat.done", { n: ev.iterations, cost: costDisplay });
207
+ if (typeof ev.duration === "number" && ev.duration > 0) {
208
+ mainLine += I18n.t("chat.done.duration", { duration: ev.duration.toFixed(1) });
209
+ }
210
+ let cacheLine = null;
211
+ const cs = ev.cache_stats;
212
+ const total = cs && (cs.total_requests || cs["total_requests"]);
213
+ const hits = cs && (cs.cache_hit_requests || cs["cache_hit_requests"]);
214
+ const cachedTokens = cs && (cs.cache_read_input_tokens || cs["cache_read_input_tokens"]);
215
+ if (total && total > 0 && cachedTokens && cachedTokens > 0) {
216
+ const rate = ((hits / total) * 100).toFixed(1);
217
+ const tokensFmt = cachedTokens >= 1000
218
+ ? `${(cachedTokens / 1000).toFixed(1)}k`
219
+ : `${cachedTokens}`;
220
+ cacheLine = I18n.t("chat.done.cache", {
221
+ rate, hits, total: total, tokens: tokensFmt
222
+ });
223
+ }
224
+ Sessions.appendInfo(`✓ ${mainLine}`, cacheLine);
210
225
  }
211
226
  break;
212
227
 
data/lib/clacky.rb CHANGED
@@ -65,6 +65,9 @@ require_relative "clacky/version"
65
65
  require_relative "clacky/message_format/anthropic"
66
66
  require_relative "clacky/message_format/open_ai"
67
67
  require_relative "clacky/message_format/bedrock"
68
+ require_relative "clacky/bedrock_stream_aggregator"
69
+ require_relative "clacky/openai_stream_aggregator"
70
+ require_relative "clacky/anthropic_stream_aggregator"
68
71
  require_relative "clacky/client"
69
72
  require_relative "clacky/skill"
70
73
  require_relative "clacky/skill_loader"
@@ -49,6 +49,7 @@ install_via_gem() {
49
49
  configure_gem_source
50
50
  setup_gem_home
51
51
 
52
+ local target source_args=()
52
53
  if [ "$USE_CN_MIRRORS" = true ]; then
53
54
  print_info "Fetching latest version from OSS..."
54
55
  local cn_version; cn_version=$(curl -fsSL "$CN_GEM_LATEST_URL" | tr -d '[:space:]')
@@ -57,17 +58,26 @@ install_via_gem() {
57
58
  local gem_file="/tmp/openclacky-${cn_version}.gem"
58
59
  print_info "Downloading openclacky-${cn_version}.gem..."
59
60
  curl -fsSL "$gem_url" -o "$gem_file"
60
- gem install "$gem_file" --no-document --source "$CN_RUBYGEMS_URL"
61
+ target="$gem_file"
62
+ source_args=(--source "$CN_RUBYGEMS_URL")
61
63
  else
62
- gem install openclacky --no-document
64
+ target="openclacky"
63
65
  fi
64
66
 
65
- if [ $? -eq 0 ]; then
67
+ # macOS system Ruby 2.6 has a buggy gem resolver that fails on rouge 4.x.
68
+ # Pre-install a 2.6-compatible rouge to avoid resolver failure.
69
+ local ruby_ver; ruby_ver=$(ruby -e 'puts RUBY_VERSION' 2>/dev/null)
70
+ if [[ "$ruby_ver" == 2.6.* ]]; then
71
+ print_warning "Ruby 2.6 detected — pinning rouge 3.30.0 first"
72
+ gem install rouge -v 3.30.0 --no-document "${source_args[@]}" || { print_error "gem install rouge failed"; return 1; }
73
+ fi
74
+
75
+ if gem install "$target" --no-document "${source_args[@]}"; then
66
76
  print_success "${DISPLAY_NAME} installed successfully!"
67
77
  return 0
68
- else
69
- print_error "gem install failed"; return 1
70
78
  fi
79
+
80
+ print_error "gem install failed"; return 1
71
81
  }
72
82
 
73
83
  # --------------------------------------------------------------------------
data/scripts/install.ps1 CHANGED
@@ -27,6 +27,7 @@ param(
27
27
 
28
28
  Set-StrictMode -Version Latest
29
29
  $ErrorActionPreference = "Stop"
30
+ $env:WSL_UTF8 = "1"
30
31
 
31
32
  $global:DisplayName = if ($BrandName) { $BrandName } else { "OpenClacky" }
32
33
  $global:DisplayCmd = if ($CommandName) { $CommandName } else { "openclacky" }
@@ -249,9 +250,10 @@ function Install-UbuntuRootfs {
249
250
 
250
251
  Write-Step "Importing Ubuntu into WSL$WslVersion (this may take a minute)..."
251
252
  New-Item -ItemType Directory -Force -Path $UBUNTU_WSL_DIR | Out-Null
252
- wsl.exe --import Ubuntu $UBUNTU_WSL_DIR $TarPath --version $WslVersion
253
+ $wslOutput = wsl.exe --import Ubuntu $UBUNTU_WSL_DIR $TarPath --version $WslVersion 2>&1
253
254
  if ($LASTEXITCODE -ne 0) {
254
255
  Write-Fail "wsl --import failed (exit $LASTEXITCODE)."
256
+ if ($wslOutput) { Write-Fail "$wslOutput" }
255
257
  Write-Fail "Try removing $UBUNTU_WSL_DIR and running the script again."
256
258
  exit 1
257
259
  }
@@ -395,7 +397,7 @@ function Test-VirtualisationSupported {
395
397
  if ($ok) {
396
398
  Write-Info "WSL2 probe passed — using WSL2."
397
399
  } else {
398
- Write-Info "WSL2 probe failed (Hyper-V not available) — falling back to WSL1."
400
+ Write-Info "WSL2 probe failed (Hyper-V not available)."
399
401
  }
400
402
  return $ok
401
403
  }
@@ -431,6 +433,7 @@ function Enable-WslFeatures {
431
433
  dism /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart | Out-Null
432
434
  Write-Success "WSL components enabled."
433
435
  Install-WslKernel
436
+ Set-InstallReg -Name "WslFeaturesEnabled" -Value "1"
434
437
  Set-InstallReg -Name "InstallPhase" -Value "wsl-pending"
435
438
  Prompt-Reboot
436
439
  }
@@ -464,8 +467,10 @@ Write-Info "Windows Build $osBuild — OK."
464
467
  Write-Step "Checking WSL status..."
465
468
  $wslCode = Invoke-WslStatusExitCode
466
469
  Write-Info "WSL --status exit code: $wslCode"
467
- $installPhase = Get-InstallReg -Name "InstallPhase" -Default ""
470
+ $installPhase = Get-InstallReg -Name "InstallPhase" -Default ""
471
+ $wslFeaturesEnabled = Get-InstallReg -Name "WslFeaturesEnabled" -Default ""
468
472
  Write-Info "InstallPhase: '$installPhase'"
473
+ Write-Info "WslFeaturesEnabled: '$wslFeaturesEnabled'"
469
474
 
470
475
  if ($installPhase -eq "" -and $wslCode -ne 0) {
471
476
  # First run and WSL not ready: enable WSL features and reboot.
@@ -495,6 +500,12 @@ if (Test-UbuntuInstalled) {
495
500
  Install-UbuntuRootfs -WslVersion 2 -TarPath $tarPath
496
501
  $wslVersion = 2
497
502
  } else {
503
+ if ($wslFeaturesEnabled -ne "1") {
504
+ # WSL components were never fully prepared — run Enable-WslFeatures and reboot.
505
+ Write-Warn "WSL2 is not available and WSL components have not been fully set up."
506
+ Enable-WslFeatures
507
+ # Always exits (prompts reboot)
508
+ }
498
509
  Write-Info "[main] WSL2 unavailable, falling back to WSL1..."
499
510
  Install-UbuntuRootfs -WslVersion 1 -TarPath $tarPath
500
511
  $wslVersion = 1
data/scripts/install.sh CHANGED
@@ -421,6 +421,7 @@ install_via_gem() {
421
421
  configure_gem_source
422
422
  setup_gem_home
423
423
 
424
+ local target source_args=()
424
425
  if [ "$USE_CN_MIRRORS" = true ]; then
425
426
  print_info "Fetching latest version from OSS..."
426
427
  local cn_version; cn_version=$(curl -fsSL "$CN_GEM_LATEST_URL" | tr -d '[:space:]')
@@ -429,17 +430,26 @@ install_via_gem() {
429
430
  local gem_file="/tmp/openclacky-${cn_version}.gem"
430
431
  print_info "Downloading openclacky-${cn_version}.gem..."
431
432
  curl -fsSL "$gem_url" -o "$gem_file"
432
- gem install "$gem_file" --no-document --source "$CN_RUBYGEMS_URL"
433
+ target="$gem_file"
434
+ source_args=(--source "$CN_RUBYGEMS_URL")
433
435
  else
434
- gem install openclacky --no-document
436
+ target="openclacky"
435
437
  fi
436
438
 
437
- if [ $? -eq 0 ]; then
439
+ # macOS system Ruby 2.6 has a buggy gem resolver that fails on rouge 4.x.
440
+ # Pre-install a 2.6-compatible rouge to avoid resolver failure.
441
+ local ruby_ver; ruby_ver=$(ruby -e 'puts RUBY_VERSION' 2>/dev/null)
442
+ if [[ "$ruby_ver" == 2.6.* ]]; then
443
+ print_warning "Ruby 2.6 detected — pinning rouge 3.30.0 first"
444
+ gem install rouge -v 3.30.0 --no-document "${source_args[@]}" || { print_error "gem install rouge failed"; return 1; }
445
+ fi
446
+
447
+ if gem install "$target" --no-document "${source_args[@]}"; then
438
448
  print_success "${DISPLAY_NAME} installed successfully!"
439
449
  return 0
440
- else
441
- print_error "gem install failed"; return 1
442
450
  fi
451
+
452
+ print_error "gem install failed"; return 1
443
453
  }
444
454
 
445
455
  # --------------------------------------------------------------------------
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: openclacky
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - windy
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-05-15 00:00:00.000000000 Z
11
+ date: 2026-05-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -342,7 +342,9 @@ files:
342
342
  - lib/clacky/agent/tool_registry.rb
343
343
  - lib/clacky/agent_config.rb
344
344
  - lib/clacky/agent_profile.rb
345
+ - lib/clacky/anthropic_stream_aggregator.rb
345
346
  - lib/clacky/banner.rb
347
+ - lib/clacky/bedrock_stream_aggregator.rb
346
348
  - lib/clacky/block_font.rb
347
349
  - lib/clacky/brand_config.rb
348
350
  - lib/clacky/cli.rb
@@ -407,6 +409,7 @@ files:
407
409
  - lib/clacky/message_format/bedrock.rb
408
410
  - lib/clacky/message_format/open_ai.rb
409
411
  - lib/clacky/message_history.rb
412
+ - lib/clacky/openai_stream_aggregator.rb
410
413
  - lib/clacky/plain_ui_controller.rb
411
414
  - lib/clacky/platform_http_client.rb
412
415
  - lib/clacky/providers.rb
@@ -534,6 +537,29 @@ files:
534
537
  - lib/clacky/web/tasks.js
535
538
  - lib/clacky/web/theme.js
536
539
  - lib/clacky/web/trash.js
540
+ - lib/clacky/web/vendor/katex/auto-render.min.js
541
+ - lib/clacky/web/vendor/katex/fonts/KaTeX_AMS-Regular.woff2
542
+ - lib/clacky/web/vendor/katex/fonts/KaTeX_Caligraphic-Bold.woff2
543
+ - lib/clacky/web/vendor/katex/fonts/KaTeX_Caligraphic-Regular.woff2
544
+ - lib/clacky/web/vendor/katex/fonts/KaTeX_Fraktur-Bold.woff2
545
+ - lib/clacky/web/vendor/katex/fonts/KaTeX_Fraktur-Regular.woff2
546
+ - lib/clacky/web/vendor/katex/fonts/KaTeX_Main-Bold.woff2
547
+ - lib/clacky/web/vendor/katex/fonts/KaTeX_Main-BoldItalic.woff2
548
+ - lib/clacky/web/vendor/katex/fonts/KaTeX_Main-Italic.woff2
549
+ - lib/clacky/web/vendor/katex/fonts/KaTeX_Main-Regular.woff2
550
+ - lib/clacky/web/vendor/katex/fonts/KaTeX_Math-BoldItalic.woff2
551
+ - lib/clacky/web/vendor/katex/fonts/KaTeX_Math-Italic.woff2
552
+ - lib/clacky/web/vendor/katex/fonts/KaTeX_SansSerif-Bold.woff2
553
+ - lib/clacky/web/vendor/katex/fonts/KaTeX_SansSerif-Italic.woff2
554
+ - lib/clacky/web/vendor/katex/fonts/KaTeX_SansSerif-Regular.woff2
555
+ - lib/clacky/web/vendor/katex/fonts/KaTeX_Script-Regular.woff2
556
+ - lib/clacky/web/vendor/katex/fonts/KaTeX_Size1-Regular.woff2
557
+ - lib/clacky/web/vendor/katex/fonts/KaTeX_Size2-Regular.woff2
558
+ - lib/clacky/web/vendor/katex/fonts/KaTeX_Size3-Regular.woff2
559
+ - lib/clacky/web/vendor/katex/fonts/KaTeX_Size4-Regular.woff2
560
+ - lib/clacky/web/vendor/katex/fonts/KaTeX_Typewriter-Regular.woff2
561
+ - lib/clacky/web/vendor/katex/katex.min.css
562
+ - lib/clacky/web/vendor/katex/katex.min.js
537
563
  - lib/clacky/web/version.js
538
564
  - lib/clacky/web/weixin-qr.html
539
565
  - lib/clacky/web/ws-dispatcher.js