@agent-infra/browser 0.1.6 → 0.2.0-alpha.4

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 (186) hide show
  1. package/README.md +35 -52
  2. package/README.zh-CN.md +57 -0
  3. package/dist/actions/index.d.ts +3 -0
  4. package/dist/actions/index.d.ts.map +1 -0
  5. package/dist/actions/index.js +46 -0
  6. package/dist/actions/index.js.map +1 -0
  7. package/dist/actions/index.mjs +7 -0
  8. package/dist/actions/key-map.d.ts +28 -0
  9. package/dist/actions/key-map.d.ts.map +1 -0
  10. package/dist/actions/key-map.js +409 -0
  11. package/dist/actions/key-map.js.map +1 -0
  12. package/dist/actions/key-map.mjs +369 -0
  13. package/dist/actions/key-map.mjs.map +1 -0
  14. package/dist/actions/keyboard.d.ts +21 -0
  15. package/dist/actions/keyboard.d.ts.map +1 -0
  16. package/dist/actions/keyboard.js +196 -0
  17. package/dist/actions/keyboard.js.map +1 -0
  18. package/dist/actions/keyboard.mjs +152 -0
  19. package/dist/actions/keyboard.mjs.map +1 -0
  20. package/dist/actions/keyboard.test.d.ts +2 -0
  21. package/dist/actions/keyboard.test.d.ts.map +1 -0
  22. package/dist/actions/mouse.d.ts +19 -0
  23. package/dist/actions/mouse.d.ts.map +1 -0
  24. package/dist/actions/mouse.js +173 -0
  25. package/dist/actions/mouse.js.map +1 -0
  26. package/dist/actions/mouse.mjs +136 -0
  27. package/dist/actions/mouse.mjs.map +1 -0
  28. package/dist/browser/base.d.ts +47 -0
  29. package/dist/browser/base.d.ts.map +1 -0
  30. package/dist/browser/base.js +156 -0
  31. package/dist/browser/base.js.map +1 -0
  32. package/dist/browser/base.mjs +122 -0
  33. package/dist/browser/base.mjs.map +1 -0
  34. package/dist/browser/browser.d.ts +23 -0
  35. package/dist/browser/browser.d.ts.map +1 -0
  36. package/dist/browser/browser.js +183 -0
  37. package/dist/browser/browser.js.map +1 -0
  38. package/dist/browser/browser.mjs +149 -0
  39. package/dist/browser/browser.mjs.map +1 -0
  40. package/dist/env.d.ts +4 -0
  41. package/dist/env.d.ts.map +1 -0
  42. package/dist/env.js +96 -0
  43. package/dist/env.js.map +1 -0
  44. package/dist/env.mjs +62 -0
  45. package/dist/env.mjs.map +1 -0
  46. package/dist/index.node.d.ts +7 -0
  47. package/dist/index.node.d.ts.map +1 -0
  48. package/dist/index.node.js +106 -0
  49. package/dist/index.node.js.map +1 -0
  50. package/dist/index.node.mjs +10 -0
  51. package/dist/index.web.d.ts +7 -0
  52. package/dist/index.web.d.ts.map +1 -0
  53. package/dist/{index.js → index.web.js} +33 -20
  54. package/dist/index.web.js.map +1 -0
  55. package/dist/index.web.mjs +10 -0
  56. package/dist/injected-script/index.d.ts +3 -0
  57. package/dist/injected-script/index.d.ts.map +1 -0
  58. package/dist/injected-script/index.js +46 -0
  59. package/dist/injected-script/index.js.map +1 -0
  60. package/dist/injected-script/index.mjs +7 -0
  61. package/dist/injected-script/visibility.d.ts +2 -0
  62. package/dist/injected-script/visibility.d.ts.map +1 -0
  63. package/dist/injected-script/visibility.js +66 -0
  64. package/dist/injected-script/visibility.js.map +1 -0
  65. package/dist/injected-script/visibility.mjs +32 -0
  66. package/dist/injected-script/visibility.mjs.map +1 -0
  67. package/dist/injected-script/webdriver.d.ts +2 -0
  68. package/dist/injected-script/webdriver.d.ts.map +1 -0
  69. package/dist/injected-script/webdriver.js +71 -0
  70. package/dist/injected-script/webdriver.js.map +1 -0
  71. package/dist/injected-script/webdriver.mjs +37 -0
  72. package/dist/injected-script/webdriver.mjs.map +1 -0
  73. package/dist/polyfills/index.d.ts +2 -0
  74. package/dist/polyfills/index.d.ts.map +1 -0
  75. package/dist/polyfills/index.js +66 -0
  76. package/dist/polyfills/index.js.map +1 -0
  77. package/dist/polyfills/index.mjs +5 -0
  78. package/dist/polyfills/withResolvers.d.ts +2 -0
  79. package/dist/polyfills/withResolvers.d.ts.map +1 -0
  80. package/dist/polyfills/withResolvers.js +37 -0
  81. package/dist/polyfills/withResolvers.js.map +1 -0
  82. package/dist/polyfills/withResolvers.mjs +19 -0
  83. package/dist/polyfills/withResolvers.mjs.map +1 -0
  84. package/dist/tabs/dialog.d.ts +14 -0
  85. package/dist/tabs/dialog.d.ts.map +1 -0
  86. package/dist/tabs/dialog.js +175 -0
  87. package/dist/tabs/dialog.js.map +1 -0
  88. package/dist/tabs/dialog.mjs +141 -0
  89. package/dist/tabs/dialog.mjs.map +1 -0
  90. package/dist/tabs/index.d.ts +3 -0
  91. package/dist/tabs/index.d.ts.map +1 -0
  92. package/dist/tabs/index.js +46 -0
  93. package/dist/tabs/index.js.map +1 -0
  94. package/dist/tabs/index.mjs +7 -0
  95. package/dist/tabs/tab.d.ts +50 -0
  96. package/dist/tabs/tab.d.ts.map +1 -0
  97. package/dist/tabs/tab.js +579 -0
  98. package/dist/tabs/tab.js.map +1 -0
  99. package/dist/tabs/tab.mjs +545 -0
  100. package/dist/tabs/tab.mjs.map +1 -0
  101. package/dist/tabs/tabs.d.ts +21 -0
  102. package/dist/tabs/tabs.d.ts.map +1 -0
  103. package/dist/tabs/tabs.js +458 -0
  104. package/dist/tabs/tabs.js.map +1 -0
  105. package/dist/tabs/tabs.mjs +424 -0
  106. package/dist/tabs/tabs.mjs.map +1 -0
  107. package/dist/types/actions.d.ts +26 -0
  108. package/dist/types/actions.d.ts.map +1 -0
  109. package/dist/types/actions.js +24 -0
  110. package/dist/types/actions.js.map +1 -0
  111. package/dist/types/browser.d.ts +7 -0
  112. package/dist/types/browser.d.ts.map +1 -0
  113. package/dist/types/browser.js +24 -0
  114. package/dist/types/browser.js.map +1 -0
  115. package/dist/types/browser.mjs +4 -0
  116. package/dist/types/dialog.d.ts +7 -0
  117. package/dist/types/dialog.d.ts.map +1 -0
  118. package/dist/types/dialog.js +24 -0
  119. package/dist/types/dialog.js.map +1 -0
  120. package/dist/types/dialog.mjs +4 -0
  121. package/dist/types/env.d.ts +8 -0
  122. package/dist/types/env.d.ts.map +1 -0
  123. package/dist/{types.js → types/env.js} +1 -1
  124. package/dist/types/env.js.map +1 -0
  125. package/dist/types/env.mjs +4 -0
  126. package/dist/types/index.d.ts +6 -0
  127. package/dist/types/index.d.ts.map +1 -0
  128. package/dist/types/index.js +102 -0
  129. package/dist/types/index.js.map +1 -0
  130. package/dist/types/index.mjs +9 -0
  131. package/dist/types/tabs.d.ts +98 -0
  132. package/dist/types/tabs.d.ts.map +1 -0
  133. package/dist/types/tabs.js +48 -0
  134. package/dist/types/tabs.js.map +1 -0
  135. package/dist/types/tabs.mjs +14 -0
  136. package/dist/types/tabs.mjs.map +1 -0
  137. package/dist/utils/iife.d.ts +2 -0
  138. package/dist/utils/iife.d.ts.map +1 -0
  139. package/dist/utils/iife.js +48 -0
  140. package/dist/utils/iife.js.map +1 -0
  141. package/dist/utils/iife.mjs +14 -0
  142. package/dist/utils/iife.mjs.map +1 -0
  143. package/dist/utils/index.d.ts +4 -0
  144. package/dist/utils/index.d.ts.map +1 -0
  145. package/dist/utils/index.js +50 -0
  146. package/dist/utils/index.js.map +1 -0
  147. package/dist/utils/index.mjs +8 -0
  148. package/dist/utils/mutex.d.ts +21 -0
  149. package/dist/utils/mutex.d.ts.map +1 -0
  150. package/dist/utils/mutex.js +133 -0
  151. package/dist/utils/mutex.js.map +1 -0
  152. package/dist/utils/mutex.mjs +99 -0
  153. package/dist/utils/mutex.mjs.map +1 -0
  154. package/dist/utils/url.d.ts +7 -0
  155. package/dist/utils/url.d.ts.map +1 -0
  156. package/dist/utils/url.js +76 -0
  157. package/dist/utils/url.js.map +1 -0
  158. package/dist/utils/url.mjs +42 -0
  159. package/dist/utils/url.mjs.map +1 -0
  160. package/package.json +21 -13
  161. package/dist/base-browser.d.ts +0 -94
  162. package/dist/base-browser.d.ts.map +0 -1
  163. package/dist/base-browser.js +0 -189
  164. package/dist/base-browser.js.map +0 -1
  165. package/dist/base-browser.mjs +0 -155
  166. package/dist/base-browser.mjs.map +0 -1
  167. package/dist/index.d.ts +0 -15
  168. package/dist/index.d.ts.map +0 -1
  169. package/dist/index.js.map +0 -1
  170. package/dist/index.mjs +0 -8
  171. package/dist/local-browser.d.ts +0 -19
  172. package/dist/local-browser.d.ts.map +0 -1
  173. package/dist/local-browser.js +0 -134
  174. package/dist/local-browser.js.map +0 -1
  175. package/dist/local-browser.mjs +0 -100
  176. package/dist/local-browser.mjs.map +0 -1
  177. package/dist/remote-browser.d.ts +0 -49
  178. package/dist/remote-browser.d.ts.map +0 -1
  179. package/dist/remote-browser.js +0 -89
  180. package/dist/remote-browser.js.map +0 -1
  181. package/dist/remote-browser.mjs +0 -55
  182. package/dist/remote-browser.mjs.map +0 -1
  183. package/dist/types.d.ts +0 -158
  184. package/dist/types.d.ts.map +0 -1
  185. package/dist/types.js.map +0 -1
  186. /package/dist/{types.mjs → types/actions.mjs} +0 -0
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance, Inc. and its affiliates.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+ function _check_private_redeclaration(obj, privateCollection) {
6
+ if (privateCollection.has(obj)) throw new TypeError("Cannot initialize the same private elements twice on an object");
7
+ }
8
+ function _class_apply_descriptor_get(receiver, descriptor) {
9
+ if (descriptor.get) return descriptor.get.call(receiver);
10
+ return descriptor.value;
11
+ }
12
+ function _class_apply_descriptor_set(receiver, descriptor, value) {
13
+ if (descriptor.set) descriptor.set.call(receiver, value);
14
+ else {
15
+ if (!descriptor.writable) throw new TypeError("attempted to set read only private field");
16
+ descriptor.value = value;
17
+ }
18
+ }
19
+ function _class_extract_field_descriptor(receiver, privateMap, action) {
20
+ if (!privateMap.has(receiver)) throw new TypeError("attempted to " + action + " private field on non-instance");
21
+ return privateMap.get(receiver);
22
+ }
23
+ function _class_private_field_get(receiver, privateMap) {
24
+ var descriptor = _class_extract_field_descriptor(receiver, privateMap, "get");
25
+ return _class_apply_descriptor_get(receiver, descriptor);
26
+ }
27
+ function _class_private_field_init(obj, privateMap, value) {
28
+ _check_private_redeclaration(obj, privateMap);
29
+ privateMap.set(obj, value);
30
+ }
31
+ function _class_private_field_set(receiver, privateMap, value) {
32
+ var descriptor = _class_extract_field_descriptor(receiver, privateMap, "set");
33
+ _class_apply_descriptor_set(receiver, descriptor, value);
34
+ return value;
35
+ }
36
+ function _define_property(obj, key, value) {
37
+ if (key in obj) Object.defineProperty(obj, key, {
38
+ value: value,
39
+ enumerable: true,
40
+ configurable: true,
41
+ writable: true
42
+ });
43
+ else obj[key] = value;
44
+ return obj;
45
+ }
46
+ let _computedKey;
47
+ var _mutex, _onRelease;
48
+ var _computedKey1;
49
+ _computedKey1 = Symbol.dispose;
50
+ var _locked = /*#__PURE__*/ new WeakMap(), _acquirers = /*#__PURE__*/ new WeakMap();
51
+ class Mutex {
52
+ async acquire(onRelease) {
53
+ if (!_class_private_field_get(this, _locked)) {
54
+ _class_private_field_set(this, _locked, true);
55
+ return new Mutex.Guard(this);
56
+ }
57
+ const { promise, resolve } = Promise.withResolvers();
58
+ _class_private_field_get(this, _acquirers).push(resolve);
59
+ await promise;
60
+ return new Mutex.Guard(this, onRelease);
61
+ }
62
+ release() {
63
+ const resolve = _class_private_field_get(this, _acquirers).shift();
64
+ if (!resolve) return void _class_private_field_set(this, _locked, false);
65
+ resolve();
66
+ }
67
+ constructor(){
68
+ _class_private_field_init(this, _locked, {
69
+ writable: true,
70
+ value: false
71
+ });
72
+ _class_private_field_init(this, _acquirers, {
73
+ writable: true,
74
+ value: []
75
+ });
76
+ }
77
+ }
78
+ _define_property(Mutex, "Guard", (_mutex = /*#__PURE__*/ new WeakMap(), _onRelease = /*#__PURE__*/ new WeakMap(), _computedKey = _computedKey1, class {
79
+ [_computedKey]() {
80
+ var _this, _this1;
81
+ null == (_this = _class_private_field_get(_this1 = this, _onRelease)) || _this.call(_this1);
82
+ return _class_private_field_get(this, _mutex).release();
83
+ }
84
+ constructor(mutex, onRelease){
85
+ _class_private_field_init(this, _mutex, {
86
+ writable: true,
87
+ value: void 0
88
+ });
89
+ _class_private_field_init(this, _onRelease, {
90
+ writable: true,
91
+ value: void 0
92
+ });
93
+ _class_private_field_set(this, _mutex, mutex);
94
+ _class_private_field_set(this, _onRelease, onRelease);
95
+ }
96
+ }));
97
+ export { Mutex };
98
+
99
+ //# sourceMappingURL=mutex.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils/mutex.mjs","sources":["webpack://@agent-infra/browser/./src/utils/mutex.ts"],"sourcesContent":["/**\n * The following code is modified based on\n * https://github.com/puppeteer/puppeteer/blob/main/packages/puppeteer-core/src/util/Mutex.ts\n *\n * Copyright 2024 Google Inc.\n * SPDX-License-Identifier: Apache-2.0\n * https://github.com/puppeteer/puppeteer/blob/main/LICENSE\n */\n\nexport class Mutex {\n static Guard = class Guard {\n #mutex: Mutex;\n #onRelease?: () => void;\n constructor(mutex: Mutex, onRelease?: () => void) {\n this.#mutex = mutex;\n this.#onRelease = onRelease;\n }\n [Symbol.dispose](): void {\n this.#onRelease?.();\n return this.#mutex.release();\n }\n };\n\n #locked = false;\n #acquirers: Array<() => void> = [];\n\n // This is FIFO.\n async acquire(\n onRelease?: () => void,\n ): Promise<InstanceType<typeof Mutex.Guard>> {\n if (!this.#locked) {\n this.#locked = true;\n return new Mutex.Guard(this);\n }\n\n const { promise, resolve } = Promise.withResolvers<void>();\n this.#acquirers.push(resolve);\n await promise;\n\n return new Mutex.Guard(this, onRelease);\n }\n\n release(): void {\n const resolve = this.#acquirers.shift();\n if (!resolve) {\n this.#locked = false;\n return;\n }\n resolve();\n }\n}\n"],"names":["_mutex","_onRelease","Symbol","_locked","_acquirers","Mutex","onRelease","promise","resolve","Promise","_this1","mutex"],"mappings":";;;;AAOC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAIGA,QACAC;;gBAKCC,OAAO,OAAO;IAMjBC,UAAAA,WAAAA,GAAAA,IAAAA,WACAC,aAAAA,WAAAA,GAAAA,IAAAA;AAfK,MAAMC;IAkBX,MAAM,QACJC,SAAsB,EACqB;QAC3C,IAAI,CAAC,6BAAI,EAACH,UAAS;2CACZA,SAAU;YACf,OAAO,IAAIE,MAAM,KAAK,CAAC,IAAI;QAC7B;QAEA,MAAM,EAAEE,OAAO,EAAEC,OAAO,EAAE,GAAGC,QAAQ,aAAa;QAClD,6BAAI,EAACL,YAAW,IAAI,CAACI;QACrB,MAAMD;QAEN,OAAO,IAAIF,MAAM,KAAK,CAAC,IAAI,EAAEC;IAC/B;IAEA,UAAgB;QACd,MAAME,UAAU,6BAAI,EAACJ,YAAW,KAAK;QACrC,IAAI,CAACI,SAAS,2CACPL,SAAU;QAGjBK;IACF;;QA1BAL,0BAAAA,IAAAA,EAAAA,SAAAA;;mBAAU;;QACVC,0BAAAA,IAAAA,EAAAA,YAAAA;;mBAAgC,EAAE;;;AA0BpC;AAxCE,iBADWC,OACJ,SACLL,CAAAA,SAAAA,WAAAA,GAAAA,IAAAA,WACAC,aAAAA,WAAAA,GAAAA,IAAAA,WAAAA,eAAAA,eAFa;IAOb,CAAC,aAAD,GAAyB;YACvBS,OAAAA;gBAAAA,CAAAA,QAAAA,yBAAAA,SAAAA,IAAI,EAACT,WAAAA,KAALS,MAAAA,IAAAA,CAAAA;QACA,OAAO,6BAAI,EAACV,QAAO,OAAO;IAC5B;IAPA,YAAYW,KAAY,EAAEL,SAAsB,CAAE;QAFlDN,0BAAAA,IAAAA,EAAAA,QAAAA;;mBAAAA,KAAAA;;QACAC,0BAAAA,IAAAA,EAAAA,YAAAA;;mBAAAA,KAAAA;;uCAEOD,QAASW;uCACTV,YAAaK;IACpB;AAKF"}
@@ -0,0 +1,7 @@
1
+ export interface ValidateResult {
2
+ ignored: boolean;
3
+ url: string;
4
+ message?: string;
5
+ }
6
+ export declare function validateNavigationUrl(rawUrl: string): ValidateResult;
7
+ //# sourceMappingURL=url.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"url.d.ts","sourceRoot":"","sources":["../../src/utils/url.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAID,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,CAuCpE"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance, Inc. and its affiliates.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+ "use strict";
6
+ var __webpack_require__ = {};
7
+ (()=>{
8
+ __webpack_require__.d = (exports1, definition)=>{
9
+ for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
10
+ enumerable: true,
11
+ get: definition[key]
12
+ });
13
+ };
14
+ })();
15
+ (()=>{
16
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
17
+ })();
18
+ (()=>{
19
+ __webpack_require__.r = (exports1)=>{
20
+ if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
21
+ value: 'Module'
22
+ });
23
+ Object.defineProperty(exports1, '__esModule', {
24
+ value: true
25
+ });
26
+ };
27
+ })();
28
+ var __webpack_exports__ = {};
29
+ __webpack_require__.r(__webpack_exports__);
30
+ __webpack_require__.d(__webpack_exports__, {
31
+ validateNavigationUrl: ()=>validateNavigationUrl
32
+ });
33
+ const BlockedProtocols = [
34
+ 'chrome:',
35
+ 'chrome-extension:',
36
+ 'devtools:'
37
+ ];
38
+ function validateNavigationUrl(rawUrl) {
39
+ const original = (rawUrl || '').trim();
40
+ if (!original) return {
41
+ ignored: true,
42
+ url: original,
43
+ message: "Empty URL is ignored."
44
+ };
45
+ if (original.toLowerCase().startsWith('chrome://newtab') || original.toLowerCase().startsWith('chrome://new-tab-page')) return {
46
+ ignored: false,
47
+ url: original
48
+ };
49
+ let candidate = original;
50
+ let protocol;
51
+ try {
52
+ const parsed = new URL(candidate);
53
+ protocol = parsed.protocol;
54
+ } catch (e) {
55
+ candidate = `https://${candidate}`;
56
+ protocol = 'https:';
57
+ }
58
+ if (BlockedProtocols.includes(protocol)) return {
59
+ ignored: true,
60
+ url: candidate,
61
+ message: `The URL "${rawUrl}" is ignored because it uses the "${protocol}" protocol which accesses internal resources and may be dangerous.`
62
+ };
63
+ return {
64
+ ignored: false,
65
+ url: candidate
66
+ };
67
+ }
68
+ exports.validateNavigationUrl = __webpack_exports__.validateNavigationUrl;
69
+ for(var __webpack_i__ in __webpack_exports__)if (-1 === [
70
+ "validateNavigationUrl"
71
+ ].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
72
+ Object.defineProperty(exports, '__esModule', {
73
+ value: true
74
+ });
75
+
76
+ //# sourceMappingURL=url.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils/url.js","sources":["webpack://@agent-infra/browser/webpack/runtime/define_property_getters","webpack://@agent-infra/browser/webpack/runtime/has_own_property","webpack://@agent-infra/browser/webpack/runtime/make_namespace_object","webpack://@agent-infra/browser/./src/utils/url.ts"],"sourcesContent":["__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n }\n }\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","/*\n * Copyright (c) 2025 Bytedance, Inc. and its affiliates.\n * SPDX-License-Identifier: Apache-2.0\n */\n\nexport interface ValidateResult {\n ignored: boolean;\n url: string;\n message?: string;\n}\n\nconst BlockedProtocols = ['chrome:', 'chrome-extension:', 'devtools:'];\n\nexport function validateNavigationUrl(rawUrl: string): ValidateResult {\n const original = (rawUrl || '').trim();\n\n if (!original) {\n return {\n ignored: true,\n url: original,\n message: `Empty URL is ignored.`,\n };\n }\n\n if (\n original.toLowerCase().startsWith('chrome://newtab') ||\n original.toLowerCase().startsWith('chrome://new-tab-page')\n ) {\n return { ignored: false, url: original };\n }\n\n // parse and normalize URL\n let candidate = original;\n let protocol: string;\n try {\n const parsed = new URL(candidate);\n protocol = parsed.protocol;\n } catch (e) {\n candidate = `https://${candidate}`; // try https as default\n protocol = 'https:';\n }\n\n // BlockedProtocols check\n if (BlockedProtocols.includes(protocol)) {\n return {\n ignored: true,\n url: candidate,\n message: `The URL \"${rawUrl}\" is ignored because it uses the \"${protocol}\" protocol which accesses internal resources and may be dangerous.`,\n };\n }\n\n return { ignored: false, url: candidate };\n}\n"],"names":["__webpack_require__","definition","key","Object","obj","prop","Symbol","BlockedProtocols","validateNavigationUrl","rawUrl","original","candidate","protocol","parsed","URL","e"],"mappings":";;;;;;;IAAAA,oBAAoB,CAAC,GAAG,CAAC,UAASC;QACjC,IAAI,IAAIC,OAAOD,WACR,IAAGD,oBAAoB,CAAC,CAACC,YAAYC,QAAQ,CAACF,oBAAoB,CAAC,CAAC,UAASE,MACzEC,OAAO,cAAc,CAAC,UAASD,KAAK;YAAE,YAAY;YAAM,KAAKD,UAAU,CAACC,IAAI;QAAC;IAGzF;;;ICNAF,oBAAoB,CAAC,GAAG,CAACI,KAAKC,OAAUF,OAAO,SAAS,CAAC,cAAc,CAAC,IAAI,CAACC,KAAKC;;;ICClFL,oBAAoB,CAAC,GAAG,CAAC;QACxB,IAAG,AAAkB,eAAlB,OAAOM,UAA0BA,OAAO,WAAW,EACrDH,OAAO,cAAc,CAAC,UAASG,OAAO,WAAW,EAAE;YAAE,OAAO;QAAS;QAEtEH,OAAO,cAAc,CAAC,UAAS,cAAc;YAAE,OAAO;QAAK;IAC5D;;;;;;;ACKA,MAAMI,mBAAmB;IAAC;IAAW;IAAqB;CAAY;AAE/D,SAASC,sBAAsBC,MAAc;IAClD,MAAMC,WAAYD,AAAAA,CAAAA,UAAU,EAAC,EAAG,IAAI;IAEpC,IAAI,CAACC,UACH,OAAO;QACL,SAAS;QACT,KAAKA;QACL,SAAS;IACX;IAGF,IACEA,SAAS,WAAW,GAAG,UAAU,CAAC,sBAClCA,SAAS,WAAW,GAAG,UAAU,CAAC,0BAElC,OAAO;QAAE,SAAS;QAAO,KAAKA;IAAS;IAIzC,IAAIC,YAAYD;IAChB,IAAIE;IACJ,IAAI;QACF,MAAMC,SAAS,IAAIC,IAAIH;QACvBC,WAAWC,OAAO,QAAQ;IAC5B,EAAE,OAAOE,GAAG;QACVJ,YAAY,CAAC,QAAQ,EAAEA,WAAW;QAClCC,WAAW;IACb;IAGA,IAAIL,iBAAiB,QAAQ,CAACK,WAC5B,OAAO;QACL,SAAS;QACT,KAAKD;QACL,SAAS,CAAC,SAAS,EAAEF,OAAO,kCAAkC,EAAEG,SAAS,kEAAkE,CAAC;IAC9I;IAGF,OAAO;QAAE,SAAS;QAAO,KAAKD;IAAU;AAC1C"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Copyright (c) 2025 Bytedance, Inc. and its affiliates.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+ const BlockedProtocols = [
6
+ 'chrome:',
7
+ 'chrome-extension:',
8
+ 'devtools:'
9
+ ];
10
+ function validateNavigationUrl(rawUrl) {
11
+ const original = (rawUrl || '').trim();
12
+ if (!original) return {
13
+ ignored: true,
14
+ url: original,
15
+ message: "Empty URL is ignored."
16
+ };
17
+ if (original.toLowerCase().startsWith('chrome://newtab') || original.toLowerCase().startsWith('chrome://new-tab-page')) return {
18
+ ignored: false,
19
+ url: original
20
+ };
21
+ let candidate = original;
22
+ let protocol;
23
+ try {
24
+ const parsed = new URL(candidate);
25
+ protocol = parsed.protocol;
26
+ } catch (e) {
27
+ candidate = `https://${candidate}`;
28
+ protocol = 'https:';
29
+ }
30
+ if (BlockedProtocols.includes(protocol)) return {
31
+ ignored: true,
32
+ url: candidate,
33
+ message: `The URL "${rawUrl}" is ignored because it uses the "${protocol}" protocol which accesses internal resources and may be dangerous.`
34
+ };
35
+ return {
36
+ ignored: false,
37
+ url: candidate
38
+ };
39
+ }
40
+ export { validateNavigationUrl };
41
+
42
+ //# sourceMappingURL=url.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils/url.mjs","sources":["webpack://@agent-infra/browser/./src/utils/url.ts"],"sourcesContent":["/*\n * Copyright (c) 2025 Bytedance, Inc. and its affiliates.\n * SPDX-License-Identifier: Apache-2.0\n */\n\nexport interface ValidateResult {\n ignored: boolean;\n url: string;\n message?: string;\n}\n\nconst BlockedProtocols = ['chrome:', 'chrome-extension:', 'devtools:'];\n\nexport function validateNavigationUrl(rawUrl: string): ValidateResult {\n const original = (rawUrl || '').trim();\n\n if (!original) {\n return {\n ignored: true,\n url: original,\n message: `Empty URL is ignored.`,\n };\n }\n\n if (\n original.toLowerCase().startsWith('chrome://newtab') ||\n original.toLowerCase().startsWith('chrome://new-tab-page')\n ) {\n return { ignored: false, url: original };\n }\n\n // parse and normalize URL\n let candidate = original;\n let protocol: string;\n try {\n const parsed = new URL(candidate);\n protocol = parsed.protocol;\n } catch (e) {\n candidate = `https://${candidate}`; // try https as default\n protocol = 'https:';\n }\n\n // BlockedProtocols check\n if (BlockedProtocols.includes(protocol)) {\n return {\n ignored: true,\n url: candidate,\n message: `The URL \"${rawUrl}\" is ignored because it uses the \"${protocol}\" protocol which accesses internal resources and may be dangerous.`,\n };\n }\n\n return { ignored: false, url: candidate };\n}\n"],"names":["BlockedProtocols","validateNavigationUrl","rawUrl","original","candidate","protocol","parsed","URL","e"],"mappings":";;;;AAWA,MAAMA,mBAAmB;IAAC;IAAW;IAAqB;CAAY;AAE/D,SAASC,sBAAsBC,MAAc;IAClD,MAAMC,WAAYD,AAAAA,CAAAA,UAAU,EAAC,EAAG,IAAI;IAEpC,IAAI,CAACC,UACH,OAAO;QACL,SAAS;QACT,KAAKA;QACL,SAAS;IACX;IAGF,IACEA,SAAS,WAAW,GAAG,UAAU,CAAC,sBAClCA,SAAS,WAAW,GAAG,UAAU,CAAC,0BAElC,OAAO;QAAE,SAAS;QAAO,KAAKA;IAAS;IAIzC,IAAIC,YAAYD;IAChB,IAAIE;IACJ,IAAI;QACF,MAAMC,SAAS,IAAIC,IAAIH;QACvBC,WAAWC,OAAO,QAAQ;IAC5B,EAAE,OAAOE,GAAG;QACVJ,YAAY,CAAC,QAAQ,EAAEA,WAAW;QAClCC,WAAW;IACb;IAGA,IAAIL,iBAAiB,QAAQ,CAACK,WAC5B,OAAO;QACL,SAAS;QACT,KAAKD;QACL,SAAS,CAAC,SAAS,EAAEF,OAAO,kCAAkC,EAAEG,SAAS,kEAAkE,CAAC;IAC9I;IAGF,OAAO;QAAE,SAAS;QAAO,KAAKD;IAAU;AAC1C"}
package/package.json CHANGED
@@ -1,15 +1,20 @@
1
1
  {
2
2
  "name": "@agent-infra/browser",
3
- "description": "A tiny Browser Control library, built for Agent Tars.",
4
- "version": "0.1.6",
3
+ "description": "agent-infra browser",
4
+ "version": "0.2.0-alpha.4",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
7
7
  "types": "dist/index.d.ts",
8
8
  "exports": {
9
9
  ".": {
10
- "types": "./dist/index.d.ts",
11
- "import": "./dist/index.mjs",
12
- "require": "./dist/index.js"
10
+ "types": "./dist/index.node.d.ts",
11
+ "import": "./dist/index.node.mjs",
12
+ "require": "./dist/index.node.js"
13
+ },
14
+ "./web": {
15
+ "types": "./dist/index.web.d.ts",
16
+ "import": "./dist/index.web.mjs",
17
+ "require": "./dist/index.web.js"
13
18
  }
14
19
  },
15
20
  "files": [
@@ -23,17 +28,21 @@
23
28
  "access": "public"
24
29
  },
25
30
  "dependencies": {
26
- "puppeteer-core": "24.15.0",
27
31
  "@agent-infra/logger": "0.0.2-beta.2",
28
- "@agent-infra/shared": "0.0.2",
29
- "@agent-infra/browser-finder": "0.1.6"
32
+ "puppeteer-core": "24.23.0",
33
+ "delay": "6.0.0",
34
+ "valtio": "2.1.8",
35
+ "eventemitter3": "5.0.1",
36
+ "@agent-infra/browser-finder": "0.2.0-alpha.4",
37
+ "@agent-infra/media-utils": "0.2.0-alpha.4"
30
38
  },
31
39
  "devDependencies": {
32
- "@types/node": "24.1.0",
33
- "typescript": "5.8.3",
40
+ "@types/node": "24.7.1",
41
+ "@types/eventemitter3": "2.0.4",
42
+ "typescript": "5.9.3",
34
43
  "vitest": "3.2.4",
35
44
  "@vitest/coverage-v8": "3.2.4",
36
- "@rslib/core": "0.11.0"
45
+ "@rslib/core": "0.15.0"
37
46
  },
38
47
  "scripts": {
39
48
  "dev": "rslib build --watch",
@@ -41,7 +50,6 @@
41
50
  "test": "vitest run",
42
51
  "test:watch": "vitest",
43
52
  "test:e2e": "vitest --config vitest.e2e.config.ts",
44
- "coverage": "vitest run --coverage",
45
- "test:e2e:local": "vitest --config vitest.e2e.config.ts local-browser.e2e.test.ts"
53
+ "coverage": "vitest run --coverage"
46
54
  }
47
55
  }
