openclacky 1.0.2 → 1.0.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +31 -0
- data/benchmark/fixtures/sample_project/Gemfile +3 -0
- data/benchmark/fixtures/sample_project/lib/api_handler.rb +32 -0
- data/benchmark/fixtures/sample_project/lib/order_calculator.rb +23 -0
- data/benchmark/fixtures/sample_project/lib/user_renderer.rb +20 -0
- data/benchmark/fixtures/sample_project/spec/order_calculator_spec.rb +20 -0
- data/benchmark/results/EVALUATION_REPORT.md +165 -0
- data/benchmark/results/baseline_20260511_174424.json +128 -0
- data/benchmark/results/report_20260511_175256.json +271 -0
- data/benchmark/results/report_20260511_175444.json +271 -0
- data/benchmark/results/treatment_20260511_175103.json +130 -0
- data/benchmark/runner.rb +441 -0
- data/docs/proposals/2026-05-11-system-prompt-alignment.md +325 -0
- data/docs/proposals/2026-05-12-memory-mechanism-optimization.md +89 -0
- data/lib/clacky/agent/cost_tracker.rb +8 -2
- data/lib/clacky/agent/llm_caller.rb +218 -0
- data/lib/clacky/agent/memory_updater.rb +41 -30
- data/lib/clacky/agent/message_compressor.rb +15 -4
- data/lib/clacky/agent/message_compressor_helper.rb +41 -2
- data/lib/clacky/agent/skill_manager.rb +5 -2
- data/lib/clacky/agent/skill_reflector.rb +10 -1
- data/lib/clacky/agent/tool_registry.rb +109 -0
- data/lib/clacky/agent.rb +20 -0
- data/lib/clacky/agent_config.rb +17 -0
- data/lib/clacky/cli.rb +65 -0
- data/lib/clacky/client.rb +15 -0
- data/lib/clacky/default_agents/base_prompt.md +20 -20
- data/lib/clacky/default_agents/coding/system_prompt.md +51 -1
- data/lib/clacky/default_skills/channel-setup/SKILL.md +113 -5
- data/lib/clacky/default_skills/channel-setup/import_lark_skills.rb +97 -0
- data/lib/clacky/default_skills/onboard/SKILL.md +1 -1
- data/lib/clacky/default_skills/persist-memory/SKILL.md +59 -0
- data/lib/clacky/providers.rb +48 -6
- data/lib/clacky/server/channel/adapters/weixin/adapter.rb +7 -0
- data/lib/clacky/server/channel/channel_manager.rb +91 -0
- data/lib/clacky/server/discover.rb +77 -0
- data/lib/clacky/server/epipe_safe_io.rb +105 -0
- data/lib/clacky/server/http_server.rb +121 -41
- data/lib/clacky/server/server_master.rb +6 -0
- data/lib/clacky/skill.rb +30 -0
- data/lib/clacky/utils/file_processor.rb +71 -0
- data/lib/clacky/version.rb +1 -1
- data/lib/clacky/web/app.css +58 -22
- data/lib/clacky/web/i18n.js +4 -2
- data/lib/clacky/web/sessions.js +29 -17
- metadata +33 -2
data/lib/clacky/web/sessions.js
CHANGED
|
@@ -1492,7 +1492,7 @@ const Sessions = (() => {
|
|
|
1492
1492
|
: "";
|
|
1493
1493
|
|
|
1494
1494
|
// Pin icon (always visible for pinned sessions)
|
|
1495
|
-
const pinIcon = s.pinned ? `<span class="session-pin-icon"
|
|
1495
|
+
const pinIcon = s.pinned ? `<span class="session-pin-icon"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" style="transform:rotate(45deg);display:block"><line x1="12" y1="17" x2="12" y2="22"/><path d="M5 17h14v-1.76a2 2 0 0 0-1.11-1.79l-1.78-.9A2 2 0 0 1 15 10.76V6h1a2 2 0 0 0 0-4H8a2 2 0 0 0 0 4h1v4.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24Z"/></svg></span>` : "";
|
|
1496
1496
|
|
|
1497
1497
|
// Status dot: only rendered for non-idle states. Idle is the default
|
|
1498
1498
|
// state for 95% of sessions and doesn't deserve a persistent visual marker.
|
|
@@ -1505,7 +1505,7 @@ const Sessions = (() => {
|
|
|
1505
1505
|
<div class="session-name">${dotHtml}<span class="session-name__text">${escapeHtml(displayName)}</span>${badgeHtml}${codingBadgeHtml}${pinIcon}</div>
|
|
1506
1506
|
<div class="session-meta">${metaText}</div>
|
|
1507
1507
|
</div>
|
|
1508
|
-
<button class="session-actions-btn" title="Actions"
|
|
1508
|
+
<button class="session-actions-btn" title="Actions"><svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="2.5" cy="7" r="1.2" fill="currentColor"/><circle cx="7" cy="7" r="1.2" fill="currentColor"/><circle cx="11.5" cy="7" r="1.2" fill="currentColor"/></svg></button>`;
|
|
1509
1509
|
|
|
1510
1510
|
// Use a click timer to distinguish single-click (select) from double-click (old rename behavior).
|
|
1511
1511
|
let clickTimer = null;
|
|
@@ -1618,7 +1618,7 @@ const Sessions = (() => {
|
|
|
1618
1618
|
// session when renderList() forces scroll-to-active.
|
|
1619
1619
|
const sidebarList = document.getElementById("sidebar-list");
|
|
1620
1620
|
const savedScrollTop = sidebarList ? sidebarList.scrollTop : 0;
|
|
1621
|
-
Sessions.renderList();
|
|
1621
|
+
Sessions.renderList({ skipScrollToActive: true });
|
|
1622
1622
|
|
|
1623
1623
|
try {
|
|
1624
1624
|
// Cursor: oldest created_at in the current list, EXCLUDING pinned
|
|
@@ -1651,7 +1651,7 @@ const Sessions = (() => {
|
|
|
1651
1651
|
console.error("loadMore error:", e);
|
|
1652
1652
|
} finally {
|
|
1653
1653
|
_loadingMore = false;
|
|
1654
|
-
Sessions.renderList();
|
|
1654
|
+
Sessions.renderList({ skipScrollToActive: true });
|
|
1655
1655
|
// Restore scroll position so the user stays where they were
|
|
1656
1656
|
if (sidebarList) sidebarList.scrollTop = savedScrollTop;
|
|
1657
1657
|
}
|
|
@@ -1826,7 +1826,7 @@ const Sessions = (() => {
|
|
|
1826
1826
|
|
|
1827
1827
|
// ── Rendering ─────────────────────────────────────────────────────────
|
|
1828
1828
|
|
|
1829
|
-
renderList() {
|
|
1829
|
+
renderList({ skipScrollToActive = false } = {}) {
|
|
1830
1830
|
// Sort helper: pinned first, then newest-first by created_at
|
|
1831
1831
|
const byPinnedAndTime = (a, b) => {
|
|
1832
1832
|
// Pinned sessions always come first
|
|
@@ -1877,15 +1877,17 @@ const Sessions = (() => {
|
|
|
1877
1877
|
if (_hasMore) list.appendChild(_makeLoadMoreBtn());
|
|
1878
1878
|
|
|
1879
1879
|
// Scroll active session into view so the sidebar always shows the current session.
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1880
|
+
if (!skipScrollToActive) {
|
|
1881
|
+
const activeEl = list.querySelector(".session-item.active");
|
|
1882
|
+
if (activeEl) {
|
|
1883
|
+
// If the active session is the very first item, scroll to top of the sidebar
|
|
1884
|
+
// container so sticky headers / expanded panels don't obscure it.
|
|
1885
|
+
if (activeEl === list.firstElementChild) {
|
|
1886
|
+
const sidebarList = document.getElementById("sidebar-list");
|
|
1887
|
+
if (sidebarList) sidebarList.scrollTop = 0;
|
|
1888
|
+
} else {
|
|
1889
|
+
activeEl.scrollIntoView({ block: "nearest" });
|
|
1890
|
+
}
|
|
1889
1891
|
}
|
|
1890
1892
|
}
|
|
1891
1893
|
},
|
|
@@ -1961,17 +1963,27 @@ const Sessions = (() => {
|
|
|
1961
1963
|
// Close any existing menu first
|
|
1962
1964
|
Sessions._closeActionsMenu();
|
|
1963
1965
|
|
|
1966
|
+
// Lucide-style stroked icons to match the rest of the UI
|
|
1967
|
+
const iconPin = `<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="transform:rotate(45deg);display:block"><path d="M12 17v5"/><path d="M9 10.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24V16a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-.76a2 2 0 0 0-1.11-1.79l-1.78-.9A2 2 0 0 1 15 10.76V7a1 1 0 0 1 1-1 2 2 0 0 0 0-4H8a2 2 0 0 0 0 4 1 1 0 0 1 1 1z"/></svg>`;
|
|
1968
|
+
const iconRename = `<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 20h9"/><path d="M16.5 3.5a2.121 2.121 0 1 1 3 3L7 19l-4 1 1-4z"/></svg>`;
|
|
1969
|
+
const iconTrash = `<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 6h18"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"/><path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/><line x1="10" y1="11" x2="10" y2="17"/><line x1="14" y1="11" x2="14" y2="17"/></svg>`;
|
|
1970
|
+
|
|
1971
|
+
const pinLabel = session.pinned ? I18n.t("sessions.actions.unpin") : I18n.t("sessions.actions.pin");
|
|
1972
|
+
|
|
1964
1973
|
const menu = document.createElement("div");
|
|
1965
1974
|
menu.className = "session-actions-menu";
|
|
1966
1975
|
menu.innerHTML = `
|
|
1967
1976
|
<div class="session-actions-menu-item" data-action="pin">
|
|
1968
|
-
|
|
1977
|
+
<span class="session-actions-menu-icon">${iconPin}</span>
|
|
1978
|
+
<span class="session-actions-menu-label">${escapeHtml(pinLabel)}</span>
|
|
1969
1979
|
</div>
|
|
1970
1980
|
<div class="session-actions-menu-item" data-action="rename">
|
|
1971
|
-
|
|
1981
|
+
<span class="session-actions-menu-icon">${iconRename}</span>
|
|
1982
|
+
<span class="session-actions-menu-label">${escapeHtml(I18n.t("sessions.actions.rename"))}</span>
|
|
1972
1983
|
</div>
|
|
1973
1984
|
<div class="session-actions-menu-item session-actions-menu-item--danger" data-action="delete">
|
|
1974
|
-
|
|
1985
|
+
<span class="session-actions-menu-icon">${iconTrash}</span>
|
|
1986
|
+
<span class="session-actions-menu-label">${escapeHtml(I18n.t("sessions.actions.delete"))}</span>
|
|
1975
1987
|
</div>
|
|
1976
1988
|
`;
|
|
1977
1989
|
|
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.0.
|
|
4
|
+
version: 1.0.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-
|
|
11
|
+
date: 2026-05-11 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: faraday
|
|
@@ -156,6 +156,20 @@ dependencies:
|
|
|
156
156
|
- - ">="
|
|
157
157
|
- !ruby/object:Gem::Version
|
|
158
158
|
version: 0.1.0
|
|
159
|
+
- !ruby/object:Gem::Dependency
|
|
160
|
+
name: logger
|
|
161
|
+
requirement: !ruby/object:Gem::Requirement
|
|
162
|
+
requirements:
|
|
163
|
+
- - ">="
|
|
164
|
+
- !ruby/object:Gem::Version
|
|
165
|
+
version: '1.4'
|
|
166
|
+
type: :runtime
|
|
167
|
+
prerelease: false
|
|
168
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
169
|
+
requirements:
|
|
170
|
+
- - ">="
|
|
171
|
+
- !ruby/object:Gem::Version
|
|
172
|
+
version: '1.4'
|
|
159
173
|
- !ruby/object:Gem::Dependency
|
|
160
174
|
name: websocket
|
|
161
175
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -269,6 +283,17 @@ files:
|
|
|
269
283
|
- LICENSE.txt
|
|
270
284
|
- README.md
|
|
271
285
|
- Rakefile
|
|
286
|
+
- benchmark/fixtures/sample_project/Gemfile
|
|
287
|
+
- benchmark/fixtures/sample_project/lib/api_handler.rb
|
|
288
|
+
- benchmark/fixtures/sample_project/lib/order_calculator.rb
|
|
289
|
+
- benchmark/fixtures/sample_project/lib/user_renderer.rb
|
|
290
|
+
- benchmark/fixtures/sample_project/spec/order_calculator_spec.rb
|
|
291
|
+
- benchmark/results/EVALUATION_REPORT.md
|
|
292
|
+
- benchmark/results/baseline_20260511_174424.json
|
|
293
|
+
- benchmark/results/report_20260511_175256.json
|
|
294
|
+
- benchmark/results/report_20260511_175444.json
|
|
295
|
+
- benchmark/results/treatment_20260511_175103.json
|
|
296
|
+
- benchmark/runner.rb
|
|
272
297
|
- bin/clacky
|
|
273
298
|
- bin/clarky
|
|
274
299
|
- bin/openclacky
|
|
@@ -286,6 +311,8 @@ files:
|
|
|
286
311
|
- docs/install-script-simplification.md
|
|
287
312
|
- docs/memory-architecture.md
|
|
288
313
|
- docs/openclacky_cloud_api_reference.md
|
|
314
|
+
- docs/proposals/2026-05-11-system-prompt-alignment.md
|
|
315
|
+
- docs/proposals/2026-05-12-memory-mechanism-optimization.md
|
|
289
316
|
- docs/security-design.md
|
|
290
317
|
- docs/session-management-redesign.md
|
|
291
318
|
- docs/session-skill-invocation.md
|
|
@@ -338,6 +365,7 @@ files:
|
|
|
338
365
|
- lib/clacky/default_skills/browser-setup/SKILL.md
|
|
339
366
|
- lib/clacky/default_skills/channel-setup/SKILL.md
|
|
340
367
|
- lib/clacky/default_skills/channel-setup/feishu_setup.rb
|
|
368
|
+
- lib/clacky/default_skills/channel-setup/import_lark_skills.rb
|
|
341
369
|
- lib/clacky/default_skills/channel-setup/weixin_setup.rb
|
|
342
370
|
- lib/clacky/default_skills/code-explorer/SKILL.md
|
|
343
371
|
- lib/clacky/default_skills/cron-task-creator/SKILL.md
|
|
@@ -348,6 +376,7 @@ files:
|
|
|
348
376
|
- lib/clacky/default_skills/onboard/SKILL.md
|
|
349
377
|
- lib/clacky/default_skills/onboard/scripts/import_external_skills.rb
|
|
350
378
|
- lib/clacky/default_skills/onboard/scripts/install_builtin_skills.rb
|
|
379
|
+
- lib/clacky/default_skills/persist-memory/SKILL.md
|
|
351
380
|
- lib/clacky/default_skills/personal-website/SKILL.md
|
|
352
381
|
- lib/clacky/default_skills/personal-website/publish.rb
|
|
353
382
|
- lib/clacky/default_skills/product-help/SKILL.md
|
|
@@ -395,6 +424,8 @@ files:
|
|
|
395
424
|
- lib/clacky/server/channel/channel_config.rb
|
|
396
425
|
- lib/clacky/server/channel/channel_manager.rb
|
|
397
426
|
- lib/clacky/server/channel/channel_ui_controller.rb
|
|
427
|
+
- lib/clacky/server/discover.rb
|
|
428
|
+
- lib/clacky/server/epipe_safe_io.rb
|
|
398
429
|
- lib/clacky/server/http_server.rb
|
|
399
430
|
- lib/clacky/server/scheduler.rb
|
|
400
431
|
- lib/clacky/server/server_master.rb
|