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.
Files changed (157) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +233 -0
  3. package/cli.js +2 -0
  4. package/config/agent-chains.json +16 -0
  5. package/config/agent-dags.json +16 -0
  6. package/config/agents.json +46 -0
  7. package/config/bot-prompt.json +3 -0
  8. package/config/folders.json +66 -0
  9. package/config/prompts.json +92 -0
  10. package/config/repos.json +86 -0
  11. package/config/telegram-config.json +17 -0
  12. package/config/workflows.json +90 -0
  13. package/db.js +1198 -0
  14. package/package.json +55 -0
  15. package/plugins/claude-editor/client.css +171 -0
  16. package/plugins/claude-editor/client.js +183 -0
  17. package/plugins/event-stream/client.css +207 -0
  18. package/plugins/event-stream/client.js +271 -0
  19. package/plugins/linear/client.css +345 -0
  20. package/plugins/linear/client.js +380 -0
  21. package/plugins/linear/config.json +5 -0
  22. package/plugins/linear/server.js +312 -0
  23. package/plugins/repos/client.css +549 -0
  24. package/plugins/repos/client.js +663 -0
  25. package/plugins/repos/server.js +232 -0
  26. package/plugins/sudoku/client.css +196 -0
  27. package/plugins/sudoku/client.js +329 -0
  28. package/plugins/tasks/client.css +414 -0
  29. package/plugins/tasks/client.js +394 -0
  30. package/plugins/tasks/server.js +116 -0
  31. package/plugins/tic-tac-toe/client.css +167 -0
  32. package/plugins/tic-tac-toe/client.js +241 -0
  33. package/public/css/core/components.css +232 -0
  34. package/public/css/core/layout.css +330 -0
  35. package/public/css/core/print.css +18 -0
  36. package/public/css/core/reset.css +36 -0
  37. package/public/css/core/responsive.css +378 -0
  38. package/public/css/core/theme.css +116 -0
  39. package/public/css/core/variables.css +93 -0
  40. package/public/css/features/agent-monitor.css +297 -0
  41. package/public/css/features/agent-sidebar.css +525 -0
  42. package/public/css/features/agents.css +996 -0
  43. package/public/css/features/analytics.css +181 -0
  44. package/public/css/features/background-sessions.css +321 -0
  45. package/public/css/features/cost-dashboard.css +168 -0
  46. package/public/css/features/home.css +313 -0
  47. package/public/css/features/retro-terminal.css +88 -0
  48. package/public/css/features/telegram.css +127 -0
  49. package/public/css/features/tour.css +148 -0
  50. package/public/css/features/voice-input.css +60 -0
  51. package/public/css/features/welcome.css +241 -0
  52. package/public/css/panels/assistant-bot.css +442 -0
  53. package/public/css/panels/dev-docs.css +292 -0
  54. package/public/css/panels/file-explorer.css +322 -0
  55. package/public/css/panels/git-panel.css +221 -0
  56. package/public/css/panels/mcp-manager.css +199 -0
  57. package/public/css/panels/tips-feed.css +353 -0
  58. package/public/css/ui/commands.css +273 -0
  59. package/public/css/ui/context-gauge.css +76 -0
  60. package/public/css/ui/file-picker.css +69 -0
  61. package/public/css/ui/image-attachments.css +106 -0
  62. package/public/css/ui/messages.css +884 -0
  63. package/public/css/ui/modals.css +122 -0
  64. package/public/css/ui/parallel.css +217 -0
  65. package/public/css/ui/permissions.css +110 -0
  66. package/public/css/ui/right-panel.css +481 -0
  67. package/public/css/ui/sessions.css +689 -0
  68. package/public/css/ui/status-bar.css +425 -0
  69. package/public/css/ui/toolbox.css +206 -0
  70. package/public/data/tips.json +218 -0
  71. package/public/icons/favicon.png +0 -0
  72. package/public/icons/icon-192.png +0 -0
  73. package/public/icons/icon-512.png +0 -0
  74. package/public/icons/whaly.png +0 -0
  75. package/public/index.html +1140 -0
  76. package/public/js/core/api.js +591 -0
  77. package/public/js/core/constants.js +3 -0
  78. package/public/js/core/dom.js +270 -0
  79. package/public/js/core/events.js +10 -0
  80. package/public/js/core/plugin-loader.js +153 -0
  81. package/public/js/core/store.js +39 -0
  82. package/public/js/core/utils.js +25 -0
  83. package/public/js/core/ws.js +64 -0
  84. package/public/js/features/agent-monitor.js +222 -0
  85. package/public/js/features/agents.js +1209 -0
  86. package/public/js/features/analytics.js +397 -0
  87. package/public/js/features/attachments.js +251 -0
  88. package/public/js/features/background-sessions.js +475 -0
  89. package/public/js/features/chat.js +589 -0
  90. package/public/js/features/cost-dashboard.js +152 -0
  91. package/public/js/features/dag-editor.js +399 -0
  92. package/public/js/features/easter-egg.js +46 -0
  93. package/public/js/features/home.js +270 -0
  94. package/public/js/features/projects.js +372 -0
  95. package/public/js/features/prompts.js +228 -0
  96. package/public/js/features/sessions.js +332 -0
  97. package/public/js/features/telegram.js +131 -0
  98. package/public/js/features/tour.js +210 -0
  99. package/public/js/features/voice-input.js +185 -0
  100. package/public/js/features/welcome.js +43 -0
  101. package/public/js/features/workflows.js +277 -0
  102. package/public/js/main.js +51 -0
  103. package/public/js/panels/assistant-bot.js +445 -0
  104. package/public/js/panels/dev-docs.js +380 -0
  105. package/public/js/panels/file-explorer.js +486 -0
  106. package/public/js/panels/git-panel.js +285 -0
  107. package/public/js/panels/mcp-manager.js +311 -0
  108. package/public/js/panels/tips-feed.js +303 -0
  109. package/public/js/ui/commands.js +114 -0
  110. package/public/js/ui/context-gauge.js +100 -0
  111. package/public/js/ui/diff.js +124 -0
  112. package/public/js/ui/disabled-tools.js +36 -0
  113. package/public/js/ui/export.js +74 -0
  114. package/public/js/ui/formatting.js +206 -0
  115. package/public/js/ui/header-dropdowns.js +72 -0
  116. package/public/js/ui/input-meta.js +71 -0
  117. package/public/js/ui/max-turns.js +21 -0
  118. package/public/js/ui/messages.js +387 -0
  119. package/public/js/ui/model-selector.js +20 -0
  120. package/public/js/ui/notifications.js +232 -0
  121. package/public/js/ui/parallel.js +176 -0
  122. package/public/js/ui/permissions.js +168 -0
  123. package/public/js/ui/right-panel.js +173 -0
  124. package/public/js/ui/shortcuts.js +143 -0
  125. package/public/js/ui/sidebar-toggle.js +29 -0
  126. package/public/js/ui/status-bar.js +172 -0
  127. package/public/js/ui/tab-sdk.js +623 -0
  128. package/public/js/ui/theme.js +38 -0
  129. package/public/manifest.json +13 -0
  130. package/public/offline.html +190 -0
  131. package/public/style.css +42 -0
  132. package/public/sw.js +91 -0
  133. package/server/agent-loop.js +385 -0
  134. package/server/dag-executor.js +265 -0
  135. package/server/orchestrator.js +514 -0
  136. package/server/paths.js +61 -0
  137. package/server/plugin-mount.js +56 -0
  138. package/server/push-sender.js +31 -0
  139. package/server/routes/agents.js +294 -0
  140. package/server/routes/bot.js +45 -0
  141. package/server/routes/exec.js +35 -0
  142. package/server/routes/files.js +218 -0
  143. package/server/routes/mcp.js +82 -0
  144. package/server/routes/messages.js +36 -0
  145. package/server/routes/notifications.js +37 -0
  146. package/server/routes/projects.js +207 -0
  147. package/server/routes/prompts.js +53 -0
  148. package/server/routes/sessions.js +103 -0
  149. package/server/routes/stats.js +143 -0
  150. package/server/routes/telegram.js +71 -0
  151. package/server/routes/tips.js +135 -0
  152. package/server/routes/workflows.js +81 -0
  153. package/server/summarizer.js +55 -0
  154. package/server/telegram-poller.js +205 -0
  155. package/server/telegram-sender.js +304 -0
  156. package/server/ws-handler.js +926 -0
  157. package/server.js +179 -0
