openclacky 1.1.6 → 1.2.0
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 +37 -0
- data/CODE_OF_CONDUCT.md +1 -1
- data/CONTRIBUTING.md +92 -0
- data/README.md +10 -0
- data/README_CN.md +10 -0
- data/ROADMAP.md +29 -0
- data/docs/billing-system.md +340 -0
- data/docs/mcp-architecture.md +114 -0
- data/docs/mcp.example.json +22 -0
- data/lib/clacky/agent/cost_tracker.rb +37 -0
- data/lib/clacky/agent/llm_caller.rb +0 -1
- data/lib/clacky/agent/session_serializer.rb +2 -11
- data/lib/clacky/agent/skill_manager.rb +73 -26
- data/lib/clacky/agent/system_prompt_builder.rb +0 -5
- data/lib/clacky/agent/time_machine.rb +6 -0
- data/lib/clacky/agent.rb +26 -1
- data/lib/clacky/agent_config.rb +9 -19
- data/lib/clacky/billing/billing_record.rb +67 -0
- data/lib/clacky/billing/billing_store.rb +193 -0
- data/lib/clacky/cli.rb +108 -6
- data/lib/clacky/default_skills/browser-setup/SKILL.md +26 -4
- data/lib/clacky/default_skills/mcp-manager/SKILL.md +343 -0
- data/lib/clacky/idle_compression_timer.rb +4 -2
- data/lib/clacky/mcp/client.rb +204 -0
- data/lib/clacky/mcp/http_transport.rb +155 -0
- data/lib/clacky/mcp/registry.rb +229 -0
- data/lib/clacky/mcp/skill_provider.rb +75 -0
- data/lib/clacky/mcp/stdio_transport.rb +112 -0
- data/lib/clacky/mcp/transport.rb +23 -0
- data/lib/clacky/mcp/virtual_skill.rb +131 -0
- data/lib/clacky/message_history.rb +0 -1
- data/lib/clacky/server/channel/adapters/weixin/adapter.rb +2 -35
- data/lib/clacky/server/http_server.rb +519 -15
- data/lib/clacky/server/server_master.rb +8 -14
- data/lib/clacky/server/session_registry.rb +24 -2
- data/lib/clacky/server/web_ui_controller.rb +4 -0
- data/lib/clacky/session_manager.rb +41 -12
- data/lib/clacky/skill.rb +1 -5
- data/lib/clacky/skill_loader.rb +36 -5
- data/lib/clacky/tools/browser.rb +217 -38
- data/lib/clacky/tools/trash_manager.rb +154 -3
- data/lib/clacky/ui2/components/command_suggestions.rb +6 -2
- data/lib/clacky/ui_interface.rb +1 -0
- data/lib/clacky/utils/model_pricing.rb +11 -7
- data/lib/clacky/utils/trash_directory.rb +37 -6
- data/lib/clacky/version.rb +1 -1
- data/lib/clacky/web/app.css +2907 -1764
- data/lib/clacky/web/app.js +84 -10
- data/lib/clacky/web/billing.js +275 -0
- data/lib/clacky/web/brand.js +3 -0
- data/lib/clacky/web/i18n.js +242 -24
- data/lib/clacky/web/index.html +351 -134
- data/lib/clacky/web/mcp.js +328 -0
- data/lib/clacky/web/sessions.js +193 -11
- data/lib/clacky/web/settings.js +686 -174
- data/lib/clacky/web/sidebar.js +2 -0
- data/lib/clacky/web/trash.js +323 -60
- data/lib/clacky/web/ws-dispatcher.js +14 -1
- data/lib/clacky.rb +4 -0
- data/scripts/install.ps1 +23 -11
- metadata +30 -10
|
@@ -111,6 +111,10 @@ module Clacky
|
|
|
111
111
|
# - "cache miss input" = regular prompt_tokens rate
|
|
112
112
|
# - "cache hit input" = cache_read rate (DeepSeek has no separate cache-write charge)
|
|
113
113
|
# - No tiered pricing (single rate regardless of context length)
|
|
114
|
+
# Cache-hit prices are 1/10 of launch (global, permanent since 2026-04-26).
|
|
115
|
+
# v4-pro is on a 75% off promo through 2026-05-31 23:59 CST; the same
|
|
116
|
+
# numbers become the permanent price after that date (= original × 1/4),
|
|
117
|
+
# so we bill at the discounted rates both before and after the cutover.
|
|
114
118
|
"deepseek-v4-flash" => {
|
|
115
119
|
input: {
|
|
116
120
|
default: 0.14, # $0.14/MTok cache miss
|
|
@@ -122,22 +126,22 @@ module Clacky
|
|
|
122
126
|
},
|
|
123
127
|
cache: {
|
|
124
128
|
write: 0.14, # DeepSeek doesn't charge extra for writes; bill at miss rate
|
|
125
|
-
read: 0.0028
|
|
129
|
+
read: 0.0028 # $0.0028/MTok cache hit
|
|
126
130
|
}
|
|
127
131
|
},
|
|
128
132
|
|
|
129
133
|
"deepseek-v4-pro" => {
|
|
130
134
|
input: {
|
|
131
|
-
default:
|
|
132
|
-
over_200k:
|
|
135
|
+
default: 0.435, # $0.435/MTok cache miss (75% off; permanent after 5/31)
|
|
136
|
+
over_200k: 0.435
|
|
133
137
|
},
|
|
134
138
|
output: {
|
|
135
|
-
default:
|
|
136
|
-
over_200k:
|
|
139
|
+
default: 0.87, # $0.87/MTok (75% off; permanent after 5/31)
|
|
140
|
+
over_200k: 0.87
|
|
137
141
|
},
|
|
138
142
|
cache: {
|
|
139
|
-
write:
|
|
140
|
-
read: 0.
|
|
143
|
+
write: 0.435, # no separate write charge; bill at miss rate
|
|
144
|
+
read: 0.003625 # $0.003625/MTok cache hit (1/10 × 75% off)
|
|
141
145
|
}
|
|
142
146
|
},
|
|
143
147
|
|
|
@@ -4,17 +4,28 @@ require "digest"
|
|
|
4
4
|
require "fileutils"
|
|
5
5
|
|
|
6
6
|
module Clacky
|
|
7
|
-
# Manages global trash directory at ~/.clacky/trash
|
|
8
|
-
#
|
|
7
|
+
# Manages global trash directory at ~/.clacky/trash.
|
|
8
|
+
# Organises both file-trash and session-trash under one root:
|
|
9
|
+
# ~/.clacky/trash/
|
|
10
|
+
# ├── file-trash/ ← AI-deleted project files, keyed by project hash
|
|
11
|
+
# └── sessions-trash/ ← soft-deleted sessions (JSON + chunk MD files)
|
|
9
12
|
class TrashDirectory
|
|
10
13
|
GLOBAL_TRASH_ROOT = File.join(Dir.home, ".clacky", "trash")
|
|
11
14
|
|
|
15
|
+
def self.files_trash_dir
|
|
16
|
+
File.join(GLOBAL_TRASH_ROOT, "file-trash")
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def self.sessions_trash_dir
|
|
20
|
+
File.join(GLOBAL_TRASH_ROOT, "sessions-trash")
|
|
21
|
+
end
|
|
22
|
+
|
|
12
23
|
attr_reader :project_root, :trash_dir, :backup_dir
|
|
13
24
|
|
|
14
25
|
def initialize(project_root = Dir.pwd)
|
|
15
26
|
@project_root = File.expand_path(project_root)
|
|
16
27
|
@project_hash = generate_project_hash(@project_root)
|
|
17
|
-
@trash_dir = File.join(
|
|
28
|
+
@trash_dir = File.join(self.class.files_trash_dir, @project_hash)
|
|
18
29
|
@backup_dir = File.join(@trash_dir, "backups")
|
|
19
30
|
|
|
20
31
|
setup_directories
|
|
@@ -63,12 +74,32 @@ module Clacky
|
|
|
63
74
|
warn "Warning: Could not create project metadata: #{e.message}"
|
|
64
75
|
end
|
|
65
76
|
|
|
77
|
+
# ── Legacy migration ──────────────────────────────────────────────
|
|
78
|
+
|
|
79
|
+
OLD_TRASH_ROOT = File.join(Dir.home, ".clacky", "trash")
|
|
80
|
+
|
|
81
|
+
# One-time: move pre-file-trash project hash dirs from ~/.clacky/trash/
|
|
82
|
+
# directly into the new file-trash/ subdirectory. Safe to call on every boot.
|
|
83
|
+
def self.migrate_legacy_if_needed
|
|
84
|
+
return unless Dir.exist?(OLD_TRASH_ROOT)
|
|
85
|
+
|
|
86
|
+
FileUtils.mkdir_p(files_trash_dir)
|
|
87
|
+
|
|
88
|
+
Dir.glob(File.join(OLD_TRASH_ROOT, "*")).each do |entry|
|
|
89
|
+
basename = File.basename(entry)
|
|
90
|
+
next if %w[file-trash sessions-trash].include?(basename)
|
|
91
|
+
next if File.directory?(File.join(files_trash_dir, basename))
|
|
92
|
+
|
|
93
|
+
FileUtils.mv(entry, files_trash_dir)
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
66
97
|
# Get all project directories that have trash
|
|
67
98
|
def self.all_projects
|
|
68
|
-
return [] unless Dir.exist?(
|
|
99
|
+
return [] unless Dir.exist?(files_trash_dir)
|
|
69
100
|
|
|
70
101
|
projects = []
|
|
71
|
-
Dir.glob(File.join(
|
|
102
|
+
Dir.glob(File.join(files_trash_dir, "*", ".project_metadata.json")).each do |metadata_file|
|
|
72
103
|
begin
|
|
73
104
|
metadata = JSON.parse(File.read(metadata_file))
|
|
74
105
|
projects << {
|
|
@@ -93,7 +124,7 @@ module Clacky
|
|
|
93
124
|
|
|
94
125
|
# Clean up trash directories for non-existent projects
|
|
95
126
|
def self.cleanup_orphaned_projects
|
|
96
|
-
return 0 unless Dir.exist?(
|
|
127
|
+
return 0 unless Dir.exist?(files_trash_dir)
|
|
97
128
|
|
|
98
129
|
cleaned_count = 0
|
|
99
130
|
all_projects.each do |project|
|
data/lib/clacky/version.rb
CHANGED