openclacky 0.9.0 → 0.9.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +15 -0
- data/lib/clacky/agent.rb +33 -0
- data/lib/clacky/client.rb +8 -1
- data/lib/clacky/server/http_server.rb +31 -3
- data/lib/clacky/tools/browser.rb +52 -78
- data/lib/clacky/ui2/layout_manager.rb +9 -2
- data/lib/clacky/version.rb +1 -1
- data/scripts/install.sh +3 -34
- data/scripts/install_agent_browser.sh +67 -0
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 634937d9d7a20aa0a76b046ba079ef2d82c398ac81d59014968f7dbeb325726c
|
|
4
|
+
data.tar.gz: 7cd5c7eab980c54b5da38b6744dbc21dd3ac48af00c541a609d5537d6867ee70
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b874781caf58c502536666c33b8aff0c459076689909dd36bd82151f7092953d453d51b2e90259bbfdb6b2eb0ba389e5e56c083a1364118ca0a15edbef471e02
|
|
7
|
+
data.tar.gz: 1639031ccf11848ab3b8c2a18d3eb7d87c487dc1e13b856e4c0cdc8cb35e3ebf4c8001660ea607f013e64a40fa1ef09255915652af9d0bc44ad8ddf9c0b1dff2
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.9.2] - 2026-03-15
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
- **Version upgrade button now appears reliably**: the new version check now queries RubyGems directly instead of relying on local gem mirror sources (which often lag behind by hours or days), so the upgrade badge shows up promptly when a new version is available. Falls back to the local mirror if RubyGems is unreachable.
|
|
14
|
+
- **Edit confirmation diff output restored**: the file diff was not displaying correctly when the input area paused during an edit confirmation prompt; this is now fixed.
|
|
15
|
+
|
|
16
|
+
## [0.9.1] - 2026-03-15
|
|
17
|
+
|
|
18
|
+
### Added
|
|
19
|
+
- **Session context auto-injection**: the agent now automatically injects the current date and active model name into each conversation turn, so it always knows what day it is and which model it's running — helpful for time-sensitive tasks and multi-model setups
|
|
20
|
+
- **Kimi/Moonshot extended thinking support**: reasoning content is now preserved and echoed back correctly in message history, fixing HTTP 400 errors when using Kimi's extended thinking API
|
|
21
|
+
|
|
22
|
+
### Improved
|
|
23
|
+
- **Browser tool install UX**: the `agent-browser` setup flow has been redesigned with a dedicated install script and clearer guidance, making first-time setup smoother
|
|
24
|
+
|
|
10
25
|
## [0.9.0] - 2026-03-14
|
|
11
26
|
|
|
12
27
|
### Added
|
data/lib/clacky/agent.rb
CHANGED
|
@@ -182,6 +182,9 @@ module Clacky
|
|
|
182
182
|
@messages << system_message
|
|
183
183
|
end
|
|
184
184
|
|
|
185
|
+
# Inject session context (date + model) if not yet present or date has changed
|
|
186
|
+
inject_session_context_if_needed
|
|
187
|
+
|
|
185
188
|
# Format user message with images and files if provided
|
|
186
189
|
user_content = format_user_content(user_input, images, files)
|
|
187
190
|
@messages << { role: "user", content: user_content, task_id: task_id, created_at: Time.now.to_f }
|
|
@@ -423,6 +426,9 @@ module Clacky
|
|
|
423
426
|
end
|
|
424
427
|
# Store token_usage in the message so replay_history can re-emit it
|
|
425
428
|
msg[:token_usage] = response[:token_usage] if response[:token_usage]
|
|
429
|
+
# Preserve reasoning_content so it is echoed back to APIs that require it
|
|
430
|
+
# (e.g. Kimi/Moonshot extended thinking — omitting it causes HTTP 400)
|
|
431
|
+
msg[:reasoning_content] = response[:reasoning_content] if response[:reasoning_content]
|
|
426
432
|
@messages << msg
|
|
427
433
|
|
|
428
434
|
response
|
|
@@ -871,6 +877,33 @@ module Clacky
|
|
|
871
877
|
content
|
|
872
878
|
end
|
|
873
879
|
|
|
880
|
+
# Inject a session context message (date + model) into the conversation.
|
|
881
|
+
# Only injects when:
|
|
882
|
+
# 1. No context message exists yet in this session, OR
|
|
883
|
+
# 2. The existing context is from a previous day (cross-day session)
|
|
884
|
+
# Marked with system_injected: true so existing filters (replay_history,
|
|
885
|
+
# get_recent_user_messages, etc.) automatically skip it.
|
|
886
|
+
# Cache-safe: always inserted just before the current user message,
|
|
887
|
+
# so no historical cache entries are ever invalidated.
|
|
888
|
+
private def inject_session_context_if_needed
|
|
889
|
+
today = Time.now.strftime("%Y-%m-%d")
|
|
890
|
+
|
|
891
|
+
# Find the last injected context message
|
|
892
|
+
last_ctx = @messages.reverse.find { |m| m[:session_context] }
|
|
893
|
+
|
|
894
|
+
# Skip if we already have a context for today
|
|
895
|
+
return if last_ctx && last_ctx[:context_date] == today
|
|
896
|
+
|
|
897
|
+
content = "[Session context: Today is #{Time.now.strftime('%Y-%m-%d, %A')}. Current model: #{current_model}]"
|
|
898
|
+
@messages << {
|
|
899
|
+
role: "user",
|
|
900
|
+
content: content,
|
|
901
|
+
system_injected: true,
|
|
902
|
+
session_context: true,
|
|
903
|
+
context_date: today
|
|
904
|
+
}
|
|
905
|
+
end
|
|
906
|
+
|
|
874
907
|
# Track modified files for Time Machine snapshots
|
|
875
908
|
# @param tool_name [String] Name of the tool that was executed
|
|
876
909
|
# @param args [Hash] Arguments passed to the tool
|
data/lib/clacky/client.rb
CHANGED
|
@@ -659,13 +659,20 @@ module Clacky
|
|
|
659
659
|
end
|
|
660
660
|
end
|
|
661
661
|
|
|
662
|
-
{
|
|
662
|
+
result = {
|
|
663
663
|
content: message["content"],
|
|
664
664
|
tool_calls: parse_tool_calls(message["tool_calls"]),
|
|
665
665
|
finish_reason: data["choices"].first["finish_reason"],
|
|
666
666
|
usage: usage_data,
|
|
667
667
|
raw_api_usage: raw_api_usage
|
|
668
668
|
}
|
|
669
|
+
|
|
670
|
+
# Preserve reasoning_content if present (e.g. Kimi/Moonshot extended thinking).
|
|
671
|
+
# The API requires this field to be echoed back in the message history on
|
|
672
|
+
# subsequent requests, otherwise it returns HTTP 400.
|
|
673
|
+
result[:reasoning_content] = message["reasoning_content"] if message["reasoning_content"]
|
|
674
|
+
|
|
675
|
+
result
|
|
669
676
|
else
|
|
670
677
|
raise_error(response)
|
|
671
678
|
end
|
|
@@ -687,10 +687,38 @@ module Clacky
|
|
|
687
687
|
latest
|
|
688
688
|
end
|
|
689
689
|
|
|
690
|
-
# Query the latest openclacky version
|
|
691
|
-
#
|
|
692
|
-
#
|
|
690
|
+
# Query the latest openclacky version.
|
|
691
|
+
# Strategy: try RubyGems official REST API first (most accurate, not affected by mirror lag),
|
|
692
|
+
# then fall back to `gem list -r` (respects user's configured gem source).
|
|
693
693
|
private def fetch_latest_version_from_gem
|
|
694
|
+
fetch_latest_version_from_rubygems_api || fetch_latest_version_from_gem_command
|
|
695
|
+
end
|
|
696
|
+
|
|
697
|
+
# Try RubyGems official REST API — fast and always up-to-date.
|
|
698
|
+
# Returns nil if the request fails or times out.
|
|
699
|
+
private def fetch_latest_version_from_rubygems_api
|
|
700
|
+
require "net/http"
|
|
701
|
+
require "json"
|
|
702
|
+
|
|
703
|
+
uri = URI("https://rubygems.org/api/v1/gems/openclacky.json")
|
|
704
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
|
705
|
+
http.use_ssl = true
|
|
706
|
+
http.open_timeout = 5
|
|
707
|
+
http.read_timeout = 8
|
|
708
|
+
|
|
709
|
+
res = http.get(uri.request_uri)
|
|
710
|
+
return nil unless res.is_a?(Net::HTTPSuccess)
|
|
711
|
+
|
|
712
|
+
data = JSON.parse(res.body)
|
|
713
|
+
data["version"].to_s.strip.then { |v| v.empty? ? nil : v }
|
|
714
|
+
rescue StandardError
|
|
715
|
+
nil
|
|
716
|
+
end
|
|
717
|
+
|
|
718
|
+
# Fall back to `gem list -r openclacky` via login shell.
|
|
719
|
+
# Respects the user's configured gem source (rbenv/mise mirrors, etc.).
|
|
720
|
+
# Output format: "openclacky (0.9.0)"
|
|
721
|
+
private def fetch_latest_version_from_gem_command
|
|
694
722
|
shell = Clacky::Tools::Shell.new
|
|
695
723
|
result = shell.execute(command: "gem list -r openclacky", soft_timeout: 15, hard_timeout: 30)
|
|
696
724
|
return nil unless result[:exit_code] == 0
|
data/lib/clacky/tools/browser.rb
CHANGED
|
@@ -13,14 +13,24 @@ module Clacky
|
|
|
13
13
|
self.tool_description = <<~DESC
|
|
14
14
|
Browser automation for login-related operations (sign-in, OAuth, form submission requiring session). For simple page fetch or search, prefer web_fetch or web_search instead.
|
|
15
15
|
|
|
16
|
-
isolated
|
|
16
|
+
isolated: true = built-in browser (default, no setup, login persists). false = user's Chrome (keeps cookies/login, needs one-time debug setup; opens URLs in new tab).
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
18
|
+
SNAPSHOT — always run before interacting with a page. Refs (@e1, @e2...) expire after page changes, always re-snapshot before acting on a changed page:
|
|
19
|
+
- 'snapshot -i -C' — interactive + cursor-clickable elements (recommended default)
|
|
20
|
+
- 'snapshot -i' — interactive elements only (faster, for simple forms)
|
|
21
|
+
- 'snapshot' — full accessibility tree (when above miss elements)
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
|
|
23
|
+
ELEMENT SELECTION — prefer in this order:
|
|
24
|
+
1. Refs: 'click @e1', 'fill @e2 "text"'
|
|
25
|
+
2. Semantic find: 'find text "Submit" click', 'find role button "Login" click', 'find label "Email" fill "user@example.com"'
|
|
26
|
+
3. CSS: 'click "#submit-btn"'
|
|
27
|
+
|
|
28
|
+
OTHER COMMANDS:
|
|
29
|
+
- 'open <url>', 'back', 'reload', 'press Enter', 'key Control+a'
|
|
30
|
+
- 'scroll down/up', 'scrollintoview @e1', 'wait @e1', 'wait --text "..."', 'wait --load networkidle'
|
|
31
|
+
- 'dialog accept/dismiss', 'tab new <url>', 'tab <n>'
|
|
32
|
+
|
|
33
|
+
SCREENSHOT: NEVER call on your own — costs far more tokens than snapshot. Last resort only. Ask user first: "Screenshots cost more tokens. Approve?" When approved: 'screenshot --screenshot-format jpeg --screenshot-quality 50'.
|
|
24
34
|
DESC
|
|
25
35
|
self.tool_category = "web"
|
|
26
36
|
self.tool_parameters = {
|
|
@@ -47,11 +57,29 @@ module Clacky
|
|
|
47
57
|
CHROME_DEBUG_PORT = 9222
|
|
48
58
|
BROWSER_COMMAND_TIMEOUT = 30
|
|
49
59
|
CHROME_DEBUG_PAGE = "chrome://inspect/#remote-debugging"
|
|
60
|
+
MIN_AGENT_BROWSER_VERSION = "0.20.0"
|
|
50
61
|
|
|
51
62
|
def execute(command:, session: nil, isolated: nil, working_dir: nil)
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
return
|
|
63
|
+
# Handle explicit install command
|
|
64
|
+
if command.strip == "install"
|
|
65
|
+
return do_install_agent_browser
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
if !agent_browser_installed?
|
|
69
|
+
return {
|
|
70
|
+
error: "agent-browser not installed",
|
|
71
|
+
message: "agent-browser is required for browser automation but is not installed.",
|
|
72
|
+
instructions: "Tell the user: 'agent-browser is not installed. It's required for browser automation. Run `browser(command: \"install\")` to install it — this may take a minute. Would you like me to install it now?' Wait for user confirmation before calling install."
|
|
73
|
+
}
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
if agent_browser_outdated?
|
|
77
|
+
current = `agent-browser --version 2>/dev/null`.strip.split.last
|
|
78
|
+
return {
|
|
79
|
+
error: "agent-browser version too old",
|
|
80
|
+
message: "agent-browser #{current} is installed but version >= #{MIN_AGENT_BROWSER_VERSION} is required.",
|
|
81
|
+
instructions: "Tell the user: 'agent-browser needs to be upgraded from #{current} to #{MIN_AGENT_BROWSER_VERSION}+. Run `browser(command: \"install\")` to upgrade — this may take a minute. Would you like me to upgrade it now?' Wait for user confirmation before calling install."
|
|
82
|
+
}
|
|
55
83
|
end
|
|
56
84
|
|
|
57
85
|
# Default to built-in browser (isolated=true). Only use user's Chrome when explicitly isolated=false.
|
|
@@ -94,12 +122,6 @@ module Clacky
|
|
|
94
122
|
result = Shell.new.execute(command: full_command, hard_timeout: BROWSER_COMMAND_TIMEOUT, working_dir: working_dir)
|
|
95
123
|
end
|
|
96
124
|
|
|
97
|
-
if playwright_missing?(result)
|
|
98
|
-
pw_result = install_playwright_chromium
|
|
99
|
-
return pw_result if pw_result[:error]
|
|
100
|
-
result = Shell.new.execute(command: full_command, hard_timeout: BROWSER_COMMAND_TIMEOUT, working_dir: working_dir)
|
|
101
|
-
end
|
|
102
|
-
|
|
103
125
|
if use_auto_connect && !result[:success] && connection_error?(result)
|
|
104
126
|
if we_launched_chrome
|
|
105
127
|
result = Shell.new.execute(command: full_command, hard_timeout: BROWSER_COMMAND_TIMEOUT, working_dir: working_dir)
|
|
@@ -363,52 +385,23 @@ module Clacky
|
|
|
363
385
|
!!find_in_path(AGENT_BROWSER_BIN)
|
|
364
386
|
end
|
|
365
387
|
|
|
366
|
-
def
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
"Node.js not found; tried to install via mise but failed.\n\n" \
|
|
373
|
-
"Please run: mise install node@22 && mise use -g node@22"
|
|
374
|
-
}
|
|
375
|
-
end
|
|
376
|
-
|
|
377
|
-
result = Shell.new.execute(command: "#{npm} install -g agent-browser", hard_timeout: 120)
|
|
378
|
-
unless result[:success]
|
|
379
|
-
return {
|
|
380
|
-
error: "Failed to auto-install agent-browser",
|
|
381
|
-
message: "npm install -g agent-browser failed: #{result[:stderr]}\n\nPlease run it manually."
|
|
382
|
-
}
|
|
383
|
-
end
|
|
384
|
-
|
|
385
|
-
{}
|
|
386
|
-
end
|
|
387
|
-
|
|
388
|
-
def find_or_install_npm
|
|
389
|
-
npm = find_in_path("npm")
|
|
390
|
-
return npm if npm
|
|
391
|
-
|
|
392
|
-
mise = find_mise_bin
|
|
393
|
-
return nil unless mise
|
|
394
|
-
|
|
395
|
-
path = `#{Shellwords.escape(mise)} which npm 2>/dev/null`.strip
|
|
396
|
-
return path if path && !path.empty? && File.executable?(path)
|
|
397
|
-
system(mise, "install", "node@22", out: File::NULL, err: File::NULL)
|
|
398
|
-
system(mise, "use", "-g", "node@22", out: File::NULL, err: File::NULL)
|
|
399
|
-
|
|
400
|
-
path = `#{Shellwords.escape(mise)} which npm 2>/dev/null`.strip
|
|
401
|
-
return path if path && !path.empty? && File.executable?(path)
|
|
402
|
-
|
|
403
|
-
nil
|
|
388
|
+
def agent_browser_outdated?
|
|
389
|
+
version = `agent-browser --version 2>/dev/null`.strip.split.last
|
|
390
|
+
return false if version.nil? || version.empty?
|
|
391
|
+
Gem::Version.new(version) < Gem::Version.new(MIN_AGENT_BROWSER_VERSION)
|
|
392
|
+
rescue StandardError
|
|
393
|
+
false
|
|
404
394
|
end
|
|
405
395
|
|
|
406
|
-
def
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
396
|
+
def do_install_agent_browser
|
|
397
|
+
script = File.expand_path("../../../../scripts/install_agent_browser.sh", __FILE__)
|
|
398
|
+
result = Shell.new.execute(command: "bash #{Shellwords.escape(script)}", hard_timeout: 180)
|
|
399
|
+
if result[:success]
|
|
400
|
+
version = `agent-browser --version 2>/dev/null`.strip.split.last
|
|
401
|
+
{ success: true, message: "agent-browser #{version} installed successfully. You can now use browser commands." }
|
|
402
|
+
else
|
|
403
|
+
{ error: "Failed to install agent-browser", message: result[:stdout].to_s.strip }
|
|
404
|
+
end
|
|
412
405
|
end
|
|
413
406
|
|
|
414
407
|
def command_name_for_temp(command)
|
|
@@ -445,25 +438,6 @@ module Clacky
|
|
|
445
438
|
{ content: first_part.join + notice, temp_file: temp_file }
|
|
446
439
|
end
|
|
447
440
|
|
|
448
|
-
def playwright_missing?(result)
|
|
449
|
-
output = "#{result[:stdout]}#{result[:stderr]}"
|
|
450
|
-
output.include?("Executable doesn't exist") ||
|
|
451
|
-
output.include?("Please run the following command to download new browsers")
|
|
452
|
-
end
|
|
453
|
-
|
|
454
|
-
def install_playwright_chromium
|
|
455
|
-
playwright = find_in_path("playwright")
|
|
456
|
-
cmd = playwright ? "#{playwright} install chromium" : "npx playwright install chromium"
|
|
457
|
-
|
|
458
|
-
result = Shell.new.execute(command: cmd, hard_timeout: 300)
|
|
459
|
-
unless result[:success]
|
|
460
|
-
return {
|
|
461
|
-
error: "Failed to install Playwright Chromium",
|
|
462
|
-
message: "Automatic browser installation failed. Please run manually:\n npx playwright install chromium"
|
|
463
|
-
}
|
|
464
|
-
end
|
|
465
|
-
{}
|
|
466
|
-
end
|
|
467
441
|
end
|
|
468
442
|
end
|
|
469
443
|
end
|
|
@@ -59,8 +59,15 @@ module Clacky
|
|
|
59
59
|
screen.clear_line
|
|
60
60
|
end
|
|
61
61
|
|
|
62
|
-
#
|
|
63
|
-
|
|
62
|
+
# When input is paused (InlineInput active), fixed_area_start_row has grown
|
|
63
|
+
# (input_area.required_height returns 0 while paused), so the cleared rows
|
|
64
|
+
# now belong to the output area. Re-render output from buffer to fill them in.
|
|
65
|
+
if input_area.paused?
|
|
66
|
+
render_output_from_buffer
|
|
67
|
+
else
|
|
68
|
+
# Re-render fixed areas at new position
|
|
69
|
+
render_fixed_areas
|
|
70
|
+
end
|
|
64
71
|
screen.flush
|
|
65
72
|
end
|
|
66
73
|
end
|
data/lib/clacky/version.rb
CHANGED
data/scripts/install.sh
CHANGED
|
@@ -590,40 +590,9 @@ main() {
|
|
|
590
590
|
# Install agent-browser (browser automation tool)
|
|
591
591
|
# This step is optional — failures are silently skipped with a hint.
|
|
592
592
|
install_agent_browser() {
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
if ! command_exists npm; then
|
|
597
|
-
if command_exists mise || [ -x "$HOME/.local/bin/mise" ]; then
|
|
598
|
-
print_info "Installing Node.js via mise..."
|
|
599
|
-
"$HOME/.local/bin/mise" install node@22 > /dev/null 2>&1 || true
|
|
600
|
-
"$HOME/.local/bin/mise" use -g node@22 > /dev/null 2>&1 || true
|
|
601
|
-
# Reload mise so node/npm are on PATH
|
|
602
|
-
eval "$("$HOME/.local/bin/mise" activate bash 2>/dev/null)" 2>/dev/null || true
|
|
603
|
-
fi
|
|
604
|
-
fi
|
|
605
|
-
|
|
606
|
-
if ! command_exists npm; then
|
|
607
|
-
print_warning "agent-browser skipped (Node.js/npm not found)."
|
|
608
|
-
print_info "To enable browser automation later:"
|
|
609
|
-
print_info " mise install node@22 && mise use -g node@22 && npm install -g agent-browser"
|
|
610
|
-
return 0
|
|
611
|
-
fi
|
|
612
|
-
|
|
613
|
-
if command_exists agent-browser; then
|
|
614
|
-
print_success "agent-browser already installed"
|
|
615
|
-
return 0
|
|
616
|
-
fi
|
|
617
|
-
|
|
618
|
-
print_info "Running: npm install -g agent-browser"
|
|
619
|
-
if npm install -g agent-browser > /dev/null 2>&1; then
|
|
620
|
-
print_success "agent-browser installed"
|
|
621
|
-
else
|
|
622
|
-
print_warning "agent-browser installation failed — skipping."
|
|
623
|
-
print_info "To install manually later: npm install -g agent-browser"
|
|
624
|
-
fi
|
|
625
|
-
|
|
626
|
-
return 0
|
|
593
|
+
local script_dir
|
|
594
|
+
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
595
|
+
bash "$script_dir/install_agent_browser.sh" || true
|
|
627
596
|
}
|
|
628
597
|
|
|
629
598
|
# Post-installation information
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Install or upgrade agent-browser (browser automation tool)
|
|
3
|
+
# Can be sourced by install.sh or run standalone (e.g. from Ruby via shell)
|
|
4
|
+
#
|
|
5
|
+
# Exit codes:
|
|
6
|
+
# 0 — success (installed/upgraded)
|
|
7
|
+
# 1 — failure (npm not found or install failed)
|
|
8
|
+
|
|
9
|
+
set -e
|
|
10
|
+
|
|
11
|
+
RED='\033[0;31m'
|
|
12
|
+
GREEN='\033[0;32m'
|
|
13
|
+
YELLOW='\033[1;33m'
|
|
14
|
+
BLUE='\033[0;34m'
|
|
15
|
+
NC='\033[0m'
|
|
16
|
+
|
|
17
|
+
print_info() { echo -e "${BLUE}ℹ${NC} $1"; }
|
|
18
|
+
print_success() { echo -e "${GREEN}✓${NC} $1"; }
|
|
19
|
+
print_warning() { echo -e "${YELLOW}⚠${NC} $1"; }
|
|
20
|
+
print_error() { echo -e "${RED}✗${NC} $1"; }
|
|
21
|
+
print_step() { echo -e "\n${BLUE}==>${NC} $1"; }
|
|
22
|
+
|
|
23
|
+
command_exists() { command -v "$1" >/dev/null 2>&1; }
|
|
24
|
+
|
|
25
|
+
print_step "Installing agent-browser..."
|
|
26
|
+
|
|
27
|
+
# Try to find npm; if missing, attempt to install Node.js via mise
|
|
28
|
+
if ! command_exists npm; then
|
|
29
|
+
mise_bin=""
|
|
30
|
+
if command_exists mise; then
|
|
31
|
+
mise_bin="mise"
|
|
32
|
+
elif [ -x "$HOME/.local/bin/mise" ]; then
|
|
33
|
+
mise_bin="$HOME/.local/bin/mise"
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
if [ -n "$mise_bin" ]; then
|
|
37
|
+
print_info "Installing Node.js via mise..."
|
|
38
|
+
"$mise_bin" install node@22 > /dev/null 2>&1 || true
|
|
39
|
+
"$mise_bin" use -g node@22 > /dev/null 2>&1 || true
|
|
40
|
+
eval "$("$mise_bin" activate bash 2>/dev/null)" 2>/dev/null || true
|
|
41
|
+
fi
|
|
42
|
+
fi
|
|
43
|
+
|
|
44
|
+
if ! command_exists npm; then
|
|
45
|
+
print_error "agent-browser installation failed: Node.js/npm not found."
|
|
46
|
+
print_info "Please run: mise install node@22 && mise use -g node@22 && npm install -g agent-browser"
|
|
47
|
+
exit 1
|
|
48
|
+
fi
|
|
49
|
+
|
|
50
|
+
print_info "Running: npm install -g agent-browser"
|
|
51
|
+
if npm install -g agent-browser > /dev/null 2>&1; then
|
|
52
|
+
version=$(agent-browser --version 2>/dev/null | awk '{print $NF}')
|
|
53
|
+
print_success "agent-browser ${version} installed/updated"
|
|
54
|
+
else
|
|
55
|
+
print_error "agent-browser installation failed."
|
|
56
|
+
print_info "To install manually: npm install -g agent-browser"
|
|
57
|
+
exit 1
|
|
58
|
+
fi
|
|
59
|
+
|
|
60
|
+
print_info "Installing Playwright Chromium..."
|
|
61
|
+
if npx playwright install chromium > /dev/null 2>&1; then
|
|
62
|
+
print_success "Playwright Chromium installed"
|
|
63
|
+
else
|
|
64
|
+
print_error "Playwright Chromium installation failed."
|
|
65
|
+
print_info "To install manually: npx playwright install chromium"
|
|
66
|
+
exit 1
|
|
67
|
+
fi
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: openclacky
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.9.
|
|
4
|
+
version: 0.9.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- windy
|
|
@@ -397,6 +397,7 @@ files:
|
|
|
397
397
|
- lib/clacky/web/version.js
|
|
398
398
|
- lib/clacky/web/ws.js
|
|
399
399
|
- scripts/install.sh
|
|
400
|
+
- scripts/install_agent_browser.sh
|
|
400
401
|
- scripts/uninstall.sh
|
|
401
402
|
- sig/clacky.rbs
|
|
402
403
|
homepage: https://github.com/yafeilee/clacky
|