@anthropic-ai/sdk
Version:
The official TypeScript library for the Anthropic API
185 lines (161 loc) • 6.85 kB
text/typescript
/**
* The computer toolset's members: the names and input types, what each member returns, the registry row per member,
* and the function that copies the model's input.
*
* The member names and every input type are the API types in `resources/beta`. A member's result kind is kept by hand.
* So is the confirmation text the model reads after a pure action. Neither is in the API types. A test diffs the
* member set against the published toolset definition so the two cannot drift silently.
*/
import type {
BetaComputerMemberInput,
BetaComputerMemberName,
BetaResponseComputerToolUseBlock,
} from '../../../resources/beta';
import {
buildMembers,
type BetaScreenshotResult,
type KindResultOf,
type MemberRow,
type Registry,
type ResultKind,
type ToolsetMember,
type TypedResultOf,
} from './core';
export const COMPUTER_FAMILY = 'computer' as const;
export const COMPUTER_TOOLSET_TYPE = 'computer_toolset_20260801' as const;
// The generated member-name union, re-exported for the modules beside this one.
export type { BetaComputerMemberName };
// The toolset modules import these five API types from here.
export type {
BetaComputerMemberInput,
BetaComputerCursorPositionInput,
BetaComputerLeftMouseDownInput,
BetaComputerLeftMouseUpInput,
BetaComputerScreenshotInput,
} from '../../../resources/beta';
/** Each computer member's input type, by member name. */
export type ComputerMemberInputs = {
[K in BetaComputerMemberName]: Extract<BetaResponseComputerToolUseBlock, { name: K }>['input'];
};
// --- results -----------------------------------------------------------------------------------------------
/** Where the cursor is, in screenshot pixels. Rendered as `X={x},Y={y}`. */
export interface BetaComputerCursorPositionResult {
x: number;
y: number;
}
/** Anything a computer member may return: `execute`'s un-narrowed result type. */
export type BetaComputerMemberResult =
| BetaScreenshotResult
| BetaComputerCursorPositionResult
| string
| void;
/**
* What each computer member's implementation returns. A pure action returns nothing, or one line of text the model
* reads in a text block of its own after the SDK's acknowledgment.
*/
export interface ComputerMemberResults {
key: void | string;
hold_key: void | string;
type: void | string;
cursor_position: BetaComputerCursorPositionResult;
mouse_move: void | string;
left_mouse_down: void | string;
left_mouse_up: void | string;
left_click: void | string;
left_click_drag: void | string;
right_click: void | string;
middle_click: void | string;
double_click: void | string;
triple_click: void | string;
scroll: void | string;
wait: void | string;
screenshot: BetaScreenshotResult;
zoom: BetaScreenshotResult;
}
// The result map must cover exactly the member names the API declares; a member in one without the
// other fails here.
type AssertSameKeys<A, B> =
[keyof A] extends [B] ?
[B] extends [keyof A] ?
true
: never
: never;
const _computerKeys: AssertSameKeys<ComputerMemberResults, BetaComputerMemberName> = true;
void _computerKeys;
// --- the registry ------------------------------------------------------------------------------------------
/** One member of the computer toolset. */
export type ComputerMember = ToolsetMember<BetaComputerMemberName, ComputerResultKind>;
// Hand-kept: result kinds and confirmation templates. Every member is on by default. A member missing here (or an
// extra one) fails to compile.
const ROWS = {
key: ['none', 'Pressed {text}.', true],
hold_key: ['none', 'Held {text} for {duration}s.', true],
type: ['none', 'Typed.', true],
cursor_position: ['point', null, true],
mouse_move: ['none', 'Moved the mouse.', true],
left_mouse_down: ['none', 'Left mouse button pressed.', true],
left_mouse_up: ['none', 'Left mouse button released.', true],
left_click: ['none', 'Clicked.', true],
left_click_drag: ['none', 'Dragged.', true],
right_click: ['none', 'Right-clicked.', true],
middle_click: ['none', 'Middle-clicked.', true],
double_click: ['none', 'Double-clicked.', true],
triple_click: ['none', 'Triple-clicked.', true],
scroll: ['none', 'Scrolled {scroll_direction}.', true],
wait: ['none', 'Waited {duration}s.', true],
screenshot: ['screenshot', null, true],
zoom: ['screenshot', null, true],
} as const satisfies { readonly [K in BetaComputerMemberName]: MemberRow };
/** The result kinds the rows above use. */
export type ComputerResultKind = (typeof ROWS)[BetaComputerMemberName][0];
/** The declared result (`ComputerMemberResults`) of every member the rows above give result kind `R`. */
export type ComputerKindResult<R extends ResultKind> = KindResultOf<
BetaComputerMemberName,
typeof ROWS,
ComputerMemberResults,
R
>;
/** A computer member's result with its result kind, which says how to read it. */
export type ComputerTypedResult<R extends ComputerResultKind = ComputerResultKind> = TypedResultOf<
BetaComputerMemberName,
typeof ROWS,
ComputerMemberResults,
R
>;
/**
* `value` typed as what a computer member of result kind `kind` returns: the one place the driver's declared result
* type is taken at its word.
*/
export function typedComputerResult<R extends ComputerResultKind>(
kind: R,
value: ComputerKindResult<R>,
): ComputerTypedResult<R> {
return { kind, value };
}
type RowName = keyof typeof ROWS;
/**
* Every computer member name, in the order of `ROWS`. Built from the table, not imported from
* `BETA_COMPUTER_MEMBER_NAME_VALUES`, so the toolset modules do not load `resources/beta/messages/messages`.
*/
export const COMPUTER_MEMBER_NAMES: ReadonlyArray<RowName> = /* @__PURE__ */ Object.keys(ROWS) as RowName[];
/** Every computer member, in the order of `ROWS`. */
export const COMPUTER_MEMBERS: ReadonlyMap<BetaComputerMemberName, ComputerMember> =
/* @__PURE__ */ buildMembers(COMPUTER_MEMBER_NAMES, ROWS);
// The API's member data marks no computer tool as needing `confirm`, so this list is the SDK's own.
export const COMPUTER_CONFIRM_REQUIRED: ReadonlySet<string> = /* @__PURE__ */ new Set([
'type',
'key',
'hold_key',
]);
/** The computer registry as the shared toolset core reads it. No member is off by default. */
export const COMPUTER_REGISTRY: Registry<BetaComputerMemberName, ComputerMember> = {
family: COMPUTER_FAMILY,
names: COMPUTER_MEMBER_NAMES,
members: COMPUTER_MEMBERS,
defaultDisabled: /* @__PURE__ */ new Set(),
};
// --- input -------------------------------------------------------------------------------------------------
/** Copies the model's input. The copy is a spread, so an own `__proto__` key stays an ordinary key. */
export function parseComputerInput(raw: unknown): BetaComputerMemberInput {
return { ...(raw as object) } as BetaComputerMemberInput;
}