@browserbasehq/orca 3.4.0-preview-3 → 3.4.0-preview-4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/lib/v3/agent/AnthropicCUAClient.js +10 -0
- package/dist/cjs/lib/v3/agent/AnthropicCUAClient.js.map +1 -1
- package/dist/cjs/lib/v3/handlers/v3CuaAgentHandler.js +1 -0
- package/dist/cjs/lib/v3/handlers/v3CuaAgentHandler.js.map +1 -1
- package/dist/cjs/lib/v3/types/private/snapshot.d.ts +2 -0
- package/dist/cjs/lib/v3/types/private/snapshot.js.map +1 -1
- package/dist/cjs/lib/v3/understudy/a11y/snapshot/a11yTree.js +25 -0
- package/dist/cjs/lib/v3/understudy/a11y/snapshot/a11yTree.js.map +1 -1
- package/dist/cjs/lib/v3/understudy/a11y/snapshot/treeFormatUtils.js +10 -1
- package/dist/cjs/lib/v3/understudy/a11y/snapshot/treeFormatUtils.js.map +1 -1
- package/dist/cjs/lib/version.d.ts +1 -1
- package/dist/cjs/lib/version.js +1 -1
- package/dist/cjs/lib/version.js.map +1 -1
- package/dist/cjs/tests/unit/anthropic-cua-triple-click.test.d.ts +1 -0
- package/dist/cjs/tests/unit/anthropic-cua-triple-click.test.js +87 -0
- package/dist/cjs/tests/unit/anthropic-cua-triple-click.test.js.map +1 -0
- package/dist/cjs/tests/unit/snapshot-a11y-tree-utils.test.js +33 -0
- package/dist/cjs/tests/unit/snapshot-a11y-tree-utils.test.js.map +1 -1
- package/dist/cjs/tests/unit/snapshot-tree-format-utils.test.js +43 -0
- package/dist/cjs/tests/unit/snapshot-tree-format-utils.test.js.map +1 -1
- package/dist/esm/lib/v3/agent/AnthropicCUAClient.js +10 -0
- package/dist/esm/lib/v3/agent/AnthropicCUAClient.js.map +1 -1
- package/dist/esm/lib/v3/handlers/v3CuaAgentHandler.js +1 -0
- package/dist/esm/lib/v3/handlers/v3CuaAgentHandler.js.map +1 -1
- package/dist/esm/lib/v3/types/private/snapshot.d.ts +2 -0
- package/dist/esm/lib/v3/types/private/snapshot.js.map +1 -1
- package/dist/esm/lib/v3/understudy/a11y/snapshot/a11yTree.js +25 -0
- package/dist/esm/lib/v3/understudy/a11y/snapshot/a11yTree.js.map +1 -1
- package/dist/esm/lib/v3/understudy/a11y/snapshot/treeFormatUtils.js +10 -1
- package/dist/esm/lib/v3/understudy/a11y/snapshot/treeFormatUtils.js.map +1 -1
- package/dist/esm/lib/version.d.ts +1 -1
- package/dist/esm/lib/version.js +1 -1
- package/dist/esm/lib/version.js.map +1 -1
- package/dist/esm/tests/unit/anthropic-cua-triple-click.test.d.ts +1 -0
- package/dist/esm/tests/unit/anthropic-cua-triple-click.test.js +82 -0
- package/dist/esm/tests/unit/anthropic-cua-triple-click.test.js.map +1 -0
- package/dist/esm/tests/unit/snapshot-a11y-tree-utils.test.js +33 -0
- package/dist/esm/tests/unit/snapshot-a11y-tree-utils.test.js.map +1 -1
- package/dist/esm/tests/unit/snapshot-tree-format-utils.test.js +43 -0
- package/dist/esm/tests/unit/snapshot-tree-format-utils.test.js.map +1 -1
- package/package.json +7 -6
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"a11yTree.js","sourceRoot":"","sources":["../../../../../../../lib/v3/understudy/a11y/snapshot/a11yTree.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Protocol } from \"devtools-protocol\";\nimport type { CDPSessionLike } from \"../../cdp.js\";\nimport type {\n A11yNode,\n A11yOptions,\n AccessibilityTreeResult,\n} from \"../../../types/private/snapshot.js\";\nimport {\n resolveObjectIdForCss,\n resolveObjectIdForXPath,\n} from \"./focusSelectors.js\";\nimport { formatTreeLine, normaliseSpaces } from \"./treeFormatUtils.js\";\n\n/**\n * Fetch and prune the accessibility tree for a frame, optionally scoping the\n * output to a selector root for faster targeted snapshots.\n */\nexport async function a11yForFrame(\n session: CDPSessionLike,\n frameId: string | undefined,\n opts: A11yOptions,\n): Promise<AccessibilityTreeResult> {\n await session.send(\"Accessibility.enable\").catch(() => {});\n await session.send(\"Runtime.enable\").catch(() => {});\n await session.send(\"DOM.enable\").catch(() => {});\n\n let nodes: Protocol.Accessibility.AXNode[] = [];\n try {\n const params = frameId ? ({ frameId } as Record<string, unknown>) : {};\n ({ nodes } = await session.send<{\n nodes: Protocol.Accessibility.AXNode[];\n }>(\"Accessibility.getFullAXTree\", params));\n } catch (e) {\n const msg = String((e as Error)?.message ?? e ?? \"\");\n const isFrameScopeError =\n msg.includes(\"Frame with the given\") ||\n msg.includes(\"does not belong to the target\") ||\n msg.includes(\"is not found\");\n if (!isFrameScopeError || !frameId) throw e;\n ({ nodes } = await session.send<{\n nodes: Protocol.Accessibility.AXNode[];\n }>(\"Accessibility.getFullAXTree\"));\n }\n\n let scopeApplied = false;\n const nodesForOutline = await (async () => {\n const sel = opts.focusSelector?.trim();\n if (!sel) return nodes;\n try {\n const looksLikeXPath = /^xpath=/i.test(sel) || sel.startsWith(\"/\");\n const objectId = looksLikeXPath\n ? await resolveObjectIdForXPath(session, sel, frameId)\n : await resolveObjectIdForCss(session, sel, frameId);\n if (!objectId) return nodes;\n const desc = await session.send<{ node?: { backendNodeId?: number } }>(\n \"DOM.describeNode\",\n { objectId },\n );\n const be = desc.node?.backendNodeId;\n if (typeof be !== \"number\") return nodes;\n const target = nodes.find((n) => n.backendDOMNodeId === be);\n if (!target) return nodes;\n scopeApplied = true;\n const keep = new Set<string>([target.nodeId]);\n const queue: Protocol.Accessibility.AXNode[] = [target];\n while (queue.length) {\n const cur = queue.shift()!;\n for (const id of cur.childIds ?? []) {\n if (keep.has(id)) continue;\n keep.add(id);\n const child = nodes.find((n) => n.nodeId === id);\n if (child) queue.push(child);\n }\n }\n return nodes\n .filter((n) => keep.has(n.nodeId))\n .map((n) =>\n n.nodeId === target.nodeId ? { ...n, parentId: undefined } : n,\n );\n } catch {\n return nodes;\n }\n })();\n\n const filteredNodes = nodesForOutline.filter((node) => {\n const be = node.backendDOMNodeId;\n return typeof be !== \"number\" || !opts.isIgnoredBackendNode?.(be);\n });\n\n const urlMap: Record<string, string> = {};\n for (const n of filteredNodes) {\n const be = n.backendDOMNodeId;\n if (typeof be !== \"number\") continue;\n const url = extractUrlFromAXNode(n);\n if (!url) continue;\n const enc = opts.encode(be);\n urlMap[enc] = url;\n }\n\n const decorated = decorateRoles(filteredNodes, opts);\n const { tree } = await buildHierarchicalTree(decorated, opts);\n\n const simplified = tree.map((n) => formatTreeLine(n)).join(\"\\n\");\n return { outline: simplified.trimEnd(), urlMap, scopeApplied };\n}\n\nexport function decorateRoles(\n nodes: Protocol.Accessibility.AXNode[],\n opts: A11yOptions,\n): A11yNode[] {\n const asRole = (n: Protocol.Accessibility.AXNode) =>\n String(n.role?.value ?? \"\");\n\n return nodes.map((n) => {\n let encodedId: string | undefined;\n if (typeof n.backendDOMNodeId === \"number\") {\n try {\n encodedId = opts.encode(n.backendDOMNodeId);\n } catch {\n //\n }\n }\n\n let role = asRole(n);\n\n const domIsScrollable = encodedId\n ? opts.scrollableMap[encodedId] === true\n : false;\n const tag = encodedId ? opts.tagNameMap[encodedId] : undefined;\n const isHtmlElement = tag === \"html\";\n if ((domIsScrollable || isHtmlElement) && tag !== \"#document\") {\n const tagLabel = tag && tag.startsWith(\"#\") ? tag.slice(1) : tag;\n role = tagLabel\n ? `scrollable, ${tagLabel}`\n : `scrollable${role ? `, ${role}` : \"\"}`;\n }\n\n // File inputs typically get role \"button\" from Chrome's AX tree;\n // override so they appear as \"input, file\" in the outline.\n if (tag === \"input, file\") {\n role = tag;\n }\n\n return {\n role,\n name: n.name?.value,\n description: n.description?.value,\n value: n.value?.value,\n nodeId: n.nodeId,\n backendDOMNodeId: n.backendDOMNodeId,\n parentId: n.parentId,\n childIds: n.childIds,\n encodedId,\n };\n });\n}\n\nexport async function buildHierarchicalTree(\n nodes: A11yNode[],\n opts: A11yOptions,\n): Promise<{ tree: A11yNode[] }> {\n const nodeMap = new Map<string, A11yNode>();\n\n for (const n of nodes) {\n const keep =\n !!(n.name && n.name.trim()) ||\n !!(n.childIds && n.childIds.length) ||\n !isStructural(n.role);\n if (!keep) continue;\n nodeMap.set(n.nodeId, { ...n });\n }\n\n for (const n of nodes) {\n if (!n.parentId) continue;\n const parent = nodeMap.get(n.parentId);\n const cur = nodeMap.get(n.nodeId);\n if (parent && cur) (parent.children ??= []).push(cur);\n }\n\n const roots = nodes\n .filter((n) => !n.parentId && nodeMap.has(n.nodeId))\n .map((n) => nodeMap.get(n.nodeId)!) as A11yNode[];\n\n const cleaned = (await Promise.all(roots.map(pruneStructuralSafe))).filter(\n Boolean,\n ) as A11yNode[];\n\n return { tree: cleaned };\n\n async function pruneStructuralSafe(node: A11yNode): Promise<A11yNode | null> {\n if (+node.nodeId < 0) return null;\n\n const children = node.children ?? [];\n if (!children.length) {\n return isStructural(node.role) ? null : node;\n }\n\n const cleanedKids = (\n await Promise.all(children.map(pruneStructuralSafe))\n ).filter(Boolean) as A11yNode[];\n\n const prunedStatic = removeRedundantStaticTextChildren(node, cleanedKids);\n\n if (isStructural(node.role)) {\n if (prunedStatic.length === 1) return prunedStatic[0]!;\n if (prunedStatic.length === 0) return null;\n }\n\n let newRole = node.role;\n if ((newRole === \"generic\" || newRole === \"none\") && node.encodedId) {\n const tagName = opts.tagNameMap[node.encodedId];\n if (tagName) newRole = tagName;\n }\n\n if (newRole === \"combobox\" && node.encodedId) {\n const tagName = opts.tagNameMap[node.encodedId];\n if (tagName === \"select\") newRole = \"select\";\n }\n\n return { ...node, role: newRole, children: prunedStatic };\n }\n}\n\nexport function isStructural(role: string): boolean {\n const r = role?.toLowerCase();\n return r === \"generic\" || r === \"none\" || r === \"inlinetextbox\";\n}\n\nexport function extractUrlFromAXNode(\n ax: Protocol.Accessibility.AXNode,\n): string | undefined {\n const props = ax.properties ?? [];\n const urlProp = props.find((p) => p.name === \"url\");\n const value = urlProp?.value?.value;\n return typeof value === \"string\" && value.trim() ? value.trim() : undefined;\n}\n\nexport function removeRedundantStaticTextChildren(\n parent: A11yNode,\n children: A11yNode[],\n): A11yNode[] {\n if (!parent.name) return children;\n const parentNorm = normaliseSpaces(parent.name).trim();\n let combined = \"\";\n for (const c of children) {\n if (c.role === \"StaticText\" && c.name) {\n combined += normaliseSpaces(c.name).trim();\n }\n }\n if (combined === parentNorm) {\n return children.filter((c) => c.role !== \"StaticText\");\n }\n return children;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"a11yTree.js","sourceRoot":"","sources":["../../../../../../../lib/v3/understudy/a11y/snapshot/a11yTree.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Protocol } from \"devtools-protocol\";\nimport type { CDPSessionLike } from \"../../cdp.js\";\nimport type {\n A11yNode,\n A11yOptions,\n AccessibilityTreeResult,\n} from \"../../../types/private/snapshot.js\";\nimport {\n resolveObjectIdForCss,\n resolveObjectIdForXPath,\n} from \"./focusSelectors.js\";\nimport { formatTreeLine, normaliseSpaces } from \"./treeFormatUtils.js\";\n\n/**\n * Fetch and prune the accessibility tree for a frame, optionally scoping the\n * output to a selector root for faster targeted snapshots.\n */\nexport async function a11yForFrame(\n session: CDPSessionLike,\n frameId: string | undefined,\n opts: A11yOptions,\n): Promise<AccessibilityTreeResult> {\n await session.send(\"Accessibility.enable\").catch(() => {});\n await session.send(\"Runtime.enable\").catch(() => {});\n await session.send(\"DOM.enable\").catch(() => {});\n\n let nodes: Protocol.Accessibility.AXNode[] = [];\n try {\n const params = frameId ? ({ frameId } as Record<string, unknown>) : {};\n ({ nodes } = await session.send<{\n nodes: Protocol.Accessibility.AXNode[];\n }>(\"Accessibility.getFullAXTree\", params));\n } catch (e) {\n const msg = String((e as Error)?.message ?? e ?? \"\");\n const isFrameScopeError =\n msg.includes(\"Frame with the given\") ||\n msg.includes(\"does not belong to the target\") ||\n msg.includes(\"is not found\");\n if (!isFrameScopeError || !frameId) throw e;\n ({ nodes } = await session.send<{\n nodes: Protocol.Accessibility.AXNode[];\n }>(\"Accessibility.getFullAXTree\"));\n }\n\n let scopeApplied = false;\n const nodesForOutline = await (async () => {\n const sel = opts.focusSelector?.trim();\n if (!sel) return nodes;\n try {\n const looksLikeXPath = /^xpath=/i.test(sel) || sel.startsWith(\"/\");\n const objectId = looksLikeXPath\n ? await resolveObjectIdForXPath(session, sel, frameId)\n : await resolveObjectIdForCss(session, sel, frameId);\n if (!objectId) return nodes;\n const desc = await session.send<{ node?: { backendNodeId?: number } }>(\n \"DOM.describeNode\",\n { objectId },\n );\n const be = desc.node?.backendNodeId;\n if (typeof be !== \"number\") return nodes;\n const target = nodes.find((n) => n.backendDOMNodeId === be);\n if (!target) return nodes;\n scopeApplied = true;\n const keep = new Set<string>([target.nodeId]);\n const queue: Protocol.Accessibility.AXNode[] = [target];\n while (queue.length) {\n const cur = queue.shift()!;\n for (const id of cur.childIds ?? []) {\n if (keep.has(id)) continue;\n keep.add(id);\n const child = nodes.find((n) => n.nodeId === id);\n if (child) queue.push(child);\n }\n }\n return nodes\n .filter((n) => keep.has(n.nodeId))\n .map((n) =>\n n.nodeId === target.nodeId ? { ...n, parentId: undefined } : n,\n );\n } catch {\n return nodes;\n }\n })();\n\n const filteredNodes = nodesForOutline.filter((node) => {\n const be = node.backendDOMNodeId;\n return typeof be !== \"number\" || !opts.isIgnoredBackendNode?.(be);\n });\n\n const urlMap: Record<string, string> = {};\n for (const n of filteredNodes) {\n const be = n.backendDOMNodeId;\n if (typeof be !== \"number\") continue;\n const url = extractUrlFromAXNode(n);\n if (!url) continue;\n const enc = opts.encode(be);\n urlMap[enc] = url;\n }\n\n const decorated = decorateRoles(filteredNodes, opts);\n const { tree } = await buildHierarchicalTree(decorated, opts);\n\n const simplified = tree.map((n) => formatTreeLine(n)).join(\"\\n\");\n return { outline: simplified.trimEnd(), urlMap, scopeApplied };\n}\n\nexport function decorateRoles(\n nodes: Protocol.Accessibility.AXNode[],\n opts: A11yOptions,\n): A11yNode[] {\n const asRole = (n: Protocol.Accessibility.AXNode) =>\n String(n.role?.value ?? \"\");\n\n return nodes.map((n) => {\n let encodedId: string | undefined;\n if (typeof n.backendDOMNodeId === \"number\") {\n try {\n encodedId = opts.encode(n.backendDOMNodeId);\n } catch {\n //\n }\n }\n\n let role = asRole(n);\n\n const domIsScrollable = encodedId\n ? opts.scrollableMap[encodedId] === true\n : false;\n const tag = encodedId ? opts.tagNameMap[encodedId] : undefined;\n const isHtmlElement = tag === \"html\";\n if ((domIsScrollable || isHtmlElement) && tag !== \"#document\") {\n const tagLabel = tag && tag.startsWith(\"#\") ? tag.slice(1) : tag;\n role = tagLabel\n ? `scrollable, ${tagLabel}`\n : `scrollable${role ? `, ${role}` : \"\"}`;\n }\n\n // File inputs typically get role \"button\" from Chrome's AX tree;\n // override so they appear as \"input, file\" in the outline.\n if (tag === \"input, file\") {\n role = tag;\n }\n\n return {\n role,\n name: n.name?.value,\n description: n.description?.value,\n value: n.value?.value,\n selected: extractBooleanProperty(n, \"selected\"),\n checked: extractBooleanProperty(n, \"checked\"),\n nodeId: n.nodeId,\n backendDOMNodeId: n.backendDOMNodeId,\n parentId: n.parentId,\n childIds: n.childIds,\n encodedId,\n };\n });\n}\n\nexport async function buildHierarchicalTree(\n nodes: A11yNode[],\n opts: A11yOptions,\n): Promise<{ tree: A11yNode[] }> {\n const nodeMap = new Map<string, A11yNode>();\n\n for (const n of nodes) {\n const keep =\n !!(n.name && n.name.trim()) ||\n !!(n.childIds && n.childIds.length) ||\n !isStructural(n.role);\n if (!keep) continue;\n nodeMap.set(n.nodeId, { ...n });\n }\n\n for (const n of nodes) {\n if (!n.parentId) continue;\n const parent = nodeMap.get(n.parentId);\n const cur = nodeMap.get(n.nodeId);\n if (parent && cur) (parent.children ??= []).push(cur);\n }\n\n const roots = nodes\n .filter((n) => !n.parentId && nodeMap.has(n.nodeId))\n .map((n) => nodeMap.get(n.nodeId)!) as A11yNode[];\n\n const cleaned = (await Promise.all(roots.map(pruneStructuralSafe))).filter(\n Boolean,\n ) as A11yNode[];\n\n return { tree: cleaned };\n\n async function pruneStructuralSafe(node: A11yNode): Promise<A11yNode | null> {\n if (+node.nodeId < 0) return null;\n\n const children = node.children ?? [];\n if (!children.length) {\n return isStructural(node.role) ? null : node;\n }\n\n const cleanedKids = (\n await Promise.all(children.map(pruneStructuralSafe))\n ).filter(Boolean) as A11yNode[];\n\n const prunedStatic = removeRedundantStaticTextChildren(node, cleanedKids);\n\n if (isStructural(node.role)) {\n if (prunedStatic.length === 1) return prunedStatic[0]!;\n if (prunedStatic.length === 0) return null;\n }\n\n let newRole = node.role;\n if ((newRole === \"generic\" || newRole === \"none\") && node.encodedId) {\n const tagName = opts.tagNameMap[node.encodedId];\n if (tagName) newRole = tagName;\n }\n\n if (newRole === \"combobox\" && node.encodedId) {\n const tagName = opts.tagNameMap[node.encodedId];\n if (tagName === \"select\") newRole = \"select\";\n }\n\n return { ...node, role: newRole, children: prunedStatic };\n }\n}\n\nexport function isStructural(role: string): boolean {\n const r = role?.toLowerCase();\n return r === \"generic\" || r === \"none\" || r === \"inlinetextbox\";\n}\n\nexport function extractUrlFromAXNode(\n ax: Protocol.Accessibility.AXNode,\n): string | undefined {\n const props = ax.properties ?? [];\n const urlProp = props.find((p) => p.name === \"url\");\n const value = urlProp?.value?.value;\n return typeof value === \"string\" && value.trim() ? value.trim() : undefined;\n}\nfunction toBooleanValue(value: unknown): boolean | undefined {\n if (typeof value === \"boolean\") return value;\n if (typeof value === \"number\") {\n if (value === 1) return true;\n if (value === 0) return false;\n }\n if (typeof value === \"string\") {\n const normalized = value.toLowerCase();\n if (normalized === \"true\") return true;\n if (normalized === \"false\") return false;\n }\n return undefined;\n}\n\nfunction extractBooleanProperty(\n node: Protocol.Accessibility.AXNode,\n propertyName: string,\n): boolean | undefined {\n const value = node.properties?.find((p) => p.name === propertyName)?.value\n ?.value;\n return toBooleanValue(value);\n}\n\nexport function removeRedundantStaticTextChildren(\n parent: A11yNode,\n children: A11yNode[],\n): A11yNode[] {\n if (!parent.name) return children;\n const parentNorm = normaliseSpaces(parent.name).trim();\n let combined = \"\";\n for (const c of children) {\n if (c.role === \"StaticText\" && c.name) {\n combined += normaliseSpaces(c.name).trim();\n }\n }\n if (combined === parentNorm) {\n return children.filter((c) => c.role !== \"StaticText\");\n }\n return children;\n}\n"]}
|
|
@@ -6,10 +6,19 @@
|
|
|
6
6
|
export function formatTreeLine(node, level = 0) {
|
|
7
7
|
const indent = " ".repeat(level);
|
|
8
8
|
const labelId = node.encodedId ?? node.nodeId;
|
|
9
|
-
const
|
|
9
|
+
const stateFlags = formatStateFlags(node);
|
|
10
|
+
const label = `[${labelId}] ${node.role}${node.name ? `: ${cleanText(node.name)}` : ""}${stateFlags}`;
|
|
10
11
|
const kids = node.children?.map((c) => formatTreeLine(c, level + 1)).join("\n") ?? "";
|
|
11
12
|
return kids ? `${indent}${label}\n${kids}` : `${indent}${label}`;
|
|
12
13
|
}
|
|
14
|
+
function formatStateFlags(node) {
|
|
15
|
+
let flags = "";
|
|
16
|
+
if (node.selected)
|
|
17
|
+
flags += " [selected]";
|
|
18
|
+
if (node.checked)
|
|
19
|
+
flags += " [checked]";
|
|
20
|
+
return flags;
|
|
21
|
+
}
|
|
13
22
|
/**
|
|
14
23
|
* Inject each child frame outline under the parent's iframe node line.
|
|
15
24
|
* Keys in `idToTree` are the parent's iframe encoded ids.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"treeFormatUtils.js","sourceRoot":"","sources":["../../../../../../../lib/v3/understudy/a11y/snapshot/treeFormatUtils.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,IAAc,EAAE,KAAK,GAAG,CAAC;IACtD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAClC,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,MAAM,CAAC;IAC9C,MAAM,KAAK,GAAG,IAAI,OAAO,KAAK,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"treeFormatUtils.js","sourceRoot":"","sources":["../../../../../../../lib/v3/understudy/a11y/snapshot/treeFormatUtils.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,IAAc,EAAE,KAAK,GAAG,CAAC;IACtD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAClC,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,MAAM,CAAC;IAC9C,MAAM,UAAU,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;IAC1C,MAAM,KAAK,GAAG,IAAI,OAAO,KAAK,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,UAAU,EAAE,CAAC;IACtG,MAAM,IAAI,GACR,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IAC3E,OAAO,IAAI,CAAC,CAAC,CAAC,GAAG,MAAM,GAAG,KAAK,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,MAAM,GAAG,KAAK,EAAE,CAAC;AACnE,CAAC;AAED,SAAS,gBAAgB,CAAC,IAAc;IACtC,IAAI,KAAK,GAAG,EAAE,CAAC;IACf,IAAI,IAAI,CAAC,QAAQ;QAAE,KAAK,IAAI,aAAa,CAAC;IAC1C,IAAI,IAAI,CAAC,OAAO;QAAE,KAAK,IAAI,YAAY,CAAC;IACxC,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAC5B,WAAmB,EACnB,QAA6B;IAG7B,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,MAAM,KAAK,GAAY,CAAC,EAAE,KAAK,EAAE,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IAElE,OAAO,KAAK,CAAC,MAAM,EAAE,CAAC;QACpB,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACpC,IAAI,GAAG,CAAC,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YAC9B,KAAK,CAAC,GAAG,EAAE,CAAC;YACZ,SAAS;QACX,CAAC;QAED,MAAM,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC;QAC/B,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAEd,MAAM,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC9C,MAAM,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAEzC,MAAM,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;QACxC,IAAI,CAAC,CAAC;YAAE,SAAS;QAEjB,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC;QACpB,MAAM,YAAY,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACzC,IAAI,CAAC,YAAY,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;YAAE,SAAS;QAElD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAEnB,MAAM,kBAAkB,GAAG,cAAc,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;QAClE,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,kBAAkB,CAAC,OAAO,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC;IACrE,CAAC;IAED,OAAO,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACxB,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAa,EAAE,MAAc;IACvD,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IACtB,OAAO,KAAK;SACT,KAAK,CAAC,IAAI,CAAC;SACX,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;SAC5D,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,QAAgB,EAAE,QAAgB;IAClE,MAAM,OAAO,GAAG,IAAI,GAAG,CACrB,CAAC,QAAQ,IAAI,EAAE,CAAC;SACb,KAAK,CAAC,IAAI,CAAC;SACX,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;SACpB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAC/B,CAAC;IAEF,MAAM,SAAS,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC/C,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;QAC7B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI;YAAE,SAAS;QACpB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3C,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAElC,IAAI,SAAS,GAAG,QAAQ,CAAC;IACzB,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE;YAAE,SAAS;QACxB,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAC1B,MAAM,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QACvC,IAAI,SAAS,GAAG,SAAS;YAAE,SAAS,GAAG,SAAS,CAAC;IACnD,CAAC;IACD,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC;QAAE,SAAS,GAAG,CAAC,CAAC;IAExC,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAC1B,CAAC,CAAC,MAAM,IAAI,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAC/C,CAAC;IACF,OAAO,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACxB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS,CAAC,KAAa;IACrC,MAAM,SAAS,GAAG,MAAM,CAAC;IACzB,MAAM,OAAO,GAAG,MAAM,CAAC;IACvB,MAAM,IAAI,GAAG,IAAI,GAAG,CAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAE/D,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,IAAI,SAAS,GAAG,KAAK,CAAC;IACtB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QACjC,IAAI,IAAI,IAAI,SAAS,IAAI,IAAI,IAAI,OAAO;YAAE,SAAS;QACnD,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACnB,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,GAAG,IAAI,GAAG,CAAC;gBACX,SAAS,GAAG,IAAI,CAAC;YACnB,CAAC;YACD,SAAS;QACX,CAAC;QACD,GAAG,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC;QAChB,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC;IAC/B,CAAC;IACD,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC;AACpB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,CAAS;IACvC,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,IAAI,IAAI,GAAG,KAAK,CAAC;IACjB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAClC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC;QACjB,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC3B,IAAI,IAAI,EAAE,CAAC;YACT,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,GAAG,IAAI,GAAG,CAAC;gBACX,IAAI,GAAG,IAAI,CAAC;YACd,CAAC;QACH,CAAC;aAAM,CAAC;YACN,GAAG,IAAI,EAAE,CAAC;YACV,IAAI,GAAG,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC","sourcesContent":["import type { A11yNode } from \"../../../types/private/snapshot.js\";\n\n/**\n * Render a formatted outline (with encoded ids) for the accessibility tree.\n * Keeps indentation logic shared between modules so unit tests can cover these\n * pure formatting helpers without a full snapshot pipeline.\n */\nexport function formatTreeLine(node: A11yNode, level = 0): string {\n const indent = \" \".repeat(level);\n const labelId = node.encodedId ?? node.nodeId;\n const stateFlags = formatStateFlags(node);\n const label = `[${labelId}] ${node.role}${node.name ? `: ${cleanText(node.name)}` : \"\"}${stateFlags}`;\n const kids =\n node.children?.map((c) => formatTreeLine(c, level + 1)).join(\"\\n\") ?? \"\";\n return kids ? `${indent}${label}\\n${kids}` : `${indent}${label}`;\n}\n\nfunction formatStateFlags(node: A11yNode): string {\n let flags = \"\";\n if (node.selected) flags += \" [selected]\";\n if (node.checked) flags += \" [checked]\";\n return flags;\n}\n\n/**\n * Inject each child frame outline under the parent's iframe node line.\n * Keys in `idToTree` are the parent's iframe encoded ids.\n */\nexport function injectSubtrees(\n rootOutline: string,\n idToTree: Map<string, string>,\n): string {\n type Frame = { lines: string[]; i: number };\n const out: string[] = [];\n const visited = new Set<string>();\n const stack: Frame[] = [{ lines: rootOutline.split(\"\\n\"), i: 0 }];\n\n while (stack.length) {\n const top = stack[stack.length - 1];\n if (top.i >= top.lines.length) {\n stack.pop();\n continue;\n }\n\n const raw = top.lines[top.i++];\n out.push(raw);\n\n const indent = raw.match(/^(\\s*)/)?.[1] ?? \"\";\n const content = raw.slice(indent.length);\n\n const m = content.match(/^\\[([^\\]]+)]/);\n if (!m) continue;\n\n const encId = m[1]!;\n const childOutline = idToTree.get(encId);\n if (!childOutline || visited.has(encId)) continue;\n\n visited.add(encId);\n\n const fullyInjectedChild = injectSubtrees(childOutline, idToTree);\n out.push(indentBlock(fullyInjectedChild.trimEnd(), indent + \" \"));\n }\n\n return out.join(\"\\n\");\n}\n\nexport function indentBlock(block: string, indent: string): string {\n if (!block) return \"\";\n return block\n .split(\"\\n\")\n .map((line) => (line.length ? indent + line : indent + line))\n .join(\"\\n\");\n}\n\n/**\n * Return the lines that appear in `nextTree` but not in `prevTree`.\n * Comparison is done line-by-line, ignoring leading whitespace in both trees.\n * The returned block is re-indented so the minimal indent becomes column 0.\n */\nexport function diffCombinedTrees(prevTree: string, nextTree: string): string {\n const prevSet = new Set(\n (prevTree || \"\")\n .split(\"\\n\")\n .map((l) => l.trim())\n .filter((l) => l.length > 0),\n );\n\n const nextLines = (nextTree || \"\").split(\"\\n\");\n const added: string[] = [];\n for (const line of nextLines) {\n const core = line.trim();\n if (!core) continue;\n if (!prevSet.has(core)) added.push(line);\n }\n\n if (added.length === 0) return \"\";\n\n let minIndent = Infinity;\n for (const l of added) {\n if (!l.trim()) continue;\n const m = l.match(/^\\s*/);\n const indentLen = m ? m[0]!.length : 0;\n if (indentLen < minIndent) minIndent = indentLen;\n }\n if (!isFinite(minIndent)) minIndent = 0;\n\n const out = added.map((l) =>\n l.length >= minIndent ? l.slice(minIndent) : l,\n );\n return out.join(\"\\n\");\n}\n\n/**\n * Remove whitespace noise and invisible code points before rendering names.\n */\nexport function cleanText(input: string): string {\n const PUA_START = 0xe000;\n const PUA_END = 0xf8ff;\n const NBSP = new Set<number>([0x00a0, 0x202f, 0x2007, 0xfeff]);\n\n let out = \"\";\n let prevSpace = false;\n for (let i = 0; i < input.length; i++) {\n const code = input.charCodeAt(i);\n if (code >= PUA_START && code <= PUA_END) continue;\n if (NBSP.has(code)) {\n if (!prevSpace) {\n out += \" \";\n prevSpace = true;\n }\n continue;\n }\n out += input[i];\n prevSpace = input[i] === \" \";\n }\n return out.trim();\n}\n\n/**\n * Collapse all whitespace runs in a string to a single space without trimming.\n * Exported for pruning routines that need the same normalization.\n */\nexport function normaliseSpaces(s: string): string {\n let out = \"\";\n let inWs = false;\n for (let i = 0; i < s.length; i++) {\n const ch = s[i]!;\n const isWs = /\\s/.test(ch);\n if (isWs) {\n if (!inWs) {\n out += \" \";\n inWs = true;\n }\n } else {\n out += ch;\n inWs = false;\n }\n }\n return out;\n}\n"]}
|
package/dist/esm/lib/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../../lib/version.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,OAAgB,CAAC","sourcesContent":["/**\n * AUTO-GENERATED — DO NOT EDIT BY HAND\n * Run `pnpm run gen-version` to refresh.\n */\nexport const STAGEHAND_VERSION = \"3.
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../../lib/version.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,OAAgB,CAAC","sourcesContent":["/**\n * AUTO-GENERATED — DO NOT EDIT BY HAND\n * Run `pnpm run gen-version` to refresh.\n */\nexport const STAGEHAND_VERSION = \"3.4.0\" as const;\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { describe, expect, it, vi, beforeEach } from "vitest";
|
|
2
|
+
import { AnthropicCUAClient } from "../../lib/v3/agent/AnthropicCUAClient.js";
|
|
3
|
+
import Anthropic from "@anthropic-ai/sdk";
|
|
4
|
+
vi.mock("@anthropic-ai/sdk", () => {
|
|
5
|
+
const mockCreate = vi.fn();
|
|
6
|
+
return {
|
|
7
|
+
default: class MockAnthropic {
|
|
8
|
+
beta = {
|
|
9
|
+
messages: {
|
|
10
|
+
create: mockCreate,
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
},
|
|
14
|
+
};
|
|
15
|
+
});
|
|
16
|
+
describe("AnthropicCUAClient triple_click handling", () => {
|
|
17
|
+
let mockCreate;
|
|
18
|
+
let client;
|
|
19
|
+
let executedActions;
|
|
20
|
+
beforeEach(() => {
|
|
21
|
+
vi.clearAllMocks();
|
|
22
|
+
const anthropic = new Anthropic({ apiKey: "test" });
|
|
23
|
+
mockCreate = anthropic.beta.messages.create;
|
|
24
|
+
client = new AnthropicCUAClient("anthropic", "claude-sonnet-4-5-20250929", undefined, {
|
|
25
|
+
apiKey: "test-key",
|
|
26
|
+
});
|
|
27
|
+
client.setViewport(1280, 720);
|
|
28
|
+
client.setScreenshotProvider(async () => "fake-base64-screenshot");
|
|
29
|
+
executedActions = [];
|
|
30
|
+
client.setActionHandler(async (action) => {
|
|
31
|
+
executedActions.push({ ...action });
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
it("should convert triple_click with coordinate array to tripleClick action", async () => {
|
|
35
|
+
mockCreate.mockResolvedValue({
|
|
36
|
+
id: "test-id",
|
|
37
|
+
content: [
|
|
38
|
+
{
|
|
39
|
+
type: "tool_use",
|
|
40
|
+
id: "tool-1",
|
|
41
|
+
name: "computer",
|
|
42
|
+
input: {
|
|
43
|
+
action: "triple_click",
|
|
44
|
+
coordinate: [640, 360],
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
usage: { input_tokens: 10, output_tokens: 20 },
|
|
49
|
+
});
|
|
50
|
+
const logger = vi.fn();
|
|
51
|
+
await client.executeStep([{ role: "user", content: "triple click the paragraph" }], logger);
|
|
52
|
+
expect(executedActions).toHaveLength(1);
|
|
53
|
+
expect(executedActions[0].type).toBe("tripleClick");
|
|
54
|
+
expect(executedActions[0].x).toBe(640);
|
|
55
|
+
expect(executedActions[0].y).toBe(360);
|
|
56
|
+
});
|
|
57
|
+
it("should convert triple_click with x/y fields to tripleClick action", async () => {
|
|
58
|
+
mockCreate.mockResolvedValue({
|
|
59
|
+
id: "test-id",
|
|
60
|
+
content: [
|
|
61
|
+
{
|
|
62
|
+
type: "tool_use",
|
|
63
|
+
id: "tool-2",
|
|
64
|
+
name: "computer",
|
|
65
|
+
input: {
|
|
66
|
+
action: "triple_click",
|
|
67
|
+
x: 100,
|
|
68
|
+
y: 200,
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
],
|
|
72
|
+
usage: { input_tokens: 10, output_tokens: 20 },
|
|
73
|
+
});
|
|
74
|
+
const logger = vi.fn();
|
|
75
|
+
await client.executeStep([{ role: "user", content: "triple click the line" }], logger);
|
|
76
|
+
expect(executedActions).toHaveLength(1);
|
|
77
|
+
expect(executedActions[0].type).toBe("tripleClick");
|
|
78
|
+
expect(executedActions[0].x).toBe(100);
|
|
79
|
+
expect(executedActions[0].y).toBe(200);
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
//# sourceMappingURL=anthropic-cua-triple-click.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anthropic-cua-triple-click.test.js","sourceRoot":"","sources":["../../../../tests/unit/anthropic-cua-triple-click.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, expect, it, vi, beforeEach } from \"vitest\";\nimport { AnthropicCUAClient } from \"../../lib/v3/agent/AnthropicCUAClient.js\";\nimport Anthropic from \"@anthropic-ai/sdk\";\n\nvi.mock(\"@anthropic-ai/sdk\", () => {\n const mockCreate = vi.fn();\n\n return {\n default: class MockAnthropic {\n beta = {\n messages: {\n create: mockCreate,\n },\n };\n },\n };\n});\n\ndescribe(\"AnthropicCUAClient triple_click handling\", () => {\n let mockCreate: ReturnType<typeof vi.fn>;\n let client: AnthropicCUAClient;\n let executedActions: Array<Record<string, unknown>>;\n\n beforeEach(() => {\n vi.clearAllMocks();\n const anthropic = new Anthropic({ apiKey: \"test\" });\n mockCreate = anthropic.beta.messages.create as ReturnType<typeof vi.fn>;\n\n client = new AnthropicCUAClient(\n \"anthropic\",\n \"claude-sonnet-4-5-20250929\",\n undefined,\n {\n apiKey: \"test-key\",\n },\n );\n client.setViewport(1280, 720);\n client.setScreenshotProvider(async () => \"fake-base64-screenshot\");\n\n executedActions = [];\n client.setActionHandler(async (action) => {\n executedActions.push({ ...action });\n });\n });\n\n it(\"should convert triple_click with coordinate array to tripleClick action\", async () => {\n mockCreate.mockResolvedValue({\n id: \"test-id\",\n content: [\n {\n type: \"tool_use\",\n id: \"tool-1\",\n name: \"computer\",\n input: {\n action: \"triple_click\",\n coordinate: [640, 360],\n },\n },\n ],\n usage: { input_tokens: 10, output_tokens: 20 },\n });\n\n const logger = vi.fn();\n await client.executeStep(\n [{ role: \"user\", content: \"triple click the paragraph\" }],\n logger,\n );\n\n expect(executedActions).toHaveLength(1);\n expect(executedActions[0].type).toBe(\"tripleClick\");\n expect(executedActions[0].x).toBe(640);\n expect(executedActions[0].y).toBe(360);\n });\n\n it(\"should convert triple_click with x/y fields to tripleClick action\", async () => {\n mockCreate.mockResolvedValue({\n id: \"test-id\",\n content: [\n {\n type: \"tool_use\",\n id: \"tool-2\",\n name: \"computer\",\n input: {\n action: \"triple_click\",\n x: 100,\n y: 200,\n },\n },\n ],\n usage: { input_tokens: 10, output_tokens: 20 },\n });\n\n const logger = vi.fn();\n await client.executeStep(\n [{ role: \"user\", content: \"triple click the line\" }],\n logger,\n );\n\n expect(executedActions).toHaveLength(1);\n expect(executedActions[0].type).toBe(\"tripleClick\");\n expect(executedActions[0].x).toBe(100);\n expect(executedActions[0].y).toBe(200);\n });\n});\n"]}
|
|
@@ -4,6 +4,10 @@ const axString = (value) => ({
|
|
|
4
4
|
type: "string",
|
|
5
5
|
value,
|
|
6
6
|
});
|
|
7
|
+
const axBool = (value) => ({
|
|
8
|
+
type: "boolean",
|
|
9
|
+
value,
|
|
10
|
+
});
|
|
7
11
|
const defaultOpts = {
|
|
8
12
|
focusSelector: undefined,
|
|
9
13
|
experimental: false,
|
|
@@ -92,6 +96,35 @@ describe("decorateRoles", () => {
|
|
|
92
96
|
const decorated = decorateRoles(nodes, opts);
|
|
93
97
|
expect(decorated[0]?.encodedId).toBeUndefined();
|
|
94
98
|
});
|
|
99
|
+
it("maps selected/checked AX properties into boolean fields", () => {
|
|
100
|
+
const nodes = [
|
|
101
|
+
makeAxNode({
|
|
102
|
+
backendDOMNodeId: 12,
|
|
103
|
+
role: axString("option"),
|
|
104
|
+
name: axString("Option B"),
|
|
105
|
+
properties: [{ name: "selected", value: axBool(true) }],
|
|
106
|
+
}),
|
|
107
|
+
makeAxNode({
|
|
108
|
+
backendDOMNodeId: 13,
|
|
109
|
+
role: axString("radio"),
|
|
110
|
+
name: axString("Option C"),
|
|
111
|
+
properties: [{ name: "checked", value: axBool(true) }],
|
|
112
|
+
}),
|
|
113
|
+
makeAxNode({
|
|
114
|
+
backendDOMNodeId: 14,
|
|
115
|
+
role: axString("radio"),
|
|
116
|
+
name: axString("Option D"),
|
|
117
|
+
properties: [
|
|
118
|
+
{ name: "selected", value: axBool(true) },
|
|
119
|
+
{ name: "checked", value: axBool(true) },
|
|
120
|
+
],
|
|
121
|
+
}),
|
|
122
|
+
];
|
|
123
|
+
const decorated = decorateRoles(nodes, defaultOpts);
|
|
124
|
+
expect(decorated[0]).toMatchObject({ selected: true, checked: undefined });
|
|
125
|
+
expect(decorated[1]).toMatchObject({ selected: undefined, checked: true });
|
|
126
|
+
expect(decorated[2]).toMatchObject({ selected: true, checked: true });
|
|
127
|
+
});
|
|
95
128
|
});
|
|
96
129
|
describe("buildHierarchicalTree", () => {
|
|
97
130
|
const opts = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"snapshot-a11y-tree-utils.test.js","sourceRoot":"","sources":["../../../../tests/unit/snapshot-a11y-tree-utils.test.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Protocol } from \"devtools-protocol\";\nimport { describe, expect, it } from \"vitest\";\nimport type {\n A11yNode,\n A11yOptions,\n} from \"../../lib/v3/types/private/snapshot.js\";\nimport {\n buildHierarchicalTree,\n decorateRoles,\n extractUrlFromAXNode,\n isStructural,\n removeRedundantStaticTextChildren,\n} from \"../../lib/v3/understudy/a11y/snapshot/a11yTree.js\";\n\nconst axString = (value: string): Protocol.Accessibility.AXValue => ({\n type: \"string\",\n value,\n});\n\nconst defaultOpts: A11yOptions = {\n focusSelector: undefined,\n experimental: false,\n tagNameMap: {},\n scrollableMap: {},\n encode: (backendNodeId: number) => `enc-${backendNodeId}`,\n};\n\nconst makeAxNode = (\n overrides: Partial<Protocol.Accessibility.AXNode> = {},\n): Protocol.Accessibility.AXNode => ({\n nodeId: overrides.nodeId ?? String(Math.random()),\n backendDOMNodeId:\n overrides.backendDOMNodeId ?? Math.floor(Math.random() * 1e6),\n role: overrides.role ?? axString(\"generic\"),\n childIds: overrides.childIds ?? [],\n parentId: overrides.parentId,\n properties: overrides.properties ?? [],\n name: overrides.name,\n description: overrides.description,\n value: overrides.value,\n ignored: overrides.ignored ?? false,\n});\n\ndescribe(\"decorateRoles\", () => {\n it(\"marks scrollable DOM nodes with tag labels and encoded ids\", () => {\n const opts: A11yOptions = {\n ...defaultOpts,\n tagNameMap: {\n \"enc-1\": \"div\",\n \"enc-2\": \"html\",\n \"enc-3\": \"#document\",\n \"enc-4\": \"#svg\",\n },\n scrollableMap: { \"enc-1\": true, \"enc-4\": true },\n };\n const nodes = [\n makeAxNode({\n backendDOMNodeId: 1,\n role: { type: \"string\", value: \"region\" },\n }),\n makeAxNode({\n backendDOMNodeId: 2,\n role: { type: \"string\", value: \"generic\" },\n }),\n makeAxNode({\n backendDOMNodeId: 3,\n role: { type: \"string\", value: \"generic\" },\n }),\n makeAxNode({\n backendDOMNodeId: 4,\n role: { type: \"string\", value: \"generic\" },\n }),\n ];\n\n const decorated = decorateRoles(nodes, opts);\n expect(decorated).toMatchObject([\n { encodedId: \"enc-1\", role: \"scrollable, div\" },\n { encodedId: \"enc-2\", role: \"scrollable, html\" },\n { encodedId: \"enc-3\", role: \"generic\" },\n { encodedId: \"enc-4\", role: \"scrollable, svg\" },\n ]);\n });\n\n it(\"overrides role to 'input, file' for file inputs\", () => {\n const opts: A11yOptions = {\n ...defaultOpts,\n tagNameMap: { \"enc-10\": \"input, file\" },\n scrollableMap: {},\n };\n const nodes = [\n makeAxNode({\n backendDOMNodeId: 10,\n role: axString(\"button\"),\n name: axString(\"Choose File\"),\n }),\n ];\n\n const decorated = decorateRoles(nodes, opts);\n expect(decorated[0]).toMatchObject({\n encodedId: \"enc-10\",\n role: \"input, file\",\n name: \"Choose File\",\n });\n });\n\n it(\"falls back when encoding fails\", () => {\n const opts: A11yOptions = {\n ...defaultOpts,\n encode: () => {\n throw new Error(\"boom\");\n },\n };\n const nodes = [makeAxNode({ backendDOMNodeId: 4 })];\n const decorated = decorateRoles(nodes, opts);\n expect(decorated[0]?.encodedId).toBeUndefined();\n });\n});\n\ndescribe(\"buildHierarchicalTree\", () => {\n const opts: A11yOptions = {\n ...defaultOpts,\n tagNameMap: { root: \"div\", child: \"span\" },\n };\n\n it(\"drops structural nodes without children or names\", async () => {\n const nodes: A11yNode[] = [\n {\n role: \"generic\",\n name: \"\",\n nodeId: \"root\",\n encodedId: \"root\",\n parentId: undefined,\n childIds: [\"child\"],\n },\n {\n role: \"generic\",\n name: \"\",\n nodeId: \"child\",\n encodedId: \"child\",\n parentId: \"root\",\n childIds: [],\n },\n ];\n\n const { tree } = await buildHierarchicalTree(nodes, opts);\n expect(tree).toEqual([]);\n });\n\n it(\"promotes select/combobox tag names for structural nodes\", async () => {\n const nodes: A11yNode[] = [\n {\n role: \"combobox\",\n name: \"Select\",\n nodeId: \"root\",\n encodedId: \"root\",\n parentId: undefined,\n childIds: [\"child\"],\n },\n {\n role: \"StaticText\",\n name: \"Option\",\n nodeId: \"child\",\n encodedId: \"child\",\n parentId: \"root\",\n childIds: [],\n },\n ];\n\n const { tree } = await buildHierarchicalTree(nodes, {\n ...opts,\n tagNameMap: { root: \"select\" },\n });\n expect(tree[0]?.role).toBe(\"select\");\n });\n\n it(\"drops structural parents with a single cleaned child while keeping it in place\", async () => {\n const nodes: A11yNode[] = [\n {\n role: \"generic\",\n name: \"\",\n nodeId: \"root\",\n encodedId: \"root\",\n parentId: undefined,\n childIds: [\"child\"],\n },\n {\n role: \"StaticText\",\n name: \"Ok\",\n nodeId: \"child\",\n encodedId: \"child\",\n parentId: \"root\",\n childIds: [],\n },\n ];\n\n const { tree } = await buildHierarchicalTree(nodes, opts);\n expect(tree[0]?.role).toBe(\"StaticText\");\n });\n\n it(\"drops structural parents entirely when all descendants are pruned\", async () => {\n const nodes: A11yNode[] = [\n {\n role: \"generic\",\n name: \"\",\n nodeId: \"root\",\n encodedId: \"root\",\n parentId: undefined,\n childIds: [\"child\"],\n },\n {\n role: \"generic\",\n name: \"\",\n nodeId: \"child\",\n encodedId: \"child\",\n parentId: \"root\",\n childIds: [],\n },\n ];\n\n const { tree } = await buildHierarchicalTree(nodes, opts);\n expect(tree).toEqual([]);\n });\n\n it(\"renames structural nodes to their tag names when not combobox\", async () => {\n const nodes: A11yNode[] = [\n {\n role: \"generic\",\n name: \"Container\",\n nodeId: \"root\",\n encodedId: \"root\",\n parentId: undefined,\n childIds: [\"child-a\", \"child-b\"],\n },\n {\n role: \"StaticText\",\n name: \"A\",\n nodeId: \"child-a\",\n encodedId: \"child-a\",\n parentId: \"root\",\n childIds: [],\n },\n {\n role: \"StaticText\",\n name: \"B\",\n nodeId: \"child-b\",\n encodedId: \"child-b\",\n parentId: \"root\",\n childIds: [],\n },\n ];\n\n const { tree } = await buildHierarchicalTree(nodes, {\n ...opts,\n tagNameMap: { root: \"section\" },\n });\n expect(tree[0]?.role).toBe(\"section\");\n });\n\n it(\"skips nodes with negative node ids early\", async () => {\n const nodes: A11yNode[] = [\n {\n role: \"button\",\n name: \"Hidden\",\n nodeId: \"-1\",\n encodedId: \"hidden\",\n parentId: undefined,\n childIds: [],\n },\n ];\n\n const { tree } = await buildHierarchicalTree(nodes, opts);\n expect(tree).toEqual([]);\n });\n});\n\ndescribe(\"isStructural\", () => {\n it(\"marks generic/none/InlineTextBox roles as structural\", () => {\n expect(isStructural(\"generic\")).toBe(true);\n expect(isStructural(\"none\")).toBe(true);\n expect(isStructural(\"InlineTextBox\")).toBe(true);\n expect(isStructural(\"button\")).toBe(false);\n });\n});\n\ndescribe(\"removeRedundantStaticTextChildren\", () => {\n it(\"removes static text children whose concatenated text equals the parent name\", () => {\n const parent: A11yNode = {\n role: \"button\",\n name: \"HelloWorld\",\n nodeId: \"root\",\n };\n const children: A11yNode[] = [\n { role: \"StaticText\", name: \"Hello\", nodeId: \"c1\" },\n { role: \"StaticText\", name: \"World\", nodeId: \"c2\" },\n { role: \"button\", name: \"Child\", nodeId: \"c3\" },\n ];\n const pruned = removeRedundantStaticTextChildren(parent, children);\n expect(pruned).toEqual([{ role: \"button\", name: \"Child\", nodeId: \"c3\" }]);\n });\n\n it(\"keeps static text when combined text differs\", () => {\n const parent: A11yNode = {\n role: \"button\",\n name: \"Hello World\",\n nodeId: \"root\",\n };\n const children: A11yNode[] = [\n { role: \"StaticText\", name: \"Hello\", nodeId: \"c1\" },\n { role: \"StaticText\", name: \"Mars\", nodeId: \"c2\" },\n ];\n expect(removeRedundantStaticTextChildren(parent, children)).toEqual(\n children,\n );\n });\n it(\"returns original children when parent name is empty\", () => {\n const parent: A11yNode = {\n role: \"button\",\n nodeId: \"root\",\n };\n const children: A11yNode[] = [\n { role: \"StaticText\", name: \"Hello\", nodeId: \"c1\" },\n { role: \"StaticText\", name: \"World\", nodeId: \"c2\" },\n ];\n expect(removeRedundantStaticTextChildren(parent, children)).toEqual(\n children,\n );\n });\n});\n\ndescribe(\"extractUrlFromAXNode\", () => {\n it(\"returns trimmed URL string from node properties\", () => {\n const node = makeAxNode({\n properties: [\n { name: \"busy\", value: axString(\"bar\") },\n { name: \"url\", value: axString(\" https://example.com \") },\n ],\n });\n expect(extractUrlFromAXNode(node)).toBe(\"https://example.com\");\n });\n\n it(\"returns undefined when url property missing or invalid\", () => {\n expect(\n extractUrlFromAXNode(makeAxNode({ properties: [] })),\n ).toBeUndefined();\n expect(\n extractUrlFromAXNode(\n makeAxNode({\n properties: [{ name: \"url\", value: { type: \"number\", value: 123 } }],\n }),\n ),\n ).toBeUndefined();\n });\n});\n"]}
|
|
1
|
+
{"version":3,"file":"snapshot-a11y-tree-utils.test.js","sourceRoot":"","sources":["../../../../tests/unit/snapshot-a11y-tree-utils.test.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Protocol } from \"devtools-protocol\";\nimport { describe, expect, it } from \"vitest\";\nimport type {\n A11yNode,\n A11yOptions,\n} from \"../../lib/v3/types/private/snapshot.js\";\nimport {\n buildHierarchicalTree,\n decorateRoles,\n extractUrlFromAXNode,\n isStructural,\n removeRedundantStaticTextChildren,\n} from \"../../lib/v3/understudy/a11y/snapshot/a11yTree.js\";\n\nconst axString = (value: string): Protocol.Accessibility.AXValue => ({\n type: \"string\",\n value,\n});\n\nconst axBool = (value: boolean): Protocol.Accessibility.AXValue => ({\n type: \"boolean\",\n value,\n});\n\nconst defaultOpts: A11yOptions = {\n focusSelector: undefined,\n experimental: false,\n tagNameMap: {},\n scrollableMap: {},\n encode: (backendNodeId: number) => `enc-${backendNodeId}`,\n};\n\nconst makeAxNode = (\n overrides: Partial<Protocol.Accessibility.AXNode> = {},\n): Protocol.Accessibility.AXNode => ({\n nodeId: overrides.nodeId ?? String(Math.random()),\n backendDOMNodeId:\n overrides.backendDOMNodeId ?? Math.floor(Math.random() * 1e6),\n role: overrides.role ?? axString(\"generic\"),\n childIds: overrides.childIds ?? [],\n parentId: overrides.parentId,\n properties: overrides.properties ?? [],\n name: overrides.name,\n description: overrides.description,\n value: overrides.value,\n ignored: overrides.ignored ?? false,\n});\n\ndescribe(\"decorateRoles\", () => {\n it(\"marks scrollable DOM nodes with tag labels and encoded ids\", () => {\n const opts: A11yOptions = {\n ...defaultOpts,\n tagNameMap: {\n \"enc-1\": \"div\",\n \"enc-2\": \"html\",\n \"enc-3\": \"#document\",\n \"enc-4\": \"#svg\",\n },\n scrollableMap: { \"enc-1\": true, \"enc-4\": true },\n };\n const nodes = [\n makeAxNode({\n backendDOMNodeId: 1,\n role: { type: \"string\", value: \"region\" },\n }),\n makeAxNode({\n backendDOMNodeId: 2,\n role: { type: \"string\", value: \"generic\" },\n }),\n makeAxNode({\n backendDOMNodeId: 3,\n role: { type: \"string\", value: \"generic\" },\n }),\n makeAxNode({\n backendDOMNodeId: 4,\n role: { type: \"string\", value: \"generic\" },\n }),\n ];\n\n const decorated = decorateRoles(nodes, opts);\n expect(decorated).toMatchObject([\n { encodedId: \"enc-1\", role: \"scrollable, div\" },\n { encodedId: \"enc-2\", role: \"scrollable, html\" },\n { encodedId: \"enc-3\", role: \"generic\" },\n { encodedId: \"enc-4\", role: \"scrollable, svg\" },\n ]);\n });\n\n it(\"overrides role to 'input, file' for file inputs\", () => {\n const opts: A11yOptions = {\n ...defaultOpts,\n tagNameMap: { \"enc-10\": \"input, file\" },\n scrollableMap: {},\n };\n const nodes = [\n makeAxNode({\n backendDOMNodeId: 10,\n role: axString(\"button\"),\n name: axString(\"Choose File\"),\n }),\n ];\n\n const decorated = decorateRoles(nodes, opts);\n expect(decorated[0]).toMatchObject({\n encodedId: \"enc-10\",\n role: \"input, file\",\n name: \"Choose File\",\n });\n });\n\n it(\"falls back when encoding fails\", () => {\n const opts: A11yOptions = {\n ...defaultOpts,\n encode: () => {\n throw new Error(\"boom\");\n },\n };\n const nodes = [makeAxNode({ backendDOMNodeId: 4 })];\n const decorated = decorateRoles(nodes, opts);\n expect(decorated[0]?.encodedId).toBeUndefined();\n });\n\n it(\"maps selected/checked AX properties into boolean fields\", () => {\n const nodes = [\n makeAxNode({\n backendDOMNodeId: 12,\n role: axString(\"option\"),\n name: axString(\"Option B\"),\n properties: [{ name: \"selected\", value: axBool(true) }],\n }),\n makeAxNode({\n backendDOMNodeId: 13,\n role: axString(\"radio\"),\n name: axString(\"Option C\"),\n properties: [{ name: \"checked\", value: axBool(true) }],\n }),\n makeAxNode({\n backendDOMNodeId: 14,\n role: axString(\"radio\"),\n name: axString(\"Option D\"),\n properties: [\n { name: \"selected\", value: axBool(true) },\n { name: \"checked\", value: axBool(true) },\n ],\n }),\n ];\n\n const decorated = decorateRoles(nodes, defaultOpts);\n expect(decorated[0]).toMatchObject({ selected: true, checked: undefined });\n expect(decorated[1]).toMatchObject({ selected: undefined, checked: true });\n expect(decorated[2]).toMatchObject({ selected: true, checked: true });\n });\n});\n\ndescribe(\"buildHierarchicalTree\", () => {\n const opts: A11yOptions = {\n ...defaultOpts,\n tagNameMap: { root: \"div\", child: \"span\" },\n };\n\n it(\"drops structural nodes without children or names\", async () => {\n const nodes: A11yNode[] = [\n {\n role: \"generic\",\n name: \"\",\n nodeId: \"root\",\n encodedId: \"root\",\n parentId: undefined,\n childIds: [\"child\"],\n },\n {\n role: \"generic\",\n name: \"\",\n nodeId: \"child\",\n encodedId: \"child\",\n parentId: \"root\",\n childIds: [],\n },\n ];\n\n const { tree } = await buildHierarchicalTree(nodes, opts);\n expect(tree).toEqual([]);\n });\n\n it(\"promotes select/combobox tag names for structural nodes\", async () => {\n const nodes: A11yNode[] = [\n {\n role: \"combobox\",\n name: \"Select\",\n nodeId: \"root\",\n encodedId: \"root\",\n parentId: undefined,\n childIds: [\"child\"],\n },\n {\n role: \"StaticText\",\n name: \"Option\",\n nodeId: \"child\",\n encodedId: \"child\",\n parentId: \"root\",\n childIds: [],\n },\n ];\n\n const { tree } = await buildHierarchicalTree(nodes, {\n ...opts,\n tagNameMap: { root: \"select\" },\n });\n expect(tree[0]?.role).toBe(\"select\");\n });\n\n it(\"drops structural parents with a single cleaned child while keeping it in place\", async () => {\n const nodes: A11yNode[] = [\n {\n role: \"generic\",\n name: \"\",\n nodeId: \"root\",\n encodedId: \"root\",\n parentId: undefined,\n childIds: [\"child\"],\n },\n {\n role: \"StaticText\",\n name: \"Ok\",\n nodeId: \"child\",\n encodedId: \"child\",\n parentId: \"root\",\n childIds: [],\n },\n ];\n\n const { tree } = await buildHierarchicalTree(nodes, opts);\n expect(tree[0]?.role).toBe(\"StaticText\");\n });\n\n it(\"drops structural parents entirely when all descendants are pruned\", async () => {\n const nodes: A11yNode[] = [\n {\n role: \"generic\",\n name: \"\",\n nodeId: \"root\",\n encodedId: \"root\",\n parentId: undefined,\n childIds: [\"child\"],\n },\n {\n role: \"generic\",\n name: \"\",\n nodeId: \"child\",\n encodedId: \"child\",\n parentId: \"root\",\n childIds: [],\n },\n ];\n\n const { tree } = await buildHierarchicalTree(nodes, opts);\n expect(tree).toEqual([]);\n });\n\n it(\"renames structural nodes to their tag names when not combobox\", async () => {\n const nodes: A11yNode[] = [\n {\n role: \"generic\",\n name: \"Container\",\n nodeId: \"root\",\n encodedId: \"root\",\n parentId: undefined,\n childIds: [\"child-a\", \"child-b\"],\n },\n {\n role: \"StaticText\",\n name: \"A\",\n nodeId: \"child-a\",\n encodedId: \"child-a\",\n parentId: \"root\",\n childIds: [],\n },\n {\n role: \"StaticText\",\n name: \"B\",\n nodeId: \"child-b\",\n encodedId: \"child-b\",\n parentId: \"root\",\n childIds: [],\n },\n ];\n\n const { tree } = await buildHierarchicalTree(nodes, {\n ...opts,\n tagNameMap: { root: \"section\" },\n });\n expect(tree[0]?.role).toBe(\"section\");\n });\n\n it(\"skips nodes with negative node ids early\", async () => {\n const nodes: A11yNode[] = [\n {\n role: \"button\",\n name: \"Hidden\",\n nodeId: \"-1\",\n encodedId: \"hidden\",\n parentId: undefined,\n childIds: [],\n },\n ];\n\n const { tree } = await buildHierarchicalTree(nodes, opts);\n expect(tree).toEqual([]);\n });\n});\n\ndescribe(\"isStructural\", () => {\n it(\"marks generic/none/InlineTextBox roles as structural\", () => {\n expect(isStructural(\"generic\")).toBe(true);\n expect(isStructural(\"none\")).toBe(true);\n expect(isStructural(\"InlineTextBox\")).toBe(true);\n expect(isStructural(\"button\")).toBe(false);\n });\n});\n\ndescribe(\"removeRedundantStaticTextChildren\", () => {\n it(\"removes static text children whose concatenated text equals the parent name\", () => {\n const parent: A11yNode = {\n role: \"button\",\n name: \"HelloWorld\",\n nodeId: \"root\",\n };\n const children: A11yNode[] = [\n { role: \"StaticText\", name: \"Hello\", nodeId: \"c1\" },\n { role: \"StaticText\", name: \"World\", nodeId: \"c2\" },\n { role: \"button\", name: \"Child\", nodeId: \"c3\" },\n ];\n const pruned = removeRedundantStaticTextChildren(parent, children);\n expect(pruned).toEqual([{ role: \"button\", name: \"Child\", nodeId: \"c3\" }]);\n });\n\n it(\"keeps static text when combined text differs\", () => {\n const parent: A11yNode = {\n role: \"button\",\n name: \"Hello World\",\n nodeId: \"root\",\n };\n const children: A11yNode[] = [\n { role: \"StaticText\", name: \"Hello\", nodeId: \"c1\" },\n { role: \"StaticText\", name: \"Mars\", nodeId: \"c2\" },\n ];\n expect(removeRedundantStaticTextChildren(parent, children)).toEqual(\n children,\n );\n });\n it(\"returns original children when parent name is empty\", () => {\n const parent: A11yNode = {\n role: \"button\",\n nodeId: \"root\",\n };\n const children: A11yNode[] = [\n { role: \"StaticText\", name: \"Hello\", nodeId: \"c1\" },\n { role: \"StaticText\", name: \"World\", nodeId: \"c2\" },\n ];\n expect(removeRedundantStaticTextChildren(parent, children)).toEqual(\n children,\n );\n });\n});\n\ndescribe(\"extractUrlFromAXNode\", () => {\n it(\"returns trimmed URL string from node properties\", () => {\n const node = makeAxNode({\n properties: [\n { name: \"busy\", value: axString(\"bar\") },\n { name: \"url\", value: axString(\" https://example.com \") },\n ],\n });\n expect(extractUrlFromAXNode(node)).toBe(\"https://example.com\");\n });\n\n it(\"returns undefined when url property missing or invalid\", () => {\n expect(\n extractUrlFromAXNode(makeAxNode({ properties: [] })),\n ).toBeUndefined();\n expect(\n extractUrlFromAXNode(\n makeAxNode({\n properties: [{ name: \"url\", value: { type: \"number\", value: 123 } }],\n }),\n ),\n ).toBeUndefined();\n });\n});\n"]}
|
|
@@ -17,6 +17,49 @@ describe("formatTreeLine", () => {
|
|
|
17
17
|
});
|
|
18
18
|
expect(outline).toBe("[frame-1] section: Container\n [ax-2] button: Submit");
|
|
19
19
|
});
|
|
20
|
+
it("renders a select with child options and only one selected option", () => {
|
|
21
|
+
const outline = formatTreeLine({
|
|
22
|
+
role: "select",
|
|
23
|
+
name: "Select field",
|
|
24
|
+
nodeId: "ax-4",
|
|
25
|
+
children: [
|
|
26
|
+
{ role: "option", name: "Option A", nodeId: "ax-5" },
|
|
27
|
+
{
|
|
28
|
+
role: "option",
|
|
29
|
+
name: "Option B",
|
|
30
|
+
selected: true,
|
|
31
|
+
nodeId: "ax-6",
|
|
32
|
+
},
|
|
33
|
+
{ role: "option", name: "Option C", nodeId: "ax-7" },
|
|
34
|
+
],
|
|
35
|
+
});
|
|
36
|
+
expect(outline).toBe("[ax-4] select: Select field\n [ax-5] option: Option A\n [ax-6] option: Option B [selected]\n [ax-7] option: Option C");
|
|
37
|
+
expect(outline.match(/\[selected]/g)?.length ?? 0).toBe(1);
|
|
38
|
+
});
|
|
39
|
+
it("renders a radio group with children and only one checked radio", () => {
|
|
40
|
+
const outline = formatTreeLine({
|
|
41
|
+
role: "group",
|
|
42
|
+
name: "Select field",
|
|
43
|
+
nodeId: "ax-8",
|
|
44
|
+
children: [
|
|
45
|
+
{ role: "radio", name: "Option A", nodeId: "ax-9" },
|
|
46
|
+
{ role: "radio", name: "Option B", checked: true, nodeId: "ax-10" },
|
|
47
|
+
{ role: "radio", name: "Option C", nodeId: "ax-11" },
|
|
48
|
+
],
|
|
49
|
+
});
|
|
50
|
+
expect(outline).toBe("[ax-8] group: Select field\n [ax-9] radio: Option A\n [ax-10] radio: Option B [checked]\n [ax-11] radio: Option C");
|
|
51
|
+
expect(outline.match(/\[checked]/g)?.length ?? 0).toBe(1);
|
|
52
|
+
});
|
|
53
|
+
it("renders both flags when a node carries both states", () => {
|
|
54
|
+
const outline = formatTreeLine({
|
|
55
|
+
role: "menuitemcheckbox",
|
|
56
|
+
name: "Hybrid state",
|
|
57
|
+
selected: true,
|
|
58
|
+
checked: true,
|
|
59
|
+
nodeId: "ax-12",
|
|
60
|
+
});
|
|
61
|
+
expect(outline).toBe("[ax-12] menuitemcheckbox: Hybrid state [selected] [checked]");
|
|
62
|
+
});
|
|
20
63
|
});
|
|
21
64
|
describe("injectSubtrees", () => {
|
|
22
65
|
it("nests child outlines under iframe encoded ids", () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"snapshot-tree-format-utils.test.js","sourceRoot":"","sources":["../../../../tests/unit/snapshot-tree-format-utils.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, expect, it } from \"vitest\";\nimport {\n cleanText,\n diffCombinedTrees,\n formatTreeLine,\n indentBlock,\n injectSubtrees,\n normaliseSpaces,\n} from \"../../lib/v3/understudy/a11y/snapshot/treeFormatUtils.js\";\n\ndescribe(\"formatTreeLine\", () => {\n it(\"includes encoded ids and indents children\", () => {\n const outline = formatTreeLine({\n role: \"section\",\n name: \"Container\",\n encodedId: \"frame-1\",\n nodeId: \"ax-1\",\n children: [\n {\n role: \"button\",\n name: \"Submit\",\n nodeId: \"ax-2\",\n },\n ],\n });\n\n expect(outline).toBe(\n \"[frame-1] section: Container\\n [ax-2] button: Submit\",\n );\n });\n});\n\ndescribe(\"injectSubtrees\", () => {\n it(\"nests child outlines under iframe encoded ids\", () => {\n const rootOutline = `[root] document\\n [iframe-1] iframe\\n [leaf] item`;\n const iframeOutline = `[child-root] child\\n [nested-frame] iframe`;\n const nestedOutline = `[nested-leaf] nested`;\n\n const merged = injectSubtrees(\n rootOutline,\n new Map([\n [\"iframe-1\", iframeOutline],\n [\"nested-frame\", nestedOutline],\n ]),\n );\n\n expect(merged).toBe(\n `[root] document\n [iframe-1] iframe\n [child-root] child\n [nested-frame] iframe\n [nested-leaf] nested\n [leaf] item`,\n );\n });\n\n it(\"injects child outline only once when the same id repeats\", () => {\n const rootOutline = `[root] document\n [iframe-1] iframe\n [iframe-1] iframe`;\n const iframeOutline = `[child-root] child`;\n\n const merged = injectSubtrees(\n rootOutline,\n new Map([[\"iframe-1\", iframeOutline]]),\n );\n\n expect(merged).toBe(\n `[root] document\n [iframe-1] iframe\n [child-root] child\n [iframe-1] iframe`,\n );\n });\n\n it(\"returns the original outline when no encoded ids are matched\", () => {\n const outline = `[root] document\\n [leaf] item`;\n expect(injectSubtrees(outline, new Map([[\"other\", \"[x] child\"]]))).toBe(\n outline,\n );\n });\n});\n\ndescribe(\"indentBlock\", () => {\n it(\"prefixes each line with the provided indent\", () => {\n expect(indentBlock(\"a\\nb\", \" \")).toBe(\" a\\n b\");\n expect(indentBlock(\"\", \" \")).toBe(\"\");\n });\n});\n\ndescribe(\"diffCombinedTrees\", () => {\n it(\"returns newly-added lines relative to previous outline\", () => {\n const prev = `[root] document\\n [child] a`;\n const next = `[root] document\\n [child] a\\n [child-2] b`;\n expect(diffCombinedTrees(prev, next)).toBe(\"[child-2] b\");\n });\n\n it(\"normalizes indentation for added lines with stray spaces\", () => {\n const prev = `[root] document\\n [child] a`;\n const next = `[root] document\\n [child] a\\n [child-2] b`;\n expect(diffCombinedTrees(prev, next)).toBe(\"[child-2] b\");\n });\n});\n\ndescribe(\"cleanText\", () => {\n it(\"removes NBSP and private-use characters while collapsing spaces\", () => {\n const dirty = `Hello\\u00A0\\u00A0world\\uE000 !`;\n expect(cleanText(dirty)).toBe(\"Hello world !\");\n });\n});\n\ndescribe(\"normaliseSpaces\", () => {\n it(\"replaces whitespace runs with a single space\", () => {\n expect(normaliseSpaces(\"a b\\tc\\nd\")).toBe(\"a b c d\");\n });\n});\n"]}
|
|
1
|
+
{"version":3,"file":"snapshot-tree-format-utils.test.js","sourceRoot":"","sources":["../../../../tests/unit/snapshot-tree-format-utils.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, expect, it } from \"vitest\";\nimport {\n cleanText,\n diffCombinedTrees,\n formatTreeLine,\n indentBlock,\n injectSubtrees,\n normaliseSpaces,\n} from \"../../lib/v3/understudy/a11y/snapshot/treeFormatUtils.js\";\n\ndescribe(\"formatTreeLine\", () => {\n it(\"includes encoded ids and indents children\", () => {\n const outline = formatTreeLine({\n role: \"section\",\n name: \"Container\",\n encodedId: \"frame-1\",\n nodeId: \"ax-1\",\n children: [\n {\n role: \"button\",\n name: \"Submit\",\n nodeId: \"ax-2\",\n },\n ],\n });\n\n expect(outline).toBe(\n \"[frame-1] section: Container\\n [ax-2] button: Submit\",\n );\n });\n\n it(\"renders a select with child options and only one selected option\", () => {\n const outline = formatTreeLine({\n role: \"select\",\n name: \"Select field\",\n nodeId: \"ax-4\",\n children: [\n { role: \"option\", name: \"Option A\", nodeId: \"ax-5\" },\n {\n role: \"option\",\n name: \"Option B\",\n selected: true,\n nodeId: \"ax-6\",\n },\n { role: \"option\", name: \"Option C\", nodeId: \"ax-7\" },\n ],\n });\n\n expect(outline).toBe(\n \"[ax-4] select: Select field\\n [ax-5] option: Option A\\n [ax-6] option: Option B [selected]\\n [ax-7] option: Option C\",\n );\n expect(outline.match(/\\[selected]/g)?.length ?? 0).toBe(1);\n });\n\n it(\"renders a radio group with children and only one checked radio\", () => {\n const outline = formatTreeLine({\n role: \"group\",\n name: \"Select field\",\n nodeId: \"ax-8\",\n children: [\n { role: \"radio\", name: \"Option A\", nodeId: \"ax-9\" },\n { role: \"radio\", name: \"Option B\", checked: true, nodeId: \"ax-10\" },\n { role: \"radio\", name: \"Option C\", nodeId: \"ax-11\" },\n ],\n });\n\n expect(outline).toBe(\n \"[ax-8] group: Select field\\n [ax-9] radio: Option A\\n [ax-10] radio: Option B [checked]\\n [ax-11] radio: Option C\",\n );\n expect(outline.match(/\\[checked]/g)?.length ?? 0).toBe(1);\n });\n\n it(\"renders both flags when a node carries both states\", () => {\n const outline = formatTreeLine({\n role: \"menuitemcheckbox\",\n name: \"Hybrid state\",\n selected: true,\n checked: true,\n nodeId: \"ax-12\",\n });\n\n expect(outline).toBe(\n \"[ax-12] menuitemcheckbox: Hybrid state [selected] [checked]\",\n );\n });\n});\n\ndescribe(\"injectSubtrees\", () => {\n it(\"nests child outlines under iframe encoded ids\", () => {\n const rootOutline = `[root] document\\n [iframe-1] iframe\\n [leaf] item`;\n const iframeOutline = `[child-root] child\\n [nested-frame] iframe`;\n const nestedOutline = `[nested-leaf] nested`;\n\n const merged = injectSubtrees(\n rootOutline,\n new Map([\n [\"iframe-1\", iframeOutline],\n [\"nested-frame\", nestedOutline],\n ]),\n );\n\n expect(merged).toBe(\n `[root] document\n [iframe-1] iframe\n [child-root] child\n [nested-frame] iframe\n [nested-leaf] nested\n [leaf] item`,\n );\n });\n\n it(\"injects child outline only once when the same id repeats\", () => {\n const rootOutline = `[root] document\n [iframe-1] iframe\n [iframe-1] iframe`;\n const iframeOutline = `[child-root] child`;\n\n const merged = injectSubtrees(\n rootOutline,\n new Map([[\"iframe-1\", iframeOutline]]),\n );\n\n expect(merged).toBe(\n `[root] document\n [iframe-1] iframe\n [child-root] child\n [iframe-1] iframe`,\n );\n });\n\n it(\"returns the original outline when no encoded ids are matched\", () => {\n const outline = `[root] document\\n [leaf] item`;\n expect(injectSubtrees(outline, new Map([[\"other\", \"[x] child\"]]))).toBe(\n outline,\n );\n });\n});\n\ndescribe(\"indentBlock\", () => {\n it(\"prefixes each line with the provided indent\", () => {\n expect(indentBlock(\"a\\nb\", \" \")).toBe(\" a\\n b\");\n expect(indentBlock(\"\", \" \")).toBe(\"\");\n });\n});\n\ndescribe(\"diffCombinedTrees\", () => {\n it(\"returns newly-added lines relative to previous outline\", () => {\n const prev = `[root] document\\n [child] a`;\n const next = `[root] document\\n [child] a\\n [child-2] b`;\n expect(diffCombinedTrees(prev, next)).toBe(\"[child-2] b\");\n });\n\n it(\"normalizes indentation for added lines with stray spaces\", () => {\n const prev = `[root] document\\n [child] a`;\n const next = `[root] document\\n [child] a\\n [child-2] b`;\n expect(diffCombinedTrees(prev, next)).toBe(\"[child-2] b\");\n });\n});\n\ndescribe(\"cleanText\", () => {\n it(\"removes NBSP and private-use characters while collapsing spaces\", () => {\n const dirty = `Hello\\u00A0\\u00A0world\\uE000 !`;\n expect(cleanText(dirty)).toBe(\"Hello world !\");\n });\n});\n\ndescribe(\"normaliseSpaces\", () => {\n it(\"replaces whitespace runs with a single space\", () => {\n expect(normaliseSpaces(\"a b\\tc\\nd\")).toBe(\"a b c d\");\n });\n});\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@browserbasehq/orca",
|
|
3
|
-
"version": "3.4.0-preview-
|
|
3
|
+
"version": "3.4.0-preview-4",
|
|
4
4
|
"description": "An AI web browsing framework focused on simplicity and extensibility.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/cjs/index.js",
|
|
@@ -81,15 +81,15 @@
|
|
|
81
81
|
"@anthropic-ai/sdk": "0.39.0",
|
|
82
82
|
"@browserbasehq/sdk": "^2.10.0",
|
|
83
83
|
"@google/genai": "^1.22.0",
|
|
84
|
-
"@langchain/openai": "^
|
|
85
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
84
|
+
"@langchain/openai": "^1.4.5",
|
|
85
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
86
86
|
"ai": "^5.0.133",
|
|
87
87
|
"devtools-protocol": "^0.0.1464554",
|
|
88
88
|
"fetch-cookie": "^3.1.0",
|
|
89
89
|
"openai": "^4.104.0",
|
|
90
90
|
"pino": "^9.6.0",
|
|
91
91
|
"pino-pretty": "^13.0.0",
|
|
92
|
-
"uuid": "^11.1.
|
|
92
|
+
"uuid": "^11.1.1",
|
|
93
93
|
"ws": "^8.18.0",
|
|
94
94
|
"zod-to-json-schema": "^3.25.0"
|
|
95
95
|
},
|
|
@@ -107,7 +107,7 @@
|
|
|
107
107
|
"@ai-sdk/perplexity": "^2.0.13",
|
|
108
108
|
"@ai-sdk/togetherai": "^1.0.23",
|
|
109
109
|
"@ai-sdk/xai": "^2.0.26",
|
|
110
|
-
"@langchain/core": "^
|
|
110
|
+
"@langchain/core": "^1.1.46",
|
|
111
111
|
"bufferutil": "^4.0.9",
|
|
112
112
|
"chrome-launcher": "^1.2.0",
|
|
113
113
|
"ollama-ai-provider-v2": "^1.5.0"
|
|
@@ -129,7 +129,8 @@
|
|
|
129
129
|
"prettier": "^3.2.5",
|
|
130
130
|
"puppeteer-core": "^24.43.0",
|
|
131
131
|
"tsx": "*",
|
|
132
|
-
"
|
|
132
|
+
"vite": "^7.3.3",
|
|
133
|
+
"vitest": "^4.1.6",
|
|
133
134
|
"zod": "^3.25.76 || ^4.2.0"
|
|
134
135
|
},
|
|
135
136
|
"repository": {
|