openclacky 1.2.2 → 1.2.4

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 (39) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +36 -0
  3. data/lib/clacky/agent.rb +11 -0
  4. data/lib/clacky/client.rb +8 -4
  5. data/lib/clacky/default_skills/browser-setup/SKILL.md +90 -0
  6. data/lib/clacky/default_skills/channel-manager/SKILL.md +1 -0
  7. data/lib/clacky/default_skills/channel-manager/weixin_setup.rb +28 -8
  8. data/lib/clacky/mcp/stdio_transport.rb +6 -1
  9. data/lib/clacky/providers.rb +5 -7
  10. data/lib/clacky/server/browser_manager.rb +16 -3
  11. data/lib/clacky/server/channel/adapters/feishu/message_parser.rb +46 -1
  12. data/lib/clacky/server/channel/adapters/wecom/adapter.rb +38 -13
  13. data/lib/clacky/server/channel/channel_manager.rb +14 -4
  14. data/lib/clacky/server/channel/channel_ui_controller.rb +27 -11
  15. data/lib/clacky/server/http_server.rb +13 -3
  16. data/lib/clacky/tools/browser.rb +3 -3
  17. data/lib/clacky/tools/glob.rb +19 -4
  18. data/lib/clacky/tools/grep.rb +13 -1
  19. data/lib/clacky/tools/security.rb +1 -2
  20. data/lib/clacky/tools/terminal.rb +210 -14
  21. data/lib/clacky/ui2/ui_controller.rb +20 -2
  22. data/lib/clacky/utils/file_ignore_helper.rb +78 -5
  23. data/lib/clacky/utils/login_shell.rb +3 -1
  24. data/lib/clacky/utils/model_pricing.rb +28 -3
  25. data/lib/clacky/utils/scripts_manager.rb +1 -0
  26. data/lib/clacky/version.rb +1 -1
  27. data/lib/clacky/web/app.css +1 -0
  28. data/lib/clacky/web/settings.js +5 -0
  29. data/lib/clacky/web/weixin-qr.html +5 -4
  30. data/scripts/build/lib/apt.sh +71 -1
  31. data/scripts/build/src/install.sh.cc +1 -1
  32. data/scripts/build/src/install_rails_deps.sh.cc +4 -4
  33. data/scripts/build/src/install_system_deps.sh.cc +1 -1
  34. data/scripts/install.ps1 +44 -17
  35. data/scripts/install.sh +72 -2
  36. data/scripts/install_rails_deps.sh +75 -5
  37. data/scripts/install_system_deps.sh +72 -2
  38. data/scripts/wsl_network_doctor.ps1 +196 -0
  39. metadata +3 -2
