nstantpage-agent 0.5.10 → 0.5.12

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/dist/cli.js CHANGED
@@ -25,7 +25,7 @@ const program = new Command();
25
25
  program
26
26
  .name('nstantpage')
27
27
  .description('Local development agent for nstantpage.com — run projects on your machine, preview in the cloud')
28
- .version('0.5.9');
28
+ .version('0.5.11');
29
29
  program
30
30
  .command('login')
31
31
  .description('Authenticate with nstantpage.com')
@@ -24,7 +24,8 @@ import { getConfig, getProjectConfig, setProjectConfig, clearProjectConfig, getD
24
24
  import { TunnelClient } from '../tunnel.js';
25
25
  import { LocalServer } from '../localServer.js';
26
26
  import { PackageInstaller } from '../packageInstaller.js';
27
- const VERSION = '0.5.9';
27
+ import { probeLocalPostgres, ensureLocalProjectDb, closeAdminPool } from '../projectDb.js';
28
+ const VERSION = '0.5.12';
28
29
  /**
29
30
  * Resolve the backend API base URL.
30
31
  * - If --backend is passed, use it
@@ -274,12 +275,32 @@ export async function startCommand(directory, options) {
274
275
  if (!fs.existsSync(localConfigPath)) {
275
276
  fs.writeFileSync(localConfigPath, JSON.stringify({ projectId }, null, 2), 'utf-8');
276
277
  }
278
+ // 2.5. Auto-detect local PostgreSQL and provision project database
279
+ let databaseUrl = null;
280
+ try {
281
+ const hasPg = await probeLocalPostgres();
282
+ if (hasPg) {
283
+ databaseUrl = await ensureLocalProjectDb(projectId);
284
+ if (databaseUrl) {
285
+ console.log(chalk.green(` ✓ Database ready: project_${projectId}`));
286
+ }
287
+ }
288
+ }
289
+ catch (err) {
290
+ console.log(chalk.yellow(` ⚠ PostgreSQL setup failed: ${err.message} (will use PGlite fallback)`));
291
+ }
292
+ // Build env vars to pass to the dev server
293
+ const serverEnv = {};
294
+ if (databaseUrl) {
295
+ serverEnv['DATABASE_URL'] = databaseUrl;
296
+ }
277
297
  // 3. Start local server (API + dev server)
278
298
  const localServer = new LocalServer({
279
299
  projectDir,
280
300
  projectId,
281
301
  apiPort,
282
302
  devPort,
303
+ env: serverEnv,
283
304
  });
284
305
  // 4. Create tunnel client
285
306
  const tunnel = new TunnelClient({
@@ -373,6 +394,7 @@ export async function startCommand(directory, options) {
373
394
  tunnel.disconnect();
374
395
  await localServer.stop();
375
396
  await disconnectDevice();
397
+ await closeAdminPool();
376
398
  clearProjectConfig(projectId);
377
399
  process.exit(0);
378
400
  };
@@ -540,6 +562,7 @@ async function startStandbyMode(token, options, backendUrl, deviceId) {
540
562
  proj.tunnel.disconnect();
541
563
  await proj.localServer.stop();
542
564
  }
565
+ await closeAdminPool();
543
566
  try {
544
567
  await fetch(`${backendUrl}/api/agent/disconnect`, {
545
568
  method: 'POST',
@@ -584,9 +607,25 @@ async function startAdditionalProject(projectId, opts) {
584
607
  await new Promise(r => setTimeout(r, 50));
585
608
  // ── Phase 1: API server + file fetch + tunnel connect (all parallel) ──
586
609
  progress('fetching-files', 'Fetching project files...');
610
+ // Provision database if PostgreSQL is available
611
+ let databaseUrl = null;
612
+ try {
613
+ const hasPg = await probeLocalPostgres();
614
+ if (hasPg) {
615
+ databaseUrl = await ensureLocalProjectDb(projectId);
616
+ if (databaseUrl) {
617
+ console.log(chalk.green(` ✓ Database ready: project_${projectId}`));
618
+ }
619
+ }
620
+ }
621
+ catch { }
622
+ const serverEnv = {};
623
+ if (databaseUrl)
624
+ serverEnv['DATABASE_URL'] = databaseUrl;
587
625
  const localServer = new LocalServer({
588
626
  projectDir, projectId,
589
627
  apiPort: allocated.apiPort, devPort: allocated.devPort,
628
+ env: serverEnv,
590
629
  });
591
630
  const tunnel = new TunnelClient({
592
631
  gatewayUrl: opts.gatewayUrl,
package/dist/devServer.js CHANGED
@@ -65,6 +65,7 @@ export class DevServer {
65
65
  ...process.env,
66
66
  ...extraEnv,
67
67
  PORT: String(backendPort),
68
+ SERVER_PORT: String(backendPort),
68
69
  NODE_ENV: 'development',
69
70
  },
70
71
  shell: true,
@@ -100,7 +101,10 @@ export class DevServer {
100
101
  PORT: String(port),
101
102
  };
102
103
  if (hasBackend) {
103
- frontendEnv['VITE_BACKEND_PORT'] = String(port + 1000);
104
+ const backendPort = port + 1001;
105
+ frontendEnv['VITE_BACKEND_PORT'] = String(backendPort);
106
+ // SERVER_PORT is used by vite.config.ts proxy to route /api requests
107
+ frontendEnv['SERVER_PORT'] = String(backendPort);
104
108
  }
105
109
  console.log(` [DevServer] Starting: ${cmd} ${args.join(' ')} (port ${port})`);
106
110
  this.process = spawn(cmd, args, {
@@ -69,6 +69,12 @@ export declare class LocalServer {
69
69
  private packageInstaller;
70
70
  private lastHeartbeat;
71
71
  constructor(options: LocalServerOptions);
72
+ /**
73
+ * Ensure the project database is provisioned and DATABASE_URL is set in the DevServer env.
74
+ * Called lazily on /live/open and /live/dev to handle the case where PostgreSQL
75
+ * wasn't available during agent startup but is now (or was never probed).
76
+ */
77
+ private ensureDatabase;
72
78
  getDevServer(): DevServer;
73
79
  getApiPort(): number;
74
80
  getDevPort(): number;
@@ -22,6 +22,7 @@ import { FileManager } from './fileManager.js';
22
22
  import { Checker } from './checker.js';
23
23
  import { ErrorStore, structuredErrorToString } from './errorStore.js';
24
24
  import { PackageInstaller } from './packageInstaller.js';
25
+ import { probeLocalPostgres, ensureLocalProjectDb } from './projectDb.js';
25
26
  // ─── Try to load node-pty for real PTY support ─────────────────
26
27
  let ptyModule = null;
27
28
  try {
@@ -112,6 +113,38 @@ export class LocalServer {
112
113
  this.errorStore = new ErrorStore();
113
114
  this.packageInstaller = new PackageInstaller({ projectDir: options.projectDir });
114
115
  }
116
+ /**
117
+ * Ensure the project database is provisioned and DATABASE_URL is set in the DevServer env.
118
+ * Called lazily on /live/open and /live/dev to handle the case where PostgreSQL
119
+ * wasn't available during agent startup but is now (or was never probed).
120
+ */
121
+ async ensureDatabase() {
122
+ // Skip if DATABASE_URL is already set in the env
123
+ if (this.options.env?.['DATABASE_URL'])
124
+ return;
125
+ try {
126
+ const hasPg = await probeLocalPostgres();
127
+ if (hasPg) {
128
+ const dbUrl = await ensureLocalProjectDb(this.options.projectId);
129
+ if (dbUrl) {
130
+ // Update env for future DevServer starts
131
+ if (!this.options.env)
132
+ this.options.env = {};
133
+ this.options.env['DATABASE_URL'] = dbUrl;
134
+ // Also update the DevServer's env
135
+ this.devServer = new DevServer({
136
+ projectDir: this.options.projectDir,
137
+ port: this.options.devPort,
138
+ env: this.options.env,
139
+ });
140
+ console.log(` [LocalServer] Database provisioned: project_${this.options.projectId}`);
141
+ }
142
+ }
143
+ }
144
+ catch (err) {
145
+ console.warn(` [LocalServer] Database provisioning failed: ${err.message}`);
146
+ }
147
+ }
115
148
  getDevServer() {
116
149
  return this.devServer;
117
150
  }
@@ -349,13 +382,14 @@ export class LocalServer {
349
382
  // ─── /live/terminal ──────────────────────────────────────────
350
383
  async handleTerminal(_req, res, body) {
351
384
  const data = JSON.parse(body);
352
- const { command, cwd } = data;
385
+ const { command, cwd, timeoutSeconds } = data;
353
386
  if (!command) {
354
387
  res.statusCode = 400;
355
388
  this.json(res, { error: 'Missing command' });
356
389
  return;
357
390
  }
358
- const result = await this.devServer.exec(command);
391
+ const timeoutMs = timeoutSeconds ? timeoutSeconds * 1000 : undefined;
392
+ const result = await this.devServer.exec(command, timeoutMs);
359
393
  this.json(res, {
360
394
  success: result.exitCode === 0,
361
395
  exitCode: result.exitCode,
@@ -396,10 +430,46 @@ export class LocalServer {
396
430
  parsed = body ? JSON.parse(body) : {};
397
431
  }
398
432
  catch { }
433
+ const isAiSession = parsed.isAiSession || false;
434
+ // Reuse existing AI session if available (prevents spawning new tab per AI command)
435
+ if (isAiSession) {
436
+ const existingAiSession = Array.from(terminalSessions.values())
437
+ .find(s => s.projectId === this.options.projectId && s.isAiSession && !s.exited);
438
+ if (existingAiSession) {
439
+ existingAiSession.lastActivity = Date.now();
440
+ if (parsed.label)
441
+ existingAiSession.label = parsed.label;
442
+ // Write the new command to the existing session's PTY
443
+ if (parsed.command) {
444
+ if (existingAiSession.ptyProcess) {
445
+ existingAiSession.ptyProcess.write(parsed.command + '\n');
446
+ }
447
+ else if (existingAiSession.shell?.stdin) {
448
+ existingAiSession.shell.stdin.write(parsed.command + '\n');
449
+ }
450
+ }
451
+ this.json(res, {
452
+ success: true,
453
+ reused: true,
454
+ session: {
455
+ id: existingAiSession.id,
456
+ projectId: existingAiSession.projectId,
457
+ isAiSession: existingAiSession.isAiSession,
458
+ label: existingAiSession.label,
459
+ createdAt: existingAiSession.createdAt,
460
+ lastActivity: existingAiSession.lastActivity,
461
+ exited: false,
462
+ exitCode: null,
463
+ cols: existingAiSession.cols,
464
+ rows: existingAiSession.rows,
465
+ },
466
+ });
467
+ return;
468
+ }
469
+ }
399
470
  const sessionId = generateSessionId();
400
471
  const cols = parsed.cols || 120;
401
472
  const rows = parsed.rows || 30;
402
- const isAiSession = parsed.isAiSession || false;
403
473
  // Determine shell
404
474
  const shellCmd = process.platform === 'win32' ? 'cmd.exe' : (process.env.SHELL || '/bin/bash');
405
475
  const shellEnv = { ...process.env, TERM: 'xterm-256color', COLUMNS: String(cols), LINES: String(rows) };
@@ -426,50 +496,31 @@ export class LocalServer {
426
496
  }
427
497
  }
428
498
  if (!ptyProcess && !shell) {
499
+ // Fallback: raw spawn (no PTY, limited interactivity but works everywhere)
500
+ // NOTE: 'script' wrapper doesn't work with piped stdio (tcgetattr fails),
501
+ // so we skip it and go straight to raw shell spawn.
429
502
  try {
430
- if (process.platform === 'darwin') {
431
- // macOS fallback: use 'script' to allocate a PTY
432
- shell = spawn('script', ['-q', '/dev/null', shellCmd], {
433
- cwd: spawnCwd,
434
- env: shellEnv,
435
- stdio: ['pipe', 'pipe', 'pipe'],
436
- });
437
- }
438
- else if (process.platform === 'linux') {
439
- // Linux fallback: 'script' with -c flag
440
- shell = spawn('script', ['-qc', shellCmd, '/dev/null'], {
441
- cwd: spawnCwd,
442
- env: shellEnv,
443
- stdio: ['pipe', 'pipe', 'pipe'],
444
- });
445
- }
446
- else {
447
- // Windows / other: raw spawn (limited interactivity)
503
+ shell = spawn(shellCmd, ['-i'], {
504
+ cwd: spawnCwd,
505
+ env: shellEnv,
506
+ stdio: ['pipe', 'pipe', 'pipe'],
507
+ });
508
+ }
509
+ catch (spawnErr) {
510
+ console.warn(` [Terminal] Interactive shell failed: ${spawnErr.message} — trying non-interactive`);
511
+ try {
448
512
  shell = spawn(shellCmd, [], {
449
513
  cwd: spawnCwd,
450
514
  env: shellEnv,
451
515
  stdio: ['pipe', 'pipe', 'pipe'],
452
516
  });
453
517
  }
454
- }
455
- catch (scriptErr) {
456
- console.warn(` [Terminal] script fallback failed: ${scriptErr.message} — trying raw spawn`);
457
- }
458
- }
459
- // Last resort: raw spawn with no PTY
460
- if (!ptyProcess && !shell) {
461
- try {
462
- shell = spawn(shellCmd, [], {
463
- cwd: spawnCwd,
464
- env: shellEnv,
465
- stdio: ['pipe', 'pipe', 'pipe'],
466
- });
467
- }
468
- catch (rawErr) {
469
- console.error(` [Terminal] All spawn methods failed: ${rawErr.message}`);
470
- res.statusCode = 500;
471
- this.json(res, { success: false, error: `Failed to spawn terminal: ${rawErr.message}` });
472
- return;
518
+ catch (rawErr) {
519
+ console.error(` [Terminal] All spawn methods failed: ${rawErr.message}`);
520
+ res.statusCode = 500;
521
+ this.json(res, { success: false, error: `Failed to spawn terminal: ${rawErr.message}` });
522
+ return;
523
+ }
473
524
  }
474
525
  }
475
526
  const session = {
@@ -524,9 +575,19 @@ export class LocalServer {
524
575
  shell.on('exit', (code) => handleExit(code));
525
576
  }
526
577
  terminalSessions.set(sessionId, session);
578
+ // Write initial command to PTY if provided (AI session)
579
+ if (parsed.command) {
580
+ if (ptyProcess) {
581
+ ptyProcess.write(parsed.command + '\n');
582
+ }
583
+ else if (shell?.stdin) {
584
+ shell.stdin.write(parsed.command + '\n');
585
+ }
586
+ }
527
587
  // Return format matching frontend TerminalSessionInfo
528
588
  this.json(res, {
529
589
  success: true,
590
+ reused: false,
530
591
  session: {
531
592
  id: sessionId,
532
593
  projectId: this.options.projectId,
@@ -592,7 +653,7 @@ export class LocalServer {
592
653
  connected: true,
593
654
  projectId: this.options.projectId,
594
655
  agent: {
595
- version: '0.5.9',
656
+ version: '0.5.11',
596
657
  hostname: os.hostname(),
597
658
  platform: `${os.platform()} ${os.arch()}`,
598
659
  },
@@ -614,9 +675,10 @@ export class LocalServer {
614
675
  async handleContainerStats(_req, res) {
615
676
  const devStats = this.devServer.getStats();
616
677
  const totalMemMb = Math.round(os.totalmem() / (1024 * 1024));
617
- const freeMemMb = Math.round(os.freemem() / (1024 * 1024));
618
- const usedMemMb = totalMemMb - freeMemMb;
619
- const memPercent = totalMemMb > 0 ? Math.round((usedMemMb / totalMemMb) * 100) : 0;
678
+ // Use process-specific memory from devStats, not system-wide (os.freemem)
679
+ // os.freemem() on macOS counts filesystem cache as "used", showing ~100%
680
+ const processMemMb = Math.round(devStats.memoryMb);
681
+ const memPercent = totalMemMb > 0 ? Math.round((processMemMb / totalMemMb) * 1000) / 10 : 0;
620
682
  // Return in the same format as the container stats (ContainerStatsSnapshot)
621
683
  // so the frontend terminal panel can display it unchanged.
622
684
  this.json(res, {
@@ -624,10 +686,10 @@ export class LocalServer {
624
686
  running: this.devServer.isRunning,
625
687
  agentMode: true,
626
688
  stats: {
627
- cpuPercent: devStats.cpuPercent,
628
- memoryUsageBytes: usedMemMb * 1024 * 1024,
689
+ cpuPercent: Math.round(devStats.cpuPercent * 10) / 10,
690
+ memoryUsageBytes: processMemMb * 1024 * 1024,
629
691
  memoryLimitBytes: totalMemMb * 1024 * 1024,
630
- memoryUsageMb: usedMemMb,
692
+ memoryUsageMb: processMemMb,
631
693
  memoryLimitMb: totalMemMb,
632
694
  memoryPercent: memPercent,
633
695
  diskUsageMb: null,
@@ -659,6 +721,8 @@ export class LocalServer {
659
721
  // ─── /live/dev ───────────────────────────────────────────────
660
722
  async handleDev(_req, res, body) {
661
723
  try {
724
+ // Ensure database is provisioned before starting backend
725
+ await this.ensureDatabase();
662
726
  // Ensure dependencies are installed
663
727
  await this.packageInstaller.ensureDependencies();
664
728
  // Start dev server
@@ -694,6 +758,8 @@ export class LocalServer {
694
758
  // ─── /live/open ──────────────────────────────────────────────
695
759
  async handleOpen(_req, res) {
696
760
  try {
761
+ // Ensure database is provisioned before starting backend
762
+ await this.ensureDatabase();
697
763
  // Ensure deps are installed
698
764
  await this.packageInstaller.ensureDependencies();
699
765
  // Start dev server if not running
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Local PostgreSQL database provisioning for the nstantpage agent.
3
+ *
4
+ * Mirrors the PreviewGateway's projectDb.ts but for local (non-Docker) environments.
5
+ * On macOS, this detects Homebrew PostgreSQL (or any PG on localhost:5432).
6
+ * Each project gets an isolated database: project_{id}
7
+ *
8
+ * Usage:
9
+ * const url = await ensureLocalProjectDb('131');
10
+ * // → "postgresql://username:@127.0.0.1:5432/project_131"
11
+ */
12
+ /**
13
+ * Probe for a local PostgreSQL instance.
14
+ * Returns true if PG is accessible on localhost.
15
+ */
16
+ export declare function probeLocalPostgres(): Promise<boolean>;
17
+ /**
18
+ * Check if local PostgreSQL is available (must call probeLocalPostgres first).
19
+ */
20
+ export declare function isLocalPgAvailable(): boolean;
21
+ /**
22
+ * Ensure a project database exists and return its DATABASE_URL.
23
+ * Idempotent — safe to call multiple times.
24
+ * Returns null if PostgreSQL is not available.
25
+ */
26
+ export declare function ensureLocalProjectDb(projectId: string): Promise<string | null>;
27
+ /**
28
+ * Close the admin pool (for graceful shutdown).
29
+ */
30
+ export declare function closeAdminPool(): Promise<void>;
@@ -0,0 +1,132 @@
1
+ /**
2
+ * Local PostgreSQL database provisioning for the nstantpage agent.
3
+ *
4
+ * Mirrors the PreviewGateway's projectDb.ts but for local (non-Docker) environments.
5
+ * On macOS, this detects Homebrew PostgreSQL (or any PG on localhost:5432).
6
+ * Each project gets an isolated database: project_{id}
7
+ *
8
+ * Usage:
9
+ * const url = await ensureLocalProjectDb('131');
10
+ * // → "postgresql://username:@127.0.0.1:5432/project_131"
11
+ */
12
+ import os from 'os';
13
+ // Connection config — detect environment
14
+ const PG_HOST = process.env.PG_HOST || '127.0.0.1';
15
+ const PG_PORT = process.env.PG_PORT || '5432';
16
+ // Local macOS (Homebrew PG): current OS username, no password, trust auth
17
+ const PG_USER = process.env.PG_USER || os.userInfo().username;
18
+ const PG_PASS = process.env.PG_PASS || '';
19
+ let pgAvailable = null; // null = not yet probed
20
+ let adminPool = null;
21
+ const verifiedDbs = new Set();
22
+ /**
23
+ * Get or create the admin connection pool (connects to 'postgres' database).
24
+ */
25
+ async function getAdminPool() {
26
+ if (!adminPool) {
27
+ const pg = await import('pg');
28
+ adminPool = new pg.default.Pool({
29
+ host: PG_HOST,
30
+ port: parseInt(PG_PORT),
31
+ user: PG_USER,
32
+ password: PG_PASS,
33
+ database: 'postgres',
34
+ max: 2,
35
+ idleTimeoutMillis: 30000,
36
+ connectionTimeoutMillis: 5000,
37
+ });
38
+ }
39
+ return adminPool;
40
+ }
41
+ /**
42
+ * Probe for a local PostgreSQL instance.
43
+ * Returns true if PG is accessible on localhost.
44
+ */
45
+ export async function probeLocalPostgres() {
46
+ if (pgAvailable !== null)
47
+ return pgAvailable;
48
+ try {
49
+ const pool = await getAdminPool();
50
+ const client = await pool.connect();
51
+ await client.query('SELECT 1');
52
+ client.release();
53
+ pgAvailable = true;
54
+ console.log(` [ProjectDb] Auto-detected PostgreSQL at ${PG_HOST}:${PG_PORT} (user: ${PG_USER})`);
55
+ return true;
56
+ }
57
+ catch (err) {
58
+ pgAvailable = false;
59
+ // Reset admin pool so it doesn't hold broken connections
60
+ if (adminPool) {
61
+ adminPool.end().catch(() => { });
62
+ adminPool = null;
63
+ }
64
+ console.log(` [ProjectDb] No PostgreSQL found at ${PG_HOST}:${PG_PORT} — projects will use PGlite fallback (${err.message})`);
65
+ return false;
66
+ }
67
+ }
68
+ /**
69
+ * Check if local PostgreSQL is available (must call probeLocalPostgres first).
70
+ */
71
+ export function isLocalPgAvailable() {
72
+ return pgAvailable === true;
73
+ }
74
+ /**
75
+ * Sanitize project ID to safe database name.
76
+ */
77
+ function dbName(projectId) {
78
+ const sanitized = projectId.replace(/[^a-zA-Z0-9_]/g, '_');
79
+ return `project_${sanitized}`;
80
+ }
81
+ /**
82
+ * Build a DATABASE_URL for a project.
83
+ */
84
+ function buildDatabaseUrl(name) {
85
+ const passStr = PG_PASS ? `:${PG_PASS}` : '';
86
+ return `postgresql://${PG_USER}${passStr}@${PG_HOST}:${PG_PORT}/${name}`;
87
+ }
88
+ /**
89
+ * Ensure a project database exists and return its DATABASE_URL.
90
+ * Idempotent — safe to call multiple times.
91
+ * Returns null if PostgreSQL is not available.
92
+ */
93
+ export async function ensureLocalProjectDb(projectId) {
94
+ if (!pgAvailable)
95
+ return null;
96
+ const name = dbName(projectId);
97
+ // Fast path: already verified this session
98
+ if (verifiedDbs.has(name)) {
99
+ return buildDatabaseUrl(name);
100
+ }
101
+ try {
102
+ const pool = await getAdminPool();
103
+ // Check if database exists
104
+ const { rows } = await pool.query('SELECT 1 FROM pg_database WHERE datname = $1', [name]);
105
+ if (rows.length === 0) {
106
+ // Create database — CREATE DATABASE can't use parameterized queries
107
+ await pool.query(`CREATE DATABASE ${name}`);
108
+ console.log(` [ProjectDb] Created database '${name}' for project ${projectId}`);
109
+ }
110
+ verifiedDbs.add(name);
111
+ return buildDatabaseUrl(name);
112
+ }
113
+ catch (err) {
114
+ // Handle race condition: duplicate_database
115
+ if (err.code === '42P04') {
116
+ verifiedDbs.add(name);
117
+ return buildDatabaseUrl(name);
118
+ }
119
+ console.error(` [ProjectDb] Failed to ensure database for ${projectId}:`, err.message);
120
+ return null;
121
+ }
122
+ }
123
+ /**
124
+ * Close the admin pool (for graceful shutdown).
125
+ */
126
+ export async function closeAdminPool() {
127
+ if (adminPool) {
128
+ await adminPool.end();
129
+ adminPool = null;
130
+ }
131
+ }
132
+ //# sourceMappingURL=projectDb.js.map
package/dist/tunnel.js CHANGED
@@ -63,7 +63,7 @@ export class TunnelClient {
63
63
  // Send enhanced agent info with capabilities and deviceId
64
64
  this.send({
65
65
  type: 'agent-info',
66
- version: '0.5.9',
66
+ version: '0.5.11',
67
67
  hostname: os.hostname(),
68
68
  platform: `${os.platform()} ${os.arch()}`,
69
69
  deviceId: getDeviceId(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nstantpage-agent",
3
- "version": "0.5.10",
3
+ "version": "0.5.12",
4
4
  "description": "Local development agent for nstantpage.com — run your projects locally, preview in the cloud. Replaces cloud containers for faster builds.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -49,17 +49,19 @@
49
49
  "express": "^4.21.0",
50
50
  "http-proxy": "^1.18.1",
51
51
  "open": "^10.1.0",
52
+ "pg": "^8.13.0",
52
53
  "ws": "^8.18.0"
53
54
  },
54
55
  "devDependencies": {
55
56
  "@types/express": "^4.17.21",
56
57
  "@types/http-proxy": "^1.17.14",
57
58
  "@types/node": "^20.14.0",
59
+ "@types/pg": "^8.18.0",
58
60
  "@types/ws": "^8.5.10",
59
61
  "tsx": "^4.19.0",
60
62
  "typescript": "^5.5.0"
61
63
  },
62
64
  "optionalDependencies": {
63
- "node-pty": "^1.1.0"
65
+ "node-pty": "^1.2.0-beta.11"
64
66
  }
65
67
  }