Compare commits

..

19 Commits

Author SHA1 Message Date
Simon 64f1a8c443 chore(version): bump version to 0.0.14 2025-12-22 16:29:53 +08:00
Simon 635416f964 feat: implement @page-agent/llms 2025-12-22 16:29:19 +08:00
Simon 7c2d000e29 feat: create llms package and mv files 2025-12-22 16:12:34 +08:00
Simon b36a0c0261 chore(version): bump version to 0.0.13 2025-12-17 19:32:24 +08:00
Simon 339b066d2d fix(UMD): delay init 2025-12-17 19:31:28 +08:00
Simon c8efffa80a fix: update dotenv import and load config 2025-12-17 15:27:15 +08:00
Simon 59235263ad Merge pull request #80 from alibaba/fix/isPageDark
fix: isPageDark robust
2025-12-17 14:44:17 +08:00
Simon bc1e8fea3c fix: handle null body element 2025-12-17 14:40:11 +08:00
Simon 85a4096b2d chore(version): bump version to 0.0.12 2025-12-17 14:18:28 +08:00
Simon 0ef84bac13 chore: simplify Vite configuration 2025-12-16 20:38:15 +08:00
Simon a7834c77e1 docs: CDN and mirror 2025-12-16 20:23:17 +08:00
Simon 030e5cfc54 docs: stable CDN 2025-12-16 20:21:46 +08:00
Simon aa694e3b85 docs: stable CDN 2025-12-16 20:17:58 +08:00
Simon 2fee2d5ea3 chore: improve build scripts; change esm dir 2025-12-16 19:45:40 +08:00
Simon 3082843810 Merge pull request #77 from alibaba/dependabot/npm_and_yarn/development-dependencies-95987f47c2
chore(deps-dev): bump typescript-eslint from 8.49.0 to 8.50.0 in the development-dependencies group
2025-12-16 19:04:31 +08:00
Simon 34098e2f66 Merge pull request #76 from alibaba/dependabot/npm_and_yarn/production-dependencies-eefc12583a
chore(deps): bump zod from 4.1.13 to 4.2.0 in the production-dependencies group
2025-12-16 19:04:10 +08:00
dependabot[bot] 8461006c91 chore(deps-dev): bump typescript-eslint
Bumps the development-dependencies group with 1 update: [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint).


Updates `typescript-eslint` from 8.49.0 to 8.50.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.50.0/packages/typescript-eslint)

---
updated-dependencies:
- dependency-name: typescript-eslint
  dependency-version: 8.50.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: development-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-15 19:30:44 +00:00
