@isoldex/sentinel 0.1.0 → 2.0.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.
Files changed (100) hide show
  1. package/README.md +368 -62
  2. package/dist/__tests__/action-engine.test.d.ts +2 -0
  3. package/dist/__tests__/action-engine.test.d.ts.map +1 -0
  4. package/dist/__tests__/action-engine.test.js +144 -0
  5. package/dist/__tests__/action-engine.test.js.map +1 -0
  6. package/dist/__tests__/state-parser.test.d.ts +2 -0
  7. package/dist/__tests__/state-parser.test.d.ts.map +1 -0
  8. package/dist/__tests__/state-parser.test.js +176 -0
  9. package/dist/__tests__/state-parser.test.js.map +1 -0
  10. package/dist/__tests__/verifier.test.d.ts +2 -0
  11. package/dist/__tests__/verifier.test.d.ts.map +1 -0
  12. package/dist/__tests__/verifier.test.js +68 -0
  13. package/dist/__tests__/verifier.test.js.map +1 -0
  14. package/dist/__tests__/workflow-recorder.test.d.ts +2 -0
  15. package/dist/__tests__/workflow-recorder.test.d.ts.map +1 -0
  16. package/dist/__tests__/workflow-recorder.test.js +71 -0
  17. package/dist/__tests__/workflow-recorder.test.js.map +1 -0
  18. package/dist/agent/agent-loop.d.ts +36 -0
  19. package/dist/agent/agent-loop.d.ts.map +1 -0
  20. package/dist/agent/agent-loop.js +127 -0
  21. package/dist/agent/agent-loop.js.map +1 -0
  22. package/dist/agent/memory.d.ts +24 -0
  23. package/dist/agent/memory.d.ts.map +1 -0
  24. package/dist/agent/memory.js +34 -0
  25. package/dist/agent/memory.js.map +1 -0
  26. package/dist/agent/planner.d.ts +18 -0
  27. package/dist/agent/planner.d.ts.map +1 -0
  28. package/dist/agent/planner.js +68 -0
  29. package/dist/agent/planner.js.map +1 -0
  30. package/dist/api/act.d.ts +4 -2
  31. package/dist/api/act.d.ts.map +1 -1
  32. package/dist/api/act.js +174 -30
  33. package/dist/api/act.js.map +1 -1
  34. package/dist/api/extract.d.ts +2 -3
  35. package/dist/api/extract.d.ts.map +1 -1
  36. package/dist/api/extract.js +0 -1
  37. package/dist/api/extract.js.map +1 -1
  38. package/dist/api/observe.d.ts +2 -2
  39. package/dist/api/observe.d.ts.map +1 -1
  40. package/dist/api/observe.js +0 -1
  41. package/dist/api/observe.js.map +1 -1
  42. package/dist/core/driver.d.ts +21 -1
  43. package/dist/core/driver.d.ts.map +1 -1
  44. package/dist/core/driver.js +109 -19
  45. package/dist/core/driver.js.map +1 -1
  46. package/dist/core/state-parser.d.ts +1 -0
  47. package/dist/core/state-parser.d.ts.map +1 -1
  48. package/dist/core/state-parser.js +60 -0
  49. package/dist/core/state-parser.js.map +1 -1
  50. package/dist/core/vision-grounding.d.ts +36 -0
  51. package/dist/core/vision-grounding.d.ts.map +1 -0
  52. package/dist/core/vision-grounding.js +118 -0
  53. package/dist/core/vision-grounding.js.map +1 -0
  54. package/dist/index.d.ts +111 -2
  55. package/dist/index.d.ts.map +1 -1
  56. package/dist/index.js +168 -4
  57. package/dist/index.js.map +1 -1
  58. package/dist/recorder/workflow-recorder.d.ts +30 -0
  59. package/dist/recorder/workflow-recorder.d.ts.map +1 -0
  60. package/dist/recorder/workflow-recorder.js +83 -0
  61. package/dist/recorder/workflow-recorder.js.map +1 -0
  62. package/dist/reliability/verifier.d.ts +2 -2
  63. package/dist/reliability/verifier.d.ts.map +1 -1
  64. package/dist/reliability/verifier.js +0 -1
  65. package/dist/reliability/verifier.js.map +1 -1
  66. package/dist/types/errors.d.ts +45 -0
  67. package/dist/types/errors.d.ts.map +1 -0
  68. package/dist/types/errors.js +69 -0
  69. package/dist/types/errors.js.map +1 -0
  70. package/dist/utils/gemini.d.ts +3 -6
  71. package/dist/utils/gemini.d.ts.map +1 -1
  72. package/dist/utils/gemini.js +9 -94
  73. package/dist/utils/gemini.js.map +1 -1
  74. package/dist/utils/llm-provider.d.ts +28 -0
  75. package/dist/utils/llm-provider.d.ts.map +1 -0
  76. package/dist/utils/llm-provider.js +2 -0
  77. package/dist/utils/llm-provider.js.map +1 -0
  78. package/dist/utils/providers/claude-provider.d.ts +17 -0
  79. package/dist/utils/providers/claude-provider.d.ts.map +1 -0
  80. package/dist/utils/providers/claude-provider.js +49 -0
  81. package/dist/utils/providers/claude-provider.js.map +1 -0
  82. package/dist/utils/providers/gemini-provider.d.ts +14 -0
  83. package/dist/utils/providers/gemini-provider.d.ts.map +1 -0
  84. package/dist/utils/providers/gemini-provider.js +95 -0
  85. package/dist/utils/providers/gemini-provider.js.map +1 -0
  86. package/dist/utils/providers/ollama-provider.d.ts +18 -0
  87. package/dist/utils/providers/ollama-provider.d.ts.map +1 -0
  88. package/dist/utils/providers/ollama-provider.js +62 -0
  89. package/dist/utils/providers/ollama-provider.js.map +1 -0
  90. package/dist/utils/providers/openai-provider.d.ts +18 -0
  91. package/dist/utils/providers/openai-provider.d.ts.map +1 -0
  92. package/dist/utils/providers/openai-provider.js +51 -0
  93. package/dist/utils/providers/openai-provider.js.map +1 -0
  94. package/dist/utils/token-tracker.d.ts +25 -0
  95. package/dist/utils/token-tracker.d.ts.map +1 -0
  96. package/dist/utils/token-tracker.js +45 -0
  97. package/dist/utils/token-tracker.js.map +1 -0
  98. package/dist/whatsapp-test.js +58 -17
  99. package/dist/whatsapp-test.js.map +1 -1
  100. package/package.json +10 -4
