SPB Git forge

spb/doc-api

Public
2commits 1branches 0releases
15.7 MBsize
maindefault branch
14 days agolast push
Python 88.3% TypeScript 7.6% Shell 4.1%
3.1 KB · 52 lines typescript
Raw Blame History
1// Computer use loop skeleton (Node SDK, beta namespace for computer_20251124).2// STATUS: UNVERIFIED as a script (identical raw requests LIVE_VERIFIED 2026-09-18: tmp-live/tools/h1_*, h2_*, h4_*). Nothing is executed:3// executeAction is a stub returning a 1x1 PNG for screenshot/zoom. Run: node --env-file=.env --experimental-strip-types examples/anthropic/computer-use/computer_use_loop.ts4import Anthropic from "@anthropic-ai/sdk";5import { logRequest } from "../../shared/tool-loop/log.ts";67const client = new Anthropic();8const PNG = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==";9const NOT_EXECUTED = "Not executed: an earlier computer action in this turn failed.";10const useToolset = process.argv.includes("--toolset");11const model = useToolset ? "claude-sonnet-5" : "claude-sonnet-4-6";12const tools: any[] = useToolset13  ? [{ type: "computer_toolset_20260801", configs: { zoom: { enabled: false } } }]14  : [{ type: "computer_20251124", name: "computer", display_width_px: 1024, display_height_px: 768, display_number: 1 }];1516function executeAction(action: string, params: any): any {17  if (action === "screenshot" || action === "zoom") return [{ type: "image", source: { type: "base64", media_type: "image/png", data: PNG } }];18  if (action === "cursor_position") return "X=512, Y=384";19  if (["left_click", "right_click", "middle_click", "double_click", "triple_click", "mouse_move", "left_click_drag", "scroll", "type", "key", "hold_key", "wait", "left_mouse_down", "left_mouse_up"].includes(action)) return "OK"; // stub20  throw new Error(`Unknown action ${action}`);21}2223function processToolCalls(content: any[]): any[] {24  const results: any[] = [];25  let failed = false;26  for (const b of content) {27    if (b.type !== "tool_use") continue;28    const member = b.toolset_name === "computer";29    if (!member && b.name !== "computer") continue;30    const action = member ? b.name : b.input.action;31    const r: any = { type: "tool_result", tool_use_id: b.id, ...(member ? { toolset_name: "computer" } : {}) };32    if (failed) Object.assign(r, { content: NOT_EXECUTED, is_error: true });33    else try { r.content = executeAction(action, b.input); } catch (e) { Object.assign(r, { content: `Error: ${(e as Error).message}`, is_error: true }); failed = true; }34    results.push(r);35  }36  return results;37}3839const messages: any[] = [{ role: "user", content: "Take a screenshot." }];40let maxTokens = 100;41for (let i = 0; i < 2; i++) {42  const params: any = { model, max_tokens: maxTokens, tools, messages };43  const resp: any = useToolset ? await client.messages.create(params) : await client.beta.messages.create({ ...params, betas: ["computer-use-2025-11-24"] });44  logRequest("anthropic", "POST", "/v1/messages", 200, 0.007, `computer_use_loop.ts iter ${i}`);45  messages.push({ role: "assistant", content: resp.content });46  console.log(i, resp.stop_reason, resp.content.filter((b: any) => b.type === "tool_use").map((b: any) => [b.name, b.toolset_name, b.input]));47  const results = processToolCalls(resp.content);48  if (!results.length || resp.stop_reason !== "tool_use") break;49  messages.push({ role: "user", content: results });50  maxTokens = 50;51}52