@exreve/exk 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.
@@ -0,0 +1,488 @@
1
+ // ============ Core Types ============
2
+
3
+ export interface ChoiceRequest {
4
+ choiceId: string
5
+ question: string
6
+ options: Array<{ label: string; value: string }>
7
+ timeout?: number
8
+ }
9
+
10
+ export interface ChoiceResponse {
11
+ choiceId: string
12
+ selectedValue: string | null
13
+ }
14
+
15
+ export interface Schedule {
16
+ scheduleId: string
17
+ name: string
18
+ intervalMinutes: number
19
+ prompts: string[]
20
+ enabled: boolean
21
+ paused?: boolean
22
+ continuous?: boolean
23
+ lastRun?: string
24
+ nextRun?: string
25
+ runningPrompts?: string[]
26
+ }
27
+
28
+ export interface Project {
29
+ projectId: string
30
+ deviceId: string
31
+ name: string
32
+ path: string
33
+ sourcePath?: string
34
+ guidelines?: string // Per-project guidelines/prompts for Claude agent
35
+ schedules?: Schedule[]
36
+ archived?: boolean // Whether the project is archived
37
+ createdAt: string
38
+ updatedAt: string
39
+ }
40
+
41
+ export interface Session {
42
+ id: string
43
+ projectId: string
44
+ deviceId: string
45
+ createdAt: string
46
+ logFile: string
47
+ status: 'idle' | 'active' | 'processing'
48
+ model: string // AI model to use (e.g., 'glm-5', 'glm-4.7', 'glm-4.5-air')
49
+ name?: string // Optional: AI-generated session name from first prompt
50
+ }
51
+
52
+ export interface Device {
53
+ deviceId: string
54
+ name: string
55
+ ipAddress?: string
56
+ hostname?: string
57
+ email?: string
58
+ approved?: boolean
59
+ approvedAt?: string
60
+ registeredAt: string
61
+ lastSeen: string
62
+ guidelines?: string // Account-level guidelines/prompts for Claude agent
63
+ cloudflared?: {
64
+ authenticated: boolean
65
+ authenticatedAt?: string
66
+ accountId?: string
67
+ accountName?: string
68
+ apiToken?: string // API token (not exposed to frontend, only stored)
69
+ zoneId?: string
70
+ tunnelId?: string // Tunnel ID configured on device
71
+ tunnelName?: string // Tunnel name configured on device
72
+ }
73
+ containers?: {
74
+ enabled: boolean
75
+ runtime?: 'docker' | 'podman'
76
+ version?: string
77
+ activeContainers?: Array<{
78
+ containerId: string
79
+ name: string
80
+ image: string
81
+ status: 'running' | 'stopped' | 'exited' | 'paused'
82
+ ports: Array<{ host: number; container: number }>
83
+ createdAt: string
84
+ }>
85
+ }
86
+ }
87
+
88
+ export interface Script {
89
+ id: string
90
+ name: string
91
+ description: string
92
+ command: string
93
+ createdAt: string
94
+ }
95
+
96
+ export interface Enhancer {
97
+ id: string
98
+ title: string
99
+ }
100
+
101
+ export interface User {
102
+ id: string
103
+ email: string
104
+ createdAt: string
105
+ lastLoginAt?: string
106
+ settings?: {
107
+ whisperModel?: 'small' | 'turbo'
108
+ enabledModules?: string[]
109
+ moduleSettings?: Record<string, any>
110
+ }
111
+ }
112
+
113
+ export interface PromptMessage {
114
+ sequence: number
115
+ output: SessionOutput
116
+ }
117
+
118
+ export interface Prompt {
119
+ promptId: string
120
+ sessionId: string
121
+ text: string
122
+ status: 'pending' | 'running' | 'completed' | 'error' | 'cancelled'
123
+ createdAt: string
124
+ startedAt?: string
125
+ completedAt?: string
126
+ messages?: SessionOutput[] // Optional in-memory cache
127
+ }
128
+
129
+ export interface SessionOutput {
130
+ type: 'stdout' | 'stderr' | 'exit' | 'system' | 'user' | 'assistant' | 'tool_result' | 'tool_progress' | 'result' | 'auth_status' | 'progress' | 'stream_event' | 'todo_write'
131
+ data: string | object
132
+ timestamp: number
133
+ metadata?: {
134
+ messageType?: string
135
+ subtype?: string
136
+ toolName?: string
137
+ toolResult?: any
138
+ toolUseId?: string
139
+ parentToolUseId?: string | null
140
+ progress?: {
141
+ current?: number
142
+ total?: number
143
+ message?: string
144
+ }
145
+ [key: string]: any
146
+ }
147
+ }
148
+
149
+ // ============ Socket Event Data Types ============
150
+
151
+ export interface ClientInfo {
152
+ type: 'web' | 'cli'
153
+ deviceId?: string
154
+ userEmail?: string // User email for web clients
155
+ }
156
+
157
+ export interface RegisterData {
158
+ type: 'web' | 'cli'
159
+ deviceId?: string
160
+ }
161
+
162
+ export interface SessionSubscribeData {
163
+ sessionId: string
164
+ // Note: Sync is now prompt-based, not session-based
165
+ // Clients sync individual prompts via prompt:sync
166
+ }
167
+
168
+
169
+ export interface SessionPromptData {
170
+ sessionId: string
171
+ prompt: string
172
+ promptId?: string // Optional when sending from client, required when routing to device
173
+ enhancers?: string[] // Optional: list of skill/enhancer names to apply
174
+ projectPath?: string // Optional: project path when routing to device
175
+ model?: string // Optional: AI model to use for this session
176
+ enabledModules?: string[] // Optional: list of enabled module IDs (sent by backend to CLI)
177
+ moduleSettings?: Record<string, any> // Optional: per-module settings (sent by backend to CLI)
178
+ }
179
+
180
+ export interface DeviceRegisterData {
181
+ deviceId: string
182
+ name?: string
183
+ ipAddress?: string
184
+ hostname?: string
185
+ email?: string
186
+ }
187
+
188
+ export interface ScriptCreateData {
189
+ name: string
190
+ description: string
191
+ command: string
192
+ }
193
+
194
+ export interface ScriptRunData {
195
+ scriptId: string
196
+ }
197
+
198
+ export interface ProjectCreateData {
199
+ deviceId: string
200
+ name: string
201
+ path: string
202
+ sourcePath?: string
203
+ projectId?: string // Optional, backend generates if not provided
204
+ }
205
+
206
+ export interface ProjectListData {
207
+ deviceId?: string
208
+ }
209
+
210
+ export interface ProjectDeleteData {
211
+ projectId: string
212
+ }
213
+
214
+ export interface SessionCreateData {
215
+ projectId: string
216
+ model?: string // Optional: AI model to use (defaults to glm-5.1)
217
+ }
218
+
219
+ // ============ Project Configuration Types ============
220
+
221
+ export interface ProjectApp {
222
+ name: string
223
+ description?: string
224
+ type: 'http' | 'tcp' | 'udp' | 'websocket' | 'grpc' | 'other'
225
+ port?: number
226
+ protocol?: string
227
+ directory?: string // Directory where this app is located (relative to project root, empty string for root)
228
+ framework?: string // e.g., 'react', 'express', 'fastapi', 'django'
229
+ appType?: 'static-frontend' | 'backend' // Detected app type for runner selection
230
+ buildDir?: string // Build output directory for static frontends (dist/build/public)
231
+ env?: Record<string, string> // Environment variables
232
+ endpoints?: string[] // HTTP endpoints/routes (e.g., ['/api', '/api/v1', '/'])
233
+ healthCheck?: {
234
+ url?: string
235
+ command?: string
236
+ }
237
+ buildCommand?: string
238
+ startCommand: string // Required: how to start the app
239
+ stopCommand?: string // Optional: how to stop the app (defaults to killing process)
240
+ restartCommand?: string // Optional: how to restart (defaults to stop + start)
241
+ dependencies?: string[]
242
+ }
243
+
244
+ export interface ProjectConfig {
245
+ version: string
246
+ projectName: string
247
+ description?: string
248
+ apps: ProjectApp[] // Renamed from services
249
+ directories?: string[] // Multiple directories/apps in the project
250
+ metadata?: {
251
+ analyzedAt?: string
252
+ analyzedBy?: string
253
+ framework?: string
254
+ language?: string
255
+ packageManager?: string
256
+ }
257
+ }
258
+
259
+ export interface ProjectConfigData {
260
+ projectId: string
261
+ config: ProjectConfig
262
+ }
263
+
264
+ export interface ProjectConfigUpdateData {
265
+ projectId: string
266
+ config: Partial<ProjectConfig>
267
+ }
268
+
269
+ // ============ Socket Events Interface ============
270
+
271
+ export interface SocketEvents {
272
+ // Client → Server
273
+ register: (data: RegisterData) => void
274
+ 'session:subscribe': (data: SessionSubscribeData) => void
275
+ 'session:unsubscribe': (data: SessionSubscribeData) => void
276
+ 'project:create': (data: ProjectCreateData, callback: (response: { success: boolean; project?: Project; error?: string }) => void) => void
277
+ 'project:update:guidelines': (data: { projectId: string; guidelines: string }, callback: (response: { success: boolean; project?: Project; error?: string }) => void) => void
278
+ 'project:list': (data: ProjectListData & { includeArchived?: boolean }, callback: (response: { projects: Project[] }) => void) => void
279
+ 'project:delete': (data: ProjectDeleteData, callback: (response: { success: boolean; error?: string }) => void) => void
280
+ 'project:archive': (data: { projectId: string; archived: boolean }, callback: (response: { success: boolean; error?: string }) => void) => void
281
+ 'device:update:guidelines': (data: { deviceId: string; guidelines: string }, callback: (response: { success: boolean; device?: Device; error?: string }) => void) => void
282
+ 'session:create': (data: SessionCreateData, callback: (response: { success: boolean; session?: Session; error?: string }) => void) => void
283
+ 'session:update:model': (data: { sessionId: string; model: string }, callback: (response: { success: boolean; session?: Session; error?: string }) => void) => void
284
+ 'session:delete': (data: { sessionId: string }, callback: (response: { success: boolean }) => void) => void
285
+ 'session:prompt': (data: SessionPromptData, callback: (response: { success: boolean; promptId?: string; error?: string }) => void) => void
286
+ 'prompts:list': (data: { sessionId: string }, callback: (response: { prompts: Prompt[]; error?: string }) => void) => void
287
+ 'prompt:messages': (data: { promptId: string; fromTimestamp?: number }, callback: (response: { promptId: string; messages: SessionOutput[]; latestTimestamp: number; hasMore: boolean; error?: string }) => void) => void
288
+ 'prompt:sync': (data: { promptId: string; lastTimestamp?: number }, callback: (response: { promptId: string; messages: SessionOutput[]; latestTimestamp: number; hasMore: boolean; error?: string }) => void) => void
289
+ 'device:register': (data: DeviceRegisterData, callback: (response: { success: boolean; device?: Device }) => void) => void
290
+ 'sessions:list': (callback: (response: { sessions: Session[] }) => void) => void
291
+ 'devices:list': (callback: (response: { devices: Device[] }) => void) => void
292
+ 'scripts:list': (callback: (response: { scripts: Script[] }) => void) => void
293
+ 'script:create': (data: ScriptCreateData, callback: (response: { success: boolean; script?: Script }) => void) => void
294
+ 'script:run': (data: ScriptRunData, callback: (response: { success: boolean; error?: string }) => void) => void
295
+ 'app:start': (data: { projectId: string; appName: string }, callback: (response: { success: boolean; error?: string; processId?: string }) => void) => void
296
+ 'app:stop': (data: { projectId: string; appName: string }, callback: (response: { success: boolean; error?: string }) => void) => void
297
+ 'app:restart': (data: { projectId: string; appName: string }, callback: (response: { success: boolean; error?: string; processId?: string }) => void) => void
298
+ 'app:status': (data: { projectId: string; appName?: string }, callback: (response: { success: boolean; apps?: Array<{ name: string; running: boolean; processId?: string; pid?: number }>; error?: string }) => void) => void
299
+ 'app:logs': (data: { projectId: string; appName: string; follow?: boolean }, callback: (response: { success: boolean; logs?: string; error?: string }) => void) => void
300
+ 'cloudflared:check': (data: { deviceId: string }, callback: (response: { success: boolean; installed: boolean; hasCert: boolean; authenticated: boolean; tunnelId?: string; tunnelName?: string; error?: string }) => void) => void
301
+ 'cloudflared:sync': (data: { deviceId: string }, callback: (response: { success: boolean; error?: string }) => void) => void
302
+ 'cloudflared:login:start': (data: { deviceId: string }, callback: (response: { success: boolean; loginUrl?: string; alreadyLoggedIn?: boolean; certPath?: string; error?: string }) => void) => void
303
+ 'cloudflared:login:complete': (data: { deviceId: string }, callback: (response: { success: boolean; error?: string }) => void) => void
304
+ 'cloudflared:regenerate': (data: { deviceId: string }, callback: (response: { success: boolean; error?: string }) => void) => void
305
+ 'cloudflared:tunnels:list': (data: { deviceId: string }, callback: (response: { success: boolean; tunnels?: Array<{ id: string; name: string; created_at: string }>; error?: string }) => void) => void
306
+ 'cloudflared:routes:list': (data: { deviceId: string; tunnelId?: string }, callback: (response: { success: boolean; routes?: Array<{ id: string; name: string; type: string; content: string; zone_name: string }>; error?: string }) => void) => void
307
+ 'cloudflared:route:get': (data: { deviceId: string; tunnelId: string; routeId: string; hostname: string }, callback: (response: { success: boolean; route?: { hostname: string; port: number }; error?: string }) => void) => void
308
+ 'cloudflared:route:create': (data: { deviceId: string; tunnelId: string; hostname: string; port: number; zoneId?: string }, callback: (response: { success: boolean; error?: string }) => void) => void
309
+ 'cloudflared:route:update': (data: { deviceId: string; tunnelId: string; routeId: string; hostname: string; port: number; zoneId?: string }, callback: (response: { success: boolean; error?: string }) => void) => void
310
+ 'cloudflared:route:delete': (data: { deviceId: string; tunnelId: string; routeId: string; hostname: string; zoneId?: string }, callback: (response: { success: boolean; error?: string }) => void) => void
311
+ 'github:status': (data: { projectId: string }, callback: (response: { success: boolean; isRepo?: boolean; hasChanges?: boolean; branch?: string; remote?: string; changedFiles?: Array<{ path: string; status: string }>; changesCount?: number; error?: string }) => void) => void
312
+ 'fs:list': (data: { deviceId: string; dirPath: string }, callback: (response: { success: boolean; entries?: Array<{ name: string; path: string; isDir: boolean }>; error?: string }) => void) => void
313
+ 'fs:write': (data: { deviceId: string; filePath: string; content: string; encoding?: string }, callback: (response: { success: boolean; error?: string }) => void) => void
314
+ 'github:commit': (data: { projectId: string; message?: string }, callback: (response: { success: boolean; error?: string }) => void) => void
315
+ 'github:push': (data: { projectId: string }, callback: (response: { success: boolean; error?: string }) => void) => void
316
+ 'github:discard': (data: { projectId: string }, callback: (response: { success: boolean; error?: string }) => void) => void
317
+ 'schedule:add': (data: { projectId: string; name: string; intervalMinutes?: number; prompts: string[]; continuous?: boolean }, callback: (response: { success: boolean; schedule?: Schedule; error?: string }) => void) => void
318
+ 'schedule:update': (data: { projectId: string; scheduleId: string; name?: string; intervalMinutes?: number; prompts?: string[]; enabled?: boolean; paused?: boolean; continuous?: boolean }, callback: (response: { success: boolean; schedule?: Schedule; error?: string }) => void) => void
319
+ 'schedule:trigger': (data: { projectId: string; scheduleId: string }, callback: (response: { success: boolean; error?: string }) => void) => void
320
+ 'schedule:delete': (data: { projectId: string; scheduleId: string }, callback: (response: { success: boolean; error?: string }) => void) => void
321
+ // Container management
322
+ 'container:check': (data: { deviceId: string }, callback: (response: { success: boolean; enabled: boolean; runtime?: 'docker' | 'podman'; version?: string; error?: string }) => void) => void
323
+ 'container:list': (data: { deviceId: string }, callback: (response: { success: boolean; containers?: Array<{ containerId: string; name: string; image: string; status: string; ports: Array<{ host: number; container: number }>; createdAt: string }>; error?: string }) => void) => void
324
+ 'container:start': (data: { deviceId: string; name: string; image: string; ports?: Array<{ host: number; container: number }>; env?: Record<string, string>; runAsRoot?: boolean }, callback: (response: { success: boolean; containerId?: string; error?: string }) => void) => void
325
+ 'container:stop': (data: { deviceId: string; containerId: string }, callback: (response: { success: boolean; error?: string }) => void) => void
326
+ 'container:remove': (data: { deviceId: string; containerId: string }, callback: (response: { success: boolean; error?: string }) => void) => void
327
+ 'container:logs': (data: { deviceId: string; containerId: string; lines?: number }, callback: (response: { success: boolean; logs?: string; error?: string }) => void) => void
328
+ // Device token generation (for container auth bypass)
329
+ 'device:generate-token': (data: { deviceId: string; description?: string }, callback: (response: { success: boolean; token?: string; error?: string }) => void) => void
330
+ 'device:list-tokens': (data: { deviceId: string }, callback: (response: { success: boolean; tokens?: Array<{ token: string; createdAt: string; lastUsed?: string; description?: string }>; error?: string }) => void) => void
331
+ 'device:revoke-token': (data: { deviceId: string; token: string }, callback: (response: { success: boolean; error?: string }) => void) => void
332
+ // User settings
333
+ 'user:settings:get': (callback: (response: { success: boolean; settings?: { whisperModel?: string; userChoiceEnabled?: boolean }; error?: string }) => void) => void
334
+ // User choice feedback
335
+ 'user:choice:response': (data: { sessionId: string; choiceId: string; selectedValue: string | null }) => void
336
+ // Image generation
337
+ 'image:generate': (data: { prompt: string }, callback: (response: { success: boolean; imageUrl?: string; error?: string }) => void) => void
338
+ // Image save to client
339
+ 'image:save': (data: { images: Array<{ name: string; data: string }> }, callback: (response: { success: boolean; savedCount?: number; error?: string }) => void) => void
340
+
341
+ // Server → Client
342
+ registered: (data: { socketId: string; type: string }) => void
343
+ 'session:created': (session: Session) => void
344
+ 'session:updated': (session: Session) => void
345
+ 'session:deleted': (data: { sessionId: string }) => void
346
+ 'session:status:updated': (data: { sessionId: string; status: 'idle' | 'active' | 'processing' }) => void
347
+ 'prompt:created': (data: { promptId: string; sessionId: string; text: string; status: 'pending' | 'running' | 'completed' | 'error' | 'cancelled' }) => void
348
+ 'prompt:cancel': (data: { promptId: string; sessionId: string }, callback: (response: { success: boolean; error?: string }) => void) => void
349
+ 'prompt:updated': (data: Prompt) => void
350
+ 'session:state': (data: { sessionId: string; prompts: Prompt[]; isActive: boolean }) => void
351
+ 'prompt:sync:messages': (data: { promptId: string; messages: SessionOutput[]; latestTimestamp: number; hasMore: boolean }) => void
352
+ 'prompt:output': (data: { sessionId: string; promptId: string; type: string; data: string; timestamp: number; metadata?: any }) => void
353
+ 'session:exited': (data: { sessionId: string; exitCode: number | null }) => void
354
+ 'session:result': (data: { sessionId: string; promptId: string; exitCode: number | null }) => void
355
+ 'session:transcription': (data: { text: string }) => void
356
+ 'session:processing': (data: { status: string }) => void
357
+ 'session:prompt:received': (data: { sessionId: string; prompt: string; timestamp: number }) => void
358
+ 'session:error': (data: { error: string }) => void
359
+ 'device:registered': (device: Device) => void
360
+ 'project:created': (project: Project) => void
361
+ 'project:updated': (project: Project) => void
362
+ 'project:deleted': (data: { projectId: string }) => void
363
+ 'device:updated': (device: Device) => void
364
+ 'projects:list': (data: { projects: Project[] }) => void
365
+ 'project:config:updated': (data: { projectId: string; config: ProjectConfig }) => void
366
+ 'project:config:analyzed': (data: { projectId: string; config: ProjectConfig }) => void
367
+ 'project:config:analyze:error': (data: { projectId: string; error: string }) => void
368
+ 'script:created': (script: Script) => void
369
+ 'script:started': (data: { scriptId: string; script: Script }) => void
370
+ 'app:started': (data: { projectId: string; appName: string; processId: string; pid?: number }) => void
371
+ 'app:stopped': (data: { projectId: string; appName: string }) => void
372
+ 'app:restarted': (data: { projectId: string; appName: string; processId: string; pid?: number }) => void
373
+ 'app:status:update': (data: { projectId: string; apps: Array<{ name: string; running: boolean; processId?: string; pid?: number }> }) => void
374
+ 'app:log': (data: { projectId: string; appName: string; log: string; timestamp: number }) => void
375
+ 'cloudflared:status:updated': (data: { deviceId: string; authenticated: boolean; accountId?: string; accountName?: string }) => void
376
+ 'cloudflared:login:url': (data: { deviceId: string; loginUrl: string }) => void
377
+ 'cloudflared:login:completed': (data: { deviceId: string }) => void
378
+ 'github:status:updated': (data: { projectId: string; isRepo: boolean; hasChanges: boolean; branch?: string; remote?: string; changedFiles?: Array<{ path: string; status: string }>; changesCount?: number }) => void
379
+ 'schedule:added': (data: { projectId: string; schedule: Schedule }) => void
380
+ 'schedule:updated': (data: { projectId: string; schedule: Schedule }) => void
381
+ 'schedule:deleted': (data: { projectId: string; scheduleId: string }) => void
382
+ 'container:status:updated': (data: { deviceId: string; containers: Array<{ containerId: string; name: string; image: string; status: string; ports: Array<{ host: number; container: number }>; createdAt: string }> }) => void
383
+ 'user:choice:request': (data: { sessionId: string; choiceId: string; question: string; options: Array<{ label: string; value: string }>; timeout?: number }) => void
384
+ }
385
+
386
+ // ============ Response Types ============
387
+
388
+ export interface SuccessResponse {
389
+ success: boolean
390
+ error?: string
391
+ }
392
+
393
+ export interface SessionResponse extends SuccessResponse {
394
+ session?: Session
395
+ }
396
+
397
+ export interface DeviceResponse extends SuccessResponse {
398
+ device?: Device
399
+ }
400
+
401
+ export interface ScriptResponse extends SuccessResponse {
402
+ script?: Script
403
+ }
404
+
405
+ export interface SessionsListResponse {
406
+ sessions: Session[]
407
+ }
408
+
409
+ export interface DevicesListResponse {
410
+ devices: Device[]
411
+ }
412
+
413
+ export interface ScriptsListResponse {
414
+ scripts: Script[]
415
+ }
416
+
417
+ export interface EnhancersListResponse {
418
+ enhancers: Enhancer[]
419
+ }
420
+
421
+ // ============ Module Types ============
422
+
423
+ export type ModuleCategory = 'agent' | 'ui' | 'integration' | 'experimental'
424
+
425
+ export type ModuleSettingType = 'boolean' | 'string' | 'number' | 'select' | 'multiselect'
426
+
427
+ export interface ModuleSettingSchema {
428
+ key: string
429
+ type: ModuleSettingType
430
+ label: string
431
+ description?: string
432
+ default?: any
433
+ options?: Array<{ label: string; value: any }>
434
+ required?: boolean
435
+ }
436
+
437
+ export interface ModulePermission {
438
+ resource: string
439
+ actions: string[]
440
+ }
441
+
442
+ export interface ModuleRoute {
443
+ path: string
444
+ component: string
445
+ permissions?: string[]
446
+ }
447
+
448
+ export interface ModuleEndpoint {
449
+ method: 'get' | 'post' | 'put' | 'delete'
450
+ path: string
451
+ handler: string
452
+ }
453
+
454
+ export interface ModuleFrontendConfig {
455
+ socketEvents?: string[]
456
+ routes?: ModuleRoute[]
457
+ }
458
+
459
+ export interface ModuleBackendConfig {
460
+ socketHandlers?: Record<string, string>
461
+ endpoints?: ModuleEndpoint[]
462
+ middleware?: string[]
463
+ }
464
+
465
+ export interface ModuleState {
466
+ initial?: Record<string, any>
467
+ persistKey?: string
468
+ }
469
+
470
+ export interface Module {
471
+ id: string
472
+ name: string
473
+ description: string
474
+ icon?: string
475
+ version: string
476
+ category: ModuleCategory
477
+ enabledByDefault?: boolean // If true, module is enabled by default for new users
478
+ settingsSchema?: ModuleSettingSchema[]
479
+ permissions?: ModulePermission[]
480
+ frontend?: ModuleFrontendConfig
481
+ backend?: ModuleBackendConfig
482
+ state?: ModuleState
483
+ }
484
+
485
+ export interface ModuleRegistry {
486
+ modules: Record<string, Module>
487
+ enabledModules: string[]
488
+ }
@@ -0,0 +1,49 @@
1
+ ---
2
+ name: code-review
3
+ description: Thoroughly review code for quality, security, performance, and best practices. Use this skill when the user asks to review, audit, or analyze code.
4
+ ---
5
+
6
+ This skill guides comprehensive code reviews that identify issues, security vulnerabilities, performance problems, and violations of best practices.
7
+
8
+ ## Review Process
9
+
10
+ 1. **Understanding Context**: Identify the code's purpose, language, framework, and intended use case.
11
+
12
+ 2. **Security Analysis**: Look for:
13
+ - SQL injection, XSS, CSRF vulnerabilities
14
+ - Hardcoded secrets or API keys
15
+ - Insecure authentication/authorization
16
+ - Dependency vulnerabilities
17
+ - Input validation issues
18
+
19
+ 3. **Code Quality**: Assess:
20
+ - Code organization and structure
21
+ - Naming conventions
22
+ - Error handling
23
+ - Edge case coverage
24
+ - Code duplication
25
+
26
+ 4. **Performance**: Evaluate:
27
+ - Algorithmic complexity
28
+ - Memory usage patterns
29
+ - Database query efficiency
30
+ - Caching opportunities
31
+ - Unnecessary re-renders (frontend)
32
+
33
+ 5. **Best Practices**: Check for:
34
+ - Language/framework idioms
35
+ - Design patterns
36
+ - SOLID principles
37
+ - Testing coverage gaps
38
+ - Documentation issues
39
+
40
+ ## Output Format
41
+
42
+ Provide a structured review with:
43
+ - **Summary**: Overall assessment and priority issues
44
+ - **Critical Issues**: Security vulnerabilities or bugs that must be fixed
45
+ - **Warnings**: Potential problems or code smells
46
+ - **Suggestions**: Improvements for code quality and maintainability
47
+ - **Positive Notes**: Well-implemented aspects
48
+
49
+ Be specific with file:line references and provide code examples for fixes.
@@ -0,0 +1,36 @@
1
+ ---
2
+ name: frontend-design
3
+ description: Create distinctive, production-grade frontend interfaces with high design quality using clearglass/glassmorphism aesthetic. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
4
+ ---
5
+
6
+ This skill guides **clearglass (glassmorphism)** frontends: production-grade, distinctive, avoiding generic "AI slop." Implement real code with attention to aesthetic detail. The user provides requirements (component, page, app) and may give purpose, audience, or constraints.
7
+
8
+ ## Design Thinking
9
+
10
+ Before coding: **Purpose**—what problem, who uses it. **Tone**—iOS-inspired frosted glass, premium and refined (calm, confident, slightly iridescent); not brutalist or playful. **Constraints**—contrast and readability non-negotiable. **Differentiation**—frosted panels with a subtle rainbow shimmer on the edges; unmistakable and cohesive. Execute with precision; keep glass to nav, modals, cards (two or three per screen), not everything.
11
+
12
+ ## Clearglass Sentiment
13
+
14
+ **Core**: Frosted glass over dark space, hint of iridescence, warm gold accent. iOS control center meets dark high-end app—layers you can almost see through, soft blur, delicate borders in a spectrum (pink → orange → yellow → green → cyan → purple → pink). Dark background so glass floats; gold sparingly for primary actions and highlights. Refined, uncluttered, quietly luxurious.
15
+
16
+ - **Glass**: Secondary only (nav, modals, cards, sidebars). Strong blur and slight saturation; enough opacity for readable text. Two or three glass surfaces per screen.
17
+ - **Iridescence**: Subtle rainbow gradient on panel edges—thin shimmer, understated. Separates clearglass from generic glassmorphism.
18
+ - **Color**: Dark base; glass semi-transparent, tinted dark. White/near-white text with subtle shadow when needed. Gold only for CTAs and key highlights. Soft white/light-gray borders at low opacity.
19
+ - **Typography**: Clear, confident; system fonts, medium-to-bold. Generous size; contrast and light shadow so text stays legible on glass.
20
+ - **Motion**: Smooth, short transitions; slight scale-down on press. No flashy or drawn-out animation—personality from glass and edge.
21
+ - **Space**: Generous padding and rounding; negative space so few glass elements stand out. Asymmetry when it serves hierarchy.
22
+ - **Depth**: Layered shadows and faint inner highlight so panels feel lifted. Transparent root chrome over map/gradient/image when appropriate.
23
+
24
+ **Text vs. icon-only**: Where **text and readability matter** (labels, cards, modals, nav with words)—use full clearglass: darker, more opaque glass; iridescent edges; text shadows. Where **only an icon or compact control matters** (floating filter/location button over a map)—lighter, whitish glass; clearer border; compact round/pill; no text, so no readability trade-off. Choose per element: full clearglass for reading; lighter filter-button style for recognize-and-tap.
25
+
26
+ ## Rules
27
+
28
+ **DO**: Glass sparingly. Full clearglass where text matters; lighter glass for icon-only controls. Contrast and readability above all for text. Rainbow shimmer on content panels; gold for primary actions only. System fonts. Respect reduced motion/transparency; solid fallbacks where blur isn’t supported.
29
+
30
+ **DON’T**: Cover the screen in glass; sacrifice readability; use thin or decorative fonts; rely on color alone; ignore a11y or performance; drift to generic AI style.
31
+
32
+ **A11y & performance**: WCAG contrast; legible text on glass (shadow when needed). Honor reduced motion/transparency. Few blurred layers—a few well-placed elements are enough.
33
+
34
+ ---
35
+
36
+ **Remember**: Clearglass = frosted glass over dark, rainbow on the edges, gold for emphasis. Precision and restraint; sentiment consistent and memorable.
@@ -0,0 +1,41 @@
1
+ ---
2
+ name: frontend-design
3
+ description: Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
4
+ ---
5
+
6
+ This skill guides creation of distinctive, production-grade frontend interfaces that avoid generic "AI slop" aesthetics. Implement real working code with exceptional attention to aesthetic details and creative choices.
7
+
8
+ The user provides frontend requirements: a component, page, application, or interface to build. They may include context about the purpose, audience, or technical constraints.
9
+
10
+ ## Design Thinking
11
+
12
+ Before coding, understand the context and commit to a BOLD aesthetic direction:
13
+ - **Purpose**: What problem does this interface solve? Who uses it?
14
+ - **Tone**: Pick an extreme: brutally minimal, maximalist chaos, retro-futuristic, organic/natural, luxury/refined, playful/toy-like, editorial/magazine, brutalist/raw, art deco/geometric, soft/pastel, industrial/utilitarian, etc. There are so many flavors to choose from. Use these for inspiration but design one that is true to the aesthetic direction.
15
+ - **Constraints**: Technical requirements (framework, performance, accessibility).
16
+ - **Differentiation**: What makes this UNFORGETTABLE? What's the one thing someone will remember?
17
+
18
+ **CRITICAL**: Choose a clear conceptual direction and execute it with precision. Bold maximalism and refined minimalism both work - the key is intentionality, not intensity.
19
+
20
+ Then implement working code (HTML/CSS/JS, React, Vue, etc.) that is:
21
+ - Production-grade and functional
22
+ - Visually striking and memorable
23
+ - Cohesive with a clear aesthetic point-of-view
24
+ - Meticulously refined in every detail
25
+
26
+ ## Frontend Aesthetics Guidelines
27
+
28
+ Focus on:
29
+ - **Typography**: Choose fonts that are beautiful, unique, and interesting. Avoid generic fonts like Arial and Inter; opt instead for distinctive choices that elevate the frontend's aesthetics; unexpected, characterful font choices. Pair a distinctive display font with a refined body font.
30
+ - **Color & Theme**: Commit to a cohesive aesthetic. Use CSS variables for consistency. Dominant colors with sharp accents outperform timid, evenly-distributed palettes.
31
+ - **Motion**: Use animations for effects and micro-interactions. Prioritize CSS-only solutions for HTML. Use Motion library for React when available. Focus on high-impact moments: one well-orchestrated page load with staggered reveals (animation-delay) creates more delight than scattered micro-interactions. Use scroll-triggering and hover states that surprise.
32
+ - **Spatial Composition**: Unexpected layouts. Asymmetry. Overlap. Diagonal flow. Grid-breaking elements. Generous negative space OR controlled density.
33
+ - **Backgrounds & Visual Details**: Create atmosphere and depth rather than defaulting to solid colors. Add contextual effects and textures that match the overall aesthetic. Apply creative forms like gradient meshes, noise textures, geometric patterns, layered transparencies, dramatic shadows, decorative borders, custom cursors, and grain overlays.
34
+
35
+ NEVER use generic AI-generated aesthetics like overused font families (Inter, Roboto, Arial, system fonts), cliched color schemes (particularly purple gradients on white backgrounds), predictable layouts and component patterns, and cookie-cutter design that lacks context-specific character.
36
+
37
+ Interpret creatively and make unexpected choices that feel genuinely designed for the context. No design should be the same. Vary between light and dark themes, different fonts, different aesthetics. NEVER converge on common choices (Space Grotesk, for example) across generations.
38
+
39
+ **IMPORTANT**: Match implementation complexity to the aesthetic vision. Maximalist designs need elaborate code with extensive animations and effects. Minimalist or refined designs need restraint, precision, and careful attention to spacing, typography, and subtle details. Elegance comes from executing the vision well.
40
+
41
+ Remember: You are capable of extraordinary creative work. Don't hold back, show what can truly be created when thinking outside the box and committing fully to a distinctive vision.