@ian2018cs/agenthub 0.1.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 (136) hide show
  1. package/LICENSE +675 -0
  2. package/README.md +330 -0
  3. package/dist/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  4. package/dist/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  5. package/dist/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  6. package/dist/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  7. package/dist/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  8. package/dist/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  9. package/dist/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  10. package/dist/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  11. package/dist/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  12. package/dist/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  13. package/dist/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  14. package/dist/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  15. package/dist/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  16. package/dist/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  17. package/dist/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  18. package/dist/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  19. package/dist/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  20. package/dist/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  21. package/dist/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  22. package/dist/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  23. package/dist/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  24. package/dist/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  25. package/dist/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  26. package/dist/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  27. package/dist/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  28. package/dist/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  29. package/dist/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  30. package/dist/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  31. package/dist/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  32. package/dist/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  33. package/dist/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  34. package/dist/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  35. package/dist/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  36. package/dist/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  37. package/dist/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  38. package/dist/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  39. package/dist/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  40. package/dist/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  41. package/dist/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  42. package/dist/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  43. package/dist/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  44. package/dist/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  45. package/dist/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  46. package/dist/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  47. package/dist/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  48. package/dist/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  49. package/dist/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  50. package/dist/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  51. package/dist/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  52. package/dist/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  53. package/dist/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  54. package/dist/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  55. package/dist/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  56. package/dist/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  57. package/dist/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  58. package/dist/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  59. package/dist/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  60. package/dist/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  61. package/dist/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  62. package/dist/assets/index-B4ru3EJb.css +32 -0
  63. package/dist/assets/index-DDFuyrpY.js +154 -0
  64. package/dist/assets/vendor-codemirror-C_VWDoZS.js +39 -0
  65. package/dist/assets/vendor-icons-CJV4dnDL.js +326 -0
  66. package/dist/assets/vendor-katex-DK8hFnhL.js +261 -0
  67. package/dist/assets/vendor-markdown-VwNYkg_0.js +35 -0
  68. package/dist/assets/vendor-react-BeVl62c0.js +59 -0
  69. package/dist/assets/vendor-syntax-CdGaPJRS.js +16 -0
  70. package/dist/assets/vendor-utils-00TdZexr.js +1 -0
  71. package/dist/assets/vendor-xterm-CvdiG4-n.js +66 -0
  72. package/dist/clear-cache.html +85 -0
  73. package/dist/convert-icons.md +53 -0
  74. package/dist/favicon.png +0 -0
  75. package/dist/favicon.svg +9 -0
  76. package/dist/generate-icons.js +49 -0
  77. package/dist/icons/claude-ai-icon.svg +1 -0
  78. package/dist/icons/codex-white.svg +3 -0
  79. package/dist/icons/codex.svg +3 -0
  80. package/dist/icons/cursor-white.svg +12 -0
  81. package/dist/icons/cursor.svg +1 -0
  82. package/dist/icons/generate-icons.md +19 -0
  83. package/dist/icons/icon-128x128.png +0 -0
  84. package/dist/icons/icon-128x128.svg +12 -0
  85. package/dist/icons/icon-144x144.png +0 -0
  86. package/dist/icons/icon-144x144.svg +12 -0
  87. package/dist/icons/icon-152x152.png +0 -0
  88. package/dist/icons/icon-152x152.svg +12 -0
  89. package/dist/icons/icon-192x192.png +0 -0
  90. package/dist/icons/icon-192x192.svg +12 -0
  91. package/dist/icons/icon-384x384.png +0 -0
  92. package/dist/icons/icon-384x384.svg +12 -0
  93. package/dist/icons/icon-512x512.png +0 -0
  94. package/dist/icons/icon-512x512.svg +12 -0
  95. package/dist/icons/icon-72x72.png +0 -0
  96. package/dist/icons/icon-72x72.svg +12 -0
  97. package/dist/icons/icon-96x96.png +0 -0
  98. package/dist/icons/icon-96x96.svg +12 -0
  99. package/dist/icons/icon-template.svg +12 -0
  100. package/dist/index.html +57 -0
  101. package/dist/logo-128.png +0 -0
  102. package/dist/logo-256.png +0 -0
  103. package/dist/logo-32.png +0 -0
  104. package/dist/logo-512.png +0 -0
  105. package/dist/logo-64.png +0 -0
  106. package/dist/logo.svg +17 -0
  107. package/dist/manifest.json +61 -0
  108. package/dist/screenshots/cli-selection.png +0 -0
  109. package/dist/screenshots/desktop-main.png +0 -0
  110. package/dist/screenshots/mobile-chat.png +0 -0
  111. package/dist/screenshots/tools-modal.png +0 -0
  112. package/dist/sw.js +49 -0
  113. package/package.json +113 -0
  114. package/server/claude-sdk.js +791 -0
  115. package/server/cli.js +330 -0
  116. package/server/database/auth.db +0 -0
  117. package/server/database/db.js +523 -0
  118. package/server/database/init.sql +23 -0
  119. package/server/index.js +1678 -0
  120. package/server/load-env.js +27 -0
  121. package/server/middleware/auth.js +118 -0
  122. package/server/projects.js +899 -0
  123. package/server/routes/admin.js +89 -0
  124. package/server/routes/auth.js +144 -0
  125. package/server/routes/commands.js +570 -0
  126. package/server/routes/mcp-utils.js +37 -0
  127. package/server/routes/mcp.js +593 -0
  128. package/server/routes/projects.js +216 -0
  129. package/server/routes/skills.js +891 -0
  130. package/server/routes/usage.js +206 -0
  131. package/server/services/pricing.js +196 -0
  132. package/server/services/usage-scanner.js +283 -0
  133. package/server/services/user-directories.js +123 -0
  134. package/server/utils/commandParser.js +303 -0
  135. package/server/utils/mcp-detector.js +73 -0
  136. package/shared/modelConstants.js +23 -0
@@ -0,0 +1,89 @@
1
+ import express from 'express';
2
+ import { userDb } from '../database/db.js';
3
+ import { authenticateToken } from '../middleware/auth.js';
4
+ import { deleteUserDirectories } from '../services/user-directories.js';
5
+
6
+ const router = express.Router();
7
+
8
+ // Admin middleware
9
+ const requireAdmin = (req, res, next) => {
10
+ if (req.user.role !== 'admin') {
11
+ return res.status(403).json({ error: 'Admin access required' });
12
+ }
13
+ next();
14
+ };
15
+
16
+ // Apply auth and admin middleware to all routes
17
+ router.use(authenticateToken);
18
+ router.use(requireAdmin);
19
+
20
+ // Get all users
21
+ router.get('/users', (req, res) => {
22
+ try {
23
+ const users = userDb.getAllUsers();
24
+ res.json({ users });
25
+ } catch (error) {
26
+ console.error('Error fetching users:', error);
27
+ res.status(500).json({ error: 'Failed to fetch users' });
28
+ }
29
+ });
30
+
31
+ // Update user status
32
+ router.patch('/users/:id', (req, res) => {
33
+ try {
34
+ const { id } = req.params;
35
+ const { status } = req.body;
36
+
37
+ if (!['active', 'disabled'].includes(status)) {
38
+ return res.status(400).json({ error: 'Invalid status' });
39
+ }
40
+
41
+ // Prevent self-disable
42
+ if (parseInt(id) === req.user.id) {
43
+ return res.status(400).json({ error: 'Cannot modify your own status' });
44
+ }
45
+
46
+ const user = userDb.getUserById(id);
47
+ if (!user) {
48
+ return res.status(404).json({ error: 'User not found' });
49
+ }
50
+
51
+ userDb.updateUserStatus(id, status);
52
+ res.json({ success: true, message: `User status updated to ${status}` });
53
+ } catch (error) {
54
+ console.error('Error updating user status:', error);
55
+ res.status(500).json({ error: 'Failed to update user status' });
56
+ }
57
+ });
58
+
59
+ // Delete user
60
+ router.delete('/users/:id', async (req, res) => {
61
+ try {
62
+ const { id } = req.params;
63
+
64
+ // Prevent self-delete
65
+ if (parseInt(id) === req.user.id) {
66
+ return res.status(400).json({ error: 'Cannot delete your own account' });
67
+ }
68
+
69
+ const user = userDb.getUserById(id);
70
+ if (!user) {
71
+ return res.status(404).json({ error: 'User not found' });
72
+ }
73
+
74
+ // Delete user directories
75
+ if (user.uuid) {
76
+ await deleteUserDirectories(user.uuid);
77
+ }
78
+
79
+ // Delete from database
80
+ userDb.deleteUserById(id);
81
+
82
+ res.json({ success: true, message: 'User deleted successfully' });
83
+ } catch (error) {
84
+ console.error('Error deleting user:', error);
85
+ res.status(500).json({ error: 'Failed to delete user' });
86
+ }
87
+ });
88
+
89
+ export default router;
@@ -0,0 +1,144 @@
1
+ import express from 'express';
2
+ import bcrypt from 'bcrypt';
3
+ import { v4 as uuidv4 } from 'uuid';
4
+ import { userDb, db } from '../database/db.js';
5
+ import { generateToken, authenticateToken } from '../middleware/auth.js';
6
+ import { initUserDirectories } from '../services/user-directories.js';
7
+
8
+ const router = express.Router();
9
+
10
+ // Check auth status and setup requirements
11
+ router.get('/status', async (req, res) => {
12
+ try {
13
+ const hasUsers = await userDb.hasUsers();
14
+ res.json({
15
+ needsSetup: !hasUsers,
16
+ isAuthenticated: false // Will be overridden by frontend if token exists
17
+ });
18
+ } catch (error) {
19
+ console.error('Auth status error:', error);
20
+ res.status(500).json({ error: 'Internal server error' });
21
+ }
22
+ });
23
+
24
+ // User registration - first user becomes admin
25
+ router.post('/register', async (req, res) => {
26
+ try {
27
+ const { username, password } = req.body;
28
+
29
+ if (!username || !password) {
30
+ return res.status(400).json({ error: 'Username and password are required' });
31
+ }
32
+
33
+ if (username.length < 3 || password.length < 6) {
34
+ return res.status(400).json({
35
+ error: 'Username must be at least 3 characters, password at least 6 characters'
36
+ });
37
+ }
38
+
39
+ // Check if this is the first user (becomes admin)
40
+ const userCount = userDb.getUserCount();
41
+ const role = userCount === 0 ? 'admin' : 'user';
42
+ const uuid = uuidv4();
43
+
44
+ // Hash password
45
+ const saltRounds = 12;
46
+ const passwordHash = await bcrypt.hash(password, saltRounds);
47
+
48
+ // Create user with full details
49
+ const user = userDb.createUserFull(username, passwordHash, uuid, role);
50
+
51
+ // Initialize user directories (creates .claude.json with hasCompletedOnboarding=true)
52
+ await initUserDirectories(uuid);
53
+
54
+ // Generate token
55
+ const token = generateToken(user);
56
+
57
+ // Update last login
58
+ userDb.updateLastLogin(user.id);
59
+
60
+ res.json({
61
+ success: true,
62
+ user: {
63
+ id: user.id,
64
+ username: user.username,
65
+ uuid: user.uuid,
66
+ role: user.role
67
+ },
68
+ token
69
+ });
70
+
71
+ } catch (error) {
72
+ console.error('Registration error:', error);
73
+ if (error.code === 'SQLITE_CONSTRAINT_UNIQUE') {
74
+ res.status(409).json({ error: 'Username already exists' });
75
+ } else {
76
+ res.status(500).json({ error: 'Internal server error' });
77
+ }
78
+ }
79
+ });
80
+
81
+ // User login
82
+ router.post('/login', async (req, res) => {
83
+ try {
84
+ const { username, password } = req.body;
85
+
86
+ if (!username || !password) {
87
+ return res.status(400).json({ error: 'Username and password are required' });
88
+ }
89
+
90
+ const user = userDb.getUserByUsername(username);
91
+ if (!user) {
92
+ return res.status(401).json({ error: 'Invalid username or password' });
93
+ }
94
+
95
+ // Check if user is disabled
96
+ if (user.status === 'disabled') {
97
+ return res.status(403).json({ error: 'Account has been disabled' });
98
+ }
99
+
100
+ const isValidPassword = await bcrypt.compare(password, user.password_hash);
101
+ if (!isValidPassword) {
102
+ return res.status(401).json({ error: 'Invalid username or password' });
103
+ }
104
+
105
+ const token = generateToken(user);
106
+ userDb.updateLastLogin(user.id);
107
+
108
+ res.json({
109
+ success: true,
110
+ user: {
111
+ id: user.id,
112
+ username: user.username,
113
+ uuid: user.uuid,
114
+ role: user.role
115
+ },
116
+ token
117
+ });
118
+
119
+ } catch (error) {
120
+ console.error('Login error:', error);
121
+ res.status(500).json({ error: 'Internal server error' });
122
+ }
123
+ });
124
+
125
+ // Get current user (protected route)
126
+ router.get('/user', authenticateToken, (req, res) => {
127
+ res.json({
128
+ user: {
129
+ id: req.user.id,
130
+ username: req.user.username,
131
+ uuid: req.user.uuid,
132
+ role: req.user.role
133
+ }
134
+ });
135
+ });
136
+
137
+ // Logout (client-side token removal, but this endpoint can be used for logging)
138
+ router.post('/logout', authenticateToken, (req, res) => {
139
+ // In a simple JWT system, logout is mainly client-side
140
+ // This endpoint exists for consistency and potential future logging
141
+ res.json({ success: true, message: 'Logged out successfully' });
142
+ });
143
+
144
+ export default router;