openclacky 1.3.0 → 1.3.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.
@@ -93,9 +93,71 @@ const Workspace = (() => {
93
93
  row.addEventListener("click", () => downloadFile(entry));
94
94
  }
95
95
 
96
+ row.addEventListener("contextmenu", (e) => {
97
+ e.preventDefault();
98
+ showContextMenu(e, entry);
99
+ });
100
+
96
101
  return node;
97
102
  }
98
103
 
104
+ function showContextMenu(e, entry) {
105
+ closeContextMenu();
106
+
107
+ const iconFolder = '<svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/></svg>';
108
+
109
+ const menu = document.createElement("div");
110
+ menu.className = "wt-context-menu session-context-menu";
111
+ menu.innerHTML = `
112
+ <div class="session-actions-menu-item" data-action="reveal">
113
+ <span class="session-actions-menu-icon">${iconFolder}</span>
114
+ <span class="session-actions-menu-label">${t("workspace.revealInFinder")}</span>
115
+ </div>
116
+ `;
117
+
118
+ document.body.appendChild(menu);
119
+ menu.addEventListener("contextmenu", (e) => e.preventDefault());
120
+ menu.style.position = "fixed";
121
+ menu.style.top = e.clientY + "px";
122
+ menu.style.left = e.clientX + "px";
123
+ requestAnimationFrame(() => {
124
+ const r = menu.getBoundingClientRect();
125
+ if (r.right > window.innerWidth) menu.style.left = (window.innerWidth - r.width - 8) + "px";
126
+ if (r.bottom > window.innerHeight) menu.style.top = (window.innerHeight - r.height - 8) + "px";
127
+ });
128
+
129
+ menu.addEventListener("click", async (ev) => {
130
+ const item = ev.target.closest(".session-actions-menu-item");
131
+ if (!item) return;
132
+ closeContextMenu();
133
+ if (item.dataset.action === "reveal") await revealFile(entry);
134
+ });
135
+
136
+ setTimeout(() => {
137
+ document.addEventListener("click", closeContextMenu, { once: true });
138
+ }, 0);
139
+ }
140
+
141
+ function closeContextMenu() {
142
+ const existing = document.querySelector(".wt-context-menu");
143
+ if (existing) existing.remove();
144
+ }
145
+
146
+ async function revealFile(entry) {
147
+ const fullPath = _workingDir.replace(/\/+$/, "") + "/" + entry.path;
148
+ try {
149
+ const resp = await fetch("/api/file-action", {
150
+ method: "POST",
151
+ headers: { "Content-Type": "application/json" },
152
+ body: JSON.stringify({ path: fullPath, action: "reveal" })
153
+ });
154
+ if (!resp.ok) throw new Error(`HTTP ${resp.status}`);
155
+ } catch (err) {
156
+ console.error("reveal failed:", err);
157
+ if (typeof Modal !== "undefined") Modal.toast(t("workspace.revealFailed"), "error");
158
+ }
159
+ }
160
+
99
161
  async function toggleDir(entry, caret, children) {
100
162
  const isOpen = caret.classList.contains("open");
101
163
  if (isOpen) {
@@ -208,5 +270,47 @@ const Workspace = (() => {
208
270
  };
209
271
  })();
210
272
 
273
+ (function _initWorkspaceResize() {
274
+ const panel = document.getElementById("workspace-panel");
275
+ const handle = document.getElementById("workspace-resize-handle");
276
+ if (!panel || !handle) return;
277
+
278
+ const MIN_W = 160;
279
+ const MAX_W = 600;
280
+
281
+ const saved = localStorage.getItem("workspace-width");
282
+ if (saved) {
283
+ const w = parseFloat(saved);
284
+ if (w >= MIN_W && w <= MAX_W) panel.style.setProperty("--workspace-width", w + "px");
285
+ }
286
+
287
+ let startX = 0;
288
+ let startW = 0;
289
+
290
+ handle.addEventListener("mousedown", (e) => {
291
+ e.preventDefault();
292
+ startX = e.clientX;
293
+ startW = parseFloat(getComputedStyle(panel).getPropertyValue("--workspace-width"));
294
+ handle.classList.add("active");
295
+ document.body.style.cursor = "col-resize";
296
+ document.body.style.userSelect = "none";
297
+ });
298
+
299
+ document.addEventListener("mousemove", (e) => {
300
+ if (!handle.classList.contains("active")) return;
301
+ const dx = startX - e.clientX;
302
+ const newW = Math.min(MAX_W, Math.max(MIN_W, startW + dx));
303
+ panel.style.setProperty("--workspace-width", newW + "px");
304
+ });
305
+
306
+ document.addEventListener("mouseup", () => {
307
+ if (!handle.classList.contains("active")) return;
308
+ handle.classList.remove("active");
309
+ document.body.style.cursor = "";
310
+ document.body.style.userSelect = "";
311
+ localStorage.setItem("workspace-width", parseFloat(getComputedStyle(panel).getPropertyValue("--workspace-width")));
312
+ });
313
+ })();
314
+
211
315
  document.addEventListener("DOMContentLoaded", () => Workspace.init());
212
316
  window.Workspace = Workspace;
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: openclacky
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - windy
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2026-06-16 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: faraday
@@ -270,8 +269,8 @@ email:
270
269
  - yafei@dao42.com
271
270
  executables:
272
271
  - clacky
273
- - openclacky
274
272
  - clarky
273
+ - openclacky
275
274
  extensions: []
276
275
  extra_rdoc_files: []
277
276
  files:
@@ -632,7 +631,6 @@ metadata:
632
631
  homepage_uri: https://github.com/clacky-ai/openclacky
633
632
  source_code_uri: https://github.com/clacky-ai/openclacky
634
633
  changelog_uri: https://github.com/clacky-ai/openclacky/blob/main/CHANGELOG.md
635
- post_install_message:
636
634
  rdoc_options: []
637
635
  require_paths:
638
636
  - lib
@@ -650,8 +648,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
650
648
  - !ruby/object:Gem::Version
651
649
  version: '0'
652
650
  requirements: []
653
- rubygems_version: 3.5.22
654
- signing_key:
651
+ rubygems_version: 3.6.9
655
652
  specification_version: 4
656
653
  summary: The most Token-efficient open-source AI Agent — BYOK, Skill-driven, IM-integrated.
657
654
  test_files: []