diff --git a/package.json b/package.json index 0ba39b2..12b6e1a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@hyperbrowser/agent", - "version": "1.0.9", + "version": "1.0.10", "description": "Hyperbrowsers Web Agent", "author": "", "main": "dist/index.js", diff --git a/src/agent/index.ts b/src/agent/index.ts index ee8f821..7b12378 100644 --- a/src/agent/index.ts +++ b/src/agent/index.ts @@ -730,6 +730,9 @@ export class HyperAgent { }; } else if (step.actionType === "extract") { try { + if (!step.instruction) { + throw new Error("Missing objective/instruction for extract action"); + } const extractResult = await hyperPage.extract(step.instruction); result = { taskId: cache.taskId, @@ -783,7 +786,7 @@ export class HyperAgent { const method = step.method; if (method && validHelperMethods.has(method)) { const options: PerformOptions = { - performInstruction: step.instruction, + performInstruction: step.instruction ?? null, maxSteps: maxXPathRetries, }; if (step.frameIndex !== null && step.frameIndex !== undefined) { @@ -797,8 +800,23 @@ export class HyperAgent { valueArg, options ); - } else { + } else if (step.instruction) { result = await hyperPage.perform(step.instruction); + } else { + result = { + taskId: cache.taskId, + status: TaskStatus.FAILED, + steps: [], + output: `Cannot replay action type "${step.actionType}" without instruction`, + replayStepMeta: { + usedCachedAction: false, + fallbackUsed: false, + retries: 0, + cachedXPath: null, + fallbackXPath: null, + fallbackElementId: null, + }, + }; } } diff --git a/src/agent/shared/action-cache.ts b/src/agent/shared/action-cache.ts index 11b7b5b..41f1be5 100644 --- a/src/agent/shared/action-cache.ts +++ b/src/agent/shared/action-cache.ts @@ -23,12 +23,23 @@ const normalizeXPath = (raw?: string | null): string | null => { return raw.replace(TEXT_NODE_SUFFIX, ""); }; -const extractInstruction = (action: ActionType): string => { +const extractInstruction = (action: ActionType): string | undefined => { const params = action.params as Record; - if (isString(params.instruction)) { - return params.instruction; + switch (action.type) { + case "extract": + if (isString(params.objective)) { + return params.objective; + } + throw new Error(`Missing objective for extract action`); + case "actElement": + if (isString(params.instruction)) { + return params.instruction; + } + throw new Error(`Missing instruction for actElement action`); + default: + // Actions like goToUrl, refreshPage, wait, analyzePdf do not require an instruction + return isString(params.instruction) ? params.instruction : undefined; } - return action.type; }; const extractElementId = (action: ActionType): string | null => { diff --git a/src/types/agent/types.ts b/src/types/agent/types.ts index 638ead3..d846f65 100644 --- a/src/types/agent/types.ts +++ b/src/types/agent/types.ts @@ -30,7 +30,7 @@ export interface AgentStep { export interface ActionCacheEntry { stepIndex: number; - instruction: string; + instruction: string | undefined; elementId: string | null; method: string | null; arguments: string[];