@minded-ai/mindedjs 3.1.21 → 3.1.23

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 (45) hide show
  1. package/dist/agent.d.ts.map +1 -1
  2. package/dist/agent.js +0 -4
  3. package/dist/agent.js.map +1 -1
  4. package/dist/browserTask/executeBrowserTask.d.ts.map +1 -1
  5. package/dist/browserTask/executeBrowserTask.js +1 -69
  6. package/dist/browserTask/executeBrowserTask.js.map +1 -1
  7. package/dist/cli/validateAgent.d.ts.map +1 -1
  8. package/dist/cli/validateAgent.js +15 -0
  9. package/dist/cli/validateAgent.js.map +1 -1
  10. package/dist/nodes/addPromptNode.d.ts.map +1 -1
  11. package/dist/nodes/addPromptNode.js +1 -0
  12. package/dist/nodes/addPromptNode.js.map +1 -1
  13. package/dist/nodes/addToolRunNode.d.ts.map +1 -1
  14. package/dist/nodes/addToolRunNode.js +1 -0
  15. package/dist/nodes/addToolRunNode.js.map +1 -1
  16. package/dist/platform/toolExecutor.d.ts.map +1 -1
  17. package/dist/platform/toolExecutor.js +1 -0
  18. package/dist/platform/toolExecutor.js.map +1 -1
  19. package/dist/toolsLibrary/browserSessionPersistence.d.ts +28 -0
  20. package/dist/toolsLibrary/browserSessionPersistence.d.ts.map +1 -0
  21. package/dist/toolsLibrary/browserSessionPersistence.js +159 -0
  22. package/dist/toolsLibrary/browserSessionPersistence.js.map +1 -0
  23. package/dist/toolsLibrary/withBrowserSession.d.ts +2 -1
  24. package/dist/toolsLibrary/withBrowserSession.d.ts.map +1 -1
  25. package/dist/toolsLibrary/withBrowserSession.js +65 -50
  26. package/dist/toolsLibrary/withBrowserSession.js.map +1 -1
  27. package/dist/types/Flows.types.d.ts +0 -5
  28. package/dist/types/Flows.types.d.ts.map +1 -1
  29. package/dist/types/Flows.types.js.map +1 -1
  30. package/dist/types/Tools.types.d.ts +1 -0
  31. package/dist/types/Tools.types.d.ts.map +1 -1
  32. package/dist/types/Tools.types.js.map +1 -1
  33. package/docs/low-code-editor/rpa-tools.md +4 -1
  34. package/docs/low-code-editor/tools.md +86 -1
  35. package/package.json +1 -1
  36. package/src/agent.ts +0 -5
  37. package/src/browserTask/executeBrowserTask.ts +1 -73
  38. package/src/cli/validateAgent.ts +17 -0
  39. package/src/nodes/addPromptNode.ts +1 -0
  40. package/src/nodes/addToolRunNode.ts +1 -0
  41. package/src/platform/toolExecutor.ts +1 -0
  42. package/src/toolsLibrary/browserSessionPersistence.ts +203 -0
  43. package/src/toolsLibrary/withBrowserSession.ts +74 -56
  44. package/src/types/Flows.types.ts +0 -5
  45. package/src/types/Tools.types.ts +1 -0
@@ -4,13 +4,10 @@ import { createBrowserSession, destroyBrowserSession } from '../browserTask/exec
4
4
  import { logger } from '../utils/logger';
5
5
  import * as fs from 'fs';
6
6
  import * as path from 'path';
7
- import { CookieStore } from '../browserTask/CookieStore';
8
7
  import { awaitEmit, emit } from '../platform/mindedConnection';
9
8
  import { mindedConnectionSocketMessageType } from '../platform/mindedConnectionTypes';
10
9
  import { ProxyType } from '../types/Tools.types';
11
-
12
- // Initialize cookie store
13
- const cookieStore = new CookieStore(path.join(process.cwd(), 'local_storage', 'cookies'));
10
+ import { fetchSessionDataViaSocket, saveSessionDataViaSocket } from './browserSessionPersistence';
14
11
 
15
12
  /**
16
13
  * Strips unnecessary content from HTML to reduce file size
@@ -85,7 +82,6 @@ class ScreenshotCapture {
85
82
  error,
86
83
  });
87
84
  });
88
-
89
85
  } catch (error) {
90
86
  logger.warn({
91
87
  message: 'Failed to capture screenshot',
@@ -141,7 +137,7 @@ class LogsCapture {
141
137
  try {
142
138
  const timestamp = new Date().toISOString();
143
139
 
144
- // Send logs to backend via socket (upload all logs accumulated so far)
140
+ // Send full log history to backend - backend overwrites the file on each upload
145
141
  await awaitEmit(mindedConnectionSocketMessageType.RPA_LOGS_UPLOAD, {
146
142
  type: mindedConnectionSocketMessageType.RPA_LOGS_UPLOAD,
147
143
  sessionId: this.sessionId,
@@ -216,13 +212,20 @@ const createProxyLocator = (
216
212
  /**
217
213
  * Create a proxy page that intercepts actions and captures screenshots and logs
218
214
  */