dependabot[bot] 2e76a35188 chore(deps): bump zod in the production-dependencies group
Bumps the production-dependencies group with 1 update: [zod](https://github.com/colinhacks/zod).


Updates `zod` from 4.1.13 to 4.2.0
- [Release notes](https://github.com/colinhacks/zod/releases)
- [Commits](https://github.com/colinhacks/zod/compare/v4.1.13...v4.2.0)

---
updated-dependencies:
- dependency-name: zod
  dependency-version: 4.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-15 19:30:06 +00:00
Simon abc96b415f chore: clean up 2025-12-16 03:04:29 +08:00
42 changed files with 567 additions and 306 deletions
+1 -1
View File
@@ -25,7 +25,7 @@ jobs:
run: npm ci
- name: Build demo
run: npm run build
run: npm run build:website
- name: Setup Pages
uses: actions/configure-pages@v5
+1 -1
View File
@@ -29,7 +29,7 @@ jobs:
run: npm ci
- name: Build
run: npm run build
run: npm run build:libs
- name: Publish all public packages
run: npm publish --workspaces --access public
+8 -1
View File
@@ -1,6 +1,13 @@
{
"editor.fontLigatures": true,
"cSpell.words": ["HITL", "innerhtml", "opensource", "retryable", "wouter"],
"cSpell.words": [
"HITL",
"innerhtml",
"llms",
"opensource",
"retryable",
"wouter"
],
"markdownlint.config": {
// "comment": "Relaxed rules",
"default": true,
+2
View File
@@ -19,6 +19,8 @@ And other internal packages:
```bash
npm start # Start website dev server
npm run build # Build all packages
npm run build:libs # Build all libraries
npm run build:website # Build the website
npm run lint # ESLint with TypeScript strict rules
```
+5 -4
View File
@@ -31,10 +31,11 @@
### CDN 集成
```html
<!-- 临时 CDN URL. 未来会变更 -->
<script
src="https://hwcxiuzfylggtcktqgij.supabase.co/storage/v1/object/public/demo-public/v0.0.4/page-agent.js"
crossorigin="true"
// CDN - https://cdn.jsdelivr.net/npm/page-agent@latest/dist/umd/page-agent.js
// Mirror(CN) - https://registry.npmmirror.com/page-agent/latest/files/dist/umd/page-agent.js
<script
src="https://registry.npmmirror.com/page-agent/latest/files/dist/umd/page-agent.js"
crossorigin="true"
type="text/javascript"
></script>
```
+5 -4
View File
@@ -31,10 +31,11 @@ The GUI Agent Living in Your Webpage. Control web interfaces with natural langua
### CDN Integration
```html
<!-- temporary CDN URL. May change in the future -->
<script
src="https://hwcxiuzfylggtcktqgij.supabase.co/storage/v1/object/public/demo-public/v0.0.4/page-agent.js"
crossorigin="true"
// CDN - https://cdn.jsdelivr.net/npm/page-agent@latest/dist/umd/page-agent.js
// Mirror(CN) - https://registry.npmmirror.com/page-agent/latest/files/dist/umd/page-agent.js
<script
src="https://cdn.jsdelivr.net/npm/page-agent@latest/dist/umd/page-agent.js"
crossorigin="true"
type="text/javascript"
></script>
```
+90 -75
View File
@@ -1,16 +1,17 @@
{
"name": "root",
"version": "0.0.10",
"version": "0.0.14",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "root",
"version": "0.0.10",
"version": "0.0.14",
"license": "MIT",
"workspaces": [
"packages/page-controller",
"packages/ui",
"packages/llms",
"packages/page-agent",
"packages/website"
],
@@ -33,7 +34,7 @@
"lint-staged": "^16.2.4",
"prettier": "^3.7.4",
"typescript": "^5.9.3",
"typescript-eslint": "^8.49.0",
"typescript-eslint": "^8.50.0",
"unplugin-dts": "^1.0.0-beta.6",
"vite": "^7.3.0",
"vite-plugin-css-injected-by-js": "^3.5.2"
@@ -1558,6 +1559,10 @@
"url": "https://github.com/sponsors/epoberezkin"
}
},
"node_modules/@page-agent/llms": {
"resolved": "packages/llms",
"link": true
},
"node_modules/@page-agent/page-controller": {
"resolved": "packages/page-controller",
"link": true
@@ -2773,17 +2778,17 @@
}
},
"node_modules/@typescript-eslint/eslint-plugin": {
"version": "8.49.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.49.0.tgz",
"integrity": "sha512-JXij0vzIaTtCwu6SxTh8qBc66kmf1xs7pI4UOiMDFVct6q86G0Zs7KRcEoJgY3Cav3x5Tq0MF5jwgpgLqgKG3A==",
"version": "8.50.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.50.0.tgz",
"integrity": "sha512-O7QnmOXYKVtPrfYzMolrCTfkezCJS9+ljLdKW/+DCvRsc3UAz+sbH6Xcsv7p30+0OwUbeWfUDAQE0vpabZ3QLg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/regexpp": "^4.10.0",
"@typescript-eslint/scope-manager": "8.49.0",
"@typescript-eslint/type-utils": "8.49.0",
"@typescript-eslint/utils": "8.49.0",
"@typescript-eslint/visitor-keys": "8.49.0",
"@typescript-eslint/scope-manager": "8.50.0",
"@typescript-eslint/type-utils": "8.50.0",
"@typescript-eslint/utils": "8.50.0",
"@typescript-eslint/visitor-keys": "8.50.0",
"ignore": "^7.0.0",
"natural-compare": "^1.4.0",
"ts-api-utils": "^2.1.0"
@@ -2796,7 +2801,7 @@
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"@typescript-eslint/parser": "^8.49.0",
"@typescript-eslint/parser": "^8.50.0",
"eslint": "^8.57.0 || ^9.0.0",
"typescript": ">=4.8.4 <6.0.0"
}
@@ -2812,17 +2817,17 @@
}
},
"node_modules/@typescript-eslint/parser": {
"version": "8.49.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.49.0.tgz",
"integrity": "sha512-N9lBGA9o9aqb1hVMc9hzySbhKibHmB+N3IpoShyV6HyQYRGIhlrO5rQgttypi+yEeKsKI4idxC8Jw6gXKD4THA==",
"version": "8.50.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.50.0.tgz",
"integrity": "sha512-6/cmF2piao+f6wSxUsJLZjck7OQsYyRtcOZS02k7XINSNlz93v6emM8WutDQSXnroG2xwYlEVHJI+cPA7CPM3Q==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@typescript-eslint/scope-manager": "8.49.0",
"@typescript-eslint/types": "8.49.0",
"@typescript-eslint/typescript-estree": "8.49.0",
"@typescript-eslint/visitor-keys": "8.49.0",
"@typescript-eslint/scope-manager": "8.50.0",
"@typescript-eslint/types": "8.50.0",
"@typescript-eslint/typescript-estree": "8.50.0",
"@typescript-eslint/visitor-keys": "8.50.0",
"debug": "^4.3.4"
},
"engines": {
@@ -2838,14 +2843,14 @@
}
},
"node_modules/@typescript-eslint/project-service": {
"version": "8.49.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.49.0.tgz",
"integrity": "sha512-/wJN0/DKkmRUMXjZUXYZpD1NEQzQAAn9QWfGwo+Ai8gnzqH7tvqS7oNVdTjKqOcPyVIdZdyCMoqN66Ia789e7g==",
"version": "8.50.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.50.0.tgz",
"integrity": "sha512-Cg/nQcL1BcoTijEWyx4mkVC56r8dj44bFDvBdygifuS20f3OZCHmFbjF34DPSi07kwlFvqfv/xOLnJ5DquxSGQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/tsconfig-utils": "^8.49.0",
"@typescript-eslint/types": "^8.49.0",
"@typescript-eslint/tsconfig-utils": "^8.50.0",
"@typescript-eslint/types": "^8.50.0",
"debug": "^4.3.4"
},
"engines": {
@@ -2860,14 +2865,14 @@
}
},
"node_modules/@typescript-eslint/scope-manager": {
"version": "8.49.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.49.0.tgz",
"integrity": "sha512-npgS3zi+/30KSOkXNs0LQXtsg9ekZ8OISAOLGWA/ZOEn0ZH74Ginfl7foziV8DT+D98WfQ5Kopwqb/PZOaIJGg==",
"version": "8.50.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.50.0.tgz",
"integrity": "sha512-xCwfuCZjhIqy7+HKxBLrDVT5q/iq7XBVBXLn57RTIIpelLtEIZHXAF/Upa3+gaCpeV1NNS5Z9A+ID6jn50VD4A==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.49.0",
"@typescript-eslint/visitor-keys": "8.49.0"
"@typescript-eslint/types": "8.50.0",
"@typescript-eslint/visitor-keys": "8.50.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -2878,9 +2883,9 @@
}
},
"node_modules/@typescript-eslint/tsconfig-utils": {
"version": "8.49.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.49.0.tgz",
"integrity": "sha512-8prixNi1/6nawsRYxet4YOhnbW+W9FK/bQPxsGB1D3ZrDzbJ5FXw5XmzxZv82X3B+ZccuSxo/X8q9nQ+mFecWA==",
"version": "8.50.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.50.0.tgz",
"integrity": "sha512-vxd3G/ybKTSlm31MOA96gqvrRGv9RJ7LGtZCn2Vrc5htA0zCDvcMqUkifcjrWNNKXHUU3WCkYOzzVSFBd0wa2w==",
"dev": true,
"license": "MIT",
"engines": {
@@ -2895,15 +2900,15 @@
}
},
"node_modules/@typescript-eslint/type-utils": {
"version": "8.49.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.49.0.tgz",
"integrity": "sha512-KTExJfQ+svY8I10P4HdxKzWsvtVnsuCifU5MvXrRwoP2KOlNZ9ADNEWWsQTJgMxLzS5VLQKDjkCT/YzgsnqmZg==",
"version": "8.50.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.50.0.tgz",
"integrity": "sha512-7OciHT2lKCewR0mFoBrvZJ4AXTMe/sYOe87289WAViOocEmDjjv8MvIOT2XESuKj9jp8u3SZYUSh89QA4S1kQw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.49.0",
"@typescript-eslint/typescript-estree": "8.49.0",
"@typescript-eslint/utils": "8.49.0",
"@typescript-eslint/types": "8.50.0",
"@typescript-eslint/typescript-estree": "8.50.0",
"@typescript-eslint/utils": "8.50.0",
"debug": "^4.3.4",
"ts-api-utils": "^2.1.0"
},
@@ -2920,9 +2925,9 @@
}
},
"node_modules/@typescript-eslint/types": {
"version": "8.49.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.49.0.tgz",
"integrity": "sha512-e9k/fneezorUo6WShlQpMxXh8/8wfyc+biu6tnAqA81oWrEic0k21RHzP9uqqpyBBeBKu4T+Bsjy9/b8u7obXQ==",
"version": "8.50.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.50.0.tgz",
"integrity": "sha512-iX1mgmGrXdANhhITbpp2QQM2fGehBse9LbTf0sidWK6yg/NE+uhV5dfU1g6EYPlcReYmkE9QLPq/2irKAmtS9w==",
"dev": true,
"license": "MIT",
"engines": {
@@ -2934,16 +2939,16 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
"version": "8.49.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.49.0.tgz",
"integrity": "sha512-jrLdRuAbPfPIdYNppHJ/D0wN+wwNfJ32YTAm10eJVsFmrVpXQnDWBn8niCSMlWjvml8jsce5E/O+86IQtTbJWA==",
"version": "8.50.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.50.0.tgz",
"integrity": "sha512-W7SVAGBR/IX7zm1t70Yujpbk+zdPq/u4soeFSknWFdXIFuWsBGBOUu/Tn/I6KHSKvSh91OiMuaSnYp3mtPt5IQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/project-service": "8.49.0",
"@typescript-eslint/tsconfig-utils": "8.49.0",
"@typescript-eslint/types": "8.49.0",
"@typescript-eslint/visitor-keys": "8.49.0",
"@typescript-eslint/project-service": "8.50.0",
"@typescript-eslint/tsconfig-utils": "8.50.0",
"@typescript-eslint/types": "8.50.0",
"@typescript-eslint/visitor-keys": "8.50.0",
"debug": "^4.3.4",
"minimatch": "^9.0.4",
"semver": "^7.6.0",
@@ -2988,16 +2993,16 @@
}
},
"node_modules/@typescript-eslint/utils": {
"version": "8.49.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.49.0.tgz",
"integrity": "sha512-N3W7rJw7Rw+z1tRsHZbK395TWSYvufBXumYtEGzypgMUthlg0/hmCImeA8hgO2d2G4pd7ftpxxul2J8OdtdaFA==",
"version": "8.50.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.50.0.tgz",
"integrity": "sha512-87KgUXET09CRjGCi2Ejxy3PULXna63/bMYv72tCAlDJC3Yqwln0HiFJ3VJMst2+mEtNtZu5oFvX4qJGjKsnAgg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.7.0",
"@typescript-eslint/scope-manager": "8.49.0",
"@typescript-eslint/types": "8.49.0",
"@typescript-eslint/typescript-estree": "8.49.0"
"@typescript-eslint/scope-manager": "8.50.0",
"@typescript-eslint/types": "8.50.0",
"@typescript-eslint/typescript-estree": "8.50.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -3012,13 +3017,13 @@
}
},
"node_modules/@typescript-eslint/visitor-keys": {
"version": "8.49.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.49.0.tgz",
"integrity": "sha512-LlKaciDe3GmZFphXIc79THF/YYBugZ7FS1pO581E/edlVVNbZKDy93evqmrfQ9/Y4uN0vVhX4iuchq26mK/iiA==",
"version": "8.50.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.50.0.tgz",
"integrity": "sha512-Xzmnb58+Db78gT/CCj/PVCvK+zxbnsw6F+O1oheYszJbBSdEjVhQi3C/Xttzxgi/GLmpvOggRs1RFpiJ8+c34Q==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.49.0",
"@typescript-eslint/types": "8.50.0",
"eslint-visitor-keys": "^4.2.1"
},
"engines": {
@@ -6617,16 +6622,16 @@
}
},
"node_modules/typescript-eslint": {
"version": "8.49.0",
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.49.0.tgz",
"integrity": "sha512-zRSVH1WXD0uXczCXw+nsdjGPUdx4dfrs5VQoHnUWmv1U3oNlAKv4FUNdLDhVUg+gYn+a5hUESqch//Rv5wVhrg==",
"version": "8.50.0",
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.50.0.tgz",
"integrity": "sha512-Q1/6yNUmCpH94fbgMUMg2/BSAr/6U7GBk61kZTv1/asghQOWOjTlp9K8mixS5NcJmm2creY+UFfGeW/+OcA64A==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/eslint-plugin": "8.49.0",
"@typescript-eslint/parser": "8.49.0",
"@typescript-eslint/typescript-estree": "8.49.0",
"@typescript-eslint/utils": "8.49.0"
"@typescript-eslint/eslint-plugin": "8.50.0",
"@typescript-eslint/parser": "8.50.0",
"@typescript-eslint/typescript-estree": "8.50.0",
"@typescript-eslint/utils": "8.50.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@@ -7161,9 +7166,9 @@
}
},
"node_modules/zod": {
"version": "4.1.13",
"resolved": "https://registry.npmjs.org/zod/-/zod-4.1.13.tgz",
"integrity": "sha512-AvvthqfqrAhNH9dnfmrfKzX5upOdjUVJYFqNSlkmGf64gRaTzlPwz99IHYnVs28qYAybvAlBV+H7pn0saFY4Ig==",
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/zod/-/zod-4.2.0.tgz",
"integrity": "sha512-Bd5fw9wlIhtqCCxotZgdTOMwGm1a0u75wARVEY9HMs1X17trvA/lMi4+MGK5EUfYkXVTbX8UDiDKW4OgzHVUZw==",
"license": "MIT",
"peer": true,
"funding": {
@@ -7183,24 +7188,34 @@
"zod": "^3.25.0 || ^4.0.0"
}
},
"packages/page-agent": {
"version": "0.0.10",
"packages/llms": {
"name": "@page-agent/llms",
"version": "0.0.14",
"license": "MIT",
"dependencies": {
"@page-agent/page-controller": "0.0.10",
"@page-agent/ui": "0.0.10",
"chalk": "^5.6.2",
"zod": "^4.1.12"
"zod": "^4.2.0"
}
},
"packages/page-agent": {
"version": "0.0.14",
"license": "MIT",
"dependencies": {
"@page-agent/llms": "0.0.14",
"@page-agent/page-controller": "0.0.14",
"@page-agent/ui": "0.0.14",
"chalk": "^5.6.2",
"zod": "^4.2.0"
}
},
"packages/page-controller": {
"name": "@page-agent/page-controller",
"version": "0.0.10",
"version": "0.0.14",
"license": "MIT"
},
"packages/ui": {
"name": "@page-agent/ui",
"version": "0.0.10",
"version": "0.0.14",
"license": "MIT",
"dependencies": {
"ai-motion": "^0.4.7"
@@ -7208,7 +7223,7 @@
},
"packages/website": {
"name": "@page-agent/website",
"version": "0.0.10",
"version": "0.0.14",
"devDependencies": {
"@tailwindcss/vite": "^4.1.18",
"@types/react": "^19.2.2",
+6 -3
View File
@@ -1,11 +1,12 @@
{
"name": "root",
"private": true,
"version": "0.0.10",
"version": "0.0.14",
"type": "module",
"workspaces": [
"packages/page-controller",
"packages/ui",
"packages/llms",
"packages/page-agent",
"packages/website"
],
@@ -23,7 +24,9 @@
},
"scripts": {
"start": "npm run dev --workspace=@page-agent/website",
"build": "npm run build --workspaces --if-present",
"build:website": "npm run build:website --workspace=@page-agent/website",
"build:libs": "npm run build --workspaces --if-present",
"build": "npm run build:libs && npm run build:website",
"dev:umd": "npm run dev:umd --workspace=page-agent",
"version": "node scripts/sync-version.js",
"lint": "eslint .",
@@ -48,7 +51,7 @@
"lint-staged": "^16.2.4",
"prettier": "^3.7.4",
"typescript": "^5.9.3",
"typescript-eslint": "^8.49.0",
"typescript-eslint": "^8.50.0",
"unplugin-dts": "^1.0.0-beta.6",
"vite": "^7.3.0",
"vite-plugin-css-injected-by-js": "^3.5.2"
+41
View File
@@ -0,0 +1,41 @@
# @page-agent/llms
LLM client with a **reflection-before-action** mental model for page-agent.
## Why This Package Exists
The LLM module and the agent logic are inherently coupled. This package exists not to decouple them, but to **define the interface contract** between the LLM and the agent.
The core abstraction is the `MacroToolInput` — a structured output format that **forces the model to reflect before acting**.
## The Reflection-Before-Action Model
Every tool call must first output its reasoning state before the actual action:
```typescript
interface MacroToolInput {
// Reflection (mandatory before any action)
evaluation_previous_goal?: string // How well did the previous action work?
memory?: string // Key information to remember
next_goal?: string // What to accomplish next
// Action (the actual operation)
action: Record<string, any>
}
```
This design ensures that:
1. **The model evaluates its previous action** before deciding the next step
2. **Working memory is explicitly maintained** across conversation turns
3. **Goals are clearly stated**, making the agent's reasoning transparent and debuggable
## Key Components
| Export | Description |
|--------|-------------|
| `LLM` | Main LLM client class with retry logic |
| `MacroToolInput` | The reflection-before-action input schema |
| `AgentBrain` | Agent's thinking state (eval, memory, goal) |
| `LLMConfig` | Configuration for LLM connection |
| `parseLLMConfig` | Parse and apply defaults to config |
+43
View File
@@ -0,0 +1,43 @@
{
"name": "@page-agent/llms",
"version": "0.0.14",
"type": "module",
"main": "./dist/lib/page-agent-llms.js",
"module": "./dist/lib/page-agent-llms.js",
"types": "./dist/lib/index.d.ts",
"exports": {
".": {
"types": "./dist/lib/index.d.ts",
"import": "./dist/lib/page-agent-llms.js",
"default": "./dist/lib/page-agent-llms.js"
}
},
"files": [
"dist/"
],
"description": "LLM client with reflection-before-action mental model for page-agent",
"keywords": [
"page-agent",
"llm",
"openai",
"tool-calling",
"agent"
],
"author": "Simon<gaomeng1900>",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/alibaba/page-agent.git",
"directory": "packages/llms"
},
"homepage": "https://alibaba.github.io/page-agent/",
"scripts": {
"build": "vite build",
"prepublishOnly": "node -e \"const fs=require('fs');['LICENSE'].forEach(f=>fs.copyFileSync('../../'+f,f))\"",
"postpublish": "node -e \"['LICENSE'].forEach(f=>{try{require('fs').unlinkSync(f)}catch{}})\""
},
"dependencies": {
"chalk": "^5.6.2",
"zod": "^4.2.0"
}
}
@@ -1,9 +1,15 @@
/**
* OpenAI Client implementation
*/
import type { MacroToolInput } from '../PageAgent'
import { InvokeError, InvokeErrorType } from './errors'
import type { InvokeResult, LLMClient, Message, OpenAIClientConfig, Tool } from './types'
import type {
InvokeResult,
LLMClient,
MacroToolInput,
Message,
OpenAIClientConfig,
Tool,
} from './types'
import { lenientParseMacroToolCall, modelPatch, zodToOpenAITool } from './utils'
export class OpenAIClient implements LLMClient {
+21
View File
@@ -0,0 +1,21 @@
// Dev environment: use .env config if available, otherwise fallback to testing api
export const DEFAULT_MODEL_NAME: string =
import.meta.env.DEV && import.meta.env.LLM_MODEL_NAME
? import.meta.env.LLM_MODEL_NAME
: 'PAGE-AGENT-FREE-TESTING-RANDOM'
export const DEFAULT_API_KEY: string =
import.meta.env.DEV && import.meta.env.LLM_API_KEY
? import.meta.env.LLM_API_KEY
: 'PAGE-AGENT-FREE-TESTING-RANDOM'
export const DEFAULT_BASE_URL: string =
import.meta.env.DEV && import.meta.env.LLM_BASE_URL
? import.meta.env.LLM_BASE_URL
: 'https://hwcxiuzfylggtcktqgij.supabase.co/functions/v1/llm-testing-proxy'
// internal
export const LLM_MAX_RETRIES = 2
export const DEFAULT_TEMPERATURE = 0.7 // higher randomness helps auto-recovery
export const DEFAULT_MAX_TOKENS = 4096
+1
View File
@@ -0,0 +1 @@
/// <reference types="vite/client" />
@@ -31,13 +31,48 @@
* - 使 tool call
* - tool 使 tool call
*/
import type { LLMConfig } from '../config'
import { parseLLMConfig } from '../config'
import { OpenAIClient } from './OpenAILenientClient'
import {
DEFAULT_API_KEY,
DEFAULT_BASE_URL,
DEFAULT_MAX_TOKENS,
DEFAULT_MODEL_NAME,
DEFAULT_TEMPERATURE,
LLM_MAX_RETRIES,
} from './constants'
import { InvokeError } from './errors'
import type { InvokeResult, LLMClient, Message, Tool } from './types'
import type {
AgentBrain,
InvokeResult,
LLMClient,
LLMConfig,
MacroToolInput,
MacroToolResult,
Message,
Tool,
} from './types'
export type { Message, Tool, InvokeResult, LLMClient }
export type {
AgentBrain,
InvokeResult,
LLMClient,
LLMConfig,
MacroToolInput,
MacroToolResult,
Message,
Tool,
}
export function parseLLMConfig(config: LLMConfig): Required<LLMConfig> {
return {
baseURL: config.baseURL ?? DEFAULT_BASE_URL,
apiKey: config.apiKey ?? DEFAULT_API_KEY,
model: config.model ?? DEFAULT_MODEL_NAME,
temperature: config.temperature ?? DEFAULT_TEMPERATURE,
maxTokens: config.maxTokens ?? DEFAULT_MAX_TOKENS,
maxRetries: config.maxRetries ?? LLM_MAX_RETRIES,
}
}
export class LLM extends EventTarget {
config: Required<LLMConfig>
@@ -75,3 +75,48 @@ export interface OpenAIClientConfig {
maxTokens?: number
maxRetries?: number
}
/**
* LLM configuration for PageAgent
*/
export interface LLMConfig {
baseURL?: string
apiKey?: string
model?: string
temperature?: number
maxTokens?: number
maxRetries?: number
}
/**
* Agent brain state - the reflection-before-action model
*
* Every tool call must first reflect on:
* - evaluation_previous_goal: How well did the previous action achieve its goal?
* - memory: Key information to remember for future steps
* - next_goal: What should be accomplished in the next action?
*/
export interface AgentBrain {
// thinking?: string
evaluation_previous_goal: string
memory: string
next_goal: string
}
/**
* MacroTool input structure
*
* This is the core abstraction that enforces the "reflection-before-action" mental model.
* Before executing any action, the LLM must output its reasoning state.
*/
export interface MacroToolInput extends AgentBrain {
action: Record<string, any>
}
/**
* MacroTool output structure
*/
export interface MacroToolResult {
input: MacroToolInput
output: string
}
@@ -4,9 +4,8 @@
import chalk from 'chalk'
import { z } from 'zod'
import type { MacroToolInput } from '../PageAgent'
import { InvokeError, InvokeErrorType } from './errors'
import type { Tool } from './types'
import type { MacroToolInput, Tool } from './types'
/**
* Convert Zod schema to OpenAI tool format
+10
View File
@@ -0,0 +1,10 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
// @workaround DTS bug
// dts do not work with monorepo path mapping
// disable path mapping for it
"paths": {}
}
}
+13
View File
@@ -0,0 +1,13 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.tsbuildinfo",
"noEmit": false,
"allowImportingTsExtensions": false,
"baseUrl": ".",
"outDir": "dist"
},
"include": ["**/*.ts"],
"exclude": ["dist", "node_modules"]
}
+37
View File
@@ -0,0 +1,37 @@
// @ts-check
import chalk from 'chalk'
import { dirname, resolve } from 'path'
import dts from 'unplugin-dts/vite'
import { fileURLToPath } from 'url'
import { defineConfig } from 'vite'
const __dirname = dirname(fileURLToPath(import.meta.url))
console.log(chalk.cyan(`📦 Building @page-agent/llms`))
export default defineConfig({
clearScreen: false,
plugins: [dts({ tsconfigPath: './tsconfig.dts.json', bundleTypes: true })],
publicDir: false,
esbuild: {
keepNames: true,
},
build: {
lib: {
entry: resolve(__dirname, 'src/index.ts'),
name: 'PageAgentLLMs',
fileName: 'page-agent-llms',
formats: ['es'],
},
outDir: resolve(__dirname, 'dist', 'lib'),
rollupOptions: {
external: ['chalk', 'zod'],
},
minify: false,
sourcemap: true,
},
define: {
'process.env.NODE_ENV': '"production"',
},
})
+13 -12
View File
@@ -1,16 +1,16 @@
{
"name": "page-agent",
"private": false,
"version": "0.0.10",
"version": "0.0.14",
"type": "module",
"main": "./dist/lib/page-agent.js",
"module": "./dist/lib/page-agent.js",
"types": "./dist/lib/PageAgent.d.ts",
"main": "./dist/esm/page-agent.js",
"module": "./dist/esm/page-agent.js",
"types": "./dist/esm/PageAgent.d.ts",
"exports": {
".": {
"types": "./dist/lib/PageAgent.d.ts",
"import": "./dist/lib/page-agent.js",
"default": "./dist/lib/page-agent.js"
"types": "./dist/esm/PageAgent.d.ts",
"import": "./dist/esm/page-agent.js",
"default": "./dist/esm/page-agent.js"
}
},
"files": [
@@ -37,16 +37,17 @@
},
"homepage": "https://alibaba.github.io/page-agent/",
"scripts": {
"build": "MODE=lib vite build && MODE=umd vite build",
"build": "vite build && vite build --config vite.umd.config.js",
"serve": "npx serve dist/umd -p 5173",
"dev:umd": "concurrently \"MODE=umd vite build --watch\" \"npm run serve\"",
"dev:umd": "concurrently \"vite build --config vite.umd.config.js --watch\" \"npm run serve\"",
"prepublishOnly": "node -e \"const fs=require('fs');['README.md','LICENSE'].forEach(f=>fs.copyFileSync('../../'+f,f))\"",
"postpublish": "node -e \"['README.md','LICENSE'].forEach(f=>{try{require('fs').unlinkSync(f)}catch{}})\""
},
"dependencies": {
"chalk": "^5.6.2",
"zod": "^4.1.12",
"@page-agent/page-controller": "0.0.10",
"@page-agent/ui": "0.0.10"
"zod": "^4.2.0",
"@page-agent/llms": "0.0.14",
"@page-agent/page-controller": "0.0.14",
"@page-agent/ui": "0.0.14"
}
}
+8 -26
View File
@@ -2,6 +2,13 @@
* Copyright (C) 2025 Alibaba Group Holding Limited
* All rights reserved.
*/
import {
type AgentBrain,
LLM,
type MacroToolInput,
type MacroToolResult,
type Tool,
} from '@page-agent/llms'
import { PageController } from '@page-agent/page-controller'
import { Panel, SimulatorMask } from '@page-agent/ui'
import chalk from 'chalk'
@@ -9,7 +16,6 @@ import zod from 'zod'
import type { PageAgentConfig } from './config'
import { MAX_STEPS } from './config/constants'
import { LLM, type Tool } from './llms'
import SYSTEM_PROMPT from './prompts/system_prompt.md?raw'
import { tools } from './tools'
import { trimLines, uid, waitUntil } from './utils'
@@ -17,31 +23,7 @@ import { assert } from './utils/assert'
export type { PageAgentConfig }
export { tool, type PageAgentTool } from './tools'
export interface AgentBrain {
// thinking?: string
evaluation_previous_goal: string
memory: string
next_goal: string
}
/**
* MacroTool input structure
*/
export interface MacroToolInput {
evaluation_previous_goal?: string
memory?: string
next_goal?: string
action: Record<string, any>
}
/**
* MacroTool output structure
*/
export interface MacroToolResult {
input: MacroToolInput
output: string
}
export type { AgentBrain, MacroToolInput, MacroToolResult }
export interface AgentHistory {
brain: AgentBrain
+1 -21
View File
@@ -1,22 +1,2 @@
// Dev environment: use .env config if available, otherwise fallback to testing api
export const DEFAULT_MODEL_NAME: string =
import.meta.env.DEV && import.meta.env.LLM_MODEL_NAME
? import.meta.env.LLM_MODEL_NAME
: 'PAGE-AGENT-FREE-TESTING-RANDOM'
export const DEFAULT_API_KEY: string =
import.meta.env.DEV && import.meta.env.LLM_API_KEY
? import.meta.env.LLM_API_KEY
: 'PAGE-AGENT-FREE-TESTING-RANDOM'
export const DEFAULT_BASE_URL: string =
import.meta.env.DEV && import.meta.env.LLM_BASE_URL
? import.meta.env.LLM_BASE_URL
: 'https://hwcxiuzfylggtcktqgij.supabase.co/functions/v1/llm-testing-proxy'
// internal
export const LLM_MAX_RETRIES = 2
// Agent-specific constants (LLM constants moved to @page-agent/llms)
export const MAX_STEPS = 20
export const DEFAULT_TEMPERATURE = 0.7 // higher randomness helps auto-recovery
export const DEFAULT_MAX_TOKENS = 4096
+2 -27
View File
@@ -1,25 +1,11 @@
import type { LLMConfig } from '@page-agent/llms'
import type { PageControllerConfig } from '@page-agent/page-controller'
import type { SupportedLanguage } from '@page-agent/ui'
import type { AgentHistory, ExecutionResult, PageAgent } from '../PageAgent'
import type { PageAgentTool } from '../tools'
import {
DEFAULT_API_KEY,
DEFAULT_BASE_URL,
DEFAULT_MAX_TOKENS,
DEFAULT_MODEL_NAME,
DEFAULT_TEMPERATURE,
LLM_MAX_RETRIES,
} from './constants'
export interface LLMConfig {
baseURL?: string
apiKey?: string
model?: string
temperature?: number
maxTokens?: number
maxRetries?: number
}
export type { LLMConfig }
export interface AgentConfig {
// theme?: 'light' | 'dark'
@@ -96,14 +82,3 @@ export interface AgentConfig {
}
export type PageAgentConfig = LLMConfig & AgentConfig & PageControllerConfig
export function parseLLMConfig(config: LLMConfig): Required<LLMConfig> {
return {
baseURL: config.baseURL ?? DEFAULT_BASE_URL,
apiKey: config.apiKey ?? DEFAULT_API_KEY,
model: config.model ?? DEFAULT_MODEL_NAME,
temperature: config.temperature ?? DEFAULT_TEMPERATURE,
maxTokens: config.maxTokens ?? DEFAULT_MAX_TOKENS,
maxRetries: config.maxRetries ?? LLM_MAX_RETRIES,
}
}
+20 -16
View File
@@ -20,21 +20,25 @@ const DEMO_MODEL = 'PAGE-AGENT-FREE-TESTING-RANDOM'
const DEMO_BASE_URL = 'https://hwcxiuzfylggtcktqgij.supabase.co/functions/v1/llm-testing-proxy'
const DEMO_API_KEY = 'PAGE-AGENT-FREE-TESTING-RANDOM'
const currentScript = document.currentScript as HTMLScriptElement | null
if (currentScript) {
console.log('🚀 page-agent.js detected current script:', currentScript.src)
const url = new URL(currentScript.src)
const model = url.searchParams.get('model') || DEMO_MODEL
const baseURL = url.searchParams.get('baseURL') || DEMO_BASE_URL
const apiKey = url.searchParams.get('apiKey') || DEMO_API_KEY
const language = (url.searchParams.get('lang') as 'zh-CN' | 'en-US') || 'zh-CN'
const config: PageAgentConfig = { model, baseURL, apiKey, language }
window.pageAgent = new PageAgent(config)
} else {
console.log('🚀 page-agent.js no current script detected, using default demo config')
window.pageAgent = new PageAgent()
}
// in case document.x is not ready yet
// @todo give a switch to disable auto-init
setTimeout(() => {
const currentScript = document.currentScript as HTMLScriptElement | null
if (currentScript) {
console.log('🚀 page-agent.js detected current script:', currentScript.src)
const url = new URL(currentScript.src)
const model = url.searchParams.get('model') || DEMO_MODEL
const baseURL = url.searchParams.get('baseURL') || DEMO_BASE_URL
const apiKey = url.searchParams.get('apiKey') || DEMO_API_KEY
const language = (url.searchParams.get('lang') as 'zh-CN' | 'en-US') || 'zh-CN'
const config: PageAgentConfig = { model, baseURL, apiKey, language }
window.pageAgent = new PageAgent(config)
} else {
console.log('🚀 page-agent.js no current script detected, using default demo config')
window.pageAgent = new PageAgent()
}
console.log('🚀 page-agent.js initialized with config:', window.pageAgent.config)
console.log('🚀 page-agent.js initialized with config:', window.pageAgent.config)
window.pageAgent.panel.show() // Show panel
window.pageAgent.panel.show() // Show panel
})
+2
View File
@@ -8,6 +8,7 @@
"outDir": "dist",
"paths": {
//
"@page-agent/llms": ["../llms/src/index.ts"],
"@page-agent/page-controller": ["../page-controller/src/PageController.ts"],
"@page-agent/ui": ["../ui/src/index.ts"]
}
@@ -16,6 +17,7 @@
"exclude": ["dist", "node_modules"],
"references": [
//
{ "path": "../llms" },
{ "path": "../page-controller" },
{ "path": "../ui" }
]
+4 -61
View File
@@ -1,7 +1,4 @@
// @ts-check
import chalk from 'chalk'
import 'dotenv/config'
import process from 'node:process'
import { dirname, resolve } from 'path'
import dts from 'unplugin-dts/vite'
import { fileURLToPath } from 'url'
@@ -10,15 +7,11 @@ import cssInjectedByJsPlugin from 'vite-plugin-css-injected-by-js'
const __dirname = dirname(fileURLToPath(import.meta.url))
// ============================================================================
// Library Config (ES Module for NPM Package)
// ============================================================================
/** @type {import('vite').UserConfig} */
const libConfig = {
// ES Module for NPM Package
export default defineConfig({
clearScreen: false,
plugins: [
dts({ tsconfigPath: './tsconfig.dts.json', bundleTypes: true }),
// dts({ tsconfigPath: './tsconfig.json', bundleTypes: true, compilerOptions: { paths: {} } }),
cssInjectedByJsPlugin({ relativeCSSInjection: true }),
],
publicDir: false,
@@ -32,10 +25,9 @@ const libConfig = {
fileName: 'page-agent',
formats: ['es'],
},
outDir: resolve(__dirname, 'dist', 'lib'),
outDir: resolve(__dirname, 'dist', 'esm'),
rollupOptions: {
external: [
'ai-motion',
'chalk',
'zod',
// all the internal packages
@@ -49,53 +41,4 @@ const libConfig = {
define: {
'process.env.NODE_ENV': '"production"',
},
}
// ============================================================================
// UMD Config (Browser Bundle for CDN)
// - alias all local packages so that they can be build in
// - no external
// - no d.ts. dts does not work with monorepo aliasing
// ============================================================================
/** @type {import('vite').UserConfig} */
const umdConfig = {
plugins: [cssInjectedByJsPlugin({ relativeCSSInjection: true })],
publicDir: false,
esbuild: {
keepNames: true,
},
resolve: {
alias: {
'@page-agent/page-controller': resolve(__dirname, '../page-controller/src/PageController.ts'),
'@page-agent/ui': resolve(__dirname, '../ui/src/index.ts'),
},
},
build: {
lib: {
entry: resolve(__dirname, 'src/umd.ts'),
name: 'PageAgent',
fileName: 'page-agent',
formats: ['umd'],
},
outDir: resolve(__dirname, 'dist', 'umd'),
cssCodeSplit: true,
},
define: {
'process.env.NODE_ENV': '"production"',
},
}
// ============================================================================
const MODE = process.env.MODE
console.log(chalk.cyan(`📦 Build mode: ${chalk.bold(MODE || 'lib')}`))
let config
if (MODE === 'umd') {
config = umdConfig
} else {
config = libConfig
}
export default defineConfig(config)
})
+45
View File
@@ -0,0 +1,45 @@
// @ts-check
import { dirname, resolve } from 'path'
import { fileURLToPath } from 'url'
import { defineConfig } from 'vite'
import cssInjectedByJsPlugin from 'vite-plugin-css-injected-by-js'
const __dirname = dirname(fileURLToPath(import.meta.url))
// UMD Bundle for CDN
// - alias all local packages so that they can be build in
// - no external
// - no d.ts. dts does not work with monorepo aliasing
export default defineConfig({
plugins: [cssInjectedByJsPlugin({ relativeCSSInjection: true })],
publicDir: false,
esbuild: {
keepNames: true,
},
resolve: {
alias: {
'@page-agent/page-controller': resolve(__dirname, '../page-controller/src/PageController.ts'),
'@page-agent/llms': resolve(__dirname, '../llms/src/index.ts'),
'@page-agent/ui': resolve(__dirname, '../ui/src/index.ts'),
},
},
build: {
lib: {
entry: resolve(__dirname, 'src/umd.ts'),
name: 'PageAgent',
fileName: 'page-agent',
formats: ['umd'],
},
outDir: resolve(__dirname, 'dist', 'umd'),
rollupOptions: {
output: {
// force use .js as extension
entryFileNames: 'page-agent.js',
},
},
cssCodeSplit: true,
},
define: {
'process.env.NODE_ENV': '"production"',
},
})
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@page-agent/page-controller",
"version": "0.0.10",
"version": "0.0.14",
"type": "module",
"main": "./dist/lib/page-controller.js",
"module": "./dist/lib/page-controller.js",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@page-agent/ui",
"version": "0.0.10",
"version": "0.0.14",
"type": "module",
"main": "./dist/lib/page-agent-ui.js",
"module": "./dist/lib/page-agent-ui.js",
+23 -18
View File
@@ -3,14 +3,14 @@
* @returns {boolean} - True if a common dark mode class is found.
*/
function hasDarkModeClass() {
const DFEAULT_DARK_MODE_CLASSES = ['dark', 'dark-mode', 'theme-dark', 'night', 'night-mode']
const DEFAULT_DARK_MODE_CLASSES = ['dark', 'dark-mode', 'theme-dark', 'night', 'night-mode']
const htmlElement = document.documentElement
const bodyElement = document.body
const bodyElement = document.body || document.documentElement // can be null in some cases
// Check class names on <html> and <body>
for (const className of DFEAULT_DARK_MODE_CLASSES) {
if (htmlElement.classList.contains(className) || bodyElement.classList.contains(className)) {
for (const className of DEFAULT_DARK_MODE_CLASSES) {
if (htmlElement.classList.contains(className) || bodyElement?.classList.contains(className)) {
return true
}
}
@@ -70,7 +70,7 @@ function isColorDark(colorString: string, threshold = 128) {
function isBackgroundDark() {
// We check both <html> and <body> because some pages set the color on <html>
const htmlStyle = window.getComputedStyle(document.documentElement)
const bodyStyle = window.getComputedStyle(document.body)
const bodyStyle = window.getComputedStyle(document.body || document.documentElement)
// Get background colors
const htmlBgColor = htmlStyle.backgroundColor
@@ -93,18 +93,23 @@ function isBackgroundDark() {
* @returns {boolean} - True if the page is likely dark.
*/
export function isPageDark() {
// Strategy 1: Check for common dark mode classes
if (hasDarkModeClass()) {
return true
try {
// Strategy 1: Check for common dark mode classes
if (hasDarkModeClass()) {
return true
}
// Strategy 2: Analyze the computed background color
if (isBackgroundDark()) {
return true
}
// @TODO add more checks here, e.g., analyzing text color,
// or checking the background of major layout elements like <main> or #app.
return false
} catch (error) {
console.warn('Error determining if page is dark:', error)
return false
}
// Strategy 2: Analyze the computed background color
if (isBackgroundDark()) {
return true
}
// @TODO add more checks here, e.g., analyzing text color,
// or checking the background of major layout elements like <main> or #app.
return false
}
+2 -2
View File
@@ -1,11 +1,11 @@
{
"name": "@page-agent/website",
"private": true,
"version": "0.0.10",
"version": "0.0.14",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"build:website": "vite build",
"preview": "vite preview",
"typecheck": "tsc --noEmit"
},
+3
View File
@@ -0,0 +1,3 @@
export const CDN_URL = 'https://cdn.jsdelivr.net/npm/page-agent@latest/dist/umd/page-agent.js'
export const CDN_CN_URL =
'https://registry.npmmirror.com/page-agent/latest/files/dist/umd/page-agent.js'
@@ -1,5 +1,6 @@
import BetaNotice from '@/components/BetaNotice'
import CodeEditor from '@/components/CodeEditor'
import { CDN_CN_URL, CDN_URL } from '@/constants'
export default function CdnSetup() {
return (
@@ -15,11 +16,16 @@ export default function CdnSetup() {
<CodeEditor
className="mb-8"
code={`
// 仅供测试使用,稳定 CDN 待定
<script src="https://hwcxiuzfylggtcktqgij.supabase.co/storage/v1/object/public/demo-public/v0.0.4/page-agent.js" crossorigin="true" type="text/javascript"></script>
// CDN: \t${CDN_URL}
// Mirror: \t${CDN_CN_URL}
<script
src="${CDN_URL}"
crossorigin="true"
type="text/javascript"
></script>
<script>
window.pageAgent.panel.show()
// window.pageAgent
</script>`}
/>
@@ -2,6 +2,7 @@ import { useTranslation } from 'react-i18next'
import BetaNotice from '@/components/BetaNotice'
import CodeEditor from '@/components/CodeEditor'
import { CDN_CN_URL, CDN_URL } from '@/constants'
export default function QuickStart() {
const { t } = useTranslation('docs')
@@ -23,8 +24,9 @@ export default function QuickStart() {
<div>
<p className="text-sm font-medium mb-2">{t('quick_start.step1_cdn')}</p>
<CodeEditor
code={`// 仅供测试使用
<script src="https://hwcxiuzfylggtcktqgij.supabase.co/storage/v1/object/public/demo-public/v0.0.4/page-agent.js" crossorigin="true" type="text/javascript"></script>`}
code={`// CDN: \t${CDN_URL}
// Mirror: \t${CDN_CN_URL}
<script src="${CDN_URL}" crossorigin="true" type="text/javascript"></script>`}
language="html"
/>
</div>
@@ -18,6 +18,9 @@ export default {
step1_content: 'Show your bookmarks bar',
step2_title: 'Step 2:',
step2_content: 'Drag this button to your bookmarks',
cdn_label: 'CDN Source',
cdn_international: 'International',
cdn_china: 'China Mirror',
step3_title: 'Step 3:',
step3_content: 'Click the bookmark on any site to activate',
notice_title: '⚠️ Heads Up',
@@ -17,6 +17,9 @@ export default {
step1_content: '显示收藏夹栏',
step2_title: '步骤 2:',
step2_content: '拖拽下面按钮到收藏夹栏',
cdn_label: 'CDN 源',
cdn_international: '国际',
cdn_china: '国内镜像',
step3_title: '步骤 3:',
step3_content: '在其他网站点击收藏夹中的按钮即可使用',
notice_title: '⚠️ 注意',
+38 -18
View File
@@ -6,23 +6,27 @@ import { Link, useSearchParams } from 'wouter'
import Footer from './components/Footer'
import Header from './components/Header'
import { CDN_CN_URL, CDN_URL } from './constants'
const injection = encodeURI(
"javascript:(function(){var s=document.createElement('script');s.src=`https://hwcxiuzfylggtcktqgij.supabase.co/storage/v1/object/public/demo-public/v0.0.4/page-agent.js?t=${Math.random()}`;s.setAttribute('crossorigin', true);s.type=`text/javascript`;s.onload=()=>console.log('PageAgent script loaded!');document.body.appendChild(s);})();"
)
function getInjection(useCN?: boolean) {
const cdn = useCN ? CDN_CN_URL : CDN_URL
const injectionA = `
<a
href=${injection}
class="inline-flex items-center text-xs px-3 py-2 bg-blue-500 text-white font-medium rounded-lg hover:shadow-md transform hover:scale-105 transition-all duration-200 cursor-move border-2 border-dashed border-green-300"
draggable="true"
onclick="return false;"
title="Drag me to your bookmarks bar!"
>
✨PageAgent
</a>
const injection = encodeURI(
`javascript:(function(){var s=document.createElement('script');s.src=\`${cdn}?t=\${Math.random()}\`;s.setAttribute('crossorigin', true);s.type="text/javascript";s.onload=()=>console.log('PageAgent script loaded!');document.body.appendChild(s);})();`
)
`
return `
<a
href=${injection}
class="inline-flex items-center text-xs px-3 py-2 bg-blue-500 text-white font-medium rounded-lg hover:shadow-md transform hover:scale-105 transition-all duration-200 cursor-move border-2 border-dashed border-green-300"
draggable="true"
onclick="return false;"
title="Drag me to your bookmarks bar!"
>
✨PageAgent
</a>
`
}
export default function HomePage() {
const { t, i18n } = useTranslation(['home', 'common'])
@@ -38,6 +42,7 @@ export default function HomePage() {
const isOther = params.has('try_other')
const [activeTab, setActiveTab] = useState<'try' | 'other'>(isOther ? 'other' : 'try')
const [cdnSource, setCdnSource] = useState<'international' | 'china'>('international')
const handleExecute = async () => {
if (!task.trim()) return
@@ -194,10 +199,25 @@ export default function HomePage() {
</span>{' '}
{t('home:try_other.step2_content')}
</p>
<div
className="flex items-center justify-center gap-2 text-gray-500 dark:text-gray-400"
dangerouslySetInnerHTML={{ __html: injectionA }}
></div>
<div className="flex items-center justify-center gap-3">
<select
value={cdnSource}
onChange={(e) =>
setCdnSource(e.target.value as 'international' | 'china')
}
className="px-2 py-1.5 text-xs border border-gray-300 dark:border-gray-500 rounded bg-white dark:bg-gray-600 text-gray-700 dark:text-gray-200"
>
<option value="international">
{t('home:try_other.cdn_international')}
</option>
<option value="china">{t('home:try_other.cdn_china')}</option>
</select>
<div
dangerouslySetInnerHTML={{
__html: getInjection(cdnSource === 'china'),
}}
></div>
</div>
</div>
{/* Usage Instructions */}
+2
View File
@@ -12,6 +12,7 @@
// Simplified monorepo solution (raw npm workspace with hoisting)
"page-agent": ["../page-agent/src/PageAgent.ts"],
"@page-agent/llms": ["../llms/src/index.ts"],
"@page-agent/page-controller": ["../page-controller/src/PageController.ts"],
"@page-agent/ui": ["../ui/src/index.ts"]
}
@@ -20,6 +21,7 @@
"exclude": ["dist", "node_modules"],
"references": [
//
{ "path": "../llms" },
{ "path": "../page-agent" },
{ "path": "../page-controller" },
{ "path": "../ui" }
+5 -1
View File
@@ -1,6 +1,6 @@
import tailwindcss from '@tailwindcss/vite'
import react from '@vitejs/plugin-react-swc'
import 'dotenv/config'
import { config as dotenvConfig } from 'dotenv'
import process from 'node:process'
import { dirname, resolve } from 'path'
import { fileURLToPath } from 'url'
@@ -8,6 +8,9 @@ import { defineConfig } from 'vite'
const __dirname = dirname(fileURLToPath(import.meta.url))
// Load .env from repo root
dotenvConfig({ path: resolve(__dirname, '../../.env') })
// Website Config (React Documentation Site)
export default defineConfig({
base: './',
@@ -19,6 +22,7 @@ export default defineConfig({
'@': resolve(__dirname, 'src'),
// Monorepo packages (always bundle local code instead of npm versions)
'@page-agent/llms': resolve(__dirname, '../llms/src/index.ts'),
'@page-agent/page-controller': resolve(__dirname, '../page-controller/src/PageController.ts'),
'@page-agent/ui': resolve(__dirname, '../ui/src/index.ts'),
'page-agent': resolve(__dirname, '../page-agent/src/PageAgent.ts'),
+1
View File
@@ -3,6 +3,7 @@
"references": [
{ "path": "./packages/page-controller" },
{ "path": "./packages/ui" },
{ "path": "./packages/llms" },
{ "path": "./packages/page-agent" },
{ "path": "./packages/website" }
],