nstbrowser-ai-agent 0.0.1

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 (119) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +1321 -0
  3. package/bin/nstbrowser-ai-agent-darwin-arm64 +0 -0
  4. package/bin/nstbrowser-ai-agent-darwin-x64 +0 -0
  5. package/bin/nstbrowser-ai-agent-linux-arm64 +0 -0
  6. package/bin/nstbrowser-ai-agent-linux-x64 +0 -0
  7. package/bin/nstbrowser-ai-agent-win32-x64.exe +0 -0
  8. package/bin/nstbrowser-ai-agent.js +109 -0
  9. package/dist/action-policy.d.ts +14 -0
  10. package/dist/action-policy.d.ts.map +1 -0
  11. package/dist/action-policy.js +253 -0
  12. package/dist/action-policy.js.map +1 -0
  13. package/dist/actions.d.ts +18 -0
  14. package/dist/actions.d.ts.map +1 -0
  15. package/dist/actions.js +2037 -0
  16. package/dist/actions.js.map +1 -0
  17. package/dist/auth-cli.d.ts +2 -0
  18. package/dist/auth-cli.d.ts.map +1 -0
  19. package/dist/auth-cli.js +97 -0
  20. package/dist/auth-cli.js.map +1 -0
  21. package/dist/auth-vault.d.ts +36 -0
  22. package/dist/auth-vault.d.ts.map +1 -0
  23. package/dist/auth-vault.js +125 -0
  24. package/dist/auth-vault.js.map +1 -0
  25. package/dist/browser.d.ts +573 -0
  26. package/dist/browser.d.ts.map +1 -0
  27. package/dist/browser.js +2036 -0
  28. package/dist/browser.js.map +1 -0
  29. package/dist/confirmation.d.ts +8 -0
  30. package/dist/confirmation.d.ts.map +1 -0
  31. package/dist/confirmation.js +30 -0
  32. package/dist/confirmation.js.map +1 -0
  33. package/dist/daemon.d.ts +65 -0
  34. package/dist/daemon.d.ts.map +1 -0
  35. package/dist/daemon.js +589 -0
  36. package/dist/daemon.js.map +1 -0
  37. package/dist/diff.d.ts +18 -0
  38. package/dist/diff.d.ts.map +1 -0
  39. package/dist/diff.js +271 -0
  40. package/dist/diff.js.map +1 -0
  41. package/dist/domain-filter.d.ts +28 -0
  42. package/dist/domain-filter.d.ts.map +1 -0
  43. package/dist/domain-filter.js +149 -0
  44. package/dist/domain-filter.js.map +1 -0
  45. package/dist/encryption.d.ts +73 -0
  46. package/dist/encryption.d.ts.map +1 -0
  47. package/dist/encryption.js +171 -0
  48. package/dist/encryption.js.map +1 -0
  49. package/dist/ios-actions.d.ts +11 -0
  50. package/dist/ios-actions.d.ts.map +1 -0
  51. package/dist/ios-actions.js +228 -0
  52. package/dist/ios-actions.js.map +1 -0
  53. package/dist/ios-manager.d.ts +266 -0
  54. package/dist/ios-manager.d.ts.map +1 -0
  55. package/dist/ios-manager.js +1073 -0
  56. package/dist/ios-manager.js.map +1 -0
  57. package/dist/nstbrowser-actions.d.ts +10 -0
  58. package/dist/nstbrowser-actions.d.ts.map +1 -0
  59. package/dist/nstbrowser-actions.js +277 -0
  60. package/dist/nstbrowser-actions.js.map +1 -0
  61. package/dist/nstbrowser-client.d.ts +197 -0
  62. package/dist/nstbrowser-client.d.ts.map +1 -0
  63. package/dist/nstbrowser-client.js +454 -0
  64. package/dist/nstbrowser-client.js.map +1 -0
  65. package/dist/nstbrowser-errors.d.ts +28 -0
  66. package/dist/nstbrowser-errors.d.ts.map +1 -0
  67. package/dist/nstbrowser-errors.js +59 -0
  68. package/dist/nstbrowser-errors.js.map +1 -0
  69. package/dist/nstbrowser-profile-resolver.d.ts +89 -0
  70. package/dist/nstbrowser-profile-resolver.d.ts.map +1 -0
  71. package/dist/nstbrowser-profile-resolver.js +227 -0
  72. package/dist/nstbrowser-profile-resolver.js.map +1 -0
  73. package/dist/nstbrowser-types.d.ts +151 -0
  74. package/dist/nstbrowser-types.d.ts.map +1 -0
  75. package/dist/nstbrowser-types.js +5 -0
  76. package/dist/nstbrowser-types.js.map +1 -0
  77. package/dist/nstbrowser-utils.d.ts +71 -0
  78. package/dist/nstbrowser-utils.d.ts.map +1 -0
  79. package/dist/nstbrowser-utils.js +174 -0
  80. package/dist/nstbrowser-utils.js.map +1 -0
  81. package/dist/protocol.d.ts +26 -0
  82. package/dist/protocol.d.ts.map +1 -0
  83. package/dist/protocol.js +1245 -0
  84. package/dist/protocol.js.map +1 -0
  85. package/dist/snapshot.d.ts +67 -0
  86. package/dist/snapshot.d.ts.map +1 -0
  87. package/dist/snapshot.js +514 -0
  88. package/dist/snapshot.js.map +1 -0
  89. package/dist/state-utils.d.ts +77 -0
  90. package/dist/state-utils.d.ts.map +1 -0
  91. package/dist/state-utils.js +178 -0
  92. package/dist/state-utils.js.map +1 -0
  93. package/dist/stream-server.d.ts +117 -0
  94. package/dist/stream-server.d.ts.map +1 -0
  95. package/dist/stream-server.js +309 -0
  96. package/dist/stream-server.js.map +1 -0
  97. package/dist/types.d.ts +1121 -0
  98. package/dist/types.d.ts.map +1 -0
  99. package/dist/types.js +2 -0
  100. package/dist/types.js.map +1 -0
  101. package/package.json +83 -0
  102. package/scripts/analyze-api-coverage.js +205 -0
  103. package/scripts/analyze-cli-coverage.js +239 -0
  104. package/scripts/build-all-platforms.sh +68 -0
  105. package/scripts/check-version-sync.js +39 -0
  106. package/scripts/copy-native.js +36 -0
  107. package/scripts/download-nstbrowser-docs.js +152 -0
  108. package/scripts/generate-skills.sh +218 -0
  109. package/scripts/postinstall.js +231 -0
  110. package/scripts/sync-version.js +69 -0
  111. package/skills/nstbrowser-ai-agent/SKILL.md +759 -0
  112. package/skills/nstbrowser-ai-agent/references/batch-operations.md +414 -0
  113. package/skills/nstbrowser-ai-agent/references/nst-api-reference.md +960 -0
  114. package/skills/nstbrowser-ai-agent/references/profile-management.md +672 -0
  115. package/skills/nstbrowser-ai-agent/references/proxy-configuration.md +460 -0
  116. package/skills/nstbrowser-ai-agent/references/troubleshooting.md +773 -0
  117. package/skills/nstbrowser-ai-agent/templates/automated-workflow.sh +248 -0
  118. package/skills/nstbrowser-ai-agent/templates/batch-proxy-update.sh +257 -0
  119. package/skills/nstbrowser-ai-agent/templates/profile-setup.sh +248 -0