@@ -1,37 +1,114 @@
1
- import { chromium } from 'playwright';
1
+ import { chromium, firefox, webkit } from 'playwright';
2
+ import * as fs from 'fs';
3
+ import * as path from 'path';
2
4
  export class SentinelDriver {
3
5
  options;
4
6
  browser = null;
5
7
  context = null;
6
- page = null;
8
+ pages = [];
9
+ activePageIndex = 0;
7
10
  cdpSession = null;
8
11
  constructor(options = { headless: false }) {
9
12
  this.options = options;
10
13
  }
11
14
  async initialize() {
12
- this.browser = await chromium.launch({
15
+ const browserType = this.options.browser ?? 'chromium';
16
+ const launcher = browserType === 'firefox' ? firefox : browserType === 'webkit' ? webkit : chromium;
17
+ const launchArgs = browserType === 'chromium'
18
+ ? ['--disable-blink-features=AutomationControlled', '--no-sandbox', '--disable-dev-shm-usage']
19
+ : [];
20
+ this.browser = await launcher.launch({
13
21
  headless: this.options.headless ?? false,
14
- args: [
15
- '--disable-blink-features=AutomationControlled',
16
- '--no-sandbox',
17
- '--disable-dev-shm-usage',
18
- ],
22
+ args: launchArgs,
23
+ ...(this.options.proxy ? { proxy: this.options.proxy } : {}),
19
24
  });
25
+ // Load storageState from session file if provided
26
+ const storageState = this.options.sessionPath && fs.existsSync(this.options.sessionPath)
27
+ ? JSON.parse(fs.readFileSync(this.options.sessionPath, 'utf-8'))
28
+ : undefined;
20
29
  this.context = await this.browser.newContext({
21
30
  viewport: this.options.viewport || { width: 1280, height: 720 },
22
- userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36',
31
+ userAgent: this.getRandomUserAgent(),
23
32
  locale: 'de-AT',
24
33
  timezoneId: 'Europe/Vienna',
34
+ ...(storageState ? { storageState } : {}),
25
35
  });
26
- this.page = await this.context.newPage();
27
- this.cdpSession = await this.page.context().newCDPSession(this.page);
28
- // Enable Accessibility tree access via CDP
29
- await this.cdpSession.send('Accessibility.enable');
36
+ if (storageState) {
37
+ console.log(`[Driver] Session loaded from ${this.options.sessionPath}`);
38
+ }
39
+ const page = await this.context.newPage();
40
+ this.pages = [page];
41
+ this.activePageIndex = 0;
42
+ // CDP only available for Chromium
43
+ if (browserType === 'chromium') {
44
+ this.cdpSession = await page.context().newCDPSession(page);
45
+ await this.cdpSession.send('Accessibility.enable');
46
+ }
47
+ }
48
+ // ─── Tab Management ───────────────────────────────────────────────────────
49
+ async newTab(url) {
50
+ if (!this.context)
51
+ throw new Error('Driver not initialized');
52
+ const page = await this.context.newPage();
53
+ this.pages.push(page);
54
+ const index = this.pages.length - 1;
55
+ if (url) {
56
+ await this.gotoPage(page, url);
57
+ }
58
+ console.log(`[Driver] New tab opened (index ${index})`);
59
+ return index;
60
+ }
61
+ async switchTab(index) {
62
+ if (!this.pages[index])
63
+ throw new Error(`Tab ${index} does not exist`);
64
+ this.activePageIndex = index;
65
+ await this.pages[index].bringToFront();
66
+ // Re-attach CDP session for new active page (Chromium only)
67
+ if (this.options.browser !== 'firefox' && this.options.browser !== 'webkit') {
68
+ this.cdpSession = await this.pages[index].context().newCDPSession(this.pages[index]);
69
+ await this.cdpSession.send('Accessibility.enable');
70
+ }
71
+ console.log(`[Driver] Switched to tab ${index}`);
72
+ }
73
+ async closeTab(index) {
74
+ if (!this.pages[index])
75
+ throw new Error(`Tab ${index} does not exist`);
76
+ await this.pages[index].close();
77
+ this.pages.splice(index, 1);
78
+ if (this.activePageIndex >= this.pages.length) {
79
+ this.activePageIndex = Math.max(0, this.pages.length - 1);
80
+ }
81
+ console.log(`[Driver] Tab ${index} closed`);
82
+ }
83
+ get tabCount() {
84
+ return this.pages.length;
30
85
  }
86
+ // ─── Session Persistence ──────────────────────────────────────────────────
87
+ async saveSession(filePath) {
88
+ if (!this.context)
89
+ throw new Error('Driver not initialized');
90
+ const state = await this.context.storageState();
91
+ const dir = path.dirname(filePath);
92
+ if (!fs.existsSync(dir))
93
+ fs.mkdirSync(dir, { recursive: true });
94
+ fs.writeFileSync(filePath, JSON.stringify(state, null, 2), 'utf-8');
95
+ console.log(`[Driver] Session saved to ${filePath}`);
96
+ }
97
+ async hasLoginForm() {
98
+ const page = this.getPage();
99
+ const loginIndicators = await page.evaluate(() => {
100
+ const inputs = Array.from(document.querySelectorAll('input'));
101
+ return inputs.some(i => i.type === 'password' ||
102
+ i.name?.toLowerCase().includes('password') ||
103
+ i.id?.toLowerCase().includes('password'));
104
+ });
105
+ return loginIndicators;
106
+ }
107
+ // ─── Accessors ────────────────────────────────────────────────────────────
31
108
  getPage() {
32
- if (!this.page)
109
+ if (!this.pages[this.activePageIndex])
33
110
  throw new Error('Driver not initialized');
34
- return this.page;
111
+ return this.pages[this.activePageIndex];
35
112
  }
36
113
  getContext() {
37
114
  if (!this.context)
@@ -40,7 +117,7 @@ export class SentinelDriver {
40
117
  }
41
118
  getCDPSession() {
42
119
  if (!this.cdpSession)
43
- throw new Error('Driver not initialized');
120
+ throw new Error('CDP session not available (only supported on Chromium)');
44
121
  return this.cdpSession;
45
122
  }
46
123
  async close() {
@@ -49,13 +126,26 @@ export class SentinelDriver {
49
126
  }
50
127
  }
51
128
  async goto(url) {
52
- const page = this.getPage();
53
- // Use domcontentloaded as primary – faster and sufficient for most pages
129
+ await this.gotoPage(this.getPage(), url);
130
+ }
131
+ // ─── Internal helpers ─────────────────────────────────────────────────────
132
+ async gotoPage(page, url) {
54
133
  await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 30000 });
55
- // Then wait for network to settle (SPA content), but don't crash if it times out
56
134
  await page.waitForLoadState('networkidle', { timeout: 5000 }).catch(() => {
57
135
  console.warn(`[Driver] networkidle timeout for ${url} – proceeding anyway`);
58
136
  });
137
+ if (this.options.humanLike) {
138
+ await page.waitForTimeout(300 + Math.random() * 700);
139
+ }
140
+ }
141
+ getRandomUserAgent() {
142
+ const agents = [
143
+ 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36',
144
+ 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36',
145
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36',
146
+ 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:125.0) Gecko/20100101 Firefox/125.0',
147
+ ];
148
+ return agents[Math.floor(Math.random() * agents.length)];
59
149
  }
60
150
  }
