claudedesk 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 (182) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +431 -0
  3. package/config/repos.example.json +128 -0
  4. package/config/settings.example.json +64 -0
  5. package/config/skills/code-review.md +76 -0
  6. package/config/skills/full-check.md +26 -0
  7. package/config/skills/lint-fix.md +23 -0
  8. package/dist/api/agent-routes.d.ts +2 -0
  9. package/dist/api/agent-routes.d.ts.map +1 -0
  10. package/dist/api/agent-routes.js +251 -0
  11. package/dist/api/agent-routes.js.map +1 -0
  12. package/dist/api/app-routes.d.ts +2 -0
  13. package/dist/api/app-routes.d.ts.map +1 -0
  14. package/dist/api/app-routes.js +150 -0
  15. package/dist/api/app-routes.js.map +1 -0
  16. package/dist/api/docker-routes.d.ts +2 -0
  17. package/dist/api/docker-routes.d.ts.map +1 -0
  18. package/dist/api/docker-routes.js +167 -0
  19. package/dist/api/docker-routes.js.map +1 -0
  20. package/dist/api/middleware.d.ts +6 -0
  21. package/dist/api/middleware.d.ts.map +1 -0
  22. package/dist/api/middleware.js +293 -0
  23. package/dist/api/middleware.js.map +1 -0
  24. package/dist/api/pin-auth.d.ts +65 -0
  25. package/dist/api/pin-auth.d.ts.map +1 -0
  26. package/dist/api/pin-auth.js +218 -0
  27. package/dist/api/pin-auth.js.map +1 -0
  28. package/dist/api/routes.d.ts +2 -0
  29. package/dist/api/routes.d.ts.map +1 -0
  30. package/dist/api/routes.js +473 -0
  31. package/dist/api/routes.js.map +1 -0
  32. package/dist/api/settings-routes.d.ts +2 -0
  33. package/dist/api/settings-routes.d.ts.map +1 -0
  34. package/dist/api/settings-routes.js +570 -0
  35. package/dist/api/settings-routes.js.map +1 -0
  36. package/dist/api/skill-routes.d.ts +2 -0
  37. package/dist/api/skill-routes.d.ts.map +1 -0
  38. package/dist/api/skill-routes.js +88 -0
  39. package/dist/api/skill-routes.js.map +1 -0
  40. package/dist/api/terminal-routes.d.ts +2 -0
  41. package/dist/api/terminal-routes.d.ts.map +1 -0
  42. package/dist/api/terminal-routes.js +3524 -0
  43. package/dist/api/terminal-routes.js.map +1 -0
  44. package/dist/api/tunnel-routes.d.ts +2 -0
  45. package/dist/api/tunnel-routes.d.ts.map +1 -0
  46. package/dist/api/tunnel-routes.js +196 -0
  47. package/dist/api/tunnel-routes.js.map +1 -0
  48. package/dist/api/workspace-routes.d.ts +3 -0
  49. package/dist/api/workspace-routes.d.ts.map +1 -0
  50. package/dist/api/workspace-routes.js +649 -0
  51. package/dist/api/workspace-routes.js.map +1 -0
  52. package/dist/cli.d.ts +3 -0
  53. package/dist/cli.d.ts.map +1 -0
  54. package/dist/cli.js +276 -0
  55. package/dist/cli.js.map +1 -0
  56. package/dist/client/assets/index-B4r0njGe.js +780 -0
  57. package/dist/client/assets/index-CY_9MyE0.css +1 -0
  58. package/dist/client/favicon.svg +5 -0
  59. package/dist/client/icons/icon-192.svg +5 -0
  60. package/dist/client/icons/icon-512.svg +5 -0
  61. package/dist/client/icons/logo-with-message.png +0 -0
  62. package/dist/client/icons/logo.png +0 -0
  63. package/dist/client/index.html +25 -0
  64. package/dist/client/manifest.json +62 -0
  65. package/dist/client/sw.js +243 -0
  66. package/dist/config/agent-usage.d.ts +34 -0
  67. package/dist/config/agent-usage.d.ts.map +1 -0
  68. package/dist/config/agent-usage.js +87 -0
  69. package/dist/config/agent-usage.js.map +1 -0
  70. package/dist/config/repos.d.ts +34 -0
  71. package/dist/config/repos.d.ts.map +1 -0
  72. package/dist/config/repos.js +412 -0
  73. package/dist/config/repos.js.map +1 -0
  74. package/dist/config/settings.d.ts +634 -0
  75. package/dist/config/settings.d.ts.map +1 -0
  76. package/dist/config/settings.js +459 -0
  77. package/dist/config/settings.js.map +1 -0
  78. package/dist/config/skills.d.ts +18 -0
  79. package/dist/config/skills.d.ts.map +1 -0
  80. package/dist/config/skills.js +174 -0
  81. package/dist/config/skills.js.map +1 -0
  82. package/dist/config/workspaces.d.ts +961 -0
  83. package/dist/config/workspaces.d.ts.map +1 -0
  84. package/dist/config/workspaces.js +482 -0
  85. package/dist/config/workspaces.js.map +1 -0
  86. package/dist/core/app-manager.d.ts +85 -0
  87. package/dist/core/app-manager.d.ts.map +1 -0
  88. package/dist/core/app-manager.js +447 -0
  89. package/dist/core/app-manager.js.map +1 -0
  90. package/dist/core/claude-invoker.d.ts +49 -0
  91. package/dist/core/claude-invoker.d.ts.map +1 -0
  92. package/dist/core/claude-invoker.js +583 -0
  93. package/dist/core/claude-invoker.js.map +1 -0
  94. package/dist/core/claude-session-reader.d.ts +25 -0
  95. package/dist/core/claude-session-reader.d.ts.map +1 -0
  96. package/dist/core/claude-session-reader.js +184 -0
  97. package/dist/core/claude-session-reader.js.map +1 -0
  98. package/dist/core/claude-usage-query.d.ts +78 -0
  99. package/dist/core/claude-usage-query.d.ts.map +1 -0
  100. package/dist/core/claude-usage-query.js +294 -0
  101. package/dist/core/claude-usage-query.js.map +1 -0
  102. package/dist/core/git-credential-helper.d.ts +57 -0
  103. package/dist/core/git-credential-helper.d.ts.map +1 -0
  104. package/dist/core/git-credential-helper.js +176 -0
  105. package/dist/core/git-credential-helper.js.map +1 -0
  106. package/dist/core/git-sandbox.d.ts +135 -0
  107. package/dist/core/git-sandbox.d.ts.map +1 -0
  108. package/dist/core/git-sandbox.js +907 -0
  109. package/dist/core/git-sandbox.js.map +1 -0
  110. package/dist/core/github-integration.d.ts +66 -0
  111. package/dist/core/github-integration.d.ts.map +1 -0
  112. package/dist/core/github-integration.js +350 -0
  113. package/dist/core/github-integration.js.map +1 -0
  114. package/dist/core/github-oauth.d.ts +88 -0
  115. package/dist/core/github-oauth.d.ts.map +1 -0
  116. package/dist/core/github-oauth.js +244 -0
  117. package/dist/core/github-oauth.js.map +1 -0
  118. package/dist/core/gitlab-integration.d.ts +66 -0
  119. package/dist/core/gitlab-integration.d.ts.map +1 -0
  120. package/dist/core/gitlab-integration.js +353 -0
  121. package/dist/core/gitlab-integration.js.map +1 -0
  122. package/dist/core/gitlab-oauth.d.ts +100 -0
  123. package/dist/core/gitlab-oauth.d.ts.map +1 -0
  124. package/dist/core/gitlab-oauth.js +366 -0
  125. package/dist/core/gitlab-oauth.js.map +1 -0
  126. package/dist/core/insights-extractor.d.ts +68 -0
  127. package/dist/core/insights-extractor.d.ts.map +1 -0
  128. package/dist/core/insights-extractor.js +402 -0
  129. package/dist/core/insights-extractor.js.map +1 -0
  130. package/dist/core/logger.d.ts +27 -0
  131. package/dist/core/logger.d.ts.map +1 -0
  132. package/dist/core/logger.js +70 -0
  133. package/dist/core/logger.js.map +1 -0
  134. package/dist/core/process-runner.d.ts +27 -0
  135. package/dist/core/process-runner.d.ts.map +1 -0
  136. package/dist/core/process-runner.js +147 -0
  137. package/dist/core/process-runner.js.map +1 -0
  138. package/dist/core/project-detector.d.ts +30 -0
  139. package/dist/core/project-detector.d.ts.map +1 -0
  140. package/dist/core/project-detector.js +482 -0
  141. package/dist/core/project-detector.js.map +1 -0
  142. package/dist/core/qr-generator.d.ts +18 -0
  143. package/dist/core/qr-generator.d.ts.map +1 -0
  144. package/dist/core/qr-generator.js +61 -0
  145. package/dist/core/qr-generator.js.map +1 -0
  146. package/dist/core/remote-tunnel-manager.d.ts +59 -0
  147. package/dist/core/remote-tunnel-manager.d.ts.map +1 -0
  148. package/dist/core/remote-tunnel-manager.js +235 -0
  149. package/dist/core/remote-tunnel-manager.js.map +1 -0
  150. package/dist/core/shared-docker-manager.d.ts +41 -0
  151. package/dist/core/shared-docker-manager.d.ts.map +1 -0
  152. package/dist/core/shared-docker-manager.js +409 -0
  153. package/dist/core/shared-docker-manager.js.map +1 -0
  154. package/dist/core/skill-executor.d.ts +25 -0
  155. package/dist/core/skill-executor.d.ts.map +1 -0
  156. package/dist/core/skill-executor.js +171 -0
  157. package/dist/core/skill-executor.js.map +1 -0
  158. package/dist/core/terminal-session.d.ts +149 -0
  159. package/dist/core/terminal-session.d.ts.map +1 -0
  160. package/dist/core/terminal-session.js +2340 -0
  161. package/dist/core/terminal-session.js.map +1 -0
  162. package/dist/core/tunnel-manager.d.ts +35 -0
  163. package/dist/core/tunnel-manager.d.ts.map +1 -0
  164. package/dist/core/tunnel-manager.js +137 -0
  165. package/dist/core/tunnel-manager.js.map +1 -0
  166. package/dist/core/usage-manager.d.ts +57 -0
  167. package/dist/core/usage-manager.d.ts.map +1 -0
  168. package/dist/core/usage-manager.js +363 -0
  169. package/dist/core/usage-manager.js.map +1 -0
  170. package/dist/core/ws-manager.d.ts +39 -0
  171. package/dist/core/ws-manager.d.ts.map +1 -0
  172. package/dist/core/ws-manager.js +190 -0
  173. package/dist/core/ws-manager.js.map +1 -0
  174. package/dist/index.d.ts +7 -0
  175. package/dist/index.d.ts.map +1 -0
  176. package/dist/index.js +229 -0
  177. package/dist/index.js.map +1 -0
  178. package/dist/types.d.ts +868 -0
  179. package/dist/types.d.ts.map +1 -0
  180. package/dist/types.js +119 -0
  181. package/dist/types.js.map +1 -0
  182. package/package.json +96 -0
