openclacky 1.3.6 → 1.3.7
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 +30 -0
- data/lib/clacky/agent.rb +8 -1
- data/lib/clacky/agent_profile.rb +121 -53
- data/lib/clacky/brand_config.rb +309 -6
- data/lib/clacky/cli.rb +4 -57
- data/lib/clacky/default_extensions/coding/ext.yml +18 -0
- data/lib/clacky/default_extensions/ext-studio/agents/ext-developer/system_prompt.md +95 -0
- data/lib/clacky/default_extensions/ext-studio/api/handler.rb +254 -0
- data/lib/clacky/default_extensions/ext-studio/ext.yml +32 -0
- data/lib/clacky/default_extensions/ext-studio/panels/studio/view.js +1269 -0
- data/lib/clacky/default_extensions/ext-studio/skills/ext-debug/SKILL.md +71 -0
- data/lib/clacky/default_extensions/ext-studio/skills/ext-publish/SKILL.md +74 -0
- data/lib/clacky/default_extensions/ext-studio/skills/ext-scaffold/SKILL.md +65 -0
- data/lib/clacky/default_extensions/general/ext.yml +18 -0
- data/lib/clacky/default_extensions/git/ext.yml +12 -0
- data/lib/clacky/{default_agents/_panels/git/panel.js → default_extensions/git/panels/git/view.js} +1 -2
- data/lib/clacky/default_extensions/meeting/{handler.rb → api/handler.rb} +78 -26
- data/lib/clacky/default_extensions/meeting/ext.yml +15 -0
- data/lib/clacky/default_extensions/meeting/{meeting.js → panels/meeting/view.js} +266 -89
- data/lib/clacky/default_extensions/meeting/skills/meeting-summarizer/SKILL.md +2 -1
- data/lib/clacky/default_extensions/time_machine/ext.yml +12 -0
- data/lib/clacky/{default_agents/_panels/time_machine/panel.js → default_extensions/time_machine/panels/time_machine/view.js} +58 -47
- data/lib/clacky/default_skills/channel-manager/discord_setup.rb +1 -1
- data/lib/clacky/default_skills/extend-openclacky/SKILL.md +83 -18
- data/lib/clacky/{api_extension.rb → extension/api_extension.rb} +27 -11
- data/lib/clacky/extension/api_loader.rb +136 -0
- data/lib/clacky/extension/cli_commands.rb +226 -0
- data/lib/clacky/{server/api_extension_dispatcher.rb → extension/dispatcher.rb} +22 -9
- data/lib/clacky/extension/hook_loader.rb +77 -0
- data/lib/clacky/extension/loader.rb +483 -0
- data/lib/clacky/extension/packager.rb +226 -0
- data/lib/clacky/{patch_loader.rb → extension/patch_loader.rb} +45 -0
- data/lib/clacky/extension/scaffold/template_renderer.rb +64 -0
- data/lib/clacky/extension/scaffold/templates/full/README.md.erb +48 -0
- data/lib/clacky/extension/scaffold/templates/full/agents/designer.md +5 -0
- data/lib/clacky/extension/scaffold/templates/full/api/handler.rb.erb +16 -0
- data/lib/clacky/extension/scaffold/templates/full/channels/noop.rb.erb +40 -0
- data/lib/clacky/extension/scaffold/templates/full/ext.yml.erb +41 -0
- data/lib/clacky/extension/scaffold/templates/full/hooks/audit.rb +9 -0
- data/lib/clacky/extension/scaffold/templates/full/panels/dashboard/view.js.erb +194 -0
- data/lib/clacky/extension/scaffold/templates/full/patches/audit.rb +15 -0
- data/lib/clacky/extension/scaffold/templates/full/skills/__slug__-skill/SKILL.md.erb +8 -0
- data/lib/clacky/extension/scaffold/templates/hello/api/handler.rb.erb +9 -0
- data/lib/clacky/extension/scaffold/templates/hello/ext.yml.erb +12 -0
- data/lib/clacky/extension/scaffold/templates/hello/panels/hello/view.js.erb +31 -0
- data/lib/clacky/extension/scaffold.rb +55 -0
- data/lib/clacky/extension/verifier.rb +196 -0
- data/lib/clacky/identity.rb +70 -0
- data/lib/clacky/locales/en.rb +19 -1
- data/lib/clacky/locales/zh.rb +19 -1
- data/lib/clacky/platform_http_client.rb +18 -15
- data/lib/clacky/server/channel/extension_adapter_loader.rb +32 -0
- data/lib/clacky/server/channel.rb +6 -0
- data/lib/clacky/server/http_server.rb +313 -144
- data/lib/clacky/server/session_registry.rb +9 -2
- data/lib/clacky/skill_loader.rb +28 -1
- data/lib/clacky/ui2/ui_controller.rb +9 -6
- data/lib/clacky/version.rb +1 -1
- data/lib/clacky/web/app.css +748 -573
- data/lib/clacky/web/app.js +63 -15
- data/lib/clacky/web/auth.js +2 -0
- data/lib/clacky/web/components/notify.js +2 -0
- data/lib/clacky/web/components/sidebar.js +1 -5
- data/lib/clacky/web/core/ext.js +316 -79
- data/lib/clacky/web/features/backup/store.js +1 -0
- data/lib/clacky/web/features/backup/view.js +0 -1
- data/lib/clacky/web/features/brand/view.js +13 -5
- data/lib/clacky/web/features/extensions/store.js +184 -0
- data/lib/clacky/web/features/extensions/view.js +389 -0
- data/lib/clacky/web/features/new-session/store.js +186 -0
- data/lib/clacky/web/features/new-session/view.js +319 -0
- data/lib/clacky/web/features/share/view.js +63 -14
- data/lib/clacky/web/features/skills/store.js +3 -1
- data/lib/clacky/web/features/skills/view.js +1 -1
- data/lib/clacky/web/features/tasks/view.js +12 -0
- data/lib/clacky/web/features/trash/store.js +24 -6
- data/lib/clacky/web/features/trash/view.js +46 -9
- data/lib/clacky/web/features/workspace/store.js +2 -0
- data/lib/clacky/web/features/workspace/view.js +0 -1
- data/lib/clacky/web/i18n.js +118 -106
- data/lib/clacky/web/index.html +138 -188
- data/lib/clacky/web/sessions.js +64 -269
- data/lib/clacky/web/settings.js +1 -1
- data/lib/clacky/web/skills.js +2 -0
- data/lib/clacky/web/theme.js +2 -0
- data/lib/clacky/web/ws-dispatcher.js +1 -0
- data/lib/clacky/web/ws.js +2 -0
- data/lib/clacky.rb +21 -10
- metadata +55 -24
- data/benchmark/runner.rb +0 -441
- data/lib/clacky/api_extension_loader.rb +0 -168
- data/lib/clacky/default_agents/SOUL.md +0 -3
- data/lib/clacky/default_agents/USER.md +0 -1
- data/lib/clacky/default_agents/coding/profile.yml +0 -5
- data/lib/clacky/default_agents/coding/webui/.gitkeep +0 -0
- data/lib/clacky/default_agents/general/profile.yml +0 -2
- data/lib/clacky/default_extensions/meeting/meta.yml +0 -3
- data/lib/clacky/web/features/creator/store.js +0 -81
- data/lib/clacky/web/features/creator/view.js +0 -380
- /data/lib/clacky/{default_agents → default_extensions/coding/agents}/coding/system_prompt.md +0 -0
- /data/lib/clacky/{default_agents → default_extensions/general/agents}/general/system_prompt.md +0 -0
- /data/lib/clacky/{default_agents/base_prompt.md → prompts/base.md} +0 -0
data/lib/clacky/web/app.js
CHANGED
|
@@ -31,7 +31,7 @@ function escapeHtml(str) {
|
|
|
31
31
|
// Single source of truth for panel visibility and URL hash.
|
|
32
32
|
//
|
|
33
33
|
// Views:
|
|
34
|
-
// welcome → /#
|
|
34
|
+
// welcome → /#new (new-session landing page)
|
|
35
35
|
// session/{id} → /#session/{id}
|
|
36
36
|
// tasks → /#tasks
|
|
37
37
|
// skills → /#skills
|
|
@@ -54,11 +54,12 @@ const PANELS = [
|
|
|
54
54
|
"skills-panel",
|
|
55
55
|
"channels-panel",
|
|
56
56
|
"mcp-panel",
|
|
57
|
+
"extensions-panel",
|
|
57
58
|
"trash-panel",
|
|
58
59
|
"profile-panel",
|
|
59
60
|
"billing-panel",
|
|
60
61
|
"settings-panel",
|
|
61
|
-
"
|
|
62
|
+
"ext-slot-main-workspace",
|
|
62
63
|
];
|
|
63
64
|
|
|
64
65
|
const Router = (() => {
|
|
@@ -75,7 +76,12 @@ const Router = (() => {
|
|
|
75
76
|
}
|
|
76
77
|
|
|
77
78
|
// Update the URL hash without triggering a hashchange handler loop.
|
|
79
|
+
// Only arm the skip-flag if the hash is actually going to change — otherwise
|
|
80
|
+
// the browser fires no hashchange event and the flag would linger and
|
|
81
|
+
// silently swallow the next real hashchange.
|
|
78
82
|
function _setHash(hash) {
|
|
83
|
+
const target = hash ? "#" + hash : "";
|
|
84
|
+
if (location.hash === target || (target === "" && location.hash === "")) return;
|
|
79
85
|
_skipNextHashChange = true;
|
|
80
86
|
location.hash = hash;
|
|
81
87
|
}
|
|
@@ -84,10 +90,14 @@ const Router = (() => {
|
|
|
84
90
|
function _parseHash(hash) {
|
|
85
91
|
const h = (hash || "").replace(/^#\/?/, "");
|
|
86
92
|
if (!h) return { view: "welcome", params: {} };
|
|
93
|
+
if (h === "new") return { view: "welcome", params: {} };
|
|
87
94
|
if (h === "tasks") return { view: "tasks", params: {} };
|
|
88
95
|
if (h === "skills") return { view: "skills", params: {} };
|
|
89
96
|
if (h === "channels") return { view: "channels", params: {} };
|
|
90
97
|
if (h === "mcp") return { view: "mcp", params: {} };
|
|
98
|
+
if (h === "extensions") return { view: "extensions", params: {} };
|
|
99
|
+
const mExtDetail = h.match(/^extensions\/(.+)$/);
|
|
100
|
+
if (mExtDetail) return { view: "extensions", params: { detailId: mExtDetail[1] } };
|
|
91
101
|
if (h === "trash") return { view: "trash", params: {} };
|
|
92
102
|
if (h === "profile") return { view: "profile", params: {} };
|
|
93
103
|
// Legacy: #memories redirects to #profile (memories are now merged into
|
|
@@ -95,7 +105,8 @@ const Router = (() => {
|
|
|
95
105
|
if (h === "memories") return { view: "profile", params: {} };
|
|
96
106
|
if (h === "billing") return { view: "billing", params: {} };
|
|
97
107
|
if (h === "settings") return { view: "settings", params: {} };
|
|
98
|
-
|
|
108
|
+
const mExt = h.match(/^ext\/(.+)$/);
|
|
109
|
+
if (mExt) return { view: "ext-workspace", params: { id: mExt[1] } };
|
|
99
110
|
const m = h.match(/^session\/(.+)$/);
|
|
100
111
|
if (m) return { view: "session", params: { id: m[1] } };
|
|
101
112
|
return { view: "welcome", params: {} };
|
|
@@ -109,10 +120,10 @@ const Router = (() => {
|
|
|
109
120
|
skills: "skills-sidebar-item",
|
|
110
121
|
channels: "channels-sidebar-item",
|
|
111
122
|
mcp: "mcp-sidebar-item",
|
|
123
|
+
extensions: "extensions-sidebar-item",
|
|
112
124
|
trash: "trash-sidebar-item",
|
|
113
125
|
profile: "profile-sidebar-item",
|
|
114
126
|
billing: "billing-sidebar-item",
|
|
115
|
-
creator: "creator-sidebar-item",
|
|
116
127
|
};
|
|
117
128
|
|
|
118
129
|
// Remove active highlight from all Router-managed sidebar items.
|
|
@@ -121,6 +132,10 @@ const Router = (() => {
|
|
|
121
132
|
const el = $(id);
|
|
122
133
|
if (el) el.classList.remove("active");
|
|
123
134
|
});
|
|
135
|
+
// Extension workspace nav items tag themselves with data-ext-workspace;
|
|
136
|
+
// the Router owns their active highlight the same way as built-in items.
|
|
137
|
+
document.querySelectorAll("[data-ext-workspace].active")
|
|
138
|
+
.forEach(el => el.classList.remove("active"));
|
|
124
139
|
}
|
|
125
140
|
|
|
126
141
|
// Core: apply a view change. Called both from navigate() and hashchange.
|
|
@@ -238,6 +253,18 @@ const Router = (() => {
|
|
|
238
253
|
Sessions.renderList();
|
|
239
254
|
break;
|
|
240
255
|
|
|
256
|
+
case "extensions":
|
|
257
|
+
$("extensions-panel").style.display = "flex";
|
|
258
|
+
if (params.detailId) {
|
|
259
|
+
_setHash(`extensions/${params.detailId}`);
|
|
260
|
+
Extensions.onPanelShow({ detailId: params.detailId });
|
|
261
|
+
} else {
|
|
262
|
+
_setHash("extensions");
|
|
263
|
+
Extensions.onPanelShow();
|
|
264
|
+
}
|
|
265
|
+
Sessions.renderList();
|
|
266
|
+
break;
|
|
267
|
+
|
|
241
268
|
case "trash":
|
|
242
269
|
_setHash("trash");
|
|
243
270
|
$("trash-panel").style.display = "flex";
|
|
@@ -259,13 +286,6 @@ const Router = (() => {
|
|
|
259
286
|
Sessions.renderList();
|
|
260
287
|
break;
|
|
261
288
|
|
|
262
|
-
case "creator":
|
|
263
|
-
_setHash("creator");
|
|
264
|
-
$("creator-panel").style.display = "flex";
|
|
265
|
-
Creator.onPanelShow();
|
|
266
|
-
Sessions.renderList();
|
|
267
|
-
break;
|
|
268
|
-
|
|
269
289
|
case "settings":
|
|
270
290
|
_setHash("settings");
|
|
271
291
|
$("settings-panel").style.display = "";
|
|
@@ -284,10 +304,26 @@ const Router = (() => {
|
|
|
284
304
|
$("onboard-panel").style.display = "flex";
|
|
285
305
|
break;
|
|
286
306
|
|
|
307
|
+
case "ext-workspace": {
|
|
308
|
+
const ws = window.Clacky && Clacky.ext && Clacky.ext._getWorkspace(params.id);
|
|
309
|
+
if (!ws) { await _apply("welcome"); return; }
|
|
310
|
+
_setHash(`ext/${params.id}`);
|
|
311
|
+
const container = $("ext-slot-main-workspace");
|
|
312
|
+
container.replaceChildren();
|
|
313
|
+
container.style.display = "block";
|
|
314
|
+
try { ws.render(container, {}); }
|
|
315
|
+
catch (err) { console.error("ext workspace render failed:", err); }
|
|
316
|
+
Sessions.renderList();
|
|
317
|
+
break;
|
|
318
|
+
}
|
|
319
|
+
|
|
287
320
|
default: // "welcome"
|
|
288
|
-
_setHash("");
|
|
321
|
+
_setHash("new");
|
|
289
322
|
$("welcome").style.display = "";
|
|
290
323
|
Sessions.renderList();
|
|
324
|
+
if (window.NewSessionView && NewSessionView.onPanelShow) {
|
|
325
|
+
NewSessionView.onPanelShow();
|
|
326
|
+
}
|
|
291
327
|
break;
|
|
292
328
|
}
|
|
293
329
|
|
|
@@ -296,6 +332,9 @@ const Router = (() => {
|
|
|
296
332
|
_clearSidebarActive();
|
|
297
333
|
const activeItem = SIDEBAR_ITEMS[view];
|
|
298
334
|
if (activeItem) $(activeItem)?.classList.add("active");
|
|
335
|
+
if (view === "ext-workspace" && params.id) {
|
|
336
|
+
document.querySelector(`[data-ext-workspace="${params.id}"]`)?.classList.add("active");
|
|
337
|
+
}
|
|
299
338
|
}
|
|
300
339
|
|
|
301
340
|
// Listen for browser back/forward (or manual hash edits).
|
|
@@ -308,6 +347,14 @@ const Router = (() => {
|
|
|
308
347
|
_apply(view, params).catch(err => console.error("Router._apply failed:", err));
|
|
309
348
|
});
|
|
310
349
|
|
|
350
|
+
// Extensions request navigation via a CustomEvent so ext.js has no direct
|
|
351
|
+
// dependency on Router. Detail is { view, params } — same shape as navigate().
|
|
352
|
+
document.addEventListener("clacky:ext:navigate", (e) => {
|
|
353
|
+
const { view, params } = e.detail || {};
|
|
354
|
+
if (!view) return;
|
|
355
|
+
_apply(view, params || {}).catch(err => console.error("Router._apply failed:", err));
|
|
356
|
+
});
|
|
357
|
+
|
|
311
358
|
return {
|
|
312
359
|
get current() { return _current; },
|
|
313
360
|
get params() { return _params; },
|
|
@@ -328,6 +375,8 @@ const Router = (() => {
|
|
|
328
375
|
};
|
|
329
376
|
})();
|
|
330
377
|
|
|
378
|
+
Clacky.Router = Router;
|
|
379
|
+
|
|
331
380
|
// ── Modal utility ─────────────────────────────────────────────────────────
|
|
332
381
|
const Modal = (() => {
|
|
333
382
|
/** Show a yes/no confirmation dialog. Returns a Promise<boolean>. */
|
|
@@ -484,6 +533,8 @@ const Modal = (() => {
|
|
|
484
533
|
return { confirm, confirmOnce, prompt, rename };
|
|
485
534
|
})();
|
|
486
535
|
|
|
536
|
+
Clacky.Modal = Modal;
|
|
537
|
+
|
|
487
538
|
// ── Toast helper ──────────────────────────────────────────────────────────
|
|
488
539
|
// Non-blocking notification stack. Replaces alert() for success/error/info
|
|
489
540
|
// feedback. Supports an optional action button (e.g. "Go check").
|
|
@@ -700,9 +751,6 @@ window.bootAfterBrand = async function() {
|
|
|
700
751
|
// key_setup blocks boot entirely; onboard.js calls _bootUI() when done.
|
|
701
752
|
if (needsOnboard && phase === "key_setup") return;
|
|
702
753
|
|
|
703
|
-
// Show creator sidebar entry if user_licensed
|
|
704
|
-
Creator.updateSidebarVisibility();
|
|
705
|
-
|
|
706
754
|
// Initialize skill autocomplete
|
|
707
755
|
SkillAC.init();
|
|
708
756
|
|
data/lib/clacky/web/auth.js
CHANGED
|
@@ -146,6 +146,8 @@ const Notify = (() => {
|
|
|
146
146
|
return { init, toggle, enabled, setEnabled, onTaskFinished };
|
|
147
147
|
})();
|
|
148
148
|
|
|
149
|
+
Clacky.Notify = Notify;
|
|
150
|
+
|
|
149
151
|
// Initialize on load (button binding + initial icon state).
|
|
150
152
|
if (document.readyState === "loading") {
|
|
151
153
|
document.addEventListener("DOMContentLoaded", () => Notify.init());
|
|
@@ -23,16 +23,12 @@ const Sidebar = (() => {
|
|
|
23
23
|
document.getElementById("skills-sidebar-item").addEventListener("click", () => Router.navigate("skills"));
|
|
24
24
|
document.getElementById("channels-sidebar-item").addEventListener("click", () => Router.navigate("channels"));
|
|
25
25
|
document.getElementById("mcp-sidebar-item").addEventListener("click", () => Router.navigate("mcp"));
|
|
26
|
+
document.getElementById("extensions-sidebar-item").addEventListener("click", () => Router.navigate("extensions"));
|
|
26
27
|
document.getElementById("trash-sidebar-item").addEventListener("click", () => Router.navigate("trash"));
|
|
27
28
|
document.getElementById("profile-sidebar-item").addEventListener("click", () => Router.navigate("profile"));
|
|
28
29
|
document.getElementById("billing-sidebar-item").addEventListener("click", () => Router.navigate("billing"));
|
|
29
30
|
|
|
30
31
|
// memories-sidebar-item is retained as a hidden legacy placeholder — no click handler.
|
|
31
|
-
|
|
32
|
-
// creator-sidebar-item is conditionally rendered (only when user_licensed).
|
|
33
|
-
// This ?. is a legitimate business guard, not defensive padding — the
|
|
34
|
-
// element genuinely may not exist in the DOM for unlicensed users.
|
|
35
|
-
document.getElementById("creator-sidebar-item")?.addEventListener("click", () => Router.navigate("creator"));
|
|
36
32
|
}
|
|
37
33
|
|
|
38
34
|
return { init };
|