Merge branch 'main' into feat/ext

This commit is contained in:
Simon
2026-01-21 18:55:50 +08:00
12 changed files with 59 additions and 35 deletions

View File

@@ -37,7 +37,7 @@
```html ```html
<script <script
src="https://registry.npmmirror.com/page-agent/1.0.0-beta.3/files/dist/iife/page-agent.demo.js" src="https://registry.npmmirror.com/page-agent/1.0.0-beta.4/files/dist/iife/page-agent.demo.js"
crossorigin="true" crossorigin="true"
></script> ></script>
``` ```
@@ -46,8 +46,8 @@
| 镜像 | URL | | 镜像 | URL |
| ------ | ----------------------------------------------------------------------------------------- | | ------ | ----------------------------------------------------------------------------------------- |
| Global | https://cdn.jsdelivr.net/npm/page-agent@1.0.0-beta.3/dist/iife/page-agent.demo.js | | Global | https://cdn.jsdelivr.net/npm/page-agent@1.0.0-beta.4/dist/iife/page-agent.demo.js |
| China | https://registry.npmmirror.com/page-agent/1.0.0-beta.3/files/dist/iife/page-agent.demo.js | | China | https://registry.npmmirror.com/page-agent/1.0.0-beta.4/files/dist/iife/page-agent.demo.js |
### NPM 安装 ### NPM 安装

View File

@@ -37,7 +37,7 @@ Fastest way to try PageAgent:
```html ```html
<script <script
src="https://cdn.jsdelivr.net/npm/page-agent@1.0.0-beta.3/dist/iife/page-agent.demo.js" src="https://cdn.jsdelivr.net/npm/page-agent@1.0.0-beta.4/dist/iife/page-agent.demo.js"
crossorigin="true" crossorigin="true"
></script> ></script>
``` ```
@@ -46,8 +46,8 @@ Fastest way to try PageAgent:
| Mirrors | URL | | Mirrors | URL |
| ------- | ----------------------------------------------------------------------------------------- | | ------- | ----------------------------------------------------------------------------------------- |
| Global | https://cdn.jsdelivr.net/npm/page-agent@1.0.0-beta.3/dist/iife/page-agent.demo.js | | Global | https://cdn.jsdelivr.net/npm/page-agent@1.0.0-beta.4/dist/iife/page-agent.demo.js |
| China | https://registry.npmmirror.com/page-agent/1.0.0-beta.3/files/dist/iife/page-agent.demo.js | | China | https://registry.npmmirror.com/page-agent/1.0.0-beta.4/files/dist/iife/page-agent.demo.js |
### NPM Installation ### NPM Installation