61
151
  //# sourceMappingURL=driver.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"driver.js","sourceRoot":"","sources":["../../src/core/driver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAQtC,MAAM,OAAO,cAAc;IAML;IALZ,OAAO,GAAmB,IAAI,CAAC;IAC/B,OAAO,GAA0B,IAAI,CAAC;IACtC,IAAI,GAAgB,IAAI,CAAC;IACzB,UAAU,GAAsB,IAAI,CAAC;IAE7C,YAAoB,UAAyB,EAAE,QAAQ,EAAE,KAAK,EAAE;QAA5C,YAAO,GAAP,OAAO,CAAqC;IAAG,CAAC;IAEpE,KAAK,CAAC,UAAU;QACd,IAAI,CAAC,OAAO,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC;YACnC,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,QAAQ,IAAI,KAAK;YACxC,IAAI,EAAE;gBACJ,+CAA+C;gBAC/C,cAAc;gBACd,yBAAyB;aAC1B;SACF,CAAC,CAAC;QAEH,IAAI,CAAC,OAAO,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC;YAC3C,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,QAAQ,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE;YAC/D,SAAS,EACP,iHAAiH;YACnH,MAAM,EAAE,OAAO;YACf,UAAU,EAAE,eAAe;SAC5B,CAAC,CAAC;QAEH,IAAI,CAAC,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;QACzC,IAAI,CAAC,UAAU,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAErE,2CAA2C;QAC3C,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;IACrD,CAAC;IAED,OAAO;QACL,IAAI,CAAC,IAAI,CAAC,IAAI;YAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;QAC1D,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;IAED,UAAU;QACR,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;QAC7D,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,aAAa;QACX,IAAI,CAAC,IAAI,CAAC,UAAU;YAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;QAChE,OAAO,IAAI,CAAC,UAAU,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QAC7B,CAAC;IACH,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,GAAW;QACpB,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;QAE5B,yEAAyE;QACzE,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,kBAAkB,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QAExE,iFAAiF;QACjF,MAAM,IAAI,CAAC,gBAAgB,CAAC,aAAa,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE;YACvE,OAAO,CAAC,IAAI,CAAC,oCAAoC,GAAG,sBAAsB,CAAC,CAAC;QAC9E,CAAC,CAAC,CAAC;IACL,CAAC;CACF"}
