openclacky 1.3.6 → 1.3.8

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.
Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +54 -0
  3. data/lib/clacky/agent/hook_manager.rb +10 -1
  4. data/lib/clacky/agent/system_prompt_builder.rb +1 -1
  5. data/lib/clacky/agent.rb +17 -3
  6. data/lib/clacky/agent_profile.rb +124 -53
  7. data/lib/clacky/billing/billing_store.rb +3 -2
  8. data/lib/clacky/brand_config.rb +309 -6
  9. data/lib/clacky/cli.rb +4 -57
  10. data/lib/clacky/default_extensions/coding/agents/coding/avatar.png +0 -0
  11. data/lib/clacky/default_extensions/coding/ext.yml +19 -0
  12. data/lib/clacky/default_extensions/ext-studio/agents/ext-developer/avatar.png +0 -0
  13. data/lib/clacky/default_extensions/ext-studio/agents/ext-developer/system_prompt.md +95 -0
  14. data/lib/clacky/default_extensions/ext-studio/api/handler.rb +254 -0
  15. data/lib/clacky/default_extensions/ext-studio/ext.yml +33 -0
  16. data/lib/clacky/default_extensions/ext-studio/panels/studio/view.js +1288 -0
  17. data/lib/clacky/default_extensions/ext-studio/skills/ext-debug/SKILL.md +71 -0
  18. data/lib/clacky/default_extensions/ext-studio/skills/ext-publish/SKILL.md +74 -0
  19. data/lib/clacky/default_extensions/ext-studio/skills/ext-scaffold/SKILL.md +65 -0
  20. data/lib/clacky/default_extensions/general/agents/general/avatar.png +0 -0
  21. data/lib/clacky/default_extensions/general/ext.yml +19 -0
  22. data/lib/clacky/default_extensions/git/ext.yml +12 -0
  23. data/lib/clacky/{default_agents/_panels/git/panel.js → default_extensions/git/panels/git/view.js} +4 -5
  24. data/lib/clacky/default_extensions/meeting/{handler.rb → api/handler.rb} +78 -26
  25. data/lib/clacky/default_extensions/meeting/ext.yml +15 -0
  26. data/lib/clacky/default_extensions/meeting/{meeting.js → panels/meeting/view.js} +266 -90
  27. data/lib/clacky/default_extensions/meeting/skills/meeting-summarizer/SKILL.md +2 -1
  28. data/lib/clacky/default_extensions/time_machine/ext.yml +12 -0
  29. data/lib/clacky/{default_agents/_panels/time_machine/panel.js → default_extensions/time_machine/panels/time_machine/view.js} +58 -47
  30. data/lib/clacky/default_skills/channel-manager/discord_setup.rb +1 -1
  31. data/lib/clacky/default_skills/extend-openclacky/SKILL.md +83 -18
  32. data/lib/clacky/{api_extension.rb → extension/api_extension.rb} +27 -11
  33. data/lib/clacky/extension/api_loader.rb +136 -0
  34. data/lib/clacky/extension/cli_commands.rb +226 -0
  35. data/lib/clacky/{server/api_extension_dispatcher.rb → extension/dispatcher.rb} +22 -9
  36. data/lib/clacky/extension/hook_loader.rb +77 -0
  37. data/lib/clacky/extension/loader.rb +489 -0
  38. data/lib/clacky/extension/packager.rb +226 -0
  39. data/lib/clacky/{patch_loader.rb → extension/patch_loader.rb} +45 -0
  40. data/lib/clacky/extension/scaffold/template_renderer.rb +64 -0
  41. data/lib/clacky/extension/scaffold/templates/full/README.md.erb +48 -0
  42. data/lib/clacky/extension/scaffold/templates/full/agents/designer.md +5 -0
  43. data/lib/clacky/extension/scaffold/templates/full/api/handler.rb.erb +16 -0
  44. data/lib/clacky/extension/scaffold/templates/full/channels/noop.rb.erb +40 -0
  45. data/lib/clacky/extension/scaffold/templates/full/ext.yml.erb +41 -0
  46. data/lib/clacky/extension/scaffold/templates/full/hooks/audit.rb +9 -0
  47. data/lib/clacky/extension/scaffold/templates/full/panels/dashboard/view.js.erb +194 -0
  48. data/lib/clacky/extension/scaffold/templates/full/patches/audit.rb +15 -0
  49. data/lib/clacky/extension/scaffold/templates/full/skills/__slug__-skill/SKILL.md.erb +8 -0
  50. data/lib/clacky/extension/scaffold/templates/hello/api/handler.rb.erb +9 -0
  51. data/lib/clacky/extension/scaffold/templates/hello/ext.yml.erb +12 -0
  52. data/lib/clacky/extension/scaffold/templates/hello/panels/hello/view.js.erb +31 -0
  53. data/lib/clacky/extension/scaffold.rb +55 -0
  54. data/lib/clacky/extension/verifier.rb +196 -0
  55. data/lib/clacky/identity.rb +70 -0
  56. data/lib/clacky/locales/en.rb +19 -1
  57. data/lib/clacky/locales/zh.rb +19 -1
  58. data/lib/clacky/platform_http_client.rb +18 -15
  59. data/lib/clacky/server/channel/extension_adapter_loader.rb +32 -0
  60. data/lib/clacky/server/channel.rb +6 -0
  61. data/lib/clacky/server/http_server.rb +439 -146
  62. data/lib/clacky/server/session_registry.rb +9 -2
  63. data/lib/clacky/shell_hook_loader.rb +266 -22
  64. data/lib/clacky/skill_loader.rb +28 -1
  65. data/lib/clacky/ui2/components/welcome_banner.rb +1 -1
  66. data/lib/clacky/ui2/ui_controller.rb +9 -6
  67. data/lib/clacky/utils/workspace_rules.rb +2 -2
  68. data/lib/clacky/version.rb +1 -1
  69. data/lib/clacky/web/app.css +1034 -675
  70. data/lib/clacky/web/app.js +63 -15
  71. data/lib/clacky/web/auth.js +2 -0
  72. data/lib/clacky/web/components/notify.js +2 -0
  73. data/lib/clacky/web/components/sidebar.js +1 -5
  74. data/lib/clacky/web/core/ext.js +432 -89
  75. data/lib/clacky/web/features/backup/store.js +1 -0
  76. data/lib/clacky/web/features/backup/view.js +0 -1
  77. data/lib/clacky/web/features/brand/view.js +13 -5
  78. data/lib/clacky/web/features/extensions/store.js +184 -0
  79. data/lib/clacky/web/features/extensions/view.js +390 -0
  80. data/lib/clacky/web/features/new-session/store.js +199 -0
  81. data/lib/clacky/web/features/new-session/view.js +619 -0
  82. data/lib/clacky/web/features/share/view.js +63 -14
  83. data/lib/clacky/web/features/skills/store.js +3 -1
  84. data/lib/clacky/web/features/skills/view.js +1 -1
  85. data/lib/clacky/web/features/tasks/view.js +12 -0
  86. data/lib/clacky/web/features/trash/store.js +24 -6
  87. data/lib/clacky/web/features/trash/view.js +48 -12
  88. data/lib/clacky/web/features/workspace/store.js +2 -0
  89. data/lib/clacky/web/features/workspace/view.js +0 -1
  90. data/lib/clacky/web/i18n.js +152 -106
  91. data/lib/clacky/web/index.html +172 -190
  92. data/lib/clacky/web/sessions.js +67 -272
  93. data/lib/clacky/web/settings.js +1 -1
  94. data/lib/clacky/web/skills.js +88 -48
  95. data/lib/clacky/web/theme.js +5 -0
  96. data/lib/clacky/web/ws-dispatcher.js +12 -2
  97. data/lib/clacky/web/ws.js +2 -0
  98. data/lib/clacky.rb +21 -10
  99. metadata +52 -21
  100. data/benchmark/runner.rb +0 -441
  101. data/lib/clacky/api_extension_loader.rb +0 -168
  102. data/lib/clacky/default_agents/SOUL.md +0 -3
  103. data/lib/clacky/default_agents/USER.md +0 -1
  104. data/lib/clacky/default_agents/coding/profile.yml +0 -5
  105. data/lib/clacky/default_agents/coding/webui/.gitkeep +0 -0
  106. data/lib/clacky/default_agents/general/profile.yml +0 -2
  107. data/lib/clacky/default_extensions/meeting/meta.yml +0 -3
  108. data/lib/clacky/web/features/creator/store.js +0 -81
  109. data/lib/clacky/web/features/creator/view.js +0 -380
  110. /data/lib/clacky/{default_agents → default_extensions/coding/agents}/coding/system_prompt.md +0 -0
  111. /data/lib/clacky/{default_agents → default_extensions/general/agents}/general/system_prompt.md +0 -0
  112. /data/lib/clacky/{default_agents/base_prompt.md → prompts/base.md} +0 -0
