claudeck 1.0.0
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.
- package/LICENSE +21 -0
- package/README.md +233 -0
- package/cli.js +2 -0
- package/config/agent-chains.json +16 -0
- package/config/agent-dags.json +16 -0
- package/config/agents.json +46 -0
- package/config/bot-prompt.json +3 -0
- package/config/folders.json +66 -0
- package/config/prompts.json +92 -0
- package/config/repos.json +86 -0
- package/config/telegram-config.json +17 -0
- package/config/workflows.json +90 -0
- package/db.js +1198 -0
- package/package.json +55 -0
- package/plugins/claude-editor/client.css +171 -0
- package/plugins/claude-editor/client.js +183 -0
- package/plugins/event-stream/client.css +207 -0
- package/plugins/event-stream/client.js +271 -0
- package/plugins/linear/client.css +345 -0
- package/plugins/linear/client.js +380 -0
- package/plugins/linear/config.json +5 -0
- package/plugins/linear/server.js +312 -0
- package/plugins/repos/client.css +549 -0
- package/plugins/repos/client.js +663 -0
- package/plugins/repos/server.js +232 -0
- package/plugins/sudoku/client.css +196 -0
- package/plugins/sudoku/client.js +329 -0
- package/plugins/tasks/client.css +414 -0
- package/plugins/tasks/client.js +394 -0
- package/plugins/tasks/server.js +116 -0
- package/plugins/tic-tac-toe/client.css +167 -0
- package/plugins/tic-tac-toe/client.js +241 -0
- package/public/css/core/components.css +232 -0
- package/public/css/core/layout.css +330 -0
- package/public/css/core/print.css +18 -0
- package/public/css/core/reset.css +36 -0
- package/public/css/core/responsive.css +378 -0
- package/public/css/core/theme.css +116 -0
- package/public/css/core/variables.css +93 -0
- package/public/css/features/agent-monitor.css +297 -0
- package/public/css/features/agent-sidebar.css +525 -0
- package/public/css/features/agents.css +996 -0
- package/public/css/features/analytics.css +181 -0
- package/public/css/features/background-sessions.css +321 -0
- package/public/css/features/cost-dashboard.css +168 -0
- package/public/css/features/home.css +313 -0
- package/public/css/features/retro-terminal.css +88 -0
- package/public/css/features/telegram.css +127 -0
- package/public/css/features/tour.css +148 -0
- package/public/css/features/voice-input.css +60 -0
- package/public/css/features/welcome.css +241 -0
- package/public/css/panels/assistant-bot.css +442 -0
- package/public/css/panels/dev-docs.css +292 -0
- package/public/css/panels/file-explorer.css +322 -0
- package/public/css/panels/git-panel.css +221 -0
- package/public/css/panels/mcp-manager.css +199 -0
- package/public/css/panels/tips-feed.css +353 -0
- package/public/css/ui/commands.css +273 -0
- package/public/css/ui/context-gauge.css +76 -0
- package/public/css/ui/file-picker.css +69 -0
- package/public/css/ui/image-attachments.css +106 -0
- package/public/css/ui/messages.css +884 -0
- package/public/css/ui/modals.css +122 -0
- package/public/css/ui/parallel.css +217 -0
- package/public/css/ui/permissions.css +110 -0
- package/public/css/ui/right-panel.css +481 -0
- package/public/css/ui/sessions.css +689 -0
- package/public/css/ui/status-bar.css +425 -0
- package/public/css/ui/toolbox.css +206 -0
- package/public/data/tips.json +218 -0
- package/public/icons/favicon.png +0 -0
- package/public/icons/icon-192.png +0 -0
- package/public/icons/icon-512.png +0 -0
- package/public/icons/whaly.png +0 -0
- package/public/index.html +1140 -0
- package/public/js/core/api.js +591 -0
- package/public/js/core/constants.js +3 -0
- package/public/js/core/dom.js +270 -0
- package/public/js/core/events.js +10 -0
- package/public/js/core/plugin-loader.js +153 -0
- package/public/js/core/store.js +39 -0
- package/public/js/core/utils.js +25 -0
- package/public/js/core/ws.js +64 -0
- package/public/js/features/agent-monitor.js +222 -0
- package/public/js/features/agents.js +1209 -0
- package/public/js/features/analytics.js +397 -0
- package/public/js/features/attachments.js +251 -0
- package/public/js/features/background-sessions.js +475 -0
- package/public/js/features/chat.js +589 -0
- package/public/js/features/cost-dashboard.js +152 -0
- package/public/js/features/dag-editor.js +399 -0
- package/public/js/features/easter-egg.js +46 -0
- package/public/js/features/home.js +270 -0
- package/public/js/features/projects.js +372 -0
- package/public/js/features/prompts.js +228 -0
- package/public/js/features/sessions.js +332 -0
- package/public/js/features/telegram.js +131 -0
- package/public/js/features/tour.js +210 -0
- package/public/js/features/voice-input.js +185 -0
- package/public/js/features/welcome.js +43 -0
- package/public/js/features/workflows.js +277 -0
- package/public/js/main.js +51 -0
- package/public/js/panels/assistant-bot.js +445 -0
- package/public/js/panels/dev-docs.js +380 -0
- package/public/js/panels/file-explorer.js +486 -0
- package/public/js/panels/git-panel.js +285 -0
- package/public/js/panels/mcp-manager.js +311 -0
- package/public/js/panels/tips-feed.js +303 -0
- package/public/js/ui/commands.js +114 -0
- package/public/js/ui/context-gauge.js +100 -0
- package/public/js/ui/diff.js +124 -0
- package/public/js/ui/disabled-tools.js +36 -0
- package/public/js/ui/export.js +74 -0
- package/public/js/ui/formatting.js +206 -0
- package/public/js/ui/header-dropdowns.js +72 -0
- package/public/js/ui/input-meta.js +71 -0
- package/public/js/ui/max-turns.js +21 -0
- package/public/js/ui/messages.js +387 -0
- package/public/js/ui/model-selector.js +20 -0
- package/public/js/ui/notifications.js +232 -0
- package/public/js/ui/parallel.js +176 -0
- package/public/js/ui/permissions.js +168 -0
- package/public/js/ui/right-panel.js +173 -0
- package/public/js/ui/shortcuts.js +143 -0
- package/public/js/ui/sidebar-toggle.js +29 -0
- package/public/js/ui/status-bar.js +172 -0
- package/public/js/ui/tab-sdk.js +623 -0
- package/public/js/ui/theme.js +38 -0
- package/public/manifest.json +13 -0
- package/public/offline.html +190 -0
- package/public/style.css +42 -0
- package/public/sw.js +91 -0
- package/server/agent-loop.js +385 -0
- package/server/dag-executor.js +265 -0
- package/server/orchestrator.js +514 -0
- package/server/paths.js +61 -0
- package/server/plugin-mount.js +56 -0
- package/server/push-sender.js +31 -0
- package/server/routes/agents.js +294 -0
- package/server/routes/bot.js +45 -0
- package/server/routes/exec.js +35 -0
- package/server/routes/files.js +218 -0
- package/server/routes/mcp.js +82 -0
- package/server/routes/messages.js +36 -0
- package/server/routes/notifications.js +37 -0
- package/server/routes/projects.js +207 -0
- package/server/routes/prompts.js +53 -0
- package/server/routes/sessions.js +103 -0
- package/server/routes/stats.js +143 -0
- package/server/routes/telegram.js +71 -0
- package/server/routes/tips.js +135 -0
- package/server/routes/workflows.js +81 -0
- package/server/summarizer.js +55 -0
- package/server/telegram-poller.js +205 -0
- package/server/telegram-sender.js +304 -0
- package/server/ws-handler.js +926 -0
- package/server.js +179 -0
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
// Centralized DOM references
|
|
2
|
+
export const $ = {
|
|
3
|
+
// Home
|
|
4
|
+
homeBtn: document.getElementById("home-btn"),
|
|
5
|
+
homePage: document.getElementById("home-page"),
|
|
6
|
+
|
|
7
|
+
// Main controls
|
|
8
|
+
projectSelect: document.getElementById("project-select"),
|
|
9
|
+
newSessionBtn: document.getElementById("new-session-btn"),
|
|
10
|
+
sessionList: document.getElementById("session-list"),
|
|
11
|
+
messagesDiv: document.getElementById("messages"),
|
|
12
|
+
messageInput: document.getElementById("message-input"),
|
|
13
|
+
sendBtn: document.getElementById("send-btn"),
|
|
14
|
+
stopBtn: document.getElementById("stop-btn"),
|
|
15
|
+
toggleParallelBtn: document.getElementById("toggle-parallel-btn"),
|
|
16
|
+
|
|
17
|
+
// Header
|
|
18
|
+
connectionDot: document.getElementById("connection-dot"),
|
|
19
|
+
connectionText: document.getElementById("connection-text"),
|
|
20
|
+
accountEmail: document.getElementById("account-email"),
|
|
21
|
+
accountPlan: document.getElementById("account-plan"),
|
|
22
|
+
totalCostEl: document.getElementById("total-cost"),
|
|
23
|
+
projectCostEl: document.getElementById("project-cost"),
|
|
24
|
+
headerProjectName: document.getElementById("header-project-name"),
|
|
25
|
+
|
|
26
|
+
// Toolbox
|
|
27
|
+
toolboxBtn: document.getElementById("toolbox-btn"),
|
|
28
|
+
toolboxPanel: document.getElementById("toolbox-panel"),
|
|
29
|
+
|
|
30
|
+
// Workflows (panel kept for legacy, button merged into agent-btn)
|
|
31
|
+
workflowBtn: document.getElementById("workflow-btn"), // removed from DOM — will be null
|
|
32
|
+
workflowPanel: document.getElementById("workflow-panel"),
|
|
33
|
+
|
|
34
|
+
// Workflow CRUD Modal
|
|
35
|
+
wfModal: document.getElementById("wf-modal"),
|
|
36
|
+
wfModalTitle: document.getElementById("wf-modal-title"),
|
|
37
|
+
wfModalClose: document.getElementById("wf-modal-close"),
|
|
38
|
+
wfModalCancel: document.getElementById("wf-modal-cancel"),
|
|
39
|
+
wfForm: document.getElementById("wf-form"),
|
|
40
|
+
wfFormTitle: document.getElementById("wf-form-title"),
|
|
41
|
+
wfFormDesc: document.getElementById("wf-form-desc"),
|
|
42
|
+
wfStepsList: document.getElementById("wf-steps-list"),
|
|
43
|
+
wfAddStepBtn: document.getElementById("wf-add-step-btn"),
|
|
44
|
+
wfFormEditId: document.getElementById("wf-form-edit-id"),
|
|
45
|
+
|
|
46
|
+
// Agents
|
|
47
|
+
agentBtn: document.getElementById("agent-btn"),
|
|
48
|
+
agentPanel: document.getElementById("agent-panel"),
|
|
49
|
+
agentModal: document.getElementById("agent-modal"),
|
|
50
|
+
agentModalTitle: document.getElementById("agent-modal-title"),
|
|
51
|
+
agentModalClose: document.getElementById("agent-modal-close"),
|
|
52
|
+
agentModalCancel: document.getElementById("agent-modal-cancel"),
|
|
53
|
+
agentForm: document.getElementById("agent-form"),
|
|
54
|
+
agentFormTitle: document.getElementById("agent-form-title"),
|
|
55
|
+
agentFormDesc: document.getElementById("agent-form-desc"),
|
|
56
|
+
agentFormIcon: document.getElementById("agent-form-icon"),
|
|
57
|
+
agentFormGoal: document.getElementById("agent-form-goal"),
|
|
58
|
+
agentFormMaxTurns: document.getElementById("agent-form-max-turns"),
|
|
59
|
+
agentFormTimeout: document.getElementById("agent-form-timeout"),
|
|
60
|
+
agentFormEditId: document.getElementById("agent-form-edit-id"),
|
|
61
|
+
|
|
62
|
+
// Agent Chains
|
|
63
|
+
chainModal: document.getElementById("chain-modal"),
|
|
64
|
+
chainModalTitle: document.getElementById("chain-modal-title"),
|
|
65
|
+
chainModalClose: document.getElementById("chain-modal-close"),
|
|
66
|
+
chainModalCancel: document.getElementById("chain-modal-cancel"),
|
|
67
|
+
chainForm: document.getElementById("chain-form"),
|
|
68
|
+
chainFormTitle: document.getElementById("chain-form-title"),
|
|
69
|
+
chainFormDesc: document.getElementById("chain-form-desc"),
|
|
70
|
+
chainAgentList: document.getElementById("chain-agent-list"),
|
|
71
|
+
chainAddAgentBtn: document.getElementById("chain-add-agent-btn"),
|
|
72
|
+
chainFormContext: document.getElementById("chain-form-context"),
|
|
73
|
+
chainFormEditId: document.getElementById("chain-form-edit-id"),
|
|
74
|
+
|
|
75
|
+
// DAG Editor
|
|
76
|
+
dagModal: document.getElementById("dag-modal"),
|
|
77
|
+
dagModalTitle: document.getElementById("dag-modal-title"),
|
|
78
|
+
dagModalClose: document.getElementById("dag-modal-close"),
|
|
79
|
+
dagModalCancel: document.getElementById("dag-modal-cancel"),
|
|
80
|
+
dagModalSave: document.getElementById("dag-modal-save"),
|
|
81
|
+
dagAutoLayout: document.getElementById("dag-auto-layout"),
|
|
82
|
+
dagFormTitle: document.getElementById("dag-form-title"),
|
|
83
|
+
dagFormDesc: document.getElementById("dag-form-desc"),
|
|
84
|
+
dagFormEditId: document.getElementById("dag-form-edit-id"),
|
|
85
|
+
dagNodePalette: document.getElementById("dag-node-palette"),
|
|
86
|
+
dagCanvas: document.getElementById("dag-canvas"),
|
|
87
|
+
|
|
88
|
+
// System prompt
|
|
89
|
+
spBadge: document.getElementById("system-prompt-badge"),
|
|
90
|
+
spEditBtn: document.getElementById("system-prompt-edit-btn"),
|
|
91
|
+
spModal: document.getElementById("system-prompt-modal"),
|
|
92
|
+
spTextarea: document.getElementById("sp-textarea"),
|
|
93
|
+
spForm: document.getElementById("system-prompt-form"),
|
|
94
|
+
|
|
95
|
+
// File picker
|
|
96
|
+
attachBtn: document.getElementById("attach-btn"),
|
|
97
|
+
attachBadge: document.getElementById("attach-badge"),
|
|
98
|
+
fpModal: document.getElementById("file-picker-modal"),
|
|
99
|
+
fpSearch: document.getElementById("fp-search"),
|
|
100
|
+
fpList: document.getElementById("fp-list"),
|
|
101
|
+
fpCount: document.getElementById("fp-count"),
|
|
102
|
+
|
|
103
|
+
// Image attachments
|
|
104
|
+
imageBtn: document.getElementById("image-btn"),
|
|
105
|
+
imageFileInput: document.getElementById("image-file-input"),
|
|
106
|
+
imagePreviewStrip: document.getElementById("image-preview-strip"),
|
|
107
|
+
|
|
108
|
+
// Voice input
|
|
109
|
+
micBtn: document.getElementById("mic-btn"),
|
|
110
|
+
|
|
111
|
+
// Prompt modal
|
|
112
|
+
promptModal: document.getElementById("prompt-modal"),
|
|
113
|
+
promptForm: document.getElementById("prompt-form"),
|
|
114
|
+
modalCloseBtn: document.getElementById("modal-close"),
|
|
115
|
+
modalCancelBtn: document.getElementById("modal-cancel"),
|
|
116
|
+
|
|
117
|
+
// Shortcuts
|
|
118
|
+
shortcutsModal: document.getElementById("shortcuts-modal"),
|
|
119
|
+
|
|
120
|
+
// Cost dashboard
|
|
121
|
+
costDashboardModal: document.getElementById("cost-dashboard-modal"),
|
|
122
|
+
costModalClose: document.getElementById("cost-modal-close"),
|
|
123
|
+
|
|
124
|
+
// Theme
|
|
125
|
+
themeToggleBtn: document.getElementById("theme-toggle-btn"),
|
|
126
|
+
themeIconSun: document.getElementById("theme-icon-sun"),
|
|
127
|
+
themeIconMoon: document.getElementById("theme-icon-moon"),
|
|
128
|
+
|
|
129
|
+
// Session search
|
|
130
|
+
sessionSearchInput: document.getElementById("session-search"),
|
|
131
|
+
|
|
132
|
+
// Context gauge
|
|
133
|
+
contextGauge: document.getElementById("context-gauge"),
|
|
134
|
+
contextGaugeFill: document.getElementById("context-gauge-fill"),
|
|
135
|
+
contextGaugeLabel: document.getElementById("context-gauge-label"),
|
|
136
|
+
|
|
137
|
+
// Streaming tokens (status bar)
|
|
138
|
+
streamingTokens: document.getElementById("sb-streaming-tokens"),
|
|
139
|
+
streamingTokensValue: document.getElementById("sb-tokens-value"),
|
|
140
|
+
streamingTokensSep: document.getElementById("sb-tokens-sep"),
|
|
141
|
+
|
|
142
|
+
// Model selector
|
|
143
|
+
modelSelect: document.getElementById("model-select"),
|
|
144
|
+
|
|
145
|
+
// Max turns selector
|
|
146
|
+
maxTurnsSelect: document.getElementById("max-turns-select"),
|
|
147
|
+
|
|
148
|
+
// Permissions
|
|
149
|
+
permModeSelect: document.getElementById("perm-mode-select"),
|
|
150
|
+
permModal: document.getElementById("perm-modal"),
|
|
151
|
+
permModalToolName: document.getElementById("perm-modal-tool-name"),
|
|
152
|
+
permModalSummary: document.getElementById("perm-modal-summary"),
|
|
153
|
+
permModalInput: document.getElementById("perm-modal-input"),
|
|
154
|
+
permAlwaysAllowCb: document.getElementById("perm-always-allow-cb"),
|
|
155
|
+
permAlwaysAllowTool: document.getElementById("perm-always-allow-tool"),
|
|
156
|
+
permAllowBtn: document.getElementById("perm-allow-btn"),
|
|
157
|
+
permDenyBtn: document.getElementById("perm-deny-btn"),
|
|
158
|
+
|
|
159
|
+
// Background sessions
|
|
160
|
+
bgConfirmModal: document.getElementById("bg-confirm-modal"),
|
|
161
|
+
bgConfirmCancel: document.getElementById("bg-confirm-cancel"),
|
|
162
|
+
bgConfirmAbort: document.getElementById("bg-confirm-abort"),
|
|
163
|
+
bgConfirmBackground: document.getElementById("bg-confirm-background"),
|
|
164
|
+
bgSessionIndicator: document.getElementById("bg-session-indicator"),
|
|
165
|
+
bgSessionBadge: document.getElementById("bg-session-badge"),
|
|
166
|
+
|
|
167
|
+
// Telegram
|
|
168
|
+
telegramBtn: document.getElementById("telegram-settings-btn"),
|
|
169
|
+
telegramModal: document.getElementById("telegram-modal"),
|
|
170
|
+
telegramEnabled: document.getElementById("telegram-enabled"),
|
|
171
|
+
telegramBotToken: document.getElementById("telegram-bot-token"),
|
|
172
|
+
telegramChatId: document.getElementById("telegram-chat-id"),
|
|
173
|
+
telegramAfkTimeout: document.getElementById("telegram-afk-timeout"),
|
|
174
|
+
telegramTestBtn: document.getElementById("telegram-test-btn"),
|
|
175
|
+
telegramSaveBtn: document.getElementById("telegram-save-btn"),
|
|
176
|
+
telegramClose: document.getElementById("telegram-close"),
|
|
177
|
+
telegramLabel: document.getElementById("telegram-label"),
|
|
178
|
+
telegramStatus: document.getElementById("telegram-status"),
|
|
179
|
+
tgNotifySession: document.getElementById("tg-notify-session"),
|
|
180
|
+
tgNotifyWorkflow: document.getElementById("tg-notify-workflow"),
|
|
181
|
+
tgNotifyChain: document.getElementById("tg-notify-chain"),
|
|
182
|
+
tgNotifyAgent: document.getElementById("tg-notify-agent"),
|
|
183
|
+
tgNotifyOrchestrator: document.getElementById("tg-notify-orchestrator"),
|
|
184
|
+
tgNotifyDag: document.getElementById("tg-notify-dag"),
|
|
185
|
+
tgNotifyErrors: document.getElementById("tg-notify-errors"),
|
|
186
|
+
tgNotifyPermissions: document.getElementById("tg-notify-permissions"),
|
|
187
|
+
tgNotifyStart: document.getElementById("tg-notify-start"),
|
|
188
|
+
|
|
189
|
+
// Tips feed panel
|
|
190
|
+
tipsFeedPanel: document.getElementById("tips-feed-panel"),
|
|
191
|
+
tipsFeedToggleBtn: document.getElementById("tips-feed-toggle-btn"),
|
|
192
|
+
tipsFeedClose: document.getElementById("tips-feed-close"),
|
|
193
|
+
tipsFeedContent: document.getElementById("tips-feed-content"),
|
|
194
|
+
tipsFeedResize: document.getElementById("tips-feed-resize"),
|
|
195
|
+
|
|
196
|
+
// Right panel
|
|
197
|
+
rightPanel: document.getElementById("right-panel"),
|
|
198
|
+
rightPanelToggleBtn: document.getElementById("right-panel-toggle-btn"),
|
|
199
|
+
rightPanelClose: document.getElementById("right-panel-close"),
|
|
200
|
+
|
|
201
|
+
// File explorer (inside right panel files tab)
|
|
202
|
+
fileExplorerSearch: document.getElementById("file-explorer-search"),
|
|
203
|
+
fileRefreshBtn: document.getElementById("file-refresh-btn"),
|
|
204
|
+
fileTree: document.getElementById("file-tree"),
|
|
205
|
+
filePreview: document.getElementById("file-preview"),
|
|
206
|
+
filePreviewName: document.getElementById("file-preview-name"),
|
|
207
|
+
filePreviewContent: document.getElementById("file-preview-content"),
|
|
208
|
+
filePreviewImage: document.getElementById("file-preview-image"),
|
|
209
|
+
filePreviewClose: document.getElementById("file-preview-close"),
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
// Git panel (inside right panel git tab)
|
|
213
|
+
gitBranchSelect: document.getElementById("git-branch-select"),
|
|
214
|
+
gitRefreshBtn: document.getElementById("git-refresh-btn"),
|
|
215
|
+
gitStatusList: document.getElementById("git-status-list"),
|
|
216
|
+
gitCommitMsg: document.getElementById("git-commit-msg"),
|
|
217
|
+
gitCommitBtn: document.getElementById("git-commit-btn"),
|
|
218
|
+
gitLogList: document.getElementById("git-log-list"),
|
|
219
|
+
|
|
220
|
+
// MCP manager
|
|
221
|
+
mcpToggleBtn: document.getElementById("mcp-toggle-btn"),
|
|
222
|
+
mcpModal: document.getElementById("mcp-modal"),
|
|
223
|
+
mcpModalClose: document.getElementById("mcp-modal-close"),
|
|
224
|
+
mcpServerList: document.getElementById("mcp-server-list"),
|
|
225
|
+
mcpFormContainer: document.getElementById("mcp-form-container"),
|
|
226
|
+
mcpFormTitle: document.getElementById("mcp-form-title"),
|
|
227
|
+
mcpForm: document.getElementById("mcp-form"),
|
|
228
|
+
mcpName: document.getElementById("mcp-name"),
|
|
229
|
+
mcpType: document.getElementById("mcp-type"),
|
|
230
|
+
mcpStdioFields: document.getElementById("mcp-stdio-fields"),
|
|
231
|
+
mcpUrlFields: document.getElementById("mcp-url-fields"),
|
|
232
|
+
mcpCommand: document.getElementById("mcp-command"),
|
|
233
|
+
mcpArgs: document.getElementById("mcp-args"),
|
|
234
|
+
mcpEnv: document.getElementById("mcp-env"),
|
|
235
|
+
mcpUrl: document.getElementById("mcp-url"),
|
|
236
|
+
mcpFormCancel: document.getElementById("mcp-form-cancel"),
|
|
237
|
+
mcpFormSave: document.getElementById("mcp-form-save"),
|
|
238
|
+
mcpAddBtn: document.getElementById("mcp-add-btn"),
|
|
239
|
+
|
|
240
|
+
// Sidebar toggle (mobile)
|
|
241
|
+
sidebarToggleBtn: document.getElementById("sidebar-toggle-btn"),
|
|
242
|
+
sidebarBackdrop: document.getElementById("sidebar-backdrop"),
|
|
243
|
+
|
|
244
|
+
// Agent sidebar
|
|
245
|
+
agentSidebar: document.getElementById("agent-sidebar"),
|
|
246
|
+
agentSidebarClose: document.getElementById("agent-sidebar-close"),
|
|
247
|
+
|
|
248
|
+
// Orchestrate modal
|
|
249
|
+
orchModal: document.getElementById("orch-modal"),
|
|
250
|
+
orchModalClose: document.getElementById("orch-modal-close"),
|
|
251
|
+
orchModalCancel: document.getElementById("orch-modal-cancel"),
|
|
252
|
+
orchModalRun: document.getElementById("orch-modal-run"),
|
|
253
|
+
orchTaskInput: document.getElementById("orch-task-input"),
|
|
254
|
+
|
|
255
|
+
// Agent monitor
|
|
256
|
+
agentMonitorModal: document.getElementById("agent-monitor-modal"),
|
|
257
|
+
agentMonitorClose: document.getElementById("agent-monitor-close"),
|
|
258
|
+
agentMonitorContent: document.getElementById("agent-monitor-content"),
|
|
259
|
+
|
|
260
|
+
// Add project modal
|
|
261
|
+
openVscodeBtn: document.getElementById("open-vscode-btn"),
|
|
262
|
+
addProjectBtn: document.getElementById("add-project-btn"),
|
|
263
|
+
addProjectModal: document.getElementById("add-project-modal"),
|
|
264
|
+
addProjectClose: document.getElementById("add-project-close"),
|
|
265
|
+
addProjectName: document.getElementById("add-project-name"),
|
|
266
|
+
addProjectConfirm: document.getElementById("add-project-confirm"),
|
|
267
|
+
folderBreadcrumb: document.getElementById("folder-breadcrumb"),
|
|
268
|
+
folderList: document.getElementById("folder-list"),
|
|
269
|
+
|
|
270
|
+
};
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
// Plugin Loader — auto-discovers and loads tab-sdk plugins
|
|
2
|
+
//
|
|
3
|
+
// How it works:
|
|
4
|
+
// 1. Fetches GET /api/plugins → list of {name, js, css, source, apiBase} entries
|
|
5
|
+
// 2. Stores manifest for the marketplace UI
|
|
6
|
+
// 3. Only loads plugins the user has enabled (persisted in localStorage)
|
|
7
|
+
//
|
|
8
|
+
// Plugin sources (checked in order, first match wins):
|
|
9
|
+
// 1. Built-in plugins in plugins/<name>/ (client.js, client.css, server.js, config.json)
|
|
10
|
+
// 2. User plugins in ~/.claudeck/plugins/<name>/ (same directory structure)
|
|
11
|
+
|
|
12
|
+
const STORAGE_KEY = 'claudeck-enabled-plugins';
|
|
13
|
+
const ORDER_KEY = 'claudeck-plugin-order';
|
|
14
|
+
let availablePlugins = [];
|
|
15
|
+
const loadedPlugins = new Set();
|
|
16
|
+
|
|
17
|
+
/** Maps plugin file name → tab ID registered by that plugin */
|
|
18
|
+
const pluginTabIds = new Map();
|
|
19
|
+
|
|
20
|
+
/** Plugin descriptions for the marketplace. order: lower = higher in the list */
|
|
21
|
+
const pluginMeta = {
|
|
22
|
+
'claude-editor': { description: 'Edit CLAUDE.md project instructions directly in the UI', icon: '📝', order: 5 },
|
|
23
|
+
'event-stream': { description: 'Real-time WebSocket event viewer with filtering and search', icon: '⚡', order: 10 },
|
|
24
|
+
'repos': { description: 'Git repository and group management with tree view', icon: '📁', order: 20 },
|
|
25
|
+
'linear': { description: 'Linear issue tracking with settings and team management', icon: '📋', order: 25 },
|
|
26
|
+
'tasks': { description: 'Todo list with priority levels and brag tracking', icon: '✅', order: 30 },
|
|
27
|
+
'tic-tac-toe': { description: 'Classic tic-tac-toe game', icon: '🎮', order: 90 },
|
|
28
|
+
'sudoku': { description: 'Sudoku puzzle game', icon: '🧩', order: 91 },
|
|
29
|
+
};
|
|
30
|
+
const defaultMeta = { description: 'A tab-sdk plugin', icon: '🧩', order: 100 };
|
|
31
|
+
|
|
32
|
+
export function getAvailablePlugins() {
|
|
33
|
+
return availablePlugins;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function getEnabledPluginNames() {
|
|
37
|
+
try {
|
|
38
|
+
const raw = localStorage.getItem(STORAGE_KEY);
|
|
39
|
+
return raw ? JSON.parse(raw) : [];
|
|
40
|
+
} catch { return []; }
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function setEnabledPluginNames(names) {
|
|
44
|
+
localStorage.setItem(STORAGE_KEY, JSON.stringify(names));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function getPluginMeta(name) {
|
|
48
|
+
return pluginMeta[name] || defaultMeta;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function getPluginOrder() {
|
|
52
|
+
try {
|
|
53
|
+
const raw = localStorage.getItem(ORDER_KEY);
|
|
54
|
+
return raw ? JSON.parse(raw) : [];
|
|
55
|
+
} catch { return []; }
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function setPluginOrder(names) {
|
|
59
|
+
localStorage.setItem(ORDER_KEY, JSON.stringify(names));
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Return available plugins sorted by saved order (unsorted ones go to end by meta.order) */
|
|
63
|
+
export function getSortedPlugins() {
|
|
64
|
+
const saved = getPluginOrder();
|
|
65
|
+
const all = [...availablePlugins];
|
|
66
|
+
all.sort((a, b) => {
|
|
67
|
+
const ai = saved.indexOf(a.name);
|
|
68
|
+
const bi = saved.indexOf(b.name);
|
|
69
|
+
// Both in saved order — use saved positions
|
|
70
|
+
if (ai !== -1 && bi !== -1) return ai - bi;
|
|
71
|
+
// Only one in saved order — it comes first
|
|
72
|
+
if (ai !== -1) return -1;
|
|
73
|
+
if (bi !== -1) return 1;
|
|
74
|
+
// Neither saved — fall back to meta.order
|
|
75
|
+
return (getPluginMeta(a.name).order ?? 100) - (getPluginMeta(b.name).order ?? 100);
|
|
76
|
+
});
|
|
77
|
+
return all;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** Optional hook: set by tab-sdk to get current registered tab IDs */
|
|
81
|
+
let _getRegisteredTabIds = null;
|
|
82
|
+
export function setTabIdResolver(fn) { _getRegisteredTabIds = fn; }
|
|
83
|
+
|
|
84
|
+
async function loadPlugin(plugin) {
|
|
85
|
+
if (loadedPlugins.has(plugin.name)) return;
|
|
86
|
+
if (plugin.css) {
|
|
87
|
+
const link = document.createElement('link');
|
|
88
|
+
link.rel = 'stylesheet';
|
|
89
|
+
link.href = `/${plugin.css}`;
|
|
90
|
+
link.dataset.plugin = plugin.name;
|
|
91
|
+
document.head.appendChild(link);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const before = _getRegisteredTabIds ? new Set(_getRegisteredTabIds()) : null;
|
|
95
|
+
|
|
96
|
+
try {
|
|
97
|
+
await import(`/${plugin.js}`);
|
|
98
|
+
loadedPlugins.add(plugin.name);
|
|
99
|
+
console.log(`Plugin loaded: ${plugin.name}`);
|
|
100
|
+
|
|
101
|
+
// Auto-detect which tab ID this plugin registered
|
|
102
|
+
if (before && _getRegisteredTabIds) {
|
|
103
|
+
for (const id of _getRegisteredTabIds()) {
|
|
104
|
+
if (!before.has(id)) {
|
|
105
|
+
pluginTabIds.set(plugin.name, id);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
} catch (err) {
|
|
110
|
+
console.error(`Plugin failed: ${plugin.name}`, err);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export async function loadPluginByName(name) {
|
|
115
|
+
const plugin = availablePlugins.find(p => p.name === name);
|
|
116
|
+
if (plugin) await loadPlugin(plugin);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export function isPluginLoaded(name) {
|
|
120
|
+
return loadedPlugins.has(name);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/** Record which tab ID a plugin registered (called from tab-sdk) */
|
|
124
|
+
export function trackPluginTab(pluginName, tabId) {
|
|
125
|
+
pluginTabIds.set(pluginName, tabId);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/** Get the tab ID registered by a plugin */
|
|
129
|
+
export function getPluginTabId(pluginName) {
|
|
130
|
+
return pluginTabIds.get(pluginName);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/** Get all plugin-name → tab-id mappings */
|
|
134
|
+
export function getPluginTabMap() {
|
|
135
|
+
return pluginTabIds;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export async function loadPlugins() {
|
|
139
|
+
try {
|
|
140
|
+
const res = await fetch('/api/plugins');
|
|
141
|
+
if (!res.ok) { console.warn('Plugin discovery failed:', res.status); return; }
|
|
142
|
+
|
|
143
|
+
availablePlugins = await res.json();
|
|
144
|
+
if (!availablePlugins.length) return;
|
|
145
|
+
|
|
146
|
+
// Only load enabled plugins
|
|
147
|
+
const enabled = getEnabledPluginNames();
|
|
148
|
+
const toLoad = availablePlugins.filter(p => enabled.includes(p.name));
|
|
149
|
+
await Promise.all(toLoad.map(loadPlugin));
|
|
150
|
+
} catch (err) {
|
|
151
|
+
console.error('Plugin loader error:', err);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// Centralized reactive state store
|
|
2
|
+
const state = {
|
|
3
|
+
view: "home",
|
|
4
|
+
ws: null,
|
|
5
|
+
sessionId: null,
|
|
6
|
+
parallelMode: false,
|
|
7
|
+
streamingCharCount: 0,
|
|
8
|
+
prompts: [],
|
|
9
|
+
workflows: [],
|
|
10
|
+
agents: [],
|
|
11
|
+
projectsData: [],
|
|
12
|
+
attachedFiles: [],
|
|
13
|
+
imageAttachments: [],
|
|
14
|
+
allProjectFiles: [],
|
|
15
|
+
mermaidCounter: 0,
|
|
16
|
+
savedChatArea: null,
|
|
17
|
+
backgroundSessions: new Map(),
|
|
18
|
+
notificationsEnabled: false,
|
|
19
|
+
sessionTokens: { input: 0, output: 0, cacheRead: 0, cacheCreation: 0 },
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const listeners = {};
|
|
23
|
+
|
|
24
|
+
export function getState(key) {
|
|
25
|
+
return state[key];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function setState(key, val) {
|
|
29
|
+
state[key] = val;
|
|
30
|
+
emit(key, val);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function on(key, fn) {
|
|
34
|
+
(listeners[key] ||= []).push(fn);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function emit(key, val) {
|
|
38
|
+
(listeners[key] || []).forEach((fn) => fn(val));
|
|
39
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// Pure utility functions
|
|
2
|
+
|
|
3
|
+
export function escapeHtml(str) {
|
|
4
|
+
const div = document.createElement("div");
|
|
5
|
+
div.textContent = str;
|
|
6
|
+
return div.innerHTML;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function slugify(title) {
|
|
10
|
+
return title.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function getToolDetail(name, input) {
|
|
14
|
+
if (!input) return "";
|
|
15
|
+
if (input.file_path) return escapeHtml(input.file_path);
|
|
16
|
+
if (input.command) return escapeHtml(input.command.slice(0, 80));
|
|
17
|
+
if (input.pattern) return escapeHtml(input.pattern);
|
|
18
|
+
if (input.query) return escapeHtml(input.query);
|
|
19
|
+
if (input.prompt) return escapeHtml(input.prompt.slice(0, 80));
|
|
20
|
+
return "";
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function scrollToBottom(pane) {
|
|
24
|
+
pane.messagesDiv.scrollTop = pane.messagesDiv.scrollHeight;
|
|
25
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// WebSocket connection + message dispatch with exponential backoff
|
|
2
|
+
import { $ } from './dom.js';
|
|
3
|
+
import { getState, setState } from './store.js';
|
|
4
|
+
import { emit } from './events.js';
|
|
5
|
+
|
|
6
|
+
let backoffAttempt = 0;
|
|
7
|
+
let hasConnectedBefore = false;
|
|
8
|
+
|
|
9
|
+
const BACKOFF_BASE_MS = 2000;
|
|
10
|
+
const BACKOFF_FACTOR = 2;
|
|
11
|
+
const BACKOFF_MAX_MS = 30000;
|
|
12
|
+
|
|
13
|
+
function getBackoffDelay() {
|
|
14
|
+
const delay = Math.min(BACKOFF_BASE_MS * Math.pow(BACKOFF_FACTOR, backoffAttempt), BACKOFF_MAX_MS);
|
|
15
|
+
// Add 0-25% jitter
|
|
16
|
+
const jitter = delay * Math.random() * 0.25;
|
|
17
|
+
return delay + jitter;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function connectWebSocket() {
|
|
21
|
+
const protocol = location.protocol === "https:" ? "wss:" : "ws:";
|
|
22
|
+
const ws = new WebSocket(`${protocol}//${location.host}/ws`);
|
|
23
|
+
setState("ws", ws);
|
|
24
|
+
|
|
25
|
+
ws.onopen = () => {
|
|
26
|
+
console.log("WebSocket connected");
|
|
27
|
+
$.connectionDot.className = "term-dot connected";
|
|
28
|
+
$.connectionText.textContent = "connected";
|
|
29
|
+
$.connectionText.className = "term-status ok";
|
|
30
|
+
|
|
31
|
+
// Reset backoff on successful connection
|
|
32
|
+
backoffAttempt = 0;
|
|
33
|
+
|
|
34
|
+
if (hasConnectedBefore) {
|
|
35
|
+
emit("ws:reconnected");
|
|
36
|
+
} else {
|
|
37
|
+
hasConnectedBefore = true;
|
|
38
|
+
emit("ws:connected");
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
ws.onmessage = (event) => {
|
|
43
|
+
const msg = JSON.parse(event.data);
|
|
44
|
+
emit("ws:message", msg);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
ws.onclose = () => {
|
|
48
|
+
const delay = getBackoffDelay();
|
|
49
|
+
backoffAttempt++;
|
|
50
|
+
console.log(`WebSocket disconnected, reconnecting in ${Math.round(delay)}ms (attempt ${backoffAttempt})...`);
|
|
51
|
+
$.connectionDot.className = "term-dot reconnecting";
|
|
52
|
+
$.connectionText.textContent = "reconnecting";
|
|
53
|
+
$.connectionText.className = "term-status";
|
|
54
|
+
emit("ws:disconnected");
|
|
55
|
+
setTimeout(connectWebSocket, delay);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
ws.onerror = (err) => {
|
|
59
|
+
console.error("WebSocket error:", err);
|
|
60
|
+
$.connectionDot.className = "term-dot";
|
|
61
|
+
$.connectionText.textContent = "disconnected";
|
|
62
|
+
$.connectionText.className = "term-status";
|
|
63
|
+
};
|
|
64
|
+
}
|