@@ -0,0 +1,232 @@
1
+ import { Router } from "express";
2
+ import { readFile, writeFile, stat, access } from "fs/promises";
3
+ import { join, resolve } from "path";
4
+ import { configPath } from "../../server/paths.js";
5
+
6
+ const dataFile = configPath("repos.json");
7
+
8
+ const router = Router();
9
+
10
+ async function readData() {
11
+ try {
12
+ const raw = await readFile(dataFile, "utf-8");
13
+ return JSON.parse(raw);
14
+ } catch {
15
+ return { groups: [], repos: [] };
16
+ }
17
+ }
18
+
19
+ async function writeData(data) {
20
+ await writeFile(dataFile, JSON.stringify(data, null, 2) + "\n");
21
+ }
22
+
23
+ async function isGitRepo(dirPath) {
24
+ try {
25
+ const resolved = resolve(dirPath);
26
+ const s = await stat(resolved);
27
+ if (!s.isDirectory()) return false;
28
+ // Check for .git directory or .git file (worktrees/submodules)
29
+ const gitPath = join(resolved, ".git");
30
+ await access(gitPath);
31
+ return true;
32
+ } catch {
33
+ // Also check if any parent has .git (we're inside a repo subdirectory)
34
+ try {
35
+ const resolved = resolve(dirPath);
36
+ let dir = resolved;
37
+ while (dir !== "/") {
38
+ dir = dirname(dir);
39
+ await access(join(dir, ".git"));
40
+ return true;
41
+ }
42
+ } catch { /* not inside a repo either */ }
43
+ return false;
44
+ }
45
+ }
46
+
47
+ function hasCircularParent(groups, groupId, newParentId) {
48
+ if (!newParentId) return false;
49
+ let current = newParentId;
50
+ const visited = new Set();
51
+ while (current) {
52
+ if (current === groupId) return true;
53
+ if (visited.has(current)) return true;
54
+ visited.add(current);
55
+ const g = groups.find((g) => g.id === current);
56
+ current = g ? g.parentId : null;
57
+ }
58
+ return false;
59
+ }
60
+
61
+ // GET / — fetch all groups + repos
62
+ router.get("/", async (req, res) => {
63
+ try {
64
+ const data = await readData();
65
+ res.json(data);
66
+ } catch (err) {
67
+ res.status(500).json({ error: err.message });
68
+ }
69
+ });
70
+
71
+ // POST /repos — add a repo (path is optional for manual/remote-only entries)
72
+ router.post("/repos", async (req, res) => {
73
+ try {
74
+ const { name, path: repoPath, groupId } = req.body;
75
+ if (!name) {
76
+ return res.status(400).json({ error: "name is required" });
77
+ }
78
+
79
+ let resolvedPath = null;
80
+ const data = await readData();
81
+
82
+ if (repoPath) {
83
+ resolvedPath = resolve(repoPath);
84
+
85
+ if (!(await isGitRepo(resolvedPath))) {
86
+ return res.status(400).json({ error: "Path is not a valid git repository" });
87
+ }
88
+
89
+ if (data.repos.some((r) => r.path === resolvedPath)) {
90
+ return res.status(409).json({ error: "Repo with this path already exists" });
91
+ }
92
+ }
93
+
94
+ if (groupId && !data.groups.some((g) => g.id === groupId)) {
95
+ return res.status(400).json({ error: "Invalid groupId" });
96
+ }
97
+
98
+ const repo = {
99
+ id: `r_${Date.now()}`,
100
+ name,
101
+ path: resolvedPath,
102
+ groupId: groupId || null,
103
+ url: req.body.url || null,
104
+ };
105
+
106
+ data.repos.push(repo);
107
+ await writeData(data);
108
+ res.json({ ok: true, repo });
109
+ } catch (err) {
110
+ res.status(500).json({ error: err.message });
111
+ }
112
+ });
113
+
114
+ // PUT /repos/:id — update a repo
115
+ router.put("/repos/:id", async (req, res) => {
116
+ try {
117
+ const data = await readData();
118
+ const repo = data.repos.find((r) => r.id === req.params.id);
119
+ if (!repo) return res.status(404).json({ error: "Repo not found" });
120
+
121
+ const { name, groupId, url } = req.body;
122
+ if (name !== undefined) repo.name = name;
123
+ if (url !== undefined) repo.url = url;
124
+ if (groupId !== undefined) {
125
+ if (groupId !== null && !data.groups.some((g) => g.id === groupId)) {
126
+ return res.status(400).json({ error: "Invalid groupId" });
127
+ }
128
+ repo.groupId = groupId;
129
+ }
130
+
131
+ await writeData(data);
132
+ res.json({ ok: true, repo });
133
+ } catch (err) {
134
+ res.status(500).json({ error: err.message });
135
+ }
136
+ });
137
+
138
+ // DELETE /repos/:id — remove a repo
139
+ router.delete("/repos/:id", async (req, res) => {
140
+ try {
141
+ const data = await readData();
142
+ const idx = data.repos.findIndex((r) => r.id === req.params.id);
143
+ if (idx === -1) return res.status(404).json({ error: "Repo not found" });
144
+
145
+ data.repos.splice(idx, 1);
146
+ await writeData(data);
147
+ res.json({ ok: true });
148
+ } catch (err) {
149
+ res.status(500).json({ error: err.message });
150
+ }
151
+ });
152
+
153
+ // POST /groups — create a group
154
+ router.post("/groups", async (req, res) => {
155
+ try {
156
+ const { name, parentId } = req.body;
157
+ if (!name) return res.status(400).json({ error: "name is required" });
158
+
159
+ const data = await readData();
160
+
161
+ if (parentId && !data.groups.some((g) => g.id === parentId)) {
162
+ return res.status(400).json({ error: "Invalid parentId" });
163
+ }
164
+
165
+ const group = {
166
+ id: `g_${Date.now()}`,
167
+ name,
168
+ parentId: parentId || null,
169
+ };
170
+
171
+ data.groups.push(group);
172
+ await writeData(data);
173
+ res.json({ ok: true, group });
174
+ } catch (err) {
175
+ res.status(500).json({ error: err.message });
176
+ }
177
+ });
178
+
179
+ // PUT /groups/:id — rename/reparent a group
180
+ router.put("/groups/:id", async (req, res) => {
181
+ try {
182
+ const data = await readData();
183
+ const group = data.groups.find((g) => g.id === req.params.id);
184
+ if (!group) return res.status(404).json({ error: "Group not found" });
185
+
186
+ const { name, parentId } = req.body;
187
+ if (name !== undefined) group.name = name;
188
+ if (parentId !== undefined) {
189
+ if (parentId !== null && !data.groups.some((g) => g.id === parentId)) {
190
+ return res.status(400).json({ error: "Invalid parentId" });
191
+ }
192
+ if (hasCircularParent(data.groups, group.id, parentId)) {
193
+ return res.status(400).json({ error: "Circular parent reference" });
194
+ }
195
+ group.parentId = parentId;
196
+ }
197
+
198
+ await writeData(data);
199
+ res.json({ ok: true, group });
200
+ } catch (err) {
201
+ res.status(500).json({ error: err.message });
202
+ }
203
+ });
204
+
205
+ // DELETE /groups/:id — delete group (reparent children + repos)
206
+ router.delete("/groups/:id", async (req, res) => {
207
+ try {
208
+ const data = await readData();
209
+ const group = data.groups.find((g) => g.id === req.params.id);
210
+ if (!group) return res.status(404).json({ error: "Group not found" });
211
+
212
+ const parentId = group.parentId || null;
213
+
214
+ // Reparent child groups to deleted group's parent
215
+ for (const g of data.groups) {
216
+ if (g.parentId === group.id) g.parentId = parentId;
217
+ }
218
+
219
+ // Reparent repos to deleted group's parent
220
+ for (const r of data.repos) {
221
+ if (r.groupId === group.id) r.groupId = parentId;
222
+ }
223
+
224
+ data.groups = data.groups.filter((g) => g.id !== group.id);
225
+ await writeData(data);
226
+ res.json({ ok: true });
227
+ } catch (err) {
228
+ res.status(500).json({ error: err.message });
229
+ }
230
+ });
231
+
232
+ export default router;
@@ -0,0 +1,196 @@
1
+ /* Sudoku — Tab SDK plugin styles */
2
+
3
+ .sudoku-tab {
4
+ font-family: var(--font-mono);
5
+ color: var(--text);
6
+ padding: 12px;
7
+ gap: 12px;
8
+ align-items: center;
9
+ outline: none;
10
+ }
11
+
12
+ /* ── Header ── */
13
+ .sudoku-header {
14
+ display: flex;
15
+ justify-content: space-between;
16
+ align-items: center;
17
+ width: 100%;
18
+ max-width: 320px;
19
+ gap: 8px;
20
+ }
21
+
22
+ .sudoku-controls {
23
+ display: flex;
24
+ gap: 4px;
25
+ }
26
+
27
+ .sudoku-diff-btn {
28
+ background: var(--bg-tertiary);
29
+ color: var(--text-secondary);
30
+ border: 1px solid var(--border);
31
+ border-radius: var(--radius);
32
+ padding: 3px 8px;
33
+ font-size: 11px;
34
+ font-family: var(--font-mono);
35
+ cursor: pointer;
36
+ transition: all 0.15s;
37
+ }
38
+
39
+ .sudoku-diff-btn:hover {
40
+ background: var(--bg-secondary);
41
+ color: var(--text);
42
+ }
43
+
44
+ .sudoku-diff-btn.active {
45
+ background: var(--accent);
46
+ color: var(--bg);
47
+ border-color: var(--accent);
48
+ }
49
+
50
+ .sudoku-info {
51
+ display: flex;
52
+ gap: 10px;
53
+ font-size: 11px;
54
+ color: var(--text-dim);
55
+ }
56
+
57
+ .sudoku-timer {
58
+ color: var(--accent);
59
+ font-weight: 600;
60
+ }
61
+
62
+ /* ── Board ── */
63
+ .sudoku-board-wrap {
64
+ display: flex;
65
+ justify-content: center;
66
+ }
67
+
68
+ .sudoku-grid {
69
+ display: grid;
70
+ grid-template-columns: repeat(9, 32px);
71
+ grid-template-rows: repeat(9, 32px);
72
+ border: 2px solid var(--text-secondary);
73
+ border-radius: var(--radius);
74
+ overflow: hidden;
75
+ }
76
+
77
+ .sudoku-cell {
78
+ display: flex;
79
+ align-items: center;
80
+ justify-content: center;
81
+ font-size: 14px;
82
+ font-weight: 500;
83
+ border: 1px solid var(--border);
84
+ cursor: pointer;
85
+ transition: background 0.1s;
86
+ user-select: none;
87
+ background: var(--bg-secondary);
88
+ color: var(--accent);
89
+ }
90
+
91
+ .sudoku-cell.fixed {
92
+ color: var(--text);
93
+ font-weight: 700;
94
+ }
95
+
96
+ .sudoku-cell.in-scope {
97
+ background: var(--bg-tertiary);
98
+ }
99
+
100
+ .sudoku-cell.highlight {
101
+ background: rgba(99, 102, 241, 0.15);
102
+ }
103
+
104
+ .sudoku-cell.selected {
105
+ background: rgba(99, 102, 241, 0.25);
106
+ outline: 2px solid var(--accent);
107
+ outline-offset: -2px;
108
+ z-index: 1;
109
+ }
110
+
111
+ .sudoku-cell.error {
112
+ color: var(--error);
113
+ background: rgba(239, 68, 68, 0.1);
114
+ }
115
+
116
+ .sudoku-cell:hover {
117
+ background: var(--bg-tertiary);
118
+ }
119
+
120
+ .sudoku-cell.selected:hover {
121
+ background: rgba(99, 102, 241, 0.25);
122
+ }
123
+
124
+ /* Box borders — thicker lines at 3x3 boundaries */
125
+ .sudoku-cell.box-left {
126
+ border-left: 2px solid var(--text-secondary);
127
+ }
128
+
129
+ .sudoku-cell.box-top {
130
+ border-top: 2px solid var(--text-secondary);
131
+ }
132
+
133
+ /* ── Number Pad ── */
134
+ .sudoku-numpad {
135
+ display: flex;
136
+ gap: 4px;
137
+ justify-content: center;
138
+ max-width: 320px;
139
+ }
140
+
141
+ .sudoku-num-btn {
142
+ width: 30px;
143
+ height: 30px;
144
+ display: flex;
145
+ align-items: center;
146
+ justify-content: center;
147
+ background: var(--bg-tertiary);
148
+ color: var(--text);
149
+ border: 1px solid var(--border);
150
+ border-radius: var(--radius);
151
+ font-size: 13px;
152
+ font-family: var(--font-mono);
153
+ font-weight: 600;
154
+ cursor: pointer;
155
+ transition: all 0.15s;
156
+ }
157
+
158
+ .sudoku-num-btn:hover {
159
+ background: var(--accent);
160
+ color: var(--bg);
161
+ border-color: var(--accent);
162
+ }
163
+
164
+ /* ── Actions ── */
165
+ .sudoku-actions {
166
+ display: flex;
167
+ gap: 6px;
168
+ justify-content: center;
169
+ }
170
+
171
+ .sudoku-action-btn {
172
+ background: var(--bg-tertiary);
173
+ color: var(--text-secondary);
174
+ border: 1px solid var(--border);
175
+ border-radius: var(--radius);
176
+ padding: 4px 10px;
177
+ font-size: 11px;
178
+ font-family: var(--font-mono);
179
+ cursor: pointer;
180
+ transition: all 0.15s;
181
+ }
182
+
183
+ .sudoku-action-btn:hover {
184
+ background: var(--bg-secondary);
185
+ color: var(--text);
186
+ border-color: var(--text-dim);
187
+ }
188
+
189
+ /* ── Message ── */
190
+ .sudoku-message {
191
+ text-align: center;
192
+ font-size: 13px;
193
+ font-weight: 600;
194
+ color: var(--success);
195
+ min-height: 20px;
196
+ }