@@ -270,6 +270,76 @@ detect_network_region() {
270
270
 
271
271
  # ---[ @include lib/apt.sh ]---
272
272
 
273
+ # Wait until apt/dpkg lock files are no longer held (e.g. by apt-daily on
274
+ # freshly-booted WSL/Ubuntu). Uses flock(1) — the same mechanism apt uses —
275
+ # rather than checking file existence (the lock files are always present;
276
+ # advisory locks live in the kernel, not the filesystem).
277
+ wait_apt_lock() {
278
+ [ "$DISTRO" = "ubuntu" ] || [ "$DISTRO" = "debian" ] || return 0
279
+
280
+ local locks=(
281
+ "/var/lib/dpkg/lock-frontend"
282
+ "/var/lib/dpkg/lock"
283
+ "/var/lib/apt/lists/lock"
284
+ )
285
+ local max_wait="${1:-120}"
286
+ local waited=0
287
+ local announced=false
288
+
289
+ while :; do
290
+ local busy=false
291
+ for f in "${locks[@]}"; do
292
+ [ -e "$f" ] || continue
293
+ if ! sudo flock -n "$f" -c true 2>/dev/null; then
294
+ busy=true
295
+ break
296
+ fi
297
+ done
298
+
299
+ [ "$busy" = false ] && break
300
+
301
+ if [ "$announced" = false ]; then
302
+ print_info "Waiting for system apt/dpkg to finish (up to ${max_wait}s)..."
303
+ announced=true
304
+ fi
305
+
306
+ if [ "$waited" -ge "$max_wait" ]; then
307
+ print_error "apt is still locked after ${max_wait}s."
308
+ print_info "On WSL try: 'wsl --shutdown' from PowerShell, then rerun the installer."
309
+ return 1
310
+ fi
311
+
312
+ sleep 3
313
+ waited=$((waited + 3))
314
+ done
315
+
316
+ [ "$announced" = true ] && print_success "apt lock released"
317
+ return 0
318
+ }
319
+
320
+ # Run an apt-get subcommand with lock-wait + transient-failure retry.
321
+ # Usage: apt_get_run update [-qq]
322
+ # apt_get_run install -y pkg1 pkg2
323
+ apt_get_run() {
324
+ local attempts=3
325
+ local i=1
326
+ while [ "$i" -le "$attempts" ]; do
327
+ wait_apt_lock 120 || return 1
328
+ if sudo apt-get "$@"; then
329
+ return 0
330
+ fi
331
+ local rc=$?
332
+ if [ "$i" -lt "$attempts" ]; then
333
+ print_warning "apt-get $1 failed (exit $rc), retrying ($i/$((attempts-1)))..."
334
+ sleep 5
335
+ else
336
+ print_error "apt-get $1 failed after $attempts attempts."
337
+ return "$rc"
338
+ fi
339
+ i=$((i + 1))
340
+ done
341
+ }
342
+
273
343
  # Configure apt mirror for CN region and run apt-get update.
274
344
  # Guards: only runs on ubuntu/debian ($DISTRO).
275
345
  # Relies on $USE_CN_MIRRORS set by detect_network_region (network.sh).
@@ -317,7 +387,7 @@ EOF
317
387
  print_info "Region: global — using default apt sources"
318
388
  fi
319
389
 
320
- sudo apt-get update -qq
390
+ apt_get_run update -qq || return 1
321
391
  print_success "apt updated"
322
392
  }
323
393
 
@@ -462,7 +532,7 @@ ensure_linux_deps() {
462
532
 
463
533
  detect_network_region
464
534
  setup_apt_mirror
465
- sudo apt-get install -y build-essential git curl python3
535
+ apt_get_run install -y build-essential git curl python3 || return 1
466
536
  print_success "Dependencies installed"
467
537
  }
468
538
 
