@agentxjs/portagent 1.3.0 → 1.5.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.
@@ -5,10 +5,10 @@
5
5
  <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
7
  <title>Portagent - AgentX Portal</title>
8
- <script type="module" crossorigin src="/assets/index-BbPBfuHo.js"></script>
9
- <link rel="stylesheet" crossorigin href="/assets/index-C4JWk6jH.css">
8
+ <link rel="stylesheet" href="/assets/styles.css" />
10
9
  </head>
11
10
  <body>
12
11
  <div id="root"></div>
12
+ <script type="module" src="/assets/main-pnn8q2ty.js"></script>
13
13
  </body>
14
- </html>
14
+ </html>
@@ -1,15 +1,33 @@
1
+ import { createRequire } from "node:module";
2
+ var __create = Object.create;
3
+ var __getProtoOf = Object.getPrototypeOf;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __toESM = (mod, isNodeMode, target) => {
8
+ target = mod != null ? __create(__getProtoOf(mod)) : {};
9
+ const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
10
+ for (let key of __getOwnPropNames(mod))
11
+ if (!__hasOwnProp.call(to, key))
12
+ __defProp(to, key, {
13
+ get: () => mod[key],
14
+ enumerable: true
15
+ });
16
+ return to;
17
+ };
18
+ var __require = /* @__PURE__ */ createRequire(import.meta.url);
19
+
1
20
  // src/server/index.ts
2
- import { dirname, resolve } from "path";
3
- import { fileURLToPath } from "url";
21
+ import { resolve } from "path";
4
22
  import { createServer } from "http";
5
23
  import { Hono as Hono2 } from "hono";
6
24
  import { cors } from "hono/cors";
7
25
  import { serveStatic } from "@hono/node-server/serve-static";
8
26
  import { existsSync, readFileSync } from "fs";
9
27
  import { createAgentX } from "agentxjs";
10
- import { homedir } from "os";
11
- import { join } from "path";
12
- import { mkdirSync } from "fs";
28
+ import { homedir } from "node:os";
29
+ import { join } from "node:path";
30
+ import { mkdirSync } from "node:fs";
13
31
 
14
32
  // src/server/auth.ts
15
33
  import { Hono } from "hono";
@@ -18,10 +36,11 @@ import * as jose from "jose";
18
36
  var TOKEN_EXPIRY = "7d";
19
37
  function isValidInviteCode(code) {
20
38
  const timestamp = parseInt(code, 10);
21
- if (isNaN(timestamp)) return false;
22
- const now = /* @__PURE__ */ new Date();
39
+ if (isNaN(timestamp))
40
+ return false;
41
+ const now = new Date;
23
42
  const todayStart = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 1);
24
- const expectedTimestamp = Math.floor(todayStart.getTime() / 1e3);
43
+ const expectedTimestamp = Math.floor(todayStart.getTime() / 1000);
25
44
  return timestamp === expectedTimestamp;
26
45
  }
27
46
  async function createToken(secret, userId) {
@@ -50,7 +69,7 @@ function toUserInfo(user) {
50
69
  };
51
70
  }
