page-agent 0.0.1 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,7 +1,5 @@
1
1
  # PageAgent 🤖🪄
2
2
 
3
- > Unfinished Project. See [**Roadmap**](./ROADMAP.md)
4
-
5
3
  ![banner](https://img.alicdn.com/imgextra/i1/O1CN01RY0Wvh26ATVeDIX7v_!!6000000007621-0-tps-1672-512.jpg)
6
4
 
7
5
  [![npm version](https://badge.fury.io/js/page-agent.svg)](https://badge.fury.io/js/page-agent) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![TypeScript](https://img.shields.io/badge/%3C%2F%3E-TypeScript-%230074c1.svg)](http://www.typescriptlang.org/) [![Downloads](https://img.shields.io/npm/dt/page-agent.svg)](https://www.npmjs.com/package/page-agent) [![Bundle Size](https://img.shields.io/bundlephobia/minzip/page-agent)](https://bundlephobia.com/package/page-agent) [![GitHub stars](https://img.shields.io/github/stars/alibaba/page-agent.svg)](https://github.com/alibaba/page-agent)
@@ -32,11 +30,13 @@ An in-page UI agent in javascript. Control web interfaces with natural language.
32
30
 
33
31
  ### CDN Integration
34
32
 
35
- > **TODO**: CDN endpoint to be determined.
36
-
37
33
  ```html
38
- <!-- CDN script tag - URL to be updated -->
39
- <script src="TODO-CDN-URL"></script>
34
+ <!-- temporary CDN URL. May change in the future -->
35
+ <script
36
+ src="https://hwcxiuzfylggtcktqgij.supabase.co/storage/v1/object/public/demo-public/v0.0.2/page-agent.js"
37
+ crossorigin="true"
38
+ type="text/javascript"
39
+ ></script>
40
40
  ```
41
41
 
42
42
  ### NPM Installation
@@ -48,13 +48,21 @@ npm install page-agent
48
48
  ```javascript
49
49
  import { PageAgent } from 'page-agent'
50
50
 
51
+ // test server
52
+ // @note: rate limit. prompt limit. Origin limit. May change anytime. Use your own llm!
53
+ // @note Using official DeepSeek-chat(3.2). Go to DeepSeek website for privacy policy.
54
+ const DEMO_MODEL = 'PAGE-AGENT-FREE-TESTING-RANDOM'
55
+ const DEMO_BASE_URL = 'https://hwcxiuzfylggtcktqgij.supabase.co/functions/v1/llm-testing-proxy'
56
+ const DEMO_API_KEY = 'PAGE-AGENT-FREE-TESTING-RANDOM'
57
+
51
58
  const agent = new PageAgent({
52
- modelName: 'gpt-4.1-mini',
53
- baseURL: 'xxxx',
54
- apiKey: 'xxxx'
59
+ modelName: DEMO_MODEL,
60
+ baseURL: DEMO_BASE_URL,
61
+ apiKey: DEMO_API_KEY,
62
+ language: 'en-US',
55
63
  })
56
64
 
57
- await agent.execute("Click the login button")
65
+ await agent.execute('Click the login button')
58
66
  ```
59
67
 
60
68
  ## 🏗️ Structure
@@ -91,7 +99,6 @@ Please read our [Code of Conduct](CODE_OF_CONDUCT.md) and [Contributing Guide](C
91
99
  This project builds upon the excellent work of:
92
100
 
93
101
  - **[browser-use](https://github.com/browser-use/browser-use)**
94
- - **[ai-sdk](https://ai-sdk.dev/)**
95
102
 
96
103
  PageAgent is designed for **client-side web enhancement**, not server-side automation.
97
104
 
@@ -99,9 +106,8 @@ PageAgent is designed for **client-side web enhancement**, not server-side autom
99
106
 
100
107
  MIT License - see the [LICENSE](LICENSE) file for details.
101
108
 
102
-
103
109
  ```
104
- DOM processing components and prompt are derived from browser-use:
110
+ DOM processing components and prompt are derived from browser-use:
105
111
 
106
112
  Browser Use
107
113
  Copyright (c) 2024 Gregor Zunic
@@ -7,6 +7,61 @@ export declare interface AgentBrain {
7
7
  next_goal: string;
8
8
  }
9
9
 
10
+ declare interface AgentConfig {
11
+ language?: SupportedLanguage;
12
+ /**
13
+ * Custom tools to extend PageAgent capabilities
14
+ * @experimental
15
+ * @note You can also override or remove internal tools by using the same name.
16
+ * @see [tools](../tools/index.ts)
17
+ *
18
+ * @example
19
+ * // override internal tool
20
+ * import { tool } from 'page-agent'
21
+ * const customTools = {
22
+ * ask_user: tool({
23
+ * description:
24
+ * 'Ask the user or parent model a question and wait for their answer. Use this if you need more information or clarification.',
25
+ * inputSchema: zod.object({
26
+ * question: zod.string(),
27
+ * }),
28
+ * execute: async function (this: PageAgent, input) {
29
+ * const answer = await do_some_thing(input.question)
30
+ * return "✅ Received user answer: " + answer
31
+ * },
32
+ * })
33
+ * }
34
+ *
35
+ * @example
36
+ * // remove internal tool
37
+ * const customTools = {
38
+ * ask_user: null // never ask user questions
39
+ * }
40
+ */
41
+ customTools?: Record<string, PageAgentTool | null>;
42
+ onBeforeStep?: (this: PageAgent, stepCnt: number) => Promise<void> | void;
43
+ onAfterStep?: (this: PageAgent, stepCnt: number, history: AgentHistory[]) => Promise<void> | void;
44
+ onBeforeTask?: (this: PageAgent) => Promise<void> | void;
45
+ onAfterTask?: (this: PageAgent, result: ExecutionResult) => Promise<void> | void;
46
+ /**
47
+ * @note this hook can block the disposal process
48
+ * @note when dispose caused by page unload, reason will be 'PAGE_UNLOADING'. this method CANNOT block unloading. async operations may be cut.
49
+ */
50
+ onDispose?: (this: PageAgent, reason?: string) => void;
51
+ /**
52
+ * TODO: @unimplemented
53
+ * hook when action causes a new page to be opened
54
+ * @note PageAgent will try to detect new pages and decide if it's caused by an action. But not very reliable.
55
+ */
56
+ onNewPageOpen?: (this: PageAgent, url: string) => Promise<void> | void;
57
+ /**
58
+ * TODO: @unimplemented
59
+ * try to navigate to a new page instead of opening a new tab/window.
60
+ * @note will unload the current page when a action tries to open a new page. so that things keep in the same tab/window.
61
+ */
62
+ experimentalPreventNewPage?: boolean;
63
+ }
64
+
10
65
  export declare interface AgentHistory {
11
66
  brain: AgentBrain;
12
67
  action: {
@@ -303,9 +358,11 @@ export declare class PageAgent extends EventTarget {
303
358
  bus: EventBus;
304
359
  i18n: I18n;
305
360
  panel: Panel;
361
+ tools: typeof tools;
306
362
  paused: boolean;
307
363
  disposed: boolean;
308
364
  task: string;
365
+ taskId: string;
309
366
  /** Corresponds to eval_page in browser-use */
310
367
  flatTree: FlatDomTree | null;
311
368
  /**
@@ -319,8 +376,6 @@ export declare class PageAgent extends EventTarget {
319
376
  simplifiedHTML: string;
320
377
  /** last time the tree was updated */
321
378
  lastTimeUpdate: number;
322
- /** Corresponds to actions in browser-use */
323
- tools: Map<string, PageAgentTool<any>>;
324
379
  /** Fullscreen mask */
325
380
  mask: SimulatorMask;
326
381
  /** History records */
@@ -330,10 +385,10 @@ export declare class PageAgent extends EventTarget {
330
385
  * @todo maybe return something?
331
386
  */
332
387
  execute(task: string): Promise<ExecutionResult>;
333
- dispose(): void;
388
+ dispose(reason?: string): void;
334
389
  }
335
390
 
336
- export declare type PageAgentConfig = LLMConfig & DomConfig & UIConfig;
391
+ export declare type PageAgentConfig = LLMConfig & AgentConfig & DomConfig;
337
392
 
338
393
  /**
339
394
  * Event mapping definitions
@@ -363,7 +418,7 @@ declare interface PageAgentEventMap {
363
418
  /**
364
419
  * Internal tool definition that has access to PageAgent `this` context
365
420
  */
366
- declare interface PageAgentTool<TParams = any> {
421
+ export declare interface PageAgentTool<TParams = any> {
367
422
  description: string;
368
423
  inputSchema: z.ZodType<TParams>;
369
424
  execute: (this: PageAgent, args: TParams) => Promise<string>;
@@ -422,14 +477,18 @@ declare interface TextDomNode {
422
477
  [key: string]: unknown;
423
478
  }
424
479
 
480
+ export declare function tool<TParams>(options: PageAgentTool<TParams>): PageAgentTool<TParams>;
481
+
482
+ /**
483
+ * Internal tools for PageAgent.
484
+ * Note: Using any to allow different parameter types for each tool
485
+ */
486
+ declare const tools: Map<string, PageAgentTool<any>>;
487
+
425
488
  declare type TranslationKey = NestedKeyOf<TranslationSchema>;
426
489
 
427
490
  declare type TranslationParams = Record<string, string | number>;
428
491
 
429
492
  declare type TranslationSchema = DeepStringify<typeof enUS>;
430
493
 
431
- declare interface UIConfig {
432
- language?: SupportedLanguage;
433
- }
434
-
435
494
  export { }
@@ -22,14 +22,14 @@ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read fr
22
22
  var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
23
23
  var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
24
24
  var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
25
- var _bus, _wrapper, _indicator, _statusText, _historySection, _expandButton, _pauseButton, _stopButton, _inputSection, _taskInput, _bus2, _state, _isExpanded, _pageAgent, _userAnswerResolver, _isWaitingForUserAnswer, _Panel_instances, update_fn, show_fn, hide_fn, reset_fn, togglePause_fn, updatePauseButton_fn, stopAgent_fn, submitTask_fn, handleUserAnswer_fn, showInputArea_fn, hideInputArea_fn, shouldShowInputArea_fn, createWrapper_fn, setupEventListeners_fn, toggle_fn, expand_fn, collapse_fn, animateTextChange_fn, updateStatusIndicator_fn, updateHistory_fn, scrollToBottom_fn, createHistoryItem_fn, _cursor, _currentCursorX, _currentCursorY, _targetCursorX, _targetCursorY, _SimulatorMask_instances, createCursor_fn, moveCursorToTarget_fn, _llm, _totalWaitTime, _abortController, _PageAgent_instances, packMacroTool_fn, getSystemPrompt_fn, assembleUserPrompt_fn, onDone_fn, getBrowserState_fn, updateTree_fn;
25
+ var _bus, _wrapper, _indicator, _statusText, _historySection, _expandButton, _pauseButton, _stopButton, _inputSection, _taskInput, _bus2, _state, _isExpanded, _pageAgent, _userAnswerResolver, _isWaitingForUserAnswer, _headerUpdateTimer, _pendingHeaderText, _isAnimating, _Panel_instances, update_fn, show_fn, hide_fn, reset_fn, togglePause_fn, updatePauseButton_fn, stopAgent_fn, submitTask_fn, handleUserAnswer_fn, showInputArea_fn, hideInputArea_fn, shouldShowInputArea_fn, createWrapper_fn, setupEventListeners_fn, toggle_fn, expand_fn, collapse_fn, startHeaderUpdateLoop_fn, stopHeaderUpdateLoop_fn, checkAndUpdateHeader_fn, animateTextChange_fn, updateStatusIndicator_fn, updateHistory_fn, scrollToBottom_fn, createHistoryItem_fn, _cursor, _currentCursorX, _currentCursorY, _targetCursorX, _targetCursorY, _SimulatorMask_instances, createCursor_fn, moveCursorToTarget_fn, _llm, _totalWaitTime, _abortController, _PageAgent_instances, packMacroTool_fn, getSystemPrompt_fn, assembleUserPrompt_fn, onDone_fn, getBrowserState_fn, updateTree_fn;
26
26
  import chalk from "chalk";
27
27
  import zod, { z } from "zod";
28
28
  import { Motion } from "ai-motion";
29
29
  const VIEWPORT_EXPANSION = -1;
30
- const DEFAULT_MODEL_NAME = "gpt-41-mini-0414-global";
31
- const DEFAULT_API_KEY = "not-needed";
32
- const DEFAULT_BASE_URL = "http://localhost:3000/api/agent";
30
+ const DEFAULT_MODEL_NAME = "PAGE-AGENT-FREE-TESTING-RANDOM";
31
+ const DEFAULT_API_KEY = "PAGE-AGENT-FREE-TESTING-RANDOM";
32
+ const DEFAULT_BASE_URL = "https://hwcxiuzfylggtcktqgij.supabase.co/functions/v1/llm-testing-proxy";
33
33
  const LLM_MAX_RETRIES = 2;
34
34
  const MAX_STEPS = 20;
35
35
  const DEFAULT_TEMPERATURE = 0.7;
@@ -2626,6 +2626,9 @@ const _Panel = class _Panel {
2626
2626
  __privateAdd(this, _pageAgent);
2627
2627
  __privateAdd(this, _userAnswerResolver, null);
2628
2628
  __privateAdd(this, _isWaitingForUserAnswer, false);
2629
+ __privateAdd(this, _headerUpdateTimer, null);
2630
+ __privateAdd(this, _pendingHeaderText, null);
2631
+ __privateAdd(this, _isAnimating, false);
2629
2632
  __privateSet(this, _pageAgent, pageAgent);
2630
2633
  __privateSet(this, _bus2, pageAgent.bus);
2631
2634
  __privateSet(this, _wrapper, __privateMethod(this, _Panel_instances, createWrapper_fn).call(this));
@@ -2638,6 +2641,7 @@ const _Panel = class _Panel {
2638
2641
  __privateSet(this, _inputSection, __privateGet(this, _wrapper).querySelector(`.${styles$1.inputSectionWrapper}`));
2639
2642
  __privateSet(this, _taskInput, __privateGet(this, _wrapper).querySelector(`.${styles$1.taskInput}`));
2640
2643
  __privateMethod(this, _Panel_instances, setupEventListeners_fn).call(this);
2644
+ __privateMethod(this, _Panel_instances, startHeaderUpdateLoop_fn).call(this);
2641
2645
  __privateMethod(this, _Panel_instances, showInputArea_fn).call(this);
2642
2646
  __privateGet(this, _bus2).on("panel:show", () => __privateMethod(this, _Panel_instances, show_fn).call(this));
2643
2647
  __privateGet(this, _bus2).on("panel:hide", () => __privateMethod(this, _Panel_instances, hide_fn).call(this));
@@ -2671,6 +2675,7 @@ const _Panel = class _Panel {
2671
2675
  */
2672
2676
  dispose() {
2673
2677
  __privateSet(this, _isWaitingForUserAnswer, false);
2678
+ __privateMethod(this, _Panel_instances, stopHeaderUpdateLoop_fn).call(this);
2674
2679
  this.wrapper.remove();
2675
2680
  }
2676
2681
  };
@@ -2689,13 +2694,17 @@ _isExpanded = new WeakMap();
2689
2694
  _pageAgent = new WeakMap();
2690
2695
  _userAnswerResolver = new WeakMap();
2691
2696
  _isWaitingForUserAnswer = new WeakMap();
2697
+ _headerUpdateTimer = new WeakMap();
2698
+ _pendingHeaderText = new WeakMap();
2699
+ _isAnimating = new WeakMap();
2692
2700
  _Panel_instances = new WeakSet();
2693
- update_fn = /* @__PURE__ */ __name(async function(stepData) {
2701
+ /**
2702
+ * Update status
2703
+ */
2704
+ update_fn = /* @__PURE__ */ __name(function(stepData) {
2694
2705
  const step = __privateGet(this, _state).addStep(stepData);
2695
2706
  const headerText = truncate(step.displayText, 20);
2696
- if (__privateGet(this, _statusText).textContent !== headerText) {
2697
- await __privateMethod(this, _Panel_instances, animateTextChange_fn).call(this, headerText);
2698
- }
2707
+ __privateSet(this, _pendingHeaderText, headerText);
2699
2708
  __privateMethod(this, _Panel_instances, updateStatusIndicator_fn).call(this, step.type);
2700
2709
  __privateMethod(this, _Panel_instances, updateHistory_fn).call(this);
2701
2710
  if (step.type === "completed" || step.type === "error") {
@@ -2933,19 +2942,53 @@ collapse_fn = /* @__PURE__ */ __name(function() {
2933
2942
  this.wrapper.classList.add(styles$1.collapsed);
2934
2943
  __privateGet(this, _expandButton).textContent = "▼";
2935
2944
  }, "#collapse");
2936
- animateTextChange_fn = /* @__PURE__ */ __name(async function(newText) {
2937
- return new Promise((resolve) => {
2938
- __privateGet(this, _statusText).classList.add(styles$1.fadeOut);
2945
+ /**
2946
+ * Start periodic header update loop
2947
+ */
2948
+ startHeaderUpdateLoop_fn = /* @__PURE__ */ __name(function() {
2949
+ __privateSet(this, _headerUpdateTimer, setInterval(() => {
2950
+ __privateMethod(this, _Panel_instances, checkAndUpdateHeader_fn).call(this);
2951
+ }, 450));
2952
+ }, "#startHeaderUpdateLoop");
2953
+ /**
2954
+ * Stop periodic header update loop
2955
+ */
2956
+ stopHeaderUpdateLoop_fn = /* @__PURE__ */ __name(function() {
2957
+ if (__privateGet(this, _headerUpdateTimer)) {
2958
+ clearInterval(__privateGet(this, _headerUpdateTimer));
2959
+ __privateSet(this, _headerUpdateTimer, null);
2960
+ }
2961
+ }, "#stopHeaderUpdateLoop");
2962
+ /**
2963
+ * Check if header needs update and trigger animation if not currently animating
2964
+ */
2965
+ checkAndUpdateHeader_fn = /* @__PURE__ */ __name(function() {
2966
+ if (!__privateGet(this, _pendingHeaderText) || __privateGet(this, _isAnimating)) {
2967
+ return;
2968
+ }
2969
+ if (__privateGet(this, _statusText).textContent === __privateGet(this, _pendingHeaderText)) {
2970
+ __privateSet(this, _pendingHeaderText, null);
2971
+ return;
2972
+ }
2973
+ const textToShow = __privateGet(this, _pendingHeaderText);
2974
+ __privateSet(this, _pendingHeaderText, null);
2975
+ __privateMethod(this, _Panel_instances, animateTextChange_fn).call(this, textToShow);
2976
+ }, "#checkAndUpdateHeader");
2977
+ /**
2978
+ * Animate text change with fade out/in effect
2979
+ */
2980
+ animateTextChange_fn = /* @__PURE__ */ __name(function(newText) {
2981
+ __privateSet(this, _isAnimating, true);
2982
+ __privateGet(this, _statusText).classList.add(styles$1.fadeOut);
2983
+ setTimeout(() => {
2984
+ __privateGet(this, _statusText).textContent = newText;
2985
+ __privateGet(this, _statusText).classList.remove(styles$1.fadeOut);
2986
+ __privateGet(this, _statusText).classList.add(styles$1.fadeIn);
2939
2987
  setTimeout(() => {
2940
- __privateGet(this, _statusText).textContent = newText;
2941
- __privateGet(this, _statusText).classList.remove(styles$1.fadeOut);
2942
- __privateGet(this, _statusText).classList.add(styles$1.fadeIn);
2943
- setTimeout(() => {
2944
- __privateGet(this, _statusText).classList.remove(styles$1.fadeIn);
2945
- resolve();
2946
- }, 300);
2947
- }, 150);
2948
- });
2988
+ __privateGet(this, _statusText).classList.remove(styles$1.fadeIn);
2989
+ __privateSet(this, _isAnimating, false);
2990
+ }, 300);
2991
+ }, 150);
2949
2992
  }, "#animateTextChange");
2950
2993
  updateStatusIndicator_fn = /* @__PURE__ */ __name(function(type) {
2951
2994
  __privateGet(this, _indicator).className = styles$1.indicator;
@@ -3290,9 +3333,11 @@ const _PageAgent = class _PageAgent extends EventTarget {
3290
3333
  __publicField(this, "bus", getEventBus(this.id));
3291
3334
  __publicField(this, "i18n");
3292
3335
  __publicField(this, "panel");
3336
+ __publicField(this, "tools");
3293
3337
  __publicField(this, "paused", false);
3294
3338
  __publicField(this, "disposed", false);
3295
3339
  __publicField(this, "task", "");
3340
+ __publicField(this, "taskId", "");
3296
3341
  __privateAdd(this, _llm);
3297
3342
  __privateAdd(this, _totalWaitTime, 0);
3298
3343
  __privateAdd(this, _abortController, new AbortController());
@@ -3309,8 +3354,6 @@ const _PageAgent = class _PageAgent extends EventTarget {
3309
3354
  __publicField(this, "simplifiedHTML", "<EMPTY>");
3310
3355
  /** last time the tree was updated */
3311
3356
  __publicField(this, "lastTimeUpdate", 0);
3312
- /** Corresponds to actions in browser-use */
3313
- __publicField(this, "tools", new Map(tools));
3314
3357
  /** Fullscreen mask */
3315
3358
  __publicField(this, "mask", new SimulatorMask());
3316
3359
  /** History records */
@@ -3319,7 +3362,20 @@ const _PageAgent = class _PageAgent extends EventTarget {
3319
3362
  __privateSet(this, _llm, new LLM(this.config, this.id));
3320
3363
  this.i18n = new I18n(this.config.language);
3321
3364
  this.panel = new Panel(this);
3365
+ this.tools = new Map(tools);
3366
+ if (this.config.customTools) {
3367
+ for (const [name, tool2] of Object.entries(this.config.customTools)) {
3368
+ if (tool2 === null) {
3369
+ this.tools.delete(name);
3370
+ continue;
3371
+ }
3372
+ this.tools.set(name, tool2);
3373
+ }
3374
+ }
3322
3375
  patchReact();
3376
+ window.addEventListener("beforeunload", (e) => {
3377
+ if (!this.disposed) this.dispose("PAGE_UNLOADING");
3378
+ });
3323
3379
  }
3324
3380
  /**
3325
3381
  * @todo maybe return something?
@@ -3327,12 +3383,18 @@ const _PageAgent = class _PageAgent extends EventTarget {
3327
3383
  async execute(task) {
3328
3384
  if (!task) throw new Error("Task is required");
3329
3385
  this.task = task;
3386
+ this.taskId = uid();
3387
+ const onBeforeStep = this.config.onBeforeStep || (() => void 0);
3388
+ const onAfterStep = this.config.onAfterStep || (() => void 0);
3389
+ const onBeforeTask = this.config.onBeforeTask || (() => void 0);
3390
+ const onAfterTask = this.config.onAfterTask || (() => void 0);
3391
+ await onBeforeTask.call(this);
3330
3392
  this.mask.show();
3331
3393
  this.bus.emit("panel:show");
3332
3394
  this.bus.emit("panel:reset");
3333
3395
  this.bus.emit("panel:update", {
3334
3396
  type: "input",
3335
- displayText: task
3397
+ displayText: this.task
3336
3398
  });
3337
3399
  if (__privateGet(this, _abortController)) {
3338
3400
  __privateGet(this, _abortController).abort();
@@ -3342,6 +3404,7 @@ const _PageAgent = class _PageAgent extends EventTarget {
3342
3404
  try {
3343
3405
  let step = 0;
3344
3406
  while (true) {
3407
+ await onBeforeStep.call(this, step);
3345
3408
  console.group(`step: ${step + 1}`);
3346
3409
  if (__privateGet(this, _abortController).signal.aborted) throw new Error("AbortError");
3347
3410
  await waitUntil(() => !this.paused);
@@ -3385,38 +3448,45 @@ const _PageAgent = class _PageAgent extends EventTarget {
3385
3448
  });
3386
3449
  console.log(chalk.green("Step finished:"), actionName);
3387
3450
  console.groupEnd();
3451
+ await onAfterStep.call(this, step, this.history);
3388
3452
  step++;
3389
3453
  if (step > MAX_STEPS) {
3390
3454
  __privateMethod(this, _PageAgent_instances, onDone_fn).call(this, "Step count exceeded maximum limit", false);
3391
- return {
3455
+ const result2 = {
3392
3456
  success: false,
3393
3457
  data: "Step count exceeded maximum limit",
3394
3458
  history: this.history
3395
3459
  };
3460
+ await onAfterTask.call(this, result2);
3461
+ return result2;
3396
3462
  }
3397
3463
  if (actionName === "done") {
3398
3464
  const success = action.input?.success ?? false;
3399
3465
  const text = action.input?.text || "no text provided";
3400
3466
  console.log(chalk.green.bold("Task completed"), success, text);
3401
3467
  __privateMethod(this, _PageAgent_instances, onDone_fn).call(this, text, success);
3402
- return {
3468
+ const result2 = {
3403
3469
  success,
3404
3470
  data: text,
3405
3471
  history: this.history
3406
3472
  };
3473
+ await onAfterTask.call(this, result2);
3474
+ return result2;
3407
3475
  }
3408
3476
  }
3409
3477
  } catch (error2) {
3410
3478
  console.error("Task failed", error2);
3411
3479
  __privateMethod(this, _PageAgent_instances, onDone_fn).call(this, String(error2), false);
3412
- return {
3480
+ const result = {
3413
3481
  success: false,
3414
3482
  data: String(error2),
3415
3483
  history: this.history
3416
3484
  };
3485
+ await onAfterTask.call(this, result);
3486
+ return result;
3417
3487
  }
3418
3488
  }
3419
- dispose() {
3489
+ dispose(reason) {
3420
3490
  console.log("Disposing PageAgent...");
3421
3491
  this.disposed = true;
3422
3492
  cleanUpHighlights();
@@ -3426,7 +3496,8 @@ const _PageAgent = class _PageAgent extends EventTarget {
3426
3496
  this.panel.dispose();
3427
3497
  this.mask.dispose();
3428
3498
  this.history = [];
3429
- __privateGet(this, _abortController).abort("PageAgent disposed");
3499
+ __privateGet(this, _abortController).abort(reason ?? "PageAgent disposed");
3500
+ this.config.onDispose?.call(this, reason);
3430
3501
  }
3431
3502
  };
3432
3503
  _llm = new WeakMap();
@@ -3460,8 +3531,6 @@ packMacroTool_fn = /* @__PURE__ */ __name(function() {
3460
3531
  action: actionSchema
3461
3532
  });
3462
3533
  return {
3463
- // name: MACRO_TOOL_NAME,
3464
- // description: 'Execute agent action', // @todo remote
3465
3534
  inputSchema: macroToolSchema,
3466
3535
  execute: /* @__PURE__ */ __name(async (input2) => {
3467
3536
  if (__privateGet(this, _abortController).signal.aborted) throw new Error("AbortError");
@@ -3625,6 +3694,7 @@ updateTree_fn = /* @__PURE__ */ __name(function() {
3625
3694
  __name(_PageAgent, "PageAgent");
3626
3695
  let PageAgent = _PageAgent;
3627
3696
  export {
3628
- PageAgent
3697
+ PageAgent,
3698
+ tool
3629
3699
  };
3630
3700
  //# sourceMappingURL=page-agent.js.map