28
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "root", "name": "root",
"version": "1.0.0-beta.3", "version": "1.0.0-beta.4",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "root", "name": "root",
"version": "1.0.0-beta.3", "version": "1.0.0-beta.4",
"license": "MIT", "license": "MIT",
"workspaces": [ "workspaces": [
"packages/page-controller", "packages/page-controller",
@@ -11628,11 +11628,11 @@
}, },
"packages/core": { "packages/core": {
"name": "@page-agent/core", "name": "@page-agent/core",
"version": "1.0.0-beta.3", "version": "1.0.0-beta.4",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@page-agent/llms": "1.0.0-beta.3", "@page-agent/llms": "1.0.0-beta.4",
"@page-agent/page-controller": "1.0.0-beta.3", "@page-agent/page-controller": "1.0.0-beta.4",
"chalk": "^5.6.2", "chalk": "^5.6.2",
"zod": "^4.3.5" "zod": "^4.3.5"
} }
@@ -11684,7 +11684,7 @@
}, },
"packages/llms": { "packages/llms": {
"name": "@page-agent/llms", "name": "@page-agent/llms",
"version": "1.0.0-beta.3", "version": "1.0.0-beta.4",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"chalk": "^5.6.2", "chalk": "^5.6.2",
@@ -11692,20 +11692,20 @@
} }
}, },
"packages/page-agent": { "packages/page-agent": {
"version": "1.0.0-beta.3", "version": "1.0.0-beta.4",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@page-agent/core": "1.0.0-beta.3", "@page-agent/core": "1.0.0-beta.4",
"@page-agent/llms": "1.0.0-beta.3", "@page-agent/llms": "1.0.0-beta.4",
"@page-agent/page-controller": "1.0.0-beta.3", "@page-agent/page-controller": "1.0.0-beta.4",
"@page-agent/ui": "1.0.0-beta.3", "@page-agent/ui": "1.0.0-beta.4",
"chalk": "^5.6.2", "chalk": "^5.6.2",
"zod": "^4.3.5" "zod": "^4.3.5"
} }
}, },
"packages/page-controller": { "packages/page-controller": {
"name": "@page-agent/page-controller", "name": "@page-agent/page-controller",
"version": "1.0.0-beta.3", "version": "1.0.0-beta.4",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"ai-motion": "^0.4.8" "ai-motion": "^0.4.8"
@@ -11713,12 +11713,12 @@
}, },
"packages/ui": { "packages/ui": {
"name": "@page-agent/ui", "name": "@page-agent/ui",
"version": "1.0.0-beta.3", "version": "1.0.0-beta.4",
"license": "MIT" "license": "MIT"
}, },
"packages/website": { "packages/website": {
"name": "@page-agent/website", "name": "@page-agent/website",
"version": "1.0.0-beta.3", "version": "1.0.0-beta.4",
"dependencies": { "dependencies": {
"@radix-ui/react-icons": "^1.3.2", "@radix-ui/react-icons": "^1.3.2",
"@radix-ui/react-separator": "^1.1.8", "@radix-ui/react-separator": "^1.1.8",

View File

@@ -1,7 +1,7 @@
{ {
"name": "root", "name": "root",
"private": true, "private": true,
"version": "1.0.0-beta.3", "version": "1.0.0-beta.4",
"type": "module", "type": "module",
"workspaces": [ "workspaces": [
"packages/page-controller", "packages/page-controller",

View File

@@ -1,7 +1,7 @@
{ {
"name": "@page-agent/core", "name": "@page-agent/core",
"private": false, "private": false,
"version": "1.0.0-beta.3", "version": "1.0.0-beta.4",
"type": "module", "type": "module",
"main": "./dist/esm/page-agent-core.js", "main": "./dist/esm/page-agent-core.js",
"module": "./dist/esm/page-agent-core.js", "module": "./dist/esm/page-agent-core.js",
@@ -45,7 +45,7 @@
"dependencies": { "dependencies": {
"chalk": "^5.6.2", "chalk": "^5.6.2",
"zod": "^4.3.5", "zod": "^4.3.5",
"@page-agent/llms": "1.0.0-beta.3", "@page-agent/llms": "1.0.0-beta.4",
"@page-agent/page-controller": "1.0.0-beta.3" "@page-agent/page-controller": "1.0.0-beta.4"
} }
} }

View File

@@ -1,6 +1,6 @@
{ {
"name": "@page-agent/llms", "name": "@page-agent/llms",
"version": "1.0.0-beta.3", "version": "1.0.0-beta.4",
"type": "module", "type": "module",
"main": "./dist/lib/page-agent-llms.js", "main": "./dist/lib/page-agent-llms.js",
"module": "./dist/lib/page-agent-llms.js", "module": "./dist/lib/page-agent-llms.js",

View File

@@ -1,7 +1,7 @@
{ {
"name": "page-agent", "name": "page-agent",
"private": false, "private": false,
"version": "1.0.0-beta.3", "version": "1.0.0-beta.4",
"type": "module", "type": "module",
"main": "./dist/esm/page-agent.js", "main": "./dist/esm/page-agent.js",
"module": "./dist/esm/page-agent.js", "module": "./dist/esm/page-agent.js",
@@ -46,9 +46,9 @@
"dependencies": { "dependencies": {
"chalk": "^5.6.2", "chalk": "^5.6.2",
"zod": "^4.3.5", "zod": "^4.3.5",
"@page-agent/llms": "1.0.0-beta.3", "@page-agent/llms": "1.0.0-beta.4",
"@page-agent/page-controller": "1.0.0-beta.3", "@page-agent/page-controller": "1.0.0-beta.4",
"@page-agent/core": "1.0.0-beta.3", "@page-agent/core": "1.0.0-beta.4",
"@page-agent/ui": "1.0.0-beta.3" "@page-agent/ui": "1.0.0-beta.4"
} }
} }

View File

@@ -1,6 +1,6 @@
{ {
"name": "@page-agent/page-controller", "name": "@page-agent/page-controller",
"version": "1.0.0-beta.3", "version": "1.0.0-beta.4",
"type": "module", "type": "module",
"main": "./dist/lib/page-controller.js", "main": "./dist/lib/page-controller.js",
"module": "./dist/lib/page-controller.js", "module": "./dist/lib/page-controller.js",

View File

@@ -80,6 +80,9 @@ export class PageController extends EventTarget {
/** last time the tree was updated */ /** last time the tree was updated */
private lastTimeUpdate = 0 private lastTimeUpdate = 0
/** Whether the tree has been indexed at least once */
private isIndexed = false
/** Visual mask overlay for blocking user interaction during automation */ /** Visual mask overlay for blocking user interaction during automation */
private mask: InstanceType<typeof import('./mask/SimulatorMask').SimulatorMask> | null = null private mask: InstanceType<typeof import('./mask/SimulatorMask').SimulatorMask> | null = null
private maskReady: Promise<void> | null = null private maskReady: Promise<void> | null = null
@@ -196,6 +199,9 @@ export class PageController extends EventTarget {
this.elementTextMap.clear() this.elementTextMap.clear()
this.elementTextMap = dom.getElementTextMap(this.simplifiedHTML) this.elementTextMap = dom.getElementTextMap(this.simplifiedHTML)
// Mark as indexed - now element actions are allowed
this.isIndexed = true
// Restore mask blocking // Restore mask blocking
if (this.mask) { if (this.mask) {
this.mask.wrapper.style.pointerEvents = 'auto' this.mask.wrapper.style.pointerEvents = 'auto'
@@ -215,11 +221,22 @@ export class PageController extends EventTarget {
// ======= Element Actions ======= // ======= Element Actions =======
/**
* Ensure the tree has been indexed before any index-based operation.
* Throws if updateTree() hasn't been called yet.
*/
private assertIndexed(): void {
if (!this.isIndexed) {
throw new Error('DOM tree not indexed. Can not perform actions on elements.')
}
}
/** /**
* Click element by index * Click element by index
*/ */
async clickElement(index: number): Promise<ActionResult> { async clickElement(index: number): Promise<ActionResult> {
try { try {
this.assertIndexed()
const element = getElementByIndex(this.selectorMap, index) const element = getElementByIndex(this.selectorMap, index)
const elemText = this.elementTextMap.get(index) const elemText = this.elementTextMap.get(index)
await clickElement(element) await clickElement(element)
@@ -249,6 +266,7 @@ export class PageController extends EventTarget {
*/ */
async inputText(index: number, text: string): Promise<ActionResult> { async inputText(index: number, text: string): Promise<ActionResult> {
try { try {
this.assertIndexed()
const element = getElementByIndex(this.selectorMap, index) const element = getElementByIndex(this.selectorMap, index)
const elemText = this.elementTextMap.get(index) const elemText = this.elementTextMap.get(index)
await inputTextElement(element, text) await inputTextElement(element, text)
@@ -270,6 +288,7 @@ export class PageController extends EventTarget {
*/ */
async selectOption(index: number, optionText: string): Promise<ActionResult> { async selectOption(index: number, optionText: string): Promise<ActionResult> {
try { try {
this.assertIndexed()
const element = getElementByIndex(this.selectorMap, index) const element = getElementByIndex(this.selectorMap, index)
const elemText = this.elementTextMap.get(index) const elemText = this.elementTextMap.get(index)
await selectOptionElement(element as HTMLSelectElement, optionText) await selectOptionElement(element as HTMLSelectElement, optionText)
@@ -298,6 +317,8 @@ export class PageController extends EventTarget {
try { try {
const { down, numPages, pixels, index } = options const { down, numPages, pixels, index } = options
this.assertIndexed()
const scrollAmount = pixels ?? numPages * (down ? 1 : -1) * window.innerHeight const scrollAmount = pixels ?? numPages * (down ? 1 : -1) * window.innerHeight
const element = index !== undefined ? getElementByIndex(this.selectorMap, index) : null const element = index !== undefined ? getElementByIndex(this.selectorMap, index) : null
@@ -327,6 +348,8 @@ export class PageController extends EventTarget {
try { try {
const { right, pixels, index } = options const { right, pixels, index } = options
this.assertIndexed()
const scrollAmount = pixels * (right ? 1 : -1) const scrollAmount = pixels * (right ? 1 : -1)
const element = index !== undefined ? getElementByIndex(this.selectorMap, index) : null const element = index !== undefined ? getElementByIndex(this.selectorMap, index) : null
@@ -394,6 +417,7 @@ export class PageController extends EventTarget {
this.selectorMap.clear() this.selectorMap.clear()
this.elementTextMap.clear() this.elementTextMap.clear()
this.simplifiedHTML = '<EMPTY>' this.simplifiedHTML = '<EMPTY>'
this.isIndexed = false
this.mask?.dispose() this.mask?.dispose()
this.mask = null this.mask = null
} }

View File

@@ -1,6 +1,6 @@
{ {
"name": "@page-agent/ui", "name": "@page-agent/ui",
"version": "1.0.0-beta.3", "version": "1.0.0-beta.4",
"type": "module", "type": "module",
"main": "./dist/lib/page-agent-ui.js", "main": "./dist/lib/page-agent-ui.js",
"module": "./dist/lib/page-agent-ui.js", "module": "./dist/lib/page-agent-ui.js",

View File

@@ -1,7 +1,7 @@
{ {
"name": "@page-agent/website", "name": "@page-agent/website",
"private": true, "private": true,
"version": "1.0.0-beta.3", "version": "1.0.0-beta.4",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite --host 0.0.0.0", "dev": "vite --host 0.0.0.0",

View File

@@ -1,8 +1,8 @@
// Demo build (auto-init with demo LLM, for quick testing) // Demo build (auto-init with demo LLM, for quick testing)
export const CDN_DEMO_URL = export const CDN_DEMO_URL =
'https://cdn.jsdelivr.net/npm/page-agent@1.0.0-beta.3/dist/iife/page-agent.demo.js' 'https://cdn.jsdelivr.net/npm/page-agent@1.0.0-beta.4/dist/iife/page-agent.demo.js'
export const CDN_DEMO_CN_URL = export const CDN_DEMO_CN_URL =
'https://registry.npmmirror.com/page-agent/1.0.0-beta.3/files/dist/iife/page-agent.demo.js' 'https://registry.npmmirror.com/page-agent/1.0.0-beta.4/files/dist/iife/page-agent.demo.js'
// Demo LLM for website testing // Demo LLM for website testing
export const DEMO_MODEL = 'PAGE-AGENT-FREE-TESTING-RANDOM' export const DEMO_MODEL = 'PAGE-AGENT-FREE-TESTING-RANDOM'