@@ -0,0 +1,459 @@
1
+ import { readFileSync, existsSync, writeFileSync, mkdirSync } from 'fs';
2
+ import { join, dirname } from 'path';
3
+ import { randomBytes } from 'crypto';
4
+ import { z } from 'zod';
5
+ const CONFIG_PATH = join(process.cwd(), 'config', 'settings.json');
6
+ /**
7
+ * SEC-04: Generate a random password for database services.
8
+ * This replaces hardcoded defaults to improve security.
9
+ */
10
+ function generateRandomPassword() {
11
+ return randomBytes(16).toString('base64url');
12
+ }
13
+ // Docker service schema
14
+ export const DockerServiceSchema = z.object({
15
+ enabled: z.boolean().default(false),
16
+ port: z.number(),
17
+ image: z.string(),
18
+ version: z.string().optional(),
19
+ username: z.string().optional(),
20
+ password: z.string().optional(),
21
+ database: z.string().optional(),
22
+ dataVolume: z.boolean().default(true),
23
+ });
24
+ // Docker settings schema
25
+ export const DockerSettingsSchema = z.object({
26
+ enabled: z.boolean().default(false),
27
+ autoStart: z.boolean().default(false),
28
+ services: z.object({
29
+ postgres: DockerServiceSchema,
30
+ redis: DockerServiceSchema,
31
+ }),
32
+ networkName: z.string().default('claudedesk-dev-network'),
33
+ });
34
+ // Settings schema
35
+ export const SettingsSchema = z.object({
36
+ // Setup wizard completed
37
+ setupCompleted: z.boolean().default(false),
38
+ // Security acknowledgment (SEC-01)
39
+ securityAcknowledged: z.boolean().default(false),
40
+ acknowledgedAt: z.string().optional(),
41
+ // General settings
42
+ general: z.object({
43
+ theme: z.enum(['light', 'dark', 'system']).default('dark'),
44
+ defaultProofMode: z.enum(['web', 'api', 'cli']).default('web'),
45
+ logRetentionDays: z.number().min(1).max(365).default(30),
46
+ autoCleanupArtifacts: z.boolean().default(false),
47
+ }).default({}),
48
+ // Claude settings (SEC-04: Permission modes)
49
+ claude: z.object({
50
+ permissionMode: z.enum(['autonomous', 'read-only']).default('autonomous'),
51
+ }).default({}),
52
+ // Voice settings
53
+ voice: z.object({
54
+ whisperModel: z.enum(['tiny.en', 'base.en', 'small.en', 'medium.en', 'large']).default('small.en'),
55
+ enabled: z.boolean().default(true),
56
+ }).default({}),
57
+ // Notification settings
58
+ notifications: z.object({
59
+ enabled: z.boolean().default(true),
60
+ sound: z.boolean().default(true),
61
+ jobComplete: z.boolean().default(true),
62
+ jobFailed: z.boolean().default(true),
63
+ }).default({}),
64
+ // Favorites
65
+ favorites: z.object({
66
+ repos: z.array(z.string()).default([]),
67
+ recentRepos: z.array(z.string()).default([]),
68
+ }).default({}),
69
+ // Agents settings (pinned agents and auto-detection)
70
+ agents: z.object({
71
+ pinnedAgentIds: z.array(z.string()).default([]),
72
+ autoDetect: z.boolean().default(true),
73
+ }).default({}),
74
+ // GitHub OAuth settings
75
+ github: z.object({
76
+ clientId: z.string().optional(),
77
+ }).default({}),
78
+ // GitLab OAuth settings
79
+ gitlab: z.object({
80
+ clientId: z.string().optional(),
81
+ }).default({}),
82
+ // Docker settings
83
+ docker: DockerSettingsSchema.default({
84
+ enabled: false,
85
+ autoStart: false,
86
+ services: {
87
+ postgres: {
88
+ enabled: false,
89
+ port: 5432,
90
+ image: 'postgres',
91
+ version: '16-alpine',
92
+ username: 'claudedesk',
93
+ password: '', // SEC-04: Generated at runtime
94
+ database: 'claudedesk_dev',
95
+ dataVolume: true,
96
+ },
97
+ redis: {
98
+ enabled: false,
99
+ port: 6379,
100
+ image: 'redis',
101
+ version: '7-alpine',
102
+ dataVolume: false,
103
+ },
104
+ },
105
+ networkName: 'claudedesk-dev-network',
106
+ }),
107
+ // Remote access tunnel settings
108
+ tunnel: z.object({
109
+ enabled: z.boolean().default(false),
110
+ autoStart: z.boolean().default(false),
111
+ authToken: z.string().optional(),
112
+ tokenCreatedAt: z.string().optional(),
113
+ lastTunnelUrl: z.string().optional(),
114
+ }).default({ enabled: false, autoStart: false }),
115
+ });
116
+ // Default settings
117
+ const DEFAULT_SETTINGS = {
118
+ setupCompleted: false,
119
+ securityAcknowledged: false,
120
+ general: {
121
+ theme: 'dark',
122
+ defaultProofMode: 'web',
123
+ logRetentionDays: 30,
124
+ autoCleanupArtifacts: false,
125
+ },
126
+ claude: {
127
+ permissionMode: 'autonomous',
128
+ },
129
+ voice: {
130
+ whisperModel: 'small.en',
131
+ enabled: true,
132
+ },
133
+ notifications: {
134
+ enabled: true,
135
+ sound: true,
136
+ jobComplete: true,
137
+ jobFailed: true,
138
+ },
139
+ favorites: {
140
+ repos: [],
141
+ recentRepos: [],
142
+ },
143
+ agents: {
144
+ pinnedAgentIds: [],
145
+ autoDetect: true,
146
+ },
147
+ github: {},
148
+ gitlab: {},
149
+ docker: {
150
+ enabled: false,
151
+ autoStart: false,
152
+ services: {
153
+ postgres: {
154
+ enabled: false,
155
+ port: 5432,
156
+ image: 'postgres',
157
+ version: '16-alpine',
158
+ username: 'claudedesk',
159
+ password: '', // SEC-04: Will be generated on first use
160
+ database: 'claudedesk_dev',
161
+ dataVolume: true,
162
+ },
163
+ redis: {
164
+ enabled: false,
165
+ port: 6379,
166
+ image: 'redis',
167
+ version: '7-alpine',
168
+ dataVolume: false,
169
+ },
170
+ },
171
+ networkName: 'claudedesk-dev-network',
172
+ },
173
+ tunnel: {
174
+ enabled: false,
175
+ autoStart: false,
176
+ },
177
+ };
178
+ export class SettingsManager {
179
+ settings;
180
+ constructor() {
181
+ this.settings = this.load();
182
+ }
183
+ load() {
184
+ if (!existsSync(CONFIG_PATH)) {
185
+ return this.createDefault();
186
+ }
187
+ try {
188
+ const content = readFileSync(CONFIG_PATH, 'utf-8');
189
+ const parsed = JSON.parse(content);
190
+ // SEC-04: Check if postgres password needs to be generated/migrated
191
+ let postgresPassword = parsed.docker?.services?.postgres?.password;
192
+ let needsSave = false;
193
+ // Generate new password if empty or using old hardcoded default
194
+ if (!postgresPassword || postgresPassword === 'claudedesk_dev') {
195
+ postgresPassword = generateRandomPassword();
196
+ needsSave = true;
197
+ console.log('[Settings] Generated new random password for PostgreSQL');
198
+ }
199
+ // Merge with defaults to handle missing fields
200
+ const settings = SettingsSchema.parse({
201
+ setupCompleted: parsed.setupCompleted ?? DEFAULT_SETTINGS.setupCompleted,
202
+ securityAcknowledged: parsed.securityAcknowledged ?? DEFAULT_SETTINGS.securityAcknowledged,
203
+ acknowledgedAt: parsed.acknowledgedAt,
204
+ general: { ...DEFAULT_SETTINGS.general, ...parsed.general },
205
+ claude: { ...DEFAULT_SETTINGS.claude, ...parsed.claude },
206
+ voice: { ...DEFAULT_SETTINGS.voice, ...parsed.voice },
207
+ notifications: { ...DEFAULT_SETTINGS.notifications, ...parsed.notifications },
208
+ favorites: { ...DEFAULT_SETTINGS.favorites, ...parsed.favorites },
209
+ agents: { ...DEFAULT_SETTINGS.agents, ...parsed.agents },
210
+ github: { ...DEFAULT_SETTINGS.github, ...parsed.github },
211
+ gitlab: { ...DEFAULT_SETTINGS.gitlab, ...parsed.gitlab },
212
+ docker: {
213
+ ...DEFAULT_SETTINGS.docker,
214
+ ...parsed.docker,
215
+ services: {
216
+ postgres: {
217
+ ...DEFAULT_SETTINGS.docker.services.postgres,
218
+ ...parsed.docker?.services?.postgres,
219
+ password: postgresPassword,
220
+ },
221
+ redis: { ...DEFAULT_SETTINGS.docker.services.redis, ...parsed.docker?.services?.redis },
222
+ },
223
+ },
224
+ tunnel: { ...DEFAULT_SETTINGS.tunnel, ...parsed.tunnel },
225
+ });
226
+ // Save if password was migrated
227
+ if (needsSave) {
228
+ const dir = dirname(CONFIG_PATH);
229
+ if (!existsSync(dir)) {
230
+ mkdirSync(dir, { recursive: true });
231
+ }
232
+ writeFileSync(CONFIG_PATH, JSON.stringify(settings, null, 2));
233
+ }
234
+ return settings;
235
+ }
236
+ catch (error) {
237
+ console.warn('Failed to load settings, using defaults:', error);
238
+ return this.createDefault();
239
+ }
240
+ }
241
+ createDefault() {
242
+ const dir = dirname(CONFIG_PATH);
243
+ if (!existsSync(dir)) {
244
+ mkdirSync(dir, { recursive: true });
245
+ }
246
+ // SEC-04: Generate random password for postgres instead of using hardcoded default
247
+ const settings = {
248
+ ...DEFAULT_SETTINGS,
249
+ docker: {
250
+ ...DEFAULT_SETTINGS.docker,
251
+ services: {
252
+ ...DEFAULT_SETTINGS.docker.services,
253
+ postgres: {
254
+ ...DEFAULT_SETTINGS.docker.services.postgres,
255
+ password: generateRandomPassword(),
256
+ },
257
+ },
258
+ },
259
+ };
260
+ writeFileSync(CONFIG_PATH, JSON.stringify(settings, null, 2));
261
+ return settings;
262
+ }
263
+ save() {
264
+ const dir = dirname(CONFIG_PATH);
265
+ if (!existsSync(dir)) {
266
+ mkdirSync(dir, { recursive: true });
267
+ }
268
+ writeFileSync(CONFIG_PATH, JSON.stringify(this.settings, null, 2));
269
+ }
270
+ get() {
271
+ return { ...this.settings };
272
+ }
273
+ getGeneral() {
274
+ return { ...this.settings.general };
275
+ }
276
+ getClaude() {
277
+ return { ...this.settings.claude };
278
+ }
279
+ getVoice() {
280
+ return { ...this.settings.voice };
281
+ }
282
+ getNotifications() {
283
+ return { ...this.settings.notifications };
284
+ }
285
+ getFavorites() {
286
+ return { ...this.settings.favorites };
287
+ }
288
+ getAgents() {
289
+ return { ...this.settings.agents };
290
+ }
291
+ getGitHub() {
292
+ return { ...this.settings.github };
293
+ }
294
+ getGitLab() {
295
+ return { ...this.settings.gitlab };
296
+ }
297
+ getDocker() {
298
+ return JSON.parse(JSON.stringify(this.settings.docker));
299
+ }
300
+ getTunnel() {
301
+ return { ...this.settings.tunnel };
302
+ }
303
+ isSetupCompleted() {
304
+ return this.settings.setupCompleted;
305
+ }
306
+ update(updates) {
307
+ if (updates.setupCompleted !== undefined) {
308
+ this.settings.setupCompleted = updates.setupCompleted;
309
+ }
310
+ if (updates.securityAcknowledged !== undefined) {
311
+ this.settings.securityAcknowledged = updates.securityAcknowledged;
312
+ }
313
+ if (updates.acknowledgedAt !== undefined) {
314
+ this.settings.acknowledgedAt = updates.acknowledgedAt;
315
+ }
316
+ if (updates.general) {
317
+ this.settings.general = { ...this.settings.general, ...updates.general };
318
+ }
319
+ if (updates.claude) {
320
+ this.settings.claude = { ...this.settings.claude, ...updates.claude };
321
+ }
322
+ if (updates.voice) {
323
+ this.settings.voice = { ...this.settings.voice, ...updates.voice };
324
+ }
325
+ if (updates.notifications) {
326
+ this.settings.notifications = { ...this.settings.notifications, ...updates.notifications };
327
+ }
328
+ if (updates.favorites) {
329
+ this.settings.favorites = { ...this.settings.favorites, ...updates.favorites };
330
+ }
331
+ if (updates.agents) {
332
+ this.settings.agents = { ...this.settings.agents, ...updates.agents };
333
+ }
334
+ if (updates.github) {
335
+ this.settings.github = { ...this.settings.github, ...updates.github };
336
+ }
337
+ if (updates.gitlab) {
338
+ this.settings.gitlab = { ...this.settings.gitlab, ...updates.gitlab };
339
+ }
340
+ if (updates.docker) {
341
+ this.settings.docker = {
342
+ ...this.settings.docker,
343
+ ...updates.docker,
344
+ services: {
345
+ postgres: { ...this.settings.docker.services.postgres, ...updates.docker.services?.postgres },
346
+ redis: { ...this.settings.docker.services.redis, ...updates.docker.services?.redis },
347
+ },
348
+ };
349
+ }
350
+ if (updates.tunnel) {
351
+ this.settings.tunnel = { ...this.settings.tunnel, ...updates.tunnel };
352
+ }
353
+ // Validate the merged settings
354
+ this.settings = SettingsSchema.parse(this.settings);
355
+ this.save();
356
+ return this.get();
357
+ }
358
+ updateGeneral(updates) {
359
+ this.settings.general = { ...this.settings.general, ...updates };
360
+ this.save();
361
+ return this.getGeneral();
362
+ }
363
+ updateClaude(updates) {
364
+ this.settings.claude = { ...this.settings.claude, ...updates };
365
+ this.save();
366
+ return this.getClaude();
367
+ }
368
+ updateVoice(updates) {
369
+ this.settings.voice = { ...this.settings.voice, ...updates };
370
+ this.save();
371
+ return this.getVoice();
372
+ }
373
+ updateNotifications(updates) {
374
+ this.settings.notifications = { ...this.settings.notifications, ...updates };
375
+ this.save();
376
+ return this.getNotifications();
377
+ }
378
+ updateGitHub(updates) {
379
+ this.settings.github = { ...this.settings.github, ...updates };
380
+ this.save();
381
+ return this.getGitHub();
382
+ }
383
+ updateGitLab(updates) {
384
+ this.settings.gitlab = { ...this.settings.gitlab, ...updates };
385
+ this.save();
386
+ return this.getGitLab();
387
+ }
388
+ updateDocker(updates) {
389
+ this.settings.docker = {
390
+ ...this.settings.docker,
391
+ ...updates,
392
+ services: {
393
+ postgres: { ...this.settings.docker.services.postgres, ...updates.services?.postgres },
394
+ redis: { ...this.settings.docker.services.redis, ...updates.services?.redis },
395
+ },
396
+ };
397
+ this.save();
398
+ return this.getDocker();
399
+ }
400
+ updateTunnel(updates) {
401
+ this.settings.tunnel = { ...this.settings.tunnel, ...updates };
402
+ this.save();
403
+ return this.getTunnel();
404
+ }
405
+ setSetupCompleted(completed) {
406
+ this.settings.setupCompleted = completed;
407
+ this.save();
408
+ }
409
+ // Favorites management
410
+ addFavoriteRepo(repoId) {
411
+ if (!this.settings.favorites.repos.includes(repoId)) {
412
+ this.settings.favorites.repos.push(repoId);
413
+ this.save();
414
+ }
415
+ }
416
+ removeFavoriteRepo(repoId) {
417
+ this.settings.favorites.repos = this.settings.favorites.repos.filter(id => id !== repoId);
418
+ this.save();
419
+ }
420
+ isFavoriteRepo(repoId) {
421
+ return this.settings.favorites.repos.includes(repoId);
422
+ }
423
+ // Agents management
424
+ updateAgents(updates) {
425
+ this.settings.agents = { ...this.settings.agents, ...updates };
426
+ this.save();
427
+ return this.getAgents();
428
+ }
429
+ togglePinnedAgent(agentId) {
430
+ const index = this.settings.agents.pinnedAgentIds.indexOf(agentId);
431
+ if (index === -1) {
432
+ this.settings.agents.pinnedAgentIds.push(agentId);
433
+ }
434
+ else {
435
+ this.settings.agents.pinnedAgentIds.splice(index, 1);
436
+ }
437
+ this.save();
438
+ }
439
+ isPinnedAgent(agentId) {
440
+ return this.settings.agents.pinnedAgentIds.includes(agentId);
441
+ }
442
+ addRecentRepo(repoId) {
443
+ // Remove if already exists (to move to front)
444
+ this.settings.favorites.recentRepos = this.settings.favorites.recentRepos.filter(id => id !== repoId);
445
+ // Add to front
446
+ this.settings.favorites.recentRepos.unshift(repoId);
447
+ // Keep only last 5
448
+ this.settings.favorites.recentRepos = this.settings.favorites.recentRepos.slice(0, 5);
449
+ this.save();
450
+ }
451
+ reset() {
452
+ this.settings = { ...DEFAULT_SETTINGS };
453
+ this.save();
454
+ return this.get();
455
+ }
456
+ }
457
+ // Singleton instance
458
+ export const settingsManager = new SettingsManager();
459
+ //# sourceMappingURL=settings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings.js","sourceRoot":"","sources":["../../src/config/settings.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import { SkillConfig } from '../types.js';
2
+ export declare class SkillRegistry {
3
+ private globalSkills;
4
+ private repoSkillsCache;
5
+ constructor();
6
+ private loadGlobalSkills;
7
+ private parseSkillFile;
8
+ loadRepoSkills(repoId: string, repoPath: string): void;
9
+ get(skillId: string, repoId?: string): SkillConfig | undefined;
10
+ getAll(repoId?: string): SkillConfig[];
11
+ getGlobal(): SkillConfig[];
12
+ getRepoSkills(repoId: string): SkillConfig[];
13
+ reload(): void;
14
+ reloadRepo(repoId: string, repoPath: string): void;
15
+ clearRepoCache(repoId: string): void;
16
+ }
17
+ export declare const skillRegistry: SkillRegistry;
18
+ //# sourceMappingURL=skills.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../src/config/skills.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAqB,MAAM,aAAa,CAAC;AAI7D,qBAAa,aAAa;IACxB,OAAO,CAAC,YAAY,CAAuC;IAC3D,OAAO,CAAC,eAAe,CAAoD;;IAM3E,OAAO,CAAC,gBAAgB;IAsBxB,OAAO,CAAC,cAAc;IA8DtB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IA2CtD,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS;IAc9D,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,WAAW,EAAE;IAsBtC,SAAS,IAAI,WAAW,EAAE;IAK1B,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,EAAE;IAM5C,MAAM,IAAI,IAAI;IAMd,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAKlD,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;CAGrC;AAED,eAAO,MAAM,aAAa,eAAsB,CAAC"}
@@ -0,0 +1,174 @@
1
+ import { readdirSync, readFileSync, existsSync } from 'fs';
2
+ import { join, basename, extname } from 'path';
3
+ import { parse as parseYaml } from 'yaml';
4
+ import { SkillConfigSchema } from '../types.js';
5
+ const GLOBAL_SKILLS_DIR = join(process.cwd(), 'config', 'skills');
6
+ export class SkillRegistry {
7
+ globalSkills = new Map();
8
+ repoSkillsCache = new Map();
9
+ constructor() {
10
+ this.loadGlobalSkills();
11
+ }
12
+ loadGlobalSkills() {
13
+ if (!existsSync(GLOBAL_SKILLS_DIR)) {
14
+ console.log('[SkillRegistry] No global skills directory found at', GLOBAL_SKILLS_DIR);
15
+ return;
16
+ }
17
+ const files = readdirSync(GLOBAL_SKILLS_DIR)
18
+ .filter(f => f.endsWith('.md'));
19
+ for (const file of files) {
20
+ const filePath = join(GLOBAL_SKILLS_DIR, file);
21
+ const skill = this.parseSkillFile(filePath);
22
+ if (skill) {
23
+ skill.source = 'global';
24
+ skill.filePath = filePath;
25
+ this.globalSkills.set(skill.id, skill);
26
+ }
27
+ }
28
+ console.log(`[SkillRegistry] Loaded ${this.globalSkills.size} global skills`);
29
+ }
30
+ parseSkillFile(filePath) {
31
+ try {
32
+ const content = readFileSync(filePath, 'utf-8');
33
+ const filename = basename(filePath, extname(filePath));
34
+ // Skip README files
35
+ if (filename.toLowerCase() === 'readme') {
36
+ return null;
37
+ }
38
+ let metadata = {};
39
+ let body = content;
40
+ // Try to extract frontmatter if present
41
+ const frontmatterMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/);
42
+ if (frontmatterMatch) {
43
+ const [, frontmatter, markdownBody] = frontmatterMatch;
44
+ metadata = parseYaml(frontmatter) || {};
45
+ body = markdownBody;
46
+ }
47
+ else {
48
+ // No frontmatter - treat entire file as prompt content
49
+ // Try to extract description from first heading or first line
50
+ const firstHeadingMatch = content.match(/^#\s+(.+)$/m);
51
+ const firstLineMatch = content.match(/^(.+)$/m);
52
+ if (firstHeadingMatch) {
53
+ metadata.description = firstHeadingMatch[1].trim();
54
+ }
55
+ else if (firstLineMatch && firstLineMatch[1].length < 200) {
56
+ metadata.description = firstLineMatch[1].trim();
57
+ }
58
+ console.log(`[SkillRegistry] No frontmatter in ${filePath}, using defaults`);
59
+ }
60
+ // Derive ID from filename - must be lowercase with hyphens only
61
+ const rawId = metadata.id || filename;
62
+ const id = rawId.toLowerCase().replace(/[^a-z0-9-]/g, '-').replace(/-+/g, '-');
63
+ // Derive name from filename (convert hyphens to spaces, title case)
64
+ const derivedName = filename
65
+ .replace(/[-_]/g, ' ')
66
+ .replace(/\b\w/g, c => c.toUpperCase());
67
+ // Store the markdown body as the prompt content
68
+ const skillData = {
69
+ id,
70
+ name: metadata.name || derivedName,
71
+ description: metadata.description || `Skill: ${derivedName}`,
72
+ type: metadata.type || 'prompt', // Default to prompt type
73
+ promptContent: body.trim(),
74
+ ...metadata,
75
+ };
76
+ return SkillConfigSchema.parse(skillData);
77
+ }
78
+ catch (error) {
79
+ console.error(`[SkillRegistry] Failed to parse skill ${filePath}:`, error);
80
+ return null;
81
+ }
82
+ }
83
+ // Load skills for a specific repository
84
+ // Checks both .claude/skills and .claudedesk/skills directories
85
+ loadRepoSkills(repoId, repoPath) {
86
+ const skillsDirs = [
87
+ join(repoPath, '.claude', 'skills'), // Claude Code convention
88
+ join(repoPath, '.claudedesk', 'skills'), // ClaudeDesk convention
89
+ ];
90
+ console.log(`[SkillRegistry] Loading repo skills for ${repoId} from path: ${repoPath}`);
91
+ const repoSkills = new Map();
92
+ for (const skillsDir of skillsDirs) {
93
+ const dirExists = existsSync(skillsDir);
94
+ console.log(`[SkillRegistry] Checking ${skillsDir} - exists: ${dirExists}`);
95
+ if (!dirExists) {
96
+ continue;
97
+ }
98
+ const files = readdirSync(skillsDir).filter(f => f.endsWith('.md'));
99
+ console.log(`[SkillRegistry] Found ${files.length} .md files in ${skillsDir}:`, files);
100
+ for (const file of files) {
101
+ const filePath = join(skillsDir, file);
102
+ const skill = this.parseSkillFile(filePath);
103
+ if (skill) {
104
+ skill.source = 'repo';
105
+ skill.filePath = filePath;
106
+ // Don't override if already loaded (first directory has priority)
107
+ if (!repoSkills.has(skill.id)) {
108
+ repoSkills.set(skill.id, skill);
109
+ console.log(`[SkillRegistry] Loaded skill: ${skill.id} from ${filePath}`);
110
+ }
111
+ }
112
+ else {
113
+ console.log(`[SkillRegistry] Failed to parse skill from ${filePath}`);
114
+ }
115
+ }
116
+ }
117
+ this.repoSkillsCache.set(repoId, repoSkills);
118
+ console.log(`[SkillRegistry] Total: Loaded ${repoSkills.size} skills for repo ${repoId}`);
119
+ }
120
+ // Get a skill by ID with precedence: repo > global
121
+ get(skillId, repoId) {
122
+ // Check repo skills first (higher precedence)
123
+ if (repoId) {
124
+ const repoSkills = this.repoSkillsCache.get(repoId);
125
+ if (repoSkills?.has(skillId)) {
126
+ return repoSkills.get(skillId);
127
+ }
128
+ }
129
+ // Fall back to global skills
130
+ return this.globalSkills.get(skillId);
131
+ }
132
+ // Get all skills available for a repository (merged)
133
+ getAll(repoId) {
134
+ const skills = new Map();
135
+ // Add global skills first
136
+ for (const [id, skill] of this.globalSkills) {
137
+ skills.set(id, skill);
138
+ }
139
+ // Override with repo skills (higher precedence)
140
+ if (repoId) {
141
+ const repoSkills = this.repoSkillsCache.get(repoId);
142
+ if (repoSkills) {
143
+ for (const [id, skill] of repoSkills) {
144
+ skills.set(id, skill);
145
+ }
146
+ }
147
+ }
148
+ return Array.from(skills.values());
149
+ }
150
+ // Get only global skills
151
+ getGlobal() {
152
+ return Array.from(this.globalSkills.values());
153
+ }
154
+ // Get only repo-specific skills
155
+ getRepoSkills(repoId) {
156
+ const repoSkills = this.repoSkillsCache.get(repoId);
157
+ return repoSkills ? Array.from(repoSkills.values()) : [];
158
+ }
159
+ // Reload all global skills
160
+ reload() {
161
+ this.globalSkills.clear();
162
+ this.loadGlobalSkills();
163
+ }
164
+ // Reload skills for a specific repo
165
+ reloadRepo(repoId, repoPath) {
166
+ this.loadRepoSkills(repoId, repoPath);
167
+ }
168
+ // Clear repo cache (useful when repo is removed)
169
+ clearRepoCache(repoId) {
170
+ this.repoSkillsCache.delete(repoId);
171
+ }
172
+ }
173
+ export const skillRegistry = new SkillRegistry();
174
+ //# sourceMappingURL=skills.js.map