@@ -0,0 +1,196 @@
1
+ # wsl_network_doctor.ps1 — diagnose & repair WSL2 mirrored networking for the browser tool.
2
+ #
3
+ # Designed to be invoked from inside WSL via:
4
+ # powershell.exe -NoProfile -ExecutionPolicy Bypass -File <win-path-to-this-script> <subcommand>
5
+ #
6
+ # Subcommands:
7
+ # status Check whether mirrored networking is configured.
8
+ # enable Write networkingMode=mirrored to %USERPROFILE%\.wslconfig.
9
+ # repair Restart Windows Host Network Service (HNS) via UAC elevation.
10
+ #
11
+ # Exit codes (status only):
12
+ # 0 OK — mirrored configured, OR running on WSL1 (no config needed)
13
+ # 10 NEED_ENABLE — mirrored not configured, run `enable`
14
+ # 20 NEED_REPAIR — configured but suspected broken, run `repair`
15
+ # 1 unexpected error
16
+ #
17
+ # `enable` and `repair` exit 0 on success, 1 on failure.
18
+
19
+ param(
20
+ [Parameter(Position = 0)]
21
+ [ValidateSet('status', 'enable', 'repair')]
22
+ [string]$Command
23
+ )
24
+
25
+ $ErrorActionPreference = 'Stop'
26
+
27
+ # ---------------------------------------------------------------------------
28
+ # Helpers
29
+ # ---------------------------------------------------------------------------
30
+
31
+ function Get-WslConfigPath {
32
+ return (Join-Path $env:USERPROFILE '.wslconfig')
33
+ }
34
+
35
+ function Test-MirroredConfigured {
36
+ $cfg = Get-WslConfigPath
37
+ if (-not (Test-Path $cfg)) { return $false }
38
+ $content = Get-Content $cfg -Raw -ErrorAction SilentlyContinue
39
+ if ($null -eq $content) { return $false }
40
+ return ($content -match '(?im)^\s*networkingMode\s*=\s*mirrored\s*$')
41
+ }
42
+
43
+ # Returns 1 or 2 if Ubuntu is registered, $null otherwise.
44
+ # Parses `wsl.exe -l -v` output (UTF-16, may contain a star marker on default distro).
45
+ function Get-UbuntuWslVersion {
46
+ try {
47
+ $raw = & wsl.exe -l -v 2>$null
48
+ } catch {
49
+ return $null
50
+ }
51
+ if (-not $raw) { return $null }
52
+
53
+ foreach ($line in $raw) {
54
+ $clean = ($line -replace '\s+', ' ').Trim().TrimStart('*').Trim()
55
+ if ($clean -match '^Ubuntu(?:-[\w\.]+)?\s+\S+\s+(\d+)\s*$') {
56
+ return [int]$matches[1]
57
+ }
58
+ }
59
+ return $null
60
+ }
61
+
62
+ # ---------------------------------------------------------------------------
63
+ # Subcommand: status
64
+ # ---------------------------------------------------------------------------
65
+
66
+ function Invoke-Status {
67
+ $wslVer = Get-UbuntuWslVersion
68
+ if ($wslVer -eq 1) {
69
+ Write-Host "OK: Ubuntu is running on WSL1 — shares the Windows network stack directly."
70
+ Write-Host "No mirrored configuration needed. The browser tool can connect to 127.0.0.1 as-is."
71
+ exit 0
72
+ }
73
+
74
+ if (Test-MirroredConfigured) {
75
+ Write-Host "OK: mirrored networking is configured in .wslconfig."
76
+ Write-Host "If the browser tool still cannot connect, run: wsl_network_doctor.ps1 repair"
77
+ exit 0
78
+ }
79
+
80
+ Write-Host "NEED_ENABLE: mirrored networking is not configured."
81
+ Write-Host "Run: wsl_network_doctor.ps1 enable"
82
+ exit 10
83
+ }
84
+
85
+ # ---------------------------------------------------------------------------
86
+ # Subcommand: enable
87
+ # ---------------------------------------------------------------------------
88
+
89
+ function Invoke-Enable {
90
+ if (Test-MirroredConfigured) {
91
+ Write-Host "OK: already enabled. No changes needed."
92
+ Write-Host "If the browser tool still cannot connect, run: wsl_network_doctor.ps1 repair"
93
+ exit 0
94
+ }
95
+
96
+ $cfg = Get-WslConfigPath
97
+ Write-Host "Writing networkingMode=mirrored to $cfg ..."
98
+
99
+ if (-not (Test-Path $cfg)) {
100
+ New-Item -ItemType File -Path $cfg -Force | Out-Null
101
+ }
102
+
103
+ $content = Get-Content $cfg -Raw -ErrorAction SilentlyContinue
104
+ if ($null -eq $content) { $content = '' }
105
+
106
+ if ($content -match '(?im)^\s*networkingMode\s*=') {
107
+ $new = [regex]::Replace($content, '(?im)^\s*networkingMode\s*=.*$', 'networkingMode=mirrored')
108
+ Set-Content -Path $cfg -Value $new -NoNewline
109
+ } else {
110
+ if ($content -notmatch '(?im)^\[wsl2\]') {
111
+ if ($content.Length -gt 0 -and -not $content.EndsWith([char]10)) {
112
+ Add-Content -Path $cfg -Value ''
113
+ }
114
+ Add-Content -Path $cfg -Value '[wsl2]'
115
+ }
116
+ Add-Content -Path $cfg -Value 'networkingMode=mirrored'
117
+ }
118
+
119
+ Write-Host "WROTE: .wslconfig updated."
120
+ Write-Host ""
121
+ Write-Host "Next step (cannot be done from inside WSL):"
122
+ Write-Host " 1. Open Windows PowerShell"
123
+ Write-Host " 2. Run: wsl --shutdown"
124
+ Write-Host " 3. Reopen Clacky and run /browser-setup again"
125
+ exit 0
126
+ }
127
+
128
+ # ---------------------------------------------------------------------------
129
+ # Subcommand: repair
130
+ # ---------------------------------------------------------------------------
131
+ # Restart Windows Host Network Service (HNS). Requires admin → triggers UAC.
132
+ # Does NOT call `wsl --shutdown` here — the user must run it manually after
133
+ # the elevated window finishes, otherwise our own WSL session would be killed.
134
+
135
+ function Invoke-Repair {
136
+ Write-Host "Repairing Windows Host Network Service (HNS) ..."
137
+ Write-Host ""
138
+ Write-Host "A Windows User Account Control (UAC) dialog will appear."
139
+ Write-Host "Please click 'Yes' to allow the repair script to run."
140
+ Write-Host ""
141
+
142
+ $inner = @'
143
+ try {
144
+ Stop-Service hns -Force -ErrorAction SilentlyContinue
145
+ Start-Service hns -ErrorAction Stop
146
+ Write-Host "HNS restarted successfully."
147
+ } catch {
148
+ Write-Host "Repair failed: $_"
149
+ Start-Sleep 5
150
+ exit 1
151
+ }
152
+ Write-Host ""
153
+ Write-Host "Repair complete. Please run 'wsl --shutdown' in PowerShell, then reopen Clacky."
154
+ Start-Sleep 4
155
+ '@
156
+
157
+ $encoded = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($inner))
158
+
159
+ try {
160
+ Start-Process powershell -Verb RunAs -ArgumentList '-NoProfile', '-EncodedCommand', $encoded
161
+ } catch {
162
+ Write-Host "FAILED: could not trigger UAC prompt: $_"
163
+ Write-Host ""
164
+ Write-Host "You can run the repair manually:"
165
+ Write-Host " 1. Open PowerShell as Administrator"
166
+ Write-Host " 2. Run: net stop hns; net start hns"
167
+ Write-Host " 3. Run: wsl --shutdown"
168
+ Write-Host " 4. Reopen Clacky"
169
+ exit 1
170
+ }
171
+
172
+ Write-Host "Repair script launched in an elevated PowerShell window."
173
+ Write-Host ""
174
+ Write-Host "After the elevated window finishes:"
175
+ Write-Host " 1. Run in regular PowerShell: wsl --shutdown"
176
+ Write-Host " 2. Reopen Clacky and run /browser-setup again"
177
+ exit 0
178
+ }
179
+
180
+ # ---------------------------------------------------------------------------
181
+ # Dispatch
182
+ # ---------------------------------------------------------------------------
183
+
184
+ switch ($Command) {
185
+ 'status' { Invoke-Status }
186
+ 'enable' { Invoke-Enable }
187
+ 'repair' { Invoke-Repair }
188
+ default {
189
+ Write-Host "Usage: wsl_network_doctor.ps1 {status|enable|repair}"
190
+ Write-Host ""
191
+ Write-Host " status Check whether WSL2 mirrored networking is configured."
192
+ Write-Host " enable Write networkingMode=mirrored to %USERPROFILE%\.wslconfig."
193
+ Write-Host " repair Restart Windows Host Network Service (HNS) via UAC."
194
+ exit 2
195
+ }
196
+ }
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.2.2
4
+ version: 1.2.4
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-25 00:00:00.000000000 Z
11
+ date: 2026-05-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -596,6 +596,7 @@ files:
596
596
  - scripts/install_rails_deps.sh
597
597
  - scripts/install_system_deps.sh
598
598
  - scripts/uninstall.sh
599
+ - scripts/wsl_network_doctor.ps1
599
600
  - sig/clacky.rbs
600
601
  homepage: https://github.com/clacky-ai/openclacky
601
602
  licenses: