@ian2018cs/agenthub 0.1.52 → 0.1.53

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ian2018cs/agenthub",
3
- "version": "0.1.52",
3
+ "version": "0.1.53",
4
4
  "description": "A web-based UI for AI Agents",
5
5
  "type": "module",
6
6
  "main": "server/index.js",
@@ -291,6 +291,29 @@ const runMigrations = () => {
291
291
  db.exec('CREATE UNIQUE INDEX IF NOT EXISTS idx_users_email ON users(email)');
292
292
  }
293
293
 
294
+ // Agent submissions table for review workflow
295
+ db.exec(`
296
+ CREATE TABLE IF NOT EXISTS agent_submissions (
297
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
298
+ user_id INTEGER NOT NULL,
299
+ agent_name TEXT NOT NULL,
300
+ display_name TEXT NOT NULL,
301
+ description TEXT,
302
+ zip_path TEXT NOT NULL,
303
+ status TEXT NOT NULL DEFAULT 'pending'
304
+ CHECK(status IN ('pending', 'approved', 'rejected')),
305
+ reject_reason TEXT,
306
+ version TEXT,
307
+ submitted_at DATETIME DEFAULT CURRENT_TIMESTAMP,
308
+ reviewed_at DATETIME,
309
+ reviewed_by INTEGER,
310
+ FOREIGN KEY (user_id) REFERENCES users(id),
311
+ FOREIGN KEY (reviewed_by) REFERENCES users(id)
312
+ )
313
+ `);
314
+ db.exec('CREATE INDEX IF NOT EXISTS idx_agent_submissions_user ON agent_submissions(user_id)');
315
+ db.exec('CREATE INDEX IF NOT EXISTS idx_agent_submissions_status ON agent_submissions(status)');
316
+
294
317
  // 聊天图片持久化关联表
295
318
  db.exec(`
296
319
  CREATE TABLE IF NOT EXISTS message_images (
@@ -1306,6 +1329,58 @@ const imageDb = {
1306
1329
  }
1307
1330
  };
1308
1331
 
1332
+ // Agent submissions database operations
1333
+ const agentSubmissionDb = {
1334
+ create: ({ userId, agentName, displayName, description, zipPath }) => {
1335
+ const result = db.prepare(`
1336
+ INSERT INTO agent_submissions (user_id, agent_name, display_name, description, zip_path)
1337
+ VALUES (?, ?, ?, ?, ?)
1338
+ `).run(userId, agentName, displayName, description || null, zipPath);
1339
+ return result.lastInsertRowid;
1340
+ },
1341
+
1342
+ listAll: (status = null) => {
1343
+ if (status) {
1344
+ return db.prepare(`
1345
+ SELECT s.*, u.username, u.email
1346
+ FROM agent_submissions s
1347
+ LEFT JOIN users u ON s.user_id = u.id
1348
+ WHERE s.status = ?
1349
+ ORDER BY s.submitted_at DESC
1350
+ `).all(status);
1351
+ }
1352
+ return db.prepare(`
1353
+ SELECT s.*, u.username, u.email
1354
+ FROM agent_submissions s
1355
+ LEFT JOIN users u ON s.user_id = u.id
1356
+ ORDER BY s.submitted_at DESC
1357
+ `).all();
1358
+ },
1359
+
1360
+ listByUser: (userId) => {
1361
+ return db.prepare(`
1362
+ SELECT * FROM agent_submissions WHERE user_id = ? ORDER BY submitted_at DESC
1363
+ `).all(userId);
1364
+ },
1365
+
1366
+ getById: (id) => {
1367
+ return db.prepare(`
1368
+ SELECT s.*, u.username, u.email
1369
+ FROM agent_submissions s
1370
+ LEFT JOIN users u ON s.user_id = u.id
1371
+ WHERE s.id = ?
1372
+ `).get(id) || null;
1373
+ },
1374
+
1375
+ updateStatus: (id, status, { version = null, rejectReason = null, reviewedBy = null } = {}) => {
1376
+ db.prepare(`
1377
+ UPDATE agent_submissions
1378
+ SET status = ?, version = ?, reject_reason = ?, reviewed_by = ?, reviewed_at = CURRENT_TIMESTAMP
1379
+ WHERE id = ?
1380
+ `).run(status, version, rejectReason, reviewedBy, id);
1381
+ }
1382
+ };
1383
+
1309
1384
  export {
1310
1385
  db,
1311
1386
  initializeDatabase,
@@ -1315,5 +1390,6 @@ export {
1315
1390
  domainWhitelistDb,
1316
1391
  settingsDb,
1317
1392
  feishuDb,
1318
- imageDb
1393
+ imageDb,
1394
+ agentSubmissionDb
1319
1395
  };
@@ -52,4 +52,26 @@ CREATE TABLE IF NOT EXISTS email_domain_whitelist (
52
52
  FOREIGN KEY (created_by) REFERENCES users(id)
53
53
  );
54
54
 
55
- CREATE INDEX IF NOT EXISTS idx_email_domain_whitelist_domain ON email_domain_whitelist(domain);
55
+ CREATE INDEX IF NOT EXISTS idx_email_domain_whitelist_domain ON email_domain_whitelist(domain);
56
+
57
+ -- Agent submissions table for review workflow
58
+ CREATE TABLE IF NOT EXISTS agent_submissions (
59
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
60
+ user_id INTEGER NOT NULL,
61
+ agent_name TEXT NOT NULL,
62
+ display_name TEXT NOT NULL,
63
+ description TEXT,
64
+ zip_path TEXT NOT NULL,
65
+ status TEXT NOT NULL DEFAULT 'pending'
66
+ CHECK(status IN ('pending', 'approved', 'rejected')),
67
+ reject_reason TEXT,
68
+ version TEXT,
69
+ submitted_at DATETIME DEFAULT CURRENT_TIMESTAMP,
70
+ reviewed_at DATETIME,
71
+ reviewed_by INTEGER,
72
+ FOREIGN KEY (user_id) REFERENCES users(id),
73
+ FOREIGN KEY (reviewed_by) REFERENCES users(id)
74
+ );
75
+
76
+ CREATE INDEX IF NOT EXISTS idx_agent_submissions_user ON agent_submissions(user_id);
77
+ CREATE INDEX IF NOT EXISTS idx_agent_submissions_status ON agent_submissions(status);
package/server/index.js CHANGED
@@ -55,6 +55,7 @@ import usageRoutes from './routes/usage.js';
55
55
  import skillsRoutes from './routes/skills.js';
56
56
  import mcpReposRoutes from './routes/mcp-repos.js';
57
57
  import settingsRoutes from './routes/settings.js';
58
+ import agentsRoutes from './routes/agents.js';
58
59
  import { initializeDatabase, userDb, imageDb } from './database/db.js';
59
60
  import { validateApiKey, authenticateToken, authenticateWebSocket } from './middleware/auth.js';
60
61
  import { getUserPaths, initCodexDirectories, initGeminiDirectories } from './services/user-directories.js';
@@ -333,6 +334,9 @@ app.use('/api/mcp-repos', authenticateToken, mcpReposRoutes);
333
334
  // Settings API Routes (protected)
334
335
  app.use('/api/settings', authenticateToken, settingsRoutes);
335
336
 
337
+ // Agents API Routes (protected)
338
+ app.use('/api/agents', authenticateToken, agentsRoutes);
339
+
336
340
  // Static files served after API routes
337
341
  // Add cache control: HTML files should not be cached, but assets can be cached
338
342
  app.use(express.static(path.join(__dirname, '../dist'), {
@@ -336,7 +336,8 @@ async function getProjects(userUuid) {
336
336
  isManuallyAdded: true,
337
337
  createdAt: projectConfig.createdAt || null,
338
338
  lastActivity: projectConfig.lastActivity || projectConfig.createdAt || null,
339
- sessions: []
339
+ sessions: [],
340
+ ...(projectConfig.agentInfo ? { agentInfo: projectConfig.agentInfo } : {})
340
341
  };
341
342
 
342
343
  projects.push(project);