refactor: zod tree-shaking; better error handling in agent steps
This commit is contained in:
11
package-lock.json
generated
11
package-lock.json
generated
@@ -41,6 +41,7 @@
|
|||||||
"typescript-eslint": "^8.54.0",
|
"typescript-eslint": "^8.54.0",
|
||||||
"unplugin-dts": "^1.0.0-beta.6",
|
"unplugin-dts": "^1.0.0-beta.6",
|
||||||
"vite": "^7.3.1",
|
"vite": "^7.3.1",
|
||||||
|
"vite-bundle-analyzer": "^1.3.6",
|
||||||
"vite-plugin-css-injected-by-js": "^3.5.2"
|
"vite-plugin-css-injected-by-js": "^3.5.2"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -10411,6 +10412,16 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/vite-bundle-analyzer": {
|
||||||
|
"version": "1.3.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/vite-bundle-analyzer/-/vite-bundle-analyzer-1.3.6.tgz",
|
||||||
|
"integrity": "sha512-elFXkF9oGy4CJEeOdP1DSEHRDKWfmaEDfT9/GuF4jmyfmUF6nC//iN+ythqMEVvrtchOEHGKLumZwnu1NjoI0w==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"analyze": "dist/bin.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/vite-node": {
|
"node_modules/vite-node": {
|
||||||
"version": "5.3.0",
|
"version": "5.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/vite-node/-/vite-node-5.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/vite-node/-/vite-node-5.3.0.tgz",
|
||||||
|
|||||||
@@ -59,7 +59,8 @@
|
|||||||
"typescript-eslint": "^8.54.0",
|
"typescript-eslint": "^8.54.0",
|
||||||
"unplugin-dts": "^1.0.0-beta.6",
|
"unplugin-dts": "^1.0.0-beta.6",
|
||||||
"vite": "^7.3.1",
|
"vite": "^7.3.1",
|
||||||
"vite-plugin-css-injected-by-js": "^3.5.2"
|
"vite-plugin-css-injected-by-js": "^3.5.2",
|
||||||
|
"vite-bundle-analyzer": "^1.3.6"
|
||||||
},
|
},
|
||||||
"overrides": {
|
"overrides": {
|
||||||
"typescript": "^5.9.3"
|
"typescript": "^5.9.3"
|
||||||
|
|||||||
@@ -5,13 +5,13 @@
|
|||||||
import { InvokeError, LLM, type Tool } from '@page-agent/llms'
|
import { InvokeError, LLM, type Tool } from '@page-agent/llms'
|
||||||
import type { PageController } from '@page-agent/page-controller'
|
import type { PageController } from '@page-agent/page-controller'
|
||||||
import chalk from 'chalk'
|
import chalk from 'chalk'
|
||||||
import zod from 'zod'
|
import * as zod from 'zod'
|
||||||
|
|
||||||
import { type PageAgentConfig } from './config'
|
import { type PageAgentConfig } from './config'
|
||||||
import { DEFAULT_MAX_STEPS } from './config/constants'
|
import { DEFAULT_MAX_STEPS } from './config/constants'
|
||||||
import SYSTEM_PROMPT from './prompts/system_prompt.md?raw'
|
import SYSTEM_PROMPT from './prompts/system_prompt.md?raw'
|
||||||
import { tools } from './tools'
|
import { tools } from './tools'
|
||||||
import {
|
import type {
|
||||||
AgentActivity,
|
AgentActivity,
|
||||||
AgentReflection,
|
AgentReflection,
|
||||||
AgentStatus,
|
AgentStatus,
|
||||||
@@ -21,8 +21,7 @@ import {
|
|||||||
MacroToolInput,
|
MacroToolInput,
|
||||||
MacroToolResult,
|
MacroToolResult,
|
||||||
} from './types'
|
} from './types'
|
||||||
import { normalizeResponse, trimLines, uid, waitFor } from './utils'
|
import { assert, normalizeResponse, trimLines, uid, waitFor } from './utils'
|
||||||
import { assert } from './utils/assert'
|
|
||||||
|
|
||||||
export { type PageAgentConfig }
|
export { type PageAgentConfig }
|
||||||
export { tool, type PageAgentTool } from './tools'
|
export { tool, type PageAgentTool } from './tools'
|
||||||
@@ -209,20 +208,20 @@ export class PageAgentCore extends EventTarget {
|
|||||||
lastURL: '',
|
lastURL: '',
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
let step = 0
|
||||||
let step = 0
|
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
console.group(`step: ${step}`)
|
||||||
|
|
||||||
while (true) {
|
|
||||||
await this.#generateObservations(step)
|
await this.#generateObservations(step)
|
||||||
|
|
||||||
await onBeforeStep?.(this, step)
|
await onBeforeStep?.(this, step)
|
||||||
|
|
||||||
console.group(`step: ${step}`)
|
|
||||||
|
|
||||||
// abort
|
// abort
|
||||||
if (this.#abortController.signal.aborted) throw new Error('AbortError')
|
if (this.#abortController.signal.aborted) throw new Error('AbortError')
|
||||||
|
|
||||||
// Thinking
|
// status
|
||||||
console.log(chalk.blue('Thinking...'))
|
console.log(chalk.blue('Thinking...'))
|
||||||
this.#emitActivity({ type: 'thinking' })
|
this.#emitActivity({ type: 'thinking' })
|
||||||
|
|
||||||
@@ -270,22 +269,13 @@ export class PageAgentCore extends EventTarget {
|
|||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
|
await onAfterStep?.(this, this.history)
|
||||||
|
|
||||||
console.log(chalk.green('Step finished:'), actionName)
|
console.log(chalk.green('Step finished:'), actionName)
|
||||||
console.groupEnd()
|
console.groupEnd()
|
||||||
|
|
||||||
await onAfterStep?.(this, this.history)
|
// finish task if done
|
||||||
|
|
||||||
step++
|
|
||||||
if (step > this.config.maxSteps) {
|
|
||||||
this.#onDone(false)
|
|
||||||
const result: ExecutionResult = {
|
|
||||||
success: false,
|
|
||||||
data: 'Step count exceeded maximum limit',
|
|
||||||
history: this.history,
|
|
||||||
}
|
|
||||||
await onAfterTask?.(this, result)
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
if (actionName === 'done') {
|
if (actionName === 'done') {
|
||||||
const success = action.input?.success ?? false
|
const success = action.input?.success ?? false
|
||||||
const text = action.input?.text || 'no text provided'
|
const text = action.input?.text || 'no text provided'
|
||||||
@@ -299,19 +289,32 @@ export class PageAgentCore extends EventTarget {
|
|||||||
await onAfterTask?.(this, result)
|
await onAfterTask?.(this, result)
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
} catch (error: unknown) {
|
||||||
|
console.groupEnd() // to prevent nested groups
|
||||||
|
console.error('Task failed', error)
|
||||||
|
const errorMessage = String(error)
|
||||||
|
this.#emitActivity({ type: 'error', message: errorMessage })
|
||||||
|
this.#onDone(false)
|
||||||
|
const result: ExecutionResult = {
|
||||||
|
success: false,
|
||||||
|
data: errorMessage,
|
||||||
|
history: this.history,
|
||||||
|
}
|
||||||
|
await onAfterTask?.(this, result)
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
} catch (error: unknown) {
|
|
||||||
console.error('Task failed', error)
|
step++
|
||||||
const errorMessage = String(error)
|
if (step > this.config.maxSteps) {
|
||||||
this.#emitActivity({ type: 'error', message: errorMessage })
|
this.#onDone(false)
|
||||||
this.#onDone(false)
|
const result: ExecutionResult = {
|
||||||
const result: ExecutionResult = {
|
success: false,
|
||||||
success: false,
|
data: 'Step count exceeded maximum limit',
|
||||||
data: errorMessage,
|
history: this.history,
|
||||||
history: this.history,
|
}
|
||||||
|
await onAfterTask?.(this, result)
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
await onAfterTask?.(this, result)
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* Internal tools for PageAgent.
|
* Internal tools for PageAgent.
|
||||||
* @note Adapted from browser-use
|
* @note Adapted from browser-use
|
||||||
*/
|
*/
|
||||||
import zod, { type z } from 'zod'
|
import * as zod from 'zod'
|
||||||
|
|
||||||
import type { PageAgentCore } from '../PageAgentCore'
|
import type { PageAgentCore } from '../PageAgentCore'
|
||||||
import { waitFor } from '../utils'
|
import { waitFor } from '../utils'
|
||||||
@@ -13,7 +13,7 @@ import { waitFor } from '../utils'
|
|||||||
export interface PageAgentTool<TParams = any> {
|
export interface PageAgentTool<TParams = any> {
|
||||||
// name: string
|
// name: string
|
||||||
description: string
|
description: string
|
||||||
inputSchema: z.ZodType<TParams>
|
inputSchema: zod.ZodType<TParams>
|
||||||
execute: (this: PageAgentCore, args: TParams) => Promise<string>
|
execute: (this: PageAgentCore, args: TParams) => Promise<string>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
import chalk from 'chalk'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple assertion function that throws an error if the condition is falsy
|
|
||||||
* @param condition - The condition to assert
|
|
||||||
* @param message - Optional error message
|
|
||||||
* @throws Error if condition is falsy
|
|
||||||
*/
|
|
||||||
export function assert(condition: unknown, message?: string, silent?: boolean): asserts condition {
|
|
||||||
if (!condition) {
|
|
||||||
const errorMessage = message ?? 'Assertion failed'
|
|
||||||
|
|
||||||
if (!silent) console.error(chalk.red(`❌ assert: ${errorMessage}`))
|
|
||||||
|
|
||||||
throw new Error(errorMessage)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import chalk from 'chalk'
|
||||||
|
|
||||||
export { normalizeResponse } from './autoFixer'
|
export { normalizeResponse } from './autoFixer'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -85,3 +87,19 @@ export function uid() {
|
|||||||
ids.push(id)
|
ids.push(id)
|
||||||
return id
|
return id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple assertion function that throws an error if the condition is falsy
|
||||||
|
* @param condition - The condition to assert
|
||||||
|
* @param message - Optional error message
|
||||||
|
* @throws Error if condition is falsy
|
||||||
|
*/
|
||||||
|
export function assert(condition: unknown, message?: string, silent?: boolean): asserts condition {
|
||||||
|
if (!condition) {
|
||||||
|
const errorMessage = message ?? 'Assertion failed'
|
||||||
|
|
||||||
|
if (!silent) console.error(chalk.red(`❌ assert: ${errorMessage}`))
|
||||||
|
|
||||||
|
throw new Error(errorMessage)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
* - switch_to_tab: Switch to an existing tab
|
* - switch_to_tab: Switch to an existing tab
|
||||||
* - close_tab: Close a tab (optionally switch to another)
|
* - close_tab: Close a tab (optionally switch to another)
|
||||||
*/
|
*/
|
||||||
import zod from 'zod'
|
import * as zod from 'zod'
|
||||||
|
|
||||||
import type { TabsController } from './TabsController'
|
import type { TabsController } from './TabsController'
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* Utility functions for LLM integration
|
* Utility functions for LLM integration
|
||||||
*/
|
*/
|
||||||
import chalk from 'chalk'
|
import chalk from 'chalk'
|
||||||
import { z } from 'zod'
|
import * as z from 'zod'
|
||||||
|
|
||||||
import type { Tool } from './types'
|
import type { Tool } from './types'
|
||||||
|
|
||||||
|
|||||||
@@ -44,11 +44,11 @@
|
|||||||
"postpublish": "node -e \"['README.md','LICENSE'].forEach(f=>{try{require('fs').unlinkSync(f)}catch{}})\""
|
"postpublish": "node -e \"['README.md','LICENSE'].forEach(f=>{try{require('fs').unlinkSync(f)}catch{}})\""
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"chalk": "^5.6.2",
|
"@page-agent/core": "1.1.1",
|
||||||
"zod": "^4.3.5",
|
|
||||||
"@page-agent/llms": "1.1.1",
|
"@page-agent/llms": "1.1.1",
|
||||||
"@page-agent/page-controller": "1.1.1",
|
"@page-agent/page-controller": "1.1.1",
|
||||||
"@page-agent/core": "1.1.1",
|
"@page-agent/ui": "1.1.1",
|
||||||
"@page-agent/ui": "1.1.1"
|
"chalk": "^5.6.2",
|
||||||
|
"zod": "^4.3.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { config as dotenvConfig } from 'dotenv'
|
|||||||
import { dirname, resolve } from 'path'
|
import { dirname, resolve } from 'path'
|
||||||
import { fileURLToPath } from 'url'
|
import { fileURLToPath } from 'url'
|
||||||
import { defineConfig } from 'vite'
|
import { defineConfig } from 'vite'
|
||||||
|
// import { analyzer } from 'vite-bundle-analyzer'
|
||||||
import cssInjectedByJsPlugin from 'vite-plugin-css-injected-by-js'
|
import cssInjectedByJsPlugin from 'vite-plugin-css-injected-by-js'
|
||||||
|
|
||||||
const __dirname = dirname(fileURLToPath(import.meta.url))
|
const __dirname = dirname(fileURLToPath(import.meta.url))
|
||||||
@@ -14,8 +15,11 @@ dotenvConfig({ path: resolve(__dirname, '../../.env') })
|
|||||||
// - alias all local packages so that they can be build in
|
// - alias all local packages so that they can be build in
|
||||||
// - no external
|
// - no external
|
||||||
// - no d.ts. dts does not work with monorepo aliasing
|
// - no d.ts. dts does not work with monorepo aliasing
|
||||||
export default defineConfig(({ mode }) => ({
|
export default defineConfig(() => ({
|
||||||
plugins: [cssInjectedByJsPlugin({ relativeCSSInjection: true })],
|
plugins: [
|
||||||
|
cssInjectedByJsPlugin({ relativeCSSInjection: true }),
|
||||||
|
// analyzer()
|
||||||
|
],
|
||||||
publicDir: false,
|
publicDir: false,
|
||||||
esbuild: {
|
esbuild: {
|
||||||
keepNames: true,
|
keepNames: true,
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export default function CustomTools() {
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<CodeEditor
|
<CodeEditor
|
||||||
code={`import zod from 'zod'
|
code={`import * as zod from 'zod'
|
||||||
import { PageAgent, tool } from 'page-agent'
|
import { PageAgent, tool } from 'page-agent'
|
||||||
|
|
||||||
// override internal tool
|
// override internal tool
|
||||||
|
|||||||
@@ -362,11 +362,6 @@ export default function TroubleshootingPage() {
|
|||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="mb-10">
|
<div className="mb-10">
|
||||||
<h1 className="text-4xl font-bold mb-4 text-gray-900 dark:text-white">Troubleshooting</h1>
|
<h1 className="text-4xl font-bold mb-4 text-gray-900 dark:text-white">Troubleshooting</h1>
|
||||||
{/* <p className="text-lg text-gray-600 dark:text-gray-300">
|
|
||||||
{isZh
|
|
||||||
? '遇到问题了?按症状查找解决方案。'
|
|
||||||
: 'Running into issues? Find solutions by symptom.'}
|
|
||||||
</p> */}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Two-column: content + TOC */}
|
{/* Two-column: content + TOC */}
|
||||||
|
|||||||
Reference in New Issue
Block a user