Skip to content

Commit 75f87f1

Browse files
pirategithub-actions[bot]miguelg719
authored
[STG-1045] Add logging at all 4 levels: agent.execute, agent.act/observe/extract, CLICK/HOVER/SCROLL, and CDP (#1283)
# why Clarify where the execution flow goes when stagehand runs by showing more detailed logs. <img width="1443" height="529" alt="image" src="https://github.com/user-attachments/assets/1c85f91e-de94-46c3-8226-fe42d4c3e338" /> # what changed Adds a log line printed at the beginning and end of each layer's execution: 1. 🅰 Agent TASK: top-level user intent: when agent.execute('<intent here>') is called (the initial entrypoint) 2. 🆂 Stagehand STEP: any call to .act(...) .extract() or .observe() 3. 🆄 Understudy ACTION: any playwright or browser interaction api action dispatched, e.g. CLICK, HOVER, SCROLL, etc. 4. 🧠 LLM req/resp, 🅲 CDP CALL/Event: any LLM calls or CDP websocket msgs to/from the browser Log lines are written to `./.browserbase/sessions/{sessionId}/{agent,stagehand,understudy,cdp}.log` at runtime, and can be followed in a single unified screen by doing: `tail -f ./.browserbase/sessions/latest/*.log` # test plan Test by running: ```bash # (make sure `OPENAI_API_KEY` and `ANTHROPIC_API_KEY` are both set in env too) export BROWSERBASE_CONFIG_DIR=./.browserbase nano packages/core/examples/flowLoggingJourney.ts # paste in contents (it's just a basic test of the main apis) pnpm tsx packages/core/examples/flowLoggingJourney.ts & tail -f ./.browserbase/sessions/latest/* ``` `flowLoggingJourney.ts`: ```typescript import { Stagehand } from "../lib/v3"; async function run(): Promise<void> { const openaiKey = process.env.OPENAI_API_KEY; const anthropicKey = process.env.ANTHROPIC_API_KEY; if (!openaiKey || !anthropicKey) { throw new Error( "Set both OPENAI_API_KEY and ANTHROPIC_API_KEY before running this demo.", ); } const stagehand = new Stagehand({ env: "LOCAL", verbose: 2, model: { modelName: "openai/gpt-4.1-mini", apiKey: openaiKey }, localBrowserLaunchOptions: { headless: true, args: ["--window-size=1280,720"], }, disablePino: true, }); try { await stagehand.init(); const [page] = stagehand.context.pages(); await page.goto("https://example.com/", { waitUntil: "load" }); // Test standard agent path const agent = stagehand.agent({ systemPrompt: "You are a QA assistant. Keep answers short and deterministic. Finish quickly.", }); const agentResult = await agent.execute( "Glance at the Example Domain page and confirm that you see the hero text.", ); console.log("Agent result:", agentResult); // Test CUA (Computer Use Agent) path await page.goto("https://example.com/", { waitUntil: "load" }); const cuaAgent = stagehand.agent({ cua: true, model: { modelName: "anthropic/claude-sonnet-4-5-20250929", apiKey: anthropicKey, }, }); const cuaResult = await cuaAgent.execute({ instruction: "Click on the 'More information...' link on the page.", maxSteps: 3, }); console.log("CUA Agent result:", cuaResult); const observations = await stagehand.observe("Find any links on the page"); console.log("Observe result:", observations); if (observations.length > 0) { await stagehand.act(observations[0]); } else { await stagehand.act("click the link on the page"); } const extraction = await stagehand.extract( "Summarize the current page title and contents in a single sentence", ); console.log("Extraction result:", extraction); } finally { await stagehand.close({ force: true }).catch(() => {}); } } run().catch((error) => { console.error(error); process.exitCode = 1; }); ``` EXPECTED OUTPUT: ```bash 2025-12-08 12:20:26.23300 ⤑ ⤑ [🆄 #694a GOTO] ▷ Page.goto({args:[https://example.com/,{waitUntil:load}]}) 2025-12-08 12:20:26.23401 ⤑ ⤑ [🆄 #694a GOTO] [🅲 #FE7B CDP] ⏵ Page.navigate({url:https://example.com/}) 2025-12-08 12:20:26.26402 ⤑ ⤑ [🆄 #694a GOTO] [🅲 #FE7B CDP] ⏴ Page.frameStartedNavigating({frameId:8A6B…FE7B,u…rId:F41F…7B31,navigationType:differentDocument}) 2025-12-08 12:20:26.26403 ⤑ ⤑ [🆄 #694a GOTO] [🅲 #FE7B CDP] ⏴ Page.frameStartedLoading({frameId:8A6B…FE7B}) 2025-12-08 12:20:26.57304 ⤑ ⤑ [🆄 #694a GOTO] [🅲 #FE7B CDP] ⏵ Page.setLifecycleEventsEnabled({enabled:true}) 2025-12-08 12:20:26.57605 ⤑ ⤑ [🆄 #694a GOTO] [🅲 #FE7B CDP] ⏴ Page.frameNavigated({frame:{id:8A6B…FE7B,loaderI…tIsolated,gatedAPIFeatures:[]},type:Navigation}) 2025-12-08 12:20:26.57706 ⤑ ⤑ [🆄 #694a GOTO] [🅲 #FE7B CDP] ⏴ Network.policyUpdated({}) 2025-12-08 12:20:26.57807 ⤑ ⤑ [🆄 #694a GOTO] [🅲 #FE7B CDP] ⏴ Runtime.consoleAPICalled({type:info,args:[{type:…ptId:5,url:",lineNumber:0,columnNumber:2837}]}}) 2025-12-08 12:20:26.57908 ⤑ ⤑ [🆄 #694a GOTO] [🅲 #FE7B CDP] ⏴ Page.domContentEventFired({timestamp:545864.312948}) 2025-12-08 12:20:26.58009 ⤑ ⤑ [🆄 #694a GOTO] [🅲 #FE7B CDP] ⏴ Page.loadEventFired({timestamp:545864.313355}) 2025-12-08 12:20:26.58110 ⤑ ⤑ [🆄 #694a GOTO] [🅲 #FE7B CDP] ⏴ Page.frameStoppedLoading({frameId:8A6B…FE7B}) 2025-12-08 12:20:26.58311 ⤑ ⤑ [🆄 #694a GOTO] [🅲 #FE7B CDP] ⏵ Runtime.evaluate({expression:document.readyState,contextId:2,returnByValue:true}) 2025-12-08 12:20:26.58412 ⤑ ⤑ [🆄 #694a GOTO] ✓ GOTO completed in 0.35s 2025-12-08 12:20:26.58513 [🅰 #1d66] ▷ Agent.execute(Glance at the Example Domain page and confirm that you see the hero text.) 2025-12-08 12:20:26.59314 [🅰 #1d66] ⤑ [🧠 #21e1 LLM] gpt-4.1-mini ⏴ user: Glance at the Example Domain page and confirm that you see the hero text. +{10 tools} 2025-12-08 12:20:29.44715 [🅰 #1d66] ⤑ [🧠 #21e1 LLM] gpt-4.1-mini ↳ ꜛ688 ꜜ12 | tool call: ariaTree() 2025-12-08 12:20:29.44816 [🅰 #1d66] [🆂 #9ac4 EXTRACT] ▷ Stagehand.extract() 2025-12-08 12:20:29.45317 [🅰 #1d66] [🆂 #9ac4 EXTRACT] ⤑ [🅲 #FE7B CDP] ⏵ DOM.getDocument({depth:-1,pierce:true}) 2025-12-08 12:20:29.46018 [🅰 #1d66] [🆂 #9ac4 EXTRACT] ⤑ [🅲 #FE7B CDP] ⏵ Accessibility.getFullAXTree({frameId:8A6B…FE7B}) 2025-12-08 12:20:29.46419 [🅰 #1d66] [🆂 #9ac4 EXTRACT] ✓ EXTRACT completed in 0.02s 2025-12-08 12:20:29.46520 [🅰 #1d66] ⤑ [🧠 #03a1 LLM] gpt-4.1-mini ⏴ tool result: ariaTree(): Accessibility Tre…7] paragraph [0-18] link: Learn more +{10 tools} 2025-12-08 12:20:32.21321 [🅰 #1d66] ⤑ [🧠 #03a1 LLM] gpt-4.1-mini ↳ ꜛ806 ꜜ34 | tool call: close() 2025-12-08 12:20:32.21422 [🅰 #1d66] ✓ Agent.execute() DONE in 5.6s | 2 LLM calls ꜛ1494 ꜜ46 tokens | 6 CDP msgs 2025-12-08 12:20:32.21523 ⤑ ⤑ [🆄 #cb65 GOTO] ▷ Page.goto({args:[https://example.com/,{waitUntil:load}]}) 2025-12-08 12:20:32.21524 ⤑ ⤑ [🆄 #cb65 GOTO] [🅲 #FE7B CDP] ⏵ Page.navigate({url:https://example.com/}) 2025-12-08 12:20:32.25425 ⤑ ⤑ [🆄 #cb65 GOTO] [🅲 #FE7B CDP] ⏴ Page.frameStartedNavigating({frameId:8A6B…FE7B,u…rId:2130…4BDE,navigationType:differentDocument}) 2025-12-08 12:20:32.25426 ⤑ ⤑ [🆄 #cb65 GOTO] [🅲 #FE7B CDP] ⏴ Page.frameStartedLoading({frameId:8A6B…FE7B}) 2025-12-08 12:20:32.25727 ⤑ ⤑ [🆄 #cb65 GOTO] [🅲 #FE7B CDP] ⏵ Page.setLifecycleEventsEnabled({enabled:true}) 2025-12-08 12:20:32.25828 ⤑ ⤑ [🆄 #cb65 GOTO] [🅲 #FE7B CDP] ⏴ DOM.scrollableFlagUpdated({nodeId:1,isScrollable:false}) 2025-12-08 12:20:32.25929 ⤑ ⤑ [🆄 #cb65 GOTO] [🅲 #FE7B CDP] ⏴ Page.frameNavigated({frame:{id:8A6B…FE7B,loaderI…tIsolated,gatedAPIFeatures:[]},type:Navigation}) 2025-12-08 12:20:32.26030 ⤑ ⤑ [🆄 #cb65 GOTO] [🅲 #FE7B CDP] ⏴ Network.policyUpdated({}) 2025-12-08 12:20:32.26031 ⤑ ⤑ [🆄 #cb65 GOTO] [🅲 #FE7B CDP] ⏴ DOM.documentUpdated({}) 2025-12-08 12:20:32.26032 ⤑ ⤑ [🆄 #cb65 GOTO] [🅲 #FE7B CDP] ⏴ Runtime.consoleAPICalled({type:info,args:[{type:…ptId:5,url:",lineNumber:0,columnNumber:2837}]}}) 2025-12-08 12:20:32.26133 ⤑ ⤑ [🆄 #cb65 GOTO] [🅲 #FE7B CDP] ⏴ DOM.documentUpdated({}) 2025-12-08 12:20:32.26134 ⤑ ⤑ [🆄 #cb65 GOTO] [🅲 #FE7B CDP] ⏴ Page.domContentEventFired({timestamp:545869.998129}) 2025-12-08 12:20:32.26135 ⤑ ⤑ [🆄 #cb65 GOTO] [🅲 #FE7B CDP] ⏴ Page.loadEventFired({timestamp:545869.998762}) 2025-12-08 12:20:32.26136 ⤑ ⤑ [🆄 #cb65 GOTO] [🅲 #FE7B CDP] ⏴ Page.frameStoppedLoading({frameId:8A6B…FE7B}) 2025-12-08 12:20:32.26237 ⤑ ⤑ [🆄 #cb65 GOTO] [🅲 #FE7B CDP] ⏵ Runtime.evaluate({expression:document.readyState,contextId:3,returnByValue:true}) 2025-12-08 12:20:32.26338 ⤑ ⤑ [🆄 #cb65 GOTO] ✓ GOTO completed in 0.05s 2025-12-08 12:20:32.26339 [🅰 #c756] ▷ Agent.execute({instruction:Click on the More information... link on the page.,maxSteps:3}) 2025-12-08 12:20:32.26440 [🅰 #c756] ⤑ ⤑ [🅲 #FE7B CDP] ⏵ Page.addScriptToEvaluateOnNewDocument({source:(() => …ue });\n setTimeout(install, 100);\n }\n })();}) 2025-12-08 12:20:32.26441 [🅰 #c756] ⤑ ⤑ [🅲 #FE7B CDP] ⏴ Accessibility.loadComplete({root:{nodeId:23,ignored:f…ds:[24],backendDOMNodeId:23,frameId:8A6B…FE7B}}) 2025-12-08 12:20:32.26542 [🅰 #c756] ⤑ ⤑ [🅲 #FE7B CDP] ⏵ Runtime.evaluate({expression:({ w: window.innerWidth,…ntextId:3,awaitPromise:true,returnByValue:true}) 2025-12-08 12:20:32.26543 [🅰 #c756] ⤑ ⤑ [🅲 #FE7B CDP] ⏵ Runtime.evaluate({expression:(() => {\n const ID = __… 100);\n }\n })();,includeCommandLineAPI:false}) 2025-12-08 12:20:32.26744 [🅰 #c756] ⤑ [🧠 #2798 LLM] claude-sonnet-4-5-20250929 ⏴ Click on the More information... link on the page. 2025-12-08 12:20:36.15745 [🅰 #c756] ⤑ [🧠 #2798 LLM] claude-sonnet-4-5-20250929 ↳ ꜛ1875 ꜜ79 | Ill help you click on the More information... l tool_use:computer 2025-12-08 12:20:36.96146 [🅰 #c756] ⤑ [🆄 #f55d SCREENSHOT] ▷ Page.screenshot({args:[{fullPage:false}]}) 2025-12-08 12:20:36.96447 [🅰 #c756] ⤑ [🆄 #f55d SCREENSHOT] [🅲 #FE7B CDP] ⏵ Runtime.evaluate({expression:(() …ntextId:3,awaitPromise:true,returnByValue:true}) 2025-12-08 12:20:36.96648 [🅰 #c756] ⤑ [🆄 #f55d SCREENSHOT] [🅲 #FE7B CDP] ⏵ Page.captureScreenshot({format:png,fromSurface:true,captureBeyondViewport:false}) 2025-12-08 12:20:37.01149 [🅰 #c756] ⤑ [🆄 #f55d SCREENSHOT] [🅲 #FE7B CDP] ⏵ Runtime.evaluate({expression:(() …ntextId:3,awaitPromise:true,returnByValue:true}) 2025-12-08 12:20:37.01250 [🅰 #c756] ⤑ [🆄 #f55d SCREENSHOT] ✓ SCREENSHOT completed in 0.05s 2025-12-08 12:20:37.01251 [🅰 #c756] ⤑ [🆄 #cce8 SCREENSHOT] ▷ Page.screenshot({args:[{fullPage:false}]}) 2025-12-08 12:20:37.01352 [🅰 #c756] ⤑ [🆄 #cce8 SCREENSHOT] [🅲 #FE7B CDP] ⏵ Runtime.evaluate({expression:(() …ntextId:3,awaitPromise:true,returnByValue:true}) 2025-12-08 12:20:37.01453 [🅰 #c756] ⤑ [🆄 #cce8 SCREENSHOT] [🅲 #FE7B CDP] ⏵ Page.captureScreenshot({format:png,fromSurface:true,captureBeyondViewport:false}) 2025-12-08 12:20:37.04054 [🅰 #c756] ⤑ [🆄 #cce8 SCREENSHOT] [🅲 #FE7B CDP] ⏵ Runtime.evaluate({expression:(() …ntextId:3,awaitPromise:true,returnByValue:true}) 2025-12-08 12:20:37.04155 [🅰 #c756] ⤑ [🆄 #cce8 SCREENSHOT] ✓ SCREENSHOT completed in 0.03s 2025-12-08 12:20:37.04156 [🅰 #c756] ⤑ [🧠 #ce80 LLM] claude-sonnet-4-5-20250929 ⏴ Current URL: https://example.com/ +{15.8kb image} 2025-12-08 12:20:44.82757 [🅰 #c756] ⤑ [🧠 #ce80 LLM] claude-sonnet-4-5-20250929 ↳ ꜛ3192 ꜜ192 | I can see a pag…ith Example Domain as the head tool_use:computer 2025-12-08 12:20:45.12958 [🅰 #c756] ⤑ [🆄 #f8c3 V3CUA.SCROLL] ▷ v3CUA.scroll({target:(644, 400),args:[{type:sc…scroll_amount:3,pageUrl:https://example.com/}]}) 2025-12-08 12:20:45.12959 [🅰 #c756] ⤑ [🆄 #3fc9 SCROLL] [🅲 #FE7B CDP] ⏵ Runtime.evaluate({expression:typeof w…"undefined\"&&window.__v3Cursor.move(644, 400)}) 2025-12-08 12:20:45.12960 [🅰 #c756] ⤑ [🆄 #3fc9 SCROLL] ▷ Page.scroll({args:[644,400,0,300]}) 2025-12-08 12:20:45.13061 [🅰 #c756] ⤑ [🆄 #3fc9 SCROLL] [🅲 #FE7B CDP] ⏵ Input.dispatchMouseEvent({type:mouseMoved,x:644,y:400,button:none}) 2025-12-08 12:20:45.13762 [🅰 #c756] ⤑ [🆄 #3fc9 SCROLL] [🅲 #FE7B CDP] ⏵ Input.dispatchMouseEvent({type:mouseW…el,x:644,y:400,button:none,deltaX:0,deltaY:300}) 2025-12-08 12:20:45.14663 [🅰 #c756] ⤑ [🆄 #3fc9 SCROLL] ✓ SCROLL completed in 0.02s 2025-12-08 12:20:45.64764 [🅰 #c756] ⤑ [🆄 #ccb0 SCREENSHOT] ▷ Page.screenshot({args:[{fullPage:false}]}) 2025-12-08 12:20:45.64965 [🅰 #c756] ⤑ [🆄 #ccb0 SCREENSHOT] [🅲 #FE7B CDP] ⏵ Runtime.evaluate({expression:(() …ntextId:3,awaitPromise:true,returnByValue:true}) 2025-12-08 12:20:45.65266 [🅰 #c756] ⤑ [🆄 #ccb0 SCREENSHOT] [🅲 #FE7B CDP] ⏵ Page.captureScreenshot({format:png,fromSurface:true,captureBeyondViewport:false}) 2025-12-08 12:20:45.68567 [🅰 #c756] ⤑ [🆄 #ccb0 SCREENSHOT] [🅲 #FE7B CDP] ⏵ Runtime.evaluate({expression:(() …ntextId:3,awaitPromise:true,returnByValue:true}) 2025-12-08 12:20:45.68668 [🅰 #c756] ⤑ [🆄 #ccb0 SCREENSHOT] ✓ SCREENSHOT completed in 0.04s 2025-12-08 12:20:45.68769 [🅰 #c756] ⤑ [🆄 #87f4 SCREENSHOT] ▷ Page.screenshot({args:[{fullPage:false}]}) 2025-12-08 12:20:45.68770 [🅰 #c756] ⤑ [🆄 #87f4 SCREENSHOT] [🅲 #FE7B CDP] ⏵ Runtime.evaluate({expression:(() …ntextId:3,awaitPromise:true,returnByValue:true}) 2025-12-08 12:20:45.68971 [🅰 #c756] ⤑ [🆄 #87f4 SCREENSHOT] [🅲 #FE7B CDP] ⏵ Page.captureScreenshot({format:png,fromSurface:true,captureBeyondViewport:false}) 2025-12-08 12:20:45.71372 [🅰 #c756] ⤑ [🆄 #87f4 SCREENSHOT] [🅲 #FE7B CDP] ⏵ Runtime.evaluate({expression:(() …ntextId:3,awaitPromise:true,returnByValue:true}) 2025-12-08 12:20:45.71473 [🅰 #c756] ⤑ [🆄 #87f4 SCREENSHOT] ✓ SCREENSHOT completed in 0.03s 2025-12-08 12:20:45.71474 [🅰 #c756] ⤑ [🧠 #ed51 LLM] claude-sonnet-4-5-20250929 ⏴ Current URL: https://example.com/ +{15.8kb image} ``` --------- Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com> Co-authored-by: Nick Sweeting <pirate@users.noreply.github.com> Co-authored-by: Miguel <36487034+miguelg719@users.noreply.github.com>
1 parent a8a7c53 commit 75f87f1

File tree

14 files changed

+1539
-48
lines changed

14 files changed

+1539
-48
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ screenshot.png
99
.env
1010
downloads/
1111
dist/
12+
.browserbase/
1213
packages/evals/**/public
1314
packages/core/lib/dom/build/
1415
packages/core/lib/v3/dom/build/

packages/core/lib/v3/agent/AnthropicCUAClient.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ import { AgentClient } from "./AgentClient";
1818
import { compressConversationImages } from "./utils/imageCompression";
1919
import { toJsonSchema } from "../zodCompat";
2020
import type { StagehandZodSchema } from "../zodCompat";
21+
import {
22+
SessionFileLogger,
23+
formatCuaPromptPreview,
24+
formatCuaResponsePreview,
25+
} from "../flowLogger";
26+
import { v7 as uuidv7 } from "uuid";
2127

2228
export type ResponseInputItem = AnthropicMessage | AnthropicToolResult;
2329

@@ -480,6 +486,15 @@ export class AnthropicCUAClient extends AgentClient {
480486
requestParams.thinking = thinking;
481487
}
482488

489+
// Log LLM request
490+
const llmRequestId = uuidv7();
491+
SessionFileLogger.logLlmRequest({
492+
requestId: llmRequestId,
493+
model: this.modelName,
494+
operation: "CUA.getAction",
495+
prompt: formatCuaPromptPreview(messages),
496+
});
497+
483498
const startTime = Date.now();
484499
// Create the message using the Anthropic Messages API
485500
// @ts-expect-error - The Anthropic SDK types are stricter than what we need
@@ -492,6 +507,16 @@ export class AnthropicCUAClient extends AgentClient {
492507
inference_time_ms: elapsedMs,
493508
};
494509

510+
// Log LLM response
511+
SessionFileLogger.logLlmResponse({
512+
requestId: llmRequestId,
513+
model: this.modelName,
514+
operation: "CUA.getAction",
515+
output: formatCuaResponsePreview(response.content),
516+
inputTokens: response.usage.input_tokens,
517+
outputTokens: response.usage.output_tokens,
518+
});
519+
495520
// Store the message ID for future use
496521
this.lastMessageId = response.id;
497522

packages/core/lib/v3/agent/GoogleCUAClient.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@ import {
3030
convertToolSetToFunctionDeclarations,
3131
} from "./utils/googleCustomToolHandler";
3232
import { ToolSet } from "ai";
33+
import {
34+
SessionFileLogger,
35+
formatCuaPromptPreview,
36+
formatCuaResponsePreview,
37+
} from "../flowLogger";
38+
import { v7 as uuidv7 } from "uuid";
3339

3440
/**
3541
* Client for Google's Computer Use Assistant API
@@ -300,6 +306,15 @@ export class GoogleCUAClient extends AgentClient {
300306
let lastError: Error | null = null;
301307
let response: GenerateContentResponse | null = null;
302308

309+
// Log LLM request
310+
const llmRequestId = uuidv7();
311+
SessionFileLogger.logLlmRequest({
312+
requestId: llmRequestId,
313+
model: this.modelName,
314+
operation: "CUA.generateContent",
315+
prompt: formatCuaPromptPreview(compressedHistory),
316+
});
317+
303318
for (let attempt = 0; attempt < maxRetries; attempt++) {
304319
try {
305320
// Add exponential backoff delay for retries
@@ -357,6 +372,16 @@ export class GoogleCUAClient extends AgentClient {
357372
const elapsedMs = endTime - startTime;
358373
const { usageMetadata } = response;
359374

375+
// Log LLM response
376+
SessionFileLogger.logLlmResponse({
377+
requestId: llmRequestId,
378+
model: this.modelName,
379+
operation: "CUA.generateContent",
380+
output: formatCuaResponsePreview(response),
381+
inputTokens: usageMetadata?.promptTokenCount,
382+
outputTokens: usageMetadata?.candidatesTokenCount,
383+
});
384+
360385
// Process the response
361386
const result = await this.processResponse(response, logger);
362387

packages/core/lib/v3/agent/OpenAICUAClient.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@ import { ClientOptions } from "../types/public/model";
1414
import { AgentClient } from "./AgentClient";
1515
import { AgentScreenshotProviderError } from "../types/public/sdkErrors";
1616
import { ToolSet } from "ai";
17+
import {
18+
SessionFileLogger,
19+
formatCuaPromptPreview,
20+
formatCuaResponsePreview,
21+
} from "../flowLogger";
22+
import { v7 as uuidv7 } from "uuid";
1723

1824
/**
1925
* Client for OpenAI's Computer Use Assistant API
@@ -409,6 +415,15 @@ export class OpenAICUAClient extends AgentClient {
409415
requestParams.previous_response_id = previousResponseId;
410416
}
411417

418+
// Log LLM request
419+
const llmRequestId = uuidv7();
420+
SessionFileLogger.logLlmRequest({
421+
requestId: llmRequestId,
422+
model: this.modelName,
423+
operation: "CUA.getAction",
424+
prompt: formatCuaPromptPreview(inputItems),
425+
});
426+
412427
const startTime = Date.now();
413428
// Create the response using the OpenAI Responses API
414429
// @ts-expect-error - Force type to match what the OpenAI SDK expects
@@ -423,6 +438,16 @@ export class OpenAICUAClient extends AgentClient {
423438
inference_time_ms: elapsedMs,
424439
};
425440

441+
// Log LLM response
442+
SessionFileLogger.logLlmResponse({
443+
requestId: llmRequestId,
444+
model: this.modelName,
445+
operation: "CUA.getAction",
446+
output: formatCuaResponsePreview(response.output),
447+
inputTokens: response.usage.input_tokens,
448+
outputTokens: response.usage.output_tokens,
449+
});
450+
426451
// Store the response ID for future use
427452
this.lastResponseId = response.id;
428453

0 commit comments

Comments
 (0)