@@ -0,0 +1,199 @@
1
+ // ── NewSession · store — agent list + selection + advanced options ────────
2
+ //
3
+ // Owns the state for the "new session" landing page: the list of agents
4
+ // fetched from /api/agents, the current selection (persisted in localStorage),
5
+ // and the advanced-options form values (name / model / working dir / init).
6
+ // It never renders — NewSessionView owns the DOM.
7
+ //
8
+ // Also handles session creation: POST /api/sessions with the current selection
9
+ // and returns the created session summary. Sending the first message is the
10
+ // caller's job (via Sessions.setPendingMessage + Sessions.select).
11
+ //
12
+ // Depends on: Clacky.ext (for cross-module event emit).
13
+ // ───────────────────────────────────────────────────────────────────────────
14
+
15
+ const NewSessionStore = (() => {
16
+ const LS_AGENT_KEY = "openclacky.newSession.lastAgent";
17
+
18
+ const _state = {
19
+ agents: [],
20
+ selectedAgentId: null,
21
+ advanced: {
22
+ name: "",
23
+ modelId: "",
24
+ workingDir: "",
25
+ initProject: false,
26
+ },
27
+ advancedOpen: false,
28
+ creating: false,
29
+ };
30
+
31
+ const _listeners = {};
32
+
33
+ function _on(event, handler) {
34
+ (_listeners[event] ||= []).push(handler);
35
+ return () => {
36
+ const list = _listeners[event];
37
+ const i = list ? list.indexOf(handler) : -1;
38
+ if (i >= 0) list.splice(i, 1);
39
+ };
40
+ }
41
+
42
+ function _emit(event, payload) {
43
+ (_listeners[event] || []).forEach((h) => h(payload));
44
+ if (window.Clacky && Clacky.ext) Clacky.ext.emit(event, payload);
45
+ }
46
+
47
+ async function loadAgents() {
48
+ try {
49
+ const res = await fetch("/api/agents");
50
+ if (!res.ok) return;
51
+ const data = await res.json();
52
+ _state.agents = (data && data.agents) || [];
53
+
54
+ // Restore last-used agent from localStorage; fall back to the first
55
+ // available one (typically "general").
56
+ const remembered = localStorage.getItem(LS_AGENT_KEY);
57
+ const found = _state.agents.find((a) => a.id === remembered);
58
+ _state.selectedAgentId = found
59
+ ? found.id
60
+ : (_state.agents[0] && _state.agents[0].id) || "general";
61
+
62
+ _emit("newSession:agents-loaded", { agents: _state.agents });
63
+ _emit("newSession:selection-changed", { agentId: _state.selectedAgentId });
64
+ } catch (e) {
65
+ console.error("Failed to load agents:", e);
66
+ }
67
+ }
68
+
69
+ function selectAgent(agentId) {
70
+ if (!agentId || agentId === _state.selectedAgentId) return;
71
+ const found = _state.agents.find((a) => a.id === agentId);
72
+ if (!found) return;
73
+ _state.selectedAgentId = agentId;
74
+ localStorage.setItem(LS_AGENT_KEY, agentId);
75
+ _emit("newSession:selection-changed", { agentId });
76
+ }
77
+
78
+ function currentAgent() {
79
+ return _state.agents.find((a) => a.id === _state.selectedAgentId) || null;
80
+ }
81
+
82
+ function toggleAdvanced(open) {
83
+ _state.advancedOpen = open === undefined ? !_state.advancedOpen : !!open;
84
+ _emit("newSession:advanced-toggled", { open: _state.advancedOpen });
85
+ }
86
+
87
+ function updateAdvanced(patch) {
88
+ Object.assign(_state.advanced, patch);
89
+ _emit("newSession:advanced-changed", { advanced: _state.advanced });
90
+ }
91
+
92
+ async function loadModels() {
93
+ try {
94
+ const res = await fetch("/api/config");
95
+ if (!res.ok) return [];
96
+ const data = await res.json();
97
+ return (data && data.models) || [];
98
+ } catch (e) {
99
+ console.error("Failed to load models:", e);
100
+ return [];
101
+ }
102
+ }
103
+
104
+ async function loadDefaultDirectory() {
105
+ try {
106
+ const res = await fetch("/api/dirs");
107
+ if (!res.ok) return "";
108
+ const data = await res.json();
109
+ const home = data && data.home;
110
+ if (!home) return "";
111
+ return home.replace(/\/+$/, "") + "/clacky_workspace";
112
+ } catch (e) {
113
+ return "";
114
+ }
115
+ }
116
+
117
+ function _autoName(existingSessions) {
118
+ const maxN = (existingSessions || []).reduce((max, s) => {
119
+ const m = s.name && s.name.match(/^Session (\d+)$/);
120
+ return m ? Math.max(max, parseInt(m[1], 10)) : max;
121
+ }, 0);
122
+ return "Session " + (maxN + 1);
123
+ }
124
+
125
+ async function createSession({ existingSessions } = {}) {
126
+ if (_state.creating) return null;
127
+ _state.creating = true;
128
+ _emit("newSession:creating", { creating: true });
129
+
130
+ try {
131
+ const agentId = _state.selectedAgentId || "general";
132
+ const adv = _state.advanced;
133
+ const name = adv.name.trim() || _autoName(existingSessions);
134
+
135
+ const payload = { name, agent_profile: agentId, source: "manual" };
136
+ if (adv.workingDir.trim()) payload.working_dir = adv.workingDir.trim();
137
+ if (adv.modelId) payload.model_id = adv.modelId;
138
+
139
+ const res = await fetch("/api/sessions", {
140
+ method: "POST",
141
+ headers: { "Content-Type": "application/json" },
142
+ body: JSON.stringify(payload),
143
+ });
144
+ const data = await res.json();
145
+
146
+ if (!res.ok) {
147
+ const msg = data.error || "unknown error";
148
+ const friendly = res.status === 409
149
+ ? I18n.t("sessions.dirNotEmpty")
150
+ : I18n.t("sessions.createError") + msg;
151
+ alert(friendly);
152
+ return null;
153
+ }
154
+
155
+ return data.session || null;
156
+ } catch (e) {
157
+ alert(I18n.t("sessions.createError") + e.message);
158
+ return null;
159
+ } finally {
160
+ _state.creating = false;
161
+ _emit("newSession:creating", { creating: false });
162
+ }
163
+ }
164
+
165
+ function reset() {
166
+ _state.advanced.name = "";
167
+ _state.advanced.initProject = false;
168
+ _emit("newSession:reset", {});
169
+ }
170
+
171
+ async function fetchSkillsForAgent(agentId) {
172
+ try {
173
+ const res = await fetch(`/api/agents/${encodeURIComponent(agentId)}/skills`);
174
+ if (!res.ok) return [];
175
+ const data = await res.json();
176
+ return data.skills || [];
177
+ } catch (e) {
178
+ console.error("Failed to load skills:", e);
179
+ return [];
180
+ }
181
+ }
182
+
183
+ return {
184
+ get state() { return _state; },
185
+ on: _on,
186
+ loadAgents,
187
+ selectAgent,
188
+ currentAgent,
189
+ toggleAdvanced,
190
+ updateAdvanced,
191
+ loadModels,
192
+ loadDefaultDirectory,
193
+ createSession,
194
+ fetchSkillsForAgent,
195
+ reset,
196
+ };
197
+ })();
198
+
199
+ window.NewSessionStore = NewSessionStore;