openclacky 1.3.4 → 1.3.5
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 +27 -0
- data/lib/clacky/agent/fake_tool_call_detector.rb +52 -0
- data/lib/clacky/agent/session_serializer.rb +3 -2
- data/lib/clacky/agent/tool_executor.rb +0 -12
- data/lib/clacky/agent.rb +74 -9
- data/lib/clacky/api_extension.rb +81 -0
- data/lib/clacky/api_extension_loader.rb +13 -1
- data/lib/clacky/client.rb +14 -17
- data/lib/clacky/default_agents/_panels/time_machine/panel.js +22 -0
- data/lib/clacky/default_agents/base_prompt.md +1 -0
- data/lib/clacky/default_extensions/meeting/handler.rb +331 -0
- data/lib/clacky/default_extensions/meeting/meeting.js +790 -0
- data/lib/clacky/default_extensions/meeting/meta.yml +3 -0
- data/lib/clacky/default_extensions/meeting/skills/meeting-summarizer/SKILL.md +44 -0
- data/lib/clacky/default_skills/media-gen/SKILL.md +63 -0
- data/lib/clacky/default_skills/media-gen/scripts/video_seq.sh +114 -0
- data/lib/clacky/json_ui_controller.rb +1 -1
- data/lib/clacky/media/base.rb +60 -0
- data/lib/clacky/media/dashscope.rb +385 -21
- data/lib/clacky/media/gemini.rb +9 -0
- data/lib/clacky/media/generator.rb +52 -0
- data/lib/clacky/media/openai_compat.rb +166 -0
- data/lib/clacky/null_ui_controller.rb +13 -0
- data/lib/clacky/plain_ui_controller.rb +1 -1
- data/lib/clacky/providers.rb +50 -2
- data/lib/clacky/rich_ui/rich_ui_controller.rb +1 -1
- data/lib/clacky/server/channel/channel_ui_controller.rb +1 -1
- data/lib/clacky/server/http_server.rb +144 -9
- data/lib/clacky/server/session_registry.rb +4 -2
- data/lib/clacky/server/web_ui_controller.rb +3 -2
- data/lib/clacky/skill_loader.rb +14 -2
- data/lib/clacky/tools/terminal/output_cleaner.rb +1 -3
- data/lib/clacky/tools/terminal.rb +0 -43
- data/lib/clacky/ui2/components/modal_component.rb +1 -1
- data/lib/clacky/ui2/ui_controller.rb +140 -31
- data/lib/clacky/ui_interface.rb +10 -1
- data/lib/clacky/utils/encoding.rb +25 -0
- data/lib/clacky/version.rb +1 -1
- data/lib/clacky/web/app.css +145 -22
- data/lib/clacky/web/components/onboard.js +1 -14
- data/lib/clacky/web/features/brand/view.js +8 -5
- data/lib/clacky/web/features/channels/store.js +1 -20
- data/lib/clacky/web/features/mcp/store.js +1 -20
- data/lib/clacky/web/features/profile/store.js +1 -13
- data/lib/clacky/web/features/profile/view.js +16 -4
- data/lib/clacky/web/features/skills/store.js +6 -21
- data/lib/clacky/web/features/version/store.js +2 -0
- data/lib/clacky/web/i18n.js +24 -1
- data/lib/clacky/web/index.html +15 -0
- data/lib/clacky/web/sessions.js +141 -51
- data/lib/clacky/web/settings.js +34 -2
- data/lib/clacky/web/ws-dispatcher.js +11 -3
- data/lib/clacky.rb +12 -5
- metadata +8 -1
data/lib/clacky/web/settings.js
CHANGED
|
@@ -1508,6 +1508,7 @@ const Settings = (() => {
|
|
|
1508
1508
|
_showBrandResult(true, I18n.t("settings.brand.activated", { name: data.product_name || "configured" }));
|
|
1509
1509
|
// Apply brand name and logo across the entire UI immediately
|
|
1510
1510
|
if (data.product_name) Brand.applyBrandName(data.product_name);
|
|
1511
|
+
if (data.theme_color) _applyAccentColor(data.theme_color, { persist: true });
|
|
1511
1512
|
Brand.clearBrandCache();
|
|
1512
1513
|
Brand.applyHeaderLogo();
|
|
1513
1514
|
// Refresh brand status flags (user_licensed may have flipped from false
|
|
@@ -1683,7 +1684,7 @@ const Settings = (() => {
|
|
|
1683
1684
|
// The state object per kind:
|
|
1684
1685
|
// { source, configured, model, base_url, api_key_masked, provider, available }
|
|
1685
1686
|
|
|
1686
|
-
const MEDIA_KINDS = ["image", "video", "audio", "ocr"];
|
|
1687
|
+
const MEDIA_KINDS = ["image", "video", "audio", "stt", "video_understanding", "ocr"];
|
|
1687
1688
|
let _mediaState = null;
|
|
1688
1689
|
let _mediaDefaults = null;
|
|
1689
1690
|
const _mediaCustomDraft = {};
|
|
@@ -2173,6 +2174,8 @@ const Settings = (() => {
|
|
|
2173
2174
|
Brand.applyBrandName("OpenClacky");
|
|
2174
2175
|
Brand.clearBrandCache();
|
|
2175
2176
|
Brand.applyHeaderLogo();
|
|
2177
|
+
const userAccent = (() => { try { return localStorage.getItem("clacky-accent-color"); } catch (_) { return null; } })();
|
|
2178
|
+
_applyAccentColor(userAccent || ACCENT_DEFAULT, { persist: false });
|
|
2176
2179
|
// Reset Skills panel state (hide Brand Skills tab, switch to My Skills)
|
|
2177
2180
|
if (typeof Skills !== "undefined" && Skills.resetAfterUnbind) {
|
|
2178
2181
|
Skills.resetAfterUnbind();
|
|
@@ -2203,6 +2206,7 @@ const Settings = (() => {
|
|
|
2203
2206
|
_initLangBtns();
|
|
2204
2207
|
_initFontBtns();
|
|
2205
2208
|
_initCurrencyBtns();
|
|
2209
|
+
_initAccentColorBtns();
|
|
2206
2210
|
|
|
2207
2211
|
// Re-render model cards when language changes (dynamic HTML, not data-i18n)
|
|
2208
2212
|
document.addEventListener("langchange", () => {
|
|
@@ -2364,6 +2368,34 @@ const Settings = (() => {
|
|
|
2364
2368
|
});
|
|
2365
2369
|
}
|
|
2366
2370
|
|
|
2371
|
+
// ── Accent Color ──────────────────────────────────────────────────────
|
|
2372
|
+
const ACCENT_STORAGE_KEY = "clacky-accent-color";
|
|
2373
|
+
const ACCENT_DEFAULT = "#4f46e5";
|
|
2374
|
+
|
|
2375
|
+
function _applyAccentColor(color, { persist = true } = {}) {
|
|
2376
|
+
const root = document.documentElement;
|
|
2377
|
+
root.style.setProperty("--color-accent-primary", color);
|
|
2378
|
+
root.style.setProperty("--color-accent-hover", color);
|
|
2379
|
+
root.style.setProperty("--color-button-primary", color);
|
|
2380
|
+
root.style.setProperty("--color-button-primary-hover", `color-mix(in srgb, ${color} 82%, #000)`);
|
|
2381
|
+
if (persist) {
|
|
2382
|
+
try { localStorage.setItem(ACCENT_STORAGE_KEY, color); } catch (_) {}
|
|
2383
|
+
}
|
|
2384
|
+
document.querySelectorAll("#accent-color-section .settings-accent-swatch").forEach(btn => {
|
|
2385
|
+
btn.classList.toggle("active", btn.dataset.color === color);
|
|
2386
|
+
});
|
|
2387
|
+
}
|
|
2388
|
+
|
|
2389
|
+
function _initAccentColorBtns() {
|
|
2390
|
+
let saved = null;
|
|
2391
|
+
try { saved = localStorage.getItem(ACCENT_STORAGE_KEY); } catch (_) {}
|
|
2392
|
+
_applyAccentColor(saved || ACCENT_DEFAULT, { persist: !!saved });
|
|
2393
|
+
|
|
2394
|
+
document.querySelectorAll("#accent-color-section .settings-accent-swatch").forEach(btn => {
|
|
2395
|
+
btn.addEventListener("click", () => _applyAccentColor(btn.dataset.color));
|
|
2396
|
+
});
|
|
2397
|
+
}
|
|
2398
|
+
|
|
2367
2399
|
// ── QR Code Lightbox ───────────────────────────────────────────────────
|
|
2368
2400
|
// Sets up click-to-enlarge behaviour for the support QR code.
|
|
2369
2401
|
// Safe to call multiple times — idempotent via a data attribute guard.
|
|
@@ -2404,5 +2436,5 @@ const Settings = (() => {
|
|
|
2404
2436
|
});
|
|
2405
2437
|
}
|
|
2406
2438
|
|
|
2407
|
-
return { open, init, loadBrand: _loadBrand };
|
|
2439
|
+
return { open, init, loadBrand: _loadBrand, applyAccentColor: _applyAccentColor };
|
|
2408
2440
|
})();
|
|
@@ -216,7 +216,7 @@ WS.onEvent(ev => {
|
|
|
216
216
|
// send it now — after restoreFromHash has settled — so appendMsg won't be wiped.
|
|
217
217
|
const pendingMsg = Sessions.takePendingMessage();
|
|
218
218
|
if (pendingMsg && pendingMsg.session_id === ev.session_id) {
|
|
219
|
-
Sessions.appendMsg("user", escapeHtml(pendingMsg.content), { time: new Date() });
|
|
219
|
+
Sessions.appendMsg("user", escapeHtml(pendingMsg.display || pendingMsg.content), { time: new Date() });
|
|
220
220
|
WS.send({ type: "message", session_id: pendingMsg.session_id, content: pendingMsg.content, lang: I18n.lang() });
|
|
221
221
|
}
|
|
222
222
|
break;
|
|
@@ -310,6 +310,9 @@ WS.onEvent(ev => {
|
|
|
310
310
|
if (ev.session_id !== Sessions.activeId) break;
|
|
311
311
|
Sessions.clearProgress();
|
|
312
312
|
Sessions.appendMsg("assistant", ev.content);
|
|
313
|
+
if (window.Clacky && Clacky.ext) {
|
|
314
|
+
Clacky.ext.emit("session:assistant-message", { sessionId: ev.session_id, content: ev.content });
|
|
315
|
+
}
|
|
313
316
|
break;
|
|
314
317
|
|
|
315
318
|
case "tool_call":
|
|
@@ -442,10 +445,15 @@ function renderErrorEvent(ev) {
|
|
|
442
445
|
const action = ev.top_up_url
|
|
443
446
|
? ` <a href="${escapeHtml(ev.top_up_url)}" target="_blank" rel="noopener noreferrer">${escapeHtml(I18n.t("error.insufficient_credit.action"))} →</a>`
|
|
444
447
|
: "";
|
|
445
|
-
Sessions.appendMsg("error", `<span>${body}${action}</span
|
|
448
|
+
Sessions.appendMsg("error", `<span>${body}${action}</span>${_buildRawDetail(ev.raw_message)}`);
|
|
446
449
|
return;
|
|
447
450
|
}
|
|
448
|
-
Sessions.appendMsg("error", escapeHtml(ev.message));
|
|
451
|
+
Sessions.appendMsg("error", escapeHtml(ev.message) + _buildRawDetail(ev.raw_message));
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
function _buildRawDetail(raw) {
|
|
455
|
+
if (!raw) return "";
|
|
456
|
+
return `<details class="error-raw-detail"><summary>${escapeHtml(I18n.t("error.show_detail"))}</summary><pre>${escapeHtml(raw)}</pre></details>`;
|
|
449
457
|
}
|
|
450
458
|
|
|
451
459
|
window.renderErrorEvent = renderErrorEvent;
|
data/lib/clacky.rb
CHANGED
|
@@ -155,20 +155,27 @@ require_relative "clacky/server/api_extension_dispatcher"
|
|
|
155
155
|
|
|
156
156
|
module Clacky
|
|
157
157
|
class AgentInterrupted < Exception; end # Inherit from Exception to bypass rescue StandardError
|
|
158
|
-
class AgentError < StandardError
|
|
158
|
+
class AgentError < StandardError
|
|
159
|
+
attr_reader :raw_message
|
|
160
|
+
|
|
161
|
+
def initialize(message, raw_message: nil)
|
|
162
|
+
super(message)
|
|
163
|
+
@raw_message = raw_message
|
|
164
|
+
end
|
|
165
|
+
end
|
|
159
166
|
class BadRequestError < AgentError
|
|
160
167
|
attr_reader :display_message
|
|
161
168
|
|
|
162
|
-
def initialize(message, display_message: nil)
|
|
163
|
-
super(message)
|
|
169
|
+
def initialize(message, display_message: nil, raw_message: nil)
|
|
170
|
+
super(message, raw_message: raw_message)
|
|
164
171
|
@display_message = display_message
|
|
165
172
|
end
|
|
166
173
|
end
|
|
167
174
|
class InsufficientCreditError < AgentError
|
|
168
175
|
attr_reader :error_code, :provider_id
|
|
169
176
|
|
|
170
|
-
def initialize(message, error_code: nil, provider_id: nil)
|
|
171
|
-
super(message)
|
|
177
|
+
def initialize(message, error_code: nil, provider_id: nil, raw_message: nil)
|
|
178
|
+
super(message, raw_message: raw_message)
|
|
172
179
|
@error_code = error_code
|
|
173
180
|
@provider_id = provider_id
|
|
174
181
|
end
|
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: 1.3.
|
|
4
|
+
version: 1.3.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- windy
|
|
@@ -338,6 +338,7 @@ files:
|
|
|
338
338
|
- lib/clacky/aes_gcm.rb
|
|
339
339
|
- lib/clacky/agent.rb
|
|
340
340
|
- lib/clacky/agent/cost_tracker.rb
|
|
341
|
+
- lib/clacky/agent/fake_tool_call_detector.rb
|
|
341
342
|
- lib/clacky/agent/hook_manager.rb
|
|
342
343
|
- lib/clacky/agent/llm_caller.rb
|
|
343
344
|
- lib/clacky/agent/memory_updater.rb
|
|
@@ -375,6 +376,10 @@ files:
|
|
|
375
376
|
- lib/clacky/default_agents/coding/webui/.gitkeep
|
|
376
377
|
- lib/clacky/default_agents/general/profile.yml
|
|
377
378
|
- lib/clacky/default_agents/general/system_prompt.md
|
|
379
|
+
- lib/clacky/default_extensions/meeting/handler.rb
|
|
380
|
+
- lib/clacky/default_extensions/meeting/meeting.js
|
|
381
|
+
- lib/clacky/default_extensions/meeting/meta.yml
|
|
382
|
+
- lib/clacky/default_extensions/meeting/skills/meeting-summarizer/SKILL.md
|
|
378
383
|
- lib/clacky/default_parsers/doc_parser.rb
|
|
379
384
|
- lib/clacky/default_parsers/docx_parser.rb
|
|
380
385
|
- lib/clacky/default_parsers/pdf_parser.rb
|
|
@@ -399,6 +404,7 @@ files:
|
|
|
399
404
|
- lib/clacky/default_skills/extend-openclacky/SKILL.md
|
|
400
405
|
- lib/clacky/default_skills/mcp-manager/SKILL.md
|
|
401
406
|
- lib/clacky/default_skills/media-gen/SKILL.md
|
|
407
|
+
- lib/clacky/default_skills/media-gen/scripts/video_seq.sh
|
|
402
408
|
- lib/clacky/default_skills/new/SKILL.md
|
|
403
409
|
- lib/clacky/default_skills/new/scripts/create_rails_project.sh
|
|
404
410
|
- lib/clacky/default_skills/onboard/SKILL.md
|
|
@@ -449,6 +455,7 @@ files:
|
|
|
449
455
|
- lib/clacky/message_format/bedrock.rb
|
|
450
456
|
- lib/clacky/message_format/open_ai.rb
|
|
451
457
|
- lib/clacky/message_history.rb
|
|
458
|
+
- lib/clacky/null_ui_controller.rb
|
|
452
459
|
- lib/clacky/openai_stream_aggregator.rb
|
|
453
460
|
- lib/clacky/patch_loader.rb
|
|
454
461
|
- lib/clacky/plain_ui_controller.rb
|