219
- const createProxyPage = (
220
- page: Page,
221
- screenshotCapture: ScreenshotCapture,
222
- logsCapture: LogsCapture,
223
- ): Page => {
215
+ const createProxyPage = (page: Page, screenshotCapture: ScreenshotCapture, logsCapture: LogsCapture): Page => {
224
216
  // List of methods to intercept for screenshot capture and logging
225
- const methodsToIntercept = ['click', 'fill', 'type', 'goto', 'selectOption', 'check', 'uncheck', 'setInputFiles', 'waitForTimeout', 'evaluate'];
217
+ const methodsToIntercept = [
218
+ 'click',
219
+ 'fill',
220
+ 'type',
221
+ 'goto',
222
+ 'selectOption',
223
+ 'check',
224
+ 'uncheck',
225
+ 'setInputFiles',
226
+ 'waitForTimeout',
227
+ 'evaluate',
228
+ ];
226
229
  // Methods that return locators and need special handling
227
230
  const locatorMethods = ['locator'];
228
231
 
@@ -323,37 +326,6 @@ const formatLocatorActionLog = (action: string, selector: string | undefined, ar
323
326
  }
324
327
  };
325
328
 
326
- // Helper function to load cookies for a session
327
- const loadCookiesForSession = async (context: BrowserContext, sessionId: string): Promise<void> => {
328
- const stored = await cookieStore.load();
329
- if (!stored || stored.length === 0) {
330
- logger.info({ message: 'No stored cookies to load', sessionId });
331
- return;
332
- }
333
-
334
- try {
335
- await context.addCookies(stored);
336
- logger.info({ message: 'Loaded cookies into browser session', sessionId, count: stored.length });
337
- } catch (error) {
338
- logger.warn({ message: 'Failed to add cookies to context', sessionId, error });
339
- }
340
- };
341
-
342
- // Helper function to save cookies for a session
343
- const saveCookiesForSession = async (context: BrowserContext, sessionId: string): Promise<void> => {
344
- try {
345
- const cookies = await context.cookies();
346
- if (cookies && cookies.length > 0) {
347
- await cookieStore.save(cookies);
348
- logger.info({ message: 'Saved cookies from browser session', sessionId, count: cookies.length });
349
- } else {
350
- logger.info({ message: 'No cookies found in browser session', sessionId });
351
- }
352
- } catch (error) {
353
- logger.warn({ message: 'Failed to get/save cookies from session', sessionId, error: JSON.stringify(error) });
354
- }
355
- };
356
-
357
329
  export const withBrowserSession = async <T>(
358
330
  {
359
331
  sessionId,
@@ -365,6 +337,7 @@ export const withBrowserSession = async <T>(
365
337
  proxyUser,
366
338
  proxyPass,
367
339
  toolName,
340
+ persistSession = true,
368
341
  }: {
369
342
  sessionId: string;
370
343
  browserTaskMode: BrowserTaskMode;
@@ -375,10 +348,19 @@ export const withBrowserSession = async <T>(
375
348
  proxyUser?: string;
376
349
  proxyPass?: string;
377
350
  toolName: string;
351
+ persistSession?: boolean;
378
352
  },
379
353
  callback: (page: Page) => Promise<T>,
380
354
  ): Promise<{ result: T }> => {
381
- const { cdpUrl } = await createBrowserSession({ sessionId, browserTaskMode, proxyCountryCode, proxyType, proxyServer, proxyUser, proxyPass });
355
+ const { cdpUrl } = await createBrowserSession({
356
+ sessionId,
357
+ browserTaskMode,
358
+ proxyCountryCode,
359
+ proxyType,
360
+ proxyServer,
361
+ proxyUser,
362
+ proxyPass,
363
+ });
382
364
  if (!cdpUrl) {
383
365
  throw new Error('CDP URL was not provided by the browser session.');
384
366
  }
@@ -409,16 +391,52 @@ export const withBrowserSession = async <T>(
409
391
  const logsCapture = new LogsCapture(sessionId, toolCallId);
410
392
  page = createProxyPage(page, screenshotCapture, logsCapture);
411
393
 
412
- // Load cookies for this session (only for local mode, best-effort)
413
- const noCookies = process.env.MINDED_NO_COOKIES === 'true';
414
- if (browserTaskMode === BrowserTaskMode.LOCAL && !noCookies) {
394
+ // Load session data (cookies + localStorage) once at startup (if persistence is enabled)
395
+ if (persistSession) {
415
396
  try {
416
- await loadCookiesForSession(context, sessionId);
397
+ const { cookies, localStorage: localStorageEntries } = await fetchSessionDataViaSocket();
398
+
399
+ // Load cookies into browser context
400
+ if (cookies && cookies.length > 0) {
401
+ await context.addCookies(cookies);
402
+ logger.info({ message: 'Loaded cookies into browser session', sessionId, count: cookies.length });
403
+ }
404
+
405
+ // Inject localStorage for ALL origins using addInitScript
406
+ // This runs on EVERY page load, but only sets items that don't already exist
407
+ // This prevents overwriting user changes during the session while restoring stored data
408
+ if (localStorageEntries && localStorageEntries.length > 0) {
409
+ const localStorageByOrigin = localStorageEntries.reduce(
410
+ (acc, entry) => {
411
+ try {
412
+ const origin = new URL(entry.url).origin;
413
+ acc[origin] = entry.data;
414
+ } catch (error) {
415
+ logger.warn({ message: 'Failed to parse origin for localStorage', url: entry.url, error });
416
+ }
417
+ return acc;
418
+ },
419
+ {} as Record<string, Record<string, string>>,
420
+ );
421
+
422
+ await context.addInitScript((storageData: Record<string, Record<string, string>>) => {
423
+ const currentOrigin = window.location.origin;
424
+ const dataForOrigin = storageData[currentOrigin];
425
+
426
+ if (dataForOrigin) {
427
+ // Only set items that don't already exist (non-destructive merge)
428
+ // This preserves any changes made by the user during the current session
429
+ for (const [key, value] of Object.entries(dataForOrigin)) {
430
+ if (localStorage.getItem(key) === null) {
431
+ localStorage.setItem(key, value);
432
+ }
433
+ }
434
+ }
435
+ }, localStorageByOrigin);
436
+ }
417
437
  } catch (error) {
418
- logger.warn({ message: 'Failed to load cookies for session', sessionId, error });
438
+ logger.warn({ message: 'Failed to load session data', sessionId, error });
419
439
  }
420
- } else if (noCookies) {
421
- logger.info({ message: 'Cookies disabled via cookies=false flag', sessionId });
422
440
  }
423
441
 
424
442
  // Configure download behavior via CDP
@@ -532,12 +550,12 @@ export const withBrowserSession = async <T>(
532
550
  }
533
551
  }
534
552
 
535
- // Save cookies before destroying session (only for local mode, best-effort)
536
- if (browserTaskMode === BrowserTaskMode.LOCAL && !noCookies) {
553
+ // Save cookies and localStorage before destroying session (if persistence is enabled)
554
+ if (persistSession) {
537
555
  try {
538
- await saveCookiesForSession(context, sessionId);
556
+ await saveSessionDataViaSocket(context, page, sessionId);
539
557
  } catch (error) {
540
- logger.warn({ message: 'Failed to save cookies before session destruction', sessionId, error });
558
+ logger.warn({ message: 'Failed to save session data', sessionId, error });
541
559
  }
542
560
  }
543
561
 
@@ -545,7 +563,7 @@ export const withBrowserSession = async <T>(
545
563
  sessionId,
546
564
  localRun: browserTaskMode === BrowserTaskMode.LOCAL,
547
565
  onPrem: browserTaskMode === BrowserTaskMode.ON_PREM,
548
- }).catch(() => { });
566
+ }).catch(() => {});
549
567
  }
550
568
  };
551
569
 
@@ -1,9 +1,5 @@
1
1
  import { LLMConfig } from './LLM.types';
2
2
  import { ToolType } from './Tools.types';
3
- export interface Position {
4
- x: number;
5
- y: number;
6
- }
7
3
 
8
4
  export enum NodeType {
9
5
  TRIGGER = 'trigger',
@@ -24,7 +20,6 @@ export enum EdgeType {
24
20
  export interface BaseNode {
25
21
  name: string;
26
22
  type: NodeType;
27
- position?: Position;
28
23
  humanInTheLoop?: boolean;
29
24
  canStayOnNode?: boolean;
30
25
  displayName: string;
@@ -33,6 +33,7 @@ export interface RPATool<Input extends z.ZodSchema, Memory = any, Output extends
33
33
  proxyUser?: string; // Custom proxy username - used when proxyType is CUSTOM
34
34
  proxyPass?: string; // Custom proxy password - used when proxyType is CUSTOM
35
35
  browserTaskMode?: BrowserTaskMode; // Optional browser provider (local/cloud/onPrem)
36
+ persistSession?: boolean; // Session persistence: true (global persistence with cloud storage, default), false (no persistence)
36
37
  execute: (input: RPAToolExecuteInput<Input, Memory>) => Promise<ToolReturnType>;
37
38
  }
38
39