fix(core): harden run settlement edge cases from review
- install #running before the `running` statuschange fires, so a listener calling stop() immediately awaits the current run - await async mask/highlight cleanup before settling: once settled, the agent must be safely reusable - make the inter-step delay abortable so stop() settles promptly; abort during the delay is classified as `stopped`
This commit is contained in:
@@ -220,13 +220,14 @@ export class PageAgentCore extends EventTarget {
|
|||||||
this.#observations = []
|
this.#observations = []
|
||||||
this.#states = { totalWaitTime: 0, lastURL: '', browserState: null }
|
this.#states = { totalWaitTime: 0, lastURL: '', browserState: null }
|
||||||
this.#abortController = new AbortController()
|
this.#abortController = new AbortController()
|
||||||
|
const signal = this.#abortController.signal
|
||||||
this.#setStatus('running')
|
|
||||||
this.#emitHistoryChange()
|
|
||||||
|
|
||||||
let resolveRunning!: () => void
|
let resolveRunning!: () => void
|
||||||
this.#running = new Promise<void>((r) => (resolveRunning = r))
|
this.#running = new Promise<void>((r) => (resolveRunning = r))
|
||||||
|
|
||||||
|
this.#setStatus('running')
|
||||||
|
this.#emitHistoryChange()
|
||||||
|
|
||||||
// Disable ask_user tool if onAskUser is not set
|
// Disable ask_user tool if onAskUser is not set
|
||||||
if (!this.onAskUser) this.tools.delete('ask_user')
|
if (!this.onAskUser) this.tools.delete('ask_user')
|
||||||
|
|
||||||
@@ -234,6 +235,8 @@ export class PageAgentCore extends EventTarget {
|
|||||||
const onAfterStep = this.config.onAfterStep
|
const onAfterStep = this.config.onAfterStep
|
||||||
const onBeforeTask = this.config.onBeforeTask
|
const onBeforeTask = this.config.onBeforeTask
|
||||||
const onAfterTask = this.config.onAfterTask
|
const onAfterTask = this.config.onAfterTask
|
||||||
|
const stepDelay = this.config.stepDelay ?? 0.4
|
||||||
|
const maxSteps = this.config.maxSteps
|
||||||
|
|
||||||
let step = 0
|
let step = 0
|
||||||
let taskResult: ExecutionResult
|
let taskResult: ExecutionResult
|
||||||
@@ -252,8 +255,9 @@ export class PageAgentCore extends EventTarget {
|
|||||||
try {
|
try {
|
||||||
console.group(`step: ${step}`)
|
console.group(`step: ${step}`)
|
||||||
|
|
||||||
// inside the try: abort between steps must settle as `stopped`
|
if (step > 0) await waitFor(stepDelay, signal)
|
||||||
this.#abortController.signal.throwIfAborted()
|
|
||||||
|
signal.throwIfAborted()
|
||||||
|
|
||||||
// observe
|
// observe
|
||||||
|
|
||||||
@@ -276,7 +280,7 @@ export class PageAgentCore extends EventTarget {
|
|||||||
console.log(chalk.blue.bold('🧠 Thinking...'))
|
console.log(chalk.blue.bold('🧠 Thinking...'))
|
||||||
this.#emitActivity({ type: 'thinking' })
|
this.#emitActivity({ type: 'thinking' })
|
||||||
|
|
||||||
const result = await this.#llm.invoke(messages, macroTool, this.#abortController.signal, {
|
const result = await this.#llm.invoke(messages, macroTool, signal, {
|
||||||
toolChoiceName: 'AgentOutput',
|
toolChoiceName: 'AgentOutput',
|
||||||
normalizeResponse: (res) => normalizeResponse(res, this.tools),
|
normalizeResponse: (res) => normalizeResponse(res, this.tools),
|
||||||
})
|
})
|
||||||
@@ -340,7 +344,7 @@ export class PageAgentCore extends EventTarget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
step++
|
step++
|
||||||
if (step > this.config.maxSteps) {
|
if (step > maxSteps) {
|
||||||
const message = 'Step count exceeded maximum limit'
|
const message = 'Step count exceeded maximum limit'
|
||||||
console.error(message)
|
console.error(message)
|
||||||
this.#emitActivity({ type: 'error', message: message })
|
this.#emitActivity({ type: 'error', message: message })
|
||||||
@@ -350,8 +354,6 @@ export class PageAgentCore extends EventTarget {
|
|||||||
finalStatus = 'error'
|
finalStatus = 'error'
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
await waitFor(this.config.stepDelay ?? 0.4)
|
|
||||||
} // while
|
} // while
|
||||||
|
|
||||||
await onAfterTask?.(this, taskResult)
|
await onAfterTask?.(this, taskResult)
|
||||||
@@ -362,8 +364,8 @@ export class PageAgentCore extends EventTarget {
|
|||||||
finalStatus = 'error'
|
finalStatus = 'error'
|
||||||
throw error
|
throw error
|
||||||
} finally {
|
} finally {
|
||||||
suppress(() => this.pageController.cleanUpHighlights())
|
await suppress(() => this.pageController.cleanUpHighlights())
|
||||||
suppress(() => this.pageController.hideMask())
|
await suppress(() => this.pageController.hideMask())
|
||||||
this.#abortController.abort()
|
this.#abortController.abort()
|
||||||
resolveRunning()
|
resolveRunning()
|
||||||
this.#setStatus(finalStatus)
|
this.#setStatus(finalStatus)
|
||||||
|
|||||||
Reference in New Issue
Block a user