package/dist/daemon.js ADDED
@@ -0,0 +1,589 @@
1
+ import * as net from 'net';
2
+ import * as fs from 'fs';
3
+ import * as path from 'path';
4
+ import * as os from 'os';
5
+ import { BrowserManager } from './browser.js';
6
+ import { parseCommand, serializeResponse, errorResponse } from './protocol.js';
7
+ import { executeCommand, initActionPolicy } from './actions.js';
8
+ import { executeNstbrowserCommand } from './nstbrowser-actions.js';
9
+ import { StreamServer } from './stream-server.js';
10
+ import { getEncryptionKey, encryptData, isValidSessionName, cleanupExpiredStates, getAutoStateFilePath, } from './state-utils.js';
11
+ /**
12
+ * Backpressure-aware socket write.
13
+ * If the kernel buffer is full (socket.write returns false),
14
+ * waits for the 'drain' event before resolving.
15
+ */
16
+ export function safeWrite(socket, payload) {
17
+ return new Promise((resolve, reject) => {
18
+ if (socket.destroyed) {
19
+ resolve();
20
+ return;
21
+ }
22
+ const canContinue = socket.write(payload);
23
+ if (canContinue) {
24
+ resolve();
25
+ }
26
+ else if (socket.destroyed) {
27
+ resolve();
28
+ }
29
+ else {
30
+ const cleanup = () => {
31
+ socket.removeListener('drain', onDrain);
32
+ socket.removeListener('error', onError);
33
+ socket.removeListener('close', onClose);
34
+ };
35
+ const onDrain = () => {
36
+ cleanup();
37
+ resolve();
38
+ };
39
+ const onError = (err) => {
40
+ cleanup();
41
+ reject(err);
42
+ };
43
+ const onClose = () => {
44
+ cleanup();
45
+ resolve();
46
+ };
47
+ socket.once('drain', onDrain);
48
+ socket.once('error', onError);
49
+ socket.once('close', onClose);
50
+ }
51
+ });
52
+ }
53
+ // Platform detection
54
+ const isWindows = process.platform === 'win32';
55
+ // Session support - each session gets its own socket/pid
56
+ let currentSession = process.env.NSTBROWSER_AI_AGENT_SESSION || 'default';
57
+ // Stream server for browser preview
58
+ let streamServer = null;
59
+ // Default stream port (can be overridden with NSTBROWSER_AI_AGENT_STREAM_PORT)
60
+ const DEFAULT_STREAM_PORT = 9223;
61
+ /**
62
+ * Save state to file with optional encryption.
63
+ */
64
+ async function saveStateToFile(browser, filepath) {
65
+ const context = browser.getContext();
66
+ if (!context) {
67
+ throw new Error('No browser context available');
68
+ }
69
+ const state = await context.storageState();
70
+ const jsonData = JSON.stringify(state, null, 2);
71
+ const key = getEncryptionKey();
72
+ if (key) {
73
+ const encrypted = encryptData(jsonData, key);
74
+ fs.writeFileSync(filepath, JSON.stringify(encrypted, null, 2));
75
+ return { encrypted: true };
76
+ }
77
+ fs.writeFileSync(filepath, jsonData);
78
+ return { encrypted: false };
79
+ }
80
+ const AUTO_EXPIRE_ENV = 'NSTBROWSER_AI_AGENT_STATE_EXPIRE_DAYS';
81
+ const DEFAULT_EXPIRE_DAYS = 30;
82
+ function runCleanupExpiredStates() {
83
+ const expireDaysStr = process.env[AUTO_EXPIRE_ENV];
84
+ const expireDays = expireDaysStr ? parseInt(expireDaysStr, 10) : DEFAULT_EXPIRE_DAYS;
85
+ if (isNaN(expireDays) || expireDays <= 0) {
86
+ return;
87
+ }
88
+ try {
89
+ const deleted = cleanupExpiredStates(expireDays);
90
+ if (deleted.length > 0 && process.env.NSTBROWSER_AI_AGENT_DEBUG === '1') {
91
+ console.error(`[DEBUG] Auto-expired ${deleted.length} state file(s) older than ${expireDays} days`);
92
+ }
93
+ }
94
+ catch (err) {
95
+ if (process.env.NSTBROWSER_AI_AGENT_DEBUG === '1') {
96
+ console.error(`[DEBUG] Failed to clean up expired states:`, err);
97
+ }
98
+ }
99
+ }
100
+ /**
101
+ * Get the validated session name and auto-state file path.
102
+ * Centralizes session name validation to prevent path traversal.
103
+ */
104
+ function getSessionAutoStatePath() {
105
+ const sessionNameRaw = process.env.NSTBROWSER_AI_AGENT_SESSION_NAME;
106
+ if (!sessionNameRaw)
107
+ return undefined;
108
+ if (!isValidSessionName(sessionNameRaw)) {
109
+ if (process.env.NSTBROWSER_AI_AGENT_DEBUG === '1') {
110
+ console.error(`[SECURITY] Invalid session name rejected: ${sessionNameRaw}`);
111
+ }
112
+ return undefined;
113
+ }
114
+ const sessionId = process.env.NSTBROWSER_AI_AGENT_SESSION || 'default';
115
+ try {
116
+ const autoStatePath = getAutoStateFilePath(sessionNameRaw, sessionId);
117
+ return autoStatePath && fs.existsSync(autoStatePath) ? autoStatePath : undefined;
118
+ }
119
+ catch {
120
+ return undefined;
121
+ }
122
+ }
123
+ /**
124
+ * Get the auto-state file path for saving (creates sessions dir if needed).
125
+ * Returns undefined if no valid session name is configured.
126
+ */
127
+ function getSessionSaveStatePath() {
128
+ const sessionNameRaw = process.env.NSTBROWSER_AI_AGENT_SESSION_NAME;
129
+ if (!sessionNameRaw)
130
+ return undefined;
131
+ if (!isValidSessionName(sessionNameRaw))
132
+ return undefined;
133
+ const sessionId = process.env.NSTBROWSER_AI_AGENT_SESSION || 'default';
134
+ try {
135
+ return getAutoStateFilePath(sessionNameRaw, sessionId) ?? undefined;
136
+ }
137
+ catch {
138
+ return undefined;
139
+ }
140
+ }
141
+ /**
142
+ * Set the current session
143
+ */
144
+ export function setSession(session) {
145
+ currentSession = session;
146
+ }
147
+ /**
148
+ * Get the current session
149
+ */
150
+ export function getSession() {
151
+ return currentSession;
152
+ }
153
+ /**
154
+ * Get port number for TCP mode (Windows)
155
+ * Uses a hash of the session name to get a consistent port
156
+ */
157
+ function getPortForSession(session) {
158
+ let hash = 0;
159
+ for (let i = 0; i < session.length; i++) {
160
+ hash = (hash << 5) - hash + session.charCodeAt(i);
161
+ hash |= 0;
162
+ }
163
+ // Port range 49152-65535 (dynamic/private ports)
164
+ return 49152 + (Math.abs(hash) % 16383);
165
+ }
166
+ /**
167
+ * Get the base directory for socket/pid files.
168
+ * Priority: NSTBROWSER_AI_AGENT_SOCKET_DIR > XDG_RUNTIME_DIR > ~/.nstbrowser-ai-agent > tmpdir
169
+ */
170
+ export function getAppDir() {
171
+ // 1. XDG_RUNTIME_DIR (Linux standard)
172
+ if (process.env.XDG_RUNTIME_DIR) {
173
+ return path.join(process.env.XDG_RUNTIME_DIR, 'nstbrowser-ai-agent');
174
+ }
175
+ // 2. Home directory fallback (like Docker Desktop's ~/.docker/run/)
176
+ const homeDir = os.homedir();
177
+ if (homeDir) {
178
+ return path.join(homeDir, '.nstbrowser-ai-agent');
179
+ }
180
+ // 3. Last resort: temp dir
181
+ return path.join(os.tmpdir(), 'nstbrowser-ai-agent');
182
+ }
183
+ export function getSocketDir() {
184
+ // Allow explicit override for socket directory
185
+ if (process.env.NSTBROWSER_AI_AGENT_SOCKET_DIR) {
186
+ return process.env.NSTBROWSER_AI_AGENT_SOCKET_DIR;
187
+ }
188
+ return getAppDir();
189
+ }
190
+ /**
191
+ * Get the socket path for the current session (Unix) or port (Windows)
192
+ */
193
+ export function getSocketPath(session) {
194
+ const sess = session ?? currentSession;
195
+ if (isWindows) {
196
+ return String(getPortForSession(sess));
197
+ }
198
+ return path.join(getSocketDir(), `${sess}.sock`);
199
+ }
200
+ /**
201
+ * Get the port file path for Windows (stores the port number)
202
+ */
203
+ export function getPortFile(session) {
204
+ const sess = session ?? currentSession;
205
+ return path.join(getSocketDir(), `${sess}.port`);
206
+ }
207
+ /**
208
+ * Get the PID file path for the current session
209
+ */
210
+ export function getPidFile(session) {
211
+ const sess = session ?? currentSession;
212
+ return path.join(getSocketDir(), `${sess}.pid`);
213
+ }
214
+ /**
215
+ * Check if daemon is running for the current session
216
+ */
217
+ export function isDaemonRunning(session) {
218
+ const pidFile = getPidFile(session);
219
+ if (!fs.existsSync(pidFile))
220
+ return false;
221
+ try {
222
+ const pid = parseInt(fs.readFileSync(pidFile, 'utf8').trim(), 10);
223
+ // Check if process exists (works on both Unix and Windows)
224
+ process.kill(pid, 0);
225
+ return true;
226
+ }
227
+ catch (err) {
228
+ // EPERM means the process exists but we lack permission to signal it
229
+ // (e.g. caller is inside a macOS sandbox). Only ESRCH means it's gone.
230
+ if (err instanceof Error && err.code === 'EPERM') {
231
+ return true;
232
+ }
233
+ // Process doesn't exist, clean up stale files
234
+ cleanupSocket(session);
235
+ return false;
236
+ }
237
+ }
238
+ /**
239
+ * Get connection info for the current session
240
+ * Returns { type: 'unix', path: string } or { type: 'tcp', port: number }
241
+ */
242
+ export function getConnectionInfo(session) {
243
+ const sess = session ?? currentSession;
244
+ if (isWindows) {
245
+ return { type: 'tcp', port: getPortForSession(sess) };
246
+ }
247
+ return { type: 'unix', path: path.join(getSocketDir(), `${sess}.sock`) };
248
+ }
249
+ /**
250
+ * Clean up socket and PID file for the current session
251
+ */
252
+ export function cleanupSocket(session) {
253
+ const pidFile = getPidFile(session);
254
+ const streamPortFile = getStreamPortFile(session);
255
+ try {
256
+ if (fs.existsSync(pidFile))
257
+ fs.unlinkSync(pidFile);
258
+ if (fs.existsSync(streamPortFile))
259
+ fs.unlinkSync(streamPortFile);
260
+ if (isWindows) {
261
+ const portFile = getPortFile(session);
262
+ if (fs.existsSync(portFile))
263
+ fs.unlinkSync(portFile);
264
+ }
265
+ else {
266
+ const socketPath = getSocketPath(session);
267
+ if (fs.existsSync(socketPath))
268
+ fs.unlinkSync(socketPath);
269
+ }
270
+ }
271
+ catch {
272
+ // Ignore cleanup errors
273
+ }
274
+ }
275
+ /**
276
+ * Get the stream port file path
277
+ */
278
+ export function getStreamPortFile(session) {
279
+ const sess = session ?? currentSession;
280
+ return path.join(getSocketDir(), `${sess}.stream`);
281
+ }
282
+ /**
283
+ * Start the daemon server
284
+ * @param options.streamPort Port for WebSocket stream server (0 to disable)
285
+ */
286
+ export async function startDaemon(options) {
287
+ // Ensure socket directory exists with restricted permissions (owner-only access)
288
+ const socketDir = getSocketDir();
289
+ if (!fs.existsSync(socketDir)) {
290
+ fs.mkdirSync(socketDir, { recursive: true, mode: 0o700 });
291
+ }
292
+ // Clean up any stale socket
293
+ cleanupSocket();
294
+ // Clean up expired state files on startup
295
+ runCleanupExpiredStates();
296
+ // Initialize action policy enforcement
297
+ initActionPolicy();
298
+ // Create browser manager
299
+ const manager = new BrowserManager();
300
+ let shuttingDown = false;
301
+ // Start stream server if port is specified (or use default if env var is set)
302
+ const streamPort = options?.streamPort ??
303
+ (process.env.NSTBROWSER_AI_AGENT_STREAM_PORT
304
+ ? parseInt(process.env.NSTBROWSER_AI_AGENT_STREAM_PORT, 10)
305
+ : 0);
306
+ if (streamPort > 0) {
307
+ streamServer = new StreamServer(manager, streamPort);
308
+ await streamServer.start();
309
+ // Write stream port to file for clients to discover
310
+ const streamPortFile = getStreamPortFile();
311
+ fs.writeFileSync(streamPortFile, streamPort.toString());
312
+ }
313
+ const server = net.createServer((socket) => {
314
+ let buffer = '';
315
+ let httpChecked = false;
316
+ // Command serialization: queue incoming lines and process them one at a time.
317
+ // This prevents concurrent command execution which can cause socket.write
318
+ // buffer contention and EAGAIN errors on the Rust CLI side.
319
+ const commandQueue = [];
320
+ let processing = false;
321
+ async function processQueue() {
322
+ if (processing)
323
+ return;
324
+ processing = true;
325
+ while (commandQueue.length > 0) {
326
+ const line = commandQueue.shift();
327
+ try {
328
+ const parseResult = parseCommand(line);
329
+ if (!parseResult.success) {
330
+ const resp = errorResponse(parseResult.id ?? 'unknown', parseResult.error);
331
+ await safeWrite(socket, serializeResponse(resp) + '\n');
332
+ continue;
333
+ }
334
+ // Debug: log received commands
335
+ if (process.env.NSTBROWSER_AI_AGENT_DEBUG === '1') {
336
+ console.error('[DAEMON] Received command:', JSON.stringify(parseResult.command, null, 2));
337
+ }
338
+ // Handle Nstbrowser commands - they don't require a browser session
339
+ if (parseResult.command.action.startsWith('nst_')) {
340
+ try {
341
+ const response = await executeNstbrowserCommand(parseResult.command);
342
+ await safeWrite(socket, serializeResponse(response) + '\n');
343
+ }
344
+ catch (err) {
345
+ const message = err instanceof Error ? err.message : String(err);
346
+ await safeWrite(socket, serializeResponse(errorResponse(parseResult.command.id, message)) + '\n');
347
+ }
348
+ continue;
349
+ }
350
+ // Auto-launch if not already launched and this isn't a launch/close/state_load command
351
+ if (!manager.isLaunched() &&
352
+ parseResult.command.action !== 'launch' &&
353
+ parseResult.command.action !== 'close' &&
354
+ parseResult.command.action !== 'state_load') {
355
+ // Auto-launch desktop browser
356
+ const extensions = process.env.NSTBROWSER_AI_AGENT_EXTENSIONS
357
+ ? process.env.NSTBROWSER_AI_AGENT_EXTENSIONS.split(',')
358
+ .map((p) => p.trim())
359
+ .filter(Boolean)
360
+ : undefined;
361
+ // Parse args from env (comma or newline separated)
362
+ const argsEnv = process.env.NSTBROWSER_AI_AGENT_ARGS;
363
+ const args = argsEnv
364
+ ? argsEnv
365
+ .split(/[,\n]/)
366
+ .map((a) => a.trim())
367
+ .filter((a) => a.length > 0)
368
+ : undefined;
369
+ // Parse proxy from env
370
+ const proxyServer = process.env.NSTBROWSER_AI_AGENT_PROXY;
371
+ const proxyBypass = process.env.NSTBROWSER_AI_AGENT_PROXY_BYPASS;
372
+ const proxy = proxyServer
373
+ ? {
374
+ server: proxyServer,
375
+ ...(proxyBypass && { bypass: proxyBypass }),
376
+ }
377
+ : undefined;
378
+ const ignoreHTTPSErrors = process.env.NSTBROWSER_AI_AGENT_IGNORE_HTTPS_ERRORS === '1';
379
+ const allowFileAccess = process.env.NSTBROWSER_AI_AGENT_ALLOW_FILE_ACCESS === '1';
380
+ const colorSchemeEnv = process.env.NSTBROWSER_AI_AGENT_COLOR_SCHEME;
381
+ const colorScheme = colorSchemeEnv === 'dark' ||
382
+ colorSchemeEnv === 'light' ||
383
+ colorSchemeEnv === 'no-preference'
384
+ ? colorSchemeEnv
385
+ : undefined;
386
+ // Extract NST profile fields from command if present
387
+ const cmd = parseResult.command;
388
+ const nstProfileName = cmd.nstProfileName;
389
+ const nstProfileId = cmd.nstProfileId;
390
+ await manager.launch({
391
+ id: 'auto',
392
+ action: 'launch',
393
+ headless: process.env.NSTBROWSER_AI_AGENT_HEADED !== '1',
394
+ executablePath: process.env.NSTBROWSER_AI_AGENT_EXECUTABLE_PATH,
395
+ extensions: extensions,
396
+ profile: process.env.NSTBROWSER_AI_AGENT_PROFILE,
397
+ storageState: process.env.NSTBROWSER_AI_AGENT_STATE,
398
+ args,
399
+ userAgent: process.env.NSTBROWSER_AI_AGENT_USER_AGENT,
400
+ proxy,
401
+ ignoreHTTPSErrors: ignoreHTTPSErrors,
402
+ allowFileAccess: allowFileAccess,
403
+ colorScheme,
404
+ autoStateFilePath: getSessionAutoStatePath(),
405
+ nstProfileName,
406
+ nstProfileId,
407
+ });
408
+ }
409
+ // Recover from stale state: browser is launched but all pages were closed
410
+ if (manager instanceof BrowserManager &&
411
+ manager.isLaunched() &&
412
+ !manager.hasPages() &&
413
+ parseResult.command.action !== 'launch' &&
414
+ parseResult.command.action !== 'close') {
415
+ await manager.ensurePage();
416
+ }
417
+ // Handle explicit launch with auto-load state
418
+ if (parseResult.command.action === 'launch' &&
419
+ manager instanceof BrowserManager &&
420
+ !parseResult.command.autoStateFilePath) {
421
+ const autoStatePath = getSessionAutoStatePath();
422
+ if (autoStatePath) {
423
+ parseResult.command.autoStateFilePath = autoStatePath;
424
+ }
425
+ }
426
+ // Handle close command specially - shuts down daemon
427
+ if (parseResult.command.action === 'close') {
428
+ // Auto-save state before closing
429
+ if (manager instanceof BrowserManager && manager.isLaunched()) {
430
+ const savePath = getSessionSaveStatePath();
431
+ if (savePath) {
432
+ try {
433
+ const { encrypted } = await saveStateToFile(manager, savePath);
434
+ fs.chmodSync(savePath, 0o600);
435
+ if (process.env.NSTBROWSER_AI_AGENT_DEBUG === '1') {
436
+ console.error(`Auto-saved session state: ${savePath}${encrypted ? ' (encrypted)' : ''}`);
437
+ }
438
+ }
439
+ catch (err) {
440
+ if (process.env.NSTBROWSER_AI_AGENT_DEBUG === '1') {
441
+ console.error(`Failed to auto-save session state:`, err);
442
+ }
443
+ }
444
+ }
445
+ }
446
+ const response = await executeCommand(parseResult.command, manager);
447
+ await safeWrite(socket, serializeResponse(response) + '\n');
448
+ if (!shuttingDown) {
449
+ shuttingDown = true;
450
+ setTimeout(() => {
451
+ server.close();
452
+ cleanupSocket();
453
+ process.exit(0);
454
+ }, 100);
455
+ }
456
+ commandQueue.length = 0;
457
+ processing = false;
458
+ return;
459
+ }
460
+ // Execute command
461
+ const response = await executeCommand(parseResult.command, manager);
462
+ // Add any launch warnings to the response
463
+ const warnings = manager.getAndClearWarnings();
464
+ if (warnings.length > 0 && response.success && response.data) {
465
+ response.data.warnings = warnings;
466
+ }
467
+ await safeWrite(socket, serializeResponse(response) + '\n');
468
+ }
469
+ catch (err) {
470
+ const message = err instanceof Error ? err.message : String(err);
471
+ await safeWrite(socket, serializeResponse(errorResponse('error', message)) + '\n').catch(() => { }); // Socket may already be destroyed
472
+ }
473
+ }
474
+ processing = false;
475
+ }
476
+ socket.on('data', (data) => {
477
+ buffer += data.toString();
478
+ // Security: Detect and reject HTTP requests to prevent cross-origin attacks.
479
+ // Browsers using fetch() must send HTTP headers (e.g., "POST / HTTP/1.1"),
480
+ // while legitimate clients send raw JSON starting with "{".
481
+ if (!httpChecked) {
482
+ httpChecked = true;
483
+ const trimmed = buffer.trimStart();
484
+ if (/^(GET|POST|PUT|DELETE|HEAD|OPTIONS|PATCH|CONNECT|TRACE)\s/i.test(trimmed)) {
485
+ socket.destroy();
486
+ return;
487
+ }
488
+ }
489
+ // Extract complete lines and enqueue them for serial processing
490
+ while (buffer.includes('\n')) {
491
+ const newlineIdx = buffer.indexOf('\n');
492
+ const line = buffer.substring(0, newlineIdx);
493
+ buffer = buffer.substring(newlineIdx + 1);
494
+ if (!line.trim())
495
+ continue;
496
+ commandQueue.push(line);
497
+ }
498
+ processQueue().catch((err) => {
499
+ // Socket write failures during queue processing are non-fatal;
500
+ // the client has likely disconnected.
501
+ // Only log err.message to avoid leaking sensitive fields (e.g. passwords) from command objects.
502
+ console.warn('[warn] processQueue error:', err?.message ?? String(err));
503
+ if (process.env.NSTBROWSER_AI_AGENT_DEBUG === '1') {
504
+ console.error('[DEBUG] processQueue error stack:', err?.stack ?? err?.message ?? String(err));
505
+ }
506
+ });
507
+ });
508
+ socket.on('error', () => {
509
+ // Client disconnected, ignore
510
+ });
511
+ });
512
+ const pidFile = getPidFile();
513
+ // Write PID file before listening
514
+ fs.writeFileSync(pidFile, process.pid.toString());
515
+ if (isWindows) {
516
+ // Windows: use TCP socket on localhost
517
+ const port = getPortForSession(currentSession);
518
+ const portFile = getPortFile();
519
+ fs.writeFileSync(portFile, port.toString());
520
+ server.listen(port, '127.0.0.1', () => {
521
+ // Daemon is ready on TCP port
522
+ });
523
+ }
524
+ else {
525
+ // Unix: use Unix domain socket
526
+ const socketPath = getSocketPath();
527
+ server.listen(socketPath, () => {
528
+ // Daemon is ready
529
+ });
530
+ }
531
+ server.on('error', (err) => {
532
+ console.error('Server error:', err);
533
+ cleanupSocket();
534
+ process.exit(1);
535
+ });
536
+ // Handle shutdown signals
537
+ const shutdown = async () => {
538
+ if (shuttingDown)
539
+ return;
540
+ shuttingDown = true;
541
+ // Stop stream server if running
542
+ if (streamServer) {
543
+ await streamServer.stop();
544
+ streamServer = null;
545
+ // Clean up stream port file
546
+ const streamPortFile = getStreamPortFile();
547
+ try {
548
+ if (fs.existsSync(streamPortFile))
549
+ fs.unlinkSync(streamPortFile);
550
+ }
551
+ catch {
552
+ // Ignore cleanup errors
553
+ }
554
+ }
555
+ await manager.close();
556
+ server.close();
557
+ cleanupSocket();
558
+ process.exit(0);
559
+ };
560
+ process.on('SIGINT', shutdown);
561
+ process.on('SIGTERM', shutdown);
562
+ process.on('SIGHUP', shutdown);
563
+ // Handle unexpected errors - always cleanup
564
+ process.on('uncaughtException', (err) => {
565
+ console.error('Uncaught exception:', err);
566
+ cleanupSocket();
567
+ process.exit(1);
568
+ });
569
+ process.on('unhandledRejection', (reason) => {
570
+ console.error('Unhandled rejection:', reason);
571
+ cleanupSocket();
572
+ process.exit(1);
573
+ });
574
+ // Cleanup on normal exit
575
+ process.on('exit', () => {
576
+ cleanupSocket();
577
+ });
578
+ // Keep process alive
579
+ process.stdin.resume();
580
+ }
581
+ // Run daemon if this is the entry point
582
+ if (process.argv[1]?.endsWith('daemon.js') || process.env.NSTBROWSER_AI_AGENT_DAEMON === '1') {
583
+ startDaemon().catch((err) => {
584
+ console.error('Daemon error:', err);
585
+ cleanupSocket();
586
+ process.exit(1);
587
+ });
588
+ }
589
+ //# sourceMappingURL=daemon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon.js","sourceRoot":"","sources":["../src/daemon.ts"],"names":[],"mappings":"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"}
package/dist/diff.d.ts ADDED
@@ -0,0 +1,18 @@
1
+ import type { BrowserContext } from 'playwright-core';
2
+ import type { DiffSnapshotData, DiffScreenshotData } from './types.js';
3
+ /**
4
+ * Produce a unified diff string and stats from two snapshot texts.
5
+ */
6
+ export declare function diffSnapshots(before: string, after: string): DiffSnapshotData;
7
+ /**
8
+ * Compare two image buffers using the browser's Canvas API for pixel comparison.
9
+ * Uses an isolated blank page to avoid CSP interference or DOM side effects on the
10
+ * user's page. Images are served via intercepted routes to avoid large base64 payloads
11
+ * through page.evaluate (which can be slow or hit CDP message size limits).
12
+ */
13
+ export declare function diffScreenshots(context: BrowserContext, baselineBuffer: Buffer, currentBuffer: Buffer, opts: {
14
+ threshold?: number;
15
+ outputPath?: string;
16
+ baselineMime?: string;
17
+ }): Promise<DiffScreenshotData>;
18
+ //# sourceMappingURL=diff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../src/diff.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,KAAK,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAsHvE;;GAEG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,gBAAgB,CAmC7E;AAcD;;;;;GAKG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,cAAc,EACvB,cAAc,EAAE,MAAM,EACtB,aAAa,EAAE,MAAM,EACrB,IAAI,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,GACvE,OAAO,CAAC,kBAAkB,CAAC,CA4J7B"}