feat(core): improve observation logic; mark states as private
This commit is contained in:
@@ -73,7 +73,7 @@ export class PageAgentCore extends EventTarget {
|
|||||||
#observations: string[] = []
|
#observations: string[] = []
|
||||||
|
|
||||||
/** internal states of a single task execution */
|
/** internal states of a single task execution */
|
||||||
states = {
|
#states = {
|
||||||
/** Accumulated wait time in seconds */
|
/** Accumulated wait time in seconds */
|
||||||
totalWaitTime: 0,
|
totalWaitTime: 0,
|
||||||
/** Last known URL for detecting navigation */
|
/** Last known URL for detecting navigation */
|
||||||
@@ -201,11 +201,8 @@ export class PageAgentCore extends EventTarget {
|
|||||||
this.#setStatus('running')
|
this.#setStatus('running')
|
||||||
this.#emitHistoryChange()
|
this.#emitHistoryChange()
|
||||||
|
|
||||||
// Reset states
|
// Reset internal states
|
||||||
this.states = {
|
this.#states = { totalWaitTime: 0, lastURL: '' }
|
||||||
totalWaitTime: 0,
|
|
||||||
lastURL: '',
|
|
||||||
}
|
|
||||||
|
|
||||||
let step = 0
|
let step = 0
|
||||||
|
|
||||||
@@ -213,18 +210,10 @@ export class PageAgentCore extends EventTarget {
|
|||||||
try {
|
try {
|
||||||
console.group(`step: ${step}`)
|
console.group(`step: ${step}`)
|
||||||
|
|
||||||
await this.#systemObservations(step)
|
|
||||||
|
|
||||||
if (this.#observations.length > 0) {
|
|
||||||
for (const content of this.#observations) {
|
|
||||||
this.history.push({ type: 'observation', content })
|
|
||||||
}
|
|
||||||
this.#observations = []
|
|
||||||
this.#emitHistoryChange()
|
|
||||||
}
|
|
||||||
|
|
||||||
await onBeforeStep?.(this, step)
|
await onBeforeStep?.(this, step)
|
||||||
|
|
||||||
|
await this.#handleObservations(step)
|
||||||
|
|
||||||
// abort
|
// abort
|
||||||
if (this.#abortController.signal.aborted) throw new Error('AbortError')
|
if (this.#abortController.signal.aborted) throw new Error('AbortError')
|
||||||
|
|
||||||
@@ -405,9 +394,11 @@ export class PageAgentCore extends EventTarget {
|
|||||||
duration,
|
duration,
|
||||||
})
|
})
|
||||||
|
|
||||||
// Reset wait time for non-wait tools
|
// counting wait time
|
||||||
if (toolName !== 'wait') {
|
if (toolName === 'wait') {
|
||||||
this.states.totalWaitTime = 0
|
this.#states.totalWaitTime += toolInput?.seconds || 0
|
||||||
|
} else {
|
||||||
|
this.#states.totalWaitTime = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return structured result
|
// Return structured result
|
||||||
@@ -476,22 +467,27 @@ export class PageAgentCore extends EventTarget {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate system observations before each step
|
* Generate system observations before each step
|
||||||
* - URL change detection
|
|
||||||
* - Too many steps warning
|
|
||||||
* @todo loop detection
|
* @todo loop detection
|
||||||
* @todo console error
|
* @todo console error
|
||||||
*/
|
*/
|
||||||
async #systemObservations(stepCount: number): Promise<void> {
|
async #handleObservations(step: number): Promise<void> {
|
||||||
|
// Accumulated wait time warning
|
||||||
|
if (this.#states.totalWaitTime >= 3) {
|
||||||
|
this.pushObservation(
|
||||||
|
`You have waited ${this.#states.totalWaitTime} seconds accumulatively. DO NOT wait any longer unless you have a good reason.`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// Detect URL change
|
// Detect URL change
|
||||||
const currentURL = await this.pageController.getCurrentUrl()
|
const currentURL = await this.pageController.getCurrentUrl()
|
||||||
if (currentURL !== this.states.lastURL) {
|
if (currentURL !== this.#states.lastURL) {
|
||||||
this.pushObservation(`Page navigated to → ${currentURL}`)
|
this.pushObservation(`Page navigated to → ${currentURL}`)
|
||||||
this.states.lastURL = currentURL
|
this.#states.lastURL = currentURL
|
||||||
await waitFor(0.5) // wait for page to stabilize
|
await waitFor(0.5) // wait for page to stabilize
|
||||||
}
|
}
|
||||||
|
|
||||||
// Warn about remaining steps
|
// Remaining steps warning
|
||||||
const remaining = this.config.maxSteps - stepCount
|
const remaining = this.config.maxSteps - step
|
||||||
if (remaining === 5) {
|
if (remaining === 5) {
|
||||||
this.pushObservation(
|
this.pushObservation(
|
||||||
`⚠️ Only ${remaining} steps remaining. Consider wrapping up or calling done with partial results.`
|
`⚠️ Only ${remaining} steps remaining. Consider wrapping up or calling done with partial results.`
|
||||||
@@ -501,6 +497,15 @@ export class PageAgentCore extends EventTarget {
|
|||||||
`⚠️ Critical: Only ${remaining} steps left! You must finish the task or call done immediately.`
|
`⚠️ Critical: Only ${remaining} steps left! You must finish the task or call done immediately.`
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Push observations to history and emit
|
||||||
|
if (this.#observations.length > 0) {
|
||||||
|
for (const content of this.#observations) {
|
||||||
|
this.history.push({ type: 'observation', content })
|
||||||
|
}
|
||||||
|
this.#observations = []
|
||||||
|
this.#emitHistoryChange()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async #assembleUserPrompt(): Promise<string> {
|
async #assembleUserPrompt(): Promise<string> {
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ tools.set(
|
|||||||
}),
|
}),
|
||||||
execute: async function (this: PageAgentCore, input) {
|
execute: async function (this: PageAgentCore, input) {
|
||||||
// @note main loop will handle this one
|
// @note main loop will handle this one
|
||||||
// this.onDone(input.text, input.success)
|
|
||||||
return Promise.resolve('Task completed')
|
return Promise.resolve('Task completed')
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -52,19 +51,12 @@ tools.set(
|
|||||||
seconds: zod.number().min(1).max(10).default(1),
|
seconds: zod.number().min(1).max(10).default(1),
|
||||||
}),
|
}),
|
||||||
execute: async function (this: PageAgentCore, input) {
|
execute: async function (this: PageAgentCore, input) {
|
||||||
|
// try to subtract LLM calling time from the actual wait time
|
||||||
const lastTimeUpdate = await this.pageController.getLastUpdateTime()
|
const lastTimeUpdate = await this.pageController.getLastUpdateTime()
|
||||||
const actualWaitTime = Math.max(0, input.seconds - (Date.now() - lastTimeUpdate) / 1000)
|
const actualWaitTime = Math.max(0, input.seconds - (Date.now() - lastTimeUpdate) / 1000)
|
||||||
console.log(`actualWaitTime: ${actualWaitTime} seconds`)
|
console.log(`actualWaitTime: ${actualWaitTime} seconds`)
|
||||||
await waitFor(actualWaitTime)
|
await waitFor(actualWaitTime)
|
||||||
|
|
||||||
this.states.totalWaitTime += input.seconds
|
|
||||||
|
|
||||||
if (this.states.totalWaitTime >= 3) {
|
|
||||||
this.pushObservation(
|
|
||||||
`You have waited ${this.states.totalWaitTime} seconds accumulatively. Do NOT wait any longer unless you have a good reason.`
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return `✅ Waited for ${input.seconds} seconds.`
|
return `✅ Waited for ${input.seconds} seconds.`
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user