1
+ {"version":3,"file":"driver.js","sourceRoot":"","sources":["../../src/core/driver.ts"],"names":[],"mappings":"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"}
@@ -32,6 +32,7 @@ export declare class StateParser {
32
32
  constructor(page: Page, cdp: CDPSession);
33
33
  invalidateCache(): void;
34
34
  parse(): Promise<SimplifiedState>;
35
+ private parseDOMSnapshot;
35
36
  private isInteractive;
36
37
  private nodeToUIElement;
37
38
  }
@@ -1 +1 @@
1
- {"version":3,"file":"state-parser.d.ts","sourceRoot":"","sources":["../../src/core/state-parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEnD,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kBAAkB,EAAE;QAClB,CAAC,EAAE,MAAM,CAAC;QACV,CAAC,EAAE,MAAM,CAAC;QACV,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,KAAK,CAAC,EAAE;QACN,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,MAAM,CAAC,EAAE,OAAO,CAAC;QACjB,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;KAC7B,CAAC;CACH;AAED,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,SAAS,EAAE,CAAC;CACvB;AAID,qBAAa,WAAW;IAKV,OAAO,CAAC,IAAI;IAAQ,OAAO,CAAC,GAAG;IAJ3C,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,WAAW,CAAgC;IACnD,OAAO,CAAC,cAAc,CAAK;gBAEP,IAAI,EAAE,IAAI,EAAU,GAAG,EAAE,UAAU;IAEvD,eAAe;IAKT,KAAK,IAAI,OAAO,CAAC,eAAe,CAAC;IAwDvC,OAAO,CAAC,aAAa;IAerB,OAAO,CAAC,eAAe;CA8BxB"}
1
+ {"version":3,"file":"state-parser.d.ts","sourceRoot":"","sources":["../../src/core/state-parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEnD,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kBAAkB,EAAE;QAClB,CAAC,EAAE,MAAM,CAAC;QACV,CAAC,EAAE,MAAM,CAAC;QACV,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,KAAK,CAAC,EAAE;QACN,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,MAAM,CAAC,EAAE,OAAO,CAAC;QACjB,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;KAC7B,CAAC;CACH;AAED,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,SAAS,EAAE,CAAC;CACvB;AAID,qBAAa,WAAW;IAKV,OAAO,CAAC,IAAI;IAAQ,OAAO,CAAC,GAAG;IAJ3C,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,WAAW,CAAgC;IACnD,OAAO,CAAC,cAAc,CAAK;gBAEP,IAAI,EAAE,IAAI,EAAU,GAAG,EAAE,UAAU;IAEvD,eAAe;IAKT,KAAK,IAAI,OAAO,CAAC,eAAe,CAAC;YAmEzB,gBAAgB;IA0D9B,OAAO,CAAC,aAAa;IAerB,OAAO,CAAC,eAAe;CA8BxB"}
@@ -45,6 +45,16 @@ export class StateParser {
45
45
  element.boundingClientRect = { x, y, width, height };
46
46
  uiElements.push(element);
47
47
  }
48
+ // DOM-Snapshot als Fallback wenn AOM zu wenige Elemente liefert (z.B. SPAs wie WhatsApp)
49
+ if (uiElements.length < 5) {
50
+ const domElements = await this.parseDOMSnapshot();
51
+ const existingNames = new Set(uiElements.map(e => e.name));
52
+ for (const el of domElements) {
53
+ if (!existingNames.has(el.name)) {
54
+ uiElements.push(el);
55
+ }
56
+ }
57
+ }
48
58
  const state = {
49
59
  url: this.page.url(),
50
60
  title: await this.page.title(),
@@ -54,6 +64,56 @@ export class StateParser {
54
64
  this.cacheTimestamp = Date.now();
55
65
  return state;
56
66
  }
67
+ async parseDOMSnapshot() {
68
+ const rawElements = await this.page.evaluate(() => {
69
+ const results = [];
70
+ const seen = new Set();
71
+ const candidates = Array.from(document.querySelectorAll('a, button, input, select, textarea, [role], [data-testid], [title], [aria-label], [onclick]'));
72
+ const MAX_ELEMENTS = 200;
73
+ const viewportWidth = window.innerWidth;
74
+ const viewportHeight = window.innerHeight;
75
+ for (const el of candidates) {
76
+ if (results.length >= MAX_ELEMENTS)
77
+ break;
78
+ const htmlEl = el;
79
+ const rect = htmlEl.getBoundingClientRect();
80
+ if (rect.width < 5 || rect.height < 5)
81
+ continue;
82
+ if (rect.top < 0 || rect.left < 0)
83
+ continue;
84
+ if (rect.left >= viewportWidth || rect.top >= viewportHeight)
85
+ continue;
86
+ const name = htmlEl.getAttribute('aria-label') ||
87
+ htmlEl.getAttribute('title') ||
88
+ htmlEl.getAttribute('data-testid') ||
89
+ htmlEl.getAttribute('placeholder') ||
90
+ htmlEl.textContent?.trim().slice(0, 80) ||
91
+ '';
92
+ if (!name)
93
+ continue;
94
+ const key = `${name}|${Math.round(rect.x)}|${Math.round(rect.y)}`;
95
+ if (seen.has(key))
96
+ continue;
97
+ seen.add(key);
98
+ results.push({
99
+ tag: htmlEl.tagName.toLowerCase(),
100
+ role: htmlEl.getAttribute('role') || htmlEl.tagName.toLowerCase(),
101
+ name,
102
+ x: rect.x,
103
+ y: rect.y,
104
+ width: rect.width,
105
+ height: rect.height,
106
+ });
107
+ }
108
+ return results;
109
+ });
110
+ return rawElements.map((el) => ({
111
+ id: this.elementCounter++,
112
+ role: el.role,
113
+ name: el.name,
114
+ boundingClientRect: { x: el.x, y: el.y, width: el.width, height: el.height },
115
+ }));
116
+ }
57
117
  isInteractive(node) {
58
118
  const interactiveRoles = [
59
119
  // Standard form controls
@@ -1 +1 @@
1
- {"version":3,"file":"state-parser.js","sourceRoot":"","sources":["../../src/core/state-parser.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"state-parser.js","sourceRoot":"","sources":["../../src/core/state-parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ import type { Page } from 'playwright';
2
+ export interface BoundingBox {
3
+ x: number;
4
+ y: number;
5
+ width: number;
6
+ height: number;
7
+ }
8
+ export interface VisionElement {
9
+ description: string;
10
+ boundingBox: BoundingBox;
11
+ confidence: number;
12
+ }
13
+ /**
14
+ * Vision-based element grounding using Gemini's multimodal capabilities.
15
+ * Used as a fallback when the AOM (Accessibility Tree) cannot find an element.
16
+ */
17
+ export declare class VisionGrounding {
18
+ private genAI;
19
+ private model;
20
+ constructor(apiKey: string);
21
+ /**
22
+ * Takes a screenshot of the current page and returns it as a base64 PNG buffer.
23
+ */
24
+ takeScreenshot(page: Page): Promise<Buffer>;
25
+ /**
26
+ * Asks Gemini Vision to find an element matching the instruction and return its bounding box.
27
+ * Returns null if the element cannot be found.
28
+ */
29
+ findElement(instruction: string, screenshot: Buffer, viewportWidth: number, viewportHeight: number): Promise<BoundingBox | null>;
30
+ /**
31
+ * Describes the current page visually using Gemini Vision.
32
+ * Useful for debugging and agent context building.
33
+ */
34
+ describeScreen(screenshot: Buffer): Promise<string>;
35
+ }
36
+ //# sourceMappingURL=vision-grounding.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vision-grounding.d.ts","sourceRoot":"","sources":["../../src/core/vision-grounding.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAGvC,MAAM,WAAW,WAAW;IAC1B,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,WAAW,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,KAAK,CAAqB;IAClC,OAAO,CAAC,KAAK,CAAM;gBAEP,MAAM,EAAE,MAAM;IAO1B;;OAEG;IACG,cAAc,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC;IAIjD;;;OAGG;IACG,WAAW,CACf,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,aAAa,EAAE,MAAM,EACrB,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAsE9B;;;OAGG;IACG,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAuB1D"}
@@ -0,0 +1,118 @@
1
+ import { GoogleGenerativeAI } from '@google/generative-ai';
2
+ /**
3
+ * Vision-based element grounding using Gemini's multimodal capabilities.
4
+ * Used as a fallback when the AOM (Accessibility Tree) cannot find an element.
5
+ */
6
+ export class VisionGrounding {
7
+ genAI;
8
+ model;
9
+ constructor(apiKey) {
10
+ this.genAI = new GoogleGenerativeAI(apiKey);
11
+ const modelName = process.env.GEMINI_VERSION;
12
+ if (!modelName)
13
+ throw new Error('GEMINI_VERSION must be set in .env');
14
+ this.model = this.genAI.getGenerativeModel({ model: modelName });
15
+ }
16
+ /**
17
+ * Takes a screenshot of the current page and returns it as a base64 PNG buffer.
18
+ */
19
+ async takeScreenshot(page) {
20
+ return await page.screenshot({ type: 'png', fullPage: false });
21
+ }
22
+ /**
23
+ * Asks Gemini Vision to find an element matching the instruction and return its bounding box.
24
+ * Returns null if the element cannot be found.
25
+ */
26
+ async findElement(instruction, screenshot, viewportWidth, viewportHeight) {
27
+ const base64 = screenshot.toString('base64');
28
+ const prompt = `
29
+ You are a browser automation assistant analyzing a screenshot.
30
+
31
+ Task: Find the UI element that matches this instruction: "${instruction}"
32
+
33
+ The screenshot is ${viewportWidth}x${viewportHeight} pixels.
34
+
35
+ Return the bounding box of the element as JSON with these fields:
36
+ - x: left edge in pixels
37
+ - y: top edge in pixels
38
+ - width: element width in pixels
39
+ - height: element height in pixels
40
+ - found: true if element was found, false if not visible
41
+
42
+ Be precise. If the element is not visible in the screenshot, set found to false.
43
+ `;
44
+ const schema = {
45
+ type: 'object',
46
+ properties: {
47
+ found: { type: 'boolean' },
48
+ x: { type: 'number' },
49
+ y: { type: 'number' },
50
+ width: { type: 'number' },
51
+ height: { type: 'number' },
52
+ reasoning: { type: 'string' },
53
+ },
54
+ required: ['found', 'reasoning'],
55
+ };
56
+ try {
57
+ const result = await this.model.generateContent({
58
+ contents: [
59
+ {
60
+ role: 'user',
61
+ parts: [
62
+ { text: prompt },
63
+ { inlineData: { mimeType: 'image/png', data: base64 } },
64
+ ],
65
+ },
66
+ ],
67
+ generationConfig: {
68
+ responseMimeType: 'application/json',
69
+ responseSchema: schema,
70
+ },
71
+ });
72
+ const parsed = JSON.parse(result.response.text());
73
+ if (!parsed.found) {
74
+ console.warn(`[Vision] Element not found: "${instruction}" — ${parsed.reasoning}`);
75
+ return null;
76
+ }
77
+ console.log(`[Vision] Found element: "${instruction}" at (${parsed.x}, ${parsed.y}) — ${parsed.reasoning}`);
78
+ return {
79
+ x: parsed.x ?? 0,
80
+ y: parsed.y ?? 0,
81
+ width: parsed.width ?? 50,
82
+ height: parsed.height ?? 30,
83
+ };
84
+ }
85
+ catch (err) {
86
+ console.error(`[Vision] findElement failed: ${err.message}`);
87
+ return null;
88
+ }
89
+ }
90
+ /**
91
+ * Describes the current page visually using Gemini Vision.
92
+ * Useful for debugging and agent context building.
93
+ */
94
+ async describeScreen(screenshot) {
95
+ const base64 = screenshot.toString('base64');
96
+ try {
97
+ const result = await this.model.generateContent({
98
+ contents: [
99
+ {
100
+ role: 'user',
101
+ parts: [
102
+ {
103
+ text: 'Describe this webpage screenshot briefly: what page is it, what are the main UI elements visible, and what actions are possible?',
104
+ },
105
+ { inlineData: { mimeType: 'image/png', data: base64 } },
106
+ ],
107
+ },
108
+ ],
109
+ });
110
+ return result.response.text();
111
+ }
112
+ catch (err) {
113
+ console.error(`[Vision] describeScreen failed: ${err.message}`);
114
+ return 'Could not describe screen.';
115
+ }
116
+ }
117
+ }
118
+ //# sourceMappingURL=vision-grounding.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vision-grounding.js","sourceRoot":"","sources":["../../src/core/vision-grounding.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,10 +1,25 @@
1
+ import { EventEmitter } from 'events';
1
2
  import type { Page, BrowserContext } from 'playwright';
3
+ import type { BrowserType, ProxyOptions } from './core/driver.js';
4
+ export type { BrowserType, ProxyOptions };
2
5
  import type { ActOptions, ActionResult } from './api/act.js';
3
6
  import type { ObserveResult } from './api/observe.js';
4
7
  import type { SchemaInput } from './utils/gemini.js';
8
+ import type { AgentRunOptions, AgentResult, AgentStepEvent } from './agent/agent-loop.js';
9
+ import type { BoundingBox } from './core/vision-grounding.js';
10
+ import type { LLMProvider } from './utils/llm-provider.js';
11
+ export type { LLMProvider };
12
+ import type { RecordedWorkflow } from './recorder/workflow-recorder.js';
13
+ import { SentinelError, ActionError, ExtractionError, NavigationError, AgentError, NotInitializedError } from './types/errors.js';
14
+ export { SentinelError, ActionError, ExtractionError, NavigationError, AgentError, NotInitializedError };
15
+ export type { RecordedWorkflow };
16
+ export { GeminiProvider } from './utils/providers/gemini-provider.js';
17
+ export { OpenAIProvider } from './utils/providers/openai-provider.js';
18
+ export { ClaudeProvider } from './utils/providers/claude-provider.js';
19
+ export { OllamaProvider } from './utils/providers/ollama-provider.js';
5
20
  import { z } from 'zod';
6
21
  export { z };
7
- export type { ActOptions, ActionResult, ObserveResult };
22
+ export type { ActOptions, ActionResult, ObserveResult, AgentRunOptions, AgentResult, AgentStepEvent, BoundingBox };
8
23
  export interface SentinelOptions {
9
24
  /** Gemini API key */
10
25
  apiKey: string;
@@ -25,19 +40,50 @@ export interface SentinelOptions {
25
40
  * Set to false to always fetch a fresh AOM state.
26
41
  */
27
42
  enableCaching?: boolean;
43
+ /**
44
+ * Enable Vision Grounding fallback via Gemini Vision when AOM cannot find an element (default: false).
45
+ */
46
+ visionFallback?: boolean;
47
+ /**
48
+ * Browser engine to use (default: 'chromium'). Firefox and WebKit do not support CDP/AOM.
49
+ */
50
+ browser?: BrowserType;
51
+ /**
52
+ * Proxy configuration.
53
+ */
54
+ proxy?: ProxyOptions;
55
+ /**
56
+ * Add random human-like delays between actions (default: false).
57
+ */
58
+ humanLike?: boolean;
59
+ /**
60
+ * Path to a session file to load/save cookies & storage state.
61
+ */
62
+ sessionPath?: string;
63
+ /**
64
+ * Custom LLM provider. If set, overrides the default Gemini provider.
65
+ * @example new OpenAIProvider({ apiKey: '...', model: 'gpt-4o' })
66
+ */
67
+ provider?: LLMProvider;
28
68
  /**
29
69
  * How long (ms) to wait for the DOM to settle after navigation/actions (default: 3000).
30
70
  */
31
71
  domSettleTimeoutMs?: number;
32
72
  }
33
- export declare class Sentinel {
73
+ export declare class Sentinel extends EventEmitter {
34
74
  private driver;
35
75
  private stateParser;
36
76
  private actionEngine;
37
77
  private extractionEngine;
38
78
  private observationEngine;
39
79
  private verifier;
80
+ private agentLoop;
81
+ private visionGrounding;
82
+ private recorder;
83
+ private tokenTracker;
40
84
  private gemini;
85
+ private readonly visionFallback;
86
+ private readonly apiKey;
41
87
  private readonly verbose;
42
88
  private readonly enableCaching;
43
89
  private readonly domSettleTimeoutMs;
@@ -49,6 +95,26 @@ export declare class Sentinel {
49
95
  init(): Promise<void>;
50
96
  goto(url: string): Promise<void>;
51
97
  close(): Promise<void>;
98
+ /** Start recording all actions into a replayable workflow. */
99
+ startRecording(name?: string): void;
100
+ /** Stop recording and return the captured workflow. */
101
+ stopRecording(): RecordedWorkflow;
102
+ /** Export a recorded workflow as TypeScript code. */
103
+ exportWorkflowAsCode(workflow: RecordedWorkflow): string;
104
+ /** Export a recorded workflow as JSON string. */
105
+ exportWorkflowAsJSON(workflow: RecordedWorkflow): string;
106
+ /** Replay a recorded workflow step by step. */
107
+ replay(workflow: RecordedWorkflow): Promise<void>;
108
+ /** Get accumulated token usage and estimated cost. */
109
+ getTokenUsage(): {
110
+ totalInputTokens: number;
111
+ totalOutputTokens: number;
112
+ totalTokens: number;
113
+ estimatedCostUsd: number;
114
+ entries: import("./utils/token-tracker.js").TokenUsageEntry[];
115
+ };
116
+ /** Export token usage log as JSON to a file path. */
117
+ exportLogs(filePath: string): void;
52
118
  /**
53
119
  * Perform an action on the page described in natural language.
54
120
  *
@@ -80,6 +146,49 @@ export declare class Sentinel {
80
146
  * const actions = await sentinel.observe('Find login-related elements');
81
147
  */
82
148
  observe(instruction?: string): Promise<ObserveResult[]>;
149
+ /**
150
+ * Save the current browser session (cookies, localStorage) to a JSON file.
151
+ */
152
+ saveSession(filePath: string): Promise<void>;
153
+ /**
154
+ * Open a new browser tab, optionally navigating to a URL.
155
+ * @returns The index of the new tab.
156
+ */
157
+ newTab(url?: string): Promise<number>;
158
+ /**
159
+ * Switch to a tab by index.
160
+ */
161
+ switchTab(index: number): Promise<void>;
162
+ /**
163
+ * Close a tab by index.
164
+ */
165
+ closeTab(index: number): Promise<void>;
166
+ /** Number of open tabs */
167
+ get tabCount(): number;
168
+ /**
169
+ * Check if the current page has a login form.
170
+ */
171
+ hasLoginForm(): Promise<boolean>;
172
+ /**
173
+ * Take a screenshot of the current page.
174
+ * @returns PNG image as a Buffer
175
+ */
176
+ screenshot(): Promise<Buffer>;
177
+ /**
178
+ * Describe the current page visually using Gemini Vision.
179
+ * Requires visionFallback: true in SentinelOptions.
180
+ */
181
+ describeScreen(): Promise<string>;
182
+ /**
183
+ * Run an autonomous multi-step agent to achieve a high-level goal.
184
+ *
185
+ * @param goal Natural language goal, e.g. "Go to Amazon, search for laptop, extract top 5 results"
186
+ * @param options Optional: maxSteps (default 15), onStep callback
187
+ *
188
+ * @example
189
+ * const result = await sentinel.run('Search for "TypeScript" on Google and extract the first 3 results');
190
+ */
191
+ run(goal: string, options?: AgentRunOptions): Promise<AgentResult>;
83
192
  private log;
84
193
  }
85
194
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAKvD,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAG7D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEtD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,CAAC,EAAE,CAAC;AACb,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,CAAC;AAExD,MAAM,WAAW,eAAe;IAC9B,qBAAqB;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,oDAAoD;IACpD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,wCAAwC;IACxC,QAAQ,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACpB;;;OAGG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;OAEG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,qBAAa,QAAQ;IACnB,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,WAAW,CAA4B;IAC/C,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,gBAAgB,CAAiC;IACzD,OAAO,CAAC,iBAAiB,CAAkC;IAC3D,OAAO,CAAC,QAAQ,CAAyB;IACzC,OAAO,CAAC,MAAM,CAAgB;IAE9B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAY;IACpC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAU;IACxC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAS;gBAEhC,OAAO,EAAE,eAAe;IAcpC,kDAAkD;IAClD,IAAI,IAAI,IAAI,IAAI,CAEf;IAED,4DAA4D;IAC5D,IAAI,OAAO,IAAI,cAAc,CAE5B;IAIK,IAAI;IAcJ,IAAI,CAAC,GAAG,EAAE,MAAM;IAMhB,KAAK;IAOX;;;;;;;;OAQG;IACG,GAAG,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,YAAY,CAAC;IAsClG;;;;;;;;OAQG;IACG,OAAO,CAAC,CAAC,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAOzE;;;;;;;OAOG;IACG,OAAO,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;IAS7D,OAAO,CAAC,GAAG;CAKZ"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}