Merge pull request #111 from alibaba/feat/extend-agent-history-for-observation

feat: extend history type
This commit is contained in:
Simon
2026-01-15 19:57:41 +08:00
committed by GitHub
2 changed files with 63 additions and 16 deletions

View File

@@ -50,7 +50,11 @@ export interface MacroToolResult {
export type { PageAgentConfig } export type { PageAgentConfig }
export { tool, type PageAgentTool } from './tools' export { tool, type PageAgentTool } from './tools'
export interface AgentHistory { /**
* A single agent step with reflection and action
*/
export interface AgentStep {
type: 'step'
brain: Partial<AgentReflection> brain: Partial<AgentReflection>
action: { action: {
name: string name: string
@@ -66,10 +70,33 @@ export interface AgentHistory {
} }
} }
/**
* Persistent observation event (stays in memory)
*/
export interface ObservationEvent {
type: 'observation'
content: string
}
/**
* User takeover event
*/
export interface UserTakeoverEvent {
type: 'user_takeover'
}
/**
* Union type for all history events
*/
export type HistoryEvent = AgentStep | ObservationEvent | UserTakeoverEvent
/** @deprecated Use AgentStep instead */
export type AgentHistory = AgentStep
export interface ExecutionResult { export interface ExecutionResult {
success: boolean success: boolean
data: string data: string
history: AgentHistory[] history: HistoryEvent[]
} }
export class PageAgent extends EventTarget { export class PageAgent extends EventTarget {
@@ -92,8 +119,8 @@ export class PageAgent extends EventTarget {
/** PageController for DOM operations */ /** PageController for DOM operations */
pageController: PageController pageController: PageController
/** History records */ /** History event stream */
history: AgentHistory[] = [] history: HistoryEvent[] = []
constructor(config: PageAgentConfig) { constructor(config: PageAgentConfig) {
super() super()
@@ -150,6 +177,14 @@ export class PageAgent extends EventTarget {
window.addEventListener('beforeunload', this.#beforeUnloadListener) window.addEventListener('beforeunload', this.#beforeUnloadListener)
} }
/**
* Push a persistent observation to the history event stream.
* This will be visible in <agent_history> and remain in memory across steps.
*/
pushObservation(content: string): void {
this.history.push({ type: 'observation', content })
}
async execute(task: string): Promise<ExecutionResult> { async execute(task: string): Promise<ExecutionResult> {
if (!task) throw new Error('Task is required') if (!task) throw new Error('Task is required')
this.task = task this.task = task
@@ -229,6 +264,7 @@ export class PageAgent extends EventTarget {
} }
this.history.push({ this.history.push({
type: 'step',
brain, brain,
action, action,
usage: result.usage, usage: result.usage,
@@ -438,31 +474,42 @@ export class PageAgent extends EventTarget {
// - <step_info> // - <step_info>
// <agent_state> // <agent_state>
const stepCount = this.history.filter((e) => e.type === 'step').length
prompt += `<agent_state> prompt += `<agent_state>
<user_request> <user_request>
${this.task} ${this.task}
</user_request> </user_request>
<step_info> <step_info>
Step ${this.history.length + 1} of ${MAX_STEPS} max possible steps Step ${stepCount + 1} of ${MAX_STEPS} max possible steps
Current date and time: ${new Date().toISOString()} Current date and time: ${new Date().toISOString()}
</step_info> </step_info>
</agent_state> </agent_state>
` `
// <agent_history> // <agent_history>
// - <step_> // - <step_N> for steps
// - <sys> for observations and system messages
prompt += '\n<agent_history>\n' prompt += '\n<agent_history>\n'
this.history.forEach((history, index) => { let stepIndex = 0
prompt += `<step_${index + 1}> for (const event of this.history) {
Evaluation of Previous Step: ${history.brain.evaluation_previous_goal} if (event.type === 'step') {
Memory: ${history.brain.memory} stepIndex++
Next Goal: ${history.brain.next_goal} prompt += `<step_${stepIndex}>
Action Results: ${history.action.output} Evaluation of Previous Step: ${event.brain.evaluation_previous_goal}
</step_${index + 1}> Memory: ${event.brain.memory}
Next Goal: ${event.brain.next_goal}
Action Results: ${event.action.output}
</step_${stepIndex}>
` `
}) } else if (event.type === 'observation') {
prompt += `<sys>${event.content}</sys>\n`
} else if (event.type === 'user_takeover') {
prompt += `<sys>User took over control and made changes to the page.</sys>\n`
}
}
prompt += '</agent_history>\n\n' prompt += '</agent_history>\n\n'

View File

@@ -2,7 +2,7 @@ import type { LLMConfig } from '@page-agent/llms'
import type { PageControllerConfig } from '@page-agent/page-controller' import type { PageControllerConfig } from '@page-agent/page-controller'
import type { SupportedLanguage } from '@page-agent/ui' import type { SupportedLanguage } from '@page-agent/ui'
import type { AgentHistory, ExecutionResult, PageAgent } from '../PageAgent' import type { ExecutionResult, HistoryEvent, PageAgent } from '../PageAgent'
import type { PageAgentTool } from '../tools' import type { PageAgentTool } from '../tools'
export type { LLMConfig } export type { LLMConfig }
@@ -65,7 +65,7 @@ export interface AgentConfig {
// @todo: remove `this` binding, pass agent as explicit parameter instead // @todo: remove `this` binding, pass agent as explicit parameter instead
onBeforeStep?: (this: PageAgent, stepCnt: number) => Promise<void> | void onBeforeStep?: (this: PageAgent, stepCnt: number) => Promise<void> | void
onAfterStep?: (this: PageAgent, stepCnt: number, history: AgentHistory[]) => Promise<void> | void onAfterStep?: (this: PageAgent, stepCnt: number, history: HistoryEvent[]) => Promise<void> | void
onBeforeTask?: (this: PageAgent) => Promise<void> | void onBeforeTask?: (this: PageAgent) => Promise<void> | void
onAfterTask?: (this: PageAgent, result: ExecutionResult) => Promise<void> | void onAfterTask?: (this: PageAgent, result: ExecutionResult) => Promise<void> | void