@@ -1,94 +0,0 @@
1
- import * as puppeteer from 'puppeteer-core';
2
- import { Logger } from '@agent-infra/logger';
3
- import { BrowserInterface, EvaluateOnNewPageOptions, LaunchOptions, Page } from './types';
4
- /**
5
- * Configuration options for the BaseBrowser class
6
- * @interface BaseBrowserOptions
7
- * @property {Logger} [logger] - Custom logger instance to use for browser logging
8
- */
9
- export interface BaseBrowserOptions {
10
- logger?: Logger;
11
- }
12
- /**
13
- * Abstract base class that implements common browser automation functionality
14
- * Provides a foundation for specific browser implementations with shared capabilities
15
- * @abstract
16
- * @implements {BrowserInterface}
17
- */
18
- export declare abstract class BaseBrowser implements BrowserInterface {
19
- /**
20
- * The underlying Puppeteer browser instance
21
- * @protected
22
- */
23
- protected browser: puppeteer.Browser | null;
24
- /**
25
- * Logger instance for browser-related logging
26
- * @protected
27
- */
28
- protected logger: Logger;
29
- /**
30
- * Reference to the currently active browser page
31
- * @protected
32
- */
33
- protected activePage: Page | null;
34
- /**
35
- * Creates an instance of BaseBrowser
36
- * @param {BaseBrowserOptions} [options] - Configuration options
37
- */
38
- constructor(options?: BaseBrowserOptions);
39
- /**
40
- * Check if the browser instance is active and responding
41
- * @returns {Promise<boolean>} True if browser is active, false otherwise
42
- */
43
- isBrowserAlive(): Promise<boolean>;
44
- /**
45
- * Get the underlying Puppeteer browser instance
46
- * @throws Error if browser is not launched
47
-
48
- * @returns {puppeteer.Browser} Puppeteer browser instance
49
- */
50
- getBrowser(): puppeteer.Browser;
51
- /**
52
- * Sets up listeners for browser page events
53
- * Tracks page creation and updates active page reference
54
- * @protected
55
- */
56
- protected setupPageListener(): Promise<void>;
57
- /**
58
- * Launches the browser with specified options
59
- * @abstract
60
- * @param {LaunchOptions} [options] - Browser launch configuration options
61
- * @returns {Promise<void>} Promise that resolves when browser is launched
62
- */
63
- abstract launch(options?: LaunchOptions): Promise<void>;
64
- /**
65
- * Closes the browser instance and cleans up resources
66
- * @returns {Promise<void>} Promise that resolves when browser is closed
67
- * @throws {Error} If browser fails to close properly
68
- */
69
- close(): Promise<void>;
70
- /**
71
- * Creates a new page, navigates to the specified URL, executes a function in the page context, and returns the result
72
- * This method is inspired and modified from https://github.com/egoist/local-web-search/blob/04608ed09aa103e2fff6402c72ca12edfb692d19/src/browser.ts#L74
73
- * @template T - Type of parameters passed to the page function
74
- * @template R - Return type of the page function
75
- * @param {EvaluateOnNewPageOptions<T, R>} options - Configuration options for the page evaluation
76
- * @returns {Promise<R | null>} Promise resolving to the result of the page function or null
77
- * @throws {Error} If page creation or evaluation fails
78
- */
79
- evaluateOnNewPage<T extends any[], R>(options: EvaluateOnNewPageOptions<T, R>): Promise<R | null>;
80
- /**
81
- * Creates a new browser page
82
- * @returns {Promise<Page>} Promise resolving to the newly created page
83
- * @throws {Error} If browser is not launched or page creation fails
84
- */
85
- createPage(): Promise<Page>;
86
- /**
87
- * Gets the currently active page or finds an active page if none is currently tracked
88
- * If no active pages exist, creates a new page
89
- * @returns {Promise<Page>} Promise resolving to the active page
90
- * @throws {Error} If browser is not launched or no active page can be found/created
91
- */
92
- getActivePage(): Promise<Page>;
93
- }
94
- //# sourceMappingURL=base-browser.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"base-browser.d.ts","sourceRoot":"","sources":["../src/base-browser.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,SAAS,MAAM,gBAAgB,CAAC;AAC5C,OAAO,EAAE,MAAM,EAAiB,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EACL,gBAAgB,EAChB,wBAAwB,EACxB,aAAa,EACb,IAAI,EACL,MAAM,SAAS,CAAC;AAEjB;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,8BAAsB,WAAY,YAAW,gBAAgB;IAC3D;;;OAGG;IACH,SAAS,CAAC,OAAO,EAAE,SAAS,CAAC,OAAO,GAAG,IAAI,CAAQ;IAEnD;;;OAGG;IACH,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC;IAEzB;;;OAGG;IACH,SAAS,CAAC,UAAU,EAAE,IAAI,GAAG,IAAI,CAAQ;IAEzC;;;OAGG;gBACS,OAAO,CAAC,EAAE,kBAAkB;IAKxC;;;OAGG;IACG,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC;IAiBxC;;;;;OAKG;IACH,UAAU,IAAI,SAAS,CAAC,OAAO;IAO/B;;;;OAIG;cACa,iBAAiB;IAwDjC;;;;;OAKG;IACH,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAEvD;;;;OAIG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAY5B;;;;;;;;OAQG;IACG,iBAAiB,CAAC,CAAC,SAAS,GAAG,EAAE,EAAE,CAAC,EACxC,OAAO,EAAE,wBAAwB,CAAC,CAAC,EAAE,CAAC,CAAC,GACtC,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAkCpB;;;;OAIG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAUjC;;;;;OAKG;IACG,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;CA+CrC"}
@@ -1,189 +0,0 @@
1
- /**
2
- * Copyright (c) 2025 Bytedance, Inc. and its affiliates.
3
- * SPDX-License-Identifier: Apache-2.0
4
- */
5
- "use strict";
6
- var __webpack_require__ = {};
7
- (()=>{
8
- __webpack_require__.d = (exports1, definition)=>{
9
- for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
10
- enumerable: true,
11
- get: definition[key]
12
- });
13
- };
14
- })();
15
- (()=>{
16
- __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
17
- })();
18
- (()=>{
19
- __webpack_require__.r = (exports1)=>{
20
- if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
21
- value: 'Module'
22
- });
23
- Object.defineProperty(exports1, '__esModule', {
24
- value: true
25
- });
26
- };
27
- })();
28
- var __webpack_exports__ = {};
29
- __webpack_require__.r(__webpack_exports__);
30
- __webpack_require__.d(__webpack_exports__, {
31
- BaseBrowser: ()=>BaseBrowser
32
- });
33
- const logger_namespaceObject = require("@agent-infra/logger");
34
- function _define_property(obj, key, value) {
35
- if (key in obj) Object.defineProperty(obj, key, {
36
- value: value,
37
- enumerable: true,
38
- configurable: true,
39
- writable: true
40
- });
41
- else obj[key] = value;
42
- return obj;
43
- }
44
- class BaseBrowser {
45
- async isBrowserAlive() {
46
- if (!this.browser) return false;
47
- try {
48
- const version = await this.browser.version();
49
- this.logger.info('Browser version:', version);
50
- return true;
51
- } catch (error) {
52
- this.logger.warn('Browser instance is no longer active:', error);
53
- this.browser = null;
54
- return false;
55
- }
56
- }
57
- getBrowser() {
58
- if (!this.browser) throw new Error('Browser not launched');
59
- return this.browser;
60
- }
61
- async setupPageListener() {
62
- this.logger.info('setupPageListener()');
63
- if (!this.browser) return;
64
- this.browser.on('targetcreated', async (target)=>{
65
- this.logger.info('PageListener: targetcreated, type:', target.type());
66
- const page = await target.page();
67
- if (page) {
68
- this.logger.info('New page created:', await page.url());
69
- this.activePage = page;
70
- page.once('close', ()=>{
71
- if (this.activePage === page) this.activePage = null;
72
- });
73
- page.once('error', ()=>{
74
- if (this.activePage === page) this.activePage = null;
75
- });
76
- }
77
- });
78
- this.browser.on('targetchanged', async (target)=>{
79
- this.logger.info('PageListener: targetchanged:', target.type());
80
- try {
81
- const changedPage = await target.page();
82
- if (changedPage) {
83
- const currentUrl = await changedPage.url();
84
- this.logger.info('The target changed', currentUrl);
85
- if (currentUrl && 'about:blank' !== currentUrl) this.activePage = changedPage;
86
- }
87
- } catch (error) {
88
- this.logger.error('error on targetchanged:', error);
89
- }
90
- });
91
- this.browser.on('targetdestroyed', async (target)=>{
92
- this.logger.info('PageListener: targetdestroyed:', target.type());
93
- if ('page' === target.type()) try {
94
- var _this_browser;
95
- const pages = await (null == (_this_browser = this.browser) ? void 0 : _this_browser.pages());
96
- this.logger.info('Destoryed, left pages:', null == pages ? void 0 : pages.length);
97
- this.activePage = null;
98
- } catch (error) {
99
- this.logger.error('error on targetdestroyed:', error);
100
- }
101
- });
102
- }
103
- async close() {
104
- this.logger.info('Closing browser');
105
- try {
106
- var _this_browser;
107
- await (null == (_this_browser = this.browser) ? void 0 : _this_browser.close());
108
- this.browser = null;
109
- this.logger.success('Browser closed successfully');
110
- } catch (error) {
111
- this.logger.error('Failed to close browser:', error);
112
- throw error;
113
- }
114
- }
115
- async evaluateOnNewPage(options) {
116
- const { url, pageFunction, pageFunctionParams, beforePageLoad, afterPageLoad, beforeSendResult, waitForOptions } = options;
117
- const page = await this.browser.newPage();
118
- try {
119
- await (null == beforePageLoad ? void 0 : beforePageLoad(page));
120
- await page.goto(url, {
121
- waitUntil: 'networkidle2',
122
- ...waitForOptions
123
- });
124
- await (null == afterPageLoad ? void 0 : afterPageLoad(page));
125
- const _window = await page.evaluateHandle(()=>window);
126
- const result = await page.evaluate(pageFunction, _window, ...pageFunctionParams);
127
- await (null == beforeSendResult ? void 0 : beforeSendResult(page, result));
128
- await _window.dispose();
129
- await page.close();
130
- return result;
131
- } catch (error) {
132
- await page.close();
133
- throw error;
134
- }
135
- }
136
- async createPage() {
137
- if (!this.browser) {
138
- this.logger.error('No active browser');
139
- throw new Error('Browser not launched');
140
- }
141
- const page = await this.browser.newPage();
142
- return page;
143
- }
144
- async getActivePage() {
145
- this.logger.info('getActivePage: current activePage', this.activePage);
146
- if (!this.browser) throw new Error('Browser not launched');
147
- if (this.activePage) try {
148
- await this.activePage.evaluate(()=>document.readyState);
149
- return this.activePage;
150
- } catch (e) {
151
- this.logger.warn('Active page no longer available:', e);
152
- this.activePage = null;
153
- }
154
- const pages = await this.browser.pages();
155
- this.logger.info('getActivePage: all of pages lenght:', pages.length);
156
- if (0 === pages.length) {
157
- this.activePage = await this.createPage();
158
- return this.activePage;
159
- }
160
- for(let i = pages.length - 1; i >= 0; i--){
161
- const page = pages[i];
162
- this.logger.info('getActivePage: page:', await page.title(), await page.url());
163
- try {
164
- await page.evaluate(()=>document.readyState);
165
- this.activePage = page;
166
- return page;
167
- } catch (e) {
168
- continue;
169
- }
170
- }
171
- throw new Error('No active page found');
172
- }
173
- constructor(options){
174
- _define_property(this, "browser", null);
175
- _define_property(this, "logger", void 0);
176
- _define_property(this, "activePage", null);
177
- this.logger = ((null == options ? void 0 : options.logger) ?? logger_namespaceObject.defaultLogger).spawn('[BaseBrowser]');
178
- this.logger.info('Browser Options:', options);
179
- }
180
- }
181
- exports.BaseBrowser = __webpack_exports__.BaseBrowser;
182
- for(var __webpack_i__ in __webpack_exports__)if (-1 === [
183
- "BaseBrowser"
184
- ].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
185
- Object.defineProperty(exports, '__esModule', {
186
- value: true
187
- });
188
-
189
- //# sourceMappingURL=base-browser.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"base-browser.js","sources":["webpack://@agent-infra/browser/webpack/runtime/define_property_getters","webpack://@agent-infra/browser/webpack/runtime/has_own_property","webpack://@agent-infra/browser/webpack/runtime/make_namespace_object","webpack://@agent-infra/browser/./src/base-browser.ts"],"sourcesContent":["__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n }\n }\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","/* eslint-disable @typescript-eslint/no-explicit-any */\n/*\n * Copyright (c) 2025 Bytedance, Inc. and its affiliates.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport * as puppeteer from 'puppeteer-core';\nimport { Logger, defaultLogger } from '@agent-infra/logger';\nimport {\n BrowserInterface,\n EvaluateOnNewPageOptions,\n LaunchOptions,\n Page,\n} from './types';\n\n/**\n * Configuration options for the BaseBrowser class\n * @interface BaseBrowserOptions\n * @property {Logger} [logger] - Custom logger instance to use for browser logging\n */\nexport interface BaseBrowserOptions {\n logger?: Logger;\n}\n\n/**\n * Abstract base class that implements common browser automation functionality\n * Provides a foundation for specific browser implementations with shared capabilities\n * @abstract\n * @implements {BrowserInterface}\n */\nexport abstract class BaseBrowser implements BrowserInterface {\n /**\n * The underlying Puppeteer browser instance\n * @protected\n */\n protected browser: puppeteer.Browser | null = null;\n\n /**\n * Logger instance for browser-related logging\n * @protected\n */\n protected logger: Logger;\n\n /**\n * Reference to the currently active browser page\n * @protected\n */\n protected activePage: Page | null = null;\n\n /**\n * Creates an instance of BaseBrowser\n * @param {BaseBrowserOptions} [options] - Configuration options\n */\n constructor(options?: BaseBrowserOptions) {\n this.logger = (options?.logger ?? defaultLogger).spawn('[BaseBrowser]');\n this.logger.info('Browser Options:', options);\n }\n\n /**\n * Check if the browser instance is active and responding\n * @returns {Promise<boolean>} True if browser is active, false otherwise\n */\n async isBrowserAlive(): Promise<boolean> {\n if (!this.browser) {\n return false;\n }\n\n try {\n // Try to get browser version to check if it's still responding\n const version = await this.browser.version();\n this.logger.info('Browser version:', version);\n return true;\n } catch (error) {\n this.logger.warn('Browser instance is no longer active:', error);\n this.browser = null;\n return false;\n }\n }\n\n /**\n * Get the underlying Puppeteer browser instance\n * @throws Error if browser is not launched\n\n * @returns {puppeteer.Browser} Puppeteer browser instance\n */\n getBrowser(): puppeteer.Browser {\n if (!this.browser) {\n throw new Error('Browser not launched');\n }\n return this.browser;\n }\n\n /**\n * Sets up listeners for browser page events\n * Tracks page creation and updates active page reference\n * @protected\n */\n protected async setupPageListener() {\n this.logger.info('setupPageListener()');\n if (!this.browser) return;\n\n this.browser.on('targetcreated', async (target) => {\n this.logger.info('PageListener: targetcreated, type:', target.type());\n\n const page = await target.page();\n if (page) {\n this.logger.info('New page created:', await page.url());\n this.activePage = page;\n\n page.once('close', () => {\n if (this.activePage === page) {\n this.activePage = null;\n }\n });\n\n page.once('error', () => {\n if (this.activePage === page) {\n this.activePage = null;\n }\n });\n }\n });\n\n this.browser.on('targetchanged', async (target: any) => {\n this.logger.info('PageListener: targetchanged:', target.type());\n try {\n const changedPage = await target.page();\n if (changedPage) {\n const currentUrl = await changedPage.url();\n this.logger.info('The target changed', currentUrl);\n if (currentUrl && currentUrl !== 'about:blank') {\n this.activePage = changedPage;\n }\n }\n } catch (error) {\n this.logger.error('error on targetchanged:', error);\n }\n });\n\n this.browser.on('targetdestroyed', async (target: any) => {\n this.logger.info('PageListener: targetdestroyed:', target.type());\n if (target.type() === 'page') {\n try {\n const pages = await this.browser?.pages();\n this.logger.info('Destoryed, left pages:', pages?.length);\n this.activePage = null;\n } catch (error) {\n this.logger.error('error on targetdestroyed:', error);\n }\n }\n });\n }\n\n /**\n * Launches the browser with specified options\n * @abstract\n * @param {LaunchOptions} [options] - Browser launch configuration options\n * @returns {Promise<void>} Promise that resolves when browser is launched\n */\n abstract launch(options?: LaunchOptions): Promise<void>;\n\n /**\n * Closes the browser instance and cleans up resources\n * @returns {Promise<void>} Promise that resolves when browser is closed\n * @throws {Error} If browser fails to close properly\n */\n async close(): Promise<void> {\n this.logger.info('Closing browser');\n try {\n await this.browser?.close();\n this.browser = null;\n this.logger.success('Browser closed successfully');\n } catch (error) {\n this.logger.error('Failed to close browser:', error);\n throw error;\n }\n }\n\n /**\n * Creates a new page, navigates to the specified URL, executes a function in the page context, and returns the result\n * This method is inspired and modified from https://github.com/egoist/local-web-search/blob/04608ed09aa103e2fff6402c72ca12edfb692d19/src/browser.ts#L74\n * @template T - Type of parameters passed to the page function\n * @template R - Return type of the page function\n * @param {EvaluateOnNewPageOptions<T, R>} options - Configuration options for the page evaluation\n * @returns {Promise<R | null>} Promise resolving to the result of the page function or null\n * @throws {Error} If page creation or evaluation fails\n */\n async evaluateOnNewPage<T extends any[], R>(\n options: EvaluateOnNewPageOptions<T, R>,\n ): Promise<R | null> {\n const {\n url,\n pageFunction,\n pageFunctionParams,\n beforePageLoad,\n afterPageLoad,\n beforeSendResult,\n waitForOptions,\n } = options;\n const page = await this.browser!.newPage();\n try {\n await beforePageLoad?.(page);\n await page.goto(url, {\n waitUntil: 'networkidle2',\n ...waitForOptions,\n });\n await afterPageLoad?.(page);\n const _window = await page.evaluateHandle(() => window);\n const result = await page.evaluate(\n pageFunction,\n _window,\n ...pageFunctionParams,\n );\n await beforeSendResult?.(page, result);\n await _window.dispose();\n await page.close();\n return result;\n } catch (error) {\n await page.close();\n throw error;\n }\n }\n\n /**\n * Creates a new browser page\n * @returns {Promise<Page>} Promise resolving to the newly created page\n * @throws {Error} If browser is not launched or page creation fails\n */\n async createPage(): Promise<Page> {\n if (!this.browser) {\n this.logger.error('No active browser');\n throw new Error('Browser not launched');\n }\n\n const page = await this.browser.newPage();\n return page;\n }\n\n /**\n * Gets the currently active page or finds an active page if none is currently tracked\n * If no active pages exist, creates a new page\n * @returns {Promise<Page>} Promise resolving to the active page\n * @throws {Error} If browser is not launched or no active page can be found/created\n */\n async getActivePage(): Promise<Page> {\n this.logger.info('getActivePage: current activePage', this.activePage);\n\n if (!this.browser) {\n throw new Error('Browser not launched');\n }\n\n // If activePage exists and is still available, return directly\n if (this.activePage) {\n try {\n // Verify that the page is still available\n await this.activePage.evaluate(() => document.readyState);\n return this.activePage;\n } catch (e) {\n this.logger.warn('Active page no longer available:', e);\n this.activePage = null;\n }\n }\n\n // Get all pages and find the last active page\n const pages = await this.browser.pages();\n this.logger.info('getActivePage: all of pages lenght:', pages.length);\n\n if (pages.length === 0) {\n this.activePage = await this.createPage();\n return this.activePage;\n }\n\n // Find the last responding page\n for (let i = pages.length - 1; i >= 0; i--) {\n const page = pages[i];\n this.logger.info(\n 'getActivePage: page:',\n await page.title(),\n await page.url(),\n );\n try {\n await page.evaluate(() => document.readyState);\n this.activePage = page;\n return page;\n } catch (e) {\n continue;\n }\n }\n\n throw new Error('No active page found');\n }\n}\n"],"names":["__webpack_require__","definition","key","Object","obj","prop","Symbol","BaseBrowser","version","error","Error","target","page","changedPage","currentUrl","_this_browser","pages","options","url","pageFunction","pageFunctionParams","beforePageLoad","afterPageLoad","beforeSendResult","waitForOptions","_window","window","result","document","e","i","defaultLogger"],"mappings":"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"}