Jev Ultrafast — a browser agent whose action space is rebuilt every step
A browser agent from the Browser Use team. Every observation produces a fresh element table, and Jev picks an operation and a target over that table — not over a fixed schema written in advance.
The operations are CLICK, TYPE_TEXT, SELECT, SCROLL_UP, SCROLL_DOWN, WAIT, DONE and BLOCKED, and only the ones the current page actually supports are offered. That is the design idea: the Choice's option set is rebuilt per step from what is on screen, so the model is never asked to pick something it cannot do.
The targets are asked speculatively, in the same request. click_target, type_text_target and select_target are each answered against only the elements compatible with that operation, and once the operation Choice lands, the matching target is the one that executes and the rest are discarded. Two decisions, one network round trip — which is where the name comes from.
Jev does not write text. When the operation is TYPE_TEXT a small LLM produces the string, and it is told the page is untrusted data. Judgment and generation stay separate jobs.
Zürich to London on Google Flights in 7.1 seconds, including generation and loading waits, with no site-specific scripts or prepared field strings in the policy.
Source (13 files)
{
"elapsed_ms": 7073,
"decision_requests": 17,
"decision_median_ms": 178,
"decision_total_ms": 3720,
"browser_actions": 11,
"wait_actions": 1,
"models": {
"decision": [
"jev-1.13.0"
],
"text": [
"inception/mercury-2.5"
]
},
"text_calls": [
{
"model": "inception/mercury-2.5",
"latency_ms": 581,
"usage": {
"prompt_tokens": 440,
"completion_tokens": 78,
"total_tokens": 518,
"cost": 2.93e-05,
"is_byok": false,
"prompt_tokens_details": {
"cached_tokens": 0,
"cache_write_tokens": 0,
"audio_tokens": 0,
"video_tokens": 0
},
"cost_details": {
"upstream_inference_cost": 2.93e-05,
"upstream_inference_prompt_cost": 1.76e-05,
"upstream_inference_completions_cost": 1.17e-05
},
"completion_tokens_details": {
"reasoning_tokens": 0,
"image_tokens": 0,
"audio_tokens": 0
}
},
"field": "Where from?",
"value": "Zurich"
},
{
"model": "inception/mercury-2.5",
"latency_ms": 346,
"usage": {
"prompt_tokens": 483,
"completion_tokens": 94,
"total_tokens": 577,
"cost": 3.342e-05,
"is_byok": false,
"prompt_tokens_details": {
"cached_tokens": 0,
"cache_write_tokens": 0,
"audio_tokens": 0,
"video_tokens": 0
},
"cost_details": {
"upstream_inference_cost": 3.342e-05,
"upstream_inference_prompt_cost": 1.932e-05,
"upstream_inference_completions_cost": 1.41e-05
},
"completion_tokens_details": {
"reasoning_tokens": 0,
"image_tokens": 0,
"audio_tokens": 0
}
},
"field": "Where to? ",
"value": "London"
}
],
"verification": {
"passed": true,
"checks": {
"search_page": true,
"one_way": true,
"origin": true,
"destination": true,
"date": true,
"year": true,
"results": true
},
"visible_flights": [
"From 216 US dollars.This price does not include overhead bin access. Nonstop flight with easyJet. Leaves Zurich Airport at 4:45 PM on Sunday, September 20 and arrives at London Gatwick Airport at 5:35 PM on Sunday, September 20. Total duration 1 hr 50 min. Select flight",
"From 265 US dollars. Nonstop flight with British Airways. Operated by BA Cityflyer. Leaves Zurich Airport at 8:25 PM on Sunday, September 20 and arrives at London City Airport at 9:00 PM on Sunday, September 20. Total duration 1 hr 35 min. Select flight",
"From 271 US dollars. Nonstop flight with British Airways. Leaves Zurich Airport at 1:20 PM on Sunday, September 20 and arrives at Heathrow Airport at 2:20 PM on Sunday, September 20. Total duration 2 hr. Select flight"
]
},
"source_hashes": {
"questions.py": "66a7054b85040b949e1757311257ea0c5a843c635f9a40c99f6d15ad660fb422",
"__init__.py": "60f025b8d24465e2c0f7a3547d43b8020fd8843de7b6cb3f892ef63f5548cf63",
"model.py": "a85ada8458d23642c5c8a4095acf0565e6268f81dcda26f6308942b653e9c9f3",
"browser.py": "6ef6c0cf9041f648c49bb09adf6b83d73ba301de5e87ffdeb03b0a4ce9e487ab",
"snapshot.js": "e50473501c8fb8e70f3b21866d987393e3f2315c639d638bd477d170e81ed78d",
"agent.py": "aaf8b271cb0ee6643fe7beb525328ab80de8568c7ac044d02b9c6721161e7c8b",
"demo.py": "a0cfb10909b370efb284cbbe16bdb4b7e7e06ba6385827404169027645a1d8a4"
},
"tokens": {
"input_tokens": 90558,
"output_tokens": 6325
},
"task": "Find one-way flights from Zurich to London on September 20, 2026, for one adult in economy. Stop when matching flight options are visible. Do not select or book a flight.",
"timing": "First prediction after initial homepage observation through final DONE; setup and independent final verification excluded.",
"video": {
"source_frames": 187,
"speed": 1,
"intro_hold_ms": 0,
"end_hold_ms": 500,
"crop": "Top 64 px account/navigation strip removed from every frame."
},
"actions": [
{
"operation": "CLICK",
"target": "12",
"action": "Change ticket type. Round trip",
"kind": "click",
"text": null,
"executed_ms": 336,
"elapsed_ms": 372,
"latency_ms": 299,
"text_latency_ms": 0
},
{
"operation": "CLICK",
"target": "14",
"action": "One way",
"kind": "click",
"text": null,
"executed_ms": 640,
"elapsed_ms": 725,
"latency_ms": 217,
"text_latency_ms": 0
},
{
"operation": "TYPE_TEXT",
"target": "15",
"action": "Where from?",
"kind": "fill",
"text": "Zurich",
"executed_ms": 1595,
"elapsed_ms": 1770,
"latency_ms": 126,
"text_latency_ms": 581
},
{
"operation": "CLICK",
"target": "3",
"action": "Z\u00fcrich, Switzerland",
"kind": "click",
"text": null,
"executed_ms": 1930,
"elapsed_ms": 1959,
"latency_ms": 121,
"text_latency_ms": 0
},
{
"operation": "TYPE_TEXT",
"target": "16",
"action": "Where to? ",
"kind": "fill",
"text": "London",
"executed_ms": 2748,
"elapsed_ms": 2875,
"latency_ms": 120,
"text_latency_ms": 346
},
{
"operation": "CLICK",
"target": "3",
"action": "London, United Kingdom",
"kind": "click",
"text": null,
"executed_ms": 3053,
"elapsed_ms": 3085,
"latency_ms": 143,
"text_latency_ms": 0
},
{
"operation": "CLICK",
"target": "18",
"action": "Open Departure",
"kind": "click",
"text": null,
"executed_ms": 3452,
"elapsed_ms": 3520,
"latency_ms": 112,
"text_latency_ms": 0
},
{
"operation": "CLICK",
"target": "7",
"action": "Sunday, September 20, 2026",
"kind": "click",
"text": null,
"executed_ms": 3769,
"elapsed_ms": 3810,
"latency_ms": 203,
"text_latency_ms": 0
},
{
"operation": "CLICK",
"target": "56",
"action": "Done. Search for one-way flights, departing on September 20, 2026",
"kind": "click",
"text": null,
"executed_ms": 4097,
"elapsed_ms": 4136,
"latency_ms": 247,
"text_latency_ms": 0
},
{
"operation": "CLICK",
"target": "19",
"action": "Search",
"kind": "click",
"text": null,
"executed_ms": 5217,
"elapsed_ms": 5320,
"latency_ms": 178,
"text_latency_ms": 0
},
{
"operation": "WAIT",
"target": null,
"action": "Wait for the page to update",
"kind": "wait",
"text": null,
"executed_ms": 5587,
"elapsed_ms": 5594,
"latency_ms": 141,
"text_latency_ms": 0
}
]
}
{
"task": "Google Flights: Z\u00fcrich to London, one way, 20 September 2026, 1 adult, economy",
"initial_url": "https://www.google.com/travel/flights?hl=en",
"final_url": "https://www.google.com/travel/flights/search?tfs=CBwQAhooEgoyMDI2LTA5LTIwagwIAxIIL20vMDg5NjZyDAgDEggvbS8wNGpwbEABSAFwAYIBCwj___________8BmAEC&hl=en",
"elapsed_ms": 12884,
"timing": "First prediction after initial page observation through final DONE; includes decisions, actions, fresh observations, screenshots, loading waits, and discarded stale decisions. Excludes initial navigation and setup.",
"model": "jev-1.13.0",
"model_requests": 17,
"model_ms": 3050,
"model_median_ms": 179,
"model_min_ms": 132,
"model_max_ms": 264,
"browser_actions": 11,
"wait_actions": 1,
"text_model_calls": 0,
"text_values": "Copied Zurich and London from the explicit goal steps.",
"verification": {
"passed": true,
"checks": {
"search_page": true,
"one_way": true,
"origin": true,
"destination": true,
"date": true,
"year": true,
"results": true
},
"visible_flights": [
"From 216 US dollars.This price does not include overhead bin access. Nonstop flight with easyJet. Leaves Zurich Airport at 4:45 PM on Sunday, September 20 and arrives at London Gatwick Airport at 5:35 PM on Sunday, September 20. Total duration 1 hr 50 min. Select flight",
"From 265 US dollars. Nonstop flight with British Airways. Operated by BA Cityflyer. Leaves Zurich Airport at 8:25 PM on Sunday, September 20 and arrives at London City Airport at 9:00 PM on Sunday, September 20. Total duration 1 hr 35 min. Select flight",
"From 370 US dollars.This price does not include overhead bin access. Nonstop flight with SWISS. Leaves Zurich Airport at 5:10 PM on Sunday, September 20 and arrives at London Gatwick Airport at 5:50 PM on Sunday, September 20. Total duration 1 hr 40 min. Select flight"
]
},
"goals": [
"Set ticket type to One way.",
"Set the departure city to \"Zurich\" and select Z\u00fcrich Switzerland from the autocomplete suggestions.",
"Set the destination city to \"London\" and select London United Kingdom from the autocomplete suggestions.",
"Set departure to Sunday September 20, 2026. Confirm the date picker.",
"Search flights and wait until flight results are visible for Z\u00fcrich to London, one way, September 20, 2026."
],
"actions": [
{
"step": 1,
"kind": "click",
"action": "Change ticket type. Round trip",
"text": null,
"executed_ms": 423,
"elapsed_ms": 603,
"latency_ms": 241
},
{
"step": 2,
"kind": "click",
"action": "One way",
"text": null,
"executed_ms": 1261,
"elapsed_ms": 1644,
"latency_ms": 185
},
{
"step": 3,
"kind": "fill",
"action": "Where from?",
"text": "Zurich",
"executed_ms": 2338,
"elapsed_ms": 2670,
"latency_ms": 149
},
{
"step": 4,
"kind": "click",
"action": "Z\u00fcrich, Switzerland",
"text": null,
"executed_ms": 3027,
"elapsed_ms": 3387,
"latency_ms": 179
},
{
"step": 5,
"kind": "fill",
"action": "Where to? ",
"text": "London",
"executed_ms": 4527,
"elapsed_ms": 4695,
"latency_ms": 139
},
{
"step": 6,
"kind": "click",
"action": "London, United Kingdom",
"text": null,
"executed_ms": 5139,
"elapsed_ms": 5714,
"latency_ms": 184
},
{
"step": 7,
"kind": "click",
"action": "Open Departure",
"text": null,
"executed_ms": 6169,
"elapsed_ms": 6522,
"latency_ms": 180
},
{
"step": 8,
"kind": "click",
"action": "Sunday, September 20, 2026",
"text": null,
"executed_ms": 7053,
"elapsed_ms": 7349,
"latency_ms": 222
},
{
"step": 9,
"kind": "click",
"action": "Done. Search for one-way flights, departing on September 20, 2026",
"text": null,
"executed_ms": 9124,
"elapsed_ms": 9511,
"latency_ms": 227
},
{
"step": 10,
"kind": "click",
"action": "Search",
"text": null,
"executed_ms": 9861,
"elapsed_ms": 10234,
"latency_ms": 132
},
{
"step": 11,
"kind": "wait",
"action": "Wait for the page to update",
"text": null,
"executed_ms": 10677,
"elapsed_ms": 12030,
"latency_ms": 202
}
],
"video": {
"source_frames": 81,
"speed": 1,
"intro_hold_ms": 750,
"end_hold_ms": 2000,
"privacy": "The Google navigation/account strip is cropped out of every frame."
},
"development_attempts": [
{
"attempt": 1,
"elapsed_ms": 14118,
"verified": true,
"notes": "Initial per-node CDP extraction."
},
{
"attempt": 2,
"elapsed_ms": 14162,
"verified": true,
"notes": "Batched layout extraction."
},
{
"attempt": 3,
"elapsed_ms": 1585,
"verified": false,
"notes": "Relaxed mutation freshness; stopped during menu animation. Change reverted."
},
{
"attempt": 4,
"elapsed_ms": 12884,
"verified": true,
"notes": "Strict freshness restored; recorded screencast."
}
],
"scope": "Single public workflow with explicit ordered goals. Iterative development attempts, not a controlled benchmark. Existing Chrome profile and caches. Fares can change."
}
{
"task": "Find one-way flights from Zurich to London on September 20, 2026, for one adult in economy. Stop when matching flight options are visible. Do not select or book a flight.",
"baseline_commit": "68c077bf79caca4e817b8e8a5854b2efa0c81ff6",
"summary": {
"baseline": {
"runs": 3,
"passed": 3,
"median_ms": 9450,
"median_cdp_calls": 1092
},
"candidate": {
"runs": 3,
"passed": 3,
"median_ms": 7092,
"median_cdp_calls": 101
}
},
"runs": [
{
"elapsed_ms": 11214,
"decision_requests": 26,
"decision_median_ms": 195.5,
"decision_total_ms": 5913,
"browser_actions": 13,
"wait_actions": 3,
"models": {
"decision": [
"jev-1.13.0"
],
"text": [
"inception/mercury-2.5"
]
},
"text_calls": [
{
"model": "inception/mercury-2.5",
"latency_ms": 490,
"usage": {
"prompt_tokens": 447,
"completion_tokens": 51,
"total_tokens": 498,
"cost": 2.553e-05,
"is_byok": false,
"prompt_tokens_details": {
"cached_tokens": 0,
"cache_write_tokens": 0,
"audio_tokens": 0,
"video_tokens": 0
},
"cost_details": {
"upstream_inference_cost": 2.553e-05,
"upstream_inference_prompt_cost": 1.788e-05,
"upstream_inference_completions_cost": 7.65e-06
},
"completion_tokens_details": {
"reasoning_tokens": 0,
"image_tokens": 0,
"audio_tokens": 0
}
},
"field": "Where from?",
"value": "Zurich"
},
{
"model": "inception/mercury-2.5",
"latency_ms": 792,
"usage": {
"prompt_tokens": 482,
"completion_tokens": 60,
"total_tokens": 542,
"cost": 2.828e-05,
"is_byok": false,
"prompt_tokens_details": {
"cached_tokens": 0,
"cache_write_tokens": 0,
"audio_tokens": 0,
"video_tokens": 0
},
"cost_details": {
"upstream_inference_cost": 2.828e-05,
"upstream_inference_prompt_cost": 1.928e-05,
"upstream_inference_completions_cost": 9e-06
},
"completion_tokens_details": {
"reasoning_tokens": 0,
"image_tokens": 0,
"audio_tokens": 0
}
},
"field": "Where to? ",
"value": "London"
}
],
"verification": {
"passed": true,
"checks": {
"search_page": true,
"one_way": true,
"origin": true,
"destination": true,
"date": true,
"year": true,
"results": true
},
"visible_flights": [
"From 216 US dollars.This price does not include overhead bin access. Nonstop flight with easyJet. Leaves Zurich Airport at 4:45 PM on Sunday, September 20 and arrives at London Gatwick Airport at 5:35 PM on Sunday, September 20. Total duration 1 hr 50 min. Select flight",
"From 265 US dollars. Nonstop flight with British Airways. Operated by BA Cityflyer. Leaves Zurich Airport at 8:25 PM on Sunday, September 20 and arrives at London City Airport at 9:00 PM on Sunday, September 20. Total duration 1 hr 35 min. Select flight",
"From 271 US dollars. Nonstop flight with British Airways. Leaves Zurich Airport at 1:20 PM on Sunday, September 20 and arrives at Heathrow Airport at 2:20 PM on Sunday, September 20. Total duration 2 hr. Select flight"
]
},
"source_hashes": {
"questions.py": "66a7054b85040b949e1757311257ea0c5a843c635f9a40c99f6d15ad660fb422",
"__init__.py": "60f025b8d24465e2c0f7a3547d43b8020fd8843de7b6cb3f892ef63f5548cf63",
"model.py": "a85ada8458d23642c5c8a4095acf0565e6268f81dcda26f6308942b653e9c9f3",
"browser.py": "d2b0e468c2dac3f4d3cbba51f3619fe26fe44fb1554446363d8d1aff5efe22f2",
"agent.py": "be5434b79de0410352485e734ff4bb7a5d9556ce22ae47f231b5be3aa67161a4",
"demo.py": "a0cfb10909b370efb284cbbe16bdb4b7e7e06ba6385827404169027645a1d8a4"
},
"tokens": {
"input_tokens": 133633,
"output_tokens": 9468
},
"arm": "baseline",
"pair": 1,
"configuration": {
"TYPESAFE_MODEL": null,
"TEXT_MODEL": "inception/mercury-2.5",
"TEXT_MODEL_BASE_URL": "https://openrouter.ai/api/v1",
"TEXT_MODEL_REASONING": "none"
},
"browser_version": "Chrome/152.0.7977.83",
"task_hash": "bce327f45dc380ca9cd76fac5b70bfddd7ce36f8e083c1f900522af2a3499ff9",
"cdp": {
"Runtime.evaluate": {
"count": 158,
"ms": 1487.242
},
"Accessibility.getFullAXTree": {
"count": 30,
"ms": 1238.199
},
"Runtime.callFunctionOn": {
"count": 40,
"ms": 223.157
},
"DOM.resolveNode": {
"count": 828,
"ms": 1215.957
},
"DOM.getBoxModel": {
"count": 10,
"ms": 8.559
},
"DOM.getNodeForLocation": {
"count": 10,
"ms": 10.932
},
"Input.dispatchMouseEvent": {
"count": 20,
"ms": 351.816
},
"Input.dispatchKeyEvent": {
"count": 4,
"ms": 35.583
},
"Input.insertText": {
"count": 2,
"ms": 11.208
}
},
"error": null,
"browser_closed": true
},
{
"elapsed_ms": 6964,
"decision_requests": 17,
"decision_median_ms": 169,
"decision_total_ms": 3284,
"browser_actions": 13,
"wait_actions": 3,
"models": {
"decision": [
"jev-1.13.0"
],
"text": [
"inception/mercury-2.5"
]
},
"text_calls": [
{
"model": "inception/mercury-2.5",
"latency_ms": 448,
"usage": {
"prompt_tokens": 456,
"completion_tokens": 59,
"total_tokens": 515,
"cost": 2.709e-05,
"is_byok": false,
"prompt_tokens_details": {
"cached_tokens": 0,
"cache_write_tokens": 0,
"audio_tokens": 0,
"video_tokens": 0
},
"cost_details": {
"upstream_inference_cost": 2.709e-05,
"upstream_inference_prompt_cost": 1.824e-05,
"upstream_inference_completions_cost": 8.85e-06
},
"completion_tokens_details": {
"reasoning_tokens": 0,
"image_tokens": 0,
"audio_tokens": 0
}
},
"field": "Where from?",
"value": "Zurich"
},
{
"model": "inception/mercury-2.5",
"latency_ms": 310,
"usage": {
"prompt_tokens": 471,
"completion_tokens": 62,
"total_tokens": 533,
"cost": 2.814e-05,
"is_byok": false,
"prompt_tokens_details": {
"cached_tokens": 0,
"cache_write_tokens": 0,
"audio_tokens": 0,
"video_tokens": 0
},
"cost_details": {
"upstream_inference_cost": 2.814e-05,
"upstream_inference_prompt_cost": 1.884e-05,
"upstream_inference_completions_cost": 9.3e-06
},
"completion_tokens_details": {
"reasoning_tokens": 0,
"image_tokens": 0,
"audio_tokens": 0
}
},
"field": "Where to? ",
"value": "London"
}
],
"verification": {
"passed": true,
"checks": {
"search_page": true,
"one_way": true,
"origin": true,
"destination": true,
"date": true,
"year": true,
"results": true
},
"visible_flights": [
"From 216 US dollars.This price does not include overhead bin access. Nonstop flight with easyJet. Leaves Zurich Airport at 4:45 PM on Sunday, September 20 and arrives at London Gatwick Airport at 5:35 PM on Sunday, September 20. Total duration 1 hr 50 min. Select flight",
"From 265 US dollars. Nonstop flight with British Airways. Operated by BA Cityflyer. Leaves Zurich Airport at 8:25 PM on Sunday, September 20 and arrives at London City Airport at 9:00 PM on Sunday, September 20. Total duration 1 hr 35 min. Select flight",
"From 271 US dollars. Nonstop flight with British Airways. Leaves Zurich Airport at 1:20 PM on Sunday, September 20 and arrives at Heathrow Airport at 2:20 PM on Sunday, September 20. Total duration 2 hr. Select flight"
]
},
"source_hashes": {
"questions.py": "66a7054b85040b949e1757311257ea0c5a843c635f9a40c99f6d15ad660fb422",
"__init__.py": "60f025b8d24465e2c0f7a3547d43b8020fd8843de7b6cb3f892ef63f5548cf63",
"model.py": "a85ada8458d23642c5c8a4095acf0565e6268f81dcda26f6308942b653e9c9f3",
"browser.py": "6ef6c0cf9041f648c49bb09adf6b83d73ba301de5e87ffdeb03b0a4ce9e487ab",
"snapshot.js": "e50473501c8fb8e70f3b21866d987393e3f2315c639d638bd477d170e81ed78d",
"agent.py": "aaf8b271cb0ee6643fe7beb525328ab80de8568c7ac044d02b9c6721161e7c8b",
"demo.py": "a0cfb10909b370efb284cbbe16bdb4b7e7e06ba6385827404169027645a1d8a4"
},
"tokens": {
"input_tokens": 84650,
"output_tokens": 5899
},
"arm": "candidate",
"pair": 1,
"configuration": {
"TYPESAFE_MODEL": null,
"TEXT_MODEL": "inception/mercury-2.5",
"TEXT_MODEL_BASE_URL": "https://openrouter.ai/api/v1",
"TEXT_MODEL_REASONING": "none"
},
"browser_version": "Chrome/152.0.7977.83",
"task_hash": "bce327f45dc380ca9cd76fac5b70bfddd7ce36f8e083c1f900522af2a3499ff9",
"cdp": {
"Runtime.evaluate": {
"count": 75,
"ms": 2251.328
},
"Input.dispatchMouseEvent": {
"count": 20,
"ms": 322.317
},
"Input.dispatchKeyEvent": {
"count": 4,
"ms": 22.038
},
"Input.insertText": {
"count": 2,
"ms": 8.988
}
},
"error": null,
"browser_closed": true
},
{
"elapsed_ms": 7913,
"decision_requests": 18,
"decision_median_ms": 182.5,
"decision_total_ms": 3595,
"browser_actions": 13,
"wait_actions": 3,
"models": {
"decision": [
"jev-1.13.0"
],
"text": [
"inception/mercury-2.5"
]
},
"text_calls": [
{
"model": "inception/mercury-2.5",
"latency_ms": 415,
"usage": {
"prompt_tokens": 440,
"completion_tokens": 47,
"total_tokens": 487,
"cost": 2.465e-05,
"is_byok": false,
"prompt_tokens_details": {
"cached_tokens": 0,
"cache_write_tokens": 0,
"audio_tokens": 0,
"video_tokens": 0
},
"cost_details": {
"upstream_inference_cost": 2.465e-05,
"upstream_inference_prompt_cost": 1.76e-05,
"upstream_inference_completions_cost": 7.05e-06
},
"completion_tokens_details": {
"reasoning_tokens": 0,
"image_tokens": 0,
"audio_tokens": 0
}
},
"field": "Where from?",
"value": "Zurich"
},
{
"model": "inception/mercury-2.5",
"latency_ms": 1137,
"usage": {
"prompt_tokens": 485,
"completion_tokens": 511,
"total_tokens": 996,
"cost": 9.605e-05,
"is_byok": false,
"prompt_tokens_details": {
"cached_tokens": 0,
"cache_write_tokens": 0,
"audio_tokens": 0,
"video_tokens": 0
},
"cost_details": {
"upstream_inference_cost": 9.605e-05,
"upstream_inference_prompt_cost": 1.94e-05,
"upstream_inference_completions_cost": 7.665e-05
},
"completion_tokens_details": {
"reasoning_tokens": 0,
"image_tokens": 0,
"audio_tokens": 0
}
},
"field": "Where to? ",
"value": "London"
}
],
"verification": {
"passed": true,
"checks": {
"search_page": true,
"one_way": true,
"origin": true,
"destination": true,
"date": true,
"year": true,
"results": true
},
"visible_flights": [
"From 216 US dollars.This price does not include overhead bin access. Nonstop flight with easyJet. Leaves Zurich Airport at 4:45 PM on Sunday, September 20 and arrives at London Gatwick Airport at 5:35 PM on Sunday, September 20. Total duration 1 hr 50 min. Select flight",
"From 265 US dollars. Nonstop flight with British Airways. Operated by BA Cityflyer. Leaves Zurich Airport at 8:25 PM on Sunday, September 20 and arrives at London City Airport at 9:00 PM on Sunday, September 20. Total duration 1 hr 35 min. Select flight",
"From 271 US dollars. Nonstop flight with British Airways. Leaves Zurich Airport at 1:20 PM on Sunday, September 20 and arrives at Heathrow Airport at 2:20 PM on Sunday, September 20. Total duration 2 hr. Select flight"
]
},
"source_hashes": {
"questions.py": "66a7054b85040b949e1757311257ea0c5a843c635f9a40c99f6d15ad660fb422",
"__init__.py": "60f025b8d24465e2c0f7a3547d43b8020fd8843de7b6cb3f892ef63f5548cf63",
"model.py": "a85ada8458d23642c5c8a4095acf0565e6268f81dcda26f6308942b653e9c9f3",
"browser.py": "6ef6c0cf9041f648c49bb09adf6b83d73ba301de5e87ffdeb03b0a4ce9e487ab",
"snapshot.js": "e50473501c8fb8e70f3b21866d987393e3f2315c639d638bd477d170e81ed78d",
"agent.py": "aaf8b271cb0ee6643fe7beb525328ab80de8568c7ac044d02b9c6721161e7c8b",
"demo.py": "a0cfb10909b370efb284cbbe16bdb4b7e7e06ba6385827404169027645a1d8a4"
},
"tokens": {
"input_tokens": 88844,
"output_tokens": 6242
},
"arm": "candidate",
"pair": 2,
"configuration": {
"TYPESAFE_MODEL": null,
"TEXT_MODEL": "inception/mercury-2.5",
"TEXT_MODEL_BASE_URL": "https://openrouter.ai/api/v1",
"TEXT_MODEL_REASONING": "none"
},
"browser_version": "Chrome/152.0.7977.83",
"task_hash": "bce327f45dc380ca9cd76fac5b70bfddd7ce36f8e083c1f900522af2a3499ff9",
"cdp": {
"Runtime.evaluate": {
"count": 77,
"ms": 2076.599
},
"Input.dispatchMouseEvent": {
"count": 20,
"ms": 334.491
},
"Input.dispatchKeyEvent": {
"count": 4,
"ms": 23.523
},
"Input.insertText": {
"count": 2,
"ms": 10.362
}
},
"error": null,
"browser_closed": true
},
{
"elapsed_ms": 8984,
"decision_requests": 21,
"decision_median_ms": 167,
"decision_total_ms": 4004,
"browser_actions": 12,
"wait_actions": 2,
"models": {
"decision": [
"jev-1.13.0"
],
"text": [
"inception/mercury-2.5"
]
},
"text_calls": [
{
"model": "inception/mercury-2.5",
"latency_ms": 395,
"usage": {
"prompt_tokens": 460,
"completion_tokens": 74,
"total_tokens": 534,
"cost": 2.95e-05,
"is_byok": false,
"prompt_tokens_details": {
"cached_tokens": 0,
"cache_write_tokens": 0,
"audio_tokens": 0,
"video_tokens": 0
},
"cost_details": {
"upstream_inference_cost": 2.95e-05,
"upstream_inference_prompt_cost": 1.84e-05,
"upstream_inference_completions_cost": 1.11e-05
},
"completion_tokens_details": {
"reasoning_tokens": 0,
"image_tokens": 0,
"audio_tokens": 0
}
},
"field": "Where from?",
"value": "Zurich"
},
{
"model": "inception/mercury-2.5",
"latency_ms": 338,
"usage": {
"prompt_tokens": 492,
"completion_tokens": 43,
"total_tokens": 535,
"cost": 2.613e-05,
"is_byok": false,
"prompt_tokens_details": {
"cached_tokens": 0,
"cache_write_tokens": 0,
"audio_tokens": 0,
"video_tokens": 0
},
"cost_details": {
"upstream_inference_cost": 2.613e-05,
"upstream_inference_prompt_cost": 1.968e-05,
"upstream_inference_completions_cost": 6.45e-06
},
"completion_tokens_details": {
"reasoning_tokens": 0,
"image_tokens": 0,
"audio_tokens": 0
}
},
"field": "Where to? ",
"value": "London"
}
],
"verification": {
"passed": true,
"checks": {
"search_page": true,
"one_way": true,
"origin": true,
"destination": true,
"date": true,
"year": true,
"results": true
},
"visible_flights": [
"From 216 US dollars.This price does not include overhead bin access. Nonstop flight with easyJet. Leaves Zurich Airport at 4:45 PM on Sunday, September 20 and arrives at London Gatwick Airport at 5:35 PM on Sunday, September 20. Total duration 1 hr 50 min. Select flight",
"From 265 US dollars. Nonstop flight with British Airways. Operated by BA Cityflyer. Leaves Zurich Airport at 8:25 PM on Sunday, September 20 and arrives at London City Airport at 9:00 PM on Sunday, September 20. Total duration 1 hr 35 min. Select flight",
"From 271 US dollars. Nonstop flight with British Airways. Leaves Zurich Airport at 1:20 PM on Sunday, September 20 and arrives at Heathrow Airport at 2:20 PM on Sunday, September 20. Total duration 2 hr. Select flight"
]
},
"source_hashes": {
"questions.py": "66a7054b85040b949e1757311257ea0c5a843c635f9a40c99f6d15ad660fb422",
"__init__.py": "60f025b8d24465e2c0f7a3547d43b8020fd8843de7b6cb3f892ef63f5548cf63",
"model.py": "a85ada8458d23642c5c8a4095acf0565e6268f81dcda26f6308942b653e9c9f3",
"browser.py": "d2b0e468c2dac3f4d3cbba51f3619fe26fe44fb1554446363d8d1aff5efe22f2",
"agent.py": "be5434b79de0410352485e734ff4bb7a5d9556ce22ae47f231b5be3aa67161a4",
"demo.py": "a0cfb10909b370efb284cbbe16bdb4b7e7e06ba6385827404169027645a1d8a4"
},
"tokens": {
"input_tokens": 106691,
"output_tokens": 7531
},
"arm": "baseline",
"pair": 2,
"configuration": {
"TYPESAFE_MODEL": null,
"TEXT_MODEL": "inception/mercury-2.5",
"TEXT_MODEL_BASE_URL": "https://openrouter.ai/api/v1",
"TEXT_MODEL_REASONING": "none"
},
"browser_version": "Chrome/152.0.7977.83",
"task_hash": "bce327f45dc380ca9cd76fac5b70bfddd7ce36f8e083c1f900522af2a3499ff9",
"cdp": {
"Runtime.evaluate": {
"count": 146,
"ms": 1595.322
},
"Accessibility.getFullAXTree": {
"count": 30,
"ms": 1311.762
},
"Runtime.callFunctionOn": {
"count": 40,
"ms": 315.525
},
"DOM.resolveNode": {
"count": 828,
"ms": 846.738
},
"DOM.getBoxModel": {
"count": 10,
"ms": 8.759
},
"DOM.getNodeForLocation": {
"count": 10,
"ms": 12.157
},
"Input.dispatchMouseEvent": {
"count": 20,
"ms": 337.511
},
"Input.dispatchKeyEvent": {
"count": 4,
"ms": 38.385
},
"Input.insertText": {
"count": 2,
"ms": 11.307
}
},
"error": null,
"browser_closed": true
},
{
"elapsed_ms": 9450,
"decision_requests": 22,
"decision_median_ms": 187.0,
"decision_total_ms": 4261,
"browser_actions": 12,
"wait_actions": 2,
"models": {
"decision": [
"jev-1.13.0"
],
"text": [
"inception/mercury-2.5"
]
},
"text_calls": [
{
"model": "inception/mercury-2.5",
"latency_ms": 460,
"usage": {
"prompt_tokens": 460,
"completion_tokens": 55,
"total_tokens": 515,
"cost": 2.665e-05,
"is_byok": false,
"prompt_tokens_details": {
"cached_tokens": 0,
"cache_write_tokens": 0,
"audio_tokens": 0,
"video_tokens": 0
},
"cost_details": {
"upstream_inference_cost": 2.665e-05,
"upstream_inference_prompt_cost": 1.84e-05,
"upstream_inference_completions_cost": 8.25e-06
},
"completion_tokens_details": {
"reasoning_tokens": 0,
"image_tokens": 0,
"audio_tokens": 0
}
},
"field": "Where from?",
"value": "Zurich"
},
{
"model": "inception/mercury-2.5",
"latency_ms": 513,
"usage": {
"prompt_tokens": 491,
"completion_tokens": 63,
"total_tokens": 554,
"cost": 2.909e-05,
"is_byok": false,
"prompt_tokens_details": {
"cached_tokens": 0,
"cache_write_tokens": 0,
"audio_tokens": 0,
"video_tokens": 0
},
"cost_details": {
"upstream_inference_cost": 2.909e-05,
"upstream_inference_prompt_cost": 1.964e-05,
"upstream_inference_completions_cost": 9.45e-06
},
"completion_tokens_details": {
"reasoning_tokens": 0,
"image_tokens": 0,
"audio_tokens": 0
}
},
"field": "Where to? ",
"value": "London"
}
],
"verification": {
"passed": true,
"checks": {
"search_page": true,
"one_way": true,
"origin": true,
"destination": true,
"date": true,
"year": true,
"results": true
},
"visible_flights": [
"From 216 US dollars.This price does not include overhead bin access. Nonstop flight with easyJet. Leaves Zurich Airport at 4:45 PM on Sunday, September 20 and arrives at London Gatwick Airport at 5:35 PM on Sunday, September 20. Total duration 1 hr 50 min. Select flight",
"From 265 US dollars. Nonstop flight with British Airways. Operated by BA Cityflyer. Leaves Zurich Airport at 8:25 PM on Sunday, September 20 and arrives at London City Airport at 9:00 PM on Sunday, September 20. Total duration 1 hr 35 min. Select flight",
"From 271 US dollars. Nonstop flight with British Airways. Leaves Zurich Airport at 1:20 PM on Sunday, September 20 and arrives at Heathrow Airport at 2:20 PM on Sunday, September 20. Total duration 2 hr. Select flight"
]
},
"source_hashes": {
"questions.py": "66a7054b85040b949e1757311257ea0c5a843c635f9a40c99f6d15ad660fb422",
"__init__.py": "60f025b8d24465e2c0f7a3547d43b8020fd8843de7b6cb3f892ef63f5548cf63",
"model.py": "a85ada8458d23642c5c8a4095acf0565e6268f81dcda26f6308942b653e9c9f3",
"browser.py": "d2b0e468c2dac3f4d3cbba51f3619fe26fe44fb1554446363d8d1aff5efe22f2",
"agent.py": "be5434b79de0410352485e734ff4bb7a5d9556ce22ae47f231b5be3aa67161a4",
"demo.py": "a0cfb10909b370efb284cbbe16bdb4b7e7e06ba6385827404169027645a1d8a4"
},
"tokens": {
"input_tokens": 115547,
"output_tokens": 8131
},
"arm": "baseline",
"pair": 3,
"configuration": {
"TYPESAFE_MODEL": null,
"TEXT_MODEL": "inception/mercury-2.5",
"TEXT_MODEL_BASE_URL": "https://openrouter.ai/api/v1",
"TEXT_MODEL_REASONING": "none"
},
"browser_version": "Chrome/152.0.7977.83",
"task_hash": "bce327f45dc380ca9cd76fac5b70bfddd7ce36f8e083c1f900522af2a3499ff9",
"cdp": {
"Runtime.evaluate": {
"count": 148,
"ms": 1452.987
},
"Accessibility.getFullAXTree": {
"count": 30,
"ms": 1382.719
},
"Runtime.callFunctionOn": {
"count": 40,
"ms": 254.649
},
"DOM.resolveNode": {
"count": 828,
"ms": 1792.588
},
"DOM.getBoxModel": {
"count": 10,
"ms": 9.862
},
"DOM.getNodeForLocation": {
"count": 10,
"ms": 11.54
},
"Input.dispatchMouseEvent": {
"count": 20,
"ms": 356.041
},
"Input.dispatchKeyEvent": {
"count": 4,
"ms": 41.423
},
"Input.insertText": {
"count": 2,
"ms": 12.43
}
},
"error": null,
"browser_closed": true
},
{
"elapsed_ms": 7092,
"decision_requests": 16,
"decision_median_ms": 182.5,
"decision_total_ms": 2996,
"browser_actions": 12,
"wait_actions": 2,
"models": {
"decision": [
"jev-1.13.0"
],
"text": [
"inception/mercury-2.5"
]
},
"text_calls": [
{
"model": "inception/mercury-2.5",
"latency_ms": 540,
"usage": {
"prompt_tokens": 453,
"completion_tokens": 74,
"total_tokens": 527,
"cost": 2.922e-05,
"is_byok": false,
"prompt_tokens_details": {
"cached_tokens": 0,
"cache_write_tokens": 0,
"audio_tokens": 0,
"video_tokens": 0
},
"cost_details": {
"upstream_inference_cost": 2.922e-05,
"upstream_inference_prompt_cost": 1.812e-05,
"upstream_inference_completions_cost": 1.11e-05
},
"completion_tokens_details": {
"reasoning_tokens": 0,
"image_tokens": 0,
"audio_tokens": 0
}
},
"field": "Where from?",
"value": "Zurich"
},
{
"model": "inception/mercury-2.5",
"latency_ms": 499,
"usage": {
"prompt_tokens": 483,
"completion_tokens": 59,
"total_tokens": 542,
"cost": 2.817e-05,
"is_byok": false,
"prompt_tokens_details": {
"cached_tokens": 0,
"cache_write_tokens": 0,
"audio_tokens": 0,
"video_tokens": 0
},
"cost_details": {
"upstream_inference_cost": 2.817e-05,
"upstream_inference_prompt_cost": 1.932e-05,
"upstream_inference_completions_cost": 8.85e-06
},
"completion_tokens_details": {
"reasoning_tokens": 0,
"image_tokens": 0,
"audio_tokens": 0
}
},
"field": "Where to? ",
"value": "London"
}
],
"verification": {
"passed": true,
"checks": {
"search_page": true,
"one_way": true,
"origin": true,
"destination": true,
"date": true,
"year": true,
"results": true
},
"visible_flights": [
"From 216 US dollars.This price does not include overhead bin access. Nonstop flight with easyJet. Leaves Zurich Airport at 4:45 PM on Sunday, September 20 and arrives at London Gatwick Airport at 5:35 PM on Sunday, September 20. Total duration 1 hr 50 min. Select flight",
"From 265 US dollars. Nonstop flight with British Airways. Operated by BA Cityflyer. Leaves Zurich Airport at 8:25 PM on Sunday, September 20 and arrives at London City Airport at 9:00 PM on Sunday, September 20. Total duration 1 hr 35 min. Select flight",
"From 271 US dollars. Nonstop flight with British Airways. Leaves Zurich Airport at 1:20 PM on Sunday, September 20 and arrives at Heathrow Airport at 2:20 PM on Sunday, September 20. Total duration 2 hr. Select flight"
]
},
"source_hashes": {
"questions.py": "66a7054b85040b949e1757311257ea0c5a843c635f9a40c99f6d15ad660fb422",
"__init__.py": "60f025b8d24465e2c0f7a3547d43b8020fd8843de7b6cb3f892ef63f5548cf63",
"model.py": "a85ada8458d23642c5c8a4095acf0565e6268f81dcda26f6308942b653e9c9f3",
"browser.py": "6ef6c0cf9041f648c49bb09adf6b83d73ba301de5e87ffdeb03b0a4ce9e487ab",
"snapshot.js": "e50473501c8fb8e70f3b21866d987393e3f2315c639d638bd477d170e81ed78d",
"agent.py": "aaf8b271cb0ee6643fe7beb525328ab80de8568c7ac044d02b9c6721161e7c8b",
"demo.py": "a0cfb10909b370efb284cbbe16bdb4b7e7e06ba6385827404169027645a1d8a4"
},
"tokens": {
"input_tokens": 82661,
"output_tokens": 5783
},
"arm": "candidate",
"pair": 3,
"configuration": {
"TYPESAFE_MODEL": null,
"TEXT_MODEL": "inception/mercury-2.5",
"TEXT_MODEL_BASE_URL": "https://openrouter.ai/api/v1",
"TEXT_MODEL_REASONING": "none"
},
"browser_version": "Chrome/152.0.7977.83",
"task_hash": "bce327f45dc380ca9cd76fac5b70bfddd7ce36f8e083c1f900522af2a3499ff9",
"cdp": {
"Runtime.evaluate": {
"count": 71,
"ms": 2483.491
},
"Input.dispatchMouseEvent": {
"count": 20,
"ms": 328.154
},
"Input.dispatchKeyEvent": {
"count": 4,
"ms": 20.116
},
"Input.insertText": {
"count": 2,
"ms": 8.988
}
},
"error": null,
"browser_closed": true
}
],
"scope": "Three alternating pairs of one task in one existing Chrome profile, 1120x780 viewport. All attempts included. Same goal, independent checker, models, and budgets. Live site/network/caches not controlled.",
"final_source_note": "After timing and recording, added stop-on-interruption handling for native SELECT. It changes a failure path not exercised by Flights. Covered by offline fault-injection and local browser checks."
}
{
"date": "2026-09-16",
"scope": "Three runs of one authored local fixture; not a general web evaluation.",
"timing": "First decision request through final DONE, including execution, observations, screenshots. Excludes Chrome startup and initial page load.",
"model": "jev-1.13.0",
"goals": [
"Enter \"Lisbon\" into the Destination field.",
"Click Find stays to search for Lisbon.",
"Set Stay category to Design.",
"Enable Free cancellation.",
"Open Casa Flora."
],
"browser_viewport": [
1120,
780
],
"platform": "macOS / Chrome / browser-harness 0.1.13",
"runs": [
{
"run": 1,
"elapsed_ms": 1242,
"actions": 5,
"requests": 6,
"request_latencies_ms": [
335,
125,
134,
105,
123,
123
],
"final_url": "http://127.0.0.1:8766/fixture.html?scenario=travel#casa-flora",
"verified_final_text": "Your filters: Design \u00b7 Free cancellation enabled \u00b7 Destination Lisbon",
"text_helper": "literal from task (no LLM)"
},
{
"run": 2,
"elapsed_ms": 1086,
"actions": 5,
"requests": 6,
"request_latencies_ms": [
127,
111,
102,
120,
167,
140
],
"final_url": "http://127.0.0.1:8766/fixture.html?scenario=travel#casa-flora",
"verified_final_text": "Your filters: Design \u00b7 Free cancellation enabled \u00b7 Destination Lisbon",
"text_helper": "literal from task (no LLM)"
},
{
"run": 3,
"elapsed_ms": 1311,
"actions": 5,
"requests": 6,
"request_latencies_ms": [
146,
143,
117,
202,
211,
198
],
"final_url": "http://127.0.0.1:8766/fixture.html?scenario=travel#casa-flora",
"verified_final_text": "Your filters: Design \u00b7 Free cancellation enabled \u00b7 Destination Lisbon",
"text_helper": "literal from task (no LLM)"
}
],
"median_ms": 1242,
"text_generation_run": {
"elapsed_ms": 4650,
"helper": "z-ai/glm-5.3-flash",
"typed": "Lisbon",
"verified": true
},
"source_sha256": {
"jev_ultrafast/questions.py": "5167c4b84206f6b038370edbb863d566dd313bd77855d3f4d91f9435b215edaf",
"jev_ultrafast/__init__.py": "60f025b8d24465e2c0f7a3547d43b8020fd8843de7b6cb3f892ef63f5548cf63",
"jev_ultrafast/model.py": "014c3f349420b0e84a3cba1b0849b38172e7ddca1558f190437058938ac9b059",
"jev_ultrafast/browser.py": "b4b73f9470e2cf2bf499d6bdc9295f9411f7ef1426bb87ff3089530260a5d1b5",
"jev_ultrafast/agent.py": "519289e4fd65b1d318f4b8b7e3951908eb31ab7a4455648abbe82442fde5855d",
"jev_ultrafast/demo.py": "f9ea4a5809062b95b017c3f7a09d744d408e57b05738855e5e41257b5d7817a2"
},
"media": {
"source": "First recorded travel run; six original screenshot observations",
"speed": 1,
"lead_in_ms": 750,
"endpoint_hold_ms": 1250
}
}"""Live Google Flights search. Calls TypeSafe; never selects or books a flight."""
import argparse
import base64
import json
from pathlib import Path
from urllib.parse import parse_qs, urlparse
from jev_ultrafast import Agent
URL = "https://www.google.com/travel/flights?hl=en"
GOALS = (
"Find one-way flights from Zurich to London on September 20, 2026, for one adult in economy. "
"Stop when matching flight options are visible. Do not select or book a flight."
)
def verify(page):
"""Independent checks on the resulting page, not the model's DONE answer."""
parsed = urlparse(page["url"])
encoded = parse_qs(parsed.query).get("tfs", [""])[0]
try:
date_in_url = b"2026-09-20" in base64.urlsafe_b64decode(encoded + "=" * (-len(encoded) % 4))
except ValueError:
date_in_url = False
actions = page["actions"]
values = {a["label"].strip(): a.get("value") for a in actions}
flights = [a["label"] for a in actions if "Select flight" in a["label"]]
checks = {
"search_page": parsed.hostname == "www.google.com" and parsed.path == "/travel/flights/search",
"one_way": values.get("Change ticket type. One way") == "One way",
"origin": values.get("Where from?") == "Zürich",
"destination": values.get("Where to?") == "London",
"date": values.get("Departure") == "Sun, Sep 20",
"year": date_in_url or "departing 2026-09-20" in page["text"],
"results": bool(flights) and all("Sunday, September 20" in f for f in flights),
}
return {"passed": all(checks.values()), "checks": checks, "visible_flights": flights}
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--output", default="artifacts/flights/latest")
parser.add_argument("--keep-open", action="store_true")
args = parser.parse_args()
folder = Path(args.output)
folder.mkdir(parents=True, exist_ok=True)
agent = Agent(URL, GOALS)
try:
for state in agent.run():
last = state["history"][-1] if state["history"] else {}
print(state["elapsed_ms"], state["status"], last.get("action", ""), flush=True)
finally:
state = agent.snapshot()
state["verification"] = verify(state["page"])
(folder / "state.json").write_text(json.dumps(state, indent=2))
(folder / "session.json").write_text(
json.dumps({"target": agent.browser.target, "session": agent.browser.session})
)
if not args.keep_open:
agent.close()
print(json.dumps(state["verification"], indent=2))
if not state["verification"]["passed"]:
raise SystemExit("Final page did not satisfy the route/date checks")
if __name__ == "__main__":
main()
"""Jev chooses an observed action. Code owns execution."""
from .agent import Agent
from .browser import Browser
__all__ = ["Agent", "Browser"]
"""Loopback-only inspector for the Jev browser agent."""
import atexit
import json
import os
import secrets
import threading
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
from pathlib import Path
from urllib.parse import urlparse
from .agent import Agent
from .questions import MAX_STEPS
ROOT = Path(__file__).parent
PORT = int(os.environ.get("TYPESAFE_DEMO_PORT", "8766"))
ORIGIN = f"http://127.0.0.1:{PORT}"
TOKEN = secrets.token_urlsafe(32)
LOCK = threading.Lock()
AGENT = None
def load_environment():
path = Path.cwd() / ".env"
if path.exists():
for line in path.read_text().splitlines():
if "=" in line and not line.startswith("#"):
key, value = line.split("=", 1)
os.environ.setdefault(key, value)
def response_state():
state = AGENT.snapshot() if AGENT else {"page": None, "status": "idle", "history": [], "decision": None}
return {**state, "text_model": os.environ.get("TEXT_MODEL", "deepseek-chat"), "max_steps": MAX_STEPS}
def close_browser():
global AGENT
if AGENT:
AGENT.close()
AGENT = None
def command(name, body):
global AGENT
if name == "reset":
scenario = body.get("scenario", "flights")
if scenario not in {"travel", "research", "flights"}:
raise ValueError("Unknown demo scenario")
goal = body.get("goal", "").strip()
if not goal or len(goal) > 2000:
raise ValueError("Enter 1–2,000 characters")
close_browser()
AGENT = Agent(
"https://www.google.com/travel/flights?hl=en"
if scenario == "flights"
else f"{ORIGIN}/fixture.html?scenario={scenario}",
goal,
screenshots=True,
record_dir=Path.cwd() / "artifacts" / "frames" if body.get("record") else None,
)
AGENT.state["scenario"] = scenario
else:
if AGENT is None:
raise ValueError("Start a demo first")
AGENT.command(name, body)
return response_state()
class Handler(BaseHTTPRequestHandler):
def send(self, status, content, mime="application/json"):
content = content if isinstance(content, bytes) else content.encode()
self.send_response(status)
self.send_header("Content-Type", mime)
self.send_header("Content-Length", str(len(content)))
self.send_header("Cache-Control", "no-store")
self.send_header("X-Content-Type-Options", "nosniff")
self.end_headers()
self.wfile.write(content)
def do_GET(self):
if self.headers.get("Host") != f"127.0.0.1:{PORT}":
return self.send(403, "Forbidden", "text/plain")
path = urlparse(self.path).path
if path == "/api/state":
with LOCK:
return self.send(200, json.dumps(response_state()))
if path == "/demo.mp4":
video = ROOT.parent / "docs" / "demo.mp4"
if video.exists():
return self.send(200, video.read_bytes(), "video/mp4")
files = {
"/": ("index.html", "text/html"),
"/app.js": ("app.js", "text/javascript"),
"/style.css": ("style.css", "text/css"),
"/fixture.html": ("fixture.html", "text/html"),
}
if path not in files:
return self.send(404, "Not found", "text/plain")
name, mime = files[path]
content = (ROOT / "static" / name).read_text().replace("__TOKEN__", TOKEN)
self.send(200, content, mime + "; charset=utf-8")
def do_POST(self):
if (
self.headers.get("Host") != f"127.0.0.1:{PORT}"
or self.headers.get("X-Demo-Token") != TOKEN
or self.headers.get("Origin") not in (None, ORIGIN)
):
return self.send(403, json.dumps({"error": "Local demo requests only"}))
if not LOCK.acquire(blocking=False):
return self.send(409, json.dumps({"error": "A browser step is already running"}))
try:
length = int(self.headers.get("Content-Length", "0"))
if not 0 < length < 8192:
raise ValueError("Invalid request size")
body = json.loads(self.rfile.read(length))
result = command(self.path.removeprefix("/api/"), body)
self.send(200, json.dumps(result))
except (ValueError, RuntimeError, TimeoutError) as error:
self.send(400, json.dumps({"error": str(error)}))
except Exception:
self.send(500, json.dumps({"error": "Local demo failed; no automatic retry. Reset to recover."}))
finally:
LOCK.release()
def log_message(self, *_args):
pass
def main():
load_environment()
atexit.register(close_browser)
server = ThreadingHTTPServer(("127.0.0.1", PORT), Handler)
print(f"Jev Ultrafast: {ORIGIN}", flush=True)
try:
server.serve_forever()
except KeyboardInterrupt:
pass
finally:
server.server_close()
if __name__ == "__main__":
main()
"""TypeSafe makes choices; an optional small OpenAI-compatible model writes field values."""
import json
import math
import os
import time
import httpx
from .questions import NEXT_ACTION, TARGET, TEXT_VALUE
CLIENT = httpx.Client(http2=True, timeout=25)
def post_json(url, key, body):
for attempt in range(3):
try:
response = CLIENT.post(url, json=body, headers={"Authorization": f"Bearer {key}"})
except httpx.HTTPError:
raise RuntimeError("Model connection failed; no action executed.") from None
if response.status_code in {429, 529, 503} and attempt < 2:
time.sleep(0.5 * 2**attempt)
continue
if response.is_error:
raise RuntimeError(f"Model provider returned HTTP {response.status_code}; no action executed.")
return response.json()
raise RuntimeError("Model unavailable")
def validate_choice(answer, ids):
try:
probabilities = answer["probabilities"]
numbers = [*probabilities.values(), answer["confidence"]]
valid = (
answer["choice"] in ids
and set(probabilities) == set(ids)
and all(type(n) in (int, float) and math.isfinite(n) and 0 <= n <= 1 for n in numbers)
and abs(sum(probabilities.values()) - 1) < 0.02
and probabilities[answer["choice"]] >= max(probabilities.values()) - 1e-6
)
except (KeyError, TypeError, ValueError):
valid = False
if not valid:
raise ValueError("Invalid TypeSafe response; no action executed.")
return answer
def action_space(actions):
"""One index per observed element; each operation has its own valid target choices."""
elements, indices, targets, controls = [], {}, {}, {}
operations = {"click": "CLICK", "fill": "TYPE_TEXT", "select": "SELECT"}
for action in actions:
kind = action["kind"]
if kind not in operations:
controls[action["id"].upper()] = action
continue
node = action["node"]
if node not in indices:
index = str(len(elements) + 1)
indices[node] = index
element = {k: action[k] for k in ("role", "value", "checked", "selected", "expanded") if k in action}
element.update(index=index, label=action["label"].split(" → ")[0], operations=[])
if kind == "select":
element["value"] = action.get("current_value", "")
element["options"] = []
elements.append(element)
index = indices[node]
operation = operations[kind]
group = targets.setdefault(operation, {})
element = elements[int(index) - 1]
if operation not in element["operations"]:
element["operations"].append(operation)
target = index
if kind == "select":
target = f"{index}:{len(element['options']) + 1}"
element["options"].append({"index": target, "label": action["label"], "value": action["value"]})
group[target] = action
return elements, targets, controls
def choose(state, goal, history):
elements, targets, controls = action_space(state["actions"])
labels = {
"CLICK": "Click an element, button, menu option, autocomplete suggestion, or calendar day.",
"TYPE_TEXT": "Enter or replace text in an editable field. A small LLM will supply the value from the goal.",
"SELECT": "Select an observed dropdown value.",
}
operations = {key: labels[key] for key in targets}
operations.update({key: value["label"] for key, value in controls.items()})
operations.update(DONE="Every requirement is visibly satisfied.", BLOCKED="No supported operation can progress.")
questions = {
"operation": {"type": "choice", "criteria": operations, "instructions": {"goal": goal, "rules": NEXT_ACTION}}
}
for operation, candidates in targets.items():
questions[operation.lower() + "_target"] = {
"type": "choice",
"criteria": {
index: {
"element": f"[{index}] {a['label']}",
"current_value": a.get("current_value", a.get("value", "")),
**{k: a[k] for k in ("role", "checked", "selected", "expanded") if k in a},
}
for index, a in candidates.items()
},
"instructions": {"goal": goal, "operation": operation, "rules": [NEXT_ACTION, TARGET]},
}
body = {
"model": os.environ.get("TYPESAFE_MODEL", "jev-latest"),
"state": {
"page": {k: state[k] for k in ("url", "title", "text")},
"elements": elements,
"recent_actions": [
{k: h.get(k) for k in ("action", "kind", "text", "page_changed")} for h in history[-10:]
],
},
"questions": questions,
}
started = time.perf_counter()
result = post_json("https://api.typesafe.ai/v1/systemone", os.environ["TYPESAFE_API_KEY"], body)
operation_answer = validate_choice(result["answers"].get("operation", {}), operations)
operation = operation_answer["choice"]
target = None
target_answer = None
probabilities = {}
if operation in targets:
# Unused target heads cannot cause an action. Validate the head selected by the operation.
target_answer = validate_choice(result["answers"].get(operation.lower() + "_target", {}), targets[operation])
target = target_answer["choice"]
choice = targets[operation][target]["id"]
probabilities = {a["id"]: target_answer["probabilities"][index] for index, a in targets[operation].items()}
else:
choice = controls[operation]["id"] if operation in controls else operation
probabilities[choice] = operation_answer["probabilities"][operation]
return {
"choice": choice,
"operation": operation,
"target": target,
"confidence": operation_answer["confidence"],
"probabilities": probabilities,
"operation_probabilities": operation_answer["probabilities"],
"target_probabilities": target_answer["probabilities"] if target_answer else {},
"target_confidence": target_answer["confidence"] if target_answer else None,
"raw_answers": result["answers"],
"model": result["model"],
"usage": result.get("usage", {}),
"latency_ms": round((time.perf_counter() - started) * 1000),
"request": body,
}
def field_context(goal, action, page, history):
return {
"goal": goal,
"field": {k: action.get(k) for k in ("label", "role", "value")},
"page": {"title": page["title"], "text": page["text"][:6000]},
"recent_actions": [{k: h.get(k) for k in ("action", "text")} for h in history[-6:]],
}
def field_text(context):
key = os.environ.get("TEXT_MODEL_API_KEY")
if not key:
raise ValueError("TYPE_TEXT needs TEXT_MODEL_API_KEY; no text is hardcoded or guessed by the executor.")
base = os.environ.get("TEXT_MODEL_BASE_URL", "https://api.deepseek.com/v1").rstrip("/")
model = os.environ.get("TEXT_MODEL", "deepseek-chat")
reasoning = {"thinking": {"type": "disabled"}} if "api.deepseek.com/" in base else {"reasoning": {"effort": "low"}}
if os.environ.get("TEXT_MODEL_REASONING") == "none":
reasoning = {"reasoning": {"enabled": False}}
started = time.perf_counter()
result = post_json(
base + "/chat/completions",
key,
{
"model": model,
"max_tokens": 1024,
"response_format": {"type": "json_object"},
**reasoning,
"messages": [
{"role": "system", "content": TEXT_VALUE},
{
"role": "user",
"content": json.dumps(context),
},
],
},
)
try:
output = json.loads(result["choices"][0]["message"]["content"])
value = output["text"]
if set(output) != {"text"} or not isinstance(value, str) or not value.strip() or len(value) > 2000:
raise ValueError()
except (ValueError, KeyError, TypeError):
raise ValueError("Text helper returned no valid field value; nothing typed.") from None
return value, {
"model": model,
"latency_ms": round((time.perf_counter() - started) * 1000),
"usage": result.get("usage", {}),
}
const $ = (id) => document.getElementById(id);
const token = document.querySelector('meta[name="demo-token"]').content;
let state = null,
busy = false,
automatic = false;
const goals = {
flights: 'Find one-way flights from Zurich to London on September 20, 2026, for one adult in economy. Stop when matching flight options are visible. Do not select or book a flight.',
travel: 'Find a Design stay in Lisbon with Free cancellation and open Casa Flora.',
research:
"Open the article about using finite choices to control browser agents.",
};
const escape = (value) =>
String(value ?? "").replace(
/[&<>"']/g,
(c) =>
({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" })[
c
],
);
const percent = (value) => `${(value * 100).toFixed(value < 0.01 ? 1 : 0)}%`;
async function call(name, body = {}) {
const response = await fetch(`/api/${name}`, {
method: "POST",
headers: { "Content-Type": "application/json", "X-Demo-Token": token },
body: JSON.stringify(body),
});
const data = await response.json();
if (!response.ok) throw Error(data.error || "Request failed");
state = data;
render();
return data;
}
function controls() {
const live = state?.page && !["done", "blocked"].includes(state.status);
$("start").disabled = busy;
$("scenario").disabled = busy;
$("goal").disabled = busy;
$("choose").disabled = busy || !live;
$("execute").disabled = busy || !state?.decision || !live;
$("auto").disabled = busy || !live;
$("auto").hidden = automatic;
$("stop").hidden = !automatic;
$("download").disabled = !state?.history?.length;
}
async function perform(fn, label) {
if (busy) return;
busy = true;
$("error").hidden = true;
controls();
$("status").textContent = label;
try {
await fn();
} catch (error) {
automatic = false;
try {
state = await fetch("/api/state").then((r) => r.json());
render();
} catch {
/* Preserve the original failure if the server disconnected. */
}
$("error").textContent = error.message;
$("error").hidden = false;
$("status").textContent = "Paused · needs attention";
} finally {
busy = false;
controls();
}
}
function render() {
if (!state) return;
$("helper").textContent = `Text helper · ${state.text_model}`;
$("plan").innerHTML = (state.plan || [])
.map(
(goal, i) =>
`<div class="plan-step ${i === state.plan_index ? "current" : ""}"><span>${i < state.plan_index ? "✓" : i + 1}</span>${escape(goal)}</div>`,
)
.join("");
const page = state.page,
d =
state.decision ||
(state.status === "done" ? state.decisions?.at(-1) : null);
const labels = {
idle: "Ready to explore",
ready: "Page observed · ready for a decision",
predicted: "Choice ready · inspect or execute",
done: "Jev reports complete · inspect the page",
blocked: "Stopped · no supported next action",
};
$("status").textContent = labels[state.status] || state.status;
if (!page) {
controls();
return;
}
$("empty").hidden = true;
$("screenshot").hidden = false;
$("screenshot").src = `data:image/jpeg;base64,${page.screenshot}`;
$("url").textContent = page.url;
$("page-title").textContent = page.title;
$("action-count").textContent = `${state.elements.length} elements`;
const chosen = page.actions.find((a) => a.id === d?.choice);
$("choice-title").textContent = d
? chosen?.label || d.choice
: "Choose an action";
$("latency").textContent = d ? `${d.latency_ms} ms` : "—";
$("confidence").textContent = d?.target_confidence != null ? percent(d.target_confidence) : "—";
$("completion").textContent = d ? d.operation : "—";
$("ranking-note").textContent = d ? "Ranked by Jev" : "Unranked";
const op = Object.entries(d?.operation_probabilities || {}).sort((a,b)=>b[1]-a[1]);
$("operation-choices").innerHTML = op.map(([name,p]) =>
`<span class="operation-choice ${name === d.operation ? 'best' : ''}">${escape(name)} <b>${percent(p)}</b></span>`).join('');
const probability = e => d?.target_probabilities[e.index] ??
Math.max(-1, ...(e.options || []).map(o=>d?.target_probabilities[o.index] ?? -1));
const selectedIndex = d?.target?.split(':')[0];
const elements = [...state.elements];
if (d) elements.sort((a,b)=>probability(b)-probability(a));
$("choices").innerHTML = elements.map(e => {
const p = probability(e);
return `<div class="choice ${selectedIndex === e.index ? 'best' : ''}" data-action="${escape(e.index)}"><span class="choice-id">[${escape(e.index)}]</span><div class="choice-label">${escape(e.label)}<small>${escape(e.role)} · ${escape(e.operations.join(' / '))}${e.value ? ' · '+escape(e.value) : ''}${e.checked !== undefined ? ' · checked '+escape(e.checked) : ''}</small>${p >= 0 ? `<div class="bar" style="--probability:${p*100}%"></div>` : ''}</div><span class="probability">${p >= 0 ? percent(p) : '—'}</span></div>`;
}).join('');
const targets = new Map();
for (const a of page.actions) if (a.rect && !targets.has(a.node)) targets.set(a.node, a);
$("targets").innerHTML = [...targets.values()].map((a,i) => {
const index=String(i+1);
return `<div class="target ${index === selectedIndex ? 'selected' : ''}" data-action="${index}" style="left:${100*a.rect.x/page.w}%;top:${100*a.rect.y/page.h}%;width:${100*a.rect.w/page.w}%;height:${100*a.rect.h/page.h}%"><span>${index}</span></div>`;
}).join('');
$("targets").hidden = !$("overlays").checked;
$("history").innerHTML = state.history.length
? state.history
.map(
(h) =>
`<div class="trace-row"><span class="number">${String(h.step).padStart(2, "0")}</span><div>${escape(h.action)}${h.text ? ` <b>“${escape(h.text)}”</b><small>${escape(h.text_helper)}</small>` : ""}</div><span class="time">${h.latency_ms} ms · ${percent(h.probability)}</span><span class="effect">${h.page_changed ? "Page changed" : "No change observed"}</span></div>`,
)
.join("")
: '<p class="muted">Each executed action leaves an observed result.</p>';
$("step-count").textContent = `${state.history.length} actions · ${(state.elapsed_ms / 1000).toFixed(2)} s`;
$("model-state").textContent = JSON.stringify(
d?.request || {
goal: state.goal,
url: page.url,
text: page.text,
actions: page.actions.map(({ rect, node, ...rest }) => rest),
},
null,
2,
);
controls();
}
$("task-form").addEventListener("submit", (event) => {
event.preventDefault();
automatic = false;
perform(
() =>
call("reset", { scenario: $("scenario").value, goal: $("goal").value }),
"Opening a fresh browser…",
);
});
$("scenario").addEventListener("change", () => {
$("goal").value = goals[$("scenario").value];
});
$("choose").addEventListener("click", () =>
perform(() => call("predict"), "Jev is comparing the actions…"),
);
$("execute").addEventListener("click", () =>
perform(
() => call("act", { fingerprint: state.page.fingerprint }),
"Executing the choice…",
),
);
$("auto").addEventListener("click", () =>
perform(async () => {
automatic = true;
controls();
for (let i = 0; i < state.max_steps * 2 && automatic; i++) {
$("status").textContent = "Running…";
if ($("pace").checked) {
await call("predict");
await new Promise(resolve => setTimeout(resolve, 450));
if (!automatic) break;
await call("act", {fingerprint: state.page.fingerprint});
} else {
await call("tick");
}
if (["done", "blocked"].includes(state.status)) break;
}
automatic = false;
}, "Running the browser…"),
);
$("stop").addEventListener("click", () => {
automatic = false;
$("status").textContent = "Pausing after the current request…";
controls();
});
$("overlays").addEventListener("change", () => {
$("targets").hidden = !$("overlays").checked;
});
$("choices").addEventListener("pointerover", (event) => {
const id = event.target.closest("[data-action]")?.dataset.action;
document
.querySelectorAll(".target")
.forEach((t) =>
t.classList.toggle(
"selected",
t.dataset.action === id || t.dataset.action === state?.decision?.target?.split(':')[0],
),
);
});
$("choices").addEventListener("pointerleave", () =>
document
.querySelectorAll(".target")
.forEach((t) =>
t.classList.toggle(
"selected",
t.dataset.action === state?.decision?.target?.split(':')[0],
),
),
);
$("download").addEventListener("click", () => {
const { page, ...rest } = state;
const blob = new Blob(
[
JSON.stringify(
{ ...rest, page: { ...page, screenshot: undefined } },
null,
2,
),
],
{ type: "application/json" },
);
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = "typesafe-browser-trace.json";
a.click();
URL.revokeObjectURL(url);
});
fetch("/api/state")
.then((r) => r.json())
.then((s) => {
state = s;
render();
})
.catch(() => {
$("status").textContent = "Cannot reach local demo server";
});
"""One live measured flight search; freeze source externally to compare revisions."""
import argparse
import hashlib
import json
import os
import sys
import time
from collections import defaultdict
from pathlib import Path
parser = argparse.ArgumentParser()
parser.add_argument("--source", default=".")
parser.add_argument("--output", required=True)
args = parser.parse_args()
source = Path(args.source).resolve()
sys.path.insert(0, str(source))
from jev_ultrafast import Agent # noqa: E402
from jev_ultrafast import browser as browser_module # noqa: E402
sys.path.append(str(Path(__file__).resolve().parents[1]))
from examples.flights import GOALS, URL, verify # noqa: E402
folder = Path(args.output)
folder.mkdir(parents=True, exist_ok=False)
source_hashes = {
p.name: hashlib.sha256(p.read_bytes()).hexdigest()
for p in (source / "jev_ultrafast").iterdir() if p.suffix in {".py", ".js"}
}
raw = browser_module.cdp
calls = defaultdict(list)
def timed(method, *positional, **kwargs):
t = time.perf_counter()
result = raw(method, *positional, **kwargs)
calls[method].append(round((time.perf_counter() - t) * 1000, 3))
return result
browser_module.cdp = timed
agent = Agent(URL, GOALS)
# Setup is excluded in both arms, as in the original demo.
calls.clear()
error = None
try:
for state in agent.run():
last = state["history"][-1] if state["history"] else {}
print(state["elapsed_ms"], state["status"], last.get("action", ""), flush=True)
except Exception as exc:
error = f"{type(exc).__name__}: {exc}"
finally:
state = agent.snapshot()
measured_calls = {method: {"count": len(times), "ms": round(sum(times), 3)} for method, times in calls.items()}
# Both arms use a NEW final observation for the independent result check, outside timing.
final = agent.browser.observe(screenshot=True)
state["verification"] = verify(final)
state["error"] = error
state["cdp"] = measured_calls
state["source_hashes"] = source_hashes
state["task_hash"] = hashlib.sha256(json.dumps([URL, GOALS]).encode()).hexdigest()
state["configuration"] = {
key: os.environ.get(key)
for key in ("TYPESAFE_MODEL", "TEXT_MODEL", "TEXT_MODEL_BASE_URL", "TEXT_MODEL_REASONING")
}
state["browser_version"] = agent.browser.call("Browser.getVersion")["product"]
state["final_page"] = final
(folder / "state.json").write_text(json.dumps(state, indent=2))
agent.close()
print("VERIFIED", state["verification"]["passed"], "ERROR", error, flush=True)
"""Render the actual Google Flights screencast at 1x, including every loading wait."""
import argparse
import json
import statistics
import subprocess
from pathlib import Path
from PIL import Image, ImageDraw, ImageFont
ROOT = Path(__file__).resolve().parents[1]
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("source", type=Path, help="Exact verified recording directory")
args = parser.parse_args()
source = args.source.resolve()
state = json.loads((source / "state.json").read_text())
assert state["verification"]["passed"] and not state["recording_errors"]
frames = [(0, Image.open(source / "frames/000000.jpg").convert("RGB"))]
frames += sorted((int(p.stem), Image.open(p).convert("RGB")) for p in (source / "screencast").glob("*.jpg"))
end = state["elapsed_ms"]
folder = source / "video-frames"
folder.mkdir(parents=True, exist_ok=False)
font_path = "/System/Library/Fonts/Supplemental/Arial.ttf"
font_bold = "/System/Library/Fonts/Supplemental/Arial Bold.ttf"
def font(n, bold=False):
return ImageFont.truetype(font_bold if bold else font_path, n)
def mono(n):
return ImageFont.truetype("/System/Library/Fonts/Menlo.ttc", n)
ink, muted, green = "#172a20", "#6a766c", "#2a743f"
steps = [
("One way", "One way"),
("Zürich", "Zürich, Switzerland"),
("London", "London, United Kingdom"),
("20 September", "Done. Search"),
("Search flights", "Search"),
]
for i in range(round((end + 500) * 30 / 1000)):
t = min(end, round(i * 1000 / 30))
screenshot = next(im for ts, im in reversed(frames) if ts <= t)
canvas = Image.new("RGB", (1536, 1000), "#f3f4ec")
d = ImageDraw.Draw(canvas)
d.text((36, 26), "browser use", font=font(23, True), fill=ink)
d.text((186, 27), "× TypeSafe", font=font(22), fill=muted)
d.rounded_rectangle((1287, 24, 1499, 59), radius=17, fill="#dfebd9")
d.text((1310, 32), "REAL WEB · 1× SPEED", font=font(14, True), fill=green)
d.text((36, 80), f"Zürich → London. In {end / 1000:.1f} seconds.", font=font(43, True), fill=ink)
d.text((38, 139), "One goal. Dynamic elements. LLM-generated text.", font=font(20), fill=muted)
d.rounded_rectangle((35, 191, 1157, 943), radius=14, fill="#202124")
for j, c in enumerate(["#de8278", "#d6bd6e", "#8dbd8a"]):
d.ellipse((54 + j * 19, 205, 63 + j * 19, 214), fill=c)
d.text((145, 201), "google.com/travel/flights", font=mono(13), fill="#d4d6d5")
# Omit Google account controls in every frame. No content from the task area is redrawn.
canvas.paste(screenshot.crop((0, 64, 1120, 780)), (36, 226))
d.text((1192, 206), "JEV ULTRAFAST", font=font(16, True), fill=green)
d.text((1189, 242), f"{t / 1000:05.2f}", font=mono(52), fill=ink)
d.text((1193, 307), "SECONDS ELAPSED", font=font(13, True), fill=muted)
history = [h for h in state["history"] if h["executed_ms"] <= t]
for j, (label, key) in enumerate(steps):
done = any(h["action"] == key or (key == "Done. Search" and h["action"].startswith(key)) for h in history)
y = 370 + j * 54
d.ellipse((1194, y, 1218, y + 24), fill=green if done else "#e0e4d9")
if done:
d.line([(1200, y + 12), (1204, y + 16), (1212, y + 8)], fill="white", width=2)
d.text((1236, y - 1), label, font=font(21, done), fill=ink if done else muted)
waiting = t >= next(h["executed_ms"] for h in state["history"] if h["action"] == "Search") and t < end
final = t >= end
d.rounded_rectangle((1189, 670, 1499, 789), radius=14, fill="#dfeeda" if final else "#e7e9df")
title = "Flights found" if final else "Waiting for Google…" if waiting else "Choose. Act. Repeat."
d.text((1209, 691), title, font=font(22, True), fill=green if final else ink)
subtitle = (
"Route + date verified"
if final
else "Loading stays in the video"
if waiting
else f"{len(history)} actions executed"
)
d.text((1209, 734), subtitle, font=font(16), fill=muted)
latencies = [x["latency_ms"] for x in state["decisions"] if x["elapsed_ms"] <= t]
latency = f"{statistics.median(latencies):.0f} ms" if latencies else "—"
d.text((1194, 835), latency, font=mono(30), fill=ink)
d.text((1194, 878), "median decision latency", font=font(16), fill=muted)
d.line((37, 960, 1498, 960), fill="#d3d9cc", width=2)
d.line((37, 960, 37 + (1498 - 37) * t / end, 960), fill=green, width=3)
d.text(
(37, 973),
f"Operation + index by Jev. Text by {state['text_calls'][0]['model'].split('/')[-1]}. "
"Original timing; waits included.",
font=font(14),
fill=muted,
)
d.text((1194, 973), "github.com/browser-use/jev-ultrafast", font=font(12), fill=muted)
canvas.save(folder / f"{i:04d}.png")
canvas.save(ROOT / "docs/flights-result.png")
subprocess.run(
[
"ffmpeg",
"-y",
"-loglevel",
"error",
"-framerate",
"30",
"-i",
str(folder / "%04d.png"),
"-c:v",
"libx264",
"-pix_fmt",
"yuv420p",
"-crf",
"18",
"-movflags",
"+faststart",
str(ROOT / "docs/demo.mp4"),
],
check=True,
)
subprocess.run(
[
"ffmpeg",
"-y",
"-loglevel",
"error",
"-i",
str(ROOT / "docs/demo.mp4"),
"-vf",
"fps=12,scale=1152:-1:flags=lanczos,split[a][b];[a]palettegen[p];[b][p]paletteuse",
"-loop",
"0",
str(ROOT / "docs/demo.gif"),
],
check=True,
)
print("Rendered", len(frames), "source frames at original timing:", end, "ms, plus a 500ms end hold.")
"""Render recorded fixture frames at their original timestamps. No acceleration."""
import json
import subprocess
from pathlib import Path
from PIL import Image, ImageDraw, ImageFont
ROOT = Path(__file__).resolve().parents[1]
source = ROOT / "artifacts/final"
state = json.loads((source / "travel-1.json").read_text())
frames = sorted((int(p.stem), Image.open(p).convert("RGB")) for p in (source / "frames").glob("*.jpg"))
end_ms = state["elapsed_ms"]
folder = ROOT / "artifacts/video-frames"
folder.mkdir(parents=True, exist_ok=True)
font_path = "/System/Library/Fonts/Menlo.ttc"
font = ImageFont.truetype(font_path, 23)
small = ImageFont.truetype(font_path, 17)
images = []
# 750 ms lead-in and 1,250 ms endpoint hold; action time itself is unmodified.
for index in range(round((end_ms + 2000) * 30 / 1000)):
t = min(end_ms, max(0, round(index * 1000 / 30) - 750))
frame = next(image for timestamp, image in reversed(frames) if timestamp <= t)
canvas = Image.new("RGB", (1240, 960), "#f5f5ed")
canvas.paste(frame, (60, 105))
draw = ImageDraw.Draw(canvas)
draw.text((60, 34), "BROWSER USE × TYPESAFE", font=font, fill="#283c2c")
draw.text((945, 38), f"{t / 1000:0.2f}s / 1×", font=small, fill="#487645")
step = sum(h["elapsed_ms"] <= t for h in state["history"])
draw.text((60, 909), f"Jev Ultrafast {step}/5 browser actions Live API calls", font=small, fill="#64745c")
canvas.save(folder / f"{index:04d}.png")
images.append(canvas.resize((930, 720)))
images[0].save(
ROOT / "docs/fixture-demo.gif", save_all=True, append_images=images[1:], duration=1000 / 30, loop=0, optimize=True
)
subprocess.run(
[
"ffmpeg",
"-y",
"-loglevel",
"error",
"-framerate",
"30",
"-i",
str(folder / "%04d.png"),
"-c:v",
"libx264",
"-pix_fmt",
"yuv420p",
"-crf",
"18",
"-movflags",
"+faststart",
str(ROOT / "docs/fixture-demo.mp4"),
],
check=True,
)
print("Rendered 1× footage from", len(frames), "recorded observations; action time:", end_ms, "ms")
"""Offline contracts for a dynamic operation/target policy. No paid APIs."""
import json
import time
from copy import deepcopy
from unittest.mock import Mock
import pytest
from jev_ultrafast import agent as loop
from jev_ultrafast import model
from jev_ultrafast.browser import StalePage, browser_operation, fingerprint
def page():
state = {
"url": "https://example.test/",
"title": "Search",
"text": "Search",
"scroll": {"y": 0},
"actions": [
{"id": "e1", "kind": "fill", "label": "Search", "role": "textbox", "value": "", "node": 10},
{"id": "e2", "kind": "click", "label": "Open Search", "role": "textbox", "value": "", "node": 10},
{"id": "e3", "kind": "click", "label": "Go", "role": "button", "value": "", "node": 20},
{"id": "wait", "kind": "wait", "label": "Wait"},
],
}
state["fingerprint"] = fingerprint(state)
return state
def choice(ids, selected):
return {"choice": selected, "confidence": 1.0, "probabilities": {i: float(i == selected) for i in ids}}
def decision(action="e1"):
return {
"choice": action,
"operation": "TYPE_TEXT",
"target": "1",
"confidence": 1.0,
"probabilities": {action: 1.0},
"latency_ms": 10,
"usage": {},
}
@pytest.mark.parametrize("mutation", ["unknown", "nan", "missing", "negative", "non_max", "confidence"])
def test_invalid_choice_is_rejected(mutation):
a = choice(["a", "b"], "a")
if mutation == "unknown":
a["choice"] = "invented"
elif mutation == "nan":
a["probabilities"]["a"] = float("nan")
elif mutation == "missing":
del a["probabilities"]["b"]
elif mutation == "negative":
a["probabilities"]["b"] = -1
elif mutation == "non_max":
a["choice"] = "b"
else:
a["confidence"] = 5
with pytest.raises(ValueError, match="Invalid TypeSafe"):
model.validate_choice(a, {"a", "b"})
def test_one_index_per_node_with_operation_specific_targets():
elements, targets, controls = model.action_space(page()["actions"])
assert len(elements) == 2
assert elements[0]["operations"] == ["TYPE_TEXT", "CLICK"]
assert targets["TYPE_TEXT"]["1"]["id"] == "e1"
assert targets["CLICK"]["1"]["id"] == "e2"
assert targets["CLICK"]["2"]["id"] == "e3"
assert "WAIT" in controls
def test_all_heads_are_one_request_and_only_matching_head_executes(monkeypatch):
calls = []
def post(_url, _key, body):
calls.append(body)
return {
"model": "test",
"answers": {
"operation": choice(body["questions"]["operation"]["criteria"], "TYPE_TEXT"),
"type_text_target": choice(["1"], "1"),
"click_target": {"choice": "invented"},
},
}
monkeypatch.setenv("TYPESAFE_API_KEY", "test")
monkeypatch.setattr(model, "post_json", post)
d = model.choose(page(), "Find a book", [])
assert len(calls) == 1
assert d["operation"] == "TYPE_TEXT" and d["target"] == "1" and d["choice"] == "e1"
assert set(calls[0]["questions"]) == {"operation", "click_target", "type_text_target"}
def test_click_cannot_consume_a_text_target(monkeypatch):
def post(_url, _key, body):
return {
"model": "test",
"answers": {
"operation": choice(body["questions"]["operation"]["criteria"], "CLICK"),
"type_text_target": choice(["1"], "1"),
"click_target": choice(["1", "2", "999"], "999"),
},
}
monkeypatch.setenv("TYPESAFE_API_KEY", "test")
monkeypatch.setattr(model, "post_json", post)
with pytest.raises(ValueError, match="Invalid TypeSafe"):
model.choose(page(), "Find a book", [])
def test_target_head_receives_control_state_and_full_next_step_rules(monkeypatch):
p = page()
p["actions"].insert(0, {
"id": "toggle", "kind": "click", "label": "Free cancellation", "node": 30,
"role": "checkbox", "checked": "true", "selected": False,
})
def post(_url, _key, body):
questions = body["questions"]
target = questions["click_target"]
assert target["criteria"]["1"]["checked"] == "true"
assert target["criteria"]["1"]["selected"] is False
assert questions["operation"]["instructions"]["rules"] in target["instructions"]["rules"]
return {
"model": "test",
"answers": {
"operation": choice(questions["operation"]["criteria"], "CLICK"),
"click_target": choice(target["criteria"], "3"),
},
}
monkeypatch.setenv("TYPESAFE_API_KEY", "test")
monkeypatch.setattr(model, "post_json", post)
d = model.choose(p, "Search with free cancellation", [])
assert d["choice"] == "e3"
def test_quoted_task_text_still_uses_the_llm(monkeypatch):
monkeypatch.setenv("TEXT_MODEL_API_KEY", "test")
post = Mock(return_value={"choices": [{"message": {"content": '{"text":"Zurich"}'}}]})
monkeypatch.setattr(model, "post_json", post)
context = model.field_context('Fly from "Zurich" to London', page()["actions"][0], page(), [])
assert model.field_text(context)[0] == "Zurich"
assert post.call_count == 1
sent = json.loads(post.call_args.args[2]["messages"][1]["content"])
assert sent["goal"] == 'Fly from "Zurich" to London'
def test_missing_text_credential_stops_before_guessing(monkeypatch):
monkeypatch.delenv("TEXT_MODEL_API_KEY", raising=False)
with pytest.raises(ValueError, match="TEXT_MODEL_API_KEY"):
model.field_text({"goal": 'Enter "Zurich"'})
@pytest.fixture
def runner():
a = loop.Agent.__new__(loop.Agent)
a.screenshots = False
a.pending_text = None
p = page()
a.state = {
"browser": Mock(fresh=Mock(return_value=True), observe=Mock(return_value=p)),
"page": p,
"decision": decision(),
"goal": "Find a book",
"history": [],
"decisions": [],
"status": "predicted",
"started_at": time.perf_counter(),
"record": False,
"text_calls": [],
}
return a
def test_stale_decision_is_consumed_before_any_mutation(runner):
runner.state["browser"].fresh.return_value = False
with pytest.raises(StalePage):
runner.command("act", {"fingerprint": runner.state["page"]["fingerprint"]})
runner.state["browser"].act.assert_not_called()
assert runner.state["decision"] is None
def test_generated_text_reused_only_for_identical_retry_context(runner, monkeypatch):
helper = Mock(return_value=("book", {"model": "test", "latency_ms": 10}))
monkeypatch.setattr(loop, "field_text", helper)
runner.state["browser"].act.side_effect = [StalePage("Changed before input"), None]
with pytest.raises(StalePage):
runner.command("act", {"fingerprint": runner.state["page"]["fingerprint"]})
runner.state["decision"] = decision()
runner.command("act", {"fingerprint": runner.state["page"]["fingerprint"]})
assert helper.call_count == 1
assert runner.state["browser"].act.call_count == 2 # The first call rejects before any browser input.
assert runner.pending_text is None
def test_changed_field_context_does_not_reuse_generated_text(runner, monkeypatch):
helper = Mock(return_value=("book", {"model": "test", "latency_ms": 10}))
monkeypatch.setattr(loop, "field_text", helper)
runner.state["browser"].act.side_effect = [StalePage("Changed before input"), None]
with pytest.raises(StalePage):
runner.command("act", {"fingerprint": runner.state["page"]["fingerprint"]})
runner.state["page"]["text"] = "Different page context"
runner.state["decision"] = decision()
runner.command("act", {"fingerprint": runner.state["page"]["fingerprint"]})
assert helper.call_count == 2
def test_loading_waits_do_not_trigger_no_progress_stop(runner):
for _ in range(5):
runner.state["decision"] = decision("wait")
runner.command("act", {"fingerprint": runner.state["page"]["fingerprint"]})
assert len(runner.state["history"]) == 5 and runner.state["status"] == "ready"
def test_stale_observation_preserves_executed_action(runner):
runner.state["decision"] = decision("e3")
runner.state["browser"].observe.side_effect = StalePage("changed")
with pytest.raises(StalePage):
runner.command("act", {"fingerprint": runner.state["page"]["fingerprint"]})
assert runner.state["history"][-1]["action"] == "Go"
runner.state["browser"].act.assert_called_once()
def test_observation_is_one_atomic_browser_read(monkeypatch):
import jev_ultrafast.browser as browser
p = page()
cdp = Mock(return_value={"result": {"value": p}})
monkeypatch.setattr(browser, "cdp", cdp)
actual = browser_operation({"operation": "observe", "session": "test", "screenshot": False})
assert actual["actions"] == p["actions"]
assert cdp.call_count == 1
assert cdp.call_args.args[0] == "Runtime.evaluate"
def test_executor_rejects_a_stale_page_before_browser_input(monkeypatch):
import jev_ultrafast.browser as browser
b = browser.Browser.__new__(browser.Browser)
b.fresh = Mock(return_value=False)
operation = Mock()
monkeypatch.setattr(browser, "browser_operation", operation)
with pytest.raises(StalePage):
b.act(page()["actions"][0], page(), "book")
operation.assert_not_called()
@pytest.mark.parametrize("response", [{"exceptionDetails": {}}, {"result": {}}])
def test_interrupted_dropdown_mutation_cannot_be_retried_as_stale(monkeypatch, response):
import jev_ultrafast.browser as browser
# A navigation can destroy the evaluation result after the change event already fired.
if "exceptionDetails" in response:
response["exceptionDetails"] = {"text": "Execution context destroyed"}
cdp = Mock(return_value=response)
monkeypatch.setattr(browser, "cdp", cdp)
with pytest.raises(RuntimeError, match="Dropdown execution"):
browser_operation({"operation": "act", "session": "test", "action": {
"id": "e1", "kind": "select", "node": 1, "value": "Design",
}})
assert cdp.call_count == 1
def test_fingerprint_tracks_values_and_identity_not_screenshots():
p = page()
other = deepcopy(p)
other["screenshot"] = "changed"
assert fingerprint(p) == fingerprint(other)
other["actions"][0]["node"] = 99
assert fingerprint(p) != fingerprint(other)
@pytest.mark.parametrize("changed", ["Departure", "Where from?", "Where to?", "year"])
def test_flight_verification_rejects_wrong_trip(changed):
from examples.flights import verify
actual = {
"url": "https://www.google.com/travel/flights/search?tfs=example",
"text": "Track prices from Zürich to London departing 2026-09-20",
"actions": [
{"label": k, "value": v}
for k, v in [
("Change ticket type. One way", "One way"),
("Where from?", "Zürich"),
("Where to?", "London"),
("Departure", "Sun, Sep 20"),
("Nonstop flight on Sunday, September 20. Select flight", ""),
]
],
}
assert verify(actual)["passed"]
if changed == "year":
actual["text"] = actual["text"].replace("2026", "2027")
else:
next(a for a in actual["actions"] if a["label"] == changed)["value"] = "wrong"
assert not verify(actual)["passed"]
@pytest.mark.parametrize(
"content", ["Thinking: Zurich", '{"text":null}', '{"text":"Zurich","extra":true}', '{"text":123}']
)
def test_text_helper_rejects_invalid_values(monkeypatch, content):
monkeypatch.setenv("TEXT_MODEL_API_KEY", "test")
monkeypatch.setattr(model, "post_json", Mock(return_value={"choices": [{"message": {"content": content}}]}))
with pytest.raises(ValueError, match="nothing typed"):
model.field_text({"goal": "Find a flight"})
def test_navigation_during_prediction_reobserves_without_action(runner):
runner.state["browser"].fresh.side_effect = StalePage("Document navigating")
runner.command("tick")
assert runner.state["status"] == "ready"
assert runner.state["decision"] is None
runner.state["browser"].act.assert_not_called()