52
71
  function authRoutes(userRepository, jwtSecret, agentx, config = {}) {
53
- const app = new Hono();
72
+ const app = new Hono;
54
73
  const { inviteCodeRequired = true } = config;
55
74
  app.get("/config", (c) => {
56
75
  return c.json({ inviteCodeRequired });
@@ -87,14 +106,11 @@ function authRoutes(userRepository, jwtSecret, agentx, config = {}) {
87
106
  avatar: body.avatar
88
107
  });
89
108
  const token = await createToken(jwtSecret, user.userId);
90
- return c.json(
91
- {
92
- token,
93
- user: toUserInfo(user),
94
- expiresIn: TOKEN_EXPIRY
95
- },
96
- 201
97
- );
109
+ return c.json({
110
+ token,
111
+ user: toUserInfo(user),
112
+ expiresIn: TOKEN_EXPIRY
113
+ }, 201);
98
114
  } catch (error) {
99
115
  const message = error instanceof Error ? error.message : "Registration failed";
100
116
  return c.json({ error: message }, 400);
@@ -167,21 +183,17 @@ function createAuthMiddleware(jwtSecret) {
167
183
  }
168
184
 
169
185
  // src/server/database/SQLiteUserRepository.ts
170
- import Database from "better-sqlite3";
186
+ import { Database } from "bun:sqlite";
171
187
  import { randomUUID } from "crypto";
172
- import { hash, compare } from "bcrypt";
173
- var SALT_ROUNDS = 10;
174
- var SQLiteUserRepository = class {
188
+
189
+ class SQLiteUserRepository {
175
190
  db;
176
191
  constructor(dbPath) {
177
192
  this.db = new Database(dbPath);
178
193
  this.initDatabase();
179
194
  }
180
- /**
181
- * Initialize database schema
182
- */
183
195
  initDatabase() {
184
- this.db.pragma("foreign_keys = ON");
196
+ this.db.run("PRAGMA foreign_keys = ON");
185
197
  this.db.exec(`
186
198
  CREATE TABLE IF NOT EXISTS users (
187
199
  userId TEXT PRIMARY KEY,
@@ -201,9 +213,6 @@ var SQLiteUserRepository = class {
201
213
  CREATE INDEX IF NOT EXISTS idx_users_containerId ON users(containerId);
202
214
  `);
203
215
  }
204
- /**
205
- * Create a new user
206
- */
207
216
  async createUser(input) {
208
217
  if (await this.usernameExists(input.username)) {
209
218
  throw new Error(`Username '${input.username}' already exists`);
@@ -211,7 +220,10 @@ var SQLiteUserRepository = class {
211
220
  if (input.email && await this.emailExists(input.email)) {
212
221
  throw new Error(`Email '${input.email}' already exists`);
213
222
  }
214
- const passwordHash = await hash(input.password, SALT_ROUNDS);
223
+ const passwordHash = await Bun.password.hash(input.password, {
224
+ algorithm: "bcrypt",
225
+ cost: 10
226
+ });
215
227
  const userId = randomUUID();
216
228
  const now = Date.now();
217
229
  const email = input.email || `${userId}@noemail.portagent`;
@@ -232,23 +244,9 @@ var SQLiteUserRepository = class {
232
244
  userId, username, email, passwordHash, containerId, displayName, avatar, isActive, createdAt, updatedAt
233
245
  ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
234
246
  `);
235
- stmt.run(
236
- user.userId,
237
- user.username,
238
- user.email,
239
- user.passwordHash,
240
- user.containerId,
241
- user.displayName,
242
- user.avatar,
243
- user.isActive ? 1 : 0,
244
- user.createdAt,
245
- user.updatedAt
246
- );
247
+ stmt.run(user.userId, user.username, user.email, user.passwordHash, user.containerId, user.displayName ?? null, user.avatar ?? null, user.isActive ? 1 : 0, user.createdAt, user.updatedAt);
247
248
  return user;
248
249
  }
249
- /**
250
- * Find user by ID
251
- */
252
250
  async findUserById(userId) {
253
251
  const stmt = this.db.prepare(`
254
252
  SELECT * FROM users WHERE userId = ?
@@ -256,9 +254,6 @@ var SQLiteUserRepository = class {
256
254
  const row = stmt.get(userId);
257
255
  return row ? this.rowToUser(row) : null;
258
256
  }
259
- /**
260
- * Find user by username
261
- */
262
257
  async findUserByUsername(username) {
263
258
  const stmt = this.db.prepare(`
264
259
  SELECT * FROM users WHERE username = ?
@@ -266,9 +261,6 @@ var SQLiteUserRepository = class {
266
261
  const row = stmt.get(username);
267
262
  return row ? this.rowToUser(row) : null;
268
263
  }
269
- /**
270
- * Find user by email
271
- */
272
264
  async findUserByEmail(email) {
273
265
  const stmt = this.db.prepare(`
274
266
  SELECT * FROM users WHERE email = ?
@@ -276,9 +268,6 @@ var SQLiteUserRepository = class {
276
268
  const row = stmt.get(email);
277
269
  return row ? this.rowToUser(row) : null;
278
270
  }
279
- /**
280
- * Find user by username or email
281
- */
282
271
  async findUserByUsernameOrEmail(usernameOrEmail) {
283
272
  const stmt = this.db.prepare(`
284
273
  SELECT * FROM users WHERE username = ? OR email = ?
@@ -286,9 +275,6 @@ var SQLiteUserRepository = class {
286
275
  const row = stmt.get(usernameOrEmail, usernameOrEmail);
287
276
  return row ? this.rowToUser(row) : null;
288
277
  }
289
- /**
290
- * Update user
291
- */
292
278
  async updateUser(userId, updates) {
293
279
  const user = await this.findUserById(userId);
294
280
  if (!user) {
@@ -296,27 +282,27 @@ var SQLiteUserRepository = class {
296
282
  }
297
283
  const fields = [];
298
284
  const values = [];
299
- if (updates.username !== void 0) {
285
+ if (updates.username !== undefined) {
300
286
  fields.push("username = ?");
301
287
  values.push(updates.username);
302
288
  }
303
- if (updates.email !== void 0) {
289
+ if (updates.email !== undefined) {
304
290
  fields.push("email = ?");
305
291
  values.push(updates.email);
306
292
  }
307
- if (updates.passwordHash !== void 0) {
293
+ if (updates.passwordHash !== undefined) {
308
294
  fields.push("passwordHash = ?");
309
295
  values.push(updates.passwordHash);
310
296
  }
311
- if (updates.displayName !== void 0) {
297
+ if (updates.displayName !== undefined) {
312
298
  fields.push("displayName = ?");
313
299
  values.push(updates.displayName);
314
300
  }
315
- if (updates.avatar !== void 0) {
301
+ if (updates.avatar !== undefined) {
316
302
  fields.push("avatar = ?");
317
303
  values.push(updates.avatar);
318
304
  }
319
- if (updates.isActive !== void 0) {
305
+ if (updates.isActive !== undefined) {
320
306
  fields.push("isActive = ?");
321
307
  values.push(updates.isActive ? 1 : 0);
322
308
  }
@@ -332,9 +318,6 @@ var SQLiteUserRepository = class {
332
318
  stmt.run(...values);
333
319
  return await this.findUserById(userId);
334
320
  }
335
- /**
336
- * Delete user
337
- */
338
321
  async deleteUser(userId) {
339
322
  const stmt = this.db.prepare(`
340
323
  DELETE FROM users WHERE userId = ?
@@ -342,9 +325,6 @@ var SQLiteUserRepository = class {
342
325
  const result = stmt.run(userId);
343
326
  return result.changes > 0;
344
327
  }
345
- /**
346
- * List all users
347
- */
348
328
  async listUsers() {
349
329
  const stmt = this.db.prepare(`
350
330
  SELECT * FROM users ORDER BY createdAt DESC
@@ -352,31 +332,18 @@ var SQLiteUserRepository = class {
352
332
  const rows = stmt.all();
353
333
  return rows.map((row) => this.rowToUser(row));
354
334
  }
355
- /**
356
- * Check if username exists
357
- */
358
335
  async usernameExists(username) {
359
336
  const stmt = this.db.prepare(`
360
337
  SELECT 1 FROM users WHERE username = ?
361
338
  `);
362
- return stmt.get(username) !== void 0;
339
+ return stmt.get(username) !== null;
363
340
  }
364
- /**
365
- * Check if email exists
366
- */
367
341
  async emailExists(email) {
368
342
  const stmt = this.db.prepare(`
369
343
  SELECT 1 FROM users WHERE email = ?
370
344
  `);
371
- return stmt.get(email) !== void 0;
345
+ return stmt.get(email) !== null;
372
346
  }
373
- /**
374
- * Verify password for login
375
- *
376
- * @param usernameOrEmail - Username or email
377
- * @param password - Plain text password
378
- * @returns User record if valid, null if invalid
379
- */
380
347
  async verifyPassword(usernameOrEmail, password) {
381
348
  const user = await this.findUserByUsernameOrEmail(usernameOrEmail);
382
349
  if (!user) {
@@ -385,18 +352,12 @@ var SQLiteUserRepository = class {
385
352
  if (!user.isActive) {
386
353
  return null;
387
354
  }
388
- const isValid = await compare(password, user.passwordHash);
355
+ const isValid = await Bun.password.verify(password, user.passwordHash);
389
356
  return isValid ? user : null;
390
357
  }
391
- /**
392
- * Close database connection
393
- */
394
358
  close() {
395
359
  this.db.close();
396
360
  }
397
- // ============================================================================
398
- // Private Helpers
399
- // ============================================================================
400
361
  rowToUser(row) {
401
362
  return {
402
363
  userId: row.userId,
@@ -411,12 +372,11 @@ var SQLiteUserRepository = class {
411
372
  updatedAt: row.updatedAt
412
373
  };
413
374
  }
414
- };
415
-
375
+ }
416
376
  // src/server/logger.ts
417
377
  import pino from "pino";
418
- import fs from "fs";
419
- import path from "path";
378
+ import fs from "node:fs";
379
+ import path from "node:path";
420
380
  var LEVEL_MAP = {
421
381
  debug: "debug",
422
382
  info: "info",
@@ -424,7 +384,11 @@ var LEVEL_MAP = {
424
384
  error: "error",
425
385
  silent: "silent"
426
386
  };
427
- var PinoLoggerAdapter = class {
387
+
388
+ class PinoLoggerAdapter {
389
+ name;
390
+ level;
391
+ pino;
428
392
  constructor(name, level, pino2) {
429
393
  this.name = name;
430
394
  this.level = level;
@@ -458,16 +422,17 @@ var PinoLoggerAdapter = class {
458
422
  isErrorEnabled() {
459
423
  return this.pino.isLevelEnabled("error");
460
424
  }
461
- };
462
- var PinoLoggerFactory = class {
425
+ }
426
+
427
+ class PinoLoggerFactory {
463
428
  rootLogger;
464
429
  constructor(options) {
465
- const { level, logDir, pretty = process.env.NODE_ENV !== "production" } = options;
430
+ const { level, logDir, pretty = true } = options;
466
431
  if (!fs.existsSync(logDir)) {
467
432
  fs.mkdirSync(logDir, { recursive: true });
468
433
  }
469
434
  const getLogFilePath = () => {
470
- const now = /* @__PURE__ */ new Date();
435
+ const now = new Date;
471
436
  const dateStr = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, "0")}-${String(now.getDate()).padStart(2, "0")}`;
472
437
  return path.join(logDir, `portagent-${dateStr}.log`);
473
438
  };
@@ -495,7 +460,6 @@ var PinoLoggerFactory = class {
495
460
  target: "pino/file",
496
461
  level: LEVEL_MAP[level],
497
462
  options: { destination: 1 }
498
- // stdout
499
463
  });
500
464
  }
501
465
  this.rootLogger = pino({
@@ -509,11 +473,9 @@ var PinoLoggerFactory = class {
509
473
  const childLogger = this.rootLogger.child({ name });
510
474
  return new PinoLoggerAdapter(name, this.rootLogger.level, childLogger);
511
475
  }
512
- };
476
+ }
513
477
 
514
478
  // src/server/index.ts
515
- var __filename = fileURLToPath(import.meta.url);
516
- var __dirname = dirname(__filename);
517
479
  function getDataPaths() {
518
480
  const dataDir = process.env.AGENTX_DIR || join(homedir(), ".agentx");
519
481
  const dataDirPath = join(dataDir, "data");
@@ -534,19 +496,17 @@ var JWT_SECRET = process.env.JWT_SECRET || crypto.randomUUID();
534
496
  var INVITE_CODE_REQUIRED = process.env.INVITE_CODE_REQUIRED === "true";
535
497
  async function createApp() {
536
498
  const paths = getDataPaths();
537
- const app = new Hono2();
538
- app.use(
539
- "*",
540
- cors({
541
- origin: "*",
542
- allowMethods: ["GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS"],
543
- allowHeaders: ["Content-Type", "Authorization"]
544
- })
545
- );
499
+ const app = new Hono2;
500
+ app.use("*", cors({
501
+ origin: "*",
502
+ allowMethods: ["GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS"],
503
+ allowHeaders: ["Content-Type", "Authorization"]
504
+ }));
546
505
  const apiKey = process.env.LLM_PROVIDER_KEY;
547
506
  if (!apiKey) {
548
507
  console.error("Error: LLM_PROVIDER_KEY is required");
549
- console.log("\nSet it via environment variable:");
508
+ console.log(`
509
+ Set it via environment variable:`);
550
510
  console.log(" export LLM_PROVIDER_KEY=sk-ant-xxx");
551
511
  process.exit(1);
552
512
  }
@@ -557,7 +517,7 @@ async function createApp() {
557
517
  const loggerFactory = new PinoLoggerFactory({
558
518
  level: logLevel,
559
519
  logDir: paths.logsDirPath,
560
- pretty: process.env.NODE_ENV !== "production"
520
+ pretty: true
561
521
  });
562
522
  const agentx = await createAgentX({
563
523
  llm: {
@@ -570,26 +530,24 @@ async function createApp() {
570
530
  factory: loggerFactory
571
531
  },
572
532
  agentxDir: paths.dataDir,
573
- // Auto-configures storage at {dataDir}/data/agentx.db
574
533
  server
575
- // Attach to existing HTTP server
576
534
  });
577
535
  const userRepository = new SQLiteUserRepository(paths.userDbPath);
578
536
  const authMiddleware = createAuthMiddleware(JWT_SECRET);
579
537
  app.get("/health", (c) => c.json({ status: "ok", timestamp: Date.now() }));
580
- app.route(
581
- "/api/auth",
582
- authRoutes(userRepository, JWT_SECRET, agentx, { inviteCodeRequired: INVITE_CODE_REQUIRED })
583
- );
538
+ app.route("/api/auth", authRoutes(userRepository, JWT_SECRET, agentx, { inviteCodeRequired: INVITE_CODE_REQUIRED }));
584
539
  app.use("/agentx/*", authMiddleware);
585
540
  app.get("/agentx/info", (c) => {
541
+ const isDev2 = true;
542
+ const wsUrl = isDev2 ? `ws://localhost:${PORT}/ws` : undefined;
586
543
  return c.json({
587
544
  version: "0.1.0",
588
- wsPath: "/ws"
545
+ wsPath: "/ws",
546
+ wsUrl
589
547
  });
590
548
  });
591
- const publicDir = resolve(__dirname, "../public");
592
- const isDev = process.env.NODE_ENV !== "production";
549
+ const isDev = import.meta.dir.includes("/src/");
550
+ const publicDir = isDev ? resolve(import.meta.dir, "../../dist/public") : resolve(import.meta.dir, "../public");
593
551
  if (existsSync(publicDir)) {
594
552
  app.use("/*", serveStatic({ root: publicDir }));
595
553
  app.get("*", (c) => {
@@ -602,10 +560,7 @@ async function createApp() {
602
560
  });
603
561
  } else if (isDev) {
604
562
  app.get("*", (c) => {
605
- return c.text(
606
- "Static files not found. Run 'pnpm build:client' first, or use 'pnpm dev' for development.",
607
- 404
608
- );
563
+ return c.text("Static files not found. Run 'pnpm build:client' first, or use 'pnpm dev' for development.", 404);
609
564
  });
610
565
  }
611
566
  return { app, server, agentx, userRepository, paths };
@@ -640,11 +595,12 @@ Endpoints:`);
640
595
  console.log(` WS /ws - WebSocket connection`);
641
596
  server.listen(PORT, "0.0.0.0", () => {
642
597
  console.log(`
643
- \u{1F680} Server running at http://localhost:${PORT}`);
644
- console.log(`\u{1F50C} WebSocket available at ws://localhost:${PORT}/ws`);
598
+ \uD83D\uDE80 Server running at http://localhost:${PORT}`);
599
+ console.log(`\uD83D\uDD0C WebSocket available at ws://localhost:${PORT}/ws`);
645
600
  });
646
601
  const shutdown = async () => {
647
- console.log("\nShutting down...");
602
+ console.log(`
603
+ Shutting down...`);
648
604
  await agentx.dispose();
649
605
  userRepository.close();
650
606
  server.close();
@@ -655,7 +611,8 @@ Endpoints:`);
655
611
  process.on("SIGTERM", shutdown);
656
612
  }
657
613
  export {
658
- createApp,
659
- startServer
614
+ startServer,
615
+ createApp
660
616
  };
661
- //# sourceMappingURL=index.js.map
617
+
618
+ //# debugId=189D7C9D8A79235864756E2164756E21