fix: reproducible build — pin deps, patch commander, move stubs to stubs/
- Move private package stubs to stubs/ (tracked), reference via file: in package.json
Stubs: color-diff-napi, modifiers-napi, @ant/claude-for-chrome-mcp,
@anthropic-ai/mcpb, @anthropic-ai/sandbox-runtime
- Add patches/commander@14.0.3.patch via pnpm patch:
Allow multi-char short flags (/^-[^-]+$/) so -d2e works with commander v14
- Pin all dependency versions to exact versions from original cli.js bundle
(extracted from node_modules package.json files in source map)
- Add @anthropic-ai/bedrock-sdk, foundry-sdk, vertex-sdk to dependencies
- Update .gitignore: node_modules/ fully ignored (regenerated by pnpm install)
- Update scripts to use plain `bun` instead of hardcoded path
- Verified: rm -rf node_modules && pnpm install && bun run build.ts succeeds
Output: dist/cli.js (22.1MB), `bun dist/cli.js --version` → 2.1.88 (Claude Code)
This commit is contained in:
50
claude-code-source/node_modules/@alcalzone/ansi-tokenize/build/ansiCodes.js
generated
vendored
50
claude-code-source/node_modules/@alcalzone/ansi-tokenize/build/ansiCodes.js
generated
vendored
@@ -1,50 +0,0 @@
|
||||
import ansiStyles from "ansi-styles";
|
||||
export const ESCAPES = new Set([27, 155]); // \x1b and \x9b
|
||||
export const CSI = "[".codePointAt(0);
|
||||
export const OSC = "]".codePointAt(0);
|
||||
export const endCodesSet = new Set();
|
||||
const endCodesMap = new Map();
|
||||
for (const [start, end] of ansiStyles.codes) {
|
||||
endCodesSet.add(ansiStyles.color.ansi(end));
|
||||
endCodesMap.set(ansiStyles.color.ansi(start), ansiStyles.color.ansi(end));
|
||||
}
|
||||
export const linkStartCodePrefix = "\x1B]8;;";
|
||||
export const linkStartCodePrefixCharCodes = linkStartCodePrefix
|
||||
.split("")
|
||||
.map((char) => char.charCodeAt(0));
|
||||
export const linkCodeSuffix = "\x07";
|
||||
export const linkCodeSuffixCharCode = linkCodeSuffix.charCodeAt(0);
|
||||
export const linkEndCode = `\x1B]8;;${linkCodeSuffix}`;
|
||||
export function getLinkStartCode(url) {
|
||||
return `${linkStartCodePrefix}${url}${linkCodeSuffix}`;
|
||||
}
|
||||
export function getEndCode(code) {
|
||||
if (endCodesSet.has(code))
|
||||
return code;
|
||||
if (endCodesMap.has(code))
|
||||
return endCodesMap.get(code);
|
||||
// We have a few special cases to handle here:
|
||||
// Links:
|
||||
if (code.startsWith(linkStartCodePrefix))
|
||||
return linkEndCode;
|
||||
code = code.slice(2);
|
||||
// 8-bit/24-bit colors:
|
||||
if (code.startsWith("38")) {
|
||||
return ansiStyles.color.close;
|
||||
}
|
||||
else if (code.startsWith("48")) {
|
||||
return ansiStyles.bgColor.close;
|
||||
}
|
||||
// Otherwise find the reset code in the ansi-styles map
|
||||
const ret = ansiStyles.codes.get(parseInt(code, 10));
|
||||
if (ret) {
|
||||
return ansiStyles.color.ansi(ret);
|
||||
}
|
||||
else {
|
||||
return ansiStyles.reset.open;
|
||||
}
|
||||
}
|
||||
export function ansiCodesToString(codes) {
|
||||
return codes.map((code) => code.code).join("");
|
||||
}
|
||||
//# sourceMappingURL=ansiCodes.js.map
|
||||
17
claude-code-source/node_modules/@alcalzone/ansi-tokenize/build/diff.js
generated
vendored
17
claude-code-source/node_modules/@alcalzone/ansi-tokenize/build/diff.js
generated
vendored
@@ -1,17 +0,0 @@
|
||||
import { undoAnsiCodes } from "./undo.js";
|
||||
/**
|
||||
* Returns the minimum amount of ANSI codes necessary to get from the compound style `from` to `to`.
|
||||
* Both `from` and `to` are expected to be reduced.
|
||||
*/
|
||||
export function diffAnsiCodes(from, to) {
|
||||
const endCodesInTo = new Set(to.map((code) => code.endCode));
|
||||
const startCodesInFrom = new Set(from.map((code) => code.code));
|
||||
return [
|
||||
// Ignore all styles in `from` that are not overwritten or removed by `to`
|
||||
// Disable all styles in `from` that are removed in `to`
|
||||
...undoAnsiCodes(from.filter((code) => !endCodesInTo.has(code.endCode))),
|
||||
// Add all styles in `to` that don't exist in `from`
|
||||
...to.filter((code) => !startCodesInFrom.has(code.code)),
|
||||
];
|
||||
}
|
||||
//# sourceMappingURL=diff.js.map
|
||||
7
claude-code-source/node_modules/@alcalzone/ansi-tokenize/build/index.js
generated
vendored
7
claude-code-source/node_modules/@alcalzone/ansi-tokenize/build/index.js
generated
vendored
@@ -1,7 +0,0 @@
|
||||
export { ansiCodesToString } from "./ansiCodes.js";
|
||||
export { diffAnsiCodes } from "./diff.js";
|
||||
export { reduceAnsiCodes, reduceAnsiCodesIncremental } from "./reduce.js";
|
||||
export * from "./styledChars.js";
|
||||
export * from "./tokenize.js";
|
||||
export { undoAnsiCodes } from "./undo.js";
|
||||
//# sourceMappingURL=index.js.map
|
||||
38
claude-code-source/node_modules/@alcalzone/ansi-tokenize/build/reduce.js
generated
vendored
38
claude-code-source/node_modules/@alcalzone/ansi-tokenize/build/reduce.js
generated
vendored
@@ -1,38 +0,0 @@
|
||||
import ansiStyles from "ansi-styles";
|
||||
import { endCodesSet } from "./ansiCodes.js";
|
||||
/** Reduces the given array of ANSI codes to the minimum necessary to render with the same style */
|
||||
export function reduceAnsiCodes(codes) {
|
||||
return reduceAnsiCodesIncremental([], codes);
|
||||
}
|
||||
/** Like {@link reduceAnsiCodes}, but assumes that `codes` is already reduced. Further reductions are only done for the items in `newCodes`. */
|
||||
export function reduceAnsiCodesIncremental(codes, newCodes) {
|
||||
let ret = [...codes];
|
||||
for (const code of newCodes) {
|
||||
if (code.code === ansiStyles.reset.open) {
|
||||
// Reset code, disable all codes
|
||||
ret = [];
|
||||
}
|
||||
else if (endCodesSet.has(code.code)) {
|
||||
// This is an end code, disable all matching start codes
|
||||
ret = ret.filter((retCode) => retCode.endCode !== code.code);
|
||||
}
|
||||
else {
|
||||
// This is a start code. Remove codes it "overrides", then add it.
|
||||
// If a new code has the same endCode, it "overrides" existing ones.
|
||||
// Special case: Intensity codes (1m, 2m) can coexist (both end with 22m).
|
||||
const isIntensityCode = code.code === ansiStyles.bold.open || code.code === ansiStyles.dim.open;
|
||||
// Add intensity codes only if not already present
|
||||
if (isIntensityCode) {
|
||||
if (!ret.find((retCode) => retCode.code === code.code && retCode.endCode === code.endCode)) {
|
||||
ret.push(code);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ret = ret.filter((retCode) => retCode.endCode !== code.endCode);
|
||||
ret.push(code);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
//# sourceMappingURL=reduce.js.map
|
||||
38
claude-code-source/node_modules/@alcalzone/ansi-tokenize/build/styledChars.js
generated
vendored
38
claude-code-source/node_modules/@alcalzone/ansi-tokenize/build/styledChars.js
generated
vendored
@@ -1,38 +0,0 @@
|
||||
import { ansiCodesToString } from "./ansiCodes.js";
|
||||
import { diffAnsiCodes } from "./diff.js";
|
||||
import { reduceAnsiCodesIncremental } from "./reduce.js";
|
||||
export function styledCharsFromTokens(tokens) {
|
||||
let codes = [];
|
||||
const ret = [];
|
||||
for (const token of tokens) {
|
||||
if (token.type === "ansi") {
|
||||
codes = reduceAnsiCodesIncremental(codes, [token]);
|
||||
}
|
||||
else if (token.type === "char") {
|
||||
ret.push({
|
||||
...token,
|
||||
styles: [...codes],
|
||||
});
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
export function styledCharsToString(chars) {
|
||||
let ret = "";
|
||||
for (let i = 0; i < chars.length; i++) {
|
||||
const char = chars[i];
|
||||
if (i === 0) {
|
||||
ret += ansiCodesToString(char.styles);
|
||||
}
|
||||
else {
|
||||
ret += ansiCodesToString(diffAnsiCodes(chars[i - 1].styles, char.styles));
|
||||
}
|
||||
ret += char.value;
|
||||
// reset active styles at the end of the string
|
||||
if (i === chars.length - 1) {
|
||||
ret += ansiCodesToString(diffAnsiCodes(char.styles, []));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
//# sourceMappingURL=styledChars.js.map
|
||||
141
claude-code-source/node_modules/@alcalzone/ansi-tokenize/build/tokenize.js
generated
vendored
141
claude-code-source/node_modules/@alcalzone/ansi-tokenize/build/tokenize.js
generated
vendored
@@ -1,141 +0,0 @@
|
||||
import isFullwidthCodePoint from "is-fullwidth-code-point";
|
||||
import { CSI, ESCAPES, getEndCode, linkStartCodePrefix, linkStartCodePrefixCharCodes, OSC, } from "./ansiCodes.js";
|
||||
// HOT PATH: Use only basic string/char code operations for maximum performance
|
||||
function parseLinkCode(string, offset) {
|
||||
string = string.slice(offset);
|
||||
for (let index = 1; index < linkStartCodePrefixCharCodes.length; index++) {
|
||||
if (string.charCodeAt(index) !== linkStartCodePrefixCharCodes[index]) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
// This is a link code (with or without the URL part). Find the end of it.
|
||||
const endIndex = string.indexOf("\x07", linkStartCodePrefix.length);
|
||||
if (endIndex === -1)
|
||||
return undefined;
|
||||
return string.slice(0, endIndex + 1);
|
||||
}
|
||||
const CC_0 = "0".charCodeAt(0);
|
||||
const CC_9 = "9".charCodeAt(0);
|
||||
const CC_SEMI = ";".charCodeAt(0);
|
||||
const CC_M = "m".charCodeAt(0);
|
||||
/**
|
||||
* Scans through the given string and finds the index of the last character of an SGR sequence
|
||||
* like `\x1B[38;2;123;123;123m`. This assumes that the string has been checked to start with `\x1B[`.
|
||||
* Returns -1 if no valid SGR sequence is found.
|
||||
*/
|
||||
function findSGRSequenceEndIndex(str) {
|
||||
for (let index = 2; index < str.length; index++) {
|
||||
const charCode = str.charCodeAt(index);
|
||||
// m marks the end of the SGR sequence
|
||||
if (charCode === CC_M)
|
||||
return index;
|
||||
// Digits and semicolons are valid
|
||||
if (charCode === CC_SEMI)
|
||||
continue;
|
||||
if (charCode >= CC_0 && charCode <= CC_9)
|
||||
continue;
|
||||
// Everything else is invalid
|
||||
break;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
// HOT PATH: Use only basic string/char code operations for maximum performance
|
||||
function parseSGRSequence(string, offset) {
|
||||
string = string.slice(offset);
|
||||
const endIndex = findSGRSequenceEndIndex(string);
|
||||
if (endIndex === -1)
|
||||
return;
|
||||
return string.slice(0, endIndex + 1);
|
||||
}
|
||||
/**
|
||||
* Splits compound SGR sequences like `\x1B[1;3;31m` into individual components
|
||||
*/
|
||||
function splitCompoundSGRSequences(code) {
|
||||
if (!code.includes(";")) {
|
||||
// Not a compound code
|
||||
return [code];
|
||||
}
|
||||
const codeParts = code
|
||||
// Strip off the escape sequences \x1B[ and m
|
||||
.slice(2, -1)
|
||||
.split(";");
|
||||
const ret = [];
|
||||
for (let i = 0; i < codeParts.length; i++) {
|
||||
const rawCode = codeParts[i];
|
||||
// Keep 8-bit and 24-bit color codes (containing multiple ";") together
|
||||
if (rawCode === "38" || rawCode === "48") {
|
||||
if (i + 2 < codeParts.length && codeParts[i + 1] === "5") {
|
||||
// 8-bit color, followed by another number
|
||||
ret.push(codeParts.slice(i, i + 3).join(";"));
|
||||
i += 2;
|
||||
continue;
|
||||
}
|
||||
else if (i + 4 < codeParts.length && codeParts[i + 1] === "2") {
|
||||
// 24-bit color, followed by three numbers
|
||||
ret.push(codeParts.slice(i, i + 5).join(";"));
|
||||
i += 4;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// Not a (valid) 8/24-bit color code, push as is
|
||||
ret.push(rawCode);
|
||||
}
|
||||
return ret.map((part) => `\x1b[${part}m`);
|
||||
}
|
||||
export function tokenize(str, endChar = Number.POSITIVE_INFINITY) {
|
||||
const ret = [];
|
||||
let index = 0;
|
||||
let visible = 0;
|
||||
while (index < str.length) {
|
||||
const codePoint = str.codePointAt(index);
|
||||
if (ESCAPES.has(codePoint)) {
|
||||
let code;
|
||||
// Peek the next code point to determine the type of ANSI sequence
|
||||
const nextCodePoint = str.codePointAt(index + 1);
|
||||
if (nextCodePoint === OSC) {
|
||||
// ] = operating system commands, like links
|
||||
code = parseLinkCode(str, index);
|
||||
if (code) {
|
||||
ret.push({
|
||||
type: "ansi",
|
||||
code: code,
|
||||
endCode: getEndCode(code),
|
||||
});
|
||||
}
|
||||
}
|
||||
else if (nextCodePoint === CSI) {
|
||||
// [ = control sequence introducer, like SGR sequences [...m
|
||||
code = parseSGRSequence(str, index);
|
||||
if (code) {
|
||||
// Split compound codes into individual tokens
|
||||
const codes = splitCompoundSGRSequences(code);
|
||||
for (const individualCode of codes) {
|
||||
ret.push({
|
||||
type: "ansi",
|
||||
code: individualCode,
|
||||
endCode: getEndCode(individualCode),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
if (code) {
|
||||
index += code.length;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
const fullWidth = isFullwidthCodePoint(codePoint);
|
||||
const character = String.fromCodePoint(codePoint);
|
||||
ret.push({
|
||||
type: "char",
|
||||
value: character,
|
||||
fullWidth,
|
||||
});
|
||||
index += character.length;
|
||||
visible += fullWidth ? 2 : character.length;
|
||||
if (visible >= endChar) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
//# sourceMappingURL=tokenize.js.map
|
||||
11
claude-code-source/node_modules/@alcalzone/ansi-tokenize/build/undo.js
generated
vendored
11
claude-code-source/node_modules/@alcalzone/ansi-tokenize/build/undo.js
generated
vendored
@@ -1,11 +0,0 @@
|
||||
import { reduceAnsiCodes } from "./reduce.js";
|
||||
/** Returns the combination of ANSI codes needed to undo the given ANSI codes */
|
||||
export function undoAnsiCodes(codes) {
|
||||
return reduceAnsiCodes(codes)
|
||||
.reverse()
|
||||
.map((code) => ({
|
||||
...code,
|
||||
code: code.endCode,
|
||||
}));
|
||||
}
|
||||
//# sourceMappingURL=undo.js.map
|
||||
25
claude-code-source/node_modules/@ant/computer-use-input/js/index.js
generated
vendored
25
claude-code-source/node_modules/@ant/computer-use-input/js/index.js
generated
vendored
@@ -1,25 +0,0 @@
|
||||
const path = require("path");
|
||||
|
||||
// Discriminated union: { isSupported: false } on non-darwin,
|
||||
// { isSupported: true, ...nativeFns } on darwin. Cross-platform consumers
|
||||
// (claude-cli-internal) require() unconditionally and narrow on isSupported.
|
||||
if (process.platform !== "darwin") {
|
||||
module.exports = { isSupported: false };
|
||||
} else {
|
||||
// COMPUTER_USE_INPUT_NODE_PATH: escape hatch for bundlers. Bun's --compile
|
||||
// embeds the .node as an asset, not in a node_modules tree — __dirname is
|
||||
// the exe dir and ../prebuilds/ doesn't exist. The consuming build bakes
|
||||
// this var to the embedded asset's path. Unset → normal node_modules layout.
|
||||
//
|
||||
// key()/keys() dispatch enigo work onto DispatchQueue.main via
|
||||
// dispatch2::run_on_main, then block a tokio worker on a channel. Under
|
||||
// Electron (CFRunLoop drains the main queue) this works; under libuv
|
||||
// (Node/bun) the main queue never drains and the promise hangs. Consumers
|
||||
// running under libuv must pump CFRunLoop while key()/keys() are pending —
|
||||
// e.g. claude-cli-internal borrows @ant/computer-use-swift's _drainMainRunLoop.
|
||||
const native = require(
|
||||
process.env.COMPUTER_USE_INPUT_NODE_PATH ??
|
||||
path.resolve(__dirname, "../prebuilds/computer-use-input.node"),
|
||||
);
|
||||
module.exports = { isSupported: true, ...native };
|
||||
}
|
||||
553
claude-code-source/node_modules/@ant/computer-use-mcp/src/deniedApps.ts
generated
vendored
553
claude-code-source/node_modules/@ant/computer-use-mcp/src/deniedApps.ts
generated
vendored
@@ -1,553 +0,0 @@
|
||||
/**
|
||||
* App category lookup for tiered CU permissions. Three categories land at a
|
||||
* restricted tier instead of `"full"`:
|
||||
*
|
||||
* - **browser** → `"read"` tier — visible in screenshots, NO interaction.
|
||||
* The model can read an already-open page but must use the Claude-in-Chrome
|
||||
* MCP for navigation/clicking/typing.
|
||||
* - **terminal** → `"click"` tier — visible + clickable, NO typing. The
|
||||
* model can click a Run button or scroll test output in an IDE, but can't
|
||||
* type into the integrated terminal. Use the Bash tool for shell work.
|
||||
* - **trading** → `"read"` tier — same restrictions as browsers, but no
|
||||
* CiC-MCP alternative exists. For platforms where a stray click can
|
||||
* execute a trade or send a message to a counterparty.
|
||||
*
|
||||
* Uncategorized apps default to `"full"`. See `getDefaultTierForApp`.
|
||||
*
|
||||
* Identification is two-layered:
|
||||
* 1. Bundle ID match (macOS-only; `InstalledApp.bundleId` is a
|
||||
* CFBundleIdentifier and meaningless on Windows). Fast, exact, the
|
||||
* primary mechanism while CU is darwin-gated.
|
||||
* 2. Display-name substring match (cross-platform fallback). Catches
|
||||
* unresolved requests ("Chrome" when Chrome isn't installed) AND will
|
||||
* be the primary mechanism on Windows/Linux where there's no bundle ID.
|
||||
* Windows-relevant names (PowerShell, cmd, Windows Terminal) are
|
||||
* included now so they activate the moment the darwin gate lifts.
|
||||
*
|
||||
* Keep this file **import-free** (like sentinelApps.ts) — the renderer may
|
||||
* import it via a package.json subpath export, and pulling in
|
||||
* `@modelcontextprotocol/sdk` (a devDep) through the index → mcpServer chain
|
||||
* would fail module resolution in Next.js. The `CuAppPermTier` type is
|
||||
* duplicated as a string literal below rather than imported.
|
||||
*/
|
||||
|
||||
export type DeniedCategory = "browser" | "terminal" | "trading";
|
||||
|
||||
/**
|
||||
* Map a category to its hardcoded tier. Return-type is the string-literal
|
||||
* union inline (this file is import-free; see header comment). The
|
||||
* authoritative type is `CuAppPermTier` in types.ts — keep in sync.
|
||||
*
|
||||
* Not bijective — both `"browser"` and `"trading"` map to `"read"`. Copy
|
||||
* that differs by category (the "use CiC" hint is browser-only) must check
|
||||
* the category, not just the tier.
|
||||
*/
|
||||
export function categoryToTier(
|
||||
category: DeniedCategory | null,
|
||||
): "read" | "click" | "full" {
|
||||
if (category === "browser" || category === "trading") return "read";
|
||||
if (category === "terminal") return "click";
|
||||
return "full";
|
||||
}
|
||||
|
||||
// ─── Bundle-ID deny sets (macOS) ─────────────────────────────────────────
|
||||
|
||||
const BROWSER_BUNDLE_IDS: ReadonlySet<string> = new Set([
|
||||
// Apple
|
||||
"com.apple.Safari",
|
||||
"com.apple.SafariTechnologyPreview",
|
||||
// Google
|
||||
"com.google.Chrome",
|
||||
"com.google.Chrome.beta",
|
||||
"com.google.Chrome.dev",
|
||||
"com.google.Chrome.canary",
|
||||
// Microsoft
|
||||
"com.microsoft.edgemac",
|
||||
"com.microsoft.edgemac.Beta",
|
||||
"com.microsoft.edgemac.Dev",
|
||||
"com.microsoft.edgemac.Canary",
|
||||
// Mozilla
|
||||
"org.mozilla.firefox",
|
||||
"org.mozilla.firefoxdeveloperedition",
|
||||
"org.mozilla.nightly",
|
||||
// Chromium-based
|
||||
"org.chromium.Chromium",
|
||||
"com.brave.Browser",
|
||||
"com.brave.Browser.beta",
|
||||
"com.brave.Browser.nightly",
|
||||
"com.operasoftware.Opera",
|
||||
"com.operasoftware.OperaGX",
|
||||
"com.operasoftware.OperaDeveloper",
|
||||
"com.vivaldi.Vivaldi",
|
||||
// The Browser Company
|
||||
"company.thebrowser.Browser", // Arc
|
||||
"company.thebrowser.dia", // Dia (agentic)
|
||||
// Privacy-focused
|
||||
"org.torproject.torbrowser",
|
||||
"com.duckduckgo.macos.browser",
|
||||
"ru.yandex.desktop.yandex-browser",
|
||||
// Agentic / AI browsers — newer entrants with LLM integrations
|
||||
"ai.perplexity.comet",
|
||||
"com.sigmaos.sigmaos.macos", // SigmaOS
|
||||
// Webkit-based misc
|
||||
"com.kagi.kagimacOS", // Orion
|
||||
]);
|
||||
|
||||
/**
|
||||
* Terminals + IDEs with integrated terminals. Supersets
|
||||
* `SHELL_ACCESS_BUNDLE_IDS` from sentinelApps.ts — terminals proceed to the
|
||||
* approval dialog at tier "click", and the sentinel warning renders
|
||||
* alongside the tier badge.
|
||||
*/
|
||||
const TERMINAL_BUNDLE_IDS: ReadonlySet<string> = new Set([
|
||||
// Dedicated terminals
|
||||
"com.apple.Terminal",
|
||||
"com.googlecode.iterm2",
|
||||
"dev.warp.Warp-Stable",
|
||||
"dev.warp.Warp-Beta",
|
||||
"com.github.wez.wezterm",
|
||||
"org.alacritty",
|
||||
"io.alacritty", // pre-v0.11.0 (renamed 2022-07) — kept for legacy installs
|
||||
"net.kovidgoyal.kitty",
|
||||
"co.zeit.hyper",
|
||||
"com.mitchellh.ghostty",
|
||||
"org.tabby",
|
||||
"com.termius-dmg.mac", // Termius
|
||||
// IDEs with integrated terminals — we can't distinguish "type in the
|
||||
// editor" from "type in the integrated terminal" via screenshot+click.
|
||||
// VS Code family
|
||||
"com.microsoft.VSCode",
|
||||
"com.microsoft.VSCodeInsiders",
|
||||
"com.vscodium", // VSCodium
|
||||
"com.todesktop.230313mzl4w4u92", // Cursor
|
||||
"com.exafunction.windsurf", // Windsurf / Codeium
|
||||
"dev.zed.Zed",
|
||||
"dev.zed.Zed-Preview",
|
||||
// JetBrains family (all have integrated terminals)
|
||||
"com.jetbrains.intellij",
|
||||
"com.jetbrains.intellij.ce",
|
||||
"com.jetbrains.pycharm",
|
||||
"com.jetbrains.pycharm.ce",
|
||||
"com.jetbrains.WebStorm",
|
||||
"com.jetbrains.CLion",
|
||||
"com.jetbrains.goland",
|
||||
"com.jetbrains.rubymine",
|
||||
"com.jetbrains.PhpStorm",
|
||||
"com.jetbrains.datagrip",
|
||||
"com.jetbrains.rider",
|
||||
"com.jetbrains.AppCode",
|
||||
"com.jetbrains.rustrover",
|
||||
"com.jetbrains.fleet",
|
||||
"com.google.android.studio", // Android Studio (JetBrains-based)
|
||||
// Other IDEs
|
||||
"com.axosoft.gitkraken", // GitKraken has an integrated terminal panel. Also keeps the "kraken" trading-substring from miscategorizing it — bundle-ID wins.
|
||||
"com.sublimetext.4",
|
||||
"com.sublimetext.3",
|
||||
"org.vim.MacVim",
|
||||
"com.neovim.neovim",
|
||||
"org.gnu.Emacs",
|
||||
// Xcode's previous carve-out (full tier for Interface Builder / simulator)
|
||||
// was reversed — at tier "click" IB and simulator taps still work (both are
|
||||
// plain clicks) while the integrated terminal is blocked from keyboard input.
|
||||
"com.apple.dt.Xcode",
|
||||
"org.eclipse.platform.ide",
|
||||
"org.netbeans.ide",
|
||||
"com.microsoft.visual-studio", // Visual Studio for Mac
|
||||
// AppleScript/automation execution surfaces — same threat as terminals:
|
||||
// type(script) → key("cmd+r") runs arbitrary code. Added after #28011
|
||||
// removed the osascript MCP server, making CU the only tool-call route
|
||||
// to AppleScript.
|
||||
"com.apple.ScriptEditor2",
|
||||
"com.apple.Automator",
|
||||
"com.apple.shortcuts",
|
||||
]);
|
||||
|
||||
/**
|
||||
* Trading / crypto platforms — granted at tier `"read"` so the agent can see
|
||||
* balances and prices but can't click into an order, transfer, or IB chat.
|
||||
* Bundle IDs populated from Homebrew cask `uninstall.quit` stanzas as they're
|
||||
* verified; the name-substring fallback below is the primary check. Bloomberg
|
||||
* Terminal has no native macOS build per their FAQ (web/Citrix only).
|
||||
*
|
||||
* Budgeting/accounting apps (Quicken, YNAB, QuickBooks, etc.) are NOT listed
|
||||
* here — they default to tier `"full"`. The risk model for brokerage/crypto
|
||||
* (a stray click can execute a trade) doesn't apply to budgeting apps; the
|
||||
* Cowork system prompt carries the soft instruction to never execute trades
|
||||
* or transfer money on the user's behalf.
|
||||
*/
|
||||
const TRADING_BUNDLE_IDS: ReadonlySet<string> = new Set([
|
||||
// Verified via Homebrew quit/zap stanzas + mdls + electron-builder source.
|
||||
// Trading
|
||||
"com.webull.desktop.v1", // Webull (direct download, Qt)
|
||||
"com.webull.trade.mac.v1", // Webull (Mac App Store)
|
||||
"com.tastytrade.desktop",
|
||||
"com.tradingview.tradingviewapp.desktop",
|
||||
"com.fidelity.activetrader", // Fidelity Trader+ (new)
|
||||
"com.fmr.activetrader", // Fidelity Active Trader Pro (legacy)
|
||||
// Interactive Brokers TWS — install4j wrapper; Homebrew quit stanza is
|
||||
// authoritative for this exact value but install4j IDs can drift across
|
||||
// major versions — name-substring "trader workstation" is the fallback.
|
||||
"com.install4j.5889-6375-8446-2021",
|
||||
// Crypto
|
||||
"com.binance.BinanceDesktop",
|
||||
"com.electron.exodus",
|
||||
// Electrum uses PyInstaller with bundle_identifier=None → defaults to
|
||||
// org.pythonmac.unspecified.<AppName>. Confirmed in spesmilo/electrum
|
||||
// source + Homebrew zap. IntuneBrew's "org.electrum.electrum" is a fork.
|
||||
"org.pythonmac.unspecified.Electrum",
|
||||
"com.ledger.live",
|
||||
"io.trezor.TrezorSuite",
|
||||
// No native macOS app (name-substring only): Schwab, E*TRADE, TradeStation,
|
||||
// Robinhood, NinjaTrader, Coinbase, Kraken, Bloomberg. thinkorswim
|
||||
// install4j ID drifts per-install — substring safer.
|
||||
]);
|
||||
|
||||
// ─── Policy-deny (not a tier — cannot be granted at all) ─────────────────
|
||||
//
|
||||
// Streaming / ebook / music apps and a handful of publisher apps. These
|
||||
// are auto-denied before the approval dialog — no tier can be granted.
|
||||
// Rationale is copyright / content-control (the agent has no legitimate
|
||||
// need to screenshot Netflix or click Play on Spotify).
|
||||
//
|
||||
// Sourced from the ACP CU-apps blocklist xlsx ("Full block" tab). See
|
||||
// /tmp/extract_cu_blocklist.py for the extraction script.
|
||||
|
||||
const POLICY_DENIED_BUNDLE_IDS: ReadonlySet<string> = new Set([
|
||||
// Verified via Homebrew quit/zap + mdls /System/Applications + IntuneBrew.
|
||||
// Apple built-ins
|
||||
"com.apple.TV",
|
||||
"com.apple.Music",
|
||||
"com.apple.iBooksX",
|
||||
"com.apple.podcasts",
|
||||
// Music
|
||||
"com.spotify.client",
|
||||
"com.amazon.music",
|
||||
"com.tidal.desktop",
|
||||
"com.deezer.deezer-desktop",
|
||||
"com.pandora.desktop",
|
||||
"com.electron.pocket-casts", // direct-download Electron wrapper
|
||||
"au.com.shiftyjelly.PocketCasts", // Mac App Store
|
||||
// Video
|
||||
"tv.plex.desktop",
|
||||
"tv.plex.htpc",
|
||||
"tv.plex.plexamp",
|
||||
"com.amazon.aiv.AIVApp", // Prime Video (iOS-on-Apple-Silicon)
|
||||
// Ebooks
|
||||
"net.kovidgoyal.calibre",
|
||||
"com.amazon.Kindle", // legacy desktop, discontinued
|
||||
"com.amazon.Lassen", // current Mac App Store (iOS-on-Mac)
|
||||
"com.kobo.desktop.Kobo",
|
||||
// No native macOS app (name-substring only): Netflix, Disney+, Hulu,
|
||||
// HBO Max, Peacock, Paramount+, YouTube, Crunchyroll, Tubi, Vudu,
|
||||
// Audible, Reddit, NYTimes. Their iOS apps don't opt into iPad-on-Mac.
|
||||
]);
|
||||
|
||||
const POLICY_DENIED_NAME_SUBSTRINGS: readonly string[] = [
|
||||
// Video streaming
|
||||
"netflix",
|
||||
"disney+",
|
||||
"hulu",
|
||||
"prime video",
|
||||
"apple tv",
|
||||
"peacock",
|
||||
"paramount+",
|
||||
// "plex" is too generic — would match "Perplexity". Covered by
|
||||
// tv.plex.* bundle IDs on macOS.
|
||||
"tubi",
|
||||
"crunchyroll",
|
||||
"vudu",
|
||||
// E-readers / audiobooks
|
||||
"kindle",
|
||||
"apple books",
|
||||
"kobo",
|
||||
"play books",
|
||||
"calibre",
|
||||
"libby",
|
||||
"readium",
|
||||
"audible",
|
||||
"libro.fm",
|
||||
"speechify",
|
||||
// Music
|
||||
"spotify",
|
||||
"apple music",
|
||||
"amazon music",
|
||||
"youtube music",
|
||||
"tidal",
|
||||
"deezer",
|
||||
"pandora",
|
||||
"pocket casts",
|
||||
// Publisher / social apps (from the same blocklist tab)
|
||||
"naver",
|
||||
"reddit",
|
||||
"sony music",
|
||||
"vegas pro",
|
||||
"pitchfork",
|
||||
"economist",
|
||||
"nytimes",
|
||||
// Skipped (too generic for substring matching — need bundle ID):
|
||||
// HBO Max / Max, YouTube (non-Music), Nook, Sony Catalyst, Wired
|
||||
];
|
||||
|
||||
/**
|
||||
* Policy-level auto-deny. Unlike `userDeniedBundleIds` (per-user Settings
|
||||
* page), this is baked into the build. `buildAccessRequest` strips these
|
||||
* before the approval dialog with "blocked by policy" guidance; the agent
|
||||
* is told to not retry.
|
||||
*/
|
||||
export function isPolicyDenied(
|
||||
bundleId: string | undefined,
|
||||
displayName: string,
|
||||
): boolean {
|
||||
if (bundleId && POLICY_DENIED_BUNDLE_IDS.has(bundleId)) return true;
|
||||
const lower = displayName.toLowerCase();
|
||||
for (const sub of POLICY_DENIED_NAME_SUBSTRINGS) {
|
||||
if (lower.includes(sub)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function getDeniedCategory(bundleId: string): DeniedCategory | null {
|
||||
if (BROWSER_BUNDLE_IDS.has(bundleId)) return "browser";
|
||||
if (TERMINAL_BUNDLE_IDS.has(bundleId)) return "terminal";
|
||||
if (TRADING_BUNDLE_IDS.has(bundleId)) return "trading";
|
||||
return null;
|
||||
}
|
||||
|
||||
// ─── Display-name fallback (cross-platform) ──────────────────────────────
|
||||
|
||||
/**
|
||||
* Lowercase substrings checked against the requested display name. Catches:
|
||||
* - Unresolved requests (app not installed, Spotlight miss)
|
||||
* - Future Windows/Linux support where bundleId is meaningless
|
||||
*
|
||||
* Matched via `.includes()` on `name.toLowerCase()`. Entries are ordered
|
||||
* by specificity (more-specific first is irrelevant since we return on
|
||||
* first match, but groupings are by category for readability).
|
||||
*/
|
||||
const BROWSER_NAME_SUBSTRINGS: readonly string[] = [
|
||||
"safari",
|
||||
"chrome",
|
||||
"firefox",
|
||||
"microsoft edge",
|
||||
"brave",
|
||||
"opera",
|
||||
"vivaldi",
|
||||
"chromium",
|
||||
// Arc/Dia: the canonical display name is just "Arc"/"Dia" — too short for
|
||||
// substring matching (false-positives: "Arcade", "Diagram"). Covered by
|
||||
// bundle ID on macOS. The "... browser" entries below catch natural-language
|
||||
// phrasings ("the arc browser") but NOT the canonical short name.
|
||||
"arc browser",
|
||||
"tor browser",
|
||||
"duckduckgo",
|
||||
"yandex",
|
||||
"orion browser",
|
||||
// Agentic / AI browsers
|
||||
"comet", // Perplexity's browser — "Comet" substring risks false positives
|
||||
// but leaving for now; "comet" in an app name is rare
|
||||
"sigmaos",
|
||||
"dia browser",
|
||||
];
|
||||
|
||||
const TERMINAL_NAME_SUBSTRINGS: readonly string[] = [
|
||||
// macOS / cross-platform terminals
|
||||
"terminal", // catches Terminal, Windows Terminal (NOT iTerm — separate entry)
|
||||
"iterm",
|
||||
"wezterm",
|
||||
"alacritty",
|
||||
"kitty",
|
||||
"ghostty",
|
||||
"tabby",
|
||||
"termius",
|
||||
// AppleScript runners — see bundle-ID comment above. "shortcuts" is too
|
||||
// generic for substring matching (many apps have "shortcuts" in the name);
|
||||
// covered by bundle ID only, like warp/hyper.
|
||||
"script editor",
|
||||
"automator",
|
||||
// NOTE: "warp" and "hyper" are too generic for substring matching —
|
||||
// they'd false-positive on "Warpaint" or "Hyperion". Covered by bundle ID
|
||||
// (dev.warp.Warp-Stable, co.zeit.hyper) for macOS; Windows exe-name
|
||||
// matching can be added when Windows CU ships.
|
||||
// Windows shells (activate when the darwin gate lifts)
|
||||
"powershell",
|
||||
"cmd.exe",
|
||||
"command prompt",
|
||||
"git bash",
|
||||
"conemu",
|
||||
"cmder",
|
||||
// IDEs (VS Code family)
|
||||
"visual studio code",
|
||||
"visual studio", // catches VS for Mac + Windows
|
||||
"vscode",
|
||||
"vs code",
|
||||
"vscodium",
|
||||
"cursor", // Cursor IDE — "cursor" is generic but IDE is the only common app
|
||||
"windsurf",
|
||||
// Zed: display name is just "Zed" — too short for substring matching
|
||||
// (false-positives). Covered by bundle ID (dev.zed.Zed) on macOS.
|
||||
// IDEs (JetBrains family)
|
||||
"intellij",
|
||||
"pycharm",
|
||||
"webstorm",
|
||||
"clion",
|
||||
"goland",
|
||||
"rubymine",
|
||||
"phpstorm",
|
||||
"datagrip",
|
||||
"rider",
|
||||
"appcode",
|
||||
"rustrover",
|
||||
"fleet",
|
||||
"android studio",
|
||||
// Other IDEs
|
||||
"sublime text",
|
||||
"macvim",
|
||||
"neovim",
|
||||
"emacs",
|
||||
"xcode",
|
||||
"eclipse",
|
||||
"netbeans",
|
||||
];
|
||||
|
||||
const TRADING_NAME_SUBSTRINGS: readonly string[] = [
|
||||
// Trading — brokerage apps. Sourced from the ACP CU-apps blocklist xlsx
|
||||
// ("Read Only" tab). Name-substring safe for proper nouns below; generic
|
||||
// names (IG, Delta, HTX) are skipped and need bundle-ID matching once
|
||||
// verified.
|
||||
"bloomberg",
|
||||
"ameritrade",
|
||||
"thinkorswim",
|
||||
"schwab",
|
||||
"fidelity",
|
||||
"e*trade",
|
||||
"interactive brokers",
|
||||
"trader workstation", // Interactive Brokers TWS
|
||||
"tradestation",
|
||||
"webull",
|
||||
"robinhood",
|
||||
"tastytrade",
|
||||
"ninjatrader",
|
||||
"tradingview",
|
||||
"moomoo",
|
||||
"tradezero",
|
||||
"prorealtime",
|
||||
"plus500",
|
||||
"saxotrader",
|
||||
"oanda",
|
||||
"metatrader",
|
||||
"forex.com",
|
||||
"avaoptions",
|
||||
"ctrader",
|
||||
"jforex",
|
||||
"iq option",
|
||||
"olymp trade",
|
||||
"binomo",
|
||||
"pocket option",
|
||||
"raceoption",
|
||||
"expertoption",
|
||||
"quotex",
|
||||
"naga",
|
||||
"morgan stanley",
|
||||
"ubs neo",
|
||||
"eikon", // Thomson Reuters / LSEG Workspace
|
||||
// Crypto — exchanges, wallets, portfolio trackers
|
||||
"coinbase",
|
||||
"kraken",
|
||||
"binance",
|
||||
"okx",
|
||||
"bybit",
|
||||
// "gate.io" is too generic — the ".io" TLD suffix is common in app names
|
||||
// (e.g., "Draw.io"). Needs bundle-ID matching once verified.
|
||||
"phemex",
|
||||
"stormgain",
|
||||
"crypto.com",
|
||||
// "exodus" is too generic — it's a common noun and would match unrelated
|
||||
// apps/games. Needs bundle-ID matching once verified.
|
||||
"electrum",
|
||||
"ledger live",
|
||||
"trezor",
|
||||
"guarda",
|
||||
"atomic wallet",
|
||||
"bitpay",
|
||||
"bisq",
|
||||
"koinly",
|
||||
"cointracker",
|
||||
"blockfi",
|
||||
"stripe cli",
|
||||
// Crypto games / metaverse (same trade-execution risk model)
|
||||
"decentraland",
|
||||
"axie infinity",
|
||||
"gods unchained",
|
||||
];
|
||||
|
||||
/**
|
||||
* Display-name substring match. Called when bundle-ID resolution returned
|
||||
* nothing (`resolved === undefined`) or when no bundle-ID deny-list entry
|
||||
* matched. Returns the category for the first matching substring, or null.
|
||||
*
|
||||
* Case-insensitive, substring — so `"Google Chrome"`, `"chrome"`, and
|
||||
* `"Chrome Canary"` all match the `"chrome"` entry.
|
||||
*/
|
||||
export function getDeniedCategoryByDisplayName(
|
||||
name: string,
|
||||
): DeniedCategory | null {
|
||||
const lower = name.toLowerCase();
|
||||
// Trading first — proper-noun-only set, most specific. "Bloomberg Terminal"
|
||||
// contains "terminal" and would miscategorize if TERMINAL_NAME_SUBSTRINGS
|
||||
// ran first.
|
||||
for (const sub of TRADING_NAME_SUBSTRINGS) {
|
||||
if (lower.includes(sub)) return "trading";
|
||||
}
|
||||
for (const sub of BROWSER_NAME_SUBSTRINGS) {
|
||||
if (lower.includes(sub)) return "browser";
|
||||
}
|
||||
for (const sub of TERMINAL_NAME_SUBSTRINGS) {
|
||||
if (lower.includes(sub)) return "terminal";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Combined check — bundle ID first (exact, fast), then display-name
|
||||
* fallback. This is the function tool-call handlers should use.
|
||||
*
|
||||
* `bundleId` may be undefined (unresolved request — model asked for an app
|
||||
* that isn't installed or Spotlight didn't find). In that case only the
|
||||
* display-name check runs.
|
||||
*/
|
||||
export function getDeniedCategoryForApp(
|
||||
bundleId: string | undefined,
|
||||
displayName: string,
|
||||
): DeniedCategory | null {
|
||||
if (bundleId) {
|
||||
const byId = getDeniedCategory(bundleId);
|
||||
if (byId) return byId;
|
||||
}
|
||||
return getDeniedCategoryByDisplayName(displayName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Default tier for an app at grant time. Wraps `getDeniedCategoryForApp` +
|
||||
* `categoryToTier`. Browsers → `"read"`, terminals/IDEs → `"click"`,
|
||||
* everything else → `"full"`.
|
||||
*
|
||||
* Called by `buildAccessRequest` to populate `ResolvedAppRequest.proposedTier`
|
||||
* before the approval dialog shows.
|
||||
*/
|
||||
export function getDefaultTierForApp(
|
||||
bundleId: string | undefined,
|
||||
displayName: string,
|
||||
): "read" | "click" | "full" {
|
||||
return categoryToTier(getDeniedCategoryForApp(bundleId, displayName));
|
||||
}
|
||||
|
||||
export const _test = {
|
||||
BROWSER_BUNDLE_IDS,
|
||||
TERMINAL_BUNDLE_IDS,
|
||||
TRADING_BUNDLE_IDS,
|
||||
POLICY_DENIED_BUNDLE_IDS,
|
||||
BROWSER_NAME_SUBSTRINGS,
|
||||
TERMINAL_NAME_SUBSTRINGS,
|
||||
TRADING_NAME_SUBSTRINGS,
|
||||
POLICY_DENIED_NAME_SUBSTRINGS,
|
||||
};
|
||||
108
claude-code-source/node_modules/@ant/computer-use-mcp/src/imageResize.ts
generated
vendored
108
claude-code-source/node_modules/@ant/computer-use-mcp/src/imageResize.ts
generated
vendored
@@ -1,108 +0,0 @@
|
||||
/**
|
||||
* Port of the API's image transcoder target-size algorithm. Pre-sizing
|
||||
* screenshots to this function's output means the API's early-return fires
|
||||
* (tokens ≤ max) and the image is NOT resized server-side — so the model
|
||||
* sees exactly the dimensions in `ScreenshotResult.width/height` and
|
||||
* `scaleCoord` stays coherent.
|
||||
*
|
||||
* Rust reference: api/api/image_transcoder/rust_transcoder/src/utils/resize.rs
|
||||
* Sibling TS port: apps/claude-browser-use/src/utils/imageResize.ts (identical
|
||||
* algorithm, lives in the Chrome extension tree — not a shared package).
|
||||
*
|
||||
* See COORDINATES.md for why this matters for click accuracy.
|
||||
*/
|
||||
|
||||
export interface ResizeParams {
|
||||
pxPerToken: number;
|
||||
maxTargetPx: number;
|
||||
maxTargetTokens: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Production defaults — match `resize.rs:160-164` and Chrome's
|
||||
* `CDPService.ts:638-642`. Vision encoder uses 28px tiles; 1568 is both
|
||||
* the long-edge cap (56 tiles) AND the token budget.
|
||||
*/
|
||||
export const API_RESIZE_PARAMS: ResizeParams = {
|
||||
pxPerToken: 28,
|
||||
maxTargetPx: 1568,
|
||||
maxTargetTokens: 1568,
|
||||
};
|
||||
|
||||
/** ceil(px / pxPerToken). Matches resize.rs:74-76 (which uses integer ceil-div). */
|
||||
export function nTokensForPx(px: number, pxPerToken: number): number {
|
||||
return Math.floor((px - 1) / pxPerToken) + 1;
|
||||
}
|
||||
|
||||
function nTokensForImg(
|
||||
width: number,
|
||||
height: number,
|
||||
pxPerToken: number,
|
||||
): number {
|
||||
return nTokensForPx(width, pxPerToken) * nTokensForPx(height, pxPerToken);
|
||||
}
|
||||
|
||||
/**
|
||||
* Binary-search along the width dimension for the largest image that:
|
||||
* - preserves the input aspect ratio
|
||||
* - has long edge ≤ maxTargetPx
|
||||
* - has ceil(w/pxPerToken) × ceil(h/pxPerToken) ≤ maxTargetTokens
|
||||
*
|
||||
* Returns [width, height]. No-op if input already satisfies all three.
|
||||
*
|
||||
* The long-edge constraint alone (what we used to use) is insufficient on
|
||||
* squarer-than-16:9 displays: 1568×1014 (MBP 16" AR) is 56×37 = 2072 tokens,
|
||||
* over budget, and gets server-resized to 1372×887 — model then clicks in
|
||||
* 1372-space but scaleCoord assumed 1568-space → ~14% coord error.
|
||||
*
|
||||
* Matches resize.rs:91-155 exactly (verified against its test vectors).
|
||||
*/
|
||||
export function targetImageSize(
|
||||
width: number,
|
||||
height: number,
|
||||
params: ResizeParams,
|
||||
): [number, number] {
|
||||
const { pxPerToken, maxTargetPx, maxTargetTokens } = params;
|
||||
|
||||
if (
|
||||
width <= maxTargetPx &&
|
||||
height <= maxTargetPx &&
|
||||
nTokensForImg(width, height, pxPerToken) <= maxTargetTokens
|
||||
) {
|
||||
return [width, height];
|
||||
}
|
||||
|
||||
// Normalize to landscape for the search; transpose result back.
|
||||
if (height > width) {
|
||||
const [w, h] = targetImageSize(height, width, params);
|
||||
return [h, w];
|
||||
}
|
||||
|
||||
const aspectRatio = width / height;
|
||||
|
||||
// Loop invariant: lowerBoundWidth is always valid, upperBoundWidth is
|
||||
// always invalid. ~12 iterations for a 4000px image.
|
||||
let upperBoundWidth = width;
|
||||
let lowerBoundWidth = 1;
|
||||
|
||||
for (;;) {
|
||||
if (lowerBoundWidth + 1 === upperBoundWidth) {
|
||||
return [
|
||||
lowerBoundWidth,
|
||||
Math.max(Math.round(lowerBoundWidth / aspectRatio), 1),
|
||||
];
|
||||
}
|
||||
|
||||
const middleWidth = Math.floor((lowerBoundWidth + upperBoundWidth) / 2);
|
||||
const middleHeight = Math.max(Math.round(middleWidth / aspectRatio), 1);
|
||||
|
||||
if (
|
||||
middleWidth <= maxTargetPx &&
|
||||
nTokensForImg(middleWidth, middleHeight, pxPerToken) <= maxTargetTokens
|
||||
) {
|
||||
lowerBoundWidth = middleWidth;
|
||||
} else {
|
||||
upperBoundWidth = middleWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
69
claude-code-source/node_modules/@ant/computer-use-mcp/src/index.ts
generated
vendored
69
claude-code-source/node_modules/@ant/computer-use-mcp/src/index.ts
generated
vendored
@@ -1,69 +0,0 @@
|
||||
export type {
|
||||
ComputerExecutor,
|
||||
DisplayGeometry,
|
||||
FrontmostApp,
|
||||
InstalledApp,
|
||||
ResolvePrepareCaptureResult,
|
||||
RunningApp,
|
||||
ScreenshotResult,
|
||||
} from "./executor.js";
|
||||
|
||||
export type {
|
||||
AppGrant,
|
||||
CuAppPermTier,
|
||||
ComputerUseHostAdapter,
|
||||
ComputerUseOverrides,
|
||||
ComputerUseSessionContext,
|
||||
CoordinateMode,
|
||||
CuGrantFlags,
|
||||
CuPermissionRequest,
|
||||
CuPermissionResponse,
|
||||
CuSubGates,
|
||||
CuTeachPermissionRequest,
|
||||
Logger,
|
||||
ResolvedAppRequest,
|
||||
ScreenshotDims,
|
||||
TeachStepRequest,
|
||||
TeachStepResult,
|
||||
} from "./types.js";
|
||||
|
||||
export { DEFAULT_GRANT_FLAGS } from "./types.js";
|
||||
|
||||
export {
|
||||
SENTINEL_BUNDLE_IDS,
|
||||
getSentinelCategory,
|
||||
} from "./sentinelApps.js";
|
||||
export type { SentinelCategory } from "./sentinelApps.js";
|
||||
|
||||
export {
|
||||
categoryToTier,
|
||||
getDefaultTierForApp,
|
||||
getDeniedCategory,
|
||||
getDeniedCategoryByDisplayName,
|
||||
getDeniedCategoryForApp,
|
||||
isPolicyDenied,
|
||||
} from "./deniedApps.js";
|
||||
export type { DeniedCategory } from "./deniedApps.js";
|
||||
|
||||
export { isSystemKeyCombo, normalizeKeySequence } from "./keyBlocklist.js";
|
||||
|
||||
export { ALL_SUB_GATES_OFF, ALL_SUB_GATES_ON } from "./subGates.js";
|
||||
|
||||
export { API_RESIZE_PARAMS, targetImageSize } from "./imageResize.js";
|
||||
export type { ResizeParams } from "./imageResize.js";
|
||||
|
||||
export { defersLockAcquire, handleToolCall } from "./toolCalls.js";
|
||||
export type {
|
||||
CuCallTelemetry,
|
||||
CuCallToolResult,
|
||||
CuErrorKind,
|
||||
} from "./toolCalls.js";
|
||||
|
||||
export { bindSessionContext, createComputerUseMcpServer } from "./mcpServer.js";
|
||||
export { buildComputerUseTools } from "./tools.js";
|
||||
|
||||
export {
|
||||
comparePixelAtLocation,
|
||||
validateClickTarget,
|
||||
} from "./pixelCompare.js";
|
||||
export type { CropRawPatchFn, PixelCompareResult } from "./pixelCompare.js";
|
||||
153
claude-code-source/node_modules/@ant/computer-use-mcp/src/keyBlocklist.ts
generated
vendored
153
claude-code-source/node_modules/@ant/computer-use-mcp/src/keyBlocklist.ts
generated
vendored
@@ -1,153 +0,0 @@
|
||||
/**
|
||||
* Key combos that cross app boundaries or terminate processes. Gated behind
|
||||
* the `systemKeyCombos` grant flag. When that flag is off, the `key` tool
|
||||
* rejects these and returns a tool error telling the model to request the
|
||||
* flag; all other combos work normally.
|
||||
*
|
||||
* Matching is canonicalized: every modifier alias the Rust executor accepts
|
||||
* collapses to one canonical name. Without this, `command+q` / `meta+q` /
|
||||
* `cmd+alt+escape` bypass the gate — see keyBlocklist.test.ts for the three
|
||||
* bypass forms and the Rust parity check that catches future alias drift.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Every modifier alias enigo_wrap.rs accepts (two copies: :351-359, :564-572),
|
||||
* mapped to one canonical per Key:: variant. Left/right variants collapse —
|
||||
* the blocklist doesn't distinguish which Ctrl.
|
||||
*
|
||||
* Canonical names are Rust's own variant names lowercased. Blocklist entries
|
||||
* below use ONLY these. "meta" reads odd for Cmd+Q but it's honest: Rust
|
||||
* sends Key::Meta, which is Cmd on darwin and Win on win32.
|
||||
*/
|
||||
const CANONICAL_MODIFIER: Readonly<Record<string, string>> = {
|
||||
// Key::Meta — "meta"|"super"|"command"|"cmd"|"windows"|"win"
|
||||
meta: "meta",
|
||||
super: "meta",
|
||||
command: "meta",
|
||||
cmd: "meta",
|
||||
windows: "meta",
|
||||
win: "meta",
|
||||
// Key::Control + LControl + RControl
|
||||
ctrl: "ctrl",
|
||||
control: "ctrl",
|
||||
lctrl: "ctrl",
|
||||
lcontrol: "ctrl",
|
||||
rctrl: "ctrl",
|
||||
rcontrol: "ctrl",
|
||||
// Key::Shift + LShift + RShift
|
||||
shift: "shift",
|
||||
lshift: "shift",
|
||||
rshift: "shift",
|
||||
// Key::Alt and Key::Option — distinct Rust variants but same keycode on
|
||||
// darwin (kVK_Option). Collapse: cmd+alt+escape and cmd+option+escape
|
||||
// both Force Quit.
|
||||
alt: "alt",
|
||||
option: "alt",
|
||||
};
|
||||
|
||||
/** Sort order for canonicals. ctrl < alt < shift < meta. */
|
||||
const MODIFIER_ORDER = ["ctrl", "alt", "shift", "meta"];
|
||||
|
||||
/**
|
||||
* Canonical-form entries only. Every modifier must be a CANONICAL_MODIFIER
|
||||
* *value* (not key), modifiers must be in MODIFIER_ORDER, non-modifier last.
|
||||
* The self-consistency test enforces this.
|
||||
*/
|
||||
const BLOCKED_DARWIN = new Set([
|
||||
"meta+q", // Cmd+Q — quit frontmost app
|
||||
"shift+meta+q", // Cmd+Shift+Q — log out
|
||||
"alt+meta+escape", // Cmd+Option+Esc — Force Quit dialog
|
||||
"meta+tab", // Cmd+Tab — app switcher
|
||||
"meta+space", // Cmd+Space — Spotlight
|
||||
"ctrl+meta+q", // Ctrl+Cmd+Q — lock screen
|
||||
]);
|
||||
|
||||
const BLOCKED_WIN32 = new Set([
|
||||
"ctrl+alt+delete", // Secure Attention Sequence
|
||||
"alt+f4", // close window
|
||||
"alt+tab", // window switcher
|
||||
"meta+l", // Win+L — lock
|
||||
"meta+d", // Win+D — show desktop
|
||||
]);
|
||||
|
||||
/**
|
||||
* Partition into sorted-canonical modifiers and non-modifier keys.
|
||||
* Shared by normalizeKeySequence (join for display) and isSystemKeyCombo
|
||||
* (check mods+each-key to catch the cmd+q+a suffix bypass).
|
||||
*/
|
||||
function partitionKeys(seq: string): { mods: string[]; keys: string[] } {
|
||||
const parts = seq
|
||||
.toLowerCase()
|
||||
.split("+")
|
||||
.map((p) => p.trim())
|
||||
.filter(Boolean);
|
||||
const mods: string[] = [];
|
||||
const keys: string[] = [];
|
||||
for (const p of parts) {
|
||||
const canonical = CANONICAL_MODIFIER[p];
|
||||
if (canonical !== undefined) {
|
||||
mods.push(canonical);
|
||||
} else {
|
||||
keys.push(p);
|
||||
}
|
||||
}
|
||||
// Dedupe: "cmd+command+q" → "meta+q", not "meta+meta+q".
|
||||
const uniqueMods = [...new Set(mods)];
|
||||
uniqueMods.sort(
|
||||
(a, b) => MODIFIER_ORDER.indexOf(a) - MODIFIER_ORDER.indexOf(b),
|
||||
);
|
||||
return { mods: uniqueMods, keys };
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize "Cmd + Shift + Q" → "shift+meta+q": lowercase, trim, alias →
|
||||
* canonical, dedupe, sort modifiers, non-modifiers last.
|
||||
*/
|
||||
export function normalizeKeySequence(seq: string): string {
|
||||
const { mods, keys } = partitionKeys(seq);
|
||||
return [...mods, ...keys].join("+");
|
||||
}
|
||||
|
||||
/**
|
||||
* True if the sequence would fire a blocked OS shortcut.
|
||||
*
|
||||
* Checks mods + EACH non-modifier key individually, not just the full
|
||||
* joined string. `cmd+q+a` → Rust presses Cmd, then Q (Cmd+Q fires here),
|
||||
* then A. Exact-match against "meta+q+a" misses; checking "meta+q" and
|
||||
* "meta+a" separately catches the Q.
|
||||
*
|
||||
* Modifiers-only sequences ("cmd+shift") are checked as-is — no key to
|
||||
* pair with, and no blocklist entry is modifier-only, so this is a no-op
|
||||
* that falls through to false. Covers the click-modifier case where
|
||||
* `left_click(text="cmd")` is legitimate.
|
||||
*/
|
||||
export function isSystemKeyCombo(
|
||||
seq: string,
|
||||
platform: "darwin" | "win32",
|
||||
): boolean {
|
||||
const blocklist = platform === "darwin" ? BLOCKED_DARWIN : BLOCKED_WIN32;
|
||||
const { mods, keys } = partitionKeys(seq);
|
||||
const prefix = mods.length > 0 ? mods.join("+") + "+" : "";
|
||||
|
||||
// No non-modifier keys (e.g. "cmd+shift" as click-modifiers) — check the
|
||||
// whole thing. Never matches (no blocklist entry is modifier-only) but
|
||||
// keeps the contract simple: every call reaches a .has().
|
||||
if (keys.length === 0) {
|
||||
return blocklist.has(mods.join("+"));
|
||||
}
|
||||
|
||||
// mods + each key. Any hit blocks the whole sequence.
|
||||
for (const key of keys) {
|
||||
if (blocklist.has(prefix + key)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export const _test = {
|
||||
CANONICAL_MODIFIER,
|
||||
BLOCKED_DARWIN,
|
||||
BLOCKED_WIN32,
|
||||
MODIFIER_ORDER,
|
||||
};
|
||||
313
claude-code-source/node_modules/@ant/computer-use-mcp/src/mcpServer.ts
generated
vendored
313
claude-code-source/node_modules/@ant/computer-use-mcp/src/mcpServer.ts
generated
vendored
@@ -1,313 +0,0 @@
|
||||
/**
|
||||
* MCP server factory + session-context binder.
|
||||
*
|
||||
* Two entry points:
|
||||
*
|
||||
* `bindSessionContext` — the wrapper closure. Takes a `ComputerUseSessionContext`
|
||||
* (getters + callbacks backed by host session state), returns a dispatcher.
|
||||
* Reusable by both the MCP CallTool handler here AND Cowork's
|
||||
* `InternalServerDefinition.handleToolCall` (which doesn't go through MCP).
|
||||
* This replaces the duplicated wrapper closures in apps/desktop/…/serverDef.ts
|
||||
* and the Claude Code CLI's CU host wrapper — both did the same thing: build `ComputerUseOverrides`
|
||||
* fresh from getters, call `handleToolCall`, stash screenshot, merge permissions.
|
||||
*
|
||||
* `createComputerUseMcpServer` — the Server object. When `context` is provided,
|
||||
* the CallTool handler is real (uses `bindSessionContext`). When not, it's the
|
||||
* legacy stub that returns a not-wired error. The tool-schema ListTools handler
|
||||
* is the same either way.
|
||||
*/
|
||||
|
||||
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
||||
import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
||||
import {
|
||||
CallToolRequestSchema,
|
||||
ListToolsRequestSchema,
|
||||
} from "@modelcontextprotocol/sdk/types.js";
|
||||
|
||||
import type { ScreenshotResult } from "./executor.js";
|
||||
import type { CuCallToolResult } from "./toolCalls.js";
|
||||
import {
|
||||
defersLockAcquire,
|
||||
handleToolCall,
|
||||
resetMouseButtonHeld,
|
||||
} from "./toolCalls.js";
|
||||
import { buildComputerUseTools } from "./tools.js";
|
||||
import type {
|
||||
AppGrant,
|
||||
ComputerUseHostAdapter,
|
||||
ComputerUseOverrides,
|
||||
ComputerUseSessionContext,
|
||||
CoordinateMode,
|
||||
CuGrantFlags,
|
||||
CuPermissionResponse,
|
||||
} from "./types.js";
|
||||
import { DEFAULT_GRANT_FLAGS } from "./types.js";
|
||||
|
||||
const DEFAULT_LOCK_HELD_MESSAGE =
|
||||
"Another Claude session is currently using the computer. Wait for that " +
|
||||
"session to finish, or find a non-computer-use approach.";
|
||||
|
||||
/**
|
||||
* Dedupe `granted` into `existing` on bundleId, spread truthy-only flags over
|
||||
* defaults+existing. Truthy-only: a subsequent `request_access` that doesn't
|
||||
* request clipboard can't revoke an earlier clipboard grant — revocation lives
|
||||
* in a Settings page, not here.
|
||||
*
|
||||
* Same merge both hosts implemented independently today.
|
||||
*/
|
||||
function mergePermissionResponse(
|
||||
existing: readonly AppGrant[],
|
||||
existingFlags: CuGrantFlags,
|
||||
response: CuPermissionResponse,
|
||||
): { apps: AppGrant[]; flags: CuGrantFlags } {
|
||||
const seen = new Set(existing.map((a) => a.bundleId));
|
||||
const apps = [
|
||||
...existing,
|
||||
...response.granted.filter((g) => !seen.has(g.bundleId)),
|
||||
];
|
||||
const truthyFlags = Object.fromEntries(
|
||||
Object.entries(response.flags).filter(([, v]) => v === true),
|
||||
);
|
||||
const flags: CuGrantFlags = {
|
||||
...DEFAULT_GRANT_FLAGS,
|
||||
...existingFlags,
|
||||
...truthyFlags,
|
||||
};
|
||||
return { apps, flags };
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind session state to a reusable dispatcher. The returned function is the
|
||||
* wrapper closure: async lock gate → build overrides fresh → `handleToolCall`
|
||||
* → stash screenshot → strip piggybacked fields.
|
||||
*
|
||||
* The last-screenshot blob is held in a closure cell here (not on `ctx`), so
|
||||
* hosts don't need to guarantee `ctx` object identity across calls — they just
|
||||
* need to hold onto the returned dispatcher. Cowork caches per
|
||||
* `InternalServerContext` in a WeakMap; the CLI host constructs once at server creation.
|
||||
*/
|
||||
export function bindSessionContext(
|
||||
adapter: ComputerUseHostAdapter,
|
||||
coordinateMode: CoordinateMode,
|
||||
ctx: ComputerUseSessionContext,
|
||||
): (name: string, args: unknown) => Promise<CuCallToolResult> {
|
||||
const { logger, serverName } = adapter;
|
||||
|
||||
// Screenshot blob persists here across calls — NOT on `ctx`. Hosts hold
|
||||
// onto the returned dispatcher; that's the identity that matters.
|
||||
let lastScreenshot: ScreenshotResult | undefined;
|
||||
|
||||
const wrapPermission = ctx.onPermissionRequest
|
||||
? async (
|
||||
req: Parameters<NonNullable<typeof ctx.onPermissionRequest>>[0],
|
||||
signal: AbortSignal,
|
||||
): Promise<CuPermissionResponse> => {
|
||||
const response = await ctx.onPermissionRequest!(req, signal);
|
||||
const { apps, flags } = mergePermissionResponse(
|
||||
ctx.getAllowedApps(),
|
||||
ctx.getGrantFlags(),
|
||||
response,
|
||||
);
|
||||
logger.debug(
|
||||
`[${serverName}] permission result: granted=${response.granted.length} denied=${response.denied.length}`,
|
||||
);
|
||||
ctx.onAllowedAppsChanged?.(apps, flags);
|
||||
return response;
|
||||
}
|
||||
: undefined;
|
||||
|
||||
const wrapTeachPermission = ctx.onTeachPermissionRequest
|
||||
? async (
|
||||
req: Parameters<NonNullable<typeof ctx.onTeachPermissionRequest>>[0],
|
||||
signal: AbortSignal,
|
||||
): Promise<CuPermissionResponse> => {
|
||||
const response = await ctx.onTeachPermissionRequest!(req, signal);
|
||||
logger.debug(
|
||||
`[${serverName}] teach permission result: granted=${response.granted.length} denied=${response.denied.length}`,
|
||||
);
|
||||
// Teach doesn't request grant flags — preserve existing.
|
||||
const { apps } = mergePermissionResponse(
|
||||
ctx.getAllowedApps(),
|
||||
ctx.getGrantFlags(),
|
||||
response,
|
||||
);
|
||||
ctx.onAllowedAppsChanged?.(apps, {
|
||||
...DEFAULT_GRANT_FLAGS,
|
||||
...ctx.getGrantFlags(),
|
||||
});
|
||||
return response;
|
||||
}
|
||||
: undefined;
|
||||
|
||||
return async (name, args) => {
|
||||
// ─── Async lock gate ─────────────────────────────────────────────────
|
||||
// Replaces the sync Gate-3 in `handleToolCall` — we pass
|
||||
// `checkCuLock: undefined` below so it no-ops. Hosts with
|
||||
// cross-process locks (O_EXCL file) await the real primitive here
|
||||
// instead of pre-computing + feeding a fake sync result.
|
||||
if (ctx.checkCuLock) {
|
||||
const lock = await ctx.checkCuLock();
|
||||
if (lock.holder !== undefined && !lock.isSelf) {
|
||||
const text =
|
||||
ctx.formatLockHeldMessage?.(lock.holder) ?? DEFAULT_LOCK_HELD_MESSAGE;
|
||||
return {
|
||||
content: [{ type: "text", text }],
|
||||
isError: true,
|
||||
telemetry: { error_kind: "cu_lock_held" },
|
||||
};
|
||||
}
|
||||
if (lock.holder === undefined && !defersLockAcquire(name)) {
|
||||
await ctx.acquireCuLock?.();
|
||||
// Re-check: the awaits above yield the microtask queue, so another
|
||||
// session's check+acquire can interleave with ours. Hosts where
|
||||
// acquire is a no-op when already held (Cowork's CuLockManager) give
|
||||
// no signal that we lost — verify we're now the holder before
|
||||
// proceeding. The CLI's O_EXCL file lock would surface this as a throw from
|
||||
// acquire instead; this re-check is a belt-and-suspenders for that
|
||||
// path too.
|
||||
const recheck = await ctx.checkCuLock();
|
||||
if (recheck.holder !== undefined && !recheck.isSelf) {
|
||||
const text =
|
||||
ctx.formatLockHeldMessage?.(recheck.holder) ??
|
||||
DEFAULT_LOCK_HELD_MESSAGE;
|
||||
return {
|
||||
content: [{ type: "text", text }],
|
||||
isError: true,
|
||||
telemetry: { error_kind: "cu_lock_held" },
|
||||
};
|
||||
}
|
||||
// Fresh holder → any prior session's mouseButtonHeld is stale.
|
||||
// Mirrors what Gate-3 does on the acquire branch. After the
|
||||
// re-check so we only clear module state when we actually won.
|
||||
resetMouseButtonHeld();
|
||||
}
|
||||
}
|
||||
|
||||
// ─── Build overrides fresh ───────────────────────────────────────────
|
||||
// Blob-first; dims-fallback with base64:"" when the closure cell is
|
||||
// unset (cross-respawn). scaleCoord reads dims; pixelCompare sees "" →
|
||||
// isEmpty → skip.
|
||||
const dimsFallback = lastScreenshot
|
||||
? undefined
|
||||
: ctx.getLastScreenshotDims?.();
|
||||
|
||||
// Per-call AbortController for dialog dismissal. Aborted in `finally` —
|
||||
// if handleToolCall finishes (MCP timeout, throw) before the user
|
||||
// answers, the host's dialog handler sees the abort and tears down.
|
||||
const dialogAbort = new AbortController();
|
||||
|
||||
const overrides: ComputerUseOverrides = {
|
||||
allowedApps: [...ctx.getAllowedApps()],
|
||||
grantFlags: ctx.getGrantFlags(),
|
||||
userDeniedBundleIds: ctx.getUserDeniedBundleIds(),
|
||||
coordinateMode,
|
||||
selectedDisplayId: ctx.getSelectedDisplayId(),
|
||||
displayPinnedByModel: ctx.getDisplayPinnedByModel?.(),
|
||||
displayResolvedForApps: ctx.getDisplayResolvedForApps?.(),
|
||||
lastScreenshot:
|
||||
lastScreenshot ??
|
||||
(dimsFallback ? { ...dimsFallback, base64: "" } : undefined),
|
||||
onPermissionRequest: wrapPermission
|
||||
? (req) => wrapPermission(req, dialogAbort.signal)
|
||||
: undefined,
|
||||
onTeachPermissionRequest: wrapTeachPermission
|
||||
? (req) => wrapTeachPermission(req, dialogAbort.signal)
|
||||
: undefined,
|
||||
onAppsHidden: ctx.onAppsHidden,
|
||||
getClipboardStash: ctx.getClipboardStash,
|
||||
onClipboardStashChanged: ctx.onClipboardStashChanged,
|
||||
onResolvedDisplayUpdated: ctx.onResolvedDisplayUpdated,
|
||||
onDisplayPinned: ctx.onDisplayPinned,
|
||||
onDisplayResolvedForApps: ctx.onDisplayResolvedForApps,
|
||||
onTeachModeActivated: ctx.onTeachModeActivated,
|
||||
onTeachStep: ctx.onTeachStep,
|
||||
onTeachWorking: ctx.onTeachWorking,
|
||||
getTeachModeActive: ctx.getTeachModeActive,
|
||||
// Undefined → handleToolCall's sync Gate-3 no-ops. The async gate
|
||||
// above already ran.
|
||||
checkCuLock: undefined,
|
||||
acquireCuLock: undefined,
|
||||
isAborted: ctx.isAborted,
|
||||
};
|
||||
|
||||
logger.debug(
|
||||
`[${serverName}] tool=${name} allowedApps=${overrides.allowedApps.length} coordMode=${coordinateMode}`,
|
||||
);
|
||||
|
||||
// ─── Dispatch ────────────────────────────────────────────────────────
|
||||
try {
|
||||
const result = await handleToolCall(adapter, name, args, overrides);
|
||||
|
||||
if (result.screenshot) {
|
||||
lastScreenshot = result.screenshot;
|
||||
const { base64: _blob, ...dims } = result.screenshot;
|
||||
logger.debug(`[${serverName}] screenshot dims: ${JSON.stringify(dims)}`);
|
||||
ctx.onScreenshotCaptured?.(dims);
|
||||
}
|
||||
|
||||
return result;
|
||||
} finally {
|
||||
dialogAbort.abort();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function createComputerUseMcpServer(
|
||||
adapter: ComputerUseHostAdapter,
|
||||
coordinateMode: CoordinateMode,
|
||||
context?: ComputerUseSessionContext,
|
||||
): Server {
|
||||
const { serverName, logger } = adapter;
|
||||
|
||||
const server = new Server(
|
||||
{ name: serverName, version: "0.1.3" },
|
||||
{ capabilities: { tools: {}, logging: {} } },
|
||||
);
|
||||
|
||||
const tools = buildComputerUseTools(
|
||||
adapter.executor.capabilities,
|
||||
coordinateMode,
|
||||
);
|
||||
|
||||
server.setRequestHandler(ListToolsRequestSchema, async () =>
|
||||
adapter.isDisabled() ? { tools: [] } : { tools },
|
||||
);
|
||||
|
||||
if (context) {
|
||||
const dispatch = bindSessionContext(adapter, coordinateMode, context);
|
||||
server.setRequestHandler(
|
||||
CallToolRequestSchema,
|
||||
async (request): Promise<CallToolResult> => {
|
||||
const { screenshot: _s, telemetry: _t, ...result } = await dispatch(
|
||||
request.params.name,
|
||||
request.params.arguments ?? {},
|
||||
);
|
||||
return result;
|
||||
},
|
||||
);
|
||||
return server;
|
||||
}
|
||||
|
||||
// Legacy: no context → stub handler. Reached only if something calls the
|
||||
// server over MCP transport WITHOUT going through a binder (a wiring
|
||||
// regression). Clear error instead of silent failure.
|
||||
server.setRequestHandler(
|
||||
CallToolRequestSchema,
|
||||
async (request): Promise<CallToolResult> => {
|
||||
logger.warn(
|
||||
`[${serverName}] tool call "${request.params.name}" reached the stub handler — no session context bound. Per-session state unavailable.`,
|
||||
);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: "This computer-use server instance is not wired to a session. Per-session app permissions are not available on this code path.",
|
||||
},
|
||||
],
|
||||
isError: true,
|
||||
};
|
||||
},
|
||||
);
|
||||
|
||||
return server;
|
||||
}
|
||||
171
claude-code-source/node_modules/@ant/computer-use-mcp/src/pixelCompare.ts
generated
vendored
171
claude-code-source/node_modules/@ant/computer-use-mcp/src/pixelCompare.ts
generated
vendored
@@ -1,171 +0,0 @@
|
||||
/**
|
||||
* Staleness guard ported from the Vercept acquisition.
|
||||
*
|
||||
* Compares the model's last-seen screenshot against a fresh-right-now
|
||||
* screenshot at the click target, so the model never clicks pixels it hasn't
|
||||
* seen. If the 9×9 patch around the target differs, the click is aborted and
|
||||
* the model is told to re-screenshot. This is NOT a popup detector.
|
||||
*
|
||||
* Semantics preserved exactly:
|
||||
* - Skip on no `lastScreenshot` (cold start) — click proceeds.
|
||||
* - Skip on any internal error (crop throws, screenshot fails, etc.) —
|
||||
* click proceeds. Validation failure must never block the action.
|
||||
* - 9×9 exact byte equality on raw pixel bytes. No fuzzing, no tolerance.
|
||||
* - Compare in percentage coords so Retina scale doesn't matter.
|
||||
*
|
||||
* JPEG decode + crop is INJECTED via `ComputerUseHostAdapter.cropRawPatch`.
|
||||
* The original used `sharp` (LGPL, native `.node` addon); we inject Electron's
|
||||
* `nativeImage` (Chromium decoders, BSD, nothing to bundle) from the host, so
|
||||
* this package never imports it — the crop is a function parameter.
|
||||
*/
|
||||
|
||||
import type { ScreenshotResult } from "./executor.js";
|
||||
import type { Logger } from "./types.js";
|
||||
|
||||
/** Injected by the host. See `ComputerUseHostAdapter.cropRawPatch`. */
|
||||
export type CropRawPatchFn = (
|
||||
jpegBase64: string,
|
||||
rect: { x: number; y: number; width: number; height: number },
|
||||
) => Buffer | null;
|
||||
|
||||
/** 9×9 is empirically the sweet spot — large enough to catch a tooltip
|
||||
* appearing, small enough to not false-positive on surrounding animation.
|
||||
**/
|
||||
const DEFAULT_GRID_SIZE = 9;
|
||||
|
||||
export interface PixelCompareResult {
|
||||
/** true → click may proceed. false → patch changed, abort the click. */
|
||||
valid: boolean;
|
||||
/** true → validation did not run (cold start, sub-gate off, or internal
|
||||
* error). The caller MUST treat this identically to `valid: true`. */
|
||||
skipped: boolean;
|
||||
/** Populated when valid === false. Returned to the model verbatim. */
|
||||
warning?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the crop rect for a patch centered on (xPercent, yPercent).
|
||||
*
|
||||
* Dimensions come from ScreenshotResult.width/height (physical pixels). Both
|
||||
* screenshots have the same dimensions (same display, consecutive captures),
|
||||
* so the rect is the same for both.
|
||||
*/
|
||||
function computeCropRect(
|
||||
imgW: number,
|
||||
imgH: number,
|
||||
xPercent: number,
|
||||
yPercent: number,
|
||||
gridSize: number,
|
||||
): { x: number; y: number; width: number; height: number } | null {
|
||||
if (!imgW || !imgH) return null;
|
||||
|
||||
const clampedX = Math.max(0, Math.min(100, xPercent));
|
||||
const clampedY = Math.max(0, Math.min(100, yPercent));
|
||||
|
||||
const centerX = Math.round((clampedX / 100.0) * imgW);
|
||||
const centerY = Math.round((clampedY / 100.0) * imgH);
|
||||
|
||||
const halfGrid = Math.floor(gridSize / 2);
|
||||
const cropX = Math.max(0, centerX - halfGrid);
|
||||
const cropY = Math.max(0, centerY - halfGrid);
|
||||
const cropW = Math.min(gridSize, imgW - cropX);
|
||||
const cropH = Math.min(gridSize, imgH - cropY);
|
||||
if (cropW <= 0 || cropH <= 0) return null;
|
||||
|
||||
return { x: cropX, y: cropY, width: cropW, height: cropH };
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare the same patch location between two screenshots.
|
||||
*
|
||||
* @returns true when the raw pixel bytes are identical. false on any
|
||||
* difference, or on any internal error (the caller treats an error here as
|
||||
* `skipped`, so the false is harmless).
|
||||
*/
|
||||
export function comparePixelAtLocation(
|
||||
crop: CropRawPatchFn,
|
||||
lastScreenshot: ScreenshotResult,
|
||||
freshScreenshot: ScreenshotResult,
|
||||
xPercent: number,
|
||||
yPercent: number,
|
||||
gridSize: number = DEFAULT_GRID_SIZE,
|
||||
): boolean {
|
||||
// Both screenshots are of the same display — use the fresh one's
|
||||
// dimensions (less likely to be stale than last's).
|
||||
const rect = computeCropRect(
|
||||
freshScreenshot.width,
|
||||
freshScreenshot.height,
|
||||
xPercent,
|
||||
yPercent,
|
||||
gridSize,
|
||||
);
|
||||
if (!rect) return false;
|
||||
|
||||
const patch1 = crop(lastScreenshot.base64, rect);
|
||||
const patch2 = crop(freshScreenshot.base64, rect);
|
||||
if (!patch1 || !patch2) return false;
|
||||
|
||||
// Direct buffer equality. Note: nativeImage.toBitmap() gives BGRA, sharp's
|
||||
// .raw() gave RGB.
|
||||
// Doesn't matter — we're comparing two same-format buffers for equality.
|
||||
return patch1.equals(patch2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Battle-tested click-target validation ported from the Vercept acquisition,
|
||||
* with the fresh-screenshot capture delegated to the caller (we don't have
|
||||
* a global `SystemActions.takeScreenshot()` — the executor is injected).
|
||||
*
|
||||
* Skip conditions (any of these → `{ valid: true, skipped: true }`):
|
||||
* - `lastScreenshot` is undefined (cold start).
|
||||
* - `takeFreshScreenshot()` throws or returns null.
|
||||
* - Injected crop function returns null (decode failure).
|
||||
* - Any other exception.
|
||||
*
|
||||
* The caller decides whether to invoke this at all (sub-gate check lives
|
||||
* in toolCalls.ts, not here).
|
||||
*/
|
||||
export async function validateClickTarget(
|
||||
crop: CropRawPatchFn,
|
||||
lastScreenshot: ScreenshotResult | undefined,
|
||||
xPercent: number,
|
||||
yPercent: number,
|
||||
takeFreshScreenshot: () => Promise<ScreenshotResult | null>,
|
||||
logger: Logger,
|
||||
gridSize: number = DEFAULT_GRID_SIZE,
|
||||
): Promise<PixelCompareResult> {
|
||||
if (!lastScreenshot) {
|
||||
return { valid: true, skipped: true };
|
||||
}
|
||||
|
||||
try {
|
||||
const fresh = await takeFreshScreenshot();
|
||||
if (!fresh) {
|
||||
return { valid: true, skipped: true };
|
||||
}
|
||||
|
||||
const pixelsMatch = comparePixelAtLocation(
|
||||
crop,
|
||||
lastScreenshot,
|
||||
fresh,
|
||||
xPercent,
|
||||
yPercent,
|
||||
gridSize,
|
||||
);
|
||||
|
||||
if (pixelsMatch) {
|
||||
return { valid: true, skipped: false };
|
||||
}
|
||||
return {
|
||||
valid: false,
|
||||
skipped: false,
|
||||
warning:
|
||||
"Screen content at the target location changed since the last screenshot. Take a new screenshot before clicking.",
|
||||
};
|
||||
} catch (err) {
|
||||
// Skip validation on technical errors, execute action anyway.
|
||||
// Battle-tested: validation failure must never block the click.
|
||||
logger.debug("[pixelCompare] validation error, skipping", err);
|
||||
return { valid: true, skipped: true };
|
||||
}
|
||||
}
|
||||
43
claude-code-source/node_modules/@ant/computer-use-mcp/src/sentinelApps.ts
generated
vendored
43
claude-code-source/node_modules/@ant/computer-use-mcp/src/sentinelApps.ts
generated
vendored
@@ -1,43 +0,0 @@
|
||||
/**
|
||||
* Bundle IDs that are escalations-in-disguise. The approval UI shows a warning
|
||||
* badge for these; they are NOT blocked. Power users may legitimately want the
|
||||
* model controlling a terminal.
|
||||
*
|
||||
* Imported by the renderer via the `./sentinelApps` subpath (package.json
|
||||
* `exports`), which keeps Next.js from reaching index.ts → mcpServer.ts →
|
||||
* @modelcontextprotocol/sdk (devDep, would fail module resolution). Keep
|
||||
* this file import-free so the subpath stays clean.
|
||||
*/
|
||||
|
||||
/** These apps can execute arbitrary shell commands. */
|
||||
const SHELL_ACCESS_BUNDLE_IDS = new Set([
|
||||
"com.apple.Terminal",
|
||||
"com.googlecode.iterm2",
|
||||
"com.microsoft.VSCode",
|
||||
"dev.warp.Warp-Stable",
|
||||
"com.github.wez.wezterm",
|
||||
"io.alacritty",
|
||||
"net.kovidgoyal.kitty",
|
||||
"com.jetbrains.intellij",
|
||||
"com.jetbrains.pycharm",
|
||||
]);
|
||||
|
||||
/** Finder in the allowlist ≈ browse + open-any-file. */
|
||||
const FILESYSTEM_ACCESS_BUNDLE_IDS = new Set(["com.apple.finder"]);
|
||||
|
||||
const SYSTEM_SETTINGS_BUNDLE_IDS = new Set(["com.apple.systempreferences"]);
|
||||
|
||||
export const SENTINEL_BUNDLE_IDS: ReadonlySet<string> = new Set([
|
||||
...SHELL_ACCESS_BUNDLE_IDS,
|
||||
...FILESYSTEM_ACCESS_BUNDLE_IDS,
|
||||
...SYSTEM_SETTINGS_BUNDLE_IDS,
|
||||
]);
|
||||
|
||||
export type SentinelCategory = "shell" | "filesystem" | "system_settings";
|
||||
|
||||
export function getSentinelCategory(bundleId: string): SentinelCategory | null {
|
||||
if (SHELL_ACCESS_BUNDLE_IDS.has(bundleId)) return "shell";
|
||||
if (FILESYSTEM_ACCESS_BUNDLE_IDS.has(bundleId)) return "filesystem";
|
||||
if (SYSTEM_SETTINGS_BUNDLE_IDS.has(bundleId)) return "system_settings";
|
||||
return null;
|
||||
}
|
||||
3649
claude-code-source/node_modules/@ant/computer-use-mcp/src/toolCalls.ts
generated
vendored
3649
claude-code-source/node_modules/@ant/computer-use-mcp/src/toolCalls.ts
generated
vendored
File diff suppressed because it is too large
Load Diff
706
claude-code-source/node_modules/@ant/computer-use-mcp/src/tools.ts
generated
vendored
706
claude-code-source/node_modules/@ant/computer-use-mcp/src/tools.ts
generated
vendored
@@ -1,706 +0,0 @@
|
||||
/**
|
||||
* MCP tool schemas for the computer-use server. Mirrors
|
||||
* claude-for-chrome-mcp/src/browserTools.ts in shape (plain `Tool`-shaped
|
||||
* object literals, no zod).
|
||||
*
|
||||
* Coordinate descriptions are baked in at tool-list build time from the
|
||||
* `chicago_coordinate_mode` gate. The model sees exactly ONE coordinate
|
||||
* convention in the param descriptions and never learns the other exists.
|
||||
* The host (`serverDef.ts`) reads the same frozen gate value for
|
||||
* `scaleCoord` — both must agree or clicks land in the wrong space.
|
||||
*/
|
||||
|
||||
import type { Tool } from "@modelcontextprotocol/sdk/types.js";
|
||||
|
||||
import type { CoordinateMode } from "./types.js";
|
||||
|
||||
// See packages/desktop/computer-use-mcp/COORDINATES.md before touching any
|
||||
// model-facing coordinate text. Chrome's browserTools.ts:143 is the reference
|
||||
// phrasing — "pixels from the left edge", no geometry, no number to do math with.
|
||||
const COORD_DESC: Record<CoordinateMode, { x: string; y: string }> = {
|
||||
pixels: {
|
||||
x: "Horizontal pixel position read directly from the most recent screenshot image, measured from the left edge. The server handles all scaling.",
|
||||
y: "Vertical pixel position read directly from the most recent screenshot image, measured from the top edge. The server handles all scaling.",
|
||||
},
|
||||
normalized_0_100: {
|
||||
x: "Horizontal position as a percentage of screen width, 0.0–100.0 (0 = left edge, 100 = right edge).",
|
||||
y: "Vertical position as a percentage of screen height, 0.0–100.0 (0 = top edge, 100 = bottom edge).",
|
||||
},
|
||||
};
|
||||
|
||||
const FRONTMOST_GATE_DESC =
|
||||
"The frontmost application must be in the session allowlist at the time of this call, or this tool returns an error and does nothing.";
|
||||
|
||||
/**
|
||||
* Item schema for the `actions` array in `computer_batch`, `teach_step`, and
|
||||
* `teach_batch`. All three dispatch through the same `dispatchAction` path
|
||||
* with the same validation — keep this enum in sync with `BATCHABLE_ACTIONS`
|
||||
* in toolCalls.ts.
|
||||
*/
|
||||
const BATCH_ACTION_ITEM_SCHEMA = {
|
||||
type: "object",
|
||||
properties: {
|
||||
action: {
|
||||
type: "string",
|
||||
enum: [
|
||||
"key",
|
||||
"type",
|
||||
"mouse_move",
|
||||
"left_click",
|
||||
"left_click_drag",
|
||||
"right_click",
|
||||
"middle_click",
|
||||
"double_click",
|
||||
"triple_click",
|
||||
"scroll",
|
||||
"hold_key",
|
||||
"screenshot",
|
||||
"cursor_position",
|
||||
"left_mouse_down",
|
||||
"left_mouse_up",
|
||||
"wait",
|
||||
],
|
||||
description: "The action to perform.",
|
||||
},
|
||||
coordinate: {
|
||||
type: "array",
|
||||
items: { type: "number" },
|
||||
minItems: 2,
|
||||
maxItems: 2,
|
||||
description:
|
||||
"(x, y) for click/mouse_move/scroll/left_click_drag end point.",
|
||||
},
|
||||
start_coordinate: {
|
||||
type: "array",
|
||||
items: { type: "number" },
|
||||
minItems: 2,
|
||||
maxItems: 2,
|
||||
description:
|
||||
"(x, y) drag start — left_click_drag only. Omit to drag from current cursor.",
|
||||
},
|
||||
text: {
|
||||
type: "string",
|
||||
description:
|
||||
"For type: the text. For key/hold_key: the chord string. For click/scroll: modifier keys to hold.",
|
||||
},
|
||||
scroll_direction: {
|
||||
type: "string",
|
||||
enum: ["up", "down", "left", "right"],
|
||||
},
|
||||
scroll_amount: { type: "integer", minimum: 0, maximum: 100 },
|
||||
duration: {
|
||||
type: "number",
|
||||
description: "Seconds (0–100). For hold_key/wait.",
|
||||
},
|
||||
repeat: {
|
||||
type: "integer",
|
||||
minimum: 1,
|
||||
maximum: 100,
|
||||
description: "For key: repeat count.",
|
||||
},
|
||||
},
|
||||
required: ["action"],
|
||||
};
|
||||
|
||||
/**
|
||||
* Build the tool list. Parameterized by capabilities and coordinate mode so
|
||||
* descriptions are honest and unambiguous (plan §1 — "Unfiltered + honest").
|
||||
*
|
||||
* `coordinateMode` MUST match what the host passes to `scaleCoord` at tool-
|
||||
* -call time. Both should read the same frozen-at-load gate constant.
|
||||
*
|
||||
* `installedAppNames` — optional pre-sanitized list of app display names to
|
||||
* enumerate in the `request_access` description. The caller is responsible
|
||||
* for sanitization (length cap, character allowlist, sort, count cap) —
|
||||
* this function just splices the list into the description verbatim. Omit
|
||||
* to fall back to the generic "display names or bundle IDs" wording.
|
||||
*/
|
||||
export function buildComputerUseTools(
|
||||
caps: {
|
||||
screenshotFiltering: "native" | "none";
|
||||
platform: "darwin" | "win32";
|
||||
/** Include request_teach_access + teach_step. Read once at server construction. */
|
||||
teachMode?: boolean;
|
||||
},
|
||||
coordinateMode: CoordinateMode,
|
||||
installedAppNames?: string[],
|
||||
): Tool[] {
|
||||
const coord = COORD_DESC[coordinateMode];
|
||||
|
||||
// Shared hint suffix for BOTH request_access and request_teach_access —
|
||||
// they use the same resolveRequestedApps path, so the model should get
|
||||
// the same enumeration for both.
|
||||
const installedAppsHint =
|
||||
installedAppNames && installedAppNames.length > 0
|
||||
? ` Available applications on this machine: ${installedAppNames.join(", ")}.`
|
||||
: "";
|
||||
|
||||
// [x, y]` tuple — param shape for all
|
||||
// click/move/scroll tools.
|
||||
const coordinateTuple = {
|
||||
type: "array",
|
||||
items: { type: "number" },
|
||||
minItems: 2,
|
||||
maxItems: 2,
|
||||
description: `(x, y): ${coord.x}`,
|
||||
};
|
||||
// Modifier hold during click. Shared across all 5 click variants.
|
||||
const clickModifierText = {
|
||||
type: "string",
|
||||
description:
|
||||
'Modifier keys to hold during the click (e.g. "shift", "ctrl+shift"). Supports the same syntax as the key tool.',
|
||||
};
|
||||
|
||||
const screenshotDesc =
|
||||
caps.screenshotFiltering === "native"
|
||||
? "Take a screenshot of the primary display. Applications not in the session allowlist are excluded at the compositor level — only granted apps and the desktop are visible."
|
||||
: "Take a screenshot of the primary display. On this platform, screenshots are NOT filtered — all open windows are visible. Input actions targeting apps not in the session allowlist are rejected.";
|
||||
|
||||
return [
|
||||
{
|
||||
name: "request_access",
|
||||
description:
|
||||
"Request user permission to control a set of applications for this session. Must be called before any other tool in this server. " +
|
||||
"The user sees a single dialog listing all requested apps and either allows the whole set or denies it. " +
|
||||
"Call this again mid-session to add more apps; previously granted apps remain granted. " +
|
||||
"Returns the granted apps, denied apps, and screenshot filtering capability.",
|
||||
inputSchema: {
|
||||
type: "object" as const,
|
||||
properties: {
|
||||
apps: {
|
||||
type: "array",
|
||||
items: { type: "string" },
|
||||
description:
|
||||
"Application display names (e.g. \"Slack\", \"Calendar\") or bundle identifiers (e.g. \"com.tinyspeck.slackmacgap\"). Display names are resolved case-insensitively against installed apps." +
|
||||
installedAppsHint,
|
||||
},
|
||||
reason: {
|
||||
type: "string",
|
||||
description:
|
||||
"One-sentence explanation shown to the user in the approval dialog. Explain the task, not the mechanism.",
|
||||
},
|
||||
clipboardRead: {
|
||||
type: "boolean",
|
||||
description:
|
||||
"Also request permission to read the user's clipboard (separate checkbox in the dialog).",
|
||||
},
|
||||
clipboardWrite: {
|
||||
type: "boolean",
|
||||
description:
|
||||
"Also request permission to write the user's clipboard. When granted, multi-line `type` calls use the clipboard fast path.",
|
||||
},
|
||||
systemKeyCombos: {
|
||||
type: "boolean",
|
||||
description:
|
||||
"Also request permission to send system-level key combos (quit app, switch app, lock screen). Without this, those specific combos are blocked.",
|
||||
},
|
||||
},
|
||||
required: ["apps", "reason"],
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "screenshot",
|
||||
description:
|
||||
screenshotDesc +
|
||||
" Returns an error if the allowlist is empty. The returned image is what subsequent click coordinates are relative to.",
|
||||
inputSchema: {
|
||||
type: "object" as const,
|
||||
properties: {
|
||||
save_to_disk: {
|
||||
type: "boolean",
|
||||
description:
|
||||
"Save the image to disk so it can be attached to a message for the user. Returns the saved path in the tool result. Only set this when you intend to share the image — screenshots you're just looking at don't need saving.",
|
||||
},
|
||||
},
|
||||
required: [],
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "zoom",
|
||||
description:
|
||||
"Take a higher-resolution screenshot of a specific region of the last full-screen screenshot. Use this liberally to inspect small text, button labels, or fine UI details that are hard to read in the downsampled full-screen image. " +
|
||||
"IMPORTANT: Coordinates in subsequent click calls always refer to the full-screen screenshot, never the zoomed image. This tool is read-only for inspecting detail.",
|
||||
inputSchema: {
|
||||
type: "object" as const,
|
||||
properties: {
|
||||
region: {
|
||||
type: "array",
|
||||
items: { type: "integer" },
|
||||
minItems: 4,
|
||||
maxItems: 4,
|
||||
description:
|
||||
"(x0, y0, x1, y1): Rectangle to zoom into, in the coordinate space of the most recent full-screen screenshot. x0,y0 = top-left, x1,y1 = bottom-right.",
|
||||
},
|
||||
save_to_disk: {
|
||||
type: "boolean",
|
||||
description:
|
||||
"Save the image to disk so it can be attached to a message for the user. Returns the saved path in the tool result. Only set this when you intend to share the image.",
|
||||
},
|
||||
},
|
||||
required: ["region"],
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "left_click",
|
||||
description: `Left-click at the given coordinates. ${FRONTMOST_GATE_DESC}`,
|
||||
inputSchema: {
|
||||
type: "object" as const,
|
||||
properties: {
|
||||
coordinate: coordinateTuple,
|
||||
text: clickModifierText,
|
||||
},
|
||||
required: ["coordinate"],
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "double_click",
|
||||
description: `Double-click at the given coordinates. Selects a word in most text editors. ${FRONTMOST_GATE_DESC}`,
|
||||
inputSchema: {
|
||||
type: "object" as const,
|
||||
properties: {
|
||||
coordinate: coordinateTuple,
|
||||
text: clickModifierText,
|
||||
},
|
||||
required: ["coordinate"],
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "triple_click",
|
||||
description: `Triple-click at the given coordinates. Selects a line in most text editors. ${FRONTMOST_GATE_DESC}`,
|
||||
inputSchema: {
|
||||
type: "object" as const,
|
||||
properties: {
|
||||
coordinate: coordinateTuple,
|
||||
text: clickModifierText,
|
||||
},
|
||||
required: ["coordinate"],
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "right_click",
|
||||
description: `Right-click at the given coordinates. Opens a context menu in most applications. ${FRONTMOST_GATE_DESC}`,
|
||||
inputSchema: {
|
||||
type: "object" as const,
|
||||
properties: {
|
||||
coordinate: coordinateTuple,
|
||||
text: clickModifierText,
|
||||
},
|
||||
required: ["coordinate"],
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "middle_click",
|
||||
description: `Middle-click (scroll-wheel click) at the given coordinates. ${FRONTMOST_GATE_DESC}`,
|
||||
inputSchema: {
|
||||
type: "object" as const,
|
||||
properties: {
|
||||
coordinate: coordinateTuple,
|
||||
text: clickModifierText,
|
||||
},
|
||||
required: ["coordinate"],
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "type",
|
||||
description: `Type text into whatever currently has keyboard focus. ${FRONTMOST_GATE_DESC} Newlines are supported. For keyboard shortcuts use \`key\` instead.`,
|
||||
inputSchema: {
|
||||
type: "object" as const,
|
||||
properties: {
|
||||
text: { type: "string", description: "Text to type." },
|
||||
},
|
||||
required: ["text"],
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "key",
|
||||
description:
|
||||
`Press a key or key combination (e.g. "return", "escape", "cmd+a", "ctrl+shift+tab"). ${FRONTMOST_GATE_DESC} ` +
|
||||
"System-level combos (quit app, switch app, lock screen) require the `systemKeyCombos` grant — without it they return an error. All other combos work.",
|
||||
inputSchema: {
|
||||
type: "object" as const,
|
||||
properties: {
|
||||
text: {
|
||||
type: "string",
|
||||
description: 'Modifiers joined with "+", e.g. "cmd+shift+a".',
|
||||
},
|
||||
repeat: {
|
||||
type: "integer",
|
||||
minimum: 1,
|
||||
maximum: 100,
|
||||
description: "Number of times to repeat the key press. Default is 1.",
|
||||
},
|
||||
},
|
||||
required: ["text"],
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "scroll",
|
||||
description: `Scroll at the given coordinates. ${FRONTMOST_GATE_DESC}`,
|
||||
inputSchema: {
|
||||
type: "object" as const,
|
||||
properties: {
|
||||
coordinate: coordinateTuple,
|
||||
scroll_direction: {
|
||||
type: "string",
|
||||
enum: ["up", "down", "left", "right"],
|
||||
description: "Direction to scroll.",
|
||||
},
|
||||
scroll_amount: {
|
||||
type: "integer",
|
||||
minimum: 0,
|
||||
maximum: 100,
|
||||
description: "Number of scroll ticks.",
|
||||
},
|
||||
},
|
||||
required: ["coordinate", "scroll_direction", "scroll_amount"],
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "left_click_drag",
|
||||
description: `Press, move to target, and release. ${FRONTMOST_GATE_DESC}`,
|
||||
inputSchema: {
|
||||
type: "object" as const,
|
||||
properties: {
|
||||
coordinate: {
|
||||
...coordinateTuple,
|
||||
description: `(x, y) end point: ${coord.x}`,
|
||||
},
|
||||
start_coordinate: {
|
||||
...coordinateTuple,
|
||||
description: `(x, y) start point. If omitted, drags from the current cursor position. ${coord.x}`,
|
||||
},
|
||||
},
|
||||
required: ["coordinate"],
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "mouse_move",
|
||||
description: `Move the mouse cursor without clicking. Useful for triggering hover states. ${FRONTMOST_GATE_DESC}`,
|
||||
inputSchema: {
|
||||
type: "object" as const,
|
||||
properties: {
|
||||
coordinate: coordinateTuple,
|
||||
},
|
||||
required: ["coordinate"],
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "open_application",
|
||||
description:
|
||||
"Bring an application to the front, launching it if necessary. The target application must already be in the session allowlist — call request_access first.",
|
||||
inputSchema: {
|
||||
type: "object" as const,
|
||||
properties: {
|
||||
app: {
|
||||
type: "string",
|
||||
description:
|
||||
"Display name (e.g. \"Slack\") or bundle identifier (e.g. \"com.tinyspeck.slackmacgap\").",
|
||||
},
|
||||
},
|
||||
required: ["app"],
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "switch_display",
|
||||
description:
|
||||
"Switch which monitor subsequent screenshots capture. Use this when the " +
|
||||
"application you need is on a different monitor than the one shown. " +
|
||||
"The screenshot tool tells you which monitor it captured and lists " +
|
||||
"other attached monitors by name — pass one of those names here. " +
|
||||
"After switching, call screenshot to see the new monitor. " +
|
||||
'Pass "auto" to return to automatic monitor selection.',
|
||||
inputSchema: {
|
||||
type: "object" as const,
|
||||
properties: {
|
||||
display: {
|
||||
type: "string",
|
||||
description:
|
||||
'Monitor name from the screenshot note (e.g. "Built-in Retina Display", ' +
|
||||
'"LG UltraFine"), or "auto" to re-enable automatic selection.',
|
||||
},
|
||||
},
|
||||
required: ["display"],
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "list_granted_applications",
|
||||
description:
|
||||
"List the applications currently in the session allowlist, plus the active grant flags and coordinate mode. No side effects.",
|
||||
inputSchema: {
|
||||
type: "object" as const,
|
||||
properties: {},
|
||||
required: [],
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "read_clipboard",
|
||||
description:
|
||||
"Read the current clipboard contents as text. Requires the `clipboardRead` grant.",
|
||||
inputSchema: {
|
||||
type: "object" as const,
|
||||
properties: {},
|
||||
required: [],
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "write_clipboard",
|
||||
description:
|
||||
"Write text to the clipboard. Requires the `clipboardWrite` grant.",
|
||||
inputSchema: {
|
||||
type: "object" as const,
|
||||
properties: {
|
||||
text: { type: "string" },
|
||||
},
|
||||
required: ["text"],
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "wait",
|
||||
description: "Wait for a specified duration.",
|
||||
inputSchema: {
|
||||
type: "object" as const,
|
||||
properties: {
|
||||
duration: {
|
||||
type: "number",
|
||||
description: "Duration in seconds (0–100).",
|
||||
},
|
||||
},
|
||||
required: ["duration"],
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "cursor_position",
|
||||
description:
|
||||
"Get the current mouse cursor position. Returns image-pixel coordinates relative to the most recent screenshot, or logical points if no screenshot has been taken.",
|
||||
inputSchema: {
|
||||
type: "object" as const,
|
||||
properties: {},
|
||||
required: [],
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "hold_key",
|
||||
description:
|
||||
`Press and hold a key or key combination for the specified duration, then release. ${FRONTMOST_GATE_DESC} ` +
|
||||
"System-level combos require the `systemKeyCombos` grant.",
|
||||
inputSchema: {
|
||||
type: "object" as const,
|
||||
properties: {
|
||||
text: {
|
||||
type: "string",
|
||||
description: 'Key or chord to hold, e.g. "space", "shift+down".',
|
||||
},
|
||||
duration: {
|
||||
type: "number",
|
||||
description: "Duration in seconds (0–100).",
|
||||
},
|
||||
},
|
||||
required: ["text", "duration"],
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "left_mouse_down",
|
||||
description:
|
||||
`Press the left mouse button at the current cursor position and leave it held. ${FRONTMOST_GATE_DESC} ` +
|
||||
"Use mouse_move first to position the cursor. Call left_mouse_up to release. Errors if the button is already held.",
|
||||
inputSchema: {
|
||||
type: "object" as const,
|
||||
properties: {},
|
||||
required: [],
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "left_mouse_up",
|
||||
description:
|
||||
`Release the left mouse button at the current cursor position. ${FRONTMOST_GATE_DESC} ` +
|
||||
"Pairs with left_mouse_down. Safe to call even if the button is not currently held.",
|
||||
inputSchema: {
|
||||
type: "object" as const,
|
||||
properties: {},
|
||||
required: [],
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "computer_batch",
|
||||
description:
|
||||
"Execute a sequence of actions in ONE tool call. Each individual tool call requires a model→API round trip (seconds); " +
|
||||
"batching a predictable sequence eliminates all but one. Use this whenever you can predict the outcome of several actions ahead — " +
|
||||
"e.g. click a field, type into it, press Return. Actions execute sequentially and stop on the first error. " +
|
||||
`${FRONTMOST_GATE_DESC} The frontmost check runs before EACH action inside the batch — if an action opens a non-allowed app, the next action's gate fires and the batch stops there. ` +
|
||||
"Mid-batch screenshot actions are allowed for inspection but coordinates in subsequent clicks always refer to the PRE-BATCH full-screen screenshot.",
|
||||
inputSchema: {
|
||||
type: "object" as const,
|
||||
properties: {
|
||||
actions: {
|
||||
type: "array",
|
||||
minItems: 1,
|
||||
items: BATCH_ACTION_ITEM_SCHEMA,
|
||||
description:
|
||||
'List of actions. Example: [{"action":"left_click","coordinate":[100,200]},{"action":"type","text":"hello"},{"action":"key","text":"Return"}]',
|
||||
},
|
||||
},
|
||||
required: ["actions"],
|
||||
},
|
||||
},
|
||||
|
||||
...(caps.teachMode ? buildTeachTools(coord, installedAppsHint) : []),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Teach-mode tools. Split out so the spread above stays a single expression;
|
||||
* takes `coord` so `teach_step.anchor`'s description uses the same
|
||||
* frozen coordinate-mode phrasing as click coords, and `installedAppsHint`
|
||||
* so `request_teach_access.apps` gets the same enumeration as
|
||||
* `request_access.apps` (same resolution path → same hint).
|
||||
*/
|
||||
function buildTeachTools(
|
||||
coord: { x: string; y: string },
|
||||
installedAppsHint: string,
|
||||
): Tool[] {
|
||||
// Shared between teach_step (top-level) and teach_batch (inside steps[]
|
||||
// items). Depends on coord, so it lives inside this factory.
|
||||
const teachStepProperties = {
|
||||
explanation: {
|
||||
type: "string",
|
||||
description:
|
||||
"Tooltip body text. Explain what the user is looking at and why it matters. " +
|
||||
"This is the ONLY place the user sees your words — be complete but concise.",
|
||||
},
|
||||
next_preview: {
|
||||
type: "string",
|
||||
description:
|
||||
"One line describing exactly what will happen when the user clicks Next. " +
|
||||
'Example: "Next: I\'ll click Create Bucket and type the name." ' +
|
||||
"Shown below the explanation in a smaller font.",
|
||||
},
|
||||
anchor: {
|
||||
type: "array",
|
||||
items: { type: "number" },
|
||||
minItems: 2,
|
||||
maxItems: 2,
|
||||
description:
|
||||
`(x, y) — where the tooltip arrow points. ${coord.x} ` +
|
||||
"Omit to center the tooltip with no arrow (for general-context steps).",
|
||||
},
|
||||
actions: {
|
||||
type: "array",
|
||||
// Empty allowed — "read this, click Next" steps.
|
||||
items: BATCH_ACTION_ITEM_SCHEMA,
|
||||
description:
|
||||
"Actions to execute when the user clicks Next. Same item schema as computer_batch.actions. " +
|
||||
"Empty array is valid for purely explanatory steps. Actions run sequentially and stop on first error.",
|
||||
},
|
||||
} as const;
|
||||
|
||||
return [
|
||||
{
|
||||
name: "request_teach_access",
|
||||
description:
|
||||
"Request permission to guide the user through a task step-by-step with on-screen tooltips. " +
|
||||
"Use this INSTEAD OF request_access when the user wants to LEARN how to do something " +
|
||||
'(phrases like "teach me", "walk me through", "show me how", "help me learn"). ' +
|
||||
"On approval the main Claude window hides and a fullscreen tooltip overlay appears. " +
|
||||
"You then call teach_step repeatedly; each call shows one tooltip and waits for the user to click Next. " +
|
||||
"Same app-allowlist semantics as request_access, but no clipboard/system-key flags. " +
|
||||
"Teach mode ends automatically when your turn ends.",
|
||||
inputSchema: {
|
||||
type: "object" as const,
|
||||
properties: {
|
||||
apps: {
|
||||
type: "array",
|
||||
items: { type: "string" },
|
||||
description:
|
||||
'Application display names (e.g. "Slack", "Calendar") or bundle identifiers. Resolved case-insensitively against installed apps.' +
|
||||
installedAppsHint,
|
||||
},
|
||||
reason: {
|
||||
type: "string",
|
||||
description:
|
||||
'What you will be teaching. Shown in the approval dialog as "Claude wants to guide you through {reason}". Keep it short and task-focused.',
|
||||
},
|
||||
},
|
||||
required: ["apps", "reason"],
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "teach_step",
|
||||
description:
|
||||
"Show one guided-tour tooltip and wait for the user to click Next. On Next, execute the actions, " +
|
||||
"take a fresh screenshot, and return both — you do NOT need a separate screenshot call between steps. " +
|
||||
"The returned image shows the state after your actions ran; anchor the next teach_step against it. " +
|
||||
"IMPORTANT — the user only sees the tooltip during teach mode. Put ALL narration in `explanation`. " +
|
||||
"Text you emit outside teach_step calls is NOT visible until teach mode ends. " +
|
||||
"Pack as many actions as possible into each step's `actions` array — the user waits through " +
|
||||
"the whole round trip between clicks, so one step that fills a form beats five steps that fill one field each. " +
|
||||
"Returns {exited:true} if the user clicks Exit — do not call teach_step again after that. " +
|
||||
"Take an initial screenshot before your FIRST teach_step to anchor it.",
|
||||
inputSchema: {
|
||||
type: "object" as const,
|
||||
properties: teachStepProperties,
|
||||
required: ["explanation", "next_preview", "actions"],
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "teach_batch",
|
||||
description:
|
||||
"Queue multiple teach steps in one tool call. Parallels computer_batch: " +
|
||||
"N steps → one model↔API round trip instead of N. Each step still shows a tooltip " +
|
||||
"and waits for the user's Next click, but YOU aren't waiting for a round trip between steps. " +
|
||||
"You can call teach_batch multiple times in one tour — treat each batch as one predictable " +
|
||||
"SEGMENT (typically: all the steps on one page). The returned screenshot shows the state " +
|
||||
"after the batch's final actions; anchor the NEXT teach_batch against it. " +
|
||||
"WITHIN a batch, all anchors and click coordinates refer to the PRE-BATCH screenshot " +
|
||||
"(same invariant as computer_batch) — for steps 2+ in a batch, either omit anchor " +
|
||||
"(centered tooltip) or target elements you know won't have moved. " +
|
||||
"Good pattern: batch 5 tooltips on page A (last step navigates) → read returned screenshot → " +
|
||||
"batch 3 tooltips on page B → done. " +
|
||||
"Returns {exited:true, stepsCompleted:N} if the user clicks Exit — do NOT call again after that; " +
|
||||
"{stepsCompleted, stepFailed, ...} if an action errors mid-batch; " +
|
||||
"otherwise {stepsCompleted, results:[...]} plus a final screenshot. " +
|
||||
"Fall back to individual teach_step calls when you need to react to each intermediate screenshot.",
|
||||
inputSchema: {
|
||||
type: "object" as const,
|
||||
properties: {
|
||||
steps: {
|
||||
type: "array",
|
||||
minItems: 1,
|
||||
items: {
|
||||
type: "object",
|
||||
properties: teachStepProperties,
|
||||
required: ["explanation", "next_preview", "actions"],
|
||||
},
|
||||
description:
|
||||
"Ordered steps. Validated upfront — a typo in step 5 errors before any tooltip shows.",
|
||||
},
|
||||
},
|
||||
required: ["steps"],
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
622
claude-code-source/node_modules/@ant/computer-use-mcp/src/types.ts
generated
vendored
622
claude-code-source/node_modules/@ant/computer-use-mcp/src/types.ts
generated
vendored
@@ -1,622 +0,0 @@
|
||||
import type {
|
||||
ComputerExecutor,
|
||||
InstalledApp,
|
||||
ScreenshotResult,
|
||||
} from "./executor.js";
|
||||
|
||||
/** `ScreenshotResult` without the base64 blob. The shape hosts persist for
|
||||
* cross-respawn `scaleCoord` survival. */
|
||||
export type ScreenshotDims = Omit<ScreenshotResult, "base64">;
|
||||
|
||||
/** Shape mirrors claude-for-chrome-mcp/src/types.ts:1-7 */
|
||||
export interface Logger {
|
||||
info: (message: string, ...args: unknown[]) => void;
|
||||
error: (message: string, ...args: unknown[]) => void;
|
||||
warn: (message: string, ...args: unknown[]) => void;
|
||||
debug: (message: string, ...args: unknown[]) => void;
|
||||
silly: (message: string, ...args: unknown[]) => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Per-app permission tier. Hardcoded by category at grant time — the
|
||||
* approval dialog displays the tier but the user cannot change it (for now).
|
||||
*
|
||||
* - `"read"` — visible in screenshots, NO interaction (no clicks, no typing).
|
||||
* Browsers land here: the model can read a page that's already open, but
|
||||
* must use the Claude-in-Chrome MCP for any navigation/clicking. Trading
|
||||
* platforms land here too (no CiC alternative — the model asks the user).
|
||||
* - `"click"` — visible + plain left-click, scroll. NO typing/keys,
|
||||
* NO right/middle-click, NO modifier-clicks, NO drag-drop (all text-
|
||||
* injection vectors). Terminals/IDEs land here: the model can click a
|
||||
* Run button or scroll test output, but `type("rm -rf /")` is blocked
|
||||
* and so is right-click→Paste and dragging text onto the terminal.
|
||||
* - `"full"` — visible + click + type/key/paste. Everything else.
|
||||
*
|
||||
* Enforced in `runInputActionGates` via the frontmost-app check: keyboard
|
||||
* actions require `"full"`, mouse actions require `"click"` or higher.
|
||||
*/
|
||||
export type CuAppPermTier = "read" | "click" | "full";
|
||||
|
||||
/**
|
||||
* A single app the user has approved for the current session. Session-scoped
|
||||
* only — there is no "once" or "forever" scope (unlike Chrome's per-domain
|
||||
* three-way). CU has no natural "once" unit; one task = hundreds of clicks.
|
||||
* Mirrors how `chromeAllowedDomains` is a plain `string[]` with no per-item
|
||||
* scope.
|
||||
*/
|
||||
export interface AppGrant {
|
||||
bundleId: string;
|
||||
displayName: string;
|
||||
/** Epoch ms. For Settings-page display ("Granted 3m ago"). */
|
||||
grantedAt: number;
|
||||
/** Undefined → `"full"` (back-compat for pre-tier grants persisted in
|
||||
* session state). */
|
||||
tier?: CuAppPermTier;
|
||||
}
|
||||
|
||||
/** Orthogonal to the app allowlist. */
|
||||
export interface CuGrantFlags {
|
||||
clipboardRead: boolean;
|
||||
clipboardWrite: boolean;
|
||||
/**
|
||||
* When false, the `key` tool rejects combos in `keyBlocklist.ts`
|
||||
* (cmd+q, cmd+tab, cmd+space, cmd+shift+q, ctrl+alt+delete). All other
|
||||
* key sequences work regardless.
|
||||
*/
|
||||
systemKeyCombos: boolean;
|
||||
}
|
||||
|
||||
export const DEFAULT_GRANT_FLAGS: CuGrantFlags = {
|
||||
clipboardRead: false,
|
||||
clipboardWrite: false,
|
||||
systemKeyCombos: false,
|
||||
};
|
||||
|
||||
/**
|
||||
* Host picks via GrowthBook JSON feature `chicago_coordinate_mode`, baked
|
||||
* into tool param descriptions at server-construction time. The model sees
|
||||
* ONE convention and never learns the other exists. `normalized_0_100`
|
||||
* sidesteps the Retina scaleFactor bug class entirely.
|
||||
*/
|
||||
export type CoordinateMode = "pixels" | "normalized_0_100";
|
||||
|
||||
/**
|
||||
* Independent kill switches for subtle/risky ported behaviors. Read from
|
||||
* GrowthBook by the host adapter, consulted in `toolCalls.ts`.
|
||||
*/
|
||||
export interface CuSubGates {
|
||||
/** 9×9 exact-byte staleness guard before click. */
|
||||
pixelValidation: boolean;
|
||||
/** Route `type("foo\nbar")` through clipboard instead of keystroke-by-keystroke. */
|
||||
clipboardPasteMultiline: boolean;
|
||||
/**
|
||||
* Ease-out-cubic mouse glide at 60fps, distance-proportional duration
|
||||
* (2000 px/sec, capped at 0.5s). Adds up to ~0.5s latency
|
||||
* per click. When off, cursor teleports instantly.
|
||||
*/
|
||||
mouseAnimation: boolean;
|
||||
/**
|
||||
* Pre-action sequence: hide non-allowlisted apps, then defocus us (from the
|
||||
* Vercept acquisition). When off, the
|
||||
* frontmost gate fires in the normal case and the model gets stuck — this
|
||||
* is the A/B-test-the-old-broken-behavior switch.
|
||||
*/
|
||||
hideBeforeAction: boolean;
|
||||
/**
|
||||
* Auto-resolve the target display before each screenshot when the
|
||||
* selected display has no allowed-app windows. When on, `handleScreenshot`
|
||||
* uses the atomic Swift path; off → sticks with `selectedDisplayId`.
|
||||
*/
|
||||
autoTargetDisplay: boolean;
|
||||
/**
|
||||
* Stash+clear the clipboard while a tier-"click" app is frontmost.
|
||||
* Closes the gap where a click-tier terminal/IDE has a UI Paste button
|
||||
* that's plain-left-clickable — without this, the tier "click"
|
||||
* keyboard block can be routed around by clicking Paste. Restored when
|
||||
* a non-"click" app becomes frontmost, or at turn end.
|
||||
*/
|
||||
clipboardGuard: boolean;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Permission request/response (mirror of BridgePermissionRequest, types.ts:77-94)
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/** One entry per app the model asked for, after name → bundle ID resolution. */
|
||||
export interface ResolvedAppRequest {
|
||||
/** What the model asked for (e.g. "Slack", "com.tinyspeck.slackmacgap"). */
|
||||
requestedName: string;
|
||||
/** The resolved InstalledApp if found, else undefined (shown greyed in the UI). */
|
||||
resolved?: InstalledApp;
|
||||
/** Shell-access-equivalent bundle IDs get a UI warning. See sentinelApps.ts. */
|
||||
isSentinel: boolean;
|
||||
/** Already in the allowlist → skip the checkbox, return in `granted` immediately. */
|
||||
alreadyGranted: boolean;
|
||||
/** Hardcoded tier for this app (browser→"read", terminal→"click", else "full").
|
||||
* The dialog displays this read-only; the renderer passes it through
|
||||
* verbatim in the AppGrant. */
|
||||
proposedTier: CuAppPermTier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Payload for the renderer approval dialog. Rides through the existing
|
||||
* `ToolPermissionRequest.input: unknown` field
|
||||
* (packages/utils/desktop/bridge/common/claude.web.ts:1262) — no IPC schema
|
||||
* change needed.
|
||||
*/
|
||||
export interface CuPermissionRequest {
|
||||
requestId: string;
|
||||
/** Model-provided reason string. Shown prominently in the approval UI. */
|
||||
reason: string;
|
||||
apps: ResolvedAppRequest[];
|
||||
/** What the model asked for. User can toggle independently of apps. */
|
||||
requestedFlags: Partial<CuGrantFlags>;
|
||||
/**
|
||||
* For the "On Windows, Claude can see all apps..." footnote. Taken from
|
||||
* `executor.capabilities.screenshotFiltering` so the renderer doesn't
|
||||
* need to know about platforms.
|
||||
*/
|
||||
screenshotFiltering: "native" | "none";
|
||||
/**
|
||||
* Present only when TCC permissions are NOT yet granted. When present,
|
||||
* the renderer shows a TCC toggle panel (two rows: Accessibility, Screen
|
||||
* Recording) INSTEAD OF the app list. Clicking a row's "Request" button
|
||||
* triggers the OS prompt; the store polls on window-focus and flips the
|
||||
* toggle when the grant is detected. macOS itself prompts the user to
|
||||
* restart after granting Screen Recording — we don't.
|
||||
*/
|
||||
tccState?: {
|
||||
accessibility: boolean;
|
||||
screenRecording: boolean;
|
||||
};
|
||||
/**
|
||||
* Apps with windows on the CU display that aren't in the requested
|
||||
* allowlist. These will be hidden the first time Claude takes an action.
|
||||
* Computed at request_access time — may be slightly stale by the time the
|
||||
* user clicks Allow, but it's a preview, not a contract. Absent when
|
||||
* empty so the renderer can skip the section cleanly.
|
||||
*/
|
||||
willHide?: Array<{ bundleId: string; displayName: string }>;
|
||||
/**
|
||||
* `chicagoAutoUnhide` app preference at request time. The renderer picks
|
||||
* between "...then restored when Claude is done" and "...will be hidden"
|
||||
* copy. Absent when `willHide` is absent (same condition).
|
||||
*/
|
||||
autoUnhideEnabled?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* What the renderer stuffs into `updatedInput._cuGrants` when the user clicks
|
||||
* "Allow for this session" (mirror of the `_allowAllSites` sentinel at
|
||||
* LocalAgentModeSessionManager.ts:2794).
|
||||
*/
|
||||
export interface CuPermissionResponse {
|
||||
granted: AppGrant[];
|
||||
/** Bundle IDs the user unchecked, or apps that weren't installed. */
|
||||
denied: Array<{ bundleId: string; reason: "user_denied" | "not_installed" }>;
|
||||
flags: CuGrantFlags;
|
||||
/**
|
||||
* Whether the user clicked Allow in THIS dialog. Only set by the
|
||||
* teach-mode handler — regular request_access doesn't need it (the
|
||||
* session manager's `result.behavior` gates the merge there). Needed
|
||||
* because when all requested apps are already granted (skipDialogGrants
|
||||
* non-empty, needDialog empty), Allow and Deny produce identical
|
||||
* `{granted:[], denied:[]}` payloads and the tool handler can't tell
|
||||
* them apart without this. Undefined → legacy/regular path, do not
|
||||
* gate on it.
|
||||
*/
|
||||
userConsented?: boolean;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Host adapter (mirror of ClaudeForChromeContext, types.ts:33-62)
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Process-lifetime singleton dependencies. Everything that does NOT vary per
|
||||
* tool call. Built once by `apps/desktop/src/main/nest-only/chicago/hostAdapter.ts`.
|
||||
* No Electron imports in this package — the host injects everything.
|
||||
*/
|
||||
export interface ComputerUseHostAdapter {
|
||||
serverName: string;
|
||||
logger: Logger;
|
||||
executor: ComputerExecutor;
|
||||
|
||||
/**
|
||||
* TCC state check — Accessibility + Screen Recording on macOS. Pure check,
|
||||
* no dialog, no relaunch. When either is missing, `request_access` threads
|
||||
* the state through to the renderer which shows a toggle panel; all other
|
||||
* tools return a tool error.
|
||||
*/
|
||||
ensureOsPermissions(): Promise<
|
||||
| { granted: true }
|
||||
| { granted: false; accessibility: boolean; screenRecording: boolean }
|
||||
>;
|
||||
|
||||
/** The Settings-page kill switch (`chicagoEnabled` app preference). */
|
||||
isDisabled(): boolean;
|
||||
|
||||
/**
|
||||
* The `chicagoAutoUnhide` app preference. Consumed by `buildAccessRequest`
|
||||
* to populate `CuPermissionRequest.autoUnhideEnabled` so the renderer's
|
||||
* "will be hidden" copy can say "then restored" only when true.
|
||||
*/
|
||||
getAutoUnhideEnabled(): boolean;
|
||||
|
||||
/**
|
||||
* Sub-gates re-read on every tool call so GrowthBook flips take effect
|
||||
* mid-session without restart.
|
||||
*/
|
||||
getSubGates(): CuSubGates;
|
||||
|
||||
/**
|
||||
* JPEG decode + crop + raw pixel bytes, for the PixelCompare staleness guard.
|
||||
* Injected so this package stays Electron-free. The host implements it via
|
||||
* `nativeImage.createFromBuffer(jpeg).crop(rect).toBitmap()` — Chromium's
|
||||
* decoders, BSD-licensed, no `.node` binary.
|
||||
*
|
||||
* Returns null on decode/crop failure — caller treats null as `skipped`,
|
||||
* click proceeds (validation failure must never block the action).
|
||||
*/
|
||||
cropRawPatch(
|
||||
jpegBase64: string,
|
||||
rect: { x: number; y: number; width: number; height: number },
|
||||
): Buffer | null;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Session context (getter/callback bag for bindSessionContext)
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Per-session state binding for `bindSessionContext`. Hosts build this once
|
||||
* per session with getters that read fresh from their session store and
|
||||
* callbacks that write back. The returned dispatcher builds
|
||||
* `ComputerUseOverrides` from these getters on every call.
|
||||
*
|
||||
* Callbacks must be set at construction time — `bindSessionContext` reads
|
||||
* them once at bind, not per call.
|
||||
*
|
||||
* The lock hooks are **async** — `bindSessionContext` awaits them before
|
||||
* `handleToolCall`, then passes `checkCuLock: undefined` in overrides so the
|
||||
* sync Gate-3 in `handleToolCall` no-ops. Hosts with in-memory sync locks
|
||||
* (Cowork) wrap them trivially; hosts with cross-process locks (the CLI's
|
||||
* O_EXCL file) call the real async primitive directly.
|
||||
*/
|
||||
export interface ComputerUseSessionContext {
|
||||
// ── Read state fresh per call ──────────────────────────────────────
|
||||
|
||||
getAllowedApps(): readonly AppGrant[];
|
||||
getGrantFlags(): CuGrantFlags;
|
||||
/** Per-user auto-deny list (Settings page). Empty array = none. */
|
||||
getUserDeniedBundleIds(): readonly string[];
|
||||
getSelectedDisplayId(): number | undefined;
|
||||
getDisplayPinnedByModel?(): boolean;
|
||||
getDisplayResolvedForApps?(): string | undefined;
|
||||
getTeachModeActive?(): boolean;
|
||||
/** Dims-only fallback when `lastScreenshot` is unset (cross-respawn).
|
||||
* `bindSessionContext` reconstructs `{...dims, base64: ""}` so scaleCoord
|
||||
* works and pixelCompare correctly skips. */
|
||||
getLastScreenshotDims?(): ScreenshotDims | undefined;
|
||||
|
||||
// ── Write-back callbacks ───────────────────────────────────────────
|
||||
|
||||
/** Shows the approval dialog. Host routes to its UI, awaits user. The
|
||||
* signal is aborted if the tool call finishes before the user answers
|
||||
* (MCP timeout, etc.) — hosts dismiss the dialog on abort. */
|
||||
onPermissionRequest?(
|
||||
req: CuPermissionRequest,
|
||||
signal: AbortSignal,
|
||||
): Promise<CuPermissionResponse>;
|
||||
/** Teach-mode sibling of `onPermissionRequest`. */
|
||||
onTeachPermissionRequest?(
|
||||
req: CuTeachPermissionRequest,
|
||||
signal: AbortSignal,
|
||||
): Promise<CuPermissionResponse>;
|
||||
/** Called by `bindSessionContext` after merging a permission response into
|
||||
* the allowlist (dedupe on bundleId, truthy-only flag spread). Host
|
||||
* persists for resume survival. */
|
||||
onAllowedAppsChanged?(apps: readonly AppGrant[], flags: CuGrantFlags): void;
|
||||
onAppsHidden?(bundleIds: string[]): void;
|
||||
/** Reads the session's clipboardGuard stash. undefined → no stash held. */
|
||||
getClipboardStash?(): string | undefined;
|
||||
/** Writes the clipboardGuard stash. undefined clears it. */
|
||||
onClipboardStashChanged?(stash: string | undefined): void;
|
||||
onResolvedDisplayUpdated?(displayId: number): void;
|
||||
onDisplayPinned?(displayId: number | undefined): void;
|
||||
onDisplayResolvedForApps?(sortedBundleIdsKey: string): void;
|
||||
/** Called after each screenshot. Host persists for respawn survival. */
|
||||
onScreenshotCaptured?(dims: ScreenshotDims): void;
|
||||
onTeachModeActivated?(): void;
|
||||
onTeachStep?(req: TeachStepRequest): Promise<TeachStepResult>;
|
||||
onTeachWorking?(): void;
|
||||
|
||||
// ── Lock (async) ───────────────────────────────────────────────────
|
||||
|
||||
/** At most one session uses CU at a time. Awaited by `bindSessionContext`
|
||||
* before dispatch. Undefined → no lock gating (proceed). */
|
||||
checkCuLock?(): Promise<{ holder: string | undefined; isSelf: boolean }>;
|
||||
/** Take the lock. Called when `checkCuLock` returned `holder: undefined`
|
||||
* on a non-deferring tool. Host emits enter-CU signals here. */
|
||||
acquireCuLock?(): Promise<void>;
|
||||
/** Host-specific lock-held error text. Default is the package's generic
|
||||
* message. The CLI host includes the holder session-ID prefix. */
|
||||
formatLockHeldMessage?(holder: string): string;
|
||||
|
||||
/** User-abort signal. Passed through to `ComputerUseOverrides.isAborted`
|
||||
* for the mid-loop checks in handleComputerBatch / handleType. See that
|
||||
* field for semantics. */
|
||||
isAborted?(): boolean;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Per-call overrides (mirror of PermissionOverrides, types.ts:97-102)
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Built FRESH on every tool call by `bindSessionContext` from
|
||||
* `ComputerUseSessionContext` getters. This is what lets a singleton MCP
|
||||
* server carry per-session state — the state lives on the host's session
|
||||
* store, not the server.
|
||||
*/
|
||||
export interface ComputerUseOverrides {
|
||||
allowedApps: AppGrant[];
|
||||
grantFlags: CuGrantFlags;
|
||||
coordinateMode: CoordinateMode;
|
||||
|
||||
/**
|
||||
* User-configured auto-deny list (Settings → Desktop app → Computer Use).
|
||||
* Bundle IDs
|
||||
* here are stripped from request_access BEFORE the approval dialog — they
|
||||
* never reach the user for approval regardless of tier. The response tells
|
||||
* the agent to ask the user to remove the app from their deny list in
|
||||
* Settings if access is genuinely needed.
|
||||
*
|
||||
* Per-USER, persists across restarts (read from appPreferences per call,
|
||||
* not session state). Contrast with `allowedApps` which is per-session.
|
||||
* Empty array = no user-configured denies (the default).
|
||||
*/
|
||||
userDeniedBundleIds: readonly string[];
|
||||
|
||||
/**
|
||||
* Display CU operates on; read fresh per call. `scaleCoord` uses the
|
||||
* `originX/Y` snapshotted in `lastScreenshot`, so mid-session switches
|
||||
* only affect the NEXT screenshot/prepare call.
|
||||
*/
|
||||
selectedDisplayId?: number;
|
||||
|
||||
/**
|
||||
* The `request_access` tool handler calls this and awaits. The wrapper
|
||||
* closure in serverDef.ts (mirroring InternalMcpServerManager.ts:131-177)
|
||||
* routes through `handleToolPermission` → IPC → renderer ChicagoApproval.
|
||||
* When it resolves, the wrapper side-effectfully mutates
|
||||
* `InternalServerContext.cuAllowedApps` BEFORE returning here.
|
||||
*
|
||||
* Undefined when the session wasn't wired with a permission handler (e.g.
|
||||
* a future headless mode). `request_access` returns a tool error in that case.
|
||||
*/
|
||||
onPermissionRequest?: (req: CuPermissionRequest) => Promise<CuPermissionResponse>;
|
||||
|
||||
/**
|
||||
* For the pixel-validation staleness guard. The model's-last-screenshot,
|
||||
* stashed by serverDef.ts after each `screenshot` tool call. Undefined on
|
||||
* cold start → pixel validation skipped (click proceeds).
|
||||
*/
|
||||
lastScreenshot?: ScreenshotResult;
|
||||
|
||||
/**
|
||||
* Fired after every `prepareForAction` with the bundle IDs it just hid.
|
||||
* The wrapper closure in serverDef.ts accumulates these into
|
||||
* `Session.cuHiddenDuringTurn` via a write-through callback (same pattern
|
||||
* as `onCuPermissionUpdated`). At turn end (`sdkMessage.type === "result"`),
|
||||
* if the `chicagoAutoUnhide` setting is on, everything in the set is
|
||||
* unhidden. Set is cleared regardless of the setting so it doesn't leak
|
||||
* across turns.
|
||||
*
|
||||
* Undefined when the session wasn't wired with a tracker — unhide just
|
||||
* doesn't happen.
|
||||
*/
|
||||
onAppsHidden?: (bundleIds: string[]) => void;
|
||||
|
||||
/**
|
||||
* Reads the clipboardGuard stash from session state. `undefined` means no
|
||||
* stash is held — `syncClipboardStash` stashes on first entry to click-tier
|
||||
* and clears on restore. Sibling of the `cuHiddenDuringTurn` getter pattern
|
||||
* — state lives on the host's session, not module-level here.
|
||||
*/
|
||||
getClipboardStash?: () => string | undefined;
|
||||
|
||||
/**
|
||||
* Writes the clipboardGuard stash to session state. `undefined` clears.
|
||||
* Sibling of `onAppsHidden` — the wrapper closure writes through to
|
||||
* `Session.cuClipboardStash`. At turn end the host reads + clears it
|
||||
* directly and restores via Electron's `clipboard.writeText` (no nest-only
|
||||
* import surface).
|
||||
*/
|
||||
onClipboardStashChanged?: (stash: string | undefined) => void;
|
||||
|
||||
/**
|
||||
* Write the resolver's picked display back to session so teach overlay
|
||||
* positioning and subsequent non-resolver calls use the same display.
|
||||
* Fired by `handleScreenshot` in the atomic `autoTargetDisplay` path when
|
||||
* `resolvePrepareCapture`'s pick differs from `selectedDisplayId`.
|
||||
* Fire-and-forget.
|
||||
*/
|
||||
onResolvedDisplayUpdated?: (displayId: number) => void;
|
||||
|
||||
/**
|
||||
* Set when the model explicitly picked a display via `switch_display`.
|
||||
* When true, `handleScreenshot` passes `autoResolve: false` so the Swift
|
||||
* resolver honors `selectedDisplayId` directly (straight cuDisplayInfo
|
||||
* passthrough) instead of running the co-location/chase chain. The
|
||||
* resolver's Step 2 ("host + allowed co-located → host") otherwise
|
||||
* overrides any `selectedDisplayId` whenever an allowed app shares the
|
||||
* host's monitor.
|
||||
*/
|
||||
displayPinnedByModel?: boolean;
|
||||
|
||||
/**
|
||||
* Write the model's explicit display pick to session. `displayId:
|
||||
* undefined` clears both `selectedDisplayId` and the pin (back to auto).
|
||||
* Sibling of `onResolvedDisplayUpdated` but also sets the pin flag —
|
||||
* the two are semantically distinct (resolver-picked vs model-picked).
|
||||
*/
|
||||
onDisplayPinned?: (displayId: number | undefined) => void;
|
||||
|
||||
/**
|
||||
* Sorted comma-joined bundle-ID set the display was last auto-resolved
|
||||
* for. `handleScreenshot` compares this to the current allowed set and
|
||||
* only passes `autoResolve: true` when they differ — so the resolver
|
||||
* doesn't yank the display on every screenshot, only when the app set
|
||||
* has changed since the last resolve (or manual switch).
|
||||
*/
|
||||
displayResolvedForApps?: string;
|
||||
|
||||
/**
|
||||
* Records which app set the current display selection was made for. Fired
|
||||
* alongside `onResolvedDisplayUpdated` when the resolver picks, so the next
|
||||
* screenshot sees a matching set and skips auto-resolve.
|
||||
*/
|
||||
onDisplayResolvedForApps?: (sortedBundleIdsKey: string) => void;
|
||||
|
||||
/**
|
||||
* Global CU lock — at most one session actively uses CU at a time. Checked
|
||||
* in `handleToolCall` after kill-switch/TCC, before dispatch. Every CU tool
|
||||
* including `request_access` goes through it.
|
||||
*
|
||||
* - `holder === undefined` → lock is free, safe to acquire
|
||||
* - `isSelf === true` → this session already holds it (no-op, proceed)
|
||||
* - `holder !== undefined && !isSelf` → blocked, return tool error
|
||||
*
|
||||
* `undefined` callback → lock system not wired (e.g. CCD). Proceed without
|
||||
* gating — absence of the mechanism ≠ locked out.
|
||||
*
|
||||
* The host manages release (on session idle/stop/archive) — this package
|
||||
* never releases.
|
||||
*/
|
||||
checkCuLock?: () => { holder: string | undefined; isSelf: boolean };
|
||||
|
||||
/**
|
||||
* Take the lock for this session. `handleToolCall` calls this exactly once
|
||||
* per turn, on the FIRST CU tool call when `checkCuLock().holder` is
|
||||
* undefined. No-op if already held (defensive — the check should have
|
||||
* short-circuited). Host emits an event the overlay listens to.
|
||||
*/
|
||||
acquireCuLock?: () => void;
|
||||
|
||||
/**
|
||||
* User-abort signal. Checked mid-iteration inside `handleComputerBatch`
|
||||
* and `handleType`'s grapheme loop so an in-flight batch/type stops
|
||||
* promptly on overlay Stop instead of running to completion after the
|
||||
* host has already abandoned the tool result.
|
||||
*
|
||||
* Undefined → never aborts (e.g. unwired host). Live per-check read —
|
||||
* same lazy-getter pattern as `checkCuLock`.
|
||||
*/
|
||||
isAborted?: () => boolean;
|
||||
|
||||
// ── Teach mode ───────────────────────────────────────────────────────
|
||||
// Wired only when the host's teachModeEnabled gate is on. All five
|
||||
// undefined → `request_teach_access` / `teach_step` return tool errors
|
||||
// and teach mode is effectively off.
|
||||
|
||||
/**
|
||||
* Sibling of `onPermissionRequest`. Same blocking-await-on-renderer-dialog
|
||||
* semantics, but routes to ComputerUseTeachApproval.tsx (which explains
|
||||
* the window-hides-during-guide behavior) instead of ComputerUseApproval.
|
||||
* The wrapper closure in serverDef.ts writes grants through to session state
|
||||
* via `onCuPermissionUpdated` exactly as `onPermissionRequest` does.
|
||||
*/
|
||||
onTeachPermissionRequest?: (
|
||||
req: CuTeachPermissionRequest,
|
||||
) => Promise<CuPermissionResponse>;
|
||||
|
||||
/**
|
||||
* Called by `handleRequestTeachAccess` after the user approves and at least
|
||||
* one app was granted. Host sets `session.teachModeActive = true`, emits
|
||||
* `teachModeChanged` → teach controller hides the main window and shows the
|
||||
* fullscreen overlay. Cleared by the host on turn end (`transitionTo("idle")`)
|
||||
* alongside the CU lock release.
|
||||
*/
|
||||
onTeachModeActivated?: () => void;
|
||||
|
||||
/**
|
||||
* Read by `handleRequestAccess` and `handleRequestTeachAccess` to
|
||||
* short-circuit with a clear tool error when teach mode is active. The
|
||||
* main window is hidden during teach mode, so permission dialogs render
|
||||
* invisibly and handleToolPermission blocks forever on an invisible
|
||||
* prompt. Better to tell the model to exit teach mode first. Getter
|
||||
* (not a boolean field) because teach mode state lives on the session,
|
||||
* not on this per-call overrides object.
|
||||
*/
|
||||
getTeachModeActive?: () => boolean;
|
||||
|
||||
/**
|
||||
* Called by `handleTeachStep` with the scaled anchor + text. Host stores
|
||||
* the resolver, emits `teachStepRequested` → teach controller pushes the
|
||||
* payload to the overlay → user reads, clicks Next → IPC → host calls the
|
||||
* stored resolver → this promise resolves. `{action: "exit"}` when the user
|
||||
* clicks Exit (or the turn is interrupted) — `handleTeachStep` short-circuits
|
||||
* without executing actions.
|
||||
*
|
||||
* Same blocking-promise pattern as `onPermissionRequest`, but resolved by
|
||||
* the teach overlay's own preload (not the main renderer's tool-approval UI).
|
||||
*/
|
||||
onTeachStep?: (req: TeachStepRequest) => Promise<TeachStepResult>;
|
||||
|
||||
/**
|
||||
* Called immediately after `onTeachStep` resolves with "next", before
|
||||
* action dispatch begins. Host emits `teachStepWorking` → overlay flips to
|
||||
* the spinner state (Next button gone, Exit stays, "Working…" + rotating
|
||||
* notch). The next `onTeachStep` call replaces the spinner with the new
|
||||
* tooltip content.
|
||||
*/
|
||||
onTeachWorking?: () => void;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Teach mode (guided-tour tooltips with Next-button action execution)
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Payload the host pushes to the teach overlay BrowserWindow. Built by
|
||||
* `handleTeachStep` in toolCalls.ts from the model's `teach_step` args.
|
||||
*
|
||||
* `anchorLogical` here is POST-`scaleCoord` — **full-display** logical
|
||||
* macOS points (origin = monitor top-left, menu bar included, since
|
||||
* cuDisplayInfo returns CGDisplayBounds). The overlay window is positioned
|
||||
* at `workArea.{x,y}` (excludes menu bar/Dock), so `updateTeachStep` in
|
||||
* teach/window.ts subtracts the workArea offset before IPC so the HTML's
|
||||
* CSS coords match.
|
||||
*/
|
||||
export interface TeachStepRequest {
|
||||
explanation: string;
|
||||
nextPreview: string;
|
||||
/** Full-display logical points. Undefined → overlay centers the tooltip, hides the arrow. */
|
||||
anchorLogical?: { x: number; y: number };
|
||||
}
|
||||
|
||||
export type TeachStepResult = { action: "next" } | { action: "exit" };
|
||||
|
||||
/**
|
||||
* Payload for the renderer's ComputerUseTeachApproval dialog. Rides through
|
||||
* `ToolPermissionRequest.input: unknown` same as `CuPermissionRequest`.
|
||||
* Separate type (not a flag on `CuPermissionRequest`) so the two approval
|
||||
* components can narrow independently and the teach dialog is free to drop
|
||||
* fields it doesn't render (no grant-flag checkboxes in teach mode).
|
||||
*/
|
||||
export interface CuTeachPermissionRequest {
|
||||
requestId: string;
|
||||
/** Model-provided reason. Shown in the dialog headline ("guide you through {reason}"). */
|
||||
reason: string;
|
||||
apps: ResolvedAppRequest[];
|
||||
screenshotFiltering: "native" | "none";
|
||||
/** Present only when TCC is ungranted — same semantics as `CuPermissionRequest.tccState`. */
|
||||
tccState?: {
|
||||
accessibility: boolean;
|
||||
screenRecording: boolean;
|
||||
};
|
||||
willHide?: Array<{ bundleId: string; displayName: string }>;
|
||||
/** Same semantics as `CuPermissionRequest.autoUnhideEnabled`. */
|
||||
autoUnhideEnabled?: boolean;
|
||||
}
|
||||
23
claude-code-source/node_modules/@ant/computer-use-swift/js/index.js
generated
vendored
23
claude-code-source/node_modules/@ant/computer-use-swift/js/index.js
generated
vendored
@@ -1,23 +0,0 @@
|
||||
const path = require("path");
|
||||
|
||||
if (process.platform !== "darwin") {
|
||||
throw new Error("@ant/computer-use-swift is only available on macOS");
|
||||
}
|
||||
|
||||
// COMPUTER_USE_SWIFT_NODE_PATH: escape hatch for bundlers. Bun's --compile
|
||||
// embeds the .node as an asset, not in a node_modules tree — __dirname is the
|
||||
// exe dir and ../prebuilds/ doesn't exist. The consuming build bakes this var
|
||||
// to the embedded asset's path. Unset → normal node_modules layout.
|
||||
//
|
||||
// Four methods use `Task { @MainActor in ... }` (captureExcluding,
|
||||
// captureRegion, apps.listInstalled, resolvePrepareCapture) which enqueue
|
||||
// onto DispatchQueue.main. Electron drains that queue via CFRunLoop; libuv
|
||||
// (Node/bun) does not — the promises hang. Consumers running under libuv
|
||||
// must pump `_drainMainRunLoop` via setInterval while those promises are
|
||||
// pending. Consumers under Electron don't need to (CFRunLoop drains
|
||||
// automatically).
|
||||
const native = require(
|
||||
process.env.COMPUTER_USE_SWIFT_NODE_PATH ??
|
||||
path.resolve(__dirname, "../prebuilds/computer_use.node"),
|
||||
);
|
||||
module.exports = native.computerUse;
|
||||
163
claude-code-source/node_modules/@anthropic-ai/bedrock-sdk/AWS_restJson1.mjs
generated
vendored
163
claude-code-source/node_modules/@anthropic-ai/bedrock-sdk/AWS_restJson1.mjs
generated
vendored
@@ -1,163 +0,0 @@
|
||||
// Copied from https://github.com/aws/aws-sdk-js-v3/blob/bee66fbd2a519a16b57c787b2689af857af720af/clients/client-bedrock-runtime/src/protocols/Aws_restJson1.ts
|
||||
// Modified to remove unnecessary code (we only need to call `de_ResponseStream`) and to adjust imports.
|
||||
import { collectBody, decorateServiceException as __decorateServiceException, expectInt32 as __expectInt32, expectString as __expectString, map, take, } from '@smithy/smithy-client';
|
||||
import { InternalServerException, ModelStreamErrorException, ThrottlingException, ValidationException, } from '@aws-sdk/client-bedrock-runtime';
|
||||
/**
|
||||
* deserializeAws_restJson1InternalServerExceptionRes
|
||||
*/
|
||||
const de_InternalServerExceptionRes = async (parsedOutput, context) => {
|
||||
const contents = map({});
|
||||
const data = parsedOutput.body;
|
||||
const doc = take(data, {
|
||||
message: __expectString,
|
||||
});
|
||||
Object.assign(contents, doc);
|
||||
const exception = new InternalServerException({
|
||||
$metadata: deserializeMetadata(parsedOutput),
|
||||
...contents,
|
||||
});
|
||||
return __decorateServiceException(exception, parsedOutput.body);
|
||||
};
|
||||
/**
|
||||
* deserializeAws_restJson1ModelStreamErrorExceptionRes
|
||||
*/
|
||||
const de_ModelStreamErrorExceptionRes = async (parsedOutput, context) => {
|
||||
const contents = map({});
|
||||
const data = parsedOutput.body;
|
||||
const doc = take(data, {
|
||||
message: __expectString,
|
||||
originalMessage: __expectString,
|
||||
originalStatusCode: __expectInt32,
|
||||
});
|
||||
Object.assign(contents, doc);
|
||||
const exception = new ModelStreamErrorException({
|
||||
$metadata: deserializeMetadata(parsedOutput),
|
||||
...contents,
|
||||
});
|
||||
return __decorateServiceException(exception, parsedOutput.body);
|
||||
};
|
||||
/**
|
||||
* deserializeAws_restJson1ThrottlingExceptionRes
|
||||
*/
|
||||
const de_ThrottlingExceptionRes = async (parsedOutput, context) => {
|
||||
const contents = map({});
|
||||
const data = parsedOutput.body;
|
||||
const doc = take(data, {
|
||||
message: __expectString,
|
||||
});
|
||||
Object.assign(contents, doc);
|
||||
const exception = new ThrottlingException({
|
||||
$metadata: deserializeMetadata(parsedOutput),
|
||||
...contents,
|
||||
});
|
||||
return __decorateServiceException(exception, parsedOutput.body);
|
||||
};
|
||||
/**
|
||||
* deserializeAws_restJson1ValidationExceptionRes
|
||||
*/
|
||||
const de_ValidationExceptionRes = async (parsedOutput, context) => {
|
||||
const contents = map({});
|
||||
const data = parsedOutput.body;
|
||||
const doc = take(data, {
|
||||
message: __expectString,
|
||||
});
|
||||
Object.assign(contents, doc);
|
||||
const exception = new ValidationException({
|
||||
$metadata: deserializeMetadata(parsedOutput),
|
||||
...contents,
|
||||
});
|
||||
return __decorateServiceException(exception, parsedOutput.body);
|
||||
};
|
||||
/**
|
||||
* deserializeAws_restJson1ResponseStream
|
||||
*/
|
||||
export const de_ResponseStream = (output, context) => {
|
||||
return context.eventStreamMarshaller.deserialize(output, async (event) => {
|
||||
if (event['chunk'] != null) {
|
||||
return {
|
||||
chunk: await de_PayloadPart_event(event['chunk'], context),
|
||||
};
|
||||
}
|
||||
if (event['internalServerException'] != null) {
|
||||
return {
|
||||
internalServerException: await de_InternalServerException_event(event['internalServerException'], context),
|
||||
};
|
||||
}
|
||||
if (event['modelStreamErrorException'] != null) {
|
||||
return {
|
||||
modelStreamErrorException: await de_ModelStreamErrorException_event(event['modelStreamErrorException'], context),
|
||||
};
|
||||
}
|
||||
if (event['validationException'] != null) {
|
||||
return {
|
||||
validationException: await de_ValidationException_event(event['validationException'], context),
|
||||
};
|
||||
}
|
||||
if (event['throttlingException'] != null) {
|
||||
return {
|
||||
throttlingException: await de_ThrottlingException_event(event['throttlingException'], context),
|
||||
};
|
||||
}
|
||||
return { $unknown: output };
|
||||
});
|
||||
};
|
||||
const de_InternalServerException_event = async (output, context) => {
|
||||
const parsedOutput = {
|
||||
...output,
|
||||
body: await parseBody(output.body, context),
|
||||
};
|
||||
return de_InternalServerExceptionRes(parsedOutput, context);
|
||||
};
|
||||
const de_ModelStreamErrorException_event = async (output, context) => {
|
||||
const parsedOutput = {
|
||||
...output,
|
||||
body: await parseBody(output.body, context),
|
||||
};
|
||||
return de_ModelStreamErrorExceptionRes(parsedOutput, context);
|
||||
};
|
||||
const de_PayloadPart_event = async (output, context) => {
|
||||
const contents = {};
|
||||
const data = await parseBody(output.body, context);
|
||||
Object.assign(contents, de_PayloadPart(data, context));
|
||||
return contents;
|
||||
};
|
||||
const de_ThrottlingException_event = async (output, context) => {
|
||||
const parsedOutput = {
|
||||
...output,
|
||||
body: await parseBody(output.body, context),
|
||||
};
|
||||
return de_ThrottlingExceptionRes(parsedOutput, context);
|
||||
};
|
||||
const de_ValidationException_event = async (output, context) => {
|
||||
const parsedOutput = {
|
||||
...output,
|
||||
body: await parseBody(output.body, context),
|
||||
};
|
||||
return de_ValidationExceptionRes(parsedOutput, context);
|
||||
};
|
||||
/**
|
||||
* deserializeAws_restJson1PayloadPart
|
||||
*/
|
||||
const de_PayloadPart = (output, context) => {
|
||||
return take(output, {
|
||||
bytes: context.base64Decoder,
|
||||
});
|
||||
};
|
||||
const deserializeMetadata = (output) => ({
|
||||
httpStatusCode: output.statusCode,
|
||||
requestId: output.headers['x-amzn-requestid'] ??
|
||||
output.headers['x-amzn-request-id'] ??
|
||||
output.headers['x-amz-request-id'] ??
|
||||
'',
|
||||
extendedRequestId: output.headers['x-amz-id-2'] ?? '',
|
||||
cfId: output.headers['x-amz-cf-id'] ?? '',
|
||||
});
|
||||
// Encode Uint8Array data into string with utf-8.
|
||||
const collectBodyString = (streamBody, context) => collectBody(streamBody, context).then((body) => context.utf8Encoder(body));
|
||||
const parseBody = (streamBody, context) => collectBodyString(streamBody, context).then((encoded) => {
|
||||
if (encoded.length) {
|
||||
return JSON.parse(encoded);
|
||||
}
|
||||
return {};
|
||||
});
|
||||
//# sourceMappingURL=AWS_restJson1.mjs.map
|
||||
124
claude-code-source/node_modules/@anthropic-ai/bedrock-sdk/client.mjs
generated
vendored
124
claude-code-source/node_modules/@anthropic-ai/bedrock-sdk/client.mjs
generated
vendored
@@ -1,124 +0,0 @@
|
||||
import { BaseAnthropic } from '@anthropic-ai/sdk/client';
|
||||
import * as Resources from '@anthropic-ai/sdk/resources/index';
|
||||
import { getAuthHeaders } from "./core/auth.mjs";
|
||||
import { Stream } from "./core/streaming.mjs";
|
||||
import { readEnv } from "./internal/utils/env.mjs";
|
||||
import { isObj } from "./internal/utils/values.mjs";
|
||||
import { buildHeaders } from "./internal/headers.mjs";
|
||||
import { path } from "./internal/utils/path.mjs";
|
||||
export { BaseAnthropic } from '@anthropic-ai/sdk/client';
|
||||
const DEFAULT_VERSION = 'bedrock-2023-05-31';
|
||||
const MODEL_ENDPOINTS = new Set(['/v1/complete', '/v1/messages', '/v1/messages?beta=true']);
|
||||
/** API Client for interfacing with the Anthropic Bedrock API. */
|
||||
export class AnthropicBedrock extends BaseAnthropic {
|
||||
/**
|
||||
* API Client for interfacing with the Anthropic Bedrock API.
|
||||
*
|
||||
* @param {string | null | undefined} [opts.awsSecretKey]
|
||||
* @param {string | null | undefined} [opts.awsAccessKey]
|
||||
* @param {string | undefined} [opts.awsRegion=process.env['AWS_REGION'] ?? us-east-1]
|
||||
* @param {string | null | undefined} [opts.awsSessionToken]
|
||||
* @param {(() => Promise<AwsCredentialIdentityProvider>) | null} [opts.providerChainResolver] - Custom provider chain resolver for AWS credentials. Useful for non-Node environments.
|
||||
* @param {string} [opts.baseURL=process.env['ANTHROPIC_BEDROCK_BASE_URL'] ?? https://bedrock-runtime.${this.awsRegion}.amazonaws.com] - Override the default base URL for the API.
|
||||
* @param {number} [opts.timeout=10 minutes] - The maximum amount of time (in milliseconds) the client will wait for a response before timing out.
|
||||
* @param {MergedRequestInit} [opts.fetchOptions] - Additional `RequestInit` options to be passed to `fetch` calls.
|
||||
* @param {Fetch} [opts.fetch] - Specify a custom `fetch` function implementation.
|
||||
* @param {number} [opts.maxRetries=2] - The maximum number of times the client will retry a request.
|
||||
* @param {HeadersLike} opts.defaultHeaders - Default headers to include with every request to the API.
|
||||
* @param {Record<string, string | undefined>} opts.defaultQuery - Default query parameters to include with every request to the API.
|
||||
* @param {boolean} [opts.dangerouslyAllowBrowser=false] - By default, client-side use of this library is not allowed, as it risks exposing your secret API credentials to attackers.
|
||||
* @param {boolean} [opts.skipAuth=false] - Skip authentication for this request. This is useful if you have an internal proxy that handles authentication for you.
|
||||
*/
|
||||
constructor({ awsRegion = readEnv('AWS_REGION') ?? 'us-east-1', baseURL = readEnv('ANTHROPIC_BEDROCK_BASE_URL') ?? `https://bedrock-runtime.${awsRegion}.amazonaws.com`, awsSecretKey = null, awsAccessKey = null, awsSessionToken = null, providerChainResolver = null, ...opts } = {}) {
|
||||
super({
|
||||
baseURL,
|
||||
...opts,
|
||||
});
|
||||
this.skipAuth = false;
|
||||
this.messages = makeMessagesResource(this);
|
||||
this.completions = new Resources.Completions(this);
|
||||
this.beta = makeBetaResource(this);
|
||||
this.awsSecretKey = awsSecretKey;
|
||||
this.awsAccessKey = awsAccessKey;
|
||||
this.awsRegion = awsRegion;
|
||||
this.awsSessionToken = awsSessionToken;
|
||||
this.skipAuth = opts.skipAuth ?? false;
|
||||
this.providerChainResolver = providerChainResolver;
|
||||
}
|
||||
validateHeaders() {
|
||||
// auth validation is handled in prepareRequest since it needs to be async
|
||||
}
|
||||
async prepareRequest(request, { url, options }) {
|
||||
if (this.skipAuth) {
|
||||
return;
|
||||
}
|
||||
const regionName = this.awsRegion;
|
||||
if (!regionName) {
|
||||
throw new Error('Expected `awsRegion` option to be passed to the client or the `AWS_REGION` environment variable to be present');
|
||||
}
|
||||
const headers = await getAuthHeaders(request, {
|
||||
url,
|
||||
regionName,
|
||||
awsAccessKey: this.awsAccessKey,
|
||||
awsSecretKey: this.awsSecretKey,
|
||||
awsSessionToken: this.awsSessionToken,
|
||||
fetchOptions: this.fetchOptions,
|
||||
providerChainResolver: this.providerChainResolver,
|
||||
});
|
||||
request.headers = buildHeaders([headers, request.headers]).values;
|
||||
}
|
||||
async buildRequest(options) {
|
||||
options.__streamClass = Stream;
|
||||
if (isObj(options.body)) {
|
||||
// create a shallow copy of the request body so that code that mutates it later
|
||||
// doesn't mutate the original user-provided object
|
||||
options.body = { ...options.body };
|
||||
}
|
||||
if (isObj(options.body)) {
|
||||
if (!options.body['anthropic_version']) {
|
||||
options.body['anthropic_version'] = DEFAULT_VERSION;
|
||||
}
|
||||
if (options.headers && !options.body['anthropic_beta']) {
|
||||
const betas = buildHeaders([options.headers]).values.get('anthropic-beta');
|
||||
if (betas != null) {
|
||||
options.body['anthropic_beta'] = betas.split(',');
|
||||
}
|
||||
}
|
||||
}
|
||||
if (MODEL_ENDPOINTS.has(options.path) && options.method === 'post') {
|
||||
if (!isObj(options.body)) {
|
||||
throw new Error('Expected request body to be an object for post /v1/messages');
|
||||
}
|
||||
const model = options.body['model'];
|
||||
options.body['model'] = undefined;
|
||||
const stream = options.body['stream'];
|
||||
options.body['stream'] = undefined;
|
||||
if (stream) {
|
||||
options.path = path `/model/${model}/invoke-with-response-stream`;
|
||||
}
|
||||
else {
|
||||
options.path = path `/model/${model}/invoke`;
|
||||
}
|
||||
}
|
||||
return super.buildRequest(options);
|
||||
}
|
||||
}
|
||||
function makeMessagesResource(client) {
|
||||
const resource = new Resources.Messages(client);
|
||||
// @ts-expect-error we're deleting non-optional properties
|
||||
delete resource.batches;
|
||||
// @ts-expect-error we're deleting non-optional properties
|
||||
delete resource.countTokens;
|
||||
return resource;
|
||||
}
|
||||
function makeBetaResource(client) {
|
||||
const resource = new Resources.Beta(client);
|
||||
// @ts-expect-error we're deleting non-optional properties
|
||||
delete resource.promptCaching;
|
||||
// @ts-expect-error we're deleting non-optional properties
|
||||
delete resource.messages.batches;
|
||||
// @ts-expect-error we're deleting non-optional properties
|
||||
delete resource.messages.countTokens;
|
||||
return resource;
|
||||
}
|
||||
//# sourceMappingURL=client.mjs.map
|
||||
82
claude-code-source/node_modules/@anthropic-ai/bedrock-sdk/core/auth.mjs
generated
vendored
82
claude-code-source/node_modules/@anthropic-ai/bedrock-sdk/core/auth.mjs
generated
vendored
@@ -1,82 +0,0 @@
|
||||
import { Sha256 } from '@aws-crypto/sha256-js';
|
||||
import { FetchHttpHandler } from '@smithy/fetch-http-handler';
|
||||
import { HttpRequest } from '@smithy/protocol-http';
|
||||
import { SignatureV4 } from '@smithy/signature-v4';
|
||||
import assert from 'assert';
|
||||
const DEFAULT_PROVIDER_CHAIN_RESOLVER = () => import('@aws-sdk/credential-providers').then(({ fromNodeProviderChain }) => fromNodeProviderChain({
|
||||
clientConfig: {
|
||||
requestHandler: new FetchHttpHandler({
|
||||
requestInit: (httpRequest) => {
|
||||
return {
|
||||
...httpRequest,
|
||||
};
|
||||
},
|
||||
}),
|
||||
},
|
||||
}))
|
||||
.catch((error) => {
|
||||
throw new Error(`Failed to import '@aws-sdk/credential-providers'.` +
|
||||
`You can provide a custom \`providerChainResolver\` in the client options if your runtime does not have access to '@aws-sdk/credential-providers': ` +
|
||||
`\`new AnthropicBedrock({ providerChainResolver })\` ` +
|
||||
`Original error: ${error.message}`);
|
||||
});
|
||||
export const getAuthHeaders = async (req, props) => {
|
||||
assert(req.method, 'Expected request method property to be set');
|
||||
const providerChain = await (props.providerChainResolver ?
|
||||
props.providerChainResolver()
|
||||
: DEFAULT_PROVIDER_CHAIN_RESOLVER());
|
||||
const credentials = await withTempEnv(() => {
|
||||
// Temporarily set the appropriate environment variables if we've been
|
||||
// explicitly given credentials so that the credentials provider can
|
||||
// resolve them.
|
||||
//
|
||||
// Note: the environment provider is only not run first if the `AWS_PROFILE`
|
||||
// environment variable is set.
|
||||
// https://github.com/aws/aws-sdk-js-v3/blob/44a18a34b2c93feccdfcd162928d13e6dbdcaf30/packages/credential-provider-node/src/defaultProvider.ts#L49
|
||||
if (props.awsAccessKey) {
|
||||
process.env['AWS_ACCESS_KEY_ID'] = props.awsAccessKey;
|
||||
}
|
||||
if (props.awsSecretKey) {
|
||||
process.env['AWS_SECRET_ACCESS_KEY'] = props.awsSecretKey;
|
||||
}
|
||||
if (props.awsSessionToken) {
|
||||
process.env['AWS_SESSION_TOKEN'] = props.awsSessionToken;
|
||||
}
|
||||
}, () => providerChain());
|
||||
const signer = new SignatureV4({
|
||||
service: 'bedrock',
|
||||
region: props.regionName,
|
||||
credentials,
|
||||
sha256: Sha256,
|
||||
});
|
||||
const url = new URL(props.url);
|
||||
const headers = !req.headers ? {}
|
||||
: Symbol.iterator in req.headers ?
|
||||
Object.fromEntries(Array.from(req.headers).map((header) => [...header]))
|
||||
: { ...req.headers };
|
||||
// The connection header may be stripped by a proxy somewhere, so the receiver
|
||||
// of this message may not see this header, so we remove it from the set of headers
|
||||
// that are signed.
|
||||
delete headers['connection'];
|
||||
headers['host'] = url.hostname;
|
||||
const request = new HttpRequest({
|
||||
method: req.method.toUpperCase(),
|
||||
protocol: url.protocol,
|
||||
path: url.pathname,
|
||||
headers,
|
||||
body: req.body,
|
||||
});
|
||||
const signed = await signer.sign(request);
|
||||
return signed.headers;
|
||||
};
|
||||
const withTempEnv = async (updateEnv, fn) => {
|
||||
const previousEnv = { ...process.env };
|
||||
try {
|
||||
updateEnv();
|
||||
return await fn();
|
||||
}
|
||||
finally {
|
||||
process.env = previousEnv;
|
||||
}
|
||||
};
|
||||
//# sourceMappingURL=auth.mjs.map
|
||||
2
claude-code-source/node_modules/@anthropic-ai/bedrock-sdk/core/error.mjs
generated
vendored
2
claude-code-source/node_modules/@anthropic-ai/bedrock-sdk/core/error.mjs
generated
vendored
@@ -1,2 +0,0 @@
|
||||
export * from '@anthropic-ai/sdk/core/error';
|
||||
//# sourceMappingURL=error.mjs.map
|
||||
108
claude-code-source/node_modules/@anthropic-ai/bedrock-sdk/core/streaming.mjs
generated
vendored
108
claude-code-source/node_modules/@anthropic-ai/bedrock-sdk/core/streaming.mjs
generated
vendored
@@ -1,108 +0,0 @@
|
||||
import { EventStreamMarshaller } from '@smithy/eventstream-serde-node';
|
||||
import { fromBase64, toBase64 } from '@smithy/util-base64';
|
||||
import { streamCollector } from '@smithy/fetch-http-handler';
|
||||
import { Stream as CoreStream } from '@anthropic-ai/sdk/streaming';
|
||||
import { AnthropicError } from '@anthropic-ai/sdk/error';
|
||||
import { APIError } from '@anthropic-ai/sdk';
|
||||
import { de_ResponseStream } from "../AWS_restJson1.mjs";
|
||||
import { ReadableStreamToAsyncIterable } from "../internal/shims.mjs";
|
||||
import { safeJSON } from "../internal/utils/values.mjs";
|
||||
import { loggerFor } from "../internal/utils/log.mjs";
|
||||
export const toUtf8 = (input) => new TextDecoder('utf-8').decode(input);
|
||||
export const fromUtf8 = (input) => new TextEncoder().encode(input);
|
||||
// `de_ResponseStream` parses a Bedrock response stream and emits events as they are found.
|
||||
// It requires a "context" argument which has many fields, but for what we're using it for
|
||||
// it only needs this.
|
||||
export const getMinimalSerdeContext = () => {
|
||||
const marshaller = new EventStreamMarshaller({ utf8Encoder: toUtf8, utf8Decoder: fromUtf8 });
|
||||
return {
|
||||
base64Decoder: fromBase64,
|
||||
base64Encoder: toBase64,
|
||||
utf8Decoder: fromUtf8,
|
||||
utf8Encoder: toUtf8,
|
||||
eventStreamMarshaller: marshaller,
|
||||
streamCollector: streamCollector,
|
||||
};
|
||||
};
|
||||
export class Stream extends CoreStream {
|
||||
static fromSSEResponse(response, controller, client) {
|
||||
let consumed = false;
|
||||
const logger = client ? loggerFor(client) : console;
|
||||
async function* iterMessages() {
|
||||
if (!response.body) {
|
||||
controller.abort();
|
||||
throw new AnthropicError(`Attempted to iterate over a response with no body`);
|
||||
}
|
||||
const responseBodyIter = ReadableStreamToAsyncIterable(response.body);
|
||||
const eventStream = de_ResponseStream(responseBodyIter, getMinimalSerdeContext());
|
||||
for await (const event of eventStream) {
|
||||
if (event.chunk && event.chunk.bytes) {
|
||||
const s = toUtf8(event.chunk.bytes);
|
||||
yield { event: 'chunk', data: s, raw: [] };
|
||||
}
|
||||
else if (event.internalServerException) {
|
||||
yield { event: 'error', data: 'InternalServerException', raw: [] };
|
||||
}
|
||||
else if (event.modelStreamErrorException) {
|
||||
yield { event: 'error', data: 'ModelStreamErrorException', raw: [] };
|
||||
}
|
||||
else if (event.validationException) {
|
||||
yield { event: 'error', data: 'ValidationException', raw: [] };
|
||||
}
|
||||
else if (event.throttlingException) {
|
||||
yield { event: 'error', data: 'ThrottlingException', raw: [] };
|
||||
}
|
||||
}
|
||||
}
|
||||
// Note: this function is copied entirely from the core SDK
|
||||
async function* iterator() {
|
||||
if (consumed) {
|
||||
throw new Error('Cannot iterate over a consumed stream, use `.tee()` to split the stream.');
|
||||
}
|
||||
consumed = true;
|
||||
let done = false;
|
||||
try {
|
||||
for await (const sse of iterMessages()) {
|
||||
if (sse.event === 'chunk') {
|
||||
try {
|
||||
yield JSON.parse(sse.data);
|
||||
}
|
||||
catch (e) {
|
||||
logger.error(`Could not parse message into JSON:`, sse.data);
|
||||
logger.error(`From chunk:`, sse.raw);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
if (sse.event === 'error') {
|
||||
const errText = sse.data;
|
||||
const errJSON = safeJSON(errText);
|
||||
const errMessage = errJSON ? undefined : errText;
|
||||
throw APIError.generate(undefined, errJSON, errMessage, response.headers);
|
||||
}
|
||||
}
|
||||
done = true;
|
||||
}
|
||||
catch (e) {
|
||||
// If the user calls `stream.controller.abort()`, we should exit without throwing.
|
||||
if (isAbortError(e))
|
||||
return;
|
||||
throw e;
|
||||
}
|
||||
finally {
|
||||
// If the user `break`s, abort the ongoing request.
|
||||
if (!done)
|
||||
controller.abort();
|
||||
}
|
||||
}
|
||||
return new Stream(iterator, controller);
|
||||
}
|
||||
}
|
||||
function isAbortError(err) {
|
||||
return (typeof err === 'object' &&
|
||||
err !== null &&
|
||||
// Spec-compliant fetch implementations
|
||||
(('name' in err && err.name === 'AbortError') ||
|
||||
// Expo fetch
|
||||
('message' in err && String(err.message).includes('FetchRequestCanceledException'))));
|
||||
}
|
||||
//# sourceMappingURL=streaming.mjs.map
|
||||
3
claude-code-source/node_modules/@anthropic-ai/bedrock-sdk/index.mjs
generated
vendored
3
claude-code-source/node_modules/@anthropic-ai/bedrock-sdk/index.mjs
generated
vendored
@@ -1,3 +0,0 @@
|
||||
export * from "./client.mjs";
|
||||
export { AnthropicBedrock as default } from "./client.mjs";
|
||||
//# sourceMappingURL=index.mjs.map
|
||||
74
claude-code-source/node_modules/@anthropic-ai/bedrock-sdk/internal/headers.mjs
generated
vendored
74
claude-code-source/node_modules/@anthropic-ai/bedrock-sdk/internal/headers.mjs
generated
vendored
@@ -1,74 +0,0 @@
|
||||
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
||||
import { isReadonlyArray } from "./utils/values.mjs";
|
||||
const brand_privateNullableHeaders = Symbol.for('brand.privateNullableHeaders');
|
||||
function* iterateHeaders(headers) {
|
||||
if (!headers)
|
||||
return;
|
||||
if (brand_privateNullableHeaders in headers) {
|
||||
const { values, nulls } = headers;
|
||||
yield* values.entries();
|
||||
for (const name of nulls) {
|
||||
yield [name, null];
|
||||
}
|
||||
return;
|
||||
}
|
||||
let shouldClear = false;
|
||||
let iter;
|
||||
if (headers instanceof Headers) {
|
||||
iter = headers.entries();
|
||||
}
|
||||
else if (isReadonlyArray(headers)) {
|
||||
iter = headers;
|
||||
}
|
||||
else {
|
||||
shouldClear = true;
|
||||
iter = Object.entries(headers ?? {});
|
||||
}
|
||||
for (let row of iter) {
|
||||
const name = row[0];
|
||||
if (typeof name !== 'string')
|
||||
throw new TypeError('expected header name to be a string');
|
||||
const values = isReadonlyArray(row[1]) ? row[1] : [row[1]];
|
||||
let didClear = false;
|
||||
for (const value of values) {
|
||||
if (value === undefined)
|
||||
continue;
|
||||
// Objects keys always overwrite older headers, they never append.
|
||||
// Yield a null to clear the header before adding the new values.
|
||||
if (shouldClear && !didClear) {
|
||||
didClear = true;
|
||||
yield [name, null];
|
||||
}
|
||||
yield [name, value];
|
||||
}
|
||||
}
|
||||
}
|
||||
export const buildHeaders = (newHeaders) => {
|
||||
const targetHeaders = new Headers();
|
||||
const nullHeaders = new Set();
|
||||
for (const headers of newHeaders) {
|
||||
const seenHeaders = new Set();
|
||||
for (const [name, value] of iterateHeaders(headers)) {
|
||||
const lowerName = name.toLowerCase();
|
||||
if (!seenHeaders.has(lowerName)) {
|
||||
targetHeaders.delete(name);
|
||||
seenHeaders.add(lowerName);
|
||||
}
|
||||
if (value === null) {
|
||||
targetHeaders.delete(name);
|
||||
nullHeaders.add(lowerName);
|
||||
}
|
||||
else {
|
||||
targetHeaders.append(name, value);
|
||||
nullHeaders.delete(lowerName);
|
||||
}
|
||||
}
|
||||
}
|
||||
return { [brand_privateNullableHeaders]: true, values: targetHeaders, nulls: nullHeaders };
|
||||
};
|
||||
export const isEmptyHeaders = (headers) => {
|
||||
for (const _ of iterateHeaders(headers))
|
||||
return false;
|
||||
return true;
|
||||
};
|
||||
//# sourceMappingURL=headers.mjs.map
|
||||
85
claude-code-source/node_modules/@anthropic-ai/bedrock-sdk/internal/shims.mjs
generated
vendored
85
claude-code-source/node_modules/@anthropic-ai/bedrock-sdk/internal/shims.mjs
generated
vendored
@@ -1,85 +0,0 @@
|
||||
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
||||
export function getDefaultFetch() {
|
||||
if (typeof fetch !== 'undefined') {
|
||||
return fetch;
|
||||
}
|
||||
throw new Error('`fetch` is not defined as a global; Either pass `fetch` to the client, `new Anthropic({ fetch })` or polyfill the global, `globalThis.fetch = fetch`');
|
||||
}
|
||||
export function makeReadableStream(...args) {
|
||||
const ReadableStream = globalThis.ReadableStream;
|
||||
if (typeof ReadableStream === 'undefined') {
|
||||
// Note: All of the platforms / runtimes we officially support already define
|
||||
// `ReadableStream` as a global, so this should only ever be hit on unsupported runtimes.
|
||||
throw new Error('`ReadableStream` is not defined as a global; You will need to polyfill it, `globalThis.ReadableStream = ReadableStream`');
|
||||
}
|
||||
return new ReadableStream(...args);
|
||||
}
|
||||
export function ReadableStreamFrom(iterable) {
|
||||
let iter = Symbol.asyncIterator in iterable ? iterable[Symbol.asyncIterator]() : iterable[Symbol.iterator]();
|
||||
return makeReadableStream({
|
||||
start() { },
|
||||
async pull(controller) {
|
||||
const { done, value } = await iter.next();
|
||||
if (done) {
|
||||
controller.close();
|
||||
}
|
||||
else {
|
||||
controller.enqueue(value);
|
||||
}
|
||||
},
|
||||
async cancel() {
|
||||
await iter.return?.();
|
||||
},
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Most browsers don't yet have async iterable support for ReadableStream,
|
||||
* and Node has a very different way of reading bytes from its "ReadableStream".
|
||||
*
|
||||
* This polyfill was pulled from https://github.com/MattiasBuelens/web-streams-polyfill/pull/122#issuecomment-1627354490
|
||||
*/
|
||||
export function ReadableStreamToAsyncIterable(stream) {
|
||||
if (stream[Symbol.asyncIterator])
|
||||
return stream;
|
||||
const reader = stream.getReader();
|
||||
return {
|
||||
async next() {
|
||||
try {
|
||||
const result = await reader.read();
|
||||
if (result?.done)
|
||||
reader.releaseLock(); // release lock when stream becomes closed
|
||||
return result;
|
||||
}
|
||||
catch (e) {
|
||||
reader.releaseLock(); // release lock when stream becomes errored
|
||||
throw e;
|
||||
}
|
||||
},
|
||||
async return() {
|
||||
const cancelPromise = reader.cancel();
|
||||
reader.releaseLock();
|
||||
await cancelPromise;
|
||||
return { done: true, value: undefined };
|
||||
},
|
||||
[Symbol.asyncIterator]() {
|
||||
return this;
|
||||
},
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Cancels a ReadableStream we don't need to consume.
|
||||
* See https://undici.nodejs.org/#/?id=garbage-collection
|
||||
*/
|
||||
export async function CancelReadableStream(stream) {
|
||||
if (stream === null || typeof stream !== 'object')
|
||||
return;
|
||||
if (stream[Symbol.asyncIterator]) {
|
||||
await stream[Symbol.asyncIterator]().return?.();
|
||||
return;
|
||||
}
|
||||
const reader = stream.getReader();
|
||||
const cancelPromise = reader.cancel();
|
||||
reader.releaseLock();
|
||||
await cancelPromise;
|
||||
}
|
||||
//# sourceMappingURL=shims.mjs.map
|
||||
18
claude-code-source/node_modules/@anthropic-ai/bedrock-sdk/internal/utils/env.mjs
generated
vendored
18
claude-code-source/node_modules/@anthropic-ai/bedrock-sdk/internal/utils/env.mjs
generated
vendored
@@ -1,18 +0,0 @@
|
||||
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
||||
/**
|
||||
* Read an environment variable.
|
||||
*
|
||||
* Trims beginning and trailing whitespace.
|
||||
*
|
||||
* Will return undefined if the environment variable doesn't exist or cannot be accessed.
|
||||
*/
|
||||
export const readEnv = (env) => {
|
||||
if (typeof globalThis.process !== 'undefined') {
|
||||
return globalThis.process.env?.[env]?.trim() ?? undefined;
|
||||
}
|
||||
if (typeof globalThis.Deno !== 'undefined') {
|
||||
return globalThis.Deno.env?.get?.(env)?.trim();
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
//# sourceMappingURL=env.mjs.map
|
||||
80
claude-code-source/node_modules/@anthropic-ai/bedrock-sdk/internal/utils/log.mjs
generated
vendored
80
claude-code-source/node_modules/@anthropic-ai/bedrock-sdk/internal/utils/log.mjs
generated
vendored
@@ -1,80 +0,0 @@
|
||||
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
||||
import { hasOwn } from "./values.mjs";
|
||||
const levelNumbers = {
|
||||
off: 0,
|
||||
error: 200,
|
||||
warn: 300,
|
||||
info: 400,
|
||||
debug: 500,
|
||||
};
|
||||
export const parseLogLevel = (maybeLevel, sourceName, client) => {
|
||||
if (!maybeLevel) {
|
||||
return undefined;
|
||||
}
|
||||
if (hasOwn(levelNumbers, maybeLevel)) {
|
||||
return maybeLevel;
|
||||
}
|
||||
loggerFor(client).warn(`${sourceName} was set to ${JSON.stringify(maybeLevel)}, expected one of ${JSON.stringify(Object.keys(levelNumbers))}`);
|
||||
return undefined;
|
||||
};
|
||||
function noop() { }
|
||||
function makeLogFn(fnLevel, logger, logLevel) {
|
||||
if (!logger || levelNumbers[fnLevel] > levelNumbers[logLevel]) {
|
||||
return noop;
|
||||
}
|
||||
else {
|
||||
// Don't wrap logger functions, we want the stacktrace intact!
|
||||
return logger[fnLevel].bind(logger);
|
||||
}
|
||||
}
|
||||
const noopLogger = {
|
||||
error: noop,
|
||||
warn: noop,
|
||||
info: noop,
|
||||
debug: noop,
|
||||
};
|
||||
let cachedLoggers = /* @__PURE__ */ new WeakMap();
|
||||
export function loggerFor(client) {
|
||||
const logger = client.logger;
|
||||
const logLevel = client.logLevel ?? 'off';
|
||||
if (!logger) {
|
||||
return noopLogger;
|
||||
}
|
||||
const cachedLogger = cachedLoggers.get(logger);
|
||||
if (cachedLogger && cachedLogger[0] === logLevel) {
|
||||
return cachedLogger[1];
|
||||
}
|
||||
const levelLogger = {
|
||||
error: makeLogFn('error', logger, logLevel),
|
||||
warn: makeLogFn('warn', logger, logLevel),
|
||||
info: makeLogFn('info', logger, logLevel),
|
||||
debug: makeLogFn('debug', logger, logLevel),
|
||||
};
|
||||
cachedLoggers.set(logger, [logLevel, levelLogger]);
|
||||
return levelLogger;
|
||||
}
|
||||
export const formatRequestDetails = (details) => {
|
||||
if (details.options) {
|
||||
details.options = { ...details.options };
|
||||
delete details.options['headers']; // redundant + leaks internals
|
||||
}
|
||||
if (details.headers) {
|
||||
details.headers = Object.fromEntries((details.headers instanceof Headers ? [...details.headers] : Object.entries(details.headers)).map(([name, value]) => [
|
||||
name,
|
||||
(name.toLowerCase() === 'x-api-key' ||
|
||||
name.toLowerCase() === 'authorization' ||
|
||||
name.toLowerCase() === 'cookie' ||
|
||||
name.toLowerCase() === 'set-cookie') ?
|
||||
'***'
|
||||
: value,
|
||||
]));
|
||||
}
|
||||
if ('retryOfRequestLogID' in details) {
|
||||
if (details.retryOfRequestLogID) {
|
||||
details.retryOf = details.retryOfRequestLogID;
|
||||
}
|
||||
delete details.retryOfRequestLogID;
|
||||
}
|
||||
return details;
|
||||
};
|
||||
//# sourceMappingURL=log.mjs.map
|
||||
74
claude-code-source/node_modules/@anthropic-ai/bedrock-sdk/internal/utils/path.mjs
generated
vendored
74
claude-code-source/node_modules/@anthropic-ai/bedrock-sdk/internal/utils/path.mjs
generated
vendored
@@ -1,74 +0,0 @@
|
||||
import { AnthropicError } from "../../core/error.mjs";
|
||||
/**
|
||||
* Percent-encode everything that isn't safe to have in a path without encoding safe chars.
|
||||
*
|
||||
* Taken from https://datatracker.ietf.org/doc/html/rfc3986#section-3.3:
|
||||
* > unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
|
||||
* > sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
|
||||
* > pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
|
||||
*/
|
||||
export function encodeURIPath(str) {
|
||||
return str.replace(/[^A-Za-z0-9\-._~!$&'()*+,;=:@]+/g, encodeURIComponent);
|
||||
}
|
||||
const EMPTY = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.create(null));
|
||||
export const createPathTagFunction = (pathEncoder = encodeURIPath) => function path(statics, ...params) {
|
||||
// If there are no params, no processing is needed.
|
||||
if (statics.length === 1)
|
||||
return statics[0];
|
||||
let postPath = false;
|
||||
const invalidSegments = [];
|
||||
const path = statics.reduce((previousValue, currentValue, index) => {
|
||||
if (/[?#]/.test(currentValue)) {
|
||||
postPath = true;
|
||||
}
|
||||
const value = params[index];
|
||||
let encoded = (postPath ? encodeURIComponent : pathEncoder)('' + value);
|
||||
if (index !== params.length &&
|
||||
(value == null ||
|
||||
(typeof value === 'object' &&
|
||||
// handle values from other realms
|
||||
value.toString ===
|
||||
Object.getPrototypeOf(Object.getPrototypeOf(value.hasOwnProperty ?? EMPTY) ?? EMPTY)
|
||||
?.toString))) {
|
||||
encoded = value + '';
|
||||
invalidSegments.push({
|
||||
start: previousValue.length + currentValue.length,
|
||||
length: encoded.length,
|
||||
error: `Value of type ${Object.prototype.toString
|
||||
.call(value)
|
||||
.slice(8, -1)} is not a valid path parameter`,
|
||||
});
|
||||
}
|
||||
return previousValue + currentValue + (index === params.length ? '' : encoded);
|
||||
}, '');
|
||||
const pathOnly = path.split(/[?#]/, 1)[0];
|
||||
const invalidSegmentPattern = /(?<=^|\/)(?:\.|%2e){1,2}(?=\/|$)/gi;
|
||||
let match;
|
||||
// Find all invalid segments
|
||||
while ((match = invalidSegmentPattern.exec(pathOnly)) !== null) {
|
||||
invalidSegments.push({
|
||||
start: match.index,
|
||||
length: match[0].length,
|
||||
error: `Value "${match[0]}" can\'t be safely passed as a path parameter`,
|
||||
});
|
||||
}
|
||||
invalidSegments.sort((a, b) => a.start - b.start);
|
||||
if (invalidSegments.length > 0) {
|
||||
let lastEnd = 0;
|
||||
const underline = invalidSegments.reduce((acc, segment) => {
|
||||
const spaces = ' '.repeat(segment.start - lastEnd);
|
||||
const arrows = '^'.repeat(segment.length);
|
||||
lastEnd = segment.start + segment.length;
|
||||
return acc + spaces + arrows;
|
||||
}, '');
|
||||
throw new AnthropicError(`Path parameters result in path with invalid segments:\n${invalidSegments
|
||||
.map((e) => e.error)
|
||||
.join('\n')}\n${path}\n${underline}`);
|
||||
}
|
||||
return path;
|
||||
};
|
||||
/**
|
||||
* URI-encodes path params and ensures no unsafe /./ or /../ path segments are introduced.
|
||||
*/
|
||||
export const path = /* @__PURE__ */ createPathTagFunction(encodeURIPath);
|
||||
//# sourceMappingURL=path.mjs.map
|
||||
94
claude-code-source/node_modules/@anthropic-ai/bedrock-sdk/internal/utils/values.mjs
generated
vendored
94
claude-code-source/node_modules/@anthropic-ai/bedrock-sdk/internal/utils/values.mjs
generated
vendored
@@ -1,94 +0,0 @@
|
||||
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
||||
import { AnthropicError } from "../../core/error.mjs";
|
||||
// https://url.spec.whatwg.org/#url-scheme-string
|
||||
const startsWithSchemeRegexp = /^[a-z][a-z0-9+.-]*:/i;
|
||||
export const isAbsoluteURL = (url) => {
|
||||
return startsWithSchemeRegexp.test(url);
|
||||
};
|
||||
export let isArray = (val) => ((isArray = Array.isArray), isArray(val));
|
||||
export let isReadonlyArray = isArray;
|
||||
/** Returns an object if the given value isn't an object, otherwise returns as-is */
|
||||
export function maybeObj(x) {
|
||||
if (typeof x !== 'object') {
|
||||
return {};
|
||||
}
|
||||
return x ?? {};
|
||||
}
|
||||
// https://stackoverflow.com/a/34491287
|
||||
export function isEmptyObj(obj) {
|
||||
if (!obj)
|
||||
return true;
|
||||
for (const _k in obj)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
// https://eslint.org/docs/latest/rules/no-prototype-builtins
|
||||
export function hasOwn(obj, key) {
|
||||
return Object.prototype.hasOwnProperty.call(obj, key);
|
||||
}
|
||||
export function isObj(obj) {
|
||||
return obj != null && typeof obj === 'object' && !Array.isArray(obj);
|
||||
}
|
||||
export const ensurePresent = (value) => {
|
||||
if (value == null) {
|
||||
throw new AnthropicError(`Expected a value to be given but received ${value} instead.`);
|
||||
}
|
||||
return value;
|
||||
};
|
||||
export const validatePositiveInteger = (name, n) => {
|
||||
if (typeof n !== 'number' || !Number.isInteger(n)) {
|
||||
throw new AnthropicError(`${name} must be an integer`);
|
||||
}
|
||||
if (n < 0) {
|
||||
throw new AnthropicError(`${name} must be a positive integer`);
|
||||
}
|
||||
return n;
|
||||
};
|
||||
export const coerceInteger = (value) => {
|
||||
if (typeof value === 'number')
|
||||
return Math.round(value);
|
||||
if (typeof value === 'string')
|
||||
return parseInt(value, 10);
|
||||
throw new AnthropicError(`Could not coerce ${value} (type: ${typeof value}) into a number`);
|
||||
};
|
||||
export const coerceFloat = (value) => {
|
||||
if (typeof value === 'number')
|
||||
return value;
|
||||
if (typeof value === 'string')
|
||||
return parseFloat(value);
|
||||
throw new AnthropicError(`Could not coerce ${value} (type: ${typeof value}) into a number`);
|
||||
};
|
||||
export const coerceBoolean = (value) => {
|
||||
if (typeof value === 'boolean')
|
||||
return value;
|
||||
if (typeof value === 'string')
|
||||
return value === 'true';
|
||||
return Boolean(value);
|
||||
};
|
||||
export const maybeCoerceInteger = (value) => {
|
||||
if (value == null) {
|
||||
return undefined;
|
||||
}
|
||||
return coerceInteger(value);
|
||||
};
|
||||
export const maybeCoerceFloat = (value) => {
|
||||
if (value == null) {
|
||||
return undefined;
|
||||
}
|
||||
return coerceFloat(value);
|
||||
};
|
||||
export const maybeCoerceBoolean = (value) => {
|
||||
if (value == null) {
|
||||
return undefined;
|
||||
}
|
||||
return coerceBoolean(value);
|
||||
};
|
||||
export const safeJSON = (text) => {
|
||||
try {
|
||||
return JSON.parse(text);
|
||||
}
|
||||
catch (err) {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
//# sourceMappingURL=values.mjs.map
|
||||
98
claude-code-source/node_modules/@anthropic-ai/foundry-sdk/client.mjs
generated
vendored
98
claude-code-source/node_modules/@anthropic-ai/foundry-sdk/client.mjs
generated
vendored
@@ -1,98 +0,0 @@
|
||||
import { buildHeaders } from "./internal/headers.mjs";
|
||||
import * as Errors from "./core/error.mjs";
|
||||
import { readEnv } from "./internal/utils.mjs";
|
||||
import { Anthropic } from '@anthropic-ai/sdk/client';
|
||||
export { BaseAnthropic } from '@anthropic-ai/sdk/client';
|
||||
import * as Resources from '@anthropic-ai/sdk/resources/index';
|
||||
/** API Client for interfacing with the Anthropic Foundry API. */
|
||||
export class AnthropicFoundry extends Anthropic {
|
||||
/**
|
||||
* API Client for interfacing with the Anthropic Foundry API.
|
||||
*
|
||||
* @param {string | undefined} [opts.resource=process.env['ANTHROPIC_FOUNDRY_RESOURCE'] ?? undefined] - Your Foundry resource name
|
||||
* @param {string | undefined} [opts.apiKey=process.env['ANTHROPIC_FOUNDRY_API_KEY'] ?? undefined]
|
||||
* @param {string | null | undefined} [opts.organization=process.env['ANTHROPIC_ORG_ID'] ?? null]
|
||||
* @param {string} [opts.baseURL=process.env['ANTHROPIC_FOUNDRY_BASE_URL']] - Sets the base URL for the API, e.g. `https://example-resource.azure.anthropic.com/anthropic/`.
|
||||
* @param {number} [opts.timeout=10 minutes] - The maximum amount of time (in milliseconds) the client will wait for a response before timing out.
|
||||
* @param {number} [opts.httpAgent] - An HTTP agent used to manage HTTP(s) connections.
|
||||
* @param {Fetch} [opts.fetch] - Specify a custom `fetch` function implementation.
|
||||
* @param {number} [opts.maxRetries=2] - The maximum number of times the client will retry a request.
|
||||
* @param {Headers} opts.defaultHeaders - Default headers to include with every request to the API.
|
||||
* @param {DefaultQuery} opts.defaultQuery - Default query parameters to include with every request to the API.
|
||||
* @param {boolean} [opts.dangerouslyAllowBrowser=false] - By default, client-side use of this library is not allowed, as it risks exposing your secret API credentials to attackers.
|
||||
*/
|
||||
constructor({ baseURL = readEnv('ANTHROPIC_FOUNDRY_BASE_URL'), apiKey = readEnv('ANTHROPIC_FOUNDRY_API_KEY'), resource = readEnv('ANTHROPIC_FOUNDRY_RESOURCE'), azureADTokenProvider, dangerouslyAllowBrowser, ...opts } = {}) {
|
||||
if (typeof azureADTokenProvider === 'function') {
|
||||
dangerouslyAllowBrowser = true;
|
||||
}
|
||||
if (!azureADTokenProvider && !apiKey) {
|
||||
throw new Errors.AnthropicError('Missing credentials. Please pass one of `apiKey` and `azureTokenProvider`, or set the `ANTHROPIC_FOUNDRY_API_KEY` environment variable.');
|
||||
}
|
||||
if (azureADTokenProvider && apiKey) {
|
||||
throw new Errors.AnthropicError('The `apiKey` and `azureADTokenProvider` arguments are mutually exclusive; only one can be passed at a time.');
|
||||
}
|
||||
if (!baseURL) {
|
||||
if (!resource) {
|
||||
throw new Errors.AnthropicError('Must provide one of the `baseURL` or `resource` arguments, or the `ANTHROPIC_FOUNDRY_RESOURCE` environment variable');
|
||||
}
|
||||
baseURL = `https://${resource}.services.ai.azure.com/anthropic/`;
|
||||
}
|
||||
else {
|
||||
if (resource) {
|
||||
throw new Errors.AnthropicError('baseURL and resource are mutually exclusive');
|
||||
}
|
||||
}
|
||||
super({
|
||||
apiKey: azureADTokenProvider ?? apiKey,
|
||||
baseURL,
|
||||
...opts,
|
||||
...(dangerouslyAllowBrowser !== undefined ? { dangerouslyAllowBrowser } : {}),
|
||||
});
|
||||
this.resource = null;
|
||||
// @ts-expect-error are using a different Messages type that omits batches
|
||||
this.messages = makeMessagesResource(this);
|
||||
// @ts-expect-error are using a different Beta type that omits batches
|
||||
this.beta = makeBetaResource(this);
|
||||
// @ts-expect-error Anthropic Foundry does not support models endpoint
|
||||
this.models = undefined;
|
||||
}
|
||||
async authHeaders() {
|
||||
if (typeof this._options.apiKey === 'function') {
|
||||
let token;
|
||||
try {
|
||||
token = await this._options.apiKey();
|
||||
}
|
||||
catch (err) {
|
||||
if (err instanceof Errors.AnthropicError)
|
||||
throw err;
|
||||
throw new Errors.AnthropicError(`Failed to get token from azureADTokenProvider: ${err.message}`,
|
||||
// @ts-ignore
|
||||
{ cause: err });
|
||||
}
|
||||
if (typeof token !== 'string' || !token) {
|
||||
throw new Errors.AnthropicError(`Expected azureADTokenProvider function argument to return a string but it returned ${token}`);
|
||||
}
|
||||
return buildHeaders([{ Authorization: `Bearer ${token}` }]);
|
||||
}
|
||||
if (typeof this._options.apiKey === 'string') {
|
||||
return buildHeaders([{ 'x-api-key': this.apiKey }]);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
validateHeaders() {
|
||||
return;
|
||||
}
|
||||
}
|
||||
function makeMessagesResource(client) {
|
||||
const resource = new Resources.Messages(client);
|
||||
// @ts-expect-error we're deleting non-optional properties
|
||||
delete resource.batches;
|
||||
return resource;
|
||||
}
|
||||
function makeBetaResource(client) {
|
||||
const resource = new Resources.Beta(client);
|
||||
// @ts-expect-error we're deleting non-optional properties
|
||||
delete resource.messages.batches;
|
||||
return resource;
|
||||
}
|
||||
//# sourceMappingURL=client.mjs.map
|
||||
2
claude-code-source/node_modules/@anthropic-ai/foundry-sdk/core/error.mjs
generated
vendored
2
claude-code-source/node_modules/@anthropic-ai/foundry-sdk/core/error.mjs
generated
vendored
@@ -1,2 +0,0 @@
|
||||
export * from '@anthropic-ai/sdk/core/error';
|
||||
//# sourceMappingURL=error.mjs.map
|
||||
3
claude-code-source/node_modules/@anthropic-ai/foundry-sdk/index.mjs
generated
vendored
3
claude-code-source/node_modules/@anthropic-ai/foundry-sdk/index.mjs
generated
vendored
@@ -1,3 +0,0 @@
|
||||
export * from "./client.mjs";
|
||||
export { AnthropicFoundry as default } from "./client.mjs";
|
||||
//# sourceMappingURL=index.mjs.map
|
||||
74
claude-code-source/node_modules/@anthropic-ai/foundry-sdk/internal/headers.mjs
generated
vendored
74
claude-code-source/node_modules/@anthropic-ai/foundry-sdk/internal/headers.mjs
generated
vendored
@@ -1,74 +0,0 @@
|
||||
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
||||
import { isReadonlyArray } from "./utils/values.mjs";
|
||||
const brand_privateNullableHeaders = Symbol.for('brand.privateNullableHeaders');
|
||||
function* iterateHeaders(headers) {
|
||||
if (!headers)
|
||||
return;
|
||||
if (brand_privateNullableHeaders in headers) {
|
||||
const { values, nulls } = headers;
|
||||
yield* values.entries();
|
||||
for (const name of nulls) {
|
||||
yield [name, null];
|
||||
}
|
||||
return;
|
||||
}
|
||||
let shouldClear = false;
|
||||
let iter;
|
||||
if (headers instanceof Headers) {
|
||||
iter = headers.entries();
|
||||
}
|
||||
else if (isReadonlyArray(headers)) {
|
||||
iter = headers;
|
||||
}
|
||||
else {
|
||||
shouldClear = true;
|
||||
iter = Object.entries(headers ?? {});
|
||||
}
|
||||
for (let row of iter) {
|
||||
const name = row[0];
|
||||
if (typeof name !== 'string')
|
||||
throw new TypeError('expected header name to be a string');
|
||||
const values = isReadonlyArray(row[1]) ? row[1] : [row[1]];
|
||||
let didClear = false;
|
||||
for (const value of values) {
|
||||
if (value === undefined)
|
||||
continue;
|
||||
// Objects keys always overwrite older headers, they never append.
|
||||
// Yield a null to clear the header before adding the new values.
|
||||
if (shouldClear && !didClear) {
|
||||
didClear = true;
|
||||
yield [name, null];
|
||||
}
|
||||
yield [name, value];
|
||||
}
|
||||
}
|
||||
}
|
||||
export const buildHeaders = (newHeaders) => {
|
||||
const targetHeaders = new Headers();
|
||||
const nullHeaders = new Set();
|
||||
for (const headers of newHeaders) {
|
||||
const seenHeaders = new Set();
|
||||
for (const [name, value] of iterateHeaders(headers)) {
|
||||
const lowerName = name.toLowerCase();
|
||||
if (!seenHeaders.has(lowerName)) {
|
||||
targetHeaders.delete(name);
|
||||
seenHeaders.add(lowerName);
|
||||
}
|
||||
if (value === null) {
|
||||
targetHeaders.delete(name);
|
||||
nullHeaders.add(lowerName);
|
||||
}
|
||||
else {
|
||||
targetHeaders.append(name, value);
|
||||
nullHeaders.delete(lowerName);
|
||||
}
|
||||
}
|
||||
}
|
||||
return { [brand_privateNullableHeaders]: true, values: targetHeaders, nulls: nullHeaders };
|
||||
};
|
||||
export const isEmptyHeaders = (headers) => {
|
||||
for (const _ of iterateHeaders(headers))
|
||||
return false;
|
||||
return true;
|
||||
};
|
||||
//# sourceMappingURL=headers.mjs.map
|
||||
8
claude-code-source/node_modules/@anthropic-ai/foundry-sdk/internal/utils.mjs
generated
vendored
8
claude-code-source/node_modules/@anthropic-ai/foundry-sdk/internal/utils.mjs
generated
vendored
@@ -1,8 +0,0 @@
|
||||
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
||||
export * from "./utils/values.mjs";
|
||||
export * from "./utils/base64.mjs";
|
||||
export * from "./utils/env.mjs";
|
||||
export * from "./utils/log.mjs";
|
||||
export * from "./utils/uuid.mjs";
|
||||
export * from "./utils/sleep.mjs";
|
||||
//# sourceMappingURL=utils.mjs.map
|
||||
33
claude-code-source/node_modules/@anthropic-ai/foundry-sdk/internal/utils/base64.mjs
generated
vendored
33
claude-code-source/node_modules/@anthropic-ai/foundry-sdk/internal/utils/base64.mjs
generated
vendored
@@ -1,33 +0,0 @@
|
||||
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
||||
import { AnthropicError } from "../../core/error.mjs";
|
||||
import { encodeUTF8 } from "./bytes.mjs";
|
||||
export const toBase64 = (data) => {
|
||||
if (!data)
|
||||
return '';
|
||||
if (typeof globalThis.Buffer !== 'undefined') {
|
||||
return globalThis.Buffer.from(data).toString('base64');
|
||||
}
|
||||
if (typeof data === 'string') {
|
||||
data = encodeUTF8(data);
|
||||
}
|
||||
if (typeof btoa !== 'undefined') {
|
||||
return btoa(String.fromCharCode.apply(null, data));
|
||||
}
|
||||
throw new AnthropicError('Cannot generate base64 string; Expected `Buffer` or `btoa` to be defined');
|
||||
};
|
||||
export const fromBase64 = (str) => {
|
||||
if (typeof globalThis.Buffer !== 'undefined') {
|
||||
const buf = globalThis.Buffer.from(str, 'base64');
|
||||
return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
|
||||
}
|
||||
if (typeof atob !== 'undefined') {
|
||||
const bstr = atob(str);
|
||||
const buf = new Uint8Array(bstr.length);
|
||||
for (let i = 0; i < bstr.length; i++) {
|
||||
buf[i] = bstr.charCodeAt(i);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
throw new AnthropicError('Cannot decode base64 string; Expected `Buffer` or `atob` to be defined');
|
||||
};
|
||||
//# sourceMappingURL=base64.mjs.map
|
||||
18
claude-code-source/node_modules/@anthropic-ai/foundry-sdk/internal/utils/env.mjs
generated
vendored
18
claude-code-source/node_modules/@anthropic-ai/foundry-sdk/internal/utils/env.mjs
generated
vendored
@@ -1,18 +0,0 @@
|
||||
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
||||
/**
|
||||
* Read an environment variable.
|
||||
*
|
||||
* Trims beginning and trailing whitespace.
|
||||
*
|
||||
* Will return undefined if the environment variable doesn't exist or cannot be accessed.
|
||||
*/
|
||||
export const readEnv = (env) => {
|
||||
if (typeof globalThis.process !== 'undefined') {
|
||||
return globalThis.process.env?.[env]?.trim() ?? undefined;
|
||||
}
|
||||
if (typeof globalThis.Deno !== 'undefined') {
|
||||
return globalThis.Deno.env?.get?.(env)?.trim();
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
//# sourceMappingURL=env.mjs.map
|
||||
80
claude-code-source/node_modules/@anthropic-ai/foundry-sdk/internal/utils/log.mjs
generated
vendored
80
claude-code-source/node_modules/@anthropic-ai/foundry-sdk/internal/utils/log.mjs
generated
vendored
@@ -1,80 +0,0 @@
|
||||
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
||||
import { hasOwn } from "./values.mjs";
|
||||
const levelNumbers = {
|
||||
off: 0,
|
||||
error: 200,
|
||||
warn: 300,
|
||||
info: 400,
|
||||
debug: 500,
|
||||
};
|
||||
export const parseLogLevel = (maybeLevel, sourceName, client) => {
|
||||
if (!maybeLevel) {
|
||||
return undefined;
|
||||
}
|
||||
if (hasOwn(levelNumbers, maybeLevel)) {
|
||||
return maybeLevel;
|
||||
}
|
||||
loggerFor(client).warn(`${sourceName} was set to ${JSON.stringify(maybeLevel)}, expected one of ${JSON.stringify(Object.keys(levelNumbers))}`);
|
||||
return undefined;
|
||||
};
|
||||
function noop() { }
|
||||
function makeLogFn(fnLevel, logger, logLevel) {
|
||||
if (!logger || levelNumbers[fnLevel] > levelNumbers[logLevel]) {
|
||||
return noop;
|
||||
}
|
||||
else {
|
||||
// Don't wrap logger functions, we want the stacktrace intact!
|
||||
return logger[fnLevel].bind(logger);
|
||||
}
|
||||
}
|
||||
const noopLogger = {
|
||||
error: noop,
|
||||
warn: noop,
|
||||
info: noop,
|
||||
debug: noop,
|
||||
};
|
||||
let cachedLoggers = /* @__PURE__ */ new WeakMap();
|
||||
export function loggerFor(client) {
|
||||
const logger = client.logger;
|
||||
const logLevel = client.logLevel ?? 'off';
|
||||
if (!logger) {
|
||||
return noopLogger;
|
||||
}
|
||||
const cachedLogger = cachedLoggers.get(logger);
|
||||
if (cachedLogger && cachedLogger[0] === logLevel) {
|
||||
return cachedLogger[1];
|
||||
}
|
||||
const levelLogger = {
|
||||
error: makeLogFn('error', logger, logLevel),
|
||||
warn: makeLogFn('warn', logger, logLevel),
|
||||
info: makeLogFn('info', logger, logLevel),
|
||||
debug: makeLogFn('debug', logger, logLevel),
|
||||
};
|
||||
cachedLoggers.set(logger, [logLevel, levelLogger]);
|
||||
return levelLogger;
|
||||
}
|
||||
export const formatRequestDetails = (details) => {
|
||||
if (details.options) {
|
||||
details.options = { ...details.options };
|
||||
delete details.options['headers']; // redundant + leaks internals
|
||||
}
|
||||
if (details.headers) {
|
||||
details.headers = Object.fromEntries((details.headers instanceof Headers ? [...details.headers] : Object.entries(details.headers)).map(([name, value]) => [
|
||||
name,
|
||||
(name.toLowerCase() === 'x-api-key' ||
|
||||
name.toLowerCase() === 'authorization' ||
|
||||
name.toLowerCase() === 'cookie' ||
|
||||
name.toLowerCase() === 'set-cookie') ?
|
||||
'***'
|
||||
: value,
|
||||
]));
|
||||
}
|
||||
if ('retryOfRequestLogID' in details) {
|
||||
if (details.retryOfRequestLogID) {
|
||||
details.retryOf = details.retryOfRequestLogID;
|
||||
}
|
||||
delete details.retryOfRequestLogID;
|
||||
}
|
||||
return details;
|
||||
};
|
||||
//# sourceMappingURL=log.mjs.map
|
||||
1
claude-code-source/node_modules/@anthropic-ai/foundry-sdk/internal/utils/sleep.mjs
generated
vendored
1
claude-code-source/node_modules/@anthropic-ai/foundry-sdk/internal/utils/sleep.mjs
generated
vendored
@@ -1 +0,0 @@
|
||||
export function sleep(ms) { return new Promise(r => setTimeout(r, ms)) }
|
||||
2
claude-code-source/node_modules/@anthropic-ai/foundry-sdk/internal/utils/uuid.mjs
generated
vendored
2
claude-code-source/node_modules/@anthropic-ai/foundry-sdk/internal/utils/uuid.mjs
generated
vendored
@@ -1,2 +0,0 @@
|
||||
import { randomUUID } from 'crypto'
|
||||
export function generateUUID() { return randomUUID() }
|
||||
100
claude-code-source/node_modules/@anthropic-ai/foundry-sdk/internal/utils/values.mjs
generated
vendored
100
claude-code-source/node_modules/@anthropic-ai/foundry-sdk/internal/utils/values.mjs
generated
vendored
@@ -1,100 +0,0 @@
|
||||
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
||||
import { AnthropicError } from "../../core/error.mjs";
|
||||
// https://url.spec.whatwg.org/#url-scheme-string
|
||||
const startsWithSchemeRegexp = /^[a-z][a-z0-9+.-]*:/i;
|
||||
export const isAbsoluteURL = (url) => {
|
||||
return startsWithSchemeRegexp.test(url);
|
||||
};
|
||||
export let isArray = (val) => ((isArray = Array.isArray), isArray(val));
|
||||
export let isReadonlyArray = isArray;
|
||||
/** Returns an object if the given value isn't an object, otherwise returns as-is */
|
||||
export function maybeObj(x) {
|
||||
if (typeof x !== 'object') {
|
||||
return {};
|
||||
}
|
||||
return x ?? {};
|
||||
}
|
||||
// https://stackoverflow.com/a/34491287
|
||||
export function isEmptyObj(obj) {
|
||||
if (!obj)
|
||||
return true;
|
||||
for (const _k in obj)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
// https://eslint.org/docs/latest/rules/no-prototype-builtins
|
||||
export function hasOwn(obj, key) {
|
||||
return Object.prototype.hasOwnProperty.call(obj, key);
|
||||
}
|
||||
export function isObj(obj) {
|
||||
return obj != null && typeof obj === 'object' && !Array.isArray(obj);
|
||||
}
|
||||
export const ensurePresent = (value) => {
|
||||
if (value == null) {
|
||||
throw new AnthropicError(`Expected a value to be given but received ${value} instead.`);
|
||||
}
|
||||
return value;
|
||||
};
|
||||
export const validatePositiveInteger = (name, n) => {
|
||||
if (typeof n !== 'number' || !Number.isInteger(n)) {
|
||||
throw new AnthropicError(`${name} must be an integer`);
|
||||
}
|
||||
if (n < 0) {
|
||||
throw new AnthropicError(`${name} must be a positive integer`);
|
||||
}
|
||||
return n;
|
||||
};
|
||||
export const coerceInteger = (value) => {
|
||||
if (typeof value === 'number')
|
||||
return Math.round(value);
|
||||
if (typeof value === 'string')
|
||||
return parseInt(value, 10);
|
||||
throw new AnthropicError(`Could not coerce ${value} (type: ${typeof value}) into a number`);
|
||||
};
|
||||
export const coerceFloat = (value) => {
|
||||
if (typeof value === 'number')
|
||||
return value;
|
||||
if (typeof value === 'string')
|
||||
return parseFloat(value);
|
||||
throw new AnthropicError(`Could not coerce ${value} (type: ${typeof value}) into a number`);
|
||||
};
|
||||
export const coerceBoolean = (value) => {
|
||||
if (typeof value === 'boolean')
|
||||
return value;
|
||||
if (typeof value === 'string')
|
||||
return value === 'true';
|
||||
return Boolean(value);
|
||||
};
|
||||
export const maybeCoerceInteger = (value) => {
|
||||
if (value == null) {
|
||||
return undefined;
|
||||
}
|
||||
return coerceInteger(value);
|
||||
};
|
||||
export const maybeCoerceFloat = (value) => {
|
||||
if (value == null) {
|
||||
return undefined;
|
||||
}
|
||||
return coerceFloat(value);
|
||||
};
|
||||
export const maybeCoerceBoolean = (value) => {
|
||||
if (value == null) {
|
||||
return undefined;
|
||||
}
|
||||
return coerceBoolean(value);
|
||||
};
|
||||
export const safeJSON = (text) => {
|
||||
try {
|
||||
return JSON.parse(text);
|
||||
}
|
||||
catch (err) {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
// Gets a value from an object, deletes the key, and returns the value (or undefined if not found)
|
||||
export const pop = (obj, key) => {
|
||||
const value = obj[key];
|
||||
delete obj[key];
|
||||
return value;
|
||||
};
|
||||
//# sourceMappingURL=values.mjs.map
|
||||
223
claude-code-source/node_modules/@anthropic-ai/sdk/_vendor/partial-json-parser/parser.mjs
generated
vendored
223
claude-code-source/node_modules/@anthropic-ai/sdk/_vendor/partial-json-parser/parser.mjs
generated
vendored
@@ -1,223 +0,0 @@
|
||||
const tokenize = (input) => {
|
||||
let current = 0;
|
||||
let tokens = [];
|
||||
while (current < input.length) {
|
||||
let char = input[current];
|
||||
if (char === '\\') {
|
||||
current++;
|
||||
continue;
|
||||
}
|
||||
if (char === '{') {
|
||||
tokens.push({
|
||||
type: 'brace',
|
||||
value: '{',
|
||||
});
|
||||
current++;
|
||||
continue;
|
||||
}
|
||||
if (char === '}') {
|
||||
tokens.push({
|
||||
type: 'brace',
|
||||
value: '}',
|
||||
});
|
||||
current++;
|
||||
continue;
|
||||
}
|
||||
if (char === '[') {
|
||||
tokens.push({
|
||||
type: 'paren',
|
||||
value: '[',
|
||||
});
|
||||
current++;
|
||||
continue;
|
||||
}
|
||||
if (char === ']') {
|
||||
tokens.push({
|
||||
type: 'paren',
|
||||
value: ']',
|
||||
});
|
||||
current++;
|
||||
continue;
|
||||
}
|
||||
if (char === ':') {
|
||||
tokens.push({
|
||||
type: 'separator',
|
||||
value: ':',
|
||||
});
|
||||
current++;
|
||||
continue;
|
||||
}
|
||||
if (char === ',') {
|
||||
tokens.push({
|
||||
type: 'delimiter',
|
||||
value: ',',
|
||||
});
|
||||
current++;
|
||||
continue;
|
||||
}
|
||||
if (char === '"') {
|
||||
let value = '';
|
||||
let danglingQuote = false;
|
||||
char = input[++current];
|
||||
while (char !== '"') {
|
||||
if (current === input.length) {
|
||||
danglingQuote = true;
|
||||
break;
|
||||
}
|
||||
if (char === '\\') {
|
||||
current++;
|
||||
if (current === input.length) {
|
||||
danglingQuote = true;
|
||||
break;
|
||||
}
|
||||
value += char + input[current];
|
||||
char = input[++current];
|
||||
}
|
||||
else {
|
||||
value += char;
|
||||
char = input[++current];
|
||||
}
|
||||
}
|
||||
char = input[++current];
|
||||
if (!danglingQuote) {
|
||||
tokens.push({
|
||||
type: 'string',
|
||||
value,
|
||||
});
|
||||
}
|
||||
continue;
|
||||
}
|
||||
let WHITESPACE = /\s/;
|
||||
if (char && WHITESPACE.test(char)) {
|
||||
current++;
|
||||
continue;
|
||||
}
|
||||
let NUMBERS = /[0-9]/;
|
||||
if ((char && NUMBERS.test(char)) || char === '-' || char === '.') {
|
||||
let value = '';
|
||||
if (char === '-') {
|
||||
value += char;
|
||||
char = input[++current];
|
||||
}
|
||||
while ((char && NUMBERS.test(char)) || char === '.') {
|
||||
value += char;
|
||||
char = input[++current];
|
||||
}
|
||||
tokens.push({
|
||||
type: 'number',
|
||||
value,
|
||||
});
|
||||
continue;
|
||||
}
|
||||
let LETTERS = /[a-z]/i;
|
||||
if (char && LETTERS.test(char)) {
|
||||
let value = '';
|
||||
while (char && LETTERS.test(char)) {
|
||||
if (current === input.length) {
|
||||
break;
|
||||
}
|
||||
value += char;
|
||||
char = input[++current];
|
||||
}
|
||||
if (value == 'true' || value == 'false' || value === 'null') {
|
||||
tokens.push({
|
||||
type: 'name',
|
||||
value,
|
||||
});
|
||||
}
|
||||
else {
|
||||
// unknown token, e.g. `nul` which isn't quite `null`
|
||||
current++;
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
current++;
|
||||
}
|
||||
return tokens;
|
||||
}, strip = (tokens) => {
|
||||
if (tokens.length === 0) {
|
||||
return tokens;
|
||||
}
|
||||
let lastToken = tokens[tokens.length - 1];
|
||||
switch (lastToken.type) {
|
||||
case 'separator':
|
||||
tokens = tokens.slice(0, tokens.length - 1);
|
||||
return strip(tokens);
|
||||
break;
|
||||
case 'number':
|
||||
let lastCharacterOfLastToken = lastToken.value[lastToken.value.length - 1];
|
||||
if (lastCharacterOfLastToken === '.' || lastCharacterOfLastToken === '-') {
|
||||
tokens = tokens.slice(0, tokens.length - 1);
|
||||
return strip(tokens);
|
||||
}
|
||||
case 'string':
|
||||
let tokenBeforeTheLastToken = tokens[tokens.length - 2];
|
||||
if (tokenBeforeTheLastToken?.type === 'delimiter') {
|
||||
tokens = tokens.slice(0, tokens.length - 1);
|
||||
return strip(tokens);
|
||||
}
|
||||
else if (tokenBeforeTheLastToken?.type === 'brace' && tokenBeforeTheLastToken.value === '{') {
|
||||
tokens = tokens.slice(0, tokens.length - 1);
|
||||
return strip(tokens);
|
||||
}
|
||||
break;
|
||||
case 'delimiter':
|
||||
tokens = tokens.slice(0, tokens.length - 1);
|
||||
return strip(tokens);
|
||||
break;
|
||||
}
|
||||
return tokens;
|
||||
}, unstrip = (tokens) => {
|
||||
let tail = [];
|
||||
tokens.map((token) => {
|
||||
if (token.type === 'brace') {
|
||||
if (token.value === '{') {
|
||||
tail.push('}');
|
||||
}
|
||||
else {
|
||||
tail.splice(tail.lastIndexOf('}'), 1);
|
||||
}
|
||||
}
|
||||
if (token.type === 'paren') {
|
||||
if (token.value === '[') {
|
||||
tail.push(']');
|
||||
}
|
||||
else {
|
||||
tail.splice(tail.lastIndexOf(']'), 1);
|
||||
}
|
||||
}
|
||||
});
|
||||
if (tail.length > 0) {
|
||||
tail.reverse().map((item) => {
|
||||
if (item === '}') {
|
||||
tokens.push({
|
||||
type: 'brace',
|
||||
value: '}',
|
||||
});
|
||||
}
|
||||
else if (item === ']') {
|
||||
tokens.push({
|
||||
type: 'paren',
|
||||
value: ']',
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
return tokens;
|
||||
}, generate = (tokens) => {
|
||||
let output = '';
|
||||
tokens.map((token) => {
|
||||
switch (token.type) {
|
||||
case 'string':
|
||||
output += '"' + token.value + '"';
|
||||
break;
|
||||
default:
|
||||
output += token.value;
|
||||
break;
|
||||
}
|
||||
});
|
||||
return output;
|
||||
}, partialParse = (input) => JSON.parse(generate(unstrip(strip(tokenize(input)))));
|
||||
export { partialParse };
|
||||
//# sourceMappingURL=parser.mjs.map
|
||||
559
claude-code-source/node_modules/@anthropic-ai/sdk/client.mjs
generated
vendored
559
claude-code-source/node_modules/@anthropic-ai/sdk/client.mjs
generated
vendored
@@ -1,559 +0,0 @@
|
||||
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
||||
var _BaseAnthropic_instances, _a, _BaseAnthropic_encoder, _BaseAnthropic_baseURLOverridden;
|
||||
import { __classPrivateFieldGet, __classPrivateFieldSet } from "./internal/tslib.mjs";
|
||||
import { uuid4 } from "./internal/utils/uuid.mjs";
|
||||
import { validatePositiveInteger, isAbsoluteURL, safeJSON } from "./internal/utils/values.mjs";
|
||||
import { sleep } from "./internal/utils/sleep.mjs";
|
||||
import { castToError, isAbortError } from "./internal/errors.mjs";
|
||||
import { getPlatformHeaders } from "./internal/detect-platform.mjs";
|
||||
import * as Shims from "./internal/shims.mjs";
|
||||
import * as Opts from "./internal/request-options.mjs";
|
||||
import { VERSION } from "./version.mjs";
|
||||
import * as Errors from "./core/error.mjs";
|
||||
import * as Pagination from "./core/pagination.mjs";
|
||||
import * as Uploads from "./core/uploads.mjs";
|
||||
import * as API from "./resources/index.mjs";
|
||||
import { APIPromise } from "./core/api-promise.mjs";
|
||||
import { Completions, } from "./resources/completions.mjs";
|
||||
import { Models } from "./resources/models.mjs";
|
||||
import { Beta, } from "./resources/beta/beta.mjs";
|
||||
import { Messages, } from "./resources/messages/messages.mjs";
|
||||
import { isRunningInBrowser } from "./internal/detect-platform.mjs";
|
||||
import { buildHeaders } from "./internal/headers.mjs";
|
||||
import { readEnv } from "./internal/utils/env.mjs";
|
||||
import { formatRequestDetails, loggerFor, parseLogLevel, } from "./internal/utils/log.mjs";
|
||||
import { isEmptyObj } from "./internal/utils/values.mjs";
|
||||
export const HUMAN_PROMPT = '\\n\\nHuman:';
|
||||
export const AI_PROMPT = '\\n\\nAssistant:';
|
||||
/**
|
||||
* Base class for Anthropic API clients.
|
||||
*/
|
||||
export class BaseAnthropic {
|
||||
/**
|
||||
* API Client for interfacing with the Anthropic API.
|
||||
*
|
||||
* @param {string | null | undefined} [opts.apiKey=process.env['ANTHROPIC_API_KEY'] ?? null]
|
||||
* @param {string | null | undefined} [opts.authToken=process.env['ANTHROPIC_AUTH_TOKEN'] ?? null]
|
||||
* @param {string} [opts.baseURL=process.env['ANTHROPIC_BASE_URL'] ?? https://api.anthropic.com] - Override the default base URL for the API.
|
||||
* @param {number} [opts.timeout=10 minutes] - The maximum amount of time (in milliseconds) the client will wait for a response before timing out.
|
||||
* @param {MergedRequestInit} [opts.fetchOptions] - Additional `RequestInit` options to be passed to `fetch` calls.
|
||||
* @param {Fetch} [opts.fetch] - Specify a custom `fetch` function implementation.
|
||||
* @param {number} [opts.maxRetries=2] - The maximum number of times the client will retry a request.
|
||||
* @param {HeadersLike} opts.defaultHeaders - Default headers to include with every request to the API.
|
||||
* @param {Record<string, string | undefined>} opts.defaultQuery - Default query parameters to include with every request to the API.
|
||||
* @param {boolean} [opts.dangerouslyAllowBrowser=false] - By default, client-side use of this library is not allowed, as it risks exposing your secret API credentials to attackers.
|
||||
*/
|
||||
constructor({ baseURL = readEnv('ANTHROPIC_BASE_URL'), apiKey = readEnv('ANTHROPIC_API_KEY') ?? null, authToken = readEnv('ANTHROPIC_AUTH_TOKEN') ?? null, ...opts } = {}) {
|
||||
_BaseAnthropic_instances.add(this);
|
||||
_BaseAnthropic_encoder.set(this, void 0);
|
||||
const options = {
|
||||
apiKey,
|
||||
authToken,
|
||||
...opts,
|
||||
baseURL: baseURL || `https://api.anthropic.com`,
|
||||
};
|
||||
if (!options.dangerouslyAllowBrowser && isRunningInBrowser()) {
|
||||
throw new Errors.AnthropicError("It looks like you're running in a browser-like environment.\n\nThis is disabled by default, as it risks exposing your secret API credentials to attackers.\nIf you understand the risks and have appropriate mitigations in place,\nyou can set the `dangerouslyAllowBrowser` option to `true`, e.g.,\n\nnew Anthropic({ apiKey, dangerouslyAllowBrowser: true });\n");
|
||||
}
|
||||
this.baseURL = options.baseURL;
|
||||
this.timeout = options.timeout ?? _a.DEFAULT_TIMEOUT /* 10 minutes */;
|
||||
this.logger = options.logger ?? console;
|
||||
const defaultLogLevel = 'warn';
|
||||
// Set default logLevel early so that we can log a warning in parseLogLevel.
|
||||
this.logLevel = defaultLogLevel;
|
||||
this.logLevel =
|
||||
parseLogLevel(options.logLevel, 'ClientOptions.logLevel', this) ??
|
||||
parseLogLevel(readEnv('ANTHROPIC_LOG'), "process.env['ANTHROPIC_LOG']", this) ??
|
||||
defaultLogLevel;
|
||||
this.fetchOptions = options.fetchOptions;
|
||||
this.maxRetries = options.maxRetries ?? 2;
|
||||
this.fetch = options.fetch ?? Shims.getDefaultFetch();
|
||||
__classPrivateFieldSet(this, _BaseAnthropic_encoder, Opts.FallbackEncoder, "f");
|
||||
this._options = options;
|
||||
this.apiKey = typeof apiKey === 'string' ? apiKey : null;
|
||||
this.authToken = authToken;
|
||||
}
|
||||
/**
|
||||
* Create a new client instance re-using the same options given to the current client with optional overriding.
|
||||
*/
|
||||
withOptions(options) {
|
||||
const client = new this.constructor({
|
||||
...this._options,
|
||||
baseURL: this.baseURL,
|
||||
maxRetries: this.maxRetries,
|
||||
timeout: this.timeout,
|
||||
logger: this.logger,
|
||||
logLevel: this.logLevel,
|
||||
fetch: this.fetch,
|
||||
fetchOptions: this.fetchOptions,
|
||||
apiKey: this.apiKey,
|
||||
authToken: this.authToken,
|
||||
...options,
|
||||
});
|
||||
return client;
|
||||
}
|
||||
defaultQuery() {
|
||||
return this._options.defaultQuery;
|
||||
}
|
||||
validateHeaders({ values, nulls }) {
|
||||
if (values.get('x-api-key') || values.get('authorization')) {
|
||||
return;
|
||||
}
|
||||
if (this.apiKey && values.get('x-api-key')) {
|
||||
return;
|
||||
}
|
||||
if (nulls.has('x-api-key')) {
|
||||
return;
|
||||
}
|
||||
if (this.authToken && values.get('authorization')) {
|
||||
return;
|
||||
}
|
||||
if (nulls.has('authorization')) {
|
||||
return;
|
||||
}
|
||||
throw new Error('Could not resolve authentication method. Expected either apiKey or authToken to be set. Or for one of the "X-Api-Key" or "Authorization" headers to be explicitly omitted');
|
||||
}
|
||||
async authHeaders(opts) {
|
||||
return buildHeaders([await this.apiKeyAuth(opts), await this.bearerAuth(opts)]);
|
||||
}
|
||||
async apiKeyAuth(opts) {
|
||||
if (this.apiKey == null) {
|
||||
return undefined;
|
||||
}
|
||||
return buildHeaders([{ 'X-Api-Key': this.apiKey }]);
|
||||
}
|
||||
async bearerAuth(opts) {
|
||||
if (this.authToken == null) {
|
||||
return undefined;
|
||||
}
|
||||
return buildHeaders([{ Authorization: `Bearer ${this.authToken}` }]);
|
||||
}
|
||||
/**
|
||||
* Basic re-implementation of `qs.stringify` for primitive types.
|
||||
*/
|
||||
stringifyQuery(query) {
|
||||
return Object.entries(query)
|
||||
.filter(([_, value]) => typeof value !== 'undefined')
|
||||
.map(([key, value]) => {
|
||||
if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
|
||||
return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
|
||||
}
|
||||
if (value === null) {
|
||||
return `${encodeURIComponent(key)}=`;
|
||||
}
|
||||
throw new Errors.AnthropicError(`Cannot stringify type ${typeof value}; Expected string, number, boolean, or null. If you need to pass nested query parameters, you can manually encode them, e.g. { query: { 'foo[key1]': value1, 'foo[key2]': value2 } }, and please open a GitHub issue requesting better support for your use case.`);
|
||||
})
|
||||
.join('&');
|
||||
}
|
||||
getUserAgent() {
|
||||
return `${this.constructor.name}/JS ${VERSION}`;
|
||||
}
|
||||
defaultIdempotencyKey() {
|
||||
return `stainless-node-retry-${uuid4()}`;
|
||||
}
|
||||
makeStatusError(status, error, message, headers) {
|
||||
return Errors.APIError.generate(status, error, message, headers);
|
||||
}
|
||||
buildURL(path, query, defaultBaseURL) {
|
||||
const baseURL = (!__classPrivateFieldGet(this, _BaseAnthropic_instances, "m", _BaseAnthropic_baseURLOverridden).call(this) && defaultBaseURL) || this.baseURL;
|
||||
const url = isAbsoluteURL(path) ?
|
||||
new URL(path)
|
||||
: new URL(baseURL + (baseURL.endsWith('/') && path.startsWith('/') ? path.slice(1) : path));
|
||||
const defaultQuery = this.defaultQuery();
|
||||
if (!isEmptyObj(defaultQuery)) {
|
||||
query = { ...defaultQuery, ...query };
|
||||
}
|
||||
if (typeof query === 'object' && query && !Array.isArray(query)) {
|
||||
url.search = this.stringifyQuery(query);
|
||||
}
|
||||
return url.toString();
|
||||
}
|
||||
_calculateNonstreamingTimeout(maxTokens) {
|
||||
const defaultTimeout = 10 * 60;
|
||||
const expectedTimeout = (60 * 60 * maxTokens) / 128000;
|
||||
if (expectedTimeout > defaultTimeout) {
|
||||
throw new Errors.AnthropicError('Streaming is required for operations that may take longer than 10 minutes. ' +
|
||||
'See https://github.com/anthropics/anthropic-sdk-typescript#streaming-responses for more details');
|
||||
}
|
||||
return defaultTimeout * 1000;
|
||||
}
|
||||
/**
|
||||
* Used as a callback for mutating the given `FinalRequestOptions` object.
|
||||
*/
|
||||
async prepareOptions(options) { }
|
||||
/**
|
||||
* Used as a callback for mutating the given `RequestInit` object.
|
||||
*
|
||||
* This is useful for cases where you want to add certain headers based off of
|
||||
* the request properties, e.g. `method` or `url`.
|
||||
*/
|
||||
async prepareRequest(request, { url, options }) { }
|
||||
get(path, opts) {
|
||||
return this.methodRequest('get', path, opts);
|
||||
}
|
||||
post(path, opts) {
|
||||
return this.methodRequest('post', path, opts);
|
||||
}
|
||||
patch(path, opts) {
|
||||
return this.methodRequest('patch', path, opts);
|
||||
}
|
||||
put(path, opts) {
|
||||
return this.methodRequest('put', path, opts);
|
||||
}
|
||||
delete(path, opts) {
|
||||
return this.methodRequest('delete', path, opts);
|
||||
}
|
||||
methodRequest(method, path, opts) {
|
||||
return this.request(Promise.resolve(opts).then((opts) => {
|
||||
return { method, path, ...opts };
|
||||
}));
|
||||
}
|
||||
request(options, remainingRetries = null) {
|
||||
return new APIPromise(this, this.makeRequest(options, remainingRetries, undefined));
|
||||
}
|
||||
async makeRequest(optionsInput, retriesRemaining, retryOfRequestLogID) {
|
||||
const options = await optionsInput;
|
||||
const maxRetries = options.maxRetries ?? this.maxRetries;
|
||||
if (retriesRemaining == null) {
|
||||
retriesRemaining = maxRetries;
|
||||
}
|
||||
await this.prepareOptions(options);
|
||||
const { req, url, timeout } = await this.buildRequest(options, {
|
||||
retryCount: maxRetries - retriesRemaining,
|
||||
});
|
||||
await this.prepareRequest(req, { url, options });
|
||||
/** Not an API request ID, just for correlating local log entries. */
|
||||
const requestLogID = 'log_' + ((Math.random() * (1 << 24)) | 0).toString(16).padStart(6, '0');
|
||||
const retryLogStr = retryOfRequestLogID === undefined ? '' : `, retryOf: ${retryOfRequestLogID}`;
|
||||
const startTime = Date.now();
|
||||
loggerFor(this).debug(`[${requestLogID}] sending request`, formatRequestDetails({
|
||||
retryOfRequestLogID,
|
||||
method: options.method,
|
||||
url,
|
||||
options,
|
||||
headers: req.headers,
|
||||
}));
|
||||
if (options.signal?.aborted) {
|
||||
throw new Errors.APIUserAbortError();
|
||||
}
|
||||
const controller = new AbortController();
|
||||
const response = await this.fetchWithTimeout(url, req, timeout, controller).catch(castToError);
|
||||
const headersTime = Date.now();
|
||||
if (response instanceof globalThis.Error) {
|
||||
const retryMessage = `retrying, ${retriesRemaining} attempts remaining`;
|
||||
if (options.signal?.aborted) {
|
||||
throw new Errors.APIUserAbortError();
|
||||
}
|
||||
// detect native connection timeout errors
|
||||
// deno throws "TypeError: error sending request for url (https://example/): client error (Connect): tcp connect error: Operation timed out (os error 60): Operation timed out (os error 60)"
|
||||
// undici throws "TypeError: fetch failed" with cause "ConnectTimeoutError: Connect Timeout Error (attempted address: example:443, timeout: 1ms)"
|
||||
// others do not provide enough information to distinguish timeouts from other connection errors
|
||||
const isTimeout = isAbortError(response) ||
|
||||
/timed? ?out/i.test(String(response) + ('cause' in response ? String(response.cause) : ''));
|
||||
if (retriesRemaining) {
|
||||
loggerFor(this).info(`[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} - ${retryMessage}`);
|
||||
loggerFor(this).debug(`[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} (${retryMessage})`, formatRequestDetails({
|
||||
retryOfRequestLogID,
|
||||
url,
|
||||
durationMs: headersTime - startTime,
|
||||
message: response.message,
|
||||
}));
|
||||
return this.retryRequest(options, retriesRemaining, retryOfRequestLogID ?? requestLogID);
|
||||
}
|
||||
loggerFor(this).info(`[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} - error; no more retries left`);
|
||||
loggerFor(this).debug(`[${requestLogID}] connection ${isTimeout ? 'timed out' : 'failed'} (error; no more retries left)`, formatRequestDetails({
|
||||
retryOfRequestLogID,
|
||||
url,
|
||||
durationMs: headersTime - startTime,
|
||||
message: response.message,
|
||||
}));
|
||||
if (isTimeout) {
|
||||
throw new Errors.APIConnectionTimeoutError();
|
||||
}
|
||||
throw new Errors.APIConnectionError({ cause: response });
|
||||
}
|
||||
const specialHeaders = [...response.headers.entries()]
|
||||
.filter(([name]) => name === 'request-id')
|
||||
.map(([name, value]) => ', ' + name + ': ' + JSON.stringify(value))
|
||||
.join('');
|
||||
const responseInfo = `[${requestLogID}${retryLogStr}${specialHeaders}] ${req.method} ${url} ${response.ok ? 'succeeded' : 'failed'} with status ${response.status} in ${headersTime - startTime}ms`;
|
||||
if (!response.ok) {
|
||||
const shouldRetry = await this.shouldRetry(response);
|
||||
if (retriesRemaining && shouldRetry) {
|
||||
const retryMessage = `retrying, ${retriesRemaining} attempts remaining`;
|
||||
// We don't need the body of this response.
|
||||
await Shims.CancelReadableStream(response.body);
|
||||
loggerFor(this).info(`${responseInfo} - ${retryMessage}`);
|
||||
loggerFor(this).debug(`[${requestLogID}] response error (${retryMessage})`, formatRequestDetails({
|
||||
retryOfRequestLogID,
|
||||
url: response.url,
|
||||
status: response.status,
|
||||
headers: response.headers,
|
||||
durationMs: headersTime - startTime,
|
||||
}));
|
||||
return this.retryRequest(options, retriesRemaining, retryOfRequestLogID ?? requestLogID, response.headers);
|
||||
}
|
||||
const retryMessage = shouldRetry ? `error; no more retries left` : `error; not retryable`;
|
||||
loggerFor(this).info(`${responseInfo} - ${retryMessage}`);
|
||||
const errText = await response.text().catch((err) => castToError(err).message);
|
||||
const errJSON = safeJSON(errText);
|
||||
const errMessage = errJSON ? undefined : errText;
|
||||
loggerFor(this).debug(`[${requestLogID}] response error (${retryMessage})`, formatRequestDetails({
|
||||
retryOfRequestLogID,
|
||||
url: response.url,
|
||||
status: response.status,
|
||||
headers: response.headers,
|
||||
message: errMessage,
|
||||
durationMs: Date.now() - startTime,
|
||||
}));
|
||||
const err = this.makeStatusError(response.status, errJSON, errMessage, response.headers);
|
||||
throw err;
|
||||
}
|
||||
loggerFor(this).info(responseInfo);
|
||||
loggerFor(this).debug(`[${requestLogID}] response start`, formatRequestDetails({
|
||||
retryOfRequestLogID,
|
||||
url: response.url,
|
||||
status: response.status,
|
||||
headers: response.headers,
|
||||
durationMs: headersTime - startTime,
|
||||
}));
|
||||
return { response, options, controller, requestLogID, retryOfRequestLogID, startTime };
|
||||
}
|
||||
getAPIList(path, Page, opts) {
|
||||
return this.requestAPIList(Page, opts && 'then' in opts ?
|
||||
opts.then((opts) => ({ method: 'get', path, ...opts }))
|
||||
: { method: 'get', path, ...opts });
|
||||
}
|
||||
requestAPIList(Page, options) {
|
||||
const request = this.makeRequest(options, null, undefined);
|
||||
return new Pagination.PagePromise(this, request, Page);
|
||||
}
|
||||
async fetchWithTimeout(url, init, ms, controller) {
|
||||
const { signal, method, ...options } = init || {};
|
||||
// Avoid creating a closure over `this`, `init`, or `options` to prevent memory leaks.
|
||||
// An arrow function like `() => controller.abort()` captures the surrounding scope,
|
||||
// which includes the request body and other large objects. When the user passes a
|
||||
// long-lived AbortSignal, the listener prevents those objects from being GC'd for
|
||||
// the lifetime of the signal. Using `.bind()` only retains a reference to the
|
||||
// controller itself.
|
||||
const abort = this._makeAbort(controller);
|
||||
if (signal)
|
||||
signal.addEventListener('abort', abort, { once: true });
|
||||
const timeout = setTimeout(abort, ms);
|
||||
const isReadableBody = (globalThis.ReadableStream && options.body instanceof globalThis.ReadableStream) ||
|
||||
(typeof options.body === 'object' && options.body !== null && Symbol.asyncIterator in options.body);
|
||||
const fetchOptions = {
|
||||
signal: controller.signal,
|
||||
...(isReadableBody ? { duplex: 'half' } : {}),
|
||||
method: 'GET',
|
||||
...options,
|
||||
};
|
||||
if (method) {
|
||||
// Custom methods like 'patch' need to be uppercased
|
||||
// See https://github.com/nodejs/undici/issues/2294
|
||||
fetchOptions.method = method.toUpperCase();
|
||||
}
|
||||
try {
|
||||
// use undefined this binding; fetch errors if bound to something else in browser/cloudflare
|
||||
return await this.fetch.call(undefined, url, fetchOptions);
|
||||
}
|
||||
finally {
|
||||
clearTimeout(timeout);
|
||||
}
|
||||
}
|
||||
async shouldRetry(response) {
|
||||
// Note this is not a standard header.
|
||||
const shouldRetryHeader = response.headers.get('x-should-retry');
|
||||
// If the server explicitly says whether or not to retry, obey.
|
||||
if (shouldRetryHeader === 'true')
|
||||
return true;
|
||||
if (shouldRetryHeader === 'false')
|
||||
return false;
|
||||
// Retry on request timeouts.
|
||||
if (response.status === 408)
|
||||
return true;
|
||||
// Retry on lock timeouts.
|
||||
if (response.status === 409)
|
||||
return true;
|
||||
// Retry on rate limits.
|
||||
if (response.status === 429)
|
||||
return true;
|
||||
// Retry internal errors.
|
||||
if (response.status >= 500)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
async retryRequest(options, retriesRemaining, requestLogID, responseHeaders) {
|
||||
let timeoutMillis;
|
||||
// Note the `retry-after-ms` header may not be standard, but is a good idea and we'd like proactive support for it.
|
||||
const retryAfterMillisHeader = responseHeaders?.get('retry-after-ms');
|
||||
if (retryAfterMillisHeader) {
|
||||
const timeoutMs = parseFloat(retryAfterMillisHeader);
|
||||
if (!Number.isNaN(timeoutMs)) {
|
||||
timeoutMillis = timeoutMs;
|
||||
}
|
||||
}
|
||||
// About the Retry-After header: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After
|
||||
const retryAfterHeader = responseHeaders?.get('retry-after');
|
||||
if (retryAfterHeader && !timeoutMillis) {
|
||||
const timeoutSeconds = parseFloat(retryAfterHeader);
|
||||
if (!Number.isNaN(timeoutSeconds)) {
|
||||
timeoutMillis = timeoutSeconds * 1000;
|
||||
}
|
||||
else {
|
||||
timeoutMillis = Date.parse(retryAfterHeader) - Date.now();
|
||||
}
|
||||
}
|
||||
// If the API asks us to wait a certain amount of time (and it's a reasonable amount),
|
||||
// just do what it says, but otherwise calculate a default
|
||||
if (!(timeoutMillis && 0 <= timeoutMillis && timeoutMillis < 60 * 1000)) {
|
||||
const maxRetries = options.maxRetries ?? this.maxRetries;
|
||||
timeoutMillis = this.calculateDefaultRetryTimeoutMillis(retriesRemaining, maxRetries);
|
||||
}
|
||||
await sleep(timeoutMillis);
|
||||
return this.makeRequest(options, retriesRemaining - 1, requestLogID);
|
||||
}
|
||||
calculateDefaultRetryTimeoutMillis(retriesRemaining, maxRetries) {
|
||||
const initialRetryDelay = 0.5;
|
||||
const maxRetryDelay = 8.0;
|
||||
const numRetries = maxRetries - retriesRemaining;
|
||||
// Apply exponential backoff, but not more than the max.
|
||||
const sleepSeconds = Math.min(initialRetryDelay * Math.pow(2, numRetries), maxRetryDelay);
|
||||
// Apply some jitter, take up to at most 25 percent of the retry time.
|
||||
const jitter = 1 - Math.random() * 0.25;
|
||||
return sleepSeconds * jitter * 1000;
|
||||
}
|
||||
calculateNonstreamingTimeout(maxTokens, maxNonstreamingTokens) {
|
||||
const maxTime = 60 * 60 * 1000; // 60 minutes
|
||||
const defaultTime = 60 * 10 * 1000; // 10 minutes
|
||||
const expectedTime = (maxTime * maxTokens) / 128000;
|
||||
if (expectedTime > defaultTime || (maxNonstreamingTokens != null && maxTokens > maxNonstreamingTokens)) {
|
||||
throw new Errors.AnthropicError('Streaming is required for operations that may take longer than 10 minutes. See https://github.com/anthropics/anthropic-sdk-typescript#long-requests for more details');
|
||||
}
|
||||
return defaultTime;
|
||||
}
|
||||
async buildRequest(inputOptions, { retryCount = 0 } = {}) {
|
||||
const options = { ...inputOptions };
|
||||
const { method, path, query, defaultBaseURL } = options;
|
||||
const url = this.buildURL(path, query, defaultBaseURL);
|
||||
if ('timeout' in options)
|
||||
validatePositiveInteger('timeout', options.timeout);
|
||||
options.timeout = options.timeout ?? this.timeout;
|
||||
const { bodyHeaders, body } = this.buildBody({ options });
|
||||
const reqHeaders = await this.buildHeaders({ options: inputOptions, method, bodyHeaders, retryCount });
|
||||
const req = {
|
||||
method,
|
||||
headers: reqHeaders,
|
||||
...(options.signal && { signal: options.signal }),
|
||||
...(globalThis.ReadableStream &&
|
||||
body instanceof globalThis.ReadableStream && { duplex: 'half' }),
|
||||
...(body && { body }),
|
||||
...(this.fetchOptions ?? {}),
|
||||
...(options.fetchOptions ?? {}),
|
||||
};
|
||||
return { req, url, timeout: options.timeout };
|
||||
}
|
||||
async buildHeaders({ options, method, bodyHeaders, retryCount, }) {
|
||||
let idempotencyHeaders = {};
|
||||
if (this.idempotencyHeader && method !== 'get') {
|
||||
if (!options.idempotencyKey)
|
||||
options.idempotencyKey = this.defaultIdempotencyKey();
|
||||
idempotencyHeaders[this.idempotencyHeader] = options.idempotencyKey;
|
||||
}
|
||||
const headers = buildHeaders([
|
||||
idempotencyHeaders,
|
||||
{
|
||||
Accept: 'application/json',
|
||||
'User-Agent': this.getUserAgent(),
|
||||
'X-Stainless-Retry-Count': String(retryCount),
|
||||
...(options.timeout ? { 'X-Stainless-Timeout': String(Math.trunc(options.timeout / 1000)) } : {}),
|
||||
...getPlatformHeaders(),
|
||||
...(this._options.dangerouslyAllowBrowser ?
|
||||
{ 'anthropic-dangerous-direct-browser-access': 'true' }
|
||||
: undefined),
|
||||
'anthropic-version': '2023-06-01',
|
||||
},
|
||||
await this.authHeaders(options),
|
||||
this._options.defaultHeaders,
|
||||
bodyHeaders,
|
||||
options.headers,
|
||||
]);
|
||||
this.validateHeaders(headers);
|
||||
return headers.values;
|
||||
}
|
||||
_makeAbort(controller) {
|
||||
// note: we can't just inline this method inside `fetchWithTimeout()` because then the closure
|
||||
// would capture all request options, and cause a memory leak.
|
||||
return () => controller.abort();
|
||||
}
|
||||
buildBody({ options: { body, headers: rawHeaders } }) {
|
||||
if (!body) {
|
||||
return { bodyHeaders: undefined, body: undefined };
|
||||
}
|
||||
const headers = buildHeaders([rawHeaders]);
|
||||
if (
|
||||
// Pass raw type verbatim
|
||||
ArrayBuffer.isView(body) ||
|
||||
body instanceof ArrayBuffer ||
|
||||
body instanceof DataView ||
|
||||
(typeof body === 'string' &&
|
||||
// Preserve legacy string encoding behavior for now
|
||||
headers.values.has('content-type')) ||
|
||||
// `Blob` is superset of `File`
|
||||
(globalThis.Blob && body instanceof globalThis.Blob) ||
|
||||
// `FormData` -> `multipart/form-data`
|
||||
body instanceof FormData ||
|
||||
// `URLSearchParams` -> `application/x-www-form-urlencoded`
|
||||
body instanceof URLSearchParams ||
|
||||
// Send chunked stream (each chunk has own `length`)
|
||||
(globalThis.ReadableStream && body instanceof globalThis.ReadableStream)) {
|
||||
return { bodyHeaders: undefined, body: body };
|
||||
}
|
||||
else if (typeof body === 'object' &&
|
||||
(Symbol.asyncIterator in body ||
|
||||
(Symbol.iterator in body && 'next' in body && typeof body.next === 'function'))) {
|
||||
return { bodyHeaders: undefined, body: Shims.ReadableStreamFrom(body) };
|
||||
}
|
||||
else {
|
||||
return __classPrivateFieldGet(this, _BaseAnthropic_encoder, "f").call(this, { body, headers });
|
||||
}
|
||||
}
|
||||
}
|
||||
_a = BaseAnthropic, _BaseAnthropic_encoder = new WeakMap(), _BaseAnthropic_instances = new WeakSet(), _BaseAnthropic_baseURLOverridden = function _BaseAnthropic_baseURLOverridden() {
|
||||
return this.baseURL !== 'https://api.anthropic.com';
|
||||
};
|
||||
BaseAnthropic.Anthropic = _a;
|
||||
BaseAnthropic.HUMAN_PROMPT = HUMAN_PROMPT;
|
||||
BaseAnthropic.AI_PROMPT = AI_PROMPT;
|
||||
BaseAnthropic.DEFAULT_TIMEOUT = 600000; // 10 minutes
|
||||
BaseAnthropic.AnthropicError = Errors.AnthropicError;
|
||||
BaseAnthropic.APIError = Errors.APIError;
|
||||
BaseAnthropic.APIConnectionError = Errors.APIConnectionError;
|
||||
BaseAnthropic.APIConnectionTimeoutError = Errors.APIConnectionTimeoutError;
|
||||
BaseAnthropic.APIUserAbortError = Errors.APIUserAbortError;
|
||||
BaseAnthropic.NotFoundError = Errors.NotFoundError;
|
||||
BaseAnthropic.ConflictError = Errors.ConflictError;
|
||||
BaseAnthropic.RateLimitError = Errors.RateLimitError;
|
||||
BaseAnthropic.BadRequestError = Errors.BadRequestError;
|
||||
BaseAnthropic.AuthenticationError = Errors.AuthenticationError;
|
||||
BaseAnthropic.InternalServerError = Errors.InternalServerError;
|
||||
BaseAnthropic.PermissionDeniedError = Errors.PermissionDeniedError;
|
||||
BaseAnthropic.UnprocessableEntityError = Errors.UnprocessableEntityError;
|
||||
BaseAnthropic.toFile = Uploads.toFile;
|
||||
/**
|
||||
* API Client for interfacing with the Anthropic API.
|
||||
*/
|
||||
export class Anthropic extends BaseAnthropic {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this.completions = new API.Completions(this);
|
||||
this.messages = new API.Messages(this);
|
||||
this.models = new API.Models(this);
|
||||
this.beta = new API.Beta(this);
|
||||
}
|
||||
}
|
||||
Anthropic.Completions = Completions;
|
||||
Anthropic.Messages = Messages;
|
||||
Anthropic.Models = Models;
|
||||
Anthropic.Beta = Beta;
|
||||
//# sourceMappingURL=client.mjs.map
|
||||
72
claude-code-source/node_modules/@anthropic-ai/sdk/core/api-promise.mjs
generated
vendored
72
claude-code-source/node_modules/@anthropic-ai/sdk/core/api-promise.mjs
generated
vendored
@@ -1,72 +0,0 @@
|
||||
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
||||
var _APIPromise_client;
|
||||
import { __classPrivateFieldGet, __classPrivateFieldSet } from "../internal/tslib.mjs";
|
||||
import { defaultParseResponse, addRequestID, } from "../internal/parse.mjs";
|
||||
/**
|
||||
* A subclass of `Promise` providing additional helper methods
|
||||
* for interacting with the SDK.
|
||||
*/
|
||||
export class APIPromise extends Promise {
|
||||
constructor(client, responsePromise, parseResponse = defaultParseResponse) {
|
||||
super((resolve) => {
|
||||
// this is maybe a bit weird but this has to be a no-op to not implicitly
|
||||
// parse the response body; instead .then, .catch, .finally are overridden
|
||||
// to parse the response
|
||||
resolve(null);
|
||||
});
|
||||
this.responsePromise = responsePromise;
|
||||
this.parseResponse = parseResponse;
|
||||
_APIPromise_client.set(this, void 0);
|
||||
__classPrivateFieldSet(this, _APIPromise_client, client, "f");
|
||||
}
|
||||
_thenUnwrap(transform) {
|
||||
return new APIPromise(__classPrivateFieldGet(this, _APIPromise_client, "f"), this.responsePromise, async (client, props) => addRequestID(transform(await this.parseResponse(client, props), props), props.response));
|
||||
}
|
||||
/**
|
||||
* Gets the raw `Response` instance instead of parsing the response
|
||||
* data.
|
||||
*
|
||||
* If you want to parse the response body but still get the `Response`
|
||||
* instance, you can use {@link withResponse()}.
|
||||
*
|
||||
* 👋 Getting the wrong TypeScript type for `Response`?
|
||||
* Try setting `"moduleResolution": "NodeNext"` or add `"lib": ["DOM"]`
|
||||
* to your `tsconfig.json`.
|
||||
*/
|
||||
asResponse() {
|
||||
return this.responsePromise.then((p) => p.response);
|
||||
}
|
||||
/**
|
||||
* Gets the parsed response data, the raw `Response` instance and the ID of the request,
|
||||
* returned via the `request-id` header which is useful for debugging requests and resporting
|
||||
* issues to Anthropic.
|
||||
*
|
||||
* If you just want to get the raw `Response` instance without parsing it,
|
||||
* you can use {@link asResponse()}.
|
||||
*
|
||||
* 👋 Getting the wrong TypeScript type for `Response`?
|
||||
* Try setting `"moduleResolution": "NodeNext"` or add `"lib": ["DOM"]`
|
||||
* to your `tsconfig.json`.
|
||||
*/
|
||||
async withResponse() {
|
||||
const [data, response] = await Promise.all([this.parse(), this.asResponse()]);
|
||||
return { data, response, request_id: response.headers.get('request-id') };
|
||||
}
|
||||
parse() {
|
||||
if (!this.parsedPromise) {
|
||||
this.parsedPromise = this.responsePromise.then((data) => this.parseResponse(__classPrivateFieldGet(this, _APIPromise_client, "f"), data));
|
||||
}
|
||||
return this.parsedPromise;
|
||||
}
|
||||
then(onfulfilled, onrejected) {
|
||||
return this.parse().then(onfulfilled, onrejected);
|
||||
}
|
||||
catch(onrejected) {
|
||||
return this.parse().catch(onrejected);
|
||||
}
|
||||
finally(onfinally) {
|
||||
return this.parse().finally(onfinally);
|
||||
}
|
||||
}
|
||||
_APIPromise_client = new WeakMap();
|
||||
//# sourceMappingURL=api-promise.mjs.map
|
||||
98
claude-code-source/node_modules/@anthropic-ai/sdk/core/error.mjs
generated
vendored
98
claude-code-source/node_modules/@anthropic-ai/sdk/core/error.mjs
generated
vendored
@@ -1,98 +0,0 @@
|
||||
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
||||
import { castToError } from "../internal/errors.mjs";
|
||||
export class AnthropicError extends Error {
|
||||
}
|
||||
export class APIError extends AnthropicError {
|
||||
constructor(status, error, message, headers) {
|
||||
super(`${APIError.makeMessage(status, error, message)}`);
|
||||
this.status = status;
|
||||
this.headers = headers;
|
||||
this.requestID = headers?.get('request-id');
|
||||
this.error = error;
|
||||
}
|
||||
static makeMessage(status, error, message) {
|
||||
const msg = error?.message ?
|
||||
typeof error.message === 'string' ?
|
||||
error.message
|
||||
: JSON.stringify(error.message)
|
||||
: error ? JSON.stringify(error)
|
||||
: message;
|
||||
if (status && msg) {
|
||||
return `${status} ${msg}`;
|
||||
}
|
||||
if (status) {
|
||||
return `${status} status code (no body)`;
|
||||
}
|
||||
if (msg) {
|
||||
return msg;
|
||||
}
|
||||
return '(no status code or body)';
|
||||
}
|
||||
static generate(status, errorResponse, message, headers) {
|
||||
if (!status || !headers) {
|
||||
return new APIConnectionError({ message, cause: castToError(errorResponse) });
|
||||
}
|
||||
const error = errorResponse;
|
||||
if (status === 400) {
|
||||
return new BadRequestError(status, error, message, headers);
|
||||
}
|
||||
if (status === 401) {
|
||||
return new AuthenticationError(status, error, message, headers);
|
||||
}
|
||||
if (status === 403) {
|
||||
return new PermissionDeniedError(status, error, message, headers);
|
||||
}
|
||||
if (status === 404) {
|
||||
return new NotFoundError(status, error, message, headers);
|
||||
}
|
||||
if (status === 409) {
|
||||
return new ConflictError(status, error, message, headers);
|
||||
}
|
||||
if (status === 422) {
|
||||
return new UnprocessableEntityError(status, error, message, headers);
|
||||
}
|
||||
if (status === 429) {
|
||||
return new RateLimitError(status, error, message, headers);
|
||||
}
|
||||
if (status >= 500) {
|
||||
return new InternalServerError(status, error, message, headers);
|
||||
}
|
||||
return new APIError(status, error, message, headers);
|
||||
}
|
||||
}
|
||||
export class APIUserAbortError extends APIError {
|
||||
constructor({ message } = {}) {
|
||||
super(undefined, undefined, message || 'Request was aborted.', undefined);
|
||||
}
|
||||
}
|
||||
export class APIConnectionError extends APIError {
|
||||
constructor({ message, cause }) {
|
||||
super(undefined, undefined, message || 'Connection error.', undefined);
|
||||
// in some environments the 'cause' property is already declared
|
||||
// @ts-ignore
|
||||
if (cause)
|
||||
this.cause = cause;
|
||||
}
|
||||
}
|
||||
export class APIConnectionTimeoutError extends APIConnectionError {
|
||||
constructor({ message } = {}) {
|
||||
super({ message: message ?? 'Request timed out.' });
|
||||
}
|
||||
}
|
||||
export class BadRequestError extends APIError {
|
||||
}
|
||||
export class AuthenticationError extends APIError {
|
||||
}
|
||||
export class PermissionDeniedError extends APIError {
|
||||
}
|
||||
export class NotFoundError extends APIError {
|
||||
}
|
||||
export class ConflictError extends APIError {
|
||||
}
|
||||
export class UnprocessableEntityError extends APIError {
|
||||
}
|
||||
export class RateLimitError extends APIError {
|
||||
}
|
||||
export class InternalServerError extends APIError {
|
||||
}
|
||||
//# sourceMappingURL=error.mjs.map
|
||||
177
claude-code-source/node_modules/@anthropic-ai/sdk/core/pagination.mjs
generated
vendored
177
claude-code-source/node_modules/@anthropic-ai/sdk/core/pagination.mjs
generated
vendored
@@ -1,177 +0,0 @@
|
||||
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
||||
var _AbstractPage_client;
|
||||
import { __classPrivateFieldGet, __classPrivateFieldSet } from "../internal/tslib.mjs";
|
||||
import { AnthropicError } from "./error.mjs";
|
||||
import { defaultParseResponse } from "../internal/parse.mjs";
|
||||
import { APIPromise } from "./api-promise.mjs";
|
||||
import { maybeObj } from "../internal/utils/values.mjs";
|
||||
export class AbstractPage {
|
||||
constructor(client, response, body, options) {
|
||||
_AbstractPage_client.set(this, void 0);
|
||||
__classPrivateFieldSet(this, _AbstractPage_client, client, "f");
|
||||
this.options = options;
|
||||
this.response = response;
|
||||
this.body = body;
|
||||
}
|
||||
hasNextPage() {
|
||||
const items = this.getPaginatedItems();
|
||||
if (!items.length)
|
||||
return false;
|
||||
return this.nextPageRequestOptions() != null;
|
||||
}
|
||||
async getNextPage() {
|
||||
const nextOptions = this.nextPageRequestOptions();
|
||||
if (!nextOptions) {
|
||||
throw new AnthropicError('No next page expected; please check `.hasNextPage()` before calling `.getNextPage()`.');
|
||||
}
|
||||
return await __classPrivateFieldGet(this, _AbstractPage_client, "f").requestAPIList(this.constructor, nextOptions);
|
||||
}
|
||||
async *iterPages() {
|
||||
let page = this;
|
||||
yield page;
|
||||
while (page.hasNextPage()) {
|
||||
page = await page.getNextPage();
|
||||
yield page;
|
||||
}
|
||||
}
|
||||
async *[(_AbstractPage_client = new WeakMap(), Symbol.asyncIterator)]() {
|
||||
for await (const page of this.iterPages()) {
|
||||
for (const item of page.getPaginatedItems()) {
|
||||
yield item;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* This subclass of Promise will resolve to an instantiated Page once the request completes.
|
||||
*
|
||||
* It also implements AsyncIterable to allow auto-paginating iteration on an unawaited list call, eg:
|
||||
*
|
||||
* for await (const item of client.items.list()) {
|
||||
* console.log(item)
|
||||
* }
|
||||
*/
|
||||
export class PagePromise extends APIPromise {
|
||||
constructor(client, request, Page) {
|
||||
super(client, request, async (client, props) => new Page(client, props.response, await defaultParseResponse(client, props), props.options));
|
||||
}
|
||||
/**
|
||||
* Allow auto-paginating iteration on an unawaited list call, eg:
|
||||
*
|
||||
* for await (const item of client.items.list()) {
|
||||
* console.log(item)
|
||||
* }
|
||||
*/
|
||||
async *[Symbol.asyncIterator]() {
|
||||
const page = await this;
|
||||
for await (const item of page) {
|
||||
yield item;
|
||||
}
|
||||
}
|
||||
}
|
||||
export class Page extends AbstractPage {
|
||||
constructor(client, response, body, options) {
|
||||
super(client, response, body, options);
|
||||
this.data = body.data || [];
|
||||
this.has_more = body.has_more || false;
|
||||
this.first_id = body.first_id || null;
|
||||
this.last_id = body.last_id || null;
|
||||
}
|
||||
getPaginatedItems() {
|
||||
return this.data ?? [];
|
||||
}
|
||||
hasNextPage() {
|
||||
if (this.has_more === false) {
|
||||
return false;
|
||||
}
|
||||
return super.hasNextPage();
|
||||
}
|
||||
nextPageRequestOptions() {
|
||||
if (this.options.query?.['before_id']) {
|
||||
// in reverse
|
||||
const first_id = this.first_id;
|
||||
if (!first_id) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
...this.options,
|
||||
query: {
|
||||
...maybeObj(this.options.query),
|
||||
before_id: first_id,
|
||||
},
|
||||
};
|
||||
}
|
||||
const cursor = this.last_id;
|
||||
if (!cursor) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
...this.options,
|
||||
query: {
|
||||
...maybeObj(this.options.query),
|
||||
after_id: cursor,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
export class TokenPage extends AbstractPage {
|
||||
constructor(client, response, body, options) {
|
||||
super(client, response, body, options);
|
||||
this.data = body.data || [];
|
||||
this.has_more = body.has_more || false;
|
||||
this.next_page = body.next_page || null;
|
||||
}
|
||||
getPaginatedItems() {
|
||||
return this.data ?? [];
|
||||
}
|
||||
hasNextPage() {
|
||||
if (this.has_more === false) {
|
||||
return false;
|
||||
}
|
||||
return super.hasNextPage();
|
||||
}
|
||||
nextPageRequestOptions() {
|
||||
const cursor = this.next_page;
|
||||
if (!cursor) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
...this.options,
|
||||
query: {
|
||||
...maybeObj(this.options.query),
|
||||
page_token: cursor,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
export class PageCursor extends AbstractPage {
|
||||
constructor(client, response, body, options) {
|
||||
super(client, response, body, options);
|
||||
this.data = body.data || [];
|
||||
this.has_more = body.has_more || false;
|
||||
this.next_page = body.next_page || null;
|
||||
}
|
||||
getPaginatedItems() {
|
||||
return this.data ?? [];
|
||||
}
|
||||
hasNextPage() {
|
||||
if (this.has_more === false) {
|
||||
return false;
|
||||
}
|
||||
return super.hasNextPage();
|
||||
}
|
||||
nextPageRequestOptions() {
|
||||
const cursor = this.next_page;
|
||||
if (!cursor) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
...this.options,
|
||||
query: {
|
||||
...maybeObj(this.options.query),
|
||||
page: cursor,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=pagination.mjs.map
|
||||
7
claude-code-source/node_modules/@anthropic-ai/sdk/core/resource.mjs
generated
vendored
7
claude-code-source/node_modules/@anthropic-ai/sdk/core/resource.mjs
generated
vendored
@@ -1,7 +0,0 @@
|
||||
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
||||
export class APIResource {
|
||||
constructor(client) {
|
||||
this._client = client;
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=resource.mjs.map
|
||||
283
claude-code-source/node_modules/@anthropic-ai/sdk/core/streaming.mjs
generated
vendored
283
claude-code-source/node_modules/@anthropic-ai/sdk/core/streaming.mjs
generated
vendored
@@ -1,283 +0,0 @@
|
||||
var _Stream_client;
|
||||
import { __classPrivateFieldGet, __classPrivateFieldSet } from "../internal/tslib.mjs";
|
||||
import { AnthropicError } from "./error.mjs";
|
||||
import { makeReadableStream } from "../internal/shims.mjs";
|
||||
import { findDoubleNewlineIndex, LineDecoder } from "../internal/decoders/line.mjs";
|
||||
import { ReadableStreamToAsyncIterable } from "../internal/shims.mjs";
|
||||
import { isAbortError } from "../internal/errors.mjs";
|
||||
import { safeJSON } from "../internal/utils/values.mjs";
|
||||
import { encodeUTF8 } from "../internal/utils/bytes.mjs";
|
||||
import { loggerFor } from "../internal/utils/log.mjs";
|
||||
import { APIError } from "./error.mjs";
|
||||
export class Stream {
|
||||
constructor(iterator, controller, client) {
|
||||
this.iterator = iterator;
|
||||
_Stream_client.set(this, void 0);
|
||||
this.controller = controller;
|
||||
__classPrivateFieldSet(this, _Stream_client, client, "f");
|
||||
}
|
||||
static fromSSEResponse(response, controller, client) {
|
||||
let consumed = false;
|
||||
const logger = client ? loggerFor(client) : console;
|
||||
async function* iterator() {
|
||||
if (consumed) {
|
||||
throw new AnthropicError('Cannot iterate over a consumed stream, use `.tee()` to split the stream.');
|
||||
}
|
||||
consumed = true;
|
||||
let done = false;
|
||||
try {
|
||||
for await (const sse of _iterSSEMessages(response, controller)) {
|
||||
if (sse.event === 'completion') {
|
||||
try {
|
||||
yield JSON.parse(sse.data);
|
||||
}
|
||||
catch (e) {
|
||||
logger.error(`Could not parse message into JSON:`, sse.data);
|
||||
logger.error(`From chunk:`, sse.raw);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
if (sse.event === 'message_start' ||
|
||||
sse.event === 'message_delta' ||
|
||||
sse.event === 'message_stop' ||
|
||||
sse.event === 'content_block_start' ||
|
||||
sse.event === 'content_block_delta' ||
|
||||
sse.event === 'content_block_stop') {
|
||||
try {
|
||||
yield JSON.parse(sse.data);
|
||||
}
|
||||
catch (e) {
|
||||
logger.error(`Could not parse message into JSON:`, sse.data);
|
||||
logger.error(`From chunk:`, sse.raw);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
if (sse.event === 'ping') {
|
||||
continue;
|
||||
}
|
||||
if (sse.event === 'error') {
|
||||
throw new APIError(undefined, safeJSON(sse.data) ?? sse.data, undefined, response.headers);
|
||||
}
|
||||
}
|
||||
done = true;
|
||||
}
|
||||
catch (e) {
|
||||
// If the user calls `stream.controller.abort()`, we should exit without throwing.
|
||||
if (isAbortError(e))
|
||||
return;
|
||||
throw e;
|
||||
}
|
||||
finally {
|
||||
// If the user `break`s, abort the ongoing request.
|
||||
if (!done)
|
||||
controller.abort();
|
||||
}
|
||||
}
|
||||
return new Stream(iterator, controller, client);
|
||||
}
|
||||
/**
|
||||
* Generates a Stream from a newline-separated ReadableStream
|
||||
* where each item is a JSON value.
|
||||
*/
|
||||
static fromReadableStream(readableStream, controller, client) {
|
||||
let consumed = false;
|
||||
async function* iterLines() {
|
||||
const lineDecoder = new LineDecoder();
|
||||
const iter = ReadableStreamToAsyncIterable(readableStream);
|
||||
for await (const chunk of iter) {
|
||||
for (const line of lineDecoder.decode(chunk)) {
|
||||
yield line;
|
||||
}
|
||||
}
|
||||
for (const line of lineDecoder.flush()) {
|
||||
yield line;
|
||||
}
|
||||
}
|
||||
async function* iterator() {
|
||||
if (consumed) {
|
||||
throw new AnthropicError('Cannot iterate over a consumed stream, use `.tee()` to split the stream.');
|
||||
}
|
||||
consumed = true;
|
||||
let done = false;
|
||||
try {
|
||||
for await (const line of iterLines()) {
|
||||
if (done)
|
||||
continue;
|
||||
if (line)
|
||||
yield JSON.parse(line);
|
||||
}
|
||||
done = true;
|
||||
}
|
||||
catch (e) {
|
||||
// If the user calls `stream.controller.abort()`, we should exit without throwing.
|
||||
if (isAbortError(e))
|
||||
return;
|
||||
throw e;
|
||||
}
|
||||
finally {
|
||||
// If the user `break`s, abort the ongoing request.
|
||||
if (!done)
|
||||
controller.abort();
|
||||
}
|
||||
}
|
||||
return new Stream(iterator, controller, client);
|
||||
}
|
||||
[(_Stream_client = new WeakMap(), Symbol.asyncIterator)]() {
|
||||
return this.iterator();
|
||||
}
|
||||
/**
|
||||
* Splits the stream into two streams which can be
|
||||
* independently read from at different speeds.
|
||||
*/
|
||||
tee() {
|
||||
const left = [];
|
||||
const right = [];
|
||||
const iterator = this.iterator();
|
||||
const teeIterator = (queue) => {
|
||||
return {
|
||||
next: () => {
|
||||
if (queue.length === 0) {
|
||||
const result = iterator.next();
|
||||
left.push(result);
|
||||
right.push(result);
|
||||
}
|
||||
return queue.shift();
|
||||
},
|
||||
};
|
||||
};
|
||||
return [
|
||||
new Stream(() => teeIterator(left), this.controller, __classPrivateFieldGet(this, _Stream_client, "f")),
|
||||
new Stream(() => teeIterator(right), this.controller, __classPrivateFieldGet(this, _Stream_client, "f")),
|
||||
];
|
||||
}
|
||||
/**
|
||||
* Converts this stream to a newline-separated ReadableStream of
|
||||
* JSON stringified values in the stream
|
||||
* which can be turned back into a Stream with `Stream.fromReadableStream()`.
|
||||
*/
|
||||
toReadableStream() {
|
||||
const self = this;
|
||||
let iter;
|
||||
return makeReadableStream({
|
||||
async start() {
|
||||
iter = self[Symbol.asyncIterator]();
|
||||
},
|
||||
async pull(ctrl) {
|
||||
try {
|
||||
const { value, done } = await iter.next();
|
||||
if (done)
|
||||
return ctrl.close();
|
||||
const bytes = encodeUTF8(JSON.stringify(value) + '\n');
|
||||
ctrl.enqueue(bytes);
|
||||
}
|
||||
catch (err) {
|
||||
ctrl.error(err);
|
||||
}
|
||||
},
|
||||
async cancel() {
|
||||
await iter.return?.();
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
export async function* _iterSSEMessages(response, controller) {
|
||||
if (!response.body) {
|
||||
controller.abort();
|
||||
if (typeof globalThis.navigator !== 'undefined' &&
|
||||
globalThis.navigator.product === 'ReactNative') {
|
||||
throw new AnthropicError(`The default react-native fetch implementation does not support streaming. Please use expo/fetch: https://docs.expo.dev/versions/latest/sdk/expo/#expofetch-api`);
|
||||
}
|
||||
throw new AnthropicError(`Attempted to iterate over a response with no body`);
|
||||
}
|
||||
const sseDecoder = new SSEDecoder();
|
||||
const lineDecoder = new LineDecoder();
|
||||
const iter = ReadableStreamToAsyncIterable(response.body);
|
||||
for await (const sseChunk of iterSSEChunks(iter)) {
|
||||
for (const line of lineDecoder.decode(sseChunk)) {
|
||||
const sse = sseDecoder.decode(line);
|
||||
if (sse)
|
||||
yield sse;
|
||||
}
|
||||
}
|
||||
for (const line of lineDecoder.flush()) {
|
||||
const sse = sseDecoder.decode(line);
|
||||
if (sse)
|
||||
yield sse;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Given an async iterable iterator, iterates over it and yields full
|
||||
* SSE chunks, i.e. yields when a double new-line is encountered.
|
||||
*/
|
||||
async function* iterSSEChunks(iterator) {
|
||||
let data = new Uint8Array();
|
||||
for await (const chunk of iterator) {
|
||||
if (chunk == null) {
|
||||
continue;
|
||||
}
|
||||
const binaryChunk = chunk instanceof ArrayBuffer ? new Uint8Array(chunk)
|
||||
: typeof chunk === 'string' ? encodeUTF8(chunk)
|
||||
: chunk;
|
||||
let newData = new Uint8Array(data.length + binaryChunk.length);
|
||||
newData.set(data);
|
||||
newData.set(binaryChunk, data.length);
|
||||
data = newData;
|
||||
let patternIndex;
|
||||
while ((patternIndex = findDoubleNewlineIndex(data)) !== -1) {
|
||||
yield data.slice(0, patternIndex);
|
||||
data = data.slice(patternIndex);
|
||||
}
|
||||
}
|
||||
if (data.length > 0) {
|
||||
yield data;
|
||||
}
|
||||
}
|
||||
class SSEDecoder {
|
||||
constructor() {
|
||||
this.event = null;
|
||||
this.data = [];
|
||||
this.chunks = [];
|
||||
}
|
||||
decode(line) {
|
||||
if (line.endsWith('\r')) {
|
||||
line = line.substring(0, line.length - 1);
|
||||
}
|
||||
if (!line) {
|
||||
// empty line and we didn't previously encounter any messages
|
||||
if (!this.event && !this.data.length)
|
||||
return null;
|
||||
const sse = {
|
||||
event: this.event,
|
||||
data: this.data.join('\n'),
|
||||
raw: this.chunks,
|
||||
};
|
||||
this.event = null;
|
||||
this.data = [];
|
||||
this.chunks = [];
|
||||
return sse;
|
||||
}
|
||||
this.chunks.push(line);
|
||||
if (line.startsWith(':')) {
|
||||
return null;
|
||||
}
|
||||
let [fieldname, _, value] = partition(line, ':');
|
||||
if (value.startsWith(' ')) {
|
||||
value = value.substring(1);
|
||||
}
|
||||
if (fieldname === 'event') {
|
||||
this.event = value;
|
||||
}
|
||||
else if (fieldname === 'data') {
|
||||
this.data.push(value);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
function partition(str, delimiter) {
|
||||
const index = str.indexOf(delimiter);
|
||||
if (index !== -1) {
|
||||
return [str.substring(0, index), delimiter, str.substring(index + delimiter.length)];
|
||||
}
|
||||
return [str, '', ''];
|
||||
}
|
||||
//# sourceMappingURL=streaming.mjs.map
|
||||
2
claude-code-source/node_modules/@anthropic-ai/sdk/core/uploads.mjs
generated
vendored
2
claude-code-source/node_modules/@anthropic-ai/sdk/core/uploads.mjs
generated
vendored
@@ -1,2 +0,0 @@
|
||||
export { toFile } from "../internal/to-file.mjs";
|
||||
//# sourceMappingURL=uploads.mjs.map
|
||||
2
claude-code-source/node_modules/@anthropic-ai/sdk/error.mjs
generated
vendored
2
claude-code-source/node_modules/@anthropic-ai/sdk/error.mjs
generated
vendored
@@ -1,2 +0,0 @@
|
||||
export * from "./core/error.mjs";
|
||||
//# sourceMappingURL=error.mjs.map
|
||||
8
claude-code-source/node_modules/@anthropic-ai/sdk/index.mjs
generated
vendored
8
claude-code-source/node_modules/@anthropic-ai/sdk/index.mjs
generated
vendored
@@ -1,8 +0,0 @@
|
||||
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
||||
export { Anthropic as default } from "./client.mjs";
|
||||
export { toFile } from "./core/uploads.mjs";
|
||||
export { APIPromise } from "./core/api-promise.mjs";
|
||||
export { BaseAnthropic, Anthropic, HUMAN_PROMPT, AI_PROMPT } from "./client.mjs";
|
||||
export { PagePromise } from "./core/pagination.mjs";
|
||||
export { AnthropicError, APIError, APIConnectionError, APIConnectionTimeoutError, APIUserAbortError, NotFoundError, ConflictError, RateLimitError, BadRequestError, AuthenticationError, InternalServerError, PermissionDeniedError, UnprocessableEntityError, } from "./core/error.mjs";
|
||||
//# sourceMappingURL=index.mjs.map
|
||||
15
claude-code-source/node_modules/@anthropic-ai/sdk/internal/constants.mjs
generated
vendored
15
claude-code-source/node_modules/@anthropic-ai/sdk/internal/constants.mjs
generated
vendored
@@ -1,15 +0,0 @@
|
||||
// File containing shared constants
|
||||
/**
|
||||
* Model-specific timeout constraints for non-streaming requests
|
||||
*/
|
||||
export const MODEL_NONSTREAMING_TOKENS = {
|
||||
'claude-opus-4-20250514': 8192,
|
||||
'claude-opus-4-0': 8192,
|
||||
'claude-4-opus-20250514': 8192,
|
||||
'anthropic.claude-opus-4-20250514-v1:0': 8192,
|
||||
'claude-opus-4@20250514': 8192,
|
||||
'claude-opus-4-1-20250805': 8192,
|
||||
'anthropic.claude-opus-4-1-20250805-v1:0': 8192,
|
||||
'claude-opus-4-1@20250805': 8192,
|
||||
};
|
||||
//# sourceMappingURL=constants.mjs.map
|
||||
35
claude-code-source/node_modules/@anthropic-ai/sdk/internal/decoders/jsonl.mjs
generated
vendored
35
claude-code-source/node_modules/@anthropic-ai/sdk/internal/decoders/jsonl.mjs
generated
vendored
@@ -1,35 +0,0 @@
|
||||
import { AnthropicError } from "../../core/error.mjs";
|
||||
import { ReadableStreamToAsyncIterable } from "../shims.mjs";
|
||||
import { LineDecoder } from "./line.mjs";
|
||||
export class JSONLDecoder {
|
||||
constructor(iterator, controller) {
|
||||
this.iterator = iterator;
|
||||
this.controller = controller;
|
||||
}
|
||||
async *decoder() {
|
||||
const lineDecoder = new LineDecoder();
|
||||
for await (const chunk of this.iterator) {
|
||||
for (const line of lineDecoder.decode(chunk)) {
|
||||
yield JSON.parse(line);
|
||||
}
|
||||
}
|
||||
for (const line of lineDecoder.flush()) {
|
||||
yield JSON.parse(line);
|
||||
}
|
||||
}
|
||||
[Symbol.asyncIterator]() {
|
||||
return this.decoder();
|
||||
}
|
||||
static fromResponse(response, controller) {
|
||||
if (!response.body) {
|
||||
controller.abort();
|
||||
if (typeof globalThis.navigator !== 'undefined' &&
|
||||
globalThis.navigator.product === 'ReactNative') {
|
||||
throw new AnthropicError(`The default react-native fetch implementation does not support streaming. Please use expo/fetch: https://docs.expo.dev/versions/latest/sdk/expo/#expofetch-api`);
|
||||
}
|
||||
throw new AnthropicError(`Attempted to iterate over a response with no body`);
|
||||
}
|
||||
return new JSONLDecoder(ReadableStreamToAsyncIterable(response.body), controller);
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=jsonl.mjs.map
|
||||
108
claude-code-source/node_modules/@anthropic-ai/sdk/internal/decoders/line.mjs
generated
vendored
108
claude-code-source/node_modules/@anthropic-ai/sdk/internal/decoders/line.mjs
generated
vendored
@@ -1,108 +0,0 @@
|
||||
var _LineDecoder_buffer, _LineDecoder_carriageReturnIndex;
|
||||
import { __classPrivateFieldGet, __classPrivateFieldSet } from "../tslib.mjs";
|
||||
import { concatBytes, decodeUTF8, encodeUTF8 } from "../utils/bytes.mjs";
|
||||
/**
|
||||
* A re-implementation of httpx's `LineDecoder` in Python that handles incrementally
|
||||
* reading lines from text.
|
||||
*
|
||||
* https://github.com/encode/httpx/blob/920333ea98118e9cf617f246905d7b202510941c/httpx/_decoders.py#L258
|
||||
*/
|
||||
export class LineDecoder {
|
||||
constructor() {
|
||||
_LineDecoder_buffer.set(this, void 0);
|
||||
_LineDecoder_carriageReturnIndex.set(this, void 0);
|
||||
__classPrivateFieldSet(this, _LineDecoder_buffer, new Uint8Array(), "f");
|
||||
__classPrivateFieldSet(this, _LineDecoder_carriageReturnIndex, null, "f");
|
||||
}
|
||||
decode(chunk) {
|
||||
if (chunk == null) {
|
||||
return [];
|
||||
}
|
||||
const binaryChunk = chunk instanceof ArrayBuffer ? new Uint8Array(chunk)
|
||||
: typeof chunk === 'string' ? encodeUTF8(chunk)
|
||||
: chunk;
|
||||
__classPrivateFieldSet(this, _LineDecoder_buffer, concatBytes([__classPrivateFieldGet(this, _LineDecoder_buffer, "f"), binaryChunk]), "f");
|
||||
const lines = [];
|
||||
let patternIndex;
|
||||
while ((patternIndex = findNewlineIndex(__classPrivateFieldGet(this, _LineDecoder_buffer, "f"), __classPrivateFieldGet(this, _LineDecoder_carriageReturnIndex, "f"))) != null) {
|
||||
if (patternIndex.carriage && __classPrivateFieldGet(this, _LineDecoder_carriageReturnIndex, "f") == null) {
|
||||
// skip until we either get a corresponding `\n`, a new `\r` or nothing
|
||||
__classPrivateFieldSet(this, _LineDecoder_carriageReturnIndex, patternIndex.index, "f");
|
||||
continue;
|
||||
}
|
||||
// we got double \r or \rtext\n
|
||||
if (__classPrivateFieldGet(this, _LineDecoder_carriageReturnIndex, "f") != null &&
|
||||
(patternIndex.index !== __classPrivateFieldGet(this, _LineDecoder_carriageReturnIndex, "f") + 1 || patternIndex.carriage)) {
|
||||
lines.push(decodeUTF8(__classPrivateFieldGet(this, _LineDecoder_buffer, "f").subarray(0, __classPrivateFieldGet(this, _LineDecoder_carriageReturnIndex, "f") - 1)));
|
||||
__classPrivateFieldSet(this, _LineDecoder_buffer, __classPrivateFieldGet(this, _LineDecoder_buffer, "f").subarray(__classPrivateFieldGet(this, _LineDecoder_carriageReturnIndex, "f")), "f");
|
||||
__classPrivateFieldSet(this, _LineDecoder_carriageReturnIndex, null, "f");
|
||||
continue;
|
||||
}
|
||||
const endIndex = __classPrivateFieldGet(this, _LineDecoder_carriageReturnIndex, "f") !== null ? patternIndex.preceding - 1 : patternIndex.preceding;
|
||||
const line = decodeUTF8(__classPrivateFieldGet(this, _LineDecoder_buffer, "f").subarray(0, endIndex));
|
||||
lines.push(line);
|
||||
__classPrivateFieldSet(this, _LineDecoder_buffer, __classPrivateFieldGet(this, _LineDecoder_buffer, "f").subarray(patternIndex.index), "f");
|
||||
__classPrivateFieldSet(this, _LineDecoder_carriageReturnIndex, null, "f");
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
flush() {
|
||||
if (!__classPrivateFieldGet(this, _LineDecoder_buffer, "f").length) {
|
||||
return [];
|
||||
}
|
||||
return this.decode('\n');
|
||||
}
|
||||
}
|
||||
_LineDecoder_buffer = new WeakMap(), _LineDecoder_carriageReturnIndex = new WeakMap();
|
||||
// prettier-ignore
|
||||
LineDecoder.NEWLINE_CHARS = new Set(['\n', '\r']);
|
||||
LineDecoder.NEWLINE_REGEXP = /\r\n|[\n\r]/g;
|
||||
/**
|
||||
* This function searches the buffer for the end patterns, (\r or \n)
|
||||
* and returns an object with the index preceding the matched newline and the
|
||||
* index after the newline char. `null` is returned if no new line is found.
|
||||
*
|
||||
* ```ts
|
||||
* findNewLineIndex('abc\ndef') -> { preceding: 2, index: 3 }
|
||||
* ```
|
||||
*/
|
||||
function findNewlineIndex(buffer, startIndex) {
|
||||
const newline = 0x0a; // \n
|
||||
const carriage = 0x0d; // \r
|
||||
for (let i = startIndex ?? 0; i < buffer.length; i++) {
|
||||
if (buffer[i] === newline) {
|
||||
return { preceding: i, index: i + 1, carriage: false };
|
||||
}
|
||||
if (buffer[i] === carriage) {
|
||||
return { preceding: i, index: i + 1, carriage: true };
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
export function findDoubleNewlineIndex(buffer) {
|
||||
// This function searches the buffer for the end patterns (\r\r, \n\n, \r\n\r\n)
|
||||
// and returns the index right after the first occurrence of any pattern,
|
||||
// or -1 if none of the patterns are found.
|
||||
const newline = 0x0a; // \n
|
||||
const carriage = 0x0d; // \r
|
||||
for (let i = 0; i < buffer.length - 1; i++) {
|
||||
if (buffer[i] === newline && buffer[i + 1] === newline) {
|
||||
// \n\n
|
||||
return i + 2;
|
||||
}
|
||||
if (buffer[i] === carriage && buffer[i + 1] === carriage) {
|
||||
// \r\r
|
||||
return i + 2;
|
||||
}
|
||||
if (buffer[i] === carriage &&
|
||||
buffer[i + 1] === newline &&
|
||||
i + 3 < buffer.length &&
|
||||
buffer[i + 2] === carriage &&
|
||||
buffer[i + 3] === newline) {
|
||||
// \r\n\r\n
|
||||
return i + 4;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
//# sourceMappingURL=line.mjs.map
|
||||
157
claude-code-source/node_modules/@anthropic-ai/sdk/internal/detect-platform.mjs
generated
vendored
157
claude-code-source/node_modules/@anthropic-ai/sdk/internal/detect-platform.mjs
generated
vendored
@@ -1,157 +0,0 @@
|
||||
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
||||
import { VERSION } from "../version.mjs";
|
||||
export const isRunningInBrowser = () => {
|
||||
return (
|
||||
// @ts-ignore
|
||||
typeof window !== 'undefined' &&
|
||||
// @ts-ignore
|
||||
typeof window.document !== 'undefined' &&
|
||||
// @ts-ignore
|
||||
typeof navigator !== 'undefined');
|
||||
};
|
||||
/**
|
||||
* Note this does not detect 'browser'; for that, use getBrowserInfo().
|
||||
*/
|
||||
function getDetectedPlatform() {
|
||||
if (typeof Deno !== 'undefined' && Deno.build != null) {
|
||||
return 'deno';
|
||||
}
|
||||
if (typeof EdgeRuntime !== 'undefined') {
|
||||
return 'edge';
|
||||
}
|
||||
if (Object.prototype.toString.call(typeof globalThis.process !== 'undefined' ? globalThis.process : 0) === '[object process]') {
|
||||
return 'node';
|
||||
}
|
||||
return 'unknown';
|
||||
}
|
||||
const getPlatformProperties = () => {
|
||||
const detectedPlatform = getDetectedPlatform();
|
||||
if (detectedPlatform === 'deno') {
|
||||
return {
|
||||
'X-Stainless-Lang': 'js',
|
||||
'X-Stainless-Package-Version': VERSION,
|
||||
'X-Stainless-OS': normalizePlatform(Deno.build.os),
|
||||
'X-Stainless-Arch': normalizeArch(Deno.build.arch),
|
||||
'X-Stainless-Runtime': 'deno',
|
||||
'X-Stainless-Runtime-Version': typeof Deno.version === 'string' ? Deno.version : Deno.version?.deno ?? 'unknown',
|
||||
};
|
||||
}
|
||||
if (typeof EdgeRuntime !== 'undefined') {
|
||||
return {
|
||||
'X-Stainless-Lang': 'js',
|
||||
'X-Stainless-Package-Version': VERSION,
|
||||
'X-Stainless-OS': 'Unknown',
|
||||
'X-Stainless-Arch': `other:${EdgeRuntime}`,
|
||||
'X-Stainless-Runtime': 'edge',
|
||||
'X-Stainless-Runtime-Version': globalThis.process.version,
|
||||
};
|
||||
}
|
||||
// Check if Node.js
|
||||
if (detectedPlatform === 'node') {
|
||||
return {
|
||||
'X-Stainless-Lang': 'js',
|
||||
'X-Stainless-Package-Version': VERSION,
|
||||
'X-Stainless-OS': normalizePlatform(globalThis.process.platform ?? 'unknown'),
|
||||
'X-Stainless-Arch': normalizeArch(globalThis.process.arch ?? 'unknown'),
|
||||
'X-Stainless-Runtime': 'node',
|
||||
'X-Stainless-Runtime-Version': globalThis.process.version ?? 'unknown',
|
||||
};
|
||||
}
|
||||
const browserInfo = getBrowserInfo();
|
||||
if (browserInfo) {
|
||||
return {
|
||||
'X-Stainless-Lang': 'js',
|
||||
'X-Stainless-Package-Version': VERSION,
|
||||
'X-Stainless-OS': 'Unknown',
|
||||
'X-Stainless-Arch': 'unknown',
|
||||
'X-Stainless-Runtime': `browser:${browserInfo.browser}`,
|
||||
'X-Stainless-Runtime-Version': browserInfo.version,
|
||||
};
|
||||
}
|
||||
// TODO add support for Cloudflare workers, etc.
|
||||
return {
|
||||
'X-Stainless-Lang': 'js',
|
||||
'X-Stainless-Package-Version': VERSION,
|
||||
'X-Stainless-OS': 'Unknown',
|
||||
'X-Stainless-Arch': 'unknown',
|
||||
'X-Stainless-Runtime': 'unknown',
|
||||
'X-Stainless-Runtime-Version': 'unknown',
|
||||
};
|
||||
};
|
||||
// Note: modified from https://github.com/JS-DevTools/host-environment/blob/b1ab79ecde37db5d6e163c050e54fe7d287d7c92/src/isomorphic.browser.ts
|
||||
function getBrowserInfo() {
|
||||
if (typeof navigator === 'undefined' || !navigator) {
|
||||
return null;
|
||||
}
|
||||
// NOTE: The order matters here!
|
||||
const browserPatterns = [
|
||||
{ key: 'edge', pattern: /Edge(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ },
|
||||
{ key: 'ie', pattern: /MSIE(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ },
|
||||
{ key: 'ie', pattern: /Trident(?:.*rv\:(\d+)\.(\d+)(?:\.(\d+))?)?/ },
|
||||
{ key: 'chrome', pattern: /Chrome(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ },
|
||||
{ key: 'firefox', pattern: /Firefox(?:\W+(\d+)\.(\d+)(?:\.(\d+))?)?/ },
|
||||
{ key: 'safari', pattern: /(?:Version\W+(\d+)\.(\d+)(?:\.(\d+))?)?(?:\W+Mobile\S*)?\W+Safari/ },
|
||||
];
|
||||
// Find the FIRST matching browser
|
||||
for (const { key, pattern } of browserPatterns) {
|
||||
const match = pattern.exec(navigator.userAgent);
|
||||
if (match) {
|
||||
const major = match[1] || 0;
|
||||
const minor = match[2] || 0;
|
||||
const patch = match[3] || 0;
|
||||
return { browser: key, version: `${major}.${minor}.${patch}` };
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
const normalizeArch = (arch) => {
|
||||
// Node docs:
|
||||
// - https://nodejs.org/api/process.html#processarch
|
||||
// Deno docs:
|
||||
// - https://doc.deno.land/deno/stable/~/Deno.build
|
||||
if (arch === 'x32')
|
||||
return 'x32';
|
||||
if (arch === 'x86_64' || arch === 'x64')
|
||||
return 'x64';
|
||||
if (arch === 'arm')
|
||||
return 'arm';
|
||||
if (arch === 'aarch64' || arch === 'arm64')
|
||||
return 'arm64';
|
||||
if (arch)
|
||||
return `other:${arch}`;
|
||||
return 'unknown';
|
||||
};
|
||||
const normalizePlatform = (platform) => {
|
||||
// Node platforms:
|
||||
// - https://nodejs.org/api/process.html#processplatform
|
||||
// Deno platforms:
|
||||
// - https://doc.deno.land/deno/stable/~/Deno.build
|
||||
// - https://github.com/denoland/deno/issues/14799
|
||||
platform = platform.toLowerCase();
|
||||
// NOTE: this iOS check is untested and may not work
|
||||
// Node does not work natively on IOS, there is a fork at
|
||||
// https://github.com/nodejs-mobile/nodejs-mobile
|
||||
// however it is unknown at the time of writing how to detect if it is running
|
||||
if (platform.includes('ios'))
|
||||
return 'iOS';
|
||||
if (platform === 'android')
|
||||
return 'Android';
|
||||
if (platform === 'darwin')
|
||||
return 'MacOS';
|
||||
if (platform === 'win32')
|
||||
return 'Windows';
|
||||
if (platform === 'freebsd')
|
||||
return 'FreeBSD';
|
||||
if (platform === 'openbsd')
|
||||
return 'OpenBSD';
|
||||
if (platform === 'linux')
|
||||
return 'Linux';
|
||||
if (platform)
|
||||
return `Other:${platform}`;
|
||||
return 'Unknown';
|
||||
};
|
||||
let _platformHeaders;
|
||||
export const getPlatformHeaders = () => {
|
||||
return (_platformHeaders ?? (_platformHeaders = getPlatformProperties()));
|
||||
};
|
||||
//# sourceMappingURL=detect-platform.mjs.map
|
||||
36
claude-code-source/node_modules/@anthropic-ai/sdk/internal/errors.mjs
generated
vendored
36
claude-code-source/node_modules/@anthropic-ai/sdk/internal/errors.mjs
generated
vendored
@@ -1,36 +0,0 @@
|
||||
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
||||
export function isAbortError(err) {
|
||||
return (typeof err === 'object' &&
|
||||
err !== null &&
|
||||
// Spec-compliant fetch implementations
|
||||
(('name' in err && err.name === 'AbortError') ||
|
||||
// Expo fetch
|
||||
('message' in err && String(err.message).includes('FetchRequestCanceledException'))));
|
||||
}
|
||||
export const castToError = (err) => {
|
||||
if (err instanceof Error)
|
||||
return err;
|
||||
if (typeof err === 'object' && err !== null) {
|
||||
try {
|
||||
if (Object.prototype.toString.call(err) === '[object Error]') {
|
||||
// @ts-ignore - not all envs have native support for cause yet
|
||||
const error = new Error(err.message, err.cause ? { cause: err.cause } : {});
|
||||
if (err.stack)
|
||||
error.stack = err.stack;
|
||||
// @ts-ignore - not all envs have native support for cause yet
|
||||
if (err.cause && !error.cause)
|
||||
error.cause = err.cause;
|
||||
if (err.name)
|
||||
error.name = err.name;
|
||||
return error;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
try {
|
||||
return new Error(JSON.stringify(err));
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
return new Error(err);
|
||||
};
|
||||
//# sourceMappingURL=errors.mjs.map
|
||||
74
claude-code-source/node_modules/@anthropic-ai/sdk/internal/headers.mjs
generated
vendored
74
claude-code-source/node_modules/@anthropic-ai/sdk/internal/headers.mjs
generated
vendored
@@ -1,74 +0,0 @@
|
||||
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
||||
import { isReadonlyArray } from "./utils/values.mjs";
|
||||
const brand_privateNullableHeaders = Symbol.for('brand.privateNullableHeaders');
|
||||
function* iterateHeaders(headers) {
|
||||
if (!headers)
|
||||
return;
|
||||
if (brand_privateNullableHeaders in headers) {
|
||||
const { values, nulls } = headers;
|
||||
yield* values.entries();
|
||||
for (const name of nulls) {
|
||||
yield [name, null];
|
||||
}
|
||||
return;
|
||||
}
|
||||
let shouldClear = false;
|
||||
let iter;
|
||||
if (headers instanceof Headers) {
|
||||
iter = headers.entries();
|
||||
}
|
||||
else if (isReadonlyArray(headers)) {
|
||||
iter = headers;
|
||||
}
|
||||
else {
|
||||
shouldClear = true;
|
||||
iter = Object.entries(headers ?? {});
|
||||
}
|
||||
for (let row of iter) {
|
||||
const name = row[0];
|
||||
if (typeof name !== 'string')
|
||||
throw new TypeError('expected header name to be a string');
|
||||
const values = isReadonlyArray(row[1]) ? row[1] : [row[1]];
|
||||
let didClear = false;
|
||||
for (const value of values) {
|
||||
if (value === undefined)
|
||||
continue;
|
||||
// Objects keys always overwrite older headers, they never append.
|
||||
// Yield a null to clear the header before adding the new values.
|
||||
if (shouldClear && !didClear) {
|
||||
didClear = true;
|
||||
yield [name, null];
|
||||
}
|
||||
yield [name, value];
|
||||
}
|
||||
}
|
||||
}
|
||||
export const buildHeaders = (newHeaders) => {
|
||||
const targetHeaders = new Headers();
|
||||
const nullHeaders = new Set();
|
||||
for (const headers of newHeaders) {
|
||||
const seenHeaders = new Set();
|
||||
for (const [name, value] of iterateHeaders(headers)) {
|
||||
const lowerName = name.toLowerCase();
|
||||
if (!seenHeaders.has(lowerName)) {
|
||||
targetHeaders.delete(name);
|
||||
seenHeaders.add(lowerName);
|
||||
}
|
||||
if (value === null) {
|
||||
targetHeaders.delete(name);
|
||||
nullHeaders.add(lowerName);
|
||||
}
|
||||
else {
|
||||
targetHeaders.append(name, value);
|
||||
nullHeaders.delete(lowerName);
|
||||
}
|
||||
}
|
||||
}
|
||||
return { [brand_privateNullableHeaders]: true, values: targetHeaders, nulls: nullHeaders };
|
||||
};
|
||||
export const isEmptyHeaders = (headers) => {
|
||||
for (const _ of iterateHeaders(headers))
|
||||
return false;
|
||||
return true;
|
||||
};
|
||||
//# sourceMappingURL=headers.mjs.map
|
||||
56
claude-code-source/node_modules/@anthropic-ai/sdk/internal/parse.mjs
generated
vendored
56
claude-code-source/node_modules/@anthropic-ai/sdk/internal/parse.mjs
generated
vendored
@@ -1,56 +0,0 @@
|
||||
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
||||
import { Stream } from "../core/streaming.mjs";
|
||||
import { formatRequestDetails, loggerFor } from "./utils/log.mjs";
|
||||
export async function defaultParseResponse(client, props) {
|
||||
const { response, requestLogID, retryOfRequestLogID, startTime } = props;
|
||||
const body = await (async () => {
|
||||
if (props.options.stream) {
|
||||
loggerFor(client).debug('response', response.status, response.url, response.headers, response.body);
|
||||
// Note: there is an invariant here that isn't represented in the type system
|
||||
// that if you set `stream: true` the response type must also be `Stream<T>`
|
||||
if (props.options.__streamClass) {
|
||||
return props.options.__streamClass.fromSSEResponse(response, props.controller);
|
||||
}
|
||||
return Stream.fromSSEResponse(response, props.controller);
|
||||
}
|
||||
// fetch refuses to read the body when the status code is 204.
|
||||
if (response.status === 204) {
|
||||
return null;
|
||||
}
|
||||
if (props.options.__binaryResponse) {
|
||||
return response;
|
||||
}
|
||||
const contentType = response.headers.get('content-type');
|
||||
const mediaType = contentType?.split(';')[0]?.trim();
|
||||
const isJSON = mediaType?.includes('application/json') || mediaType?.endsWith('+json');
|
||||
if (isJSON) {
|
||||
const contentLength = response.headers.get('content-length');
|
||||
if (contentLength === '0') {
|
||||
// if there is no content we can't do anything
|
||||
return undefined;
|
||||
}
|
||||
const json = await response.json();
|
||||
return addRequestID(json, response);
|
||||
}
|
||||
const text = await response.text();
|
||||
return text;
|
||||
})();
|
||||
loggerFor(client).debug(`[${requestLogID}] response parsed`, formatRequestDetails({
|
||||
retryOfRequestLogID,
|
||||
url: response.url,
|
||||
status: response.status,
|
||||
body,
|
||||
durationMs: Date.now() - startTime,
|
||||
}));
|
||||
return body;
|
||||
}
|
||||
export function addRequestID(value, response) {
|
||||
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
||||
return value;
|
||||
}
|
||||
return Object.defineProperty(value, '_request_id', {
|
||||
value: response.headers.get('request-id'),
|
||||
enumerable: false,
|
||||
});
|
||||
}
|
||||
//# sourceMappingURL=parse.mjs.map
|
||||
10
claude-code-source/node_modules/@anthropic-ai/sdk/internal/request-options.mjs
generated
vendored
10
claude-code-source/node_modules/@anthropic-ai/sdk/internal/request-options.mjs
generated
vendored
@@ -1,10 +0,0 @@
|
||||
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
||||
export const FallbackEncoder = ({ headers, body }) => {
|
||||
return {
|
||||
bodyHeaders: {
|
||||
'content-type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(body),
|
||||
};
|
||||
};
|
||||
//# sourceMappingURL=request-options.mjs.map
|
||||
85
claude-code-source/node_modules/@anthropic-ai/sdk/internal/shims.mjs
generated
vendored
85
claude-code-source/node_modules/@anthropic-ai/sdk/internal/shims.mjs
generated
vendored
@@ -1,85 +0,0 @@
|
||||
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
||||
export function getDefaultFetch() {
|
||||
if (typeof fetch !== 'undefined') {
|
||||
return fetch;
|
||||
}
|
||||
throw new Error('`fetch` is not defined as a global; Either pass `fetch` to the client, `new Anthropic({ fetch })` or polyfill the global, `globalThis.fetch = fetch`');
|
||||
}
|
||||
export function makeReadableStream(...args) {
|
||||
const ReadableStream = globalThis.ReadableStream;
|
||||
if (typeof ReadableStream === 'undefined') {
|
||||
// Note: All of the platforms / runtimes we officially support already define
|
||||
// `ReadableStream` as a global, so this should only ever be hit on unsupported runtimes.
|
||||
throw new Error('`ReadableStream` is not defined as a global; You will need to polyfill it, `globalThis.ReadableStream = ReadableStream`');
|
||||
}
|
||||
return new ReadableStream(...args);
|
||||
}
|
||||
export function ReadableStreamFrom(iterable) {
|
||||
let iter = Symbol.asyncIterator in iterable ? iterable[Symbol.asyncIterator]() : iterable[Symbol.iterator]();
|
||||
return makeReadableStream({
|
||||
start() { },
|
||||
async pull(controller) {
|
||||
const { done, value } = await iter.next();
|
||||
if (done) {
|
||||
controller.close();
|
||||
}
|
||||
else {
|
||||
controller.enqueue(value);
|
||||
}
|
||||
},
|
||||
async cancel() {
|
||||
await iter.return?.();
|
||||
},
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Most browsers don't yet have async iterable support for ReadableStream,
|
||||
* and Node has a very different way of reading bytes from its "ReadableStream".
|
||||
*
|
||||
* This polyfill was pulled from https://github.com/MattiasBuelens/web-streams-polyfill/pull/122#issuecomment-1627354490
|
||||
*/
|
||||
export function ReadableStreamToAsyncIterable(stream) {
|
||||
if (stream[Symbol.asyncIterator])
|
||||
return stream;
|
||||
const reader = stream.getReader();
|
||||
return {
|
||||
async next() {
|
||||
try {
|
||||
const result = await reader.read();
|
||||
if (result?.done)
|
||||
reader.releaseLock(); // release lock when stream becomes closed
|
||||
return result;
|
||||
}
|
||||
catch (e) {
|
||||
reader.releaseLock(); // release lock when stream becomes errored
|
||||
throw e;
|
||||
}
|
||||
},
|
||||
async return() {
|
||||
const cancelPromise = reader.cancel();
|
||||
reader.releaseLock();
|
||||
await cancelPromise;
|
||||
return { done: true, value: undefined };
|
||||
},
|
||||
[Symbol.asyncIterator]() {
|
||||
return this;
|
||||
},
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Cancels a ReadableStream we don't need to consume.
|
||||
* See https://undici.nodejs.org/#/?id=garbage-collection
|
||||
*/
|
||||
export async function CancelReadableStream(stream) {
|
||||
if (stream === null || typeof stream !== 'object')
|
||||
return;
|
||||
if (stream[Symbol.asyncIterator]) {
|
||||
await stream[Symbol.asyncIterator]().return?.();
|
||||
return;
|
||||
}
|
||||
const reader = stream.getReader();
|
||||
const cancelPromise = reader.cancel();
|
||||
reader.releaseLock();
|
||||
await cancelPromise;
|
||||
}
|
||||
//# sourceMappingURL=shims.mjs.map
|
||||
93
claude-code-source/node_modules/@anthropic-ai/sdk/internal/to-file.mjs
generated
vendored
93
claude-code-source/node_modules/@anthropic-ai/sdk/internal/to-file.mjs
generated
vendored
@@ -1,93 +0,0 @@
|
||||
import { getName, makeFile, isAsyncIterable } from "./uploads.mjs";
|
||||
import { checkFileSupport } from "./uploads.mjs";
|
||||
/**
|
||||
* This check adds the arrayBuffer() method type because it is available and used at runtime
|
||||
*/
|
||||
const isBlobLike = (value) => value != null &&
|
||||
typeof value === 'object' &&
|
||||
typeof value.size === 'number' &&
|
||||
typeof value.type === 'string' &&
|
||||
typeof value.text === 'function' &&
|
||||
typeof value.slice === 'function' &&
|
||||
typeof value.arrayBuffer === 'function';
|
||||
/**
|
||||
* This check adds the arrayBuffer() method type because it is available and used at runtime
|
||||
*/
|
||||
const isFileLike = (value) => value != null &&
|
||||
typeof value === 'object' &&
|
||||
typeof value.name === 'string' &&
|
||||
typeof value.lastModified === 'number' &&
|
||||
isBlobLike(value);
|
||||
const isResponseLike = (value) => value != null &&
|
||||
typeof value === 'object' &&
|
||||
typeof value.url === 'string' &&
|
||||
typeof value.blob === 'function';
|
||||
/**
|
||||
* Helper for creating a {@link File} to pass to an SDK upload method from a variety of different data formats
|
||||
* @param value the raw content of the file. Can be an {@link Uploadable}, BlobLikePart, or AsyncIterable of BlobLikeParts
|
||||
* @param {string=} name the name of the file. If omitted, toFile will try to determine a file name from bits if possible
|
||||
* @param {Object=} options additional properties
|
||||
* @param {string=} options.type the MIME type of the content
|
||||
* @param {number=} options.lastModified the last modified timestamp
|
||||
* @returns a {@link File} with the given properties
|
||||
*/
|
||||
export async function toFile(value, name, options) {
|
||||
checkFileSupport();
|
||||
// If it's a promise, resolve it.
|
||||
value = await value;
|
||||
name || (name = getName(value, true));
|
||||
// If we've been given a `File` we don't need to do anything if the name / options
|
||||
// have not been customised.
|
||||
if (isFileLike(value)) {
|
||||
if (value instanceof File && name == null && options == null) {
|
||||
return value;
|
||||
}
|
||||
return makeFile([await value.arrayBuffer()], name ?? value.name, {
|
||||
type: value.type,
|
||||
lastModified: value.lastModified,
|
||||
...options,
|
||||
});
|
||||
}
|
||||
if (isResponseLike(value)) {
|
||||
const blob = await value.blob();
|
||||
name || (name = new URL(value.url).pathname.split(/[\\/]/).pop());
|
||||
return makeFile(await getBytes(blob), name, options);
|
||||
}
|
||||
const parts = await getBytes(value);
|
||||
if (!options?.type) {
|
||||
const type = parts.find((part) => typeof part === 'object' && 'type' in part && part.type);
|
||||
if (typeof type === 'string') {
|
||||
options = { ...options, type };
|
||||
}
|
||||
}
|
||||
return makeFile(parts, name, options);
|
||||
}
|
||||
async function getBytes(value) {
|
||||
let parts = [];
|
||||
if (typeof value === 'string' ||
|
||||
ArrayBuffer.isView(value) || // includes Uint8Array, Buffer, etc.
|
||||
value instanceof ArrayBuffer) {
|
||||
parts.push(value);
|
||||
}
|
||||
else if (isBlobLike(value)) {
|
||||
parts.push(value instanceof Blob ? value : await value.arrayBuffer());
|
||||
}
|
||||
else if (isAsyncIterable(value) // includes Readable, ReadableStream, etc.
|
||||
) {
|
||||
for await (const chunk of value) {
|
||||
parts.push(...(await getBytes(chunk))); // TODO, consider validating?
|
||||
}
|
||||
}
|
||||
else {
|
||||
const constructor = value?.constructor?.name;
|
||||
throw new Error(`Unexpected data type: ${typeof value}${constructor ? `; constructor: ${constructor}` : ''}${propsForError(value)}`);
|
||||
}
|
||||
return parts;
|
||||
}
|
||||
function propsForError(value) {
|
||||
if (typeof value !== 'object' || value === null)
|
||||
return '';
|
||||
const props = Object.getOwnPropertyNames(value);
|
||||
return `; props: [${props.map((p) => `"${p}"`).join(', ')}]`;
|
||||
}
|
||||
//# sourceMappingURL=to-file.mjs.map
|
||||
17
claude-code-source/node_modules/@anthropic-ai/sdk/internal/tslib.mjs
generated
vendored
17
claude-code-source/node_modules/@anthropic-ai/sdk/internal/tslib.mjs
generated
vendored
@@ -1,17 +0,0 @@
|
||||
function __classPrivateFieldSet(receiver, state, value, kind, f) {
|
||||
if (kind === "m")
|
||||
throw new TypeError("Private method is not writable");
|
||||
if (kind === "a" && !f)
|
||||
throw new TypeError("Private accessor was defined without a setter");
|
||||
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver))
|
||||
throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
||||
return kind === "a" ? f.call(receiver, value) : f ? (f.value = value) : state.set(receiver, value), value;
|
||||
}
|
||||
function __classPrivateFieldGet(receiver, state, kind, f) {
|
||||
if (kind === "a" && !f)
|
||||
throw new TypeError("Private accessor was defined without a getter");
|
||||
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver))
|
||||
throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
||||
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
||||
}
|
||||
export { __classPrivateFieldSet, __classPrivateFieldGet };
|
||||
135
claude-code-source/node_modules/@anthropic-ai/sdk/internal/uploads.mjs
generated
vendored
135
claude-code-source/node_modules/@anthropic-ai/sdk/internal/uploads.mjs
generated
vendored
@@ -1,135 +0,0 @@
|
||||
import { ReadableStreamFrom } from "./shims.mjs";
|
||||
export const checkFileSupport = () => {
|
||||
if (typeof File === 'undefined') {
|
||||
const { process } = globalThis;
|
||||
const isOldNode = typeof process?.versions?.node === 'string' && parseInt(process.versions.node.split('.')) < 20;
|
||||
throw new Error('`File` is not defined as a global, which is required for file uploads.' +
|
||||
(isOldNode ?
|
||||
" Update to Node 20 LTS or newer, or set `globalThis.File` to `import('node:buffer').File`."
|
||||
: ''));
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Construct a `File` instance. This is used to ensure a helpful error is thrown
|
||||
* for environments that don't define a global `File` yet.
|
||||
*/
|
||||
export function makeFile(fileBits, fileName, options) {
|
||||
checkFileSupport();
|
||||
return new File(fileBits, fileName ?? 'unknown_file', options);
|
||||
}
|
||||
export function getName(value, stripPath) {
|
||||
const val = (typeof value === 'object' &&
|
||||
value !== null &&
|
||||
(('name' in value && value.name && String(value.name)) ||
|
||||
('url' in value && value.url && String(value.url)) ||
|
||||
('filename' in value && value.filename && String(value.filename)) ||
|
||||
('path' in value && value.path && String(value.path)))) ||
|
||||
'';
|
||||
return stripPath ? val.split(/[\\/]/).pop() || undefined : val;
|
||||
}
|
||||
export const isAsyncIterable = (value) => value != null && typeof value === 'object' && typeof value[Symbol.asyncIterator] === 'function';
|
||||
/**
|
||||
* Returns a multipart/form-data request if any part of the given request body contains a File / Blob value.
|
||||
* Otherwise returns the request as is.
|
||||
*/
|
||||
export const maybeMultipartFormRequestOptions = async (opts, fetch) => {
|
||||
if (!hasUploadableValue(opts.body))
|
||||
return opts;
|
||||
return { ...opts, body: await createForm(opts.body, fetch) };
|
||||
};
|
||||
export const multipartFormRequestOptions = async (opts, fetch, stripFilenames = true) => {
|
||||
return { ...opts, body: await createForm(opts.body, fetch, stripFilenames) };
|
||||
};
|
||||
const supportsFormDataMap = /* @__PURE__ */ new WeakMap();
|
||||
/**
|
||||
* node-fetch doesn't support the global FormData object in recent node versions. Instead of sending
|
||||
* properly-encoded form data, it just stringifies the object, resulting in a request body of "[object FormData]".
|
||||
* This function detects if the fetch function provided supports the global FormData object to avoid
|
||||
* confusing error messages later on.
|
||||
*/
|
||||
function supportsFormData(fetchObject) {
|
||||
const fetch = typeof fetchObject === 'function' ? fetchObject : fetchObject.fetch;
|
||||
const cached = supportsFormDataMap.get(fetch);
|
||||
if (cached)
|
||||
return cached;
|
||||
const promise = (async () => {
|
||||
try {
|
||||
const FetchResponse = ('Response' in fetch ?
|
||||
fetch.Response
|
||||
: (await fetch('data:,')).constructor);
|
||||
const data = new FormData();
|
||||
if (data.toString() === (await new FetchResponse(data).text())) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch {
|
||||
// avoid false negatives
|
||||
return true;
|
||||
}
|
||||
})();
|
||||
supportsFormDataMap.set(fetch, promise);
|
||||
return promise;
|
||||
}
|
||||
export const createForm = async (body, fetch, stripFilenames = true) => {
|
||||
if (!(await supportsFormData(fetch))) {
|
||||
throw new TypeError('The provided fetch function does not support file uploads with the current global FormData class.');
|
||||
}
|
||||
const form = new FormData();
|
||||
await Promise.all(Object.entries(body || {}).map(([key, value]) => addFormValue(form, key, value, stripFilenames)));
|
||||
return form;
|
||||
};
|
||||
// We check for Blob not File because Bun.File doesn't inherit from File,
|
||||
// but they both inherit from Blob and have a `name` property at runtime.
|
||||
const isNamedBlob = (value) => value instanceof Blob && 'name' in value;
|
||||
const isUploadable = (value) => typeof value === 'object' &&
|
||||
value !== null &&
|
||||
(value instanceof Response || isAsyncIterable(value) || isNamedBlob(value));
|
||||
const hasUploadableValue = (value) => {
|
||||
if (isUploadable(value))
|
||||
return true;
|
||||
if (Array.isArray(value))
|
||||
return value.some(hasUploadableValue);
|
||||
if (value && typeof value === 'object') {
|
||||
for (const k in value) {
|
||||
if (hasUploadableValue(value[k]))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
const addFormValue = async (form, key, value, stripFilenames) => {
|
||||
if (value === undefined)
|
||||
return;
|
||||
if (value == null) {
|
||||
throw new TypeError(`Received null for "${key}"; to pass null in FormData, you must use the string 'null'`);
|
||||
}
|
||||
// TODO: make nested formats configurable
|
||||
if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
|
||||
form.append(key, String(value));
|
||||
}
|
||||
else if (value instanceof Response) {
|
||||
let options = {};
|
||||
const contentType = value.headers.get('Content-Type');
|
||||
if (contentType) {
|
||||
options = { type: contentType };
|
||||
}
|
||||
form.append(key, makeFile([await value.blob()], getName(value, stripFilenames), options));
|
||||
}
|
||||
else if (isAsyncIterable(value)) {
|
||||
form.append(key, makeFile([await new Response(ReadableStreamFrom(value)).blob()], getName(value, stripFilenames)));
|
||||
}
|
||||
else if (isNamedBlob(value)) {
|
||||
form.append(key, makeFile([value], getName(value, stripFilenames), { type: value.type }));
|
||||
}
|
||||
else if (Array.isArray(value)) {
|
||||
await Promise.all(value.map((entry) => addFormValue(form, key + '[]', entry, stripFilenames)));
|
||||
}
|
||||
else if (typeof value === 'object') {
|
||||
await Promise.all(Object.entries(value).map(([name, prop]) => addFormValue(form, `${key}[${name}]`, prop, stripFilenames)));
|
||||
}
|
||||
else {
|
||||
throw new TypeError(`Invalid value given to form, expected a string, number, boolean, object, Array, File or Blob but got ${value} instead`);
|
||||
}
|
||||
};
|
||||
//# sourceMappingURL=uploads.mjs.map
|
||||
26
claude-code-source/node_modules/@anthropic-ai/sdk/internal/utils/bytes.mjs
generated
vendored
26
claude-code-source/node_modules/@anthropic-ai/sdk/internal/utils/bytes.mjs
generated
vendored
@@ -1,26 +0,0 @@
|
||||
export function concatBytes(buffers) {
|
||||
let length = 0;
|
||||
for (const buffer of buffers) {
|
||||
length += buffer.length;
|
||||
}
|
||||
const output = new Uint8Array(length);
|
||||
let index = 0;
|
||||
for (const buffer of buffers) {
|
||||
output.set(buffer, index);
|
||||
index += buffer.length;
|
||||
}
|
||||
return output;
|
||||
}
|
||||
let encodeUTF8_;
|
||||
export function encodeUTF8(str) {
|
||||
let encoder;
|
||||
return (encodeUTF8_ ??
|
||||
((encoder = new globalThis.TextEncoder()), (encodeUTF8_ = encoder.encode.bind(encoder))))(str);
|
||||
}
|
||||
let decodeUTF8_;
|
||||
export function decodeUTF8(bytes) {
|
||||
let decoder;
|
||||
return (decodeUTF8_ ??
|
||||
((decoder = new globalThis.TextDecoder()), (decodeUTF8_ = decoder.decode.bind(decoder))))(bytes);
|
||||
}
|
||||
//# sourceMappingURL=bytes.mjs.map
|
||||
18
claude-code-source/node_modules/@anthropic-ai/sdk/internal/utils/env.mjs
generated
vendored
18
claude-code-source/node_modules/@anthropic-ai/sdk/internal/utils/env.mjs
generated
vendored
@@ -1,18 +0,0 @@
|
||||
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
||||
/**
|
||||
* Read an environment variable.
|
||||
*
|
||||
* Trims beginning and trailing whitespace.
|
||||
*
|
||||
* Will return undefined if the environment variable doesn't exist or cannot be accessed.
|
||||
*/
|
||||
export const readEnv = (env) => {
|
||||
if (typeof globalThis.process !== 'undefined') {
|
||||
return globalThis.process.env?.[env]?.trim() ?? undefined;
|
||||
}
|
||||
if (typeof globalThis.Deno !== 'undefined') {
|
||||
return globalThis.Deno.env?.get?.(env)?.trim();
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
//# sourceMappingURL=env.mjs.map
|
||||
80
claude-code-source/node_modules/@anthropic-ai/sdk/internal/utils/log.mjs
generated
vendored
80
claude-code-source/node_modules/@anthropic-ai/sdk/internal/utils/log.mjs
generated
vendored
@@ -1,80 +0,0 @@
|
||||
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
||||
import { hasOwn } from "./values.mjs";
|
||||
const levelNumbers = {
|
||||
off: 0,
|
||||
error: 200,
|
||||
warn: 300,
|
||||
info: 400,
|
||||
debug: 500,
|
||||
};
|
||||
export const parseLogLevel = (maybeLevel, sourceName, client) => {
|
||||
if (!maybeLevel) {
|
||||
return undefined;
|
||||
}
|
||||
if (hasOwn(levelNumbers, maybeLevel)) {
|
||||
return maybeLevel;
|
||||
}
|
||||
loggerFor(client).warn(`${sourceName} was set to ${JSON.stringify(maybeLevel)}, expected one of ${JSON.stringify(Object.keys(levelNumbers))}`);
|
||||
return undefined;
|
||||
};
|
||||
function noop() { }
|
||||
function makeLogFn(fnLevel, logger, logLevel) {
|
||||
if (!logger || levelNumbers[fnLevel] > levelNumbers[logLevel]) {
|
||||
return noop;
|
||||
}
|
||||
else {
|
||||
// Don't wrap logger functions, we want the stacktrace intact!
|
||||
return logger[fnLevel].bind(logger);
|
||||
}
|
||||
}
|
||||
const noopLogger = {
|
||||
error: noop,
|
||||
warn: noop,
|
||||
info: noop,
|
||||
debug: noop,
|
||||
};
|
||||
let cachedLoggers = /* @__PURE__ */ new WeakMap();
|
||||
export function loggerFor(client) {
|
||||
const logger = client.logger;
|
||||
const logLevel = client.logLevel ?? 'off';
|
||||
if (!logger) {
|
||||
return noopLogger;
|
||||
}
|
||||
const cachedLogger = cachedLoggers.get(logger);
|
||||
if (cachedLogger && cachedLogger[0] === logLevel) {
|
||||
return cachedLogger[1];
|
||||
}
|
||||
const levelLogger = {
|
||||
error: makeLogFn('error', logger, logLevel),
|
||||
warn: makeLogFn('warn', logger, logLevel),
|
||||
info: makeLogFn('info', logger, logLevel),
|
||||
debug: makeLogFn('debug', logger, logLevel),
|
||||
};
|
||||
cachedLoggers.set(logger, [logLevel, levelLogger]);
|
||||
return levelLogger;
|
||||
}
|
||||
export const formatRequestDetails = (details) => {
|
||||
if (details.options) {
|
||||
details.options = { ...details.options };
|
||||
delete details.options['headers']; // redundant + leaks internals
|
||||
}
|
||||
if (details.headers) {
|
||||
details.headers = Object.fromEntries((details.headers instanceof Headers ? [...details.headers] : Object.entries(details.headers)).map(([name, value]) => [
|
||||
name,
|
||||
(name.toLowerCase() === 'x-api-key' ||
|
||||
name.toLowerCase() === 'authorization' ||
|
||||
name.toLowerCase() === 'cookie' ||
|
||||
name.toLowerCase() === 'set-cookie') ?
|
||||
'***'
|
||||
: value,
|
||||
]));
|
||||
}
|
||||
if ('retryOfRequestLogID' in details) {
|
||||
if (details.retryOfRequestLogID) {
|
||||
details.retryOf = details.retryOfRequestLogID;
|
||||
}
|
||||
delete details.retryOfRequestLogID;
|
||||
}
|
||||
return details;
|
||||
};
|
||||
//# sourceMappingURL=log.mjs.map
|
||||
74
claude-code-source/node_modules/@anthropic-ai/sdk/internal/utils/path.mjs
generated
vendored
74
claude-code-source/node_modules/@anthropic-ai/sdk/internal/utils/path.mjs
generated
vendored
@@ -1,74 +0,0 @@
|
||||
import { AnthropicError } from "../../core/error.mjs";
|
||||
/**
|
||||
* Percent-encode everything that isn't safe to have in a path without encoding safe chars.
|
||||
*
|
||||
* Taken from https://datatracker.ietf.org/doc/html/rfc3986#section-3.3:
|
||||
* > unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
|
||||
* > sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
|
||||
* > pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
|
||||
*/
|
||||
export function encodeURIPath(str) {
|
||||
return str.replace(/[^A-Za-z0-9\-._~!$&'()*+,;=:@]+/g, encodeURIComponent);
|
||||
}
|
||||
const EMPTY = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.create(null));
|
||||
export const createPathTagFunction = (pathEncoder = encodeURIPath) => function path(statics, ...params) {
|
||||
// If there are no params, no processing is needed.
|
||||
if (statics.length === 1)
|
||||
return statics[0];
|
||||
let postPath = false;
|
||||
const invalidSegments = [];
|
||||
const path = statics.reduce((previousValue, currentValue, index) => {
|
||||
if (/[?#]/.test(currentValue)) {
|
||||
postPath = true;
|
||||
}
|
||||
const value = params[index];
|
||||
let encoded = (postPath ? encodeURIComponent : pathEncoder)('' + value);
|
||||
if (index !== params.length &&
|
||||
(value == null ||
|
||||
(typeof value === 'object' &&
|
||||
// handle values from other realms
|
||||
value.toString ===
|
||||
Object.getPrototypeOf(Object.getPrototypeOf(value.hasOwnProperty ?? EMPTY) ?? EMPTY)
|
||||
?.toString))) {
|
||||
encoded = value + '';
|
||||
invalidSegments.push({
|
||||
start: previousValue.length + currentValue.length,
|
||||
length: encoded.length,
|
||||
error: `Value of type ${Object.prototype.toString
|
||||
.call(value)
|
||||
.slice(8, -1)} is not a valid path parameter`,
|
||||
});
|
||||
}
|
||||
return previousValue + currentValue + (index === params.length ? '' : encoded);
|
||||
}, '');
|
||||
const pathOnly = path.split(/[?#]/, 1)[0];
|
||||
const invalidSegmentPattern = /(?<=^|\/)(?:\.|%2e){1,2}(?=\/|$)/gi;
|
||||
let match;
|
||||
// Find all invalid segments
|
||||
while ((match = invalidSegmentPattern.exec(pathOnly)) !== null) {
|
||||
invalidSegments.push({
|
||||
start: match.index,
|
||||
length: match[0].length,
|
||||
error: `Value "${match[0]}" can\'t be safely passed as a path parameter`,
|
||||
});
|
||||
}
|
||||
invalidSegments.sort((a, b) => a.start - b.start);
|
||||
if (invalidSegments.length > 0) {
|
||||
let lastEnd = 0;
|
||||
const underline = invalidSegments.reduce((acc, segment) => {
|
||||
const spaces = ' '.repeat(segment.start - lastEnd);
|
||||
const arrows = '^'.repeat(segment.length);
|
||||
lastEnd = segment.start + segment.length;
|
||||
return acc + spaces + arrows;
|
||||
}, '');
|
||||
throw new AnthropicError(`Path parameters result in path with invalid segments:\n${invalidSegments
|
||||
.map((e) => e.error)
|
||||
.join('\n')}\n${path}\n${underline}`);
|
||||
}
|
||||
return path;
|
||||
};
|
||||
/**
|
||||
* URI-encodes path params and ensures no unsafe /./ or /../ path segments are introduced.
|
||||
*/
|
||||
export const path = /* @__PURE__ */ createPathTagFunction(encodeURIPath);
|
||||
//# sourceMappingURL=path.mjs.map
|
||||
3
claude-code-source/node_modules/@anthropic-ai/sdk/internal/utils/sleep.mjs
generated
vendored
3
claude-code-source/node_modules/@anthropic-ai/sdk/internal/utils/sleep.mjs
generated
vendored
@@ -1,3 +0,0 @@
|
||||
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
||||
export const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
||||
//# sourceMappingURL=sleep.mjs.map
|
||||
15
claude-code-source/node_modules/@anthropic-ai/sdk/internal/utils/uuid.mjs
generated
vendored
15
claude-code-source/node_modules/@anthropic-ai/sdk/internal/utils/uuid.mjs
generated
vendored
@@ -1,15 +0,0 @@
|
||||
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
||||
/**
|
||||
* https://stackoverflow.com/a/2117523
|
||||
*/
|
||||
export let uuid4 = function () {
|
||||
const { crypto } = globalThis;
|
||||
if (crypto?.randomUUID) {
|
||||
uuid4 = crypto.randomUUID.bind(crypto);
|
||||
return crypto.randomUUID();
|
||||
}
|
||||
const u8 = new Uint8Array(1);
|
||||
const randomByte = crypto ? () => crypto.getRandomValues(u8)[0] : () => (Math.random() * 0xff) & 0xff;
|
||||
return '10000000-1000-4000-8000-100000000000'.replace(/[018]/g, (c) => (+c ^ (randomByte() & (15 >> (+c / 4)))).toString(16));
|
||||
};
|
||||
//# sourceMappingURL=uuid.mjs.map
|
||||
100
claude-code-source/node_modules/@anthropic-ai/sdk/internal/utils/values.mjs
generated
vendored
100
claude-code-source/node_modules/@anthropic-ai/sdk/internal/utils/values.mjs
generated
vendored
@@ -1,100 +0,0 @@
|
||||
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
||||
import { AnthropicError } from "../../core/error.mjs";
|
||||
// https://url.spec.whatwg.org/#url-scheme-string
|
||||
const startsWithSchemeRegexp = /^[a-z][a-z0-9+.-]*:/i;
|
||||
export const isAbsoluteURL = (url) => {
|
||||
return startsWithSchemeRegexp.test(url);
|
||||
};
|
||||
export let isArray = (val) => ((isArray = Array.isArray), isArray(val));
|
||||
export let isReadonlyArray = isArray;
|
||||
/** Returns an object if the given value isn't an object, otherwise returns as-is */
|
||||
export function maybeObj(x) {
|
||||
if (typeof x !== 'object') {
|
||||
return {};
|
||||
}
|
||||
return x ?? {};
|
||||
}
|
||||
// https://stackoverflow.com/a/34491287
|
||||
export function isEmptyObj(obj) {
|
||||
if (!obj)
|
||||
return true;
|
||||
for (const _k in obj)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
// https://eslint.org/docs/latest/rules/no-prototype-builtins
|
||||
export function hasOwn(obj, key) {
|
||||
return Object.prototype.hasOwnProperty.call(obj, key);
|
||||
}
|
||||
export function isObj(obj) {
|
||||
return obj != null && typeof obj === 'object' && !Array.isArray(obj);
|
||||
}
|
||||
export const ensurePresent = (value) => {
|
||||
if (value == null) {
|
||||
throw new AnthropicError(`Expected a value to be given but received ${value} instead.`);
|
||||
}
|
||||
return value;
|
||||
};
|
||||
export const validatePositiveInteger = (name, n) => {
|
||||
if (typeof n !== 'number' || !Number.isInteger(n)) {
|
||||
throw new AnthropicError(`${name} must be an integer`);
|
||||
}
|
||||
if (n < 0) {
|
||||
throw new AnthropicError(`${name} must be a positive integer`);
|
||||
}
|
||||
return n;
|
||||
};
|
||||
export const coerceInteger = (value) => {
|
||||
if (typeof value === 'number')
|
||||
return Math.round(value);
|
||||
if (typeof value === 'string')
|
||||
return parseInt(value, 10);
|
||||
throw new AnthropicError(`Could not coerce ${value} (type: ${typeof value}) into a number`);
|
||||
};
|
||||
export const coerceFloat = (value) => {
|
||||
if (typeof value === 'number')
|
||||
return value;
|
||||
if (typeof value === 'string')
|
||||
return parseFloat(value);
|
||||
throw new AnthropicError(`Could not coerce ${value} (type: ${typeof value}) into a number`);
|
||||
};
|
||||
export const coerceBoolean = (value) => {
|
||||
if (typeof value === 'boolean')
|
||||
return value;
|
||||
if (typeof value === 'string')
|
||||
return value === 'true';
|
||||
return Boolean(value);
|
||||
};
|
||||
export const maybeCoerceInteger = (value) => {
|
||||
if (value == null) {
|
||||
return undefined;
|
||||
}
|
||||
return coerceInteger(value);
|
||||
};
|
||||
export const maybeCoerceFloat = (value) => {
|
||||
if (value == null) {
|
||||
return undefined;
|
||||
}
|
||||
return coerceFloat(value);
|
||||
};
|
||||
export const maybeCoerceBoolean = (value) => {
|
||||
if (value == null) {
|
||||
return undefined;
|
||||
}
|
||||
return coerceBoolean(value);
|
||||
};
|
||||
export const safeJSON = (text) => {
|
||||
try {
|
||||
return JSON.parse(text);
|
||||
}
|
||||
catch (err) {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
// Gets a value from an object, deletes the key, and returns the value (or undefined if not found)
|
||||
export const pop = (obj, key) => {
|
||||
const value = obj[key];
|
||||
delete obj[key];
|
||||
return value;
|
||||
};
|
||||
//# sourceMappingURL=values.mjs.map
|
||||
616
claude-code-source/node_modules/@anthropic-ai/sdk/lib/BetaMessageStream.mjs
generated
vendored
616
claude-code-source/node_modules/@anthropic-ai/sdk/lib/BetaMessageStream.mjs
generated
vendored
@@ -1,616 +0,0 @@
|
||||
var _BetaMessageStream_instances, _BetaMessageStream_currentMessageSnapshot, _BetaMessageStream_params, _BetaMessageStream_connectedPromise, _BetaMessageStream_resolveConnectedPromise, _BetaMessageStream_rejectConnectedPromise, _BetaMessageStream_endPromise, _BetaMessageStream_resolveEndPromise, _BetaMessageStream_rejectEndPromise, _BetaMessageStream_listeners, _BetaMessageStream_ended, _BetaMessageStream_errored, _BetaMessageStream_aborted, _BetaMessageStream_catchingPromiseCreated, _BetaMessageStream_response, _BetaMessageStream_request_id, _BetaMessageStream_logger, _BetaMessageStream_getFinalMessage, _BetaMessageStream_getFinalText, _BetaMessageStream_handleError, _BetaMessageStream_beginRequest, _BetaMessageStream_addStreamEvent, _BetaMessageStream_endRequest, _BetaMessageStream_accumulateMessage;
|
||||
import { __classPrivateFieldGet, __classPrivateFieldSet } from "../internal/tslib.mjs";
|
||||
import { partialParse } from "../_vendor/partial-json-parser/parser.mjs";
|
||||
import { AnthropicError, APIUserAbortError } from "../error.mjs";
|
||||
import { isAbortError } from "../internal/errors.mjs";
|
||||
import { Stream } from "../streaming.mjs";
|
||||
import { maybeParseBetaMessage } from "./beta-parser.mjs";
|
||||
const JSON_BUF_PROPERTY = '__json_buf';
|
||||
function tracksToolInput(content) {
|
||||
return content.type === 'tool_use' || content.type === 'server_tool_use' || content.type === 'mcp_tool_use';
|
||||
}
|
||||
export class BetaMessageStream {
|
||||
constructor(params, opts) {
|
||||
_BetaMessageStream_instances.add(this);
|
||||
this.messages = [];
|
||||
this.receivedMessages = [];
|
||||
_BetaMessageStream_currentMessageSnapshot.set(this, void 0);
|
||||
_BetaMessageStream_params.set(this, null);
|
||||
this.controller = new AbortController();
|
||||
_BetaMessageStream_connectedPromise.set(this, void 0);
|
||||
_BetaMessageStream_resolveConnectedPromise.set(this, () => { });
|
||||
_BetaMessageStream_rejectConnectedPromise.set(this, () => { });
|
||||
_BetaMessageStream_endPromise.set(this, void 0);
|
||||
_BetaMessageStream_resolveEndPromise.set(this, () => { });
|
||||
_BetaMessageStream_rejectEndPromise.set(this, () => { });
|
||||
_BetaMessageStream_listeners.set(this, {});
|
||||
_BetaMessageStream_ended.set(this, false);
|
||||
_BetaMessageStream_errored.set(this, false);
|
||||
_BetaMessageStream_aborted.set(this, false);
|
||||
_BetaMessageStream_catchingPromiseCreated.set(this, false);
|
||||
_BetaMessageStream_response.set(this, void 0);
|
||||
_BetaMessageStream_request_id.set(this, void 0);
|
||||
_BetaMessageStream_logger.set(this, void 0);
|
||||
_BetaMessageStream_handleError.set(this, (error) => {
|
||||
__classPrivateFieldSet(this, _BetaMessageStream_errored, true, "f");
|
||||
if (isAbortError(error)) {
|
||||
error = new APIUserAbortError();
|
||||
}
|
||||
if (error instanceof APIUserAbortError) {
|
||||
__classPrivateFieldSet(this, _BetaMessageStream_aborted, true, "f");
|
||||
return this._emit('abort', error);
|
||||
}
|
||||
if (error instanceof AnthropicError) {
|
||||
return this._emit('error', error);
|
||||
}
|
||||
if (error instanceof Error) {
|
||||
const anthropicError = new AnthropicError(error.message);
|
||||
// @ts-ignore
|
||||
anthropicError.cause = error;
|
||||
return this._emit('error', anthropicError);
|
||||
}
|
||||
return this._emit('error', new AnthropicError(String(error)));
|
||||
});
|
||||
__classPrivateFieldSet(this, _BetaMessageStream_connectedPromise, new Promise((resolve, reject) => {
|
||||
__classPrivateFieldSet(this, _BetaMessageStream_resolveConnectedPromise, resolve, "f");
|
||||
__classPrivateFieldSet(this, _BetaMessageStream_rejectConnectedPromise, reject, "f");
|
||||
}), "f");
|
||||
__classPrivateFieldSet(this, _BetaMessageStream_endPromise, new Promise((resolve, reject) => {
|
||||
__classPrivateFieldSet(this, _BetaMessageStream_resolveEndPromise, resolve, "f");
|
||||
__classPrivateFieldSet(this, _BetaMessageStream_rejectEndPromise, reject, "f");
|
||||
}), "f");
|
||||
// Don't let these promises cause unhandled rejection errors.
|
||||
// we will manually cause an unhandled rejection error later
|
||||
// if the user hasn't registered any error listener or called
|
||||
// any promise-returning method.
|
||||
__classPrivateFieldGet(this, _BetaMessageStream_connectedPromise, "f").catch(() => { });
|
||||
__classPrivateFieldGet(this, _BetaMessageStream_endPromise, "f").catch(() => { });
|
||||
__classPrivateFieldSet(this, _BetaMessageStream_params, params, "f");
|
||||
__classPrivateFieldSet(this, _BetaMessageStream_logger, opts?.logger ?? console, "f");
|
||||
}
|
||||
get response() {
|
||||
return __classPrivateFieldGet(this, _BetaMessageStream_response, "f");
|
||||
}
|
||||
get request_id() {
|
||||
return __classPrivateFieldGet(this, _BetaMessageStream_request_id, "f");
|
||||
}
|
||||
/**
|
||||
* Returns the `MessageStream` data, the raw `Response` instance and the ID of the request,
|
||||
* returned vie the `request-id` header which is useful for debugging requests and resporting
|
||||
* issues to Anthropic.
|
||||
*
|
||||
* This is the same as the `APIPromise.withResponse()` method.
|
||||
*
|
||||
* This method will raise an error if you created the stream using `MessageStream.fromReadableStream`
|
||||
* as no `Response` is available.
|
||||
*/
|
||||
async withResponse() {
|
||||
__classPrivateFieldSet(this, _BetaMessageStream_catchingPromiseCreated, true, "f");
|
||||
const response = await __classPrivateFieldGet(this, _BetaMessageStream_connectedPromise, "f");
|
||||
if (!response) {
|
||||
throw new Error('Could not resolve a `Response` object');
|
||||
}
|
||||
return {
|
||||
data: this,
|
||||
response,
|
||||
request_id: response.headers.get('request-id'),
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Intended for use on the frontend, consuming a stream produced with
|
||||
* `.toReadableStream()` on the backend.
|
||||
*
|
||||
* Note that messages sent to the model do not appear in `.on('message')`
|
||||
* in this context.
|
||||
*/
|
||||
static fromReadableStream(stream) {
|
||||
const runner = new BetaMessageStream(null);
|
||||
runner._run(() => runner._fromReadableStream(stream));
|
||||
return runner;
|
||||
}
|
||||
static createMessage(messages, params, options, { logger } = {}) {
|
||||
const runner = new BetaMessageStream(params, { logger });
|
||||
for (const message of params.messages) {
|
||||
runner._addMessageParam(message);
|
||||
}
|
||||
__classPrivateFieldSet(runner, _BetaMessageStream_params, { ...params, stream: true }, "f");
|
||||
runner._run(() => runner._createMessage(messages, { ...params, stream: true }, { ...options, headers: { ...options?.headers, 'X-Stainless-Helper-Method': 'stream' } }));
|
||||
return runner;
|
||||
}
|
||||
_run(executor) {
|
||||
executor().then(() => {
|
||||
this._emitFinal();
|
||||
this._emit('end');
|
||||
}, __classPrivateFieldGet(this, _BetaMessageStream_handleError, "f"));
|
||||
}
|
||||
_addMessageParam(message) {
|
||||
this.messages.push(message);
|
||||
}
|
||||
_addMessage(message, emit = true) {
|
||||
this.receivedMessages.push(message);
|
||||
if (emit) {
|
||||
this._emit('message', message);
|
||||
}
|
||||
}
|
||||
async _createMessage(messages, params, options) {
|
||||
const signal = options?.signal;
|
||||
let abortHandler;
|
||||
if (signal) {
|
||||
if (signal.aborted)
|
||||
this.controller.abort();
|
||||
abortHandler = this.controller.abort.bind(this.controller);
|
||||
signal.addEventListener('abort', abortHandler);
|
||||
}
|
||||
try {
|
||||
__classPrivateFieldGet(this, _BetaMessageStream_instances, "m", _BetaMessageStream_beginRequest).call(this);
|
||||
const { response, data: stream } = await messages
|
||||
.create({ ...params, stream: true }, { ...options, signal: this.controller.signal })
|
||||
.withResponse();
|
||||
this._connected(response);
|
||||
for await (const event of stream) {
|
||||
__classPrivateFieldGet(this, _BetaMessageStream_instances, "m", _BetaMessageStream_addStreamEvent).call(this, event);
|
||||
}
|
||||
if (stream.controller.signal?.aborted) {
|
||||
throw new APIUserAbortError();
|
||||
}
|
||||
__classPrivateFieldGet(this, _BetaMessageStream_instances, "m", _BetaMessageStream_endRequest).call(this);
|
||||
}
|
||||
finally {
|
||||
if (signal && abortHandler) {
|
||||
signal.removeEventListener('abort', abortHandler);
|
||||
}
|
||||
}
|
||||
}
|
||||
_connected(response) {
|
||||
if (this.ended)
|
||||
return;
|
||||
__classPrivateFieldSet(this, _BetaMessageStream_response, response, "f");
|
||||
__classPrivateFieldSet(this, _BetaMessageStream_request_id, response?.headers.get('request-id'), "f");
|
||||
__classPrivateFieldGet(this, _BetaMessageStream_resolveConnectedPromise, "f").call(this, response);
|
||||
this._emit('connect');
|
||||
}
|
||||
get ended() {
|
||||
return __classPrivateFieldGet(this, _BetaMessageStream_ended, "f");
|
||||
}
|
||||
get errored() {
|
||||
return __classPrivateFieldGet(this, _BetaMessageStream_errored, "f");
|
||||
}
|
||||
get aborted() {
|
||||
return __classPrivateFieldGet(this, _BetaMessageStream_aborted, "f");
|
||||
}
|
||||
abort() {
|
||||
this.controller.abort();
|
||||
}
|
||||
/**
|
||||
* Adds the listener function to the end of the listeners array for the event.
|
||||
* No checks are made to see if the listener has already been added. Multiple calls passing
|
||||
* the same combination of event and listener will result in the listener being added, and
|
||||
* called, multiple times.
|
||||
* @returns this MessageStream, so that calls can be chained
|
||||
*/
|
||||
on(event, listener) {
|
||||
const listeners = __classPrivateFieldGet(this, _BetaMessageStream_listeners, "f")[event] || (__classPrivateFieldGet(this, _BetaMessageStream_listeners, "f")[event] = []);
|
||||
listeners.push({ listener });
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Removes the specified listener from the listener array for the event.
|
||||
* off() will remove, at most, one instance of a listener from the listener array. If any single
|
||||
* listener has been added multiple times to the listener array for the specified event, then
|
||||
* off() must be called multiple times to remove each instance.
|
||||
* @returns this MessageStream, so that calls can be chained
|
||||
*/
|
||||
off(event, listener) {
|
||||
const listeners = __classPrivateFieldGet(this, _BetaMessageStream_listeners, "f")[event];
|
||||
if (!listeners)
|
||||
return this;
|
||||
const index = listeners.findIndex((l) => l.listener === listener);
|
||||
if (index >= 0)
|
||||
listeners.splice(index, 1);
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Adds a one-time listener function for the event. The next time the event is triggered,
|
||||
* this listener is removed and then invoked.
|
||||
* @returns this MessageStream, so that calls can be chained
|
||||
*/
|
||||
once(event, listener) {
|
||||
const listeners = __classPrivateFieldGet(this, _BetaMessageStream_listeners, "f")[event] || (__classPrivateFieldGet(this, _BetaMessageStream_listeners, "f")[event] = []);
|
||||
listeners.push({ listener, once: true });
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* This is similar to `.once()`, but returns a Promise that resolves the next time
|
||||
* the event is triggered, instead of calling a listener callback.
|
||||
* @returns a Promise that resolves the next time given event is triggered,
|
||||
* or rejects if an error is emitted. (If you request the 'error' event,
|
||||
* returns a promise that resolves with the error).
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* const message = await stream.emitted('message') // rejects if the stream errors
|
||||
*/
|
||||
emitted(event) {
|
||||
return new Promise((resolve, reject) => {
|
||||
__classPrivateFieldSet(this, _BetaMessageStream_catchingPromiseCreated, true, "f");
|
||||
if (event !== 'error')
|
||||
this.once('error', reject);
|
||||
this.once(event, resolve);
|
||||
});
|
||||
}
|
||||
async done() {
|
||||
__classPrivateFieldSet(this, _BetaMessageStream_catchingPromiseCreated, true, "f");
|
||||
await __classPrivateFieldGet(this, _BetaMessageStream_endPromise, "f");
|
||||
}
|
||||
get currentMessage() {
|
||||
return __classPrivateFieldGet(this, _BetaMessageStream_currentMessageSnapshot, "f");
|
||||
}
|
||||
/**
|
||||
* @returns a promise that resolves with the the final assistant Message response,
|
||||
* or rejects if an error occurred or the stream ended prematurely without producing a Message.
|
||||
* If structured outputs were used, this will be a ParsedMessage with a `parsed` field.
|
||||
*/
|
||||
async finalMessage() {
|
||||
await this.done();
|
||||
return __classPrivateFieldGet(this, _BetaMessageStream_instances, "m", _BetaMessageStream_getFinalMessage).call(this);
|
||||
}
|
||||
/**
|
||||
* @returns a promise that resolves with the the final assistant Message's text response, concatenated
|
||||
* together if there are more than one text blocks.
|
||||
* Rejects if an error occurred or the stream ended prematurely without producing a Message.
|
||||
*/
|
||||
async finalText() {
|
||||
await this.done();
|
||||
return __classPrivateFieldGet(this, _BetaMessageStream_instances, "m", _BetaMessageStream_getFinalText).call(this);
|
||||
}
|
||||
_emit(event, ...args) {
|
||||
// make sure we don't emit any MessageStreamEvents after end
|
||||
if (__classPrivateFieldGet(this, _BetaMessageStream_ended, "f"))
|
||||
return;
|
||||
if (event === 'end') {
|
||||
__classPrivateFieldSet(this, _BetaMessageStream_ended, true, "f");
|
||||
__classPrivateFieldGet(this, _BetaMessageStream_resolveEndPromise, "f").call(this);
|
||||
}
|
||||
const listeners = __classPrivateFieldGet(this, _BetaMessageStream_listeners, "f")[event];
|
||||
if (listeners) {
|
||||
__classPrivateFieldGet(this, _BetaMessageStream_listeners, "f")[event] = listeners.filter((l) => !l.once);
|
||||
listeners.forEach(({ listener }) => listener(...args));
|
||||
}
|
||||
if (event === 'abort') {
|
||||
const error = args[0];
|
||||
if (!__classPrivateFieldGet(this, _BetaMessageStream_catchingPromiseCreated, "f") && !listeners?.length) {
|
||||
Promise.reject(error);
|
||||
}
|
||||
__classPrivateFieldGet(this, _BetaMessageStream_rejectConnectedPromise, "f").call(this, error);
|
||||
__classPrivateFieldGet(this, _BetaMessageStream_rejectEndPromise, "f").call(this, error);
|
||||
this._emit('end');
|
||||
return;
|
||||
}
|
||||
if (event === 'error') {
|
||||
// NOTE: _emit('error', error) should only be called from #handleError().
|
||||
const error = args[0];
|
||||
if (!__classPrivateFieldGet(this, _BetaMessageStream_catchingPromiseCreated, "f") && !listeners?.length) {
|
||||
// Trigger an unhandled rejection if the user hasn't registered any error handlers.
|
||||
// If you are seeing stack traces here, make sure to handle errors via either:
|
||||
// - runner.on('error', () => ...)
|
||||
// - await runner.done()
|
||||
// - await runner.final...()
|
||||
// - etc.
|
||||
Promise.reject(error);
|
||||
}
|
||||
__classPrivateFieldGet(this, _BetaMessageStream_rejectConnectedPromise, "f").call(this, error);
|
||||
__classPrivateFieldGet(this, _BetaMessageStream_rejectEndPromise, "f").call(this, error);
|
||||
this._emit('end');
|
||||
}
|
||||
}
|
||||
_emitFinal() {
|
||||
const finalMessage = this.receivedMessages.at(-1);
|
||||
if (finalMessage) {
|
||||
this._emit('finalMessage', __classPrivateFieldGet(this, _BetaMessageStream_instances, "m", _BetaMessageStream_getFinalMessage).call(this));
|
||||
}
|
||||
}
|
||||
async _fromReadableStream(readableStream, options) {
|
||||
const signal = options?.signal;
|
||||
let abortHandler;
|
||||
if (signal) {
|
||||
if (signal.aborted)
|
||||
this.controller.abort();
|
||||
abortHandler = this.controller.abort.bind(this.controller);
|
||||
signal.addEventListener('abort', abortHandler);
|
||||
}
|
||||
try {
|
||||
__classPrivateFieldGet(this, _BetaMessageStream_instances, "m", _BetaMessageStream_beginRequest).call(this);
|
||||
this._connected(null);
|
||||
const stream = Stream.fromReadableStream(readableStream, this.controller);
|
||||
for await (const event of stream) {
|
||||
__classPrivateFieldGet(this, _BetaMessageStream_instances, "m", _BetaMessageStream_addStreamEvent).call(this, event);
|
||||
}
|
||||
if (stream.controller.signal?.aborted) {
|
||||
throw new APIUserAbortError();
|
||||
}
|
||||
__classPrivateFieldGet(this, _BetaMessageStream_instances, "m", _BetaMessageStream_endRequest).call(this);
|
||||
}
|
||||
finally {
|
||||
if (signal && abortHandler) {
|
||||
signal.removeEventListener('abort', abortHandler);
|
||||
}
|
||||
}
|
||||
}
|
||||
[(_BetaMessageStream_currentMessageSnapshot = new WeakMap(), _BetaMessageStream_params = new WeakMap(), _BetaMessageStream_connectedPromise = new WeakMap(), _BetaMessageStream_resolveConnectedPromise = new WeakMap(), _BetaMessageStream_rejectConnectedPromise = new WeakMap(), _BetaMessageStream_endPromise = new WeakMap(), _BetaMessageStream_resolveEndPromise = new WeakMap(), _BetaMessageStream_rejectEndPromise = new WeakMap(), _BetaMessageStream_listeners = new WeakMap(), _BetaMessageStream_ended = new WeakMap(), _BetaMessageStream_errored = new WeakMap(), _BetaMessageStream_aborted = new WeakMap(), _BetaMessageStream_catchingPromiseCreated = new WeakMap(), _BetaMessageStream_response = new WeakMap(), _BetaMessageStream_request_id = new WeakMap(), _BetaMessageStream_logger = new WeakMap(), _BetaMessageStream_handleError = new WeakMap(), _BetaMessageStream_instances = new WeakSet(), _BetaMessageStream_getFinalMessage = function _BetaMessageStream_getFinalMessage() {
|
||||
if (this.receivedMessages.length === 0) {
|
||||
throw new AnthropicError('stream ended without producing a Message with role=assistant');
|
||||
}
|
||||
return this.receivedMessages.at(-1);
|
||||
}, _BetaMessageStream_getFinalText = function _BetaMessageStream_getFinalText() {
|
||||
if (this.receivedMessages.length === 0) {
|
||||
throw new AnthropicError('stream ended without producing a Message with role=assistant');
|
||||
}
|
||||
const textBlocks = this.receivedMessages
|
||||
.at(-1)
|
||||
.content.filter((block) => block.type === 'text')
|
||||
.map((block) => block.text);
|
||||
if (textBlocks.length === 0) {
|
||||
throw new AnthropicError('stream ended without producing a content block with type=text');
|
||||
}
|
||||
return textBlocks.join(' ');
|
||||
}, _BetaMessageStream_beginRequest = function _BetaMessageStream_beginRequest() {
|
||||
if (this.ended)
|
||||
return;
|
||||
__classPrivateFieldSet(this, _BetaMessageStream_currentMessageSnapshot, undefined, "f");
|
||||
}, _BetaMessageStream_addStreamEvent = function _BetaMessageStream_addStreamEvent(event) {
|
||||
if (this.ended)
|
||||
return;
|
||||
const messageSnapshot = __classPrivateFieldGet(this, _BetaMessageStream_instances, "m", _BetaMessageStream_accumulateMessage).call(this, event);
|
||||
this._emit('streamEvent', event, messageSnapshot);
|
||||
switch (event.type) {
|
||||
case 'content_block_delta': {
|
||||
const content = messageSnapshot.content.at(-1);
|
||||
switch (event.delta.type) {
|
||||
case 'text_delta': {
|
||||
if (content.type === 'text') {
|
||||
this._emit('text', event.delta.text, content.text || '');
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'citations_delta': {
|
||||
if (content.type === 'text') {
|
||||
this._emit('citation', event.delta.citation, content.citations ?? []);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'input_json_delta': {
|
||||
if (tracksToolInput(content) && content.input) {
|
||||
this._emit('inputJson', event.delta.partial_json, content.input);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'thinking_delta': {
|
||||
if (content.type === 'thinking') {
|
||||
this._emit('thinking', event.delta.thinking, content.thinking);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'signature_delta': {
|
||||
if (content.type === 'thinking') {
|
||||
this._emit('signature', content.signature);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'compaction_delta': {
|
||||
if (content.type === 'compaction' && content.content) {
|
||||
this._emit('compaction', content.content);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
checkNever(event.delta);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'message_stop': {
|
||||
this._addMessageParam(messageSnapshot);
|
||||
this._addMessage(maybeParseBetaMessage(messageSnapshot, __classPrivateFieldGet(this, _BetaMessageStream_params, "f"), { logger: __classPrivateFieldGet(this, _BetaMessageStream_logger, "f") }), true);
|
||||
break;
|
||||
}
|
||||
case 'content_block_stop': {
|
||||
this._emit('contentBlock', messageSnapshot.content.at(-1));
|
||||
break;
|
||||
}
|
||||
case 'message_start': {
|
||||
__classPrivateFieldSet(this, _BetaMessageStream_currentMessageSnapshot, messageSnapshot, "f");
|
||||
break;
|
||||
}
|
||||
case 'content_block_start':
|
||||
case 'message_delta':
|
||||
break;
|
||||
}
|
||||
}, _BetaMessageStream_endRequest = function _BetaMessageStream_endRequest() {
|
||||
if (this.ended) {
|
||||
throw new AnthropicError(`stream has ended, this shouldn't happen`);
|
||||
}
|
||||
const snapshot = __classPrivateFieldGet(this, _BetaMessageStream_currentMessageSnapshot, "f");
|
||||
if (!snapshot) {
|
||||
throw new AnthropicError(`request ended without sending any chunks`);
|
||||
}
|
||||
__classPrivateFieldSet(this, _BetaMessageStream_currentMessageSnapshot, undefined, "f");
|
||||
return maybeParseBetaMessage(snapshot, __classPrivateFieldGet(this, _BetaMessageStream_params, "f"), { logger: __classPrivateFieldGet(this, _BetaMessageStream_logger, "f") });
|
||||
}, _BetaMessageStream_accumulateMessage = function _BetaMessageStream_accumulateMessage(event) {
|
||||
let snapshot = __classPrivateFieldGet(this, _BetaMessageStream_currentMessageSnapshot, "f");
|
||||
if (event.type === 'message_start') {
|
||||
if (snapshot) {
|
||||
throw new AnthropicError(`Unexpected event order, got ${event.type} before receiving "message_stop"`);
|
||||
}
|
||||
return event.message;
|
||||
}
|
||||
if (!snapshot) {
|
||||
throw new AnthropicError(`Unexpected event order, got ${event.type} before "message_start"`);
|
||||
}
|
||||
switch (event.type) {
|
||||
case 'message_stop':
|
||||
return snapshot;
|
||||
case 'message_delta':
|
||||
snapshot.container = event.delta.container;
|
||||
snapshot.stop_reason = event.delta.stop_reason;
|
||||
snapshot.stop_sequence = event.delta.stop_sequence;
|
||||
snapshot.usage.output_tokens = event.usage.output_tokens;
|
||||
snapshot.context_management = event.context_management;
|
||||
if (event.usage.input_tokens != null) {
|
||||
snapshot.usage.input_tokens = event.usage.input_tokens;
|
||||
}
|
||||
if (event.usage.cache_creation_input_tokens != null) {
|
||||
snapshot.usage.cache_creation_input_tokens = event.usage.cache_creation_input_tokens;
|
||||
}
|
||||
if (event.usage.cache_read_input_tokens != null) {
|
||||
snapshot.usage.cache_read_input_tokens = event.usage.cache_read_input_tokens;
|
||||
}
|
||||
if (event.usage.server_tool_use != null) {
|
||||
snapshot.usage.server_tool_use = event.usage.server_tool_use;
|
||||
}
|
||||
if (event.usage.iterations != null) {
|
||||
snapshot.usage.iterations = event.usage.iterations;
|
||||
}
|
||||
return snapshot;
|
||||
case 'content_block_start':
|
||||
snapshot.content.push(event.content_block);
|
||||
return snapshot;
|
||||
case 'content_block_delta': {
|
||||
const snapshotContent = snapshot.content.at(event.index);
|
||||
switch (event.delta.type) {
|
||||
case 'text_delta': {
|
||||
if (snapshotContent?.type === 'text') {
|
||||
snapshot.content[event.index] = {
|
||||
...snapshotContent,
|
||||
text: (snapshotContent.text || '') + event.delta.text,
|
||||
};
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'citations_delta': {
|
||||
if (snapshotContent?.type === 'text') {
|
||||
snapshot.content[event.index] = {
|
||||
...snapshotContent,
|
||||
citations: [...(snapshotContent.citations ?? []), event.delta.citation],
|
||||
};
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'input_json_delta': {
|
||||
if (snapshotContent && tracksToolInput(snapshotContent)) {
|
||||
// we need to keep track of the raw JSON string as well so that we can
|
||||
// re-parse it for each delta, for now we just store it as an untyped
|
||||
// non-enumerable property on the snapshot
|
||||
let jsonBuf = snapshotContent[JSON_BUF_PROPERTY] || '';
|
||||
jsonBuf += event.delta.partial_json;
|
||||
const newContent = { ...snapshotContent };
|
||||
Object.defineProperty(newContent, JSON_BUF_PROPERTY, {
|
||||
value: jsonBuf,
|
||||
enumerable: false,
|
||||
writable: true,
|
||||
});
|
||||
if (jsonBuf) {
|
||||
try {
|
||||
newContent.input = partialParse(jsonBuf);
|
||||
}
|
||||
catch (err) {
|
||||
const error = new AnthropicError(`Unable to parse tool parameter JSON from model. Please retry your request or adjust your prompt. Error: ${err}. JSON: ${jsonBuf}`);
|
||||
__classPrivateFieldGet(this, _BetaMessageStream_handleError, "f").call(this, error);
|
||||
}
|
||||
}
|
||||
snapshot.content[event.index] = newContent;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'thinking_delta': {
|
||||
if (snapshotContent?.type === 'thinking') {
|
||||
snapshot.content[event.index] = {
|
||||
...snapshotContent,
|
||||
thinking: snapshotContent.thinking + event.delta.thinking,
|
||||
};
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'signature_delta': {
|
||||
if (snapshotContent?.type === 'thinking') {
|
||||
snapshot.content[event.index] = {
|
||||
...snapshotContent,
|
||||
signature: event.delta.signature,
|
||||
};
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'compaction_delta': {
|
||||
if (snapshotContent?.type === 'compaction') {
|
||||
snapshot.content[event.index] = {
|
||||
...snapshotContent,
|
||||
content: (snapshotContent.content || '') + event.delta.content,
|
||||
};
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
checkNever(event.delta);
|
||||
}
|
||||
return snapshot;
|
||||
}
|
||||
case 'content_block_stop':
|
||||
return snapshot;
|
||||
}
|
||||
}, Symbol.asyncIterator)]() {
|
||||
const pushQueue = [];
|
||||
const readQueue = [];
|
||||
let done = false;
|
||||
this.on('streamEvent', (event) => {
|
||||
const reader = readQueue.shift();
|
||||
if (reader) {
|
||||
reader.resolve(event);
|
||||
}
|
||||
else {
|
||||
pushQueue.push(event);
|
||||
}
|
||||
});
|
||||
this.on('end', () => {
|
||||
done = true;
|
||||
for (const reader of readQueue) {
|
||||
reader.resolve(undefined);
|
||||
}
|
||||
readQueue.length = 0;
|
||||
});
|
||||
this.on('abort', (err) => {
|
||||
done = true;
|
||||
for (const reader of readQueue) {
|
||||
reader.reject(err);
|
||||
}
|
||||
readQueue.length = 0;
|
||||
});
|
||||
this.on('error', (err) => {
|
||||
done = true;
|
||||
for (const reader of readQueue) {
|
||||
reader.reject(err);
|
||||
}
|
||||
readQueue.length = 0;
|
||||
});
|
||||
return {
|
||||
next: async () => {
|
||||
if (!pushQueue.length) {
|
||||
if (done) {
|
||||
return { value: undefined, done: true };
|
||||
}
|
||||
return new Promise((resolve, reject) => readQueue.push({ resolve, reject })).then((chunk) => (chunk ? { value: chunk, done: false } : { value: undefined, done: true }));
|
||||
}
|
||||
const chunk = pushQueue.shift();
|
||||
return { value: chunk, done: false };
|
||||
},
|
||||
return: async () => {
|
||||
this.abort();
|
||||
return { value: undefined, done: true };
|
||||
},
|
||||
};
|
||||
}
|
||||
toReadableStream() {
|
||||
const stream = new Stream(this[Symbol.asyncIterator].bind(this), this.controller);
|
||||
return stream.toReadableStream();
|
||||
}
|
||||
}
|
||||
// used to ensure exhaustive case matching without throwing a runtime error
|
||||
function checkNever(x) { }
|
||||
//# sourceMappingURL=BetaMessageStream.mjs.map
|
||||
591
claude-code-source/node_modules/@anthropic-ai/sdk/lib/MessageStream.mjs
generated
vendored
591
claude-code-source/node_modules/@anthropic-ai/sdk/lib/MessageStream.mjs
generated
vendored
@@ -1,591 +0,0 @@
|
||||
var _MessageStream_instances, _MessageStream_currentMessageSnapshot, _MessageStream_params, _MessageStream_connectedPromise, _MessageStream_resolveConnectedPromise, _MessageStream_rejectConnectedPromise, _MessageStream_endPromise, _MessageStream_resolveEndPromise, _MessageStream_rejectEndPromise, _MessageStream_listeners, _MessageStream_ended, _MessageStream_errored, _MessageStream_aborted, _MessageStream_catchingPromiseCreated, _MessageStream_response, _MessageStream_request_id, _MessageStream_logger, _MessageStream_getFinalMessage, _MessageStream_getFinalText, _MessageStream_handleError, _MessageStream_beginRequest, _MessageStream_addStreamEvent, _MessageStream_endRequest, _MessageStream_accumulateMessage;
|
||||
import { __classPrivateFieldGet, __classPrivateFieldSet } from "../internal/tslib.mjs";
|
||||
import { isAbortError } from "../internal/errors.mjs";
|
||||
import { AnthropicError, APIUserAbortError } from "../error.mjs";
|
||||
import { Stream } from "../streaming.mjs";
|
||||
import { partialParse } from "../_vendor/partial-json-parser/parser.mjs";
|
||||
import { maybeParseMessage } from "./parser.mjs";
|
||||
const JSON_BUF_PROPERTY = '__json_buf';
|
||||
function tracksToolInput(content) {
|
||||
return content.type === 'tool_use' || content.type === 'server_tool_use';
|
||||
}
|
||||
export class MessageStream {
|
||||
constructor(params, opts) {
|
||||
_MessageStream_instances.add(this);
|
||||
this.messages = [];
|
||||
this.receivedMessages = [];
|
||||
_MessageStream_currentMessageSnapshot.set(this, void 0);
|
||||
_MessageStream_params.set(this, null);
|
||||
this.controller = new AbortController();
|
||||
_MessageStream_connectedPromise.set(this, void 0);
|
||||
_MessageStream_resolveConnectedPromise.set(this, () => { });
|
||||
_MessageStream_rejectConnectedPromise.set(this, () => { });
|
||||
_MessageStream_endPromise.set(this, void 0);
|
||||
_MessageStream_resolveEndPromise.set(this, () => { });
|
||||
_MessageStream_rejectEndPromise.set(this, () => { });
|
||||
_MessageStream_listeners.set(this, {});
|
||||
_MessageStream_ended.set(this, false);
|
||||
_MessageStream_errored.set(this, false);
|
||||
_MessageStream_aborted.set(this, false);
|
||||
_MessageStream_catchingPromiseCreated.set(this, false);
|
||||
_MessageStream_response.set(this, void 0);
|
||||
_MessageStream_request_id.set(this, void 0);
|
||||
_MessageStream_logger.set(this, void 0);
|
||||
_MessageStream_handleError.set(this, (error) => {
|
||||
__classPrivateFieldSet(this, _MessageStream_errored, true, "f");
|
||||
if (isAbortError(error)) {
|
||||
error = new APIUserAbortError();
|
||||
}
|
||||
if (error instanceof APIUserAbortError) {
|
||||
__classPrivateFieldSet(this, _MessageStream_aborted, true, "f");
|
||||
return this._emit('abort', error);
|
||||
}
|
||||
if (error instanceof AnthropicError) {
|
||||
return this._emit('error', error);
|
||||
}
|
||||
if (error instanceof Error) {
|
||||
const anthropicError = new AnthropicError(error.message);
|
||||
// @ts-ignore
|
||||
anthropicError.cause = error;
|
||||
return this._emit('error', anthropicError);
|
||||
}
|
||||
return this._emit('error', new AnthropicError(String(error)));
|
||||
});
|
||||
__classPrivateFieldSet(this, _MessageStream_connectedPromise, new Promise((resolve, reject) => {
|
||||
__classPrivateFieldSet(this, _MessageStream_resolveConnectedPromise, resolve, "f");
|
||||
__classPrivateFieldSet(this, _MessageStream_rejectConnectedPromise, reject, "f");
|
||||
}), "f");
|
||||
__classPrivateFieldSet(this, _MessageStream_endPromise, new Promise((resolve, reject) => {
|
||||
__classPrivateFieldSet(this, _MessageStream_resolveEndPromise, resolve, "f");
|
||||
__classPrivateFieldSet(this, _MessageStream_rejectEndPromise, reject, "f");
|
||||
}), "f");
|
||||
// Don't let these promises cause unhandled rejection errors.
|
||||
// we will manually cause an unhandled rejection error later
|
||||
// if the user hasn't registered any error listener or called
|
||||
// any promise-returning method.
|
||||
__classPrivateFieldGet(this, _MessageStream_connectedPromise, "f").catch(() => { });
|
||||
__classPrivateFieldGet(this, _MessageStream_endPromise, "f").catch(() => { });
|
||||
__classPrivateFieldSet(this, _MessageStream_params, params, "f");
|
||||
__classPrivateFieldSet(this, _MessageStream_logger, opts?.logger ?? console, "f");
|
||||
}
|
||||
get response() {
|
||||
return __classPrivateFieldGet(this, _MessageStream_response, "f");
|
||||
}
|
||||
get request_id() {
|
||||
return __classPrivateFieldGet(this, _MessageStream_request_id, "f");
|
||||
}
|
||||
/**
|
||||
* Returns the `MessageStream` data, the raw `Response` instance and the ID of the request,
|
||||
* returned vie the `request-id` header which is useful for debugging requests and resporting
|
||||
* issues to Anthropic.
|
||||
*
|
||||
* This is the same as the `APIPromise.withResponse()` method.
|
||||
*
|
||||
* This method will raise an error if you created the stream using `MessageStream.fromReadableStream`
|
||||
* as no `Response` is available.
|
||||
*/
|
||||
async withResponse() {
|
||||
__classPrivateFieldSet(this, _MessageStream_catchingPromiseCreated, true, "f");
|
||||
const response = await __classPrivateFieldGet(this, _MessageStream_connectedPromise, "f");
|
||||
if (!response) {
|
||||
throw new Error('Could not resolve a `Response` object');
|
||||
}
|
||||
return {
|
||||
data: this,
|
||||
response,
|
||||
request_id: response.headers.get('request-id'),
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Intended for use on the frontend, consuming a stream produced with
|
||||
* `.toReadableStream()` on the backend.
|
||||
*
|
||||
* Note that messages sent to the model do not appear in `.on('message')`
|
||||
* in this context.
|
||||
*/
|
||||
static fromReadableStream(stream) {
|
||||
const runner = new MessageStream(null);
|
||||
runner._run(() => runner._fromReadableStream(stream));
|
||||
return runner;
|
||||
}
|
||||
static createMessage(messages, params, options, { logger } = {}) {
|
||||
const runner = new MessageStream(params, { logger });
|
||||
for (const message of params.messages) {
|
||||
runner._addMessageParam(message);
|
||||
}
|
||||
__classPrivateFieldSet(runner, _MessageStream_params, { ...params, stream: true }, "f");
|
||||
runner._run(() => runner._createMessage(messages, { ...params, stream: true }, { ...options, headers: { ...options?.headers, 'X-Stainless-Helper-Method': 'stream' } }));
|
||||
return runner;
|
||||
}
|
||||
_run(executor) {
|
||||
executor().then(() => {
|
||||
this._emitFinal();
|
||||
this._emit('end');
|
||||
}, __classPrivateFieldGet(this, _MessageStream_handleError, "f"));
|
||||
}
|
||||
_addMessageParam(message) {
|
||||
this.messages.push(message);
|
||||
}
|
||||
_addMessage(message, emit = true) {
|
||||
this.receivedMessages.push(message);
|
||||
if (emit) {
|
||||
this._emit('message', message);
|
||||
}
|
||||
}
|
||||
async _createMessage(messages, params, options) {
|
||||
const signal = options?.signal;
|
||||
let abortHandler;
|
||||
if (signal) {
|
||||
if (signal.aborted)
|
||||
this.controller.abort();
|
||||
abortHandler = this.controller.abort.bind(this.controller);
|
||||
signal.addEventListener('abort', abortHandler);
|
||||
}
|
||||
try {
|
||||
__classPrivateFieldGet(this, _MessageStream_instances, "m", _MessageStream_beginRequest).call(this);
|
||||
const { response, data: stream } = await messages
|
||||
.create({ ...params, stream: true }, { ...options, signal: this.controller.signal })
|
||||
.withResponse();
|
||||
this._connected(response);
|
||||
for await (const event of stream) {
|
||||
__classPrivateFieldGet(this, _MessageStream_instances, "m", _MessageStream_addStreamEvent).call(this, event);
|
||||
}
|
||||
if (stream.controller.signal?.aborted) {
|
||||
throw new APIUserAbortError();
|
||||
}
|
||||
__classPrivateFieldGet(this, _MessageStream_instances, "m", _MessageStream_endRequest).call(this);
|
||||
}
|
||||
finally {
|
||||
if (signal && abortHandler) {
|
||||
signal.removeEventListener('abort', abortHandler);
|
||||
}
|
||||
}
|
||||
}
|
||||
_connected(response) {
|
||||
if (this.ended)
|
||||
return;
|
||||
__classPrivateFieldSet(this, _MessageStream_response, response, "f");
|
||||
__classPrivateFieldSet(this, _MessageStream_request_id, response?.headers.get('request-id'), "f");
|
||||
__classPrivateFieldGet(this, _MessageStream_resolveConnectedPromise, "f").call(this, response);
|
||||
this._emit('connect');
|
||||
}
|
||||
get ended() {
|
||||
return __classPrivateFieldGet(this, _MessageStream_ended, "f");
|
||||
}
|
||||
get errored() {
|
||||
return __classPrivateFieldGet(this, _MessageStream_errored, "f");
|
||||
}
|
||||
get aborted() {
|
||||
return __classPrivateFieldGet(this, _MessageStream_aborted, "f");
|
||||
}
|
||||
abort() {
|
||||
this.controller.abort();
|
||||
}
|
||||
/**
|
||||
* Adds the listener function to the end of the listeners array for the event.
|
||||
* No checks are made to see if the listener has already been added. Multiple calls passing
|
||||
* the same combination of event and listener will result in the listener being added, and
|
||||
* called, multiple times.
|
||||
* @returns this MessageStream, so that calls can be chained
|
||||
*/
|
||||
on(event, listener) {
|
||||
const listeners = __classPrivateFieldGet(this, _MessageStream_listeners, "f")[event] || (__classPrivateFieldGet(this, _MessageStream_listeners, "f")[event] = []);
|
||||
listeners.push({ listener });
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Removes the specified listener from the listener array for the event.
|
||||
* off() will remove, at most, one instance of a listener from the listener array. If any single
|
||||
* listener has been added multiple times to the listener array for the specified event, then
|
||||
* off() must be called multiple times to remove each instance.
|
||||
* @returns this MessageStream, so that calls can be chained
|
||||
*/
|
||||
off(event, listener) {
|
||||
const listeners = __classPrivateFieldGet(this, _MessageStream_listeners, "f")[event];
|
||||
if (!listeners)
|
||||
return this;
|
||||
const index = listeners.findIndex((l) => l.listener === listener);
|
||||
if (index >= 0)
|
||||
listeners.splice(index, 1);
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Adds a one-time listener function for the event. The next time the event is triggered,
|
||||
* this listener is removed and then invoked.
|
||||
* @returns this MessageStream, so that calls can be chained
|
||||
*/
|
||||
once(event, listener) {
|
||||
const listeners = __classPrivateFieldGet(this, _MessageStream_listeners, "f")[event] || (__classPrivateFieldGet(this, _MessageStream_listeners, "f")[event] = []);
|
||||
listeners.push({ listener, once: true });
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* This is similar to `.once()`, but returns a Promise that resolves the next time
|
||||
* the event is triggered, instead of calling a listener callback.
|
||||
* @returns a Promise that resolves the next time given event is triggered,
|
||||
* or rejects if an error is emitted. (If you request the 'error' event,
|
||||
* returns a promise that resolves with the error).
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* const message = await stream.emitted('message') // rejects if the stream errors
|
||||
*/
|
||||
emitted(event) {
|
||||
return new Promise((resolve, reject) => {
|
||||
__classPrivateFieldSet(this, _MessageStream_catchingPromiseCreated, true, "f");
|
||||
if (event !== 'error')
|
||||
this.once('error', reject);
|
||||
this.once(event, resolve);
|
||||
});
|
||||
}
|
||||
async done() {
|
||||
__classPrivateFieldSet(this, _MessageStream_catchingPromiseCreated, true, "f");
|
||||
await __classPrivateFieldGet(this, _MessageStream_endPromise, "f");
|
||||
}
|
||||
get currentMessage() {
|
||||
return __classPrivateFieldGet(this, _MessageStream_currentMessageSnapshot, "f");
|
||||
}
|
||||
/**
|
||||
* @returns a promise that resolves with the the final assistant Message response,
|
||||
* or rejects if an error occurred or the stream ended prematurely without producing a Message.
|
||||
* If structured outputs were used, this will be a ParsedMessage with a `parsed_output` field.
|
||||
*/
|
||||
async finalMessage() {
|
||||
await this.done();
|
||||
return __classPrivateFieldGet(this, _MessageStream_instances, "m", _MessageStream_getFinalMessage).call(this);
|
||||
}
|
||||
/**
|
||||
* @returns a promise that resolves with the the final assistant Message's text response, concatenated
|
||||
* together if there are more than one text blocks.
|
||||
* Rejects if an error occurred or the stream ended prematurely without producing a Message.
|
||||
*/
|
||||
async finalText() {
|
||||
await this.done();
|
||||
return __classPrivateFieldGet(this, _MessageStream_instances, "m", _MessageStream_getFinalText).call(this);
|
||||
}
|
||||
_emit(event, ...args) {
|
||||
// make sure we don't emit any MessageStreamEvents after end
|
||||
if (__classPrivateFieldGet(this, _MessageStream_ended, "f"))
|
||||
return;
|
||||
if (event === 'end') {
|
||||
__classPrivateFieldSet(this, _MessageStream_ended, true, "f");
|
||||
__classPrivateFieldGet(this, _MessageStream_resolveEndPromise, "f").call(this);
|
||||
}
|
||||
const listeners = __classPrivateFieldGet(this, _MessageStream_listeners, "f")[event];
|
||||
if (listeners) {
|
||||
__classPrivateFieldGet(this, _MessageStream_listeners, "f")[event] = listeners.filter((l) => !l.once);
|
||||
listeners.forEach(({ listener }) => listener(...args));
|
||||
}
|
||||
if (event === 'abort') {
|
||||
const error = args[0];
|
||||
if (!__classPrivateFieldGet(this, _MessageStream_catchingPromiseCreated, "f") && !listeners?.length) {
|
||||
Promise.reject(error);
|
||||
}
|
||||
__classPrivateFieldGet(this, _MessageStream_rejectConnectedPromise, "f").call(this, error);
|
||||
__classPrivateFieldGet(this, _MessageStream_rejectEndPromise, "f").call(this, error);
|
||||
this._emit('end');
|
||||
return;
|
||||
}
|
||||
if (event === 'error') {
|
||||
// NOTE: _emit('error', error) should only be called from #handleError().
|
||||
const error = args[0];
|
||||
if (!__classPrivateFieldGet(this, _MessageStream_catchingPromiseCreated, "f") && !listeners?.length) {
|
||||
// Trigger an unhandled rejection if the user hasn't registered any error handlers.
|
||||
// If you are seeing stack traces here, make sure to handle errors via either:
|
||||
// - runner.on('error', () => ...)
|
||||
// - await runner.done()
|
||||
// - await runner.final...()
|
||||
// - etc.
|
||||
Promise.reject(error);
|
||||
}
|
||||
__classPrivateFieldGet(this, _MessageStream_rejectConnectedPromise, "f").call(this, error);
|
||||
__classPrivateFieldGet(this, _MessageStream_rejectEndPromise, "f").call(this, error);
|
||||
this._emit('end');
|
||||
}
|
||||
}
|
||||
_emitFinal() {
|
||||
const finalMessage = this.receivedMessages.at(-1);
|
||||
if (finalMessage) {
|
||||
this._emit('finalMessage', __classPrivateFieldGet(this, _MessageStream_instances, "m", _MessageStream_getFinalMessage).call(this));
|
||||
}
|
||||
}
|
||||
async _fromReadableStream(readableStream, options) {
|
||||
const signal = options?.signal;
|
||||
let abortHandler;
|
||||
if (signal) {
|
||||
if (signal.aborted)
|
||||
this.controller.abort();
|
||||
abortHandler = this.controller.abort.bind(this.controller);
|
||||
signal.addEventListener('abort', abortHandler);
|
||||
}
|
||||
try {
|
||||
__classPrivateFieldGet(this, _MessageStream_instances, "m", _MessageStream_beginRequest).call(this);
|
||||
this._connected(null);
|
||||
const stream = Stream.fromReadableStream(readableStream, this.controller);
|
||||
for await (const event of stream) {
|
||||
__classPrivateFieldGet(this, _MessageStream_instances, "m", _MessageStream_addStreamEvent).call(this, event);
|
||||
}
|
||||
if (stream.controller.signal?.aborted) {
|
||||
throw new APIUserAbortError();
|
||||
}
|
||||
__classPrivateFieldGet(this, _MessageStream_instances, "m", _MessageStream_endRequest).call(this);
|
||||
}
|
||||
finally {
|
||||
if (signal && abortHandler) {
|
||||
signal.removeEventListener('abort', abortHandler);
|
||||
}
|
||||
}
|
||||
}
|
||||
[(_MessageStream_currentMessageSnapshot = new WeakMap(), _MessageStream_params = new WeakMap(), _MessageStream_connectedPromise = new WeakMap(), _MessageStream_resolveConnectedPromise = new WeakMap(), _MessageStream_rejectConnectedPromise = new WeakMap(), _MessageStream_endPromise = new WeakMap(), _MessageStream_resolveEndPromise = new WeakMap(), _MessageStream_rejectEndPromise = new WeakMap(), _MessageStream_listeners = new WeakMap(), _MessageStream_ended = new WeakMap(), _MessageStream_errored = new WeakMap(), _MessageStream_aborted = new WeakMap(), _MessageStream_catchingPromiseCreated = new WeakMap(), _MessageStream_response = new WeakMap(), _MessageStream_request_id = new WeakMap(), _MessageStream_logger = new WeakMap(), _MessageStream_handleError = new WeakMap(), _MessageStream_instances = new WeakSet(), _MessageStream_getFinalMessage = function _MessageStream_getFinalMessage() {
|
||||
if (this.receivedMessages.length === 0) {
|
||||
throw new AnthropicError('stream ended without producing a Message with role=assistant');
|
||||
}
|
||||
return this.receivedMessages.at(-1);
|
||||
}, _MessageStream_getFinalText = function _MessageStream_getFinalText() {
|
||||
if (this.receivedMessages.length === 0) {
|
||||
throw new AnthropicError('stream ended without producing a Message with role=assistant');
|
||||
}
|
||||
const textBlocks = this.receivedMessages
|
||||
.at(-1)
|
||||
.content.filter((block) => block.type === 'text')
|
||||
.map((block) => block.text);
|
||||
if (textBlocks.length === 0) {
|
||||
throw new AnthropicError('stream ended without producing a content block with type=text');
|
||||
}
|
||||
return textBlocks.join(' ');
|
||||
}, _MessageStream_beginRequest = function _MessageStream_beginRequest() {
|
||||
if (this.ended)
|
||||
return;
|
||||
__classPrivateFieldSet(this, _MessageStream_currentMessageSnapshot, undefined, "f");
|
||||
}, _MessageStream_addStreamEvent = function _MessageStream_addStreamEvent(event) {
|
||||
if (this.ended)
|
||||
return;
|
||||
const messageSnapshot = __classPrivateFieldGet(this, _MessageStream_instances, "m", _MessageStream_accumulateMessage).call(this, event);
|
||||
this._emit('streamEvent', event, messageSnapshot);
|
||||
switch (event.type) {
|
||||
case 'content_block_delta': {
|
||||
const content = messageSnapshot.content.at(-1);
|
||||
switch (event.delta.type) {
|
||||
case 'text_delta': {
|
||||
if (content.type === 'text') {
|
||||
this._emit('text', event.delta.text, content.text || '');
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'citations_delta': {
|
||||
if (content.type === 'text') {
|
||||
this._emit('citation', event.delta.citation, content.citations ?? []);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'input_json_delta': {
|
||||
if (tracksToolInput(content) && content.input) {
|
||||
this._emit('inputJson', event.delta.partial_json, content.input);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'thinking_delta': {
|
||||
if (content.type === 'thinking') {
|
||||
this._emit('thinking', event.delta.thinking, content.thinking);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'signature_delta': {
|
||||
if (content.type === 'thinking') {
|
||||
this._emit('signature', content.signature);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
checkNever(event.delta);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'message_stop': {
|
||||
this._addMessageParam(messageSnapshot);
|
||||
this._addMessage(maybeParseMessage(messageSnapshot, __classPrivateFieldGet(this, _MessageStream_params, "f"), { logger: __classPrivateFieldGet(this, _MessageStream_logger, "f") }), true);
|
||||
break;
|
||||
}
|
||||
case 'content_block_stop': {
|
||||
this._emit('contentBlock', messageSnapshot.content.at(-1));
|
||||
break;
|
||||
}
|
||||
case 'message_start': {
|
||||
__classPrivateFieldSet(this, _MessageStream_currentMessageSnapshot, messageSnapshot, "f");
|
||||
break;
|
||||
}
|
||||
case 'content_block_start':
|
||||
case 'message_delta':
|
||||
break;
|
||||
}
|
||||
}, _MessageStream_endRequest = function _MessageStream_endRequest() {
|
||||
if (this.ended) {
|
||||
throw new AnthropicError(`stream has ended, this shouldn't happen`);
|
||||
}
|
||||
const snapshot = __classPrivateFieldGet(this, _MessageStream_currentMessageSnapshot, "f");
|
||||
if (!snapshot) {
|
||||
throw new AnthropicError(`request ended without sending any chunks`);
|
||||
}
|
||||
__classPrivateFieldSet(this, _MessageStream_currentMessageSnapshot, undefined, "f");
|
||||
return maybeParseMessage(snapshot, __classPrivateFieldGet(this, _MessageStream_params, "f"), { logger: __classPrivateFieldGet(this, _MessageStream_logger, "f") });
|
||||
}, _MessageStream_accumulateMessage = function _MessageStream_accumulateMessage(event) {
|
||||
let snapshot = __classPrivateFieldGet(this, _MessageStream_currentMessageSnapshot, "f");
|
||||
if (event.type === 'message_start') {
|
||||
if (snapshot) {
|
||||
throw new AnthropicError(`Unexpected event order, got ${event.type} before receiving "message_stop"`);
|
||||
}
|
||||
return event.message;
|
||||
}
|
||||
if (!snapshot) {
|
||||
throw new AnthropicError(`Unexpected event order, got ${event.type} before "message_start"`);
|
||||
}
|
||||
switch (event.type) {
|
||||
case 'message_stop':
|
||||
return snapshot;
|
||||
case 'message_delta':
|
||||
snapshot.stop_reason = event.delta.stop_reason;
|
||||
snapshot.stop_sequence = event.delta.stop_sequence;
|
||||
snapshot.usage.output_tokens = event.usage.output_tokens;
|
||||
// Update other usage fields if they exist in the event
|
||||
if (event.usage.input_tokens != null) {
|
||||
snapshot.usage.input_tokens = event.usage.input_tokens;
|
||||
}
|
||||
if (event.usage.cache_creation_input_tokens != null) {
|
||||
snapshot.usage.cache_creation_input_tokens = event.usage.cache_creation_input_tokens;
|
||||
}
|
||||
if (event.usage.cache_read_input_tokens != null) {
|
||||
snapshot.usage.cache_read_input_tokens = event.usage.cache_read_input_tokens;
|
||||
}
|
||||
if (event.usage.server_tool_use != null) {
|
||||
snapshot.usage.server_tool_use = event.usage.server_tool_use;
|
||||
}
|
||||
return snapshot;
|
||||
case 'content_block_start':
|
||||
snapshot.content.push({ ...event.content_block });
|
||||
return snapshot;
|
||||
case 'content_block_delta': {
|
||||
const snapshotContent = snapshot.content.at(event.index);
|
||||
switch (event.delta.type) {
|
||||
case 'text_delta': {
|
||||
if (snapshotContent?.type === 'text') {
|
||||
snapshot.content[event.index] = {
|
||||
...snapshotContent,
|
||||
text: (snapshotContent.text || '') + event.delta.text,
|
||||
};
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'citations_delta': {
|
||||
if (snapshotContent?.type === 'text') {
|
||||
snapshot.content[event.index] = {
|
||||
...snapshotContent,
|
||||
citations: [...(snapshotContent.citations ?? []), event.delta.citation],
|
||||
};
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'input_json_delta': {
|
||||
if (snapshotContent && tracksToolInput(snapshotContent)) {
|
||||
// we need to keep track of the raw JSON string as well so that we can
|
||||
// re-parse it for each delta, for now we just store it as an untyped
|
||||
// non-enumerable property on the snapshot
|
||||
let jsonBuf = snapshotContent[JSON_BUF_PROPERTY] || '';
|
||||
jsonBuf += event.delta.partial_json;
|
||||
const newContent = { ...snapshotContent };
|
||||
Object.defineProperty(newContent, JSON_BUF_PROPERTY, {
|
||||
value: jsonBuf,
|
||||
enumerable: false,
|
||||
writable: true,
|
||||
});
|
||||
if (jsonBuf) {
|
||||
newContent.input = partialParse(jsonBuf);
|
||||
}
|
||||
snapshot.content[event.index] = newContent;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'thinking_delta': {
|
||||
if (snapshotContent?.type === 'thinking') {
|
||||
snapshot.content[event.index] = {
|
||||
...snapshotContent,
|
||||
thinking: snapshotContent.thinking + event.delta.thinking,
|
||||
};
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'signature_delta': {
|
||||
if (snapshotContent?.type === 'thinking') {
|
||||
snapshot.content[event.index] = {
|
||||
...snapshotContent,
|
||||
signature: event.delta.signature,
|
||||
};
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
checkNever(event.delta);
|
||||
}
|
||||
return snapshot;
|
||||
}
|
||||
case 'content_block_stop':
|
||||
return snapshot;
|
||||
}
|
||||
}, Symbol.asyncIterator)]() {
|
||||
const pushQueue = [];
|
||||
const readQueue = [];
|
||||
let done = false;
|
||||
this.on('streamEvent', (event) => {
|
||||
const reader = readQueue.shift();
|
||||
if (reader) {
|
||||
reader.resolve(event);
|
||||
}
|
||||
else {
|
||||
pushQueue.push(event);
|
||||
}
|
||||
});
|
||||
this.on('end', () => {
|
||||
done = true;
|
||||
for (const reader of readQueue) {
|
||||
reader.resolve(undefined);
|
||||
}
|
||||
readQueue.length = 0;
|
||||
});
|
||||
this.on('abort', (err) => {
|
||||
done = true;
|
||||
for (const reader of readQueue) {
|
||||
reader.reject(err);
|
||||
}
|
||||
readQueue.length = 0;
|
||||
});
|
||||
this.on('error', (err) => {
|
||||
done = true;
|
||||
for (const reader of readQueue) {
|
||||
reader.reject(err);
|
||||
}
|
||||
readQueue.length = 0;
|
||||
});
|
||||
return {
|
||||
next: async () => {
|
||||
if (!pushQueue.length) {
|
||||
if (done) {
|
||||
return { value: undefined, done: true };
|
||||
}
|
||||
return new Promise((resolve, reject) => readQueue.push({ resolve, reject })).then((chunk) => (chunk ? { value: chunk, done: false } : { value: undefined, done: true }));
|
||||
}
|
||||
const chunk = pushQueue.shift();
|
||||
return { value: chunk, done: false };
|
||||
},
|
||||
return: async () => {
|
||||
this.abort();
|
||||
return { value: undefined, done: true };
|
||||
},
|
||||
};
|
||||
}
|
||||
toReadableStream() {
|
||||
const stream = new Stream(this[Symbol.asyncIterator].bind(this), this.controller);
|
||||
return stream.toReadableStream();
|
||||
}
|
||||
}
|
||||
// used to ensure exhaustive case matching without throwing a runtime error
|
||||
function checkNever(x) { }
|
||||
//# sourceMappingURL=MessageStream.mjs.map
|
||||
75
claude-code-source/node_modules/@anthropic-ai/sdk/lib/beta-parser.mjs
generated
vendored
75
claude-code-source/node_modules/@anthropic-ai/sdk/lib/beta-parser.mjs
generated
vendored
@@ -1,75 +0,0 @@
|
||||
import { AnthropicError } from "../core/error.mjs";
|
||||
function getOutputFormat(params) {
|
||||
// Prefer output_format (deprecated) over output_config.format for backward compatibility
|
||||
return params?.output_format ?? params?.output_config?.format;
|
||||
}
|
||||
export function maybeParseBetaMessage(message, params, opts) {
|
||||
const outputFormat = getOutputFormat(params);
|
||||
if (!params || !('parse' in (outputFormat ?? {}))) {
|
||||
return {
|
||||
...message,
|
||||
content: message.content.map((block) => {
|
||||
if (block.type === 'text') {
|
||||
const parsedBlock = Object.defineProperty({ ...block }, 'parsed_output', {
|
||||
value: null,
|
||||
enumerable: false,
|
||||
});
|
||||
return Object.defineProperty(parsedBlock, 'parsed', {
|
||||
get() {
|
||||
opts.logger.warn('The `parsed` property on `text` blocks is deprecated, please use `parsed_output` instead.');
|
||||
return null;
|
||||
},
|
||||
enumerable: false,
|
||||
});
|
||||
}
|
||||
return block;
|
||||
}),
|
||||
parsed_output: null,
|
||||
};
|
||||
}
|
||||
return parseBetaMessage(message, params, opts);
|
||||
}
|
||||
export function parseBetaMessage(message, params, opts) {
|
||||
let firstParsedOutput = null;
|
||||
const content = message.content.map((block) => {
|
||||
if (block.type === 'text') {
|
||||
const parsedOutput = parseBetaOutputFormat(params, block.text);
|
||||
if (firstParsedOutput === null) {
|
||||
firstParsedOutput = parsedOutput;
|
||||
}
|
||||
const parsedBlock = Object.defineProperty({ ...block }, 'parsed_output', {
|
||||
value: parsedOutput,
|
||||
enumerable: false,
|
||||
});
|
||||
return Object.defineProperty(parsedBlock, 'parsed', {
|
||||
get() {
|
||||
opts.logger.warn('The `parsed` property on `text` blocks is deprecated, please use `parsed_output` instead.');
|
||||
return parsedOutput;
|
||||
},
|
||||
enumerable: false,
|
||||
});
|
||||
}
|
||||
return block;
|
||||
});
|
||||
return {
|
||||
...message,
|
||||
content,
|
||||
parsed_output: firstParsedOutput,
|
||||
};
|
||||
}
|
||||
function parseBetaOutputFormat(params, content) {
|
||||
const outputFormat = getOutputFormat(params);
|
||||
if (outputFormat?.type !== 'json_schema') {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
if ('parse' in outputFormat) {
|
||||
return outputFormat.parse(content);
|
||||
}
|
||||
return JSON.parse(content);
|
||||
}
|
||||
catch (error) {
|
||||
throw new AnthropicError(`Failed to parse structured output: ${error}`);
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=beta-parser.mjs.map
|
||||
62
claude-code-source/node_modules/@anthropic-ai/sdk/lib/parser.mjs
generated
vendored
62
claude-code-source/node_modules/@anthropic-ai/sdk/lib/parser.mjs
generated
vendored
@@ -1,62 +0,0 @@
|
||||
import { AnthropicError } from "../core/error.mjs";
|
||||
function getOutputFormat(params) {
|
||||
return params?.output_config?.format;
|
||||
}
|
||||
export function maybeParseMessage(message, params, opts) {
|
||||
const outputFormat = getOutputFormat(params);
|
||||
if (!params || !('parse' in (outputFormat ?? {}))) {
|
||||
return {
|
||||
...message,
|
||||
content: message.content.map((block) => {
|
||||
if (block.type === 'text') {
|
||||
const parsedBlock = Object.defineProperty({ ...block }, 'parsed_output', {
|
||||
value: null,
|
||||
enumerable: false,
|
||||
});
|
||||
return parsedBlock;
|
||||
}
|
||||
return block;
|
||||
}),
|
||||
parsed_output: null,
|
||||
};
|
||||
}
|
||||
return parseMessage(message, params, opts);
|
||||
}
|
||||
export function parseMessage(message, params, opts) {
|
||||
let firstParsedOutput = null;
|
||||
const content = message.content.map((block) => {
|
||||
if (block.type === 'text') {
|
||||
const parsedOutput = parseOutputFormat(params, block.text);
|
||||
if (firstParsedOutput === null) {
|
||||
firstParsedOutput = parsedOutput;
|
||||
}
|
||||
const parsedBlock = Object.defineProperty({ ...block }, 'parsed_output', {
|
||||
value: parsedOutput,
|
||||
enumerable: false,
|
||||
});
|
||||
return parsedBlock;
|
||||
}
|
||||
return block;
|
||||
});
|
||||
return {
|
||||
...message,
|
||||
content,
|
||||
parsed_output: firstParsedOutput,
|
||||
};
|
||||
}
|
||||
function parseOutputFormat(params, content) {
|
||||
const outputFormat = getOutputFormat(params);
|
||||
if (outputFormat?.type !== 'json_schema') {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
if ('parse' in outputFormat) {
|
||||
return outputFormat.parse(content);
|
||||
}
|
||||
return JSON.parse(content);
|
||||
}
|
||||
catch (error) {
|
||||
throw new AnthropicError(`Failed to parse structured output: ${error}`);
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=parser.mjs.map
|
||||
63
claude-code-source/node_modules/@anthropic-ai/sdk/lib/stainless-helper-header.mjs
generated
vendored
63
claude-code-source/node_modules/@anthropic-ai/sdk/lib/stainless-helper-header.mjs
generated
vendored
@@ -1,63 +0,0 @@
|
||||
/**
|
||||
* Shared utilities for tracking SDK helper usage.
|
||||
*/
|
||||
/**
|
||||
* Symbol used to mark objects created by SDK helpers for tracking.
|
||||
* The value is the helper name (e.g., 'mcpTool', 'betaZodTool').
|
||||
*/
|
||||
export const SDK_HELPER_SYMBOL = Symbol('anthropic.sdk.stainlessHelper');
|
||||
export function wasCreatedByStainlessHelper(value) {
|
||||
return typeof value === 'object' && value !== null && SDK_HELPER_SYMBOL in value;
|
||||
}
|
||||
/**
|
||||
* Collects helper names from tools and messages arrays.
|
||||
* Returns a deduplicated array of helper names found.
|
||||
*/
|
||||
export function collectStainlessHelpers(tools, messages) {
|
||||
const helpers = new Set();
|
||||
// Collect from tools
|
||||
if (tools) {
|
||||
for (const tool of tools) {
|
||||
if (wasCreatedByStainlessHelper(tool)) {
|
||||
helpers.add(tool[SDK_HELPER_SYMBOL]);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Collect from messages and their content blocks
|
||||
if (messages) {
|
||||
for (const message of messages) {
|
||||
if (wasCreatedByStainlessHelper(message)) {
|
||||
helpers.add(message[SDK_HELPER_SYMBOL]);
|
||||
}
|
||||
if (Array.isArray(message.content)) {
|
||||
for (const block of message.content) {
|
||||
if (wasCreatedByStainlessHelper(block)) {
|
||||
helpers.add(block[SDK_HELPER_SYMBOL]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return Array.from(helpers);
|
||||
}
|
||||
/**
|
||||
* Builds x-stainless-helper header value from tools and messages.
|
||||
* Returns an empty object if no helpers are found.
|
||||
*/
|
||||
export function stainlessHelperHeader(tools, messages) {
|
||||
const helpers = collectStainlessHelpers(tools, messages);
|
||||
if (helpers.length === 0)
|
||||
return {};
|
||||
return { 'x-stainless-helper': helpers.join(', ') };
|
||||
}
|
||||
/**
|
||||
* Builds x-stainless-helper header value from a file object.
|
||||
* Returns an empty object if the file is not marked with a helper.
|
||||
*/
|
||||
export function stainlessHelperHeaderFromFile(file) {
|
||||
if (wasCreatedByStainlessHelper(file)) {
|
||||
return { 'x-stainless-helper': file[SDK_HELPER_SYMBOL] };
|
||||
}
|
||||
return {};
|
||||
}
|
||||
//# sourceMappingURL=stainless-helper-header.mjs.map
|
||||
372
claude-code-source/node_modules/@anthropic-ai/sdk/lib/tools/BetaToolRunner.mjs
generated
vendored
372
claude-code-source/node_modules/@anthropic-ai/sdk/lib/tools/BetaToolRunner.mjs
generated
vendored
@@ -1,372 +0,0 @@
|
||||
var _BetaToolRunner_instances, _BetaToolRunner_consumed, _BetaToolRunner_mutated, _BetaToolRunner_state, _BetaToolRunner_options, _BetaToolRunner_message, _BetaToolRunner_toolResponse, _BetaToolRunner_completion, _BetaToolRunner_iterationCount, _BetaToolRunner_checkAndCompact, _BetaToolRunner_generateToolResponse;
|
||||
import { __classPrivateFieldGet, __classPrivateFieldSet } from "../../internal/tslib.mjs";
|
||||
import { ToolError } from "./ToolError.mjs";
|
||||
import { AnthropicError } from "../../core/error.mjs";
|
||||
import { buildHeaders } from "../../internal/headers.mjs";
|
||||
import { DEFAULT_SUMMARY_PROMPT, DEFAULT_TOKEN_THRESHOLD } from "./CompactionControl.mjs";
|
||||
import { collectStainlessHelpers } from "../stainless-helper-header.mjs";
|
||||
/**
|
||||
* Just Promise.withResolvers(), which is not available in all environments.
|
||||
*/
|
||||
function promiseWithResolvers() {
|
||||
let resolve;
|
||||
let reject;
|
||||
const promise = new Promise((res, rej) => {
|
||||
resolve = res;
|
||||
reject = rej;
|
||||
});
|
||||
return { promise, resolve: resolve, reject: reject };
|
||||
}
|
||||
/**
|
||||
* A ToolRunner handles the automatic conversation loop between the assistant and tools.
|
||||
*
|
||||
* A ToolRunner is an async iterable that yields either BetaMessage or BetaMessageStream objects
|
||||
* depending on the streaming configuration.
|
||||
*/
|
||||
export class BetaToolRunner {
|
||||
constructor(client, params, options) {
|
||||
_BetaToolRunner_instances.add(this);
|
||||
this.client = client;
|
||||
/** Whether the async iterator has been consumed */
|
||||
_BetaToolRunner_consumed.set(this, false);
|
||||
/** Whether parameters have been mutated since the last API call */
|
||||
_BetaToolRunner_mutated.set(this, false);
|
||||
/** Current state containing the request parameters */
|
||||
_BetaToolRunner_state.set(this, void 0);
|
||||
_BetaToolRunner_options.set(this, void 0);
|
||||
/** Promise for the last message received from the assistant */
|
||||
_BetaToolRunner_message.set(this, void 0);
|
||||
/** Cached tool response to avoid redundant executions */
|
||||
_BetaToolRunner_toolResponse.set(this, void 0);
|
||||
/** Promise resolvers for waiting on completion */
|
||||
_BetaToolRunner_completion.set(this, void 0);
|
||||
/** Number of iterations (API requests) made so far */
|
||||
_BetaToolRunner_iterationCount.set(this, 0);
|
||||
__classPrivateFieldSet(this, _BetaToolRunner_state, {
|
||||
params: {
|
||||
// You can't clone the entire params since there are functions as handlers.
|
||||
// You also don't really need to clone params.messages, but it probably will prevent a foot gun
|
||||
// somewhere.
|
||||
...params,
|
||||
messages: structuredClone(params.messages),
|
||||
},
|
||||
}, "f");
|
||||
const helpers = collectStainlessHelpers(params.tools, params.messages);
|
||||
const helperValue = ['BetaToolRunner', ...helpers].join(', ');
|
||||
__classPrivateFieldSet(this, _BetaToolRunner_options, {
|
||||
...options,
|
||||
headers: buildHeaders([{ 'x-stainless-helper': helperValue }, options?.headers]),
|
||||
}, "f");
|
||||
__classPrivateFieldSet(this, _BetaToolRunner_completion, promiseWithResolvers(), "f");
|
||||
}
|
||||
async *[(_BetaToolRunner_consumed = new WeakMap(), _BetaToolRunner_mutated = new WeakMap(), _BetaToolRunner_state = new WeakMap(), _BetaToolRunner_options = new WeakMap(), _BetaToolRunner_message = new WeakMap(), _BetaToolRunner_toolResponse = new WeakMap(), _BetaToolRunner_completion = new WeakMap(), _BetaToolRunner_iterationCount = new WeakMap(), _BetaToolRunner_instances = new WeakSet(), _BetaToolRunner_checkAndCompact = async function _BetaToolRunner_checkAndCompact() {
|
||||
const compactionControl = __classPrivateFieldGet(this, _BetaToolRunner_state, "f").params.compactionControl;
|
||||
if (!compactionControl || !compactionControl.enabled) {
|
||||
return false;
|
||||
}
|
||||
let tokensUsed = 0;
|
||||
if (__classPrivateFieldGet(this, _BetaToolRunner_message, "f") !== undefined) {
|
||||
try {
|
||||
const message = await __classPrivateFieldGet(this, _BetaToolRunner_message, "f");
|
||||
const totalInputTokens = message.usage.input_tokens +
|
||||
(message.usage.cache_creation_input_tokens ?? 0) +
|
||||
(message.usage.cache_read_input_tokens ?? 0);
|
||||
tokensUsed = totalInputTokens + message.usage.output_tokens;
|
||||
}
|
||||
catch {
|
||||
// If we can't get the message, skip compaction
|
||||
return false;
|
||||
}
|
||||
}
|
||||
const threshold = compactionControl.contextTokenThreshold ?? DEFAULT_TOKEN_THRESHOLD;
|
||||
if (tokensUsed < threshold) {
|
||||
return false;
|
||||
}
|
||||
const model = compactionControl.model ?? __classPrivateFieldGet(this, _BetaToolRunner_state, "f").params.model;
|
||||
const summaryPrompt = compactionControl.summaryPrompt ?? DEFAULT_SUMMARY_PROMPT;
|
||||
const messages = __classPrivateFieldGet(this, _BetaToolRunner_state, "f").params.messages;
|
||||
if (messages[messages.length - 1].role === 'assistant') {
|
||||
// Remove tool_use blocks from the last message to avoid 400 error
|
||||
// (tool_use requires tool_result, which we don't have yet)
|
||||
const lastMessage = messages[messages.length - 1];
|
||||
if (Array.isArray(lastMessage.content)) {
|
||||
const nonToolBlocks = lastMessage.content.filter((block) => block.type !== 'tool_use');
|
||||
if (nonToolBlocks.length === 0) {
|
||||
// If all blocks were tool_use, just remove the message entirely
|
||||
messages.pop();
|
||||
}
|
||||
else {
|
||||
lastMessage.content = nonToolBlocks;
|
||||
}
|
||||
}
|
||||
}
|
||||
const response = await this.client.beta.messages.create({
|
||||
model,
|
||||
messages: [
|
||||
...messages,
|
||||
{
|
||||
role: 'user',
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: summaryPrompt,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
max_tokens: __classPrivateFieldGet(this, _BetaToolRunner_state, "f").params.max_tokens,
|
||||
}, {
|
||||
headers: { 'x-stainless-helper': 'compaction' },
|
||||
});
|
||||
if (response.content[0]?.type !== 'text') {
|
||||
throw new AnthropicError('Expected text response for compaction');
|
||||
}
|
||||
__classPrivateFieldGet(this, _BetaToolRunner_state, "f").params.messages = [
|
||||
{
|
||||
role: 'user',
|
||||
content: response.content,
|
||||
},
|
||||
];
|
||||
return true;
|
||||
}, Symbol.asyncIterator)]() {
|
||||
var _a;
|
||||
if (__classPrivateFieldGet(this, _BetaToolRunner_consumed, "f")) {
|
||||
throw new AnthropicError('Cannot iterate over a consumed stream');
|
||||
}
|
||||
__classPrivateFieldSet(this, _BetaToolRunner_consumed, true, "f");
|
||||
__classPrivateFieldSet(this, _BetaToolRunner_mutated, true, "f");
|
||||
__classPrivateFieldSet(this, _BetaToolRunner_toolResponse, undefined, "f");
|
||||
try {
|
||||
while (true) {
|
||||
let stream;
|
||||
try {
|
||||
if (__classPrivateFieldGet(this, _BetaToolRunner_state, "f").params.max_iterations &&
|
||||
__classPrivateFieldGet(this, _BetaToolRunner_iterationCount, "f") >= __classPrivateFieldGet(this, _BetaToolRunner_state, "f").params.max_iterations) {
|
||||
break;
|
||||
}
|
||||
__classPrivateFieldSet(this, _BetaToolRunner_mutated, false, "f");
|
||||
__classPrivateFieldSet(this, _BetaToolRunner_toolResponse, undefined, "f");
|
||||
__classPrivateFieldSet(this, _BetaToolRunner_iterationCount, (_a = __classPrivateFieldGet(this, _BetaToolRunner_iterationCount, "f"), _a++, _a), "f");
|
||||
__classPrivateFieldSet(this, _BetaToolRunner_message, undefined, "f");
|
||||
const { max_iterations, compactionControl, ...params } = __classPrivateFieldGet(this, _BetaToolRunner_state, "f").params;
|
||||
if (params.stream) {
|
||||
stream = this.client.beta.messages.stream({ ...params }, __classPrivateFieldGet(this, _BetaToolRunner_options, "f"));
|
||||
__classPrivateFieldSet(this, _BetaToolRunner_message, stream.finalMessage(), "f");
|
||||
// Make sure that this promise doesn't throw before we get the option to do something about it.
|
||||
// Error will be caught when we call await this.#message ultimately
|
||||
__classPrivateFieldGet(this, _BetaToolRunner_message, "f").catch(() => { });
|
||||
yield stream;
|
||||
}
|
||||
else {
|
||||
__classPrivateFieldSet(this, _BetaToolRunner_message, this.client.beta.messages.create({ ...params, stream: false }, __classPrivateFieldGet(this, _BetaToolRunner_options, "f")), "f");
|
||||
yield __classPrivateFieldGet(this, _BetaToolRunner_message, "f");
|
||||
}
|
||||
const isCompacted = await __classPrivateFieldGet(this, _BetaToolRunner_instances, "m", _BetaToolRunner_checkAndCompact).call(this);
|
||||
if (!isCompacted) {
|
||||
if (!__classPrivateFieldGet(this, _BetaToolRunner_mutated, "f")) {
|
||||
const { role, content } = await __classPrivateFieldGet(this, _BetaToolRunner_message, "f");
|
||||
__classPrivateFieldGet(this, _BetaToolRunner_state, "f").params.messages.push({ role, content });
|
||||
}
|
||||
const toolMessage = await __classPrivateFieldGet(this, _BetaToolRunner_instances, "m", _BetaToolRunner_generateToolResponse).call(this, __classPrivateFieldGet(this, _BetaToolRunner_state, "f").params.messages.at(-1));
|
||||
if (toolMessage) {
|
||||
__classPrivateFieldGet(this, _BetaToolRunner_state, "f").params.messages.push(toolMessage);
|
||||
}
|
||||
else if (!__classPrivateFieldGet(this, _BetaToolRunner_mutated, "f")) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (stream) {
|
||||
stream.abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!__classPrivateFieldGet(this, _BetaToolRunner_message, "f")) {
|
||||
throw new AnthropicError('ToolRunner concluded without a message from the server');
|
||||
}
|
||||
__classPrivateFieldGet(this, _BetaToolRunner_completion, "f").resolve(await __classPrivateFieldGet(this, _BetaToolRunner_message, "f"));
|
||||
}
|
||||
catch (error) {
|
||||
__classPrivateFieldSet(this, _BetaToolRunner_consumed, false, "f");
|
||||
// Silence unhandled promise errors
|
||||
__classPrivateFieldGet(this, _BetaToolRunner_completion, "f").promise.catch(() => { });
|
||||
__classPrivateFieldGet(this, _BetaToolRunner_completion, "f").reject(error);
|
||||
__classPrivateFieldSet(this, _BetaToolRunner_completion, promiseWithResolvers(), "f");
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
setMessagesParams(paramsOrMutator) {
|
||||
if (typeof paramsOrMutator === 'function') {
|
||||
__classPrivateFieldGet(this, _BetaToolRunner_state, "f").params = paramsOrMutator(__classPrivateFieldGet(this, _BetaToolRunner_state, "f").params);
|
||||
}
|
||||
else {
|
||||
__classPrivateFieldGet(this, _BetaToolRunner_state, "f").params = paramsOrMutator;
|
||||
}
|
||||
__classPrivateFieldSet(this, _BetaToolRunner_mutated, true, "f");
|
||||
// Invalidate cached tool response since parameters changed
|
||||
__classPrivateFieldSet(this, _BetaToolRunner_toolResponse, undefined, "f");
|
||||
}
|
||||
/**
|
||||
* Get the tool response for the last message from the assistant.
|
||||
* Avoids redundant tool executions by caching results.
|
||||
*
|
||||
* @returns A promise that resolves to a BetaMessageParam containing tool results, or null if no tools need to be executed
|
||||
*
|
||||
* @example
|
||||
* const toolResponse = await runner.generateToolResponse();
|
||||
* if (toolResponse) {
|
||||
* console.log('Tool results:', toolResponse.content);
|
||||
* }
|
||||
*/
|
||||
async generateToolResponse() {
|
||||
const message = (await __classPrivateFieldGet(this, _BetaToolRunner_message, "f")) ?? this.params.messages.at(-1);
|
||||
if (!message) {
|
||||
return null;
|
||||
}
|
||||
return __classPrivateFieldGet(this, _BetaToolRunner_instances, "m", _BetaToolRunner_generateToolResponse).call(this, message);
|
||||
}
|
||||
/**
|
||||
* Wait for the async iterator to complete. This works even if the async iterator hasn't yet started, and
|
||||
* will wait for an instance to start and go to completion.
|
||||
*
|
||||
* @returns A promise that resolves to the final BetaMessage when the iterator completes
|
||||
*
|
||||
* @example
|
||||
* // Start consuming the iterator
|
||||
* for await (const message of runner) {
|
||||
* console.log('Message:', message.content);
|
||||
* }
|
||||
*
|
||||
* // Meanwhile, wait for completion from another part of the code
|
||||
* const finalMessage = await runner.done();
|
||||
* console.log('Final response:', finalMessage.content);
|
||||
*/
|
||||
done() {
|
||||
return __classPrivateFieldGet(this, _BetaToolRunner_completion, "f").promise;
|
||||
}
|
||||
/**
|
||||
* Returns a promise indicating that the stream is done. Unlike .done(), this will eagerly read the stream:
|
||||
* * If the iterator has not been consumed, consume the entire iterator and return the final message from the
|
||||
* assistant.
|
||||
* * If the iterator has been consumed, waits for it to complete and returns the final message.
|
||||
*
|
||||
* @returns A promise that resolves to the final BetaMessage from the conversation
|
||||
* @throws {AnthropicError} If no messages were processed during the conversation
|
||||
*
|
||||
* @example
|
||||
* const finalMessage = await runner.runUntilDone();
|
||||
* console.log('Final response:', finalMessage.content);
|
||||
*/
|
||||
async runUntilDone() {
|
||||
// If not yet consumed, start consuming and wait for completion
|
||||
if (!__classPrivateFieldGet(this, _BetaToolRunner_consumed, "f")) {
|
||||
for await (const _ of this) {
|
||||
// Iterator naturally populates this.#message
|
||||
}
|
||||
}
|
||||
// If consumed but not completed, wait for completion
|
||||
return this.done();
|
||||
}
|
||||
/**
|
||||
* Get the current parameters being used by the ToolRunner.
|
||||
*
|
||||
* @returns A readonly view of the current ToolRunnerParams
|
||||
*
|
||||
* @example
|
||||
* const currentParams = runner.params;
|
||||
* console.log('Current model:', currentParams.model);
|
||||
* console.log('Message count:', currentParams.messages.length);
|
||||
*/
|
||||
get params() {
|
||||
return __classPrivateFieldGet(this, _BetaToolRunner_state, "f").params;
|
||||
}
|
||||
/**
|
||||
* Add one or more messages to the conversation history.
|
||||
*
|
||||
* @param messages - One or more BetaMessageParam objects to add to the conversation
|
||||
*
|
||||
* @example
|
||||
* runner.pushMessages(
|
||||
* { role: 'user', content: 'Also, what about the weather in NYC?' }
|
||||
* );
|
||||
*
|
||||
* @example
|
||||
* // Adding multiple messages
|
||||
* runner.pushMessages(
|
||||
* { role: 'user', content: 'What about NYC?' },
|
||||
* { role: 'user', content: 'And Boston?' }
|
||||
* );
|
||||
*/
|
||||
pushMessages(...messages) {
|
||||
this.setMessagesParams((params) => ({
|
||||
...params,
|
||||
messages: [...params.messages, ...messages],
|
||||
}));
|
||||
}
|
||||
/**
|
||||
* Makes the ToolRunner directly awaitable, equivalent to calling .runUntilDone()
|
||||
* This allows using `await runner` instead of `await runner.runUntilDone()`
|
||||
*/
|
||||
then(onfulfilled, onrejected) {
|
||||
return this.runUntilDone().then(onfulfilled, onrejected);
|
||||
}
|
||||
}
|
||||
_BetaToolRunner_generateToolResponse = async function _BetaToolRunner_generateToolResponse(lastMessage) {
|
||||
if (__classPrivateFieldGet(this, _BetaToolRunner_toolResponse, "f") !== undefined) {
|
||||
return __classPrivateFieldGet(this, _BetaToolRunner_toolResponse, "f");
|
||||
}
|
||||
__classPrivateFieldSet(this, _BetaToolRunner_toolResponse, generateToolResponse(__classPrivateFieldGet(this, _BetaToolRunner_state, "f").params, lastMessage), "f");
|
||||
return __classPrivateFieldGet(this, _BetaToolRunner_toolResponse, "f");
|
||||
};
|
||||
async function generateToolResponse(params, lastMessage = params.messages.at(-1)) {
|
||||
// Only process if the last message is from the assistant and has tool use blocks
|
||||
if (!lastMessage ||
|
||||
lastMessage.role !== 'assistant' ||
|
||||
!lastMessage.content ||
|
||||
typeof lastMessage.content === 'string') {
|
||||
return null;
|
||||
}
|
||||
const toolUseBlocks = lastMessage.content.filter((content) => content.type === 'tool_use');
|
||||
if (toolUseBlocks.length === 0) {
|
||||
return null;
|
||||
}
|
||||
const toolResults = await Promise.all(toolUseBlocks.map(async (toolUse) => {
|
||||
const tool = params.tools.find((t) => ('name' in t ? t.name : t.mcp_server_name) === toolUse.name);
|
||||
if (!tool || !('run' in tool)) {
|
||||
return {
|
||||
type: 'tool_result',
|
||||
tool_use_id: toolUse.id,
|
||||
content: `Error: Tool '${toolUse.name}' not found`,
|
||||
is_error: true,
|
||||
};
|
||||
}
|
||||
try {
|
||||
let input = toolUse.input;
|
||||
if ('parse' in tool && tool.parse) {
|
||||
input = tool.parse(input);
|
||||
}
|
||||
const result = await tool.run(input);
|
||||
return {
|
||||
type: 'tool_result',
|
||||
tool_use_id: toolUse.id,
|
||||
content: result,
|
||||
};
|
||||
}
|
||||
catch (error) {
|
||||
return {
|
||||
type: 'tool_result',
|
||||
tool_use_id: toolUse.id,
|
||||
content: error instanceof ToolError ?
|
||||
error.content
|
||||
: `Error: ${error instanceof Error ? error.message : String(error)}`,
|
||||
is_error: true,
|
||||
};
|
||||
}
|
||||
}));
|
||||
return {
|
||||
role: 'user',
|
||||
content: toolResults,
|
||||
};
|
||||
}
|
||||
//# sourceMappingURL=BetaToolRunner.mjs.map
|
||||
25
claude-code-source/node_modules/@anthropic-ai/sdk/lib/tools/CompactionControl.mjs
generated
vendored
25
claude-code-source/node_modules/@anthropic-ai/sdk/lib/tools/CompactionControl.mjs
generated
vendored
@@ -1,25 +0,0 @@
|
||||
export const DEFAULT_TOKEN_THRESHOLD = 100000;
|
||||
export const DEFAULT_SUMMARY_PROMPT = `You have been working on the task described above but have not yet completed it. Write a continuation summary that will allow you (or another instance of yourself) to resume work efficiently in a future context window where the conversation history will be replaced with this summary. Your summary should be structured, concise, and actionable. Include:
|
||||
1. Task Overview
|
||||
The user's core request and success criteria
|
||||
Any clarifications or constraints they specified
|
||||
2. Current State
|
||||
What has been completed so far
|
||||
Files created, modified, or analyzed (with paths if relevant)
|
||||
Key outputs or artifacts produced
|
||||
3. Important Discoveries
|
||||
Technical constraints or requirements uncovered
|
||||
Decisions made and their rationale
|
||||
Errors encountered and how they were resolved
|
||||
What approaches were tried that didn't work (and why)
|
||||
4. Next Steps
|
||||
Specific actions needed to complete the task
|
||||
Any blockers or open questions to resolve
|
||||
Priority order if multiple steps remain
|
||||
5. Context to Preserve
|
||||
User preferences or style requirements
|
||||
Domain-specific details that aren't obvious
|
||||
Any promises made to the user
|
||||
Be concise but complete—err on the side of including information that would prevent duplicate work or repeated mistakes. Write in a way that enables immediate resumption of the task.
|
||||
Wrap your summary in <summary></summary> tags.`;
|
||||
//# sourceMappingURL=CompactionControl.mjs.map
|
||||
38
claude-code-source/node_modules/@anthropic-ai/sdk/lib/tools/ToolError.mjs
generated
vendored
38
claude-code-source/node_modules/@anthropic-ai/sdk/lib/tools/ToolError.mjs
generated
vendored
@@ -1,38 +0,0 @@
|
||||
/**
|
||||
* An error that can be thrown from a tool's `run` method to return structured
|
||||
* content blocks as the error result, rather than just a string message.
|
||||
*
|
||||
* When the ToolRunner catches this error, it will use the `content` property
|
||||
* as the tool result with `is_error: true`.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const tool = {
|
||||
* name: 'my_tool',
|
||||
* run: async (input) => {
|
||||
* if (somethingWentWrong) {
|
||||
* throw new ToolError([
|
||||
* { type: 'text', text: 'Error details here' },
|
||||
* { type: 'image', source: { type: 'base64', data: '...', media_type: 'image/png' } },
|
||||
* ]);
|
||||
* }
|
||||
* return 'success';
|
||||
* },
|
||||
* };
|
||||
* ```
|
||||
*/
|
||||
export class ToolError extends Error {
|
||||
constructor(content) {
|
||||
const message = typeof content === 'string' ? content : (content
|
||||
.map((block) => {
|
||||
if (block.type === 'text')
|
||||
return block.text;
|
||||
return `[${block.type}]`;
|
||||
})
|
||||
.join(' '));
|
||||
super(message);
|
||||
this.name = 'ToolError';
|
||||
this.content = content;
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=ToolError.mjs.map
|
||||
24
claude-code-source/node_modules/@anthropic-ai/sdk/resources/beta/beta.mjs
generated
vendored
24
claude-code-source/node_modules/@anthropic-ai/sdk/resources/beta/beta.mjs
generated
vendored
@@ -1,24 +0,0 @@
|
||||
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
||||
import { APIResource } from "../../core/resource.mjs";
|
||||
import * as FilesAPI from "./files.mjs";
|
||||
import { Files, } from "./files.mjs";
|
||||
import * as ModelsAPI from "./models.mjs";
|
||||
import { Models } from "./models.mjs";
|
||||
import * as MessagesAPI from "./messages/messages.mjs";
|
||||
import { Messages, } from "./messages/messages.mjs";
|
||||
import * as SkillsAPI from "./skills/skills.mjs";
|
||||
import { Skills, } from "./skills/skills.mjs";
|
||||
export class Beta extends APIResource {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this.models = new ModelsAPI.Models(this._client);
|
||||
this.messages = new MessagesAPI.Messages(this._client);
|
||||
this.files = new FilesAPI.Files(this._client);
|
||||
this.skills = new SkillsAPI.Skills(this._client);
|
||||
}
|
||||
}
|
||||
Beta.Models = Models;
|
||||
Beta.Messages = Messages;
|
||||
Beta.Files = Files;
|
||||
Beta.Skills = Skills;
|
||||
//# sourceMappingURL=beta.mjs.map
|
||||
120
claude-code-source/node_modules/@anthropic-ai/sdk/resources/beta/files.mjs
generated
vendored
120
claude-code-source/node_modules/@anthropic-ai/sdk/resources/beta/files.mjs
generated
vendored
@@ -1,120 +0,0 @@
|
||||
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
||||
import { APIResource } from "../../core/resource.mjs";
|
||||
import { Page } from "../../core/pagination.mjs";
|
||||
import { buildHeaders } from "../../internal/headers.mjs";
|
||||
import { stainlessHelperHeaderFromFile } from "../../lib/stainless-helper-header.mjs";
|
||||
import { multipartFormRequestOptions } from "../../internal/uploads.mjs";
|
||||
import { path } from "../../internal/utils/path.mjs";
|
||||
export class Files extends APIResource {
|
||||
/**
|
||||
* List Files
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* // Automatically fetches more pages as needed.
|
||||
* for await (const fileMetadata of client.beta.files.list()) {
|
||||
* // ...
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
list(params = {}, options) {
|
||||
const { betas, ...query } = params ?? {};
|
||||
return this._client.getAPIList('/v1/files', (Page), {
|
||||
query,
|
||||
...options,
|
||||
headers: buildHeaders([
|
||||
{ 'anthropic-beta': [...(betas ?? []), 'files-api-2025-04-14'].toString() },
|
||||
options?.headers,
|
||||
]),
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Delete File
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const deletedFile = await client.beta.files.delete(
|
||||
* 'file_id',
|
||||
* );
|
||||
* ```
|
||||
*/
|
||||
delete(fileID, params = {}, options) {
|
||||
const { betas } = params ?? {};
|
||||
return this._client.delete(path `/v1/files/${fileID}`, {
|
||||
...options,
|
||||
headers: buildHeaders([
|
||||
{ 'anthropic-beta': [...(betas ?? []), 'files-api-2025-04-14'].toString() },
|
||||
options?.headers,
|
||||
]),
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Download File
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const response = await client.beta.files.download(
|
||||
* 'file_id',
|
||||
* );
|
||||
*
|
||||
* const content = await response.blob();
|
||||
* console.log(content);
|
||||
* ```
|
||||
*/
|
||||
download(fileID, params = {}, options) {
|
||||
const { betas } = params ?? {};
|
||||
return this._client.get(path `/v1/files/${fileID}/content`, {
|
||||
...options,
|
||||
headers: buildHeaders([
|
||||
{
|
||||
'anthropic-beta': [...(betas ?? []), 'files-api-2025-04-14'].toString(),
|
||||
Accept: 'application/binary',
|
||||
},
|
||||
options?.headers,
|
||||
]),
|
||||
__binaryResponse: true,
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Get File Metadata
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const fileMetadata =
|
||||
* await client.beta.files.retrieveMetadata('file_id');
|
||||
* ```
|
||||
*/
|
||||
retrieveMetadata(fileID, params = {}, options) {
|
||||
const { betas } = params ?? {};
|
||||
return this._client.get(path `/v1/files/${fileID}`, {
|
||||
...options,
|
||||
headers: buildHeaders([
|
||||
{ 'anthropic-beta': [...(betas ?? []), 'files-api-2025-04-14'].toString() },
|
||||
options?.headers,
|
||||
]),
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Upload File
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const fileMetadata = await client.beta.files.upload({
|
||||
* file: fs.createReadStream('path/to/file'),
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
upload(params, options) {
|
||||
const { betas, ...body } = params;
|
||||
return this._client.post('/v1/files', multipartFormRequestOptions({
|
||||
body,
|
||||
...options,
|
||||
headers: buildHeaders([
|
||||
{ 'anthropic-beta': [...(betas ?? []), 'files-api-2025-04-14'].toString() },
|
||||
stainlessHelperHeaderFromFile(body.file),
|
||||
options?.headers,
|
||||
]),
|
||||
}, this._client));
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=files.mjs.map
|
||||
200
claude-code-source/node_modules/@anthropic-ai/sdk/resources/beta/messages/batches.mjs
generated
vendored
200
claude-code-source/node_modules/@anthropic-ai/sdk/resources/beta/messages/batches.mjs
generated
vendored
@@ -1,200 +0,0 @@
|
||||
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
||||
import { APIResource } from "../../../core/resource.mjs";
|
||||
import { Page } from "../../../core/pagination.mjs";
|
||||
import { buildHeaders } from "../../../internal/headers.mjs";
|
||||
import { JSONLDecoder } from "../../../internal/decoders/jsonl.mjs";
|
||||
import { AnthropicError } from "../../../error.mjs";
|
||||
import { path } from "../../../internal/utils/path.mjs";
|
||||
export class Batches extends APIResource {
|
||||
/**
|
||||
* Send a batch of Message creation requests.
|
||||
*
|
||||
* The Message Batches API can be used to process multiple Messages API requests at
|
||||
* once. Once a Message Batch is created, it begins processing immediately. Batches
|
||||
* can take up to 24 hours to complete.
|
||||
*
|
||||
* Learn more about the Message Batches API in our
|
||||
* [user guide](https://docs.claude.com/en/docs/build-with-claude/batch-processing)
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const betaMessageBatch =
|
||||
* await client.beta.messages.batches.create({
|
||||
* requests: [
|
||||
* {
|
||||
* custom_id: 'my-custom-id-1',
|
||||
* params: {
|
||||
* max_tokens: 1024,
|
||||
* messages: [
|
||||
* { content: 'Hello, world', role: 'user' },
|
||||
* ],
|
||||
* model: 'claude-opus-4-6',
|
||||
* },
|
||||
* },
|
||||
* ],
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
create(params, options) {
|
||||
const { betas, ...body } = params;
|
||||
return this._client.post('/v1/messages/batches?beta=true', {
|
||||
body,
|
||||
...options,
|
||||
headers: buildHeaders([
|
||||
{ 'anthropic-beta': [...(betas ?? []), 'message-batches-2024-09-24'].toString() },
|
||||
options?.headers,
|
||||
]),
|
||||
});
|
||||
}
|
||||
/**
|
||||
* This endpoint is idempotent and can be used to poll for Message Batch
|
||||
* completion. To access the results of a Message Batch, make a request to the
|
||||
* `results_url` field in the response.
|
||||
*
|
||||
* Learn more about the Message Batches API in our
|
||||
* [user guide](https://docs.claude.com/en/docs/build-with-claude/batch-processing)
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const betaMessageBatch =
|
||||
* await client.beta.messages.batches.retrieve(
|
||||
* 'message_batch_id',
|
||||
* );
|
||||
* ```
|
||||
*/
|
||||
retrieve(messageBatchID, params = {}, options) {
|
||||
const { betas } = params ?? {};
|
||||
return this._client.get(path `/v1/messages/batches/${messageBatchID}?beta=true`, {
|
||||
...options,
|
||||
headers: buildHeaders([
|
||||
{ 'anthropic-beta': [...(betas ?? []), 'message-batches-2024-09-24'].toString() },
|
||||
options?.headers,
|
||||
]),
|
||||
});
|
||||
}
|
||||
/**
|
||||
* List all Message Batches within a Workspace. Most recently created batches are
|
||||
* returned first.
|
||||
*
|
||||
* Learn more about the Message Batches API in our
|
||||
* [user guide](https://docs.claude.com/en/docs/build-with-claude/batch-processing)
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* // Automatically fetches more pages as needed.
|
||||
* for await (const betaMessageBatch of client.beta.messages.batches.list()) {
|
||||
* // ...
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
list(params = {}, options) {
|
||||
const { betas, ...query } = params ?? {};
|
||||
return this._client.getAPIList('/v1/messages/batches?beta=true', (Page), {
|
||||
query,
|
||||
...options,
|
||||
headers: buildHeaders([
|
||||
{ 'anthropic-beta': [...(betas ?? []), 'message-batches-2024-09-24'].toString() },
|
||||
options?.headers,
|
||||
]),
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Delete a Message Batch.
|
||||
*
|
||||
* Message Batches can only be deleted once they've finished processing. If you'd
|
||||
* like to delete an in-progress batch, you must first cancel it.
|
||||
*
|
||||
* Learn more about the Message Batches API in our
|
||||
* [user guide](https://docs.claude.com/en/docs/build-with-claude/batch-processing)
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const betaDeletedMessageBatch =
|
||||
* await client.beta.messages.batches.delete(
|
||||
* 'message_batch_id',
|
||||
* );
|
||||
* ```
|
||||
*/
|
||||
delete(messageBatchID, params = {}, options) {
|
||||
const { betas } = params ?? {};
|
||||
return this._client.delete(path `/v1/messages/batches/${messageBatchID}?beta=true`, {
|
||||
...options,
|
||||
headers: buildHeaders([
|
||||
{ 'anthropic-beta': [...(betas ?? []), 'message-batches-2024-09-24'].toString() },
|
||||
options?.headers,
|
||||
]),
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Batches may be canceled any time before processing ends. Once cancellation is
|
||||
* initiated, the batch enters a `canceling` state, at which time the system may
|
||||
* complete any in-progress, non-interruptible requests before finalizing
|
||||
* cancellation.
|
||||
*
|
||||
* The number of canceled requests is specified in `request_counts`. To determine
|
||||
* which requests were canceled, check the individual results within the batch.
|
||||
* Note that cancellation may not result in any canceled requests if they were
|
||||
* non-interruptible.
|
||||
*
|
||||
* Learn more about the Message Batches API in our
|
||||
* [user guide](https://docs.claude.com/en/docs/build-with-claude/batch-processing)
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const betaMessageBatch =
|
||||
* await client.beta.messages.batches.cancel(
|
||||
* 'message_batch_id',
|
||||
* );
|
||||
* ```
|
||||
*/
|
||||
cancel(messageBatchID, params = {}, options) {
|
||||
const { betas } = params ?? {};
|
||||
return this._client.post(path `/v1/messages/batches/${messageBatchID}/cancel?beta=true`, {
|
||||
...options,
|
||||
headers: buildHeaders([
|
||||
{ 'anthropic-beta': [...(betas ?? []), 'message-batches-2024-09-24'].toString() },
|
||||
options?.headers,
|
||||
]),
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Streams the results of a Message Batch as a `.jsonl` file.
|
||||
*
|
||||
* Each line in the file is a JSON object containing the result of a single request
|
||||
* in the Message Batch. Results are not guaranteed to be in the same order as
|
||||
* requests. Use the `custom_id` field to match results to requests.
|
||||
*
|
||||
* Learn more about the Message Batches API in our
|
||||
* [user guide](https://docs.claude.com/en/docs/build-with-claude/batch-processing)
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const betaMessageBatchIndividualResponse =
|
||||
* await client.beta.messages.batches.results(
|
||||
* 'message_batch_id',
|
||||
* );
|
||||
* ```
|
||||
*/
|
||||
async results(messageBatchID, params = {}, options) {
|
||||
const batch = await this.retrieve(messageBatchID);
|
||||
if (!batch.results_url) {
|
||||
throw new AnthropicError(`No batch \`results_url\`; Has it finished processing? ${batch.processing_status} - ${batch.id}`);
|
||||
}
|
||||
const { betas } = params ?? {};
|
||||
return this._client
|
||||
.get(batch.results_url, {
|
||||
...options,
|
||||
headers: buildHeaders([
|
||||
{
|
||||
'anthropic-beta': [...(betas ?? []), 'message-batches-2024-09-24'].toString(),
|
||||
Accept: 'application/binary',
|
||||
},
|
||||
options?.headers,
|
||||
]),
|
||||
stream: true,
|
||||
__binaryResponse: true,
|
||||
})
|
||||
._thenUnwrap((_, props) => JSONLDecoder.fromResponse(props.response, props.controller));
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=batches.mjs.map
|
||||
156
claude-code-source/node_modules/@anthropic-ai/sdk/resources/beta/messages/messages.mjs
generated
vendored
156
claude-code-source/node_modules/@anthropic-ai/sdk/resources/beta/messages/messages.mjs
generated
vendored
@@ -1,156 +0,0 @@
|
||||
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
||||
import { AnthropicError } from "../../../error.mjs";
|
||||
import { APIResource } from "../../../core/resource.mjs";
|
||||
import { MODEL_NONSTREAMING_TOKENS } from "../../../internal/constants.mjs";
|
||||
import { buildHeaders } from "../../../internal/headers.mjs";
|
||||
import { stainlessHelperHeader } from "../../../lib/stainless-helper-header.mjs";
|
||||
import { parseBetaMessage, } from "../../../lib/beta-parser.mjs";
|
||||
import { BetaMessageStream } from "../../../lib/BetaMessageStream.mjs";
|
||||
import { BetaToolRunner, } from "../../../lib/tools/BetaToolRunner.mjs";
|
||||
import { ToolError } from "../../../lib/tools/ToolError.mjs";
|
||||
import * as BatchesAPI from "./batches.mjs";
|
||||
import { Batches, } from "./batches.mjs";
|
||||
const DEPRECATED_MODELS = {
|
||||
'claude-1.3': 'November 6th, 2024',
|
||||
'claude-1.3-100k': 'November 6th, 2024',
|
||||
'claude-instant-1.1': 'November 6th, 2024',
|
||||
'claude-instant-1.1-100k': 'November 6th, 2024',
|
||||
'claude-instant-1.2': 'November 6th, 2024',
|
||||
'claude-3-sonnet-20240229': 'July 21st, 2025',
|
||||
'claude-3-opus-20240229': 'January 5th, 2026',
|
||||
'claude-2.1': 'July 21st, 2025',
|
||||
'claude-2.0': 'July 21st, 2025',
|
||||
'claude-3-7-sonnet-latest': 'February 19th, 2026',
|
||||
'claude-3-7-sonnet-20250219': 'February 19th, 2026',
|
||||
};
|
||||
const MODELS_TO_WARN_WITH_THINKING_ENABLED = ['claude-opus-4-6'];
|
||||
export class Messages extends APIResource {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this.batches = new BatchesAPI.Batches(this._client);
|
||||
}
|
||||
create(params, options) {
|
||||
// Transform deprecated output_format to output_config.format
|
||||
const modifiedParams = transformOutputFormat(params);
|
||||
const { betas, ...body } = modifiedParams;
|
||||
if (body.model in DEPRECATED_MODELS) {
|
||||
console.warn(`The model '${body.model}' is deprecated and will reach end-of-life on ${DEPRECATED_MODELS[body.model]}\nPlease migrate to a newer model. Visit https://docs.anthropic.com/en/docs/resources/model-deprecations for more information.`);
|
||||
}
|
||||
if (body.model in MODELS_TO_WARN_WITH_THINKING_ENABLED &&
|
||||
body.thinking &&
|
||||
body.thinking.type === 'enabled') {
|
||||
console.warn(`Using Claude with ${body.model} and 'thinking.type=enabled' is deprecated. Use 'thinking.type=adaptive' instead which results in better model performance in our testing: https://platform.claude.com/docs/en/build-with-claude/adaptive-thinking`);
|
||||
}
|
||||
let timeout = this._client._options.timeout;
|
||||
if (!body.stream && timeout == null) {
|
||||
const maxNonstreamingTokens = MODEL_NONSTREAMING_TOKENS[body.model] ?? undefined;
|
||||
timeout = this._client.calculateNonstreamingTimeout(body.max_tokens, maxNonstreamingTokens);
|
||||
}
|
||||
// Collect helper info from tools and messages
|
||||
const helperHeader = stainlessHelperHeader(body.tools, body.messages);
|
||||
return this._client.post('/v1/messages?beta=true', {
|
||||
body,
|
||||
timeout: timeout ?? 600000,
|
||||
...options,
|
||||
headers: buildHeaders([
|
||||
{ ...(betas?.toString() != null ? { 'anthropic-beta': betas?.toString() } : undefined) },
|
||||
helperHeader,
|
||||
options?.headers,
|
||||
]),
|
||||
stream: modifiedParams.stream ?? false,
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Send a structured list of input messages with text and/or image content, along with an expected `output_format` and
|
||||
* the response will be automatically parsed and available in the `parsed_output` property of the message.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const message = await client.beta.messages.parse({
|
||||
* model: 'claude-3-5-sonnet-20241022',
|
||||
* max_tokens: 1024,
|
||||
* messages: [{ role: 'user', content: 'What is 2+2?' }],
|
||||
* output_format: zodOutputFormat(z.object({ answer: z.number() }), 'math'),
|
||||
* });
|
||||
*
|
||||
* console.log(message.parsed_output?.answer); // 4
|
||||
* ```
|
||||
*/
|
||||
parse(params, options) {
|
||||
options = {
|
||||
...options,
|
||||
headers: buildHeaders([
|
||||
{ 'anthropic-beta': [...(params.betas ?? []), 'structured-outputs-2025-12-15'].toString() },
|
||||
options?.headers,
|
||||
]),
|
||||
};
|
||||
return this.create(params, options).then((message) => parseBetaMessage(message, params, { logger: this._client.logger ?? console }));
|
||||
}
|
||||
/**
|
||||
* Create a Message stream
|
||||
*/
|
||||
stream(body, options) {
|
||||
return BetaMessageStream.createMessage(this, body, options);
|
||||
}
|
||||
/**
|
||||
* Count the number of tokens in a Message.
|
||||
*
|
||||
* The Token Count API can be used to count the number of tokens in a Message,
|
||||
* including tools, images, and documents, without creating it.
|
||||
*
|
||||
* Learn more about token counting in our
|
||||
* [user guide](https://docs.claude.com/en/docs/build-with-claude/token-counting)
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const betaMessageTokensCount =
|
||||
* await client.beta.messages.countTokens({
|
||||
* messages: [{ content: 'string', role: 'user' }],
|
||||
* model: 'claude-opus-4-6',
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
countTokens(params, options) {
|
||||
// Transform deprecated output_format to output_config.format
|
||||
const modifiedParams = transformOutputFormat(params);
|
||||
const { betas, ...body } = modifiedParams;
|
||||
return this._client.post('/v1/messages/count_tokens?beta=true', {
|
||||
body,
|
||||
...options,
|
||||
headers: buildHeaders([
|
||||
{ 'anthropic-beta': [...(betas ?? []), 'token-counting-2024-11-01'].toString() },
|
||||
options?.headers,
|
||||
]),
|
||||
});
|
||||
}
|
||||
toolRunner(body, options) {
|
||||
return new BetaToolRunner(this._client, body, options);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Transform deprecated output_format to output_config.format
|
||||
* Returns a modified copy of the params without mutating the original
|
||||
*/
|
||||
function transformOutputFormat(params) {
|
||||
if (!params.output_format) {
|
||||
return params;
|
||||
}
|
||||
if (params.output_config?.format) {
|
||||
throw new AnthropicError('Both output_format and output_config.format were provided. ' +
|
||||
'Please use only output_config.format (output_format is deprecated).');
|
||||
}
|
||||
const { output_format, ...rest } = params;
|
||||
return {
|
||||
...rest,
|
||||
output_config: {
|
||||
...params.output_config,
|
||||
format: output_format,
|
||||
},
|
||||
};
|
||||
}
|
||||
export { BetaToolRunner } from "../../../lib/tools/BetaToolRunner.mjs";
|
||||
export { ToolError } from "../../../lib/tools/ToolError.mjs";
|
||||
Messages.Batches = Batches;
|
||||
Messages.BetaToolRunner = BetaToolRunner;
|
||||
Messages.ToolError = ToolError;
|
||||
//# sourceMappingURL=messages.mjs.map
|
||||
56
claude-code-source/node_modules/@anthropic-ai/sdk/resources/beta/models.mjs
generated
vendored
56
claude-code-source/node_modules/@anthropic-ai/sdk/resources/beta/models.mjs
generated
vendored
@@ -1,56 +0,0 @@
|
||||
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
||||
import { APIResource } from "../../core/resource.mjs";
|
||||
import { Page } from "../../core/pagination.mjs";
|
||||
import { buildHeaders } from "../../internal/headers.mjs";
|
||||
import { path } from "../../internal/utils/path.mjs";
|
||||
export class Models extends APIResource {
|
||||
/**
|
||||
* Get a specific model.
|
||||
*
|
||||
* The Models API response can be used to determine information about a specific
|
||||
* model or resolve a model alias to a model ID.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const betaModelInfo = await client.beta.models.retrieve(
|
||||
* 'model_id',
|
||||
* );
|
||||
* ```
|
||||
*/
|
||||
retrieve(modelID, params = {}, options) {
|
||||
const { betas } = params ?? {};
|
||||
return this._client.get(path `/v1/models/${modelID}?beta=true`, {
|
||||
...options,
|
||||
headers: buildHeaders([
|
||||
{ ...(betas?.toString() != null ? { 'anthropic-beta': betas?.toString() } : undefined) },
|
||||
options?.headers,
|
||||
]),
|
||||
});
|
||||
}
|
||||
/**
|
||||
* List available models.
|
||||
*
|
||||
* The Models API response can be used to determine which models are available for
|
||||
* use in the API. More recently released models are listed first.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* // Automatically fetches more pages as needed.
|
||||
* for await (const betaModelInfo of client.beta.models.list()) {
|
||||
* // ...
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
list(params = {}, options) {
|
||||
const { betas, ...query } = params ?? {};
|
||||
return this._client.getAPIList('/v1/models?beta=true', (Page), {
|
||||
query,
|
||||
...options,
|
||||
headers: buildHeaders([
|
||||
{ ...(betas?.toString() != null ? { 'anthropic-beta': betas?.toString() } : undefined) },
|
||||
options?.headers,
|
||||
]),
|
||||
});
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=models.mjs.map
|
||||
93
claude-code-source/node_modules/@anthropic-ai/sdk/resources/beta/skills/skills.mjs
generated
vendored
93
claude-code-source/node_modules/@anthropic-ai/sdk/resources/beta/skills/skills.mjs
generated
vendored
@@ -1,93 +0,0 @@
|
||||
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
||||
import { APIResource } from "../../../core/resource.mjs";
|
||||
import * as VersionsAPI from "./versions.mjs";
|
||||
import { Versions, } from "./versions.mjs";
|
||||
import { PageCursor } from "../../../core/pagination.mjs";
|
||||
import { buildHeaders } from "../../../internal/headers.mjs";
|
||||
import { multipartFormRequestOptions } from "../../../internal/uploads.mjs";
|
||||
import { path } from "../../../internal/utils/path.mjs";
|
||||
export class Skills extends APIResource {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this.versions = new VersionsAPI.Versions(this._client);
|
||||
}
|
||||
/**
|
||||
* Create Skill
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const skill = await client.beta.skills.create();
|
||||
* ```
|
||||
*/
|
||||
create(params = {}, options) {
|
||||
const { betas, ...body } = params ?? {};
|
||||
return this._client.post('/v1/skills?beta=true', multipartFormRequestOptions({
|
||||
body,
|
||||
...options,
|
||||
headers: buildHeaders([
|
||||
{ 'anthropic-beta': [...(betas ?? []), 'skills-2025-10-02'].toString() },
|
||||
options?.headers,
|
||||
]),
|
||||
}, this._client, false));
|
||||
}
|
||||
/**
|
||||
* Get Skill
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const skill = await client.beta.skills.retrieve('skill_id');
|
||||
* ```
|
||||
*/
|
||||
retrieve(skillID, params = {}, options) {
|
||||
const { betas } = params ?? {};
|
||||
return this._client.get(path `/v1/skills/${skillID}?beta=true`, {
|
||||
...options,
|
||||
headers: buildHeaders([
|
||||
{ 'anthropic-beta': [...(betas ?? []), 'skills-2025-10-02'].toString() },
|
||||
options?.headers,
|
||||
]),
|
||||
});
|
||||
}
|
||||
/**
|
||||
* List Skills
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* // Automatically fetches more pages as needed.
|
||||
* for await (const skillListResponse of client.beta.skills.list()) {
|
||||
* // ...
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
list(params = {}, options) {
|
||||
const { betas, ...query } = params ?? {};
|
||||
return this._client.getAPIList('/v1/skills?beta=true', (PageCursor), {
|
||||
query,
|
||||
...options,
|
||||
headers: buildHeaders([
|
||||
{ 'anthropic-beta': [...(betas ?? []), 'skills-2025-10-02'].toString() },
|
||||
options?.headers,
|
||||
]),
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Delete Skill
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const skill = await client.beta.skills.delete('skill_id');
|
||||
* ```
|
||||
*/
|
||||
delete(skillID, params = {}, options) {
|
||||
const { betas } = params ?? {};
|
||||
return this._client.delete(path `/v1/skills/${skillID}?beta=true`, {
|
||||
...options,
|
||||
headers: buildHeaders([
|
||||
{ 'anthropic-beta': [...(betas ?? []), 'skills-2025-10-02'].toString() },
|
||||
options?.headers,
|
||||
]),
|
||||
});
|
||||
}
|
||||
}
|
||||
Skills.Versions = Versions;
|
||||
//# sourceMappingURL=skills.mjs.map
|
||||
96
claude-code-source/node_modules/@anthropic-ai/sdk/resources/beta/skills/versions.mjs
generated
vendored
96
claude-code-source/node_modules/@anthropic-ai/sdk/resources/beta/skills/versions.mjs
generated
vendored
@@ -1,96 +0,0 @@
|
||||
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
||||
import { APIResource } from "../../../core/resource.mjs";
|
||||
import { PageCursor } from "../../../core/pagination.mjs";
|
||||
import { buildHeaders } from "../../../internal/headers.mjs";
|
||||
import { multipartFormRequestOptions } from "../../../internal/uploads.mjs";
|
||||
import { path } from "../../../internal/utils/path.mjs";
|
||||
export class Versions extends APIResource {
|
||||
/**
|
||||
* Create Skill Version
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const version = await client.beta.skills.versions.create(
|
||||
* 'skill_id',
|
||||
* );
|
||||
* ```
|
||||
*/
|
||||
create(skillID, params = {}, options) {
|
||||
const { betas, ...body } = params ?? {};
|
||||
return this._client.post(path `/v1/skills/${skillID}/versions?beta=true`, multipartFormRequestOptions({
|
||||
body,
|
||||
...options,
|
||||
headers: buildHeaders([
|
||||
{ 'anthropic-beta': [...(betas ?? []), 'skills-2025-10-02'].toString() },
|
||||
options?.headers,
|
||||
]),
|
||||
}, this._client));
|
||||
}
|
||||
/**
|
||||
* Get Skill Version
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const version = await client.beta.skills.versions.retrieve(
|
||||
* 'version',
|
||||
* { skill_id: 'skill_id' },
|
||||
* );
|
||||
* ```
|
||||
*/
|
||||
retrieve(version, params, options) {
|
||||
const { skill_id, betas } = params;
|
||||
return this._client.get(path `/v1/skills/${skill_id}/versions/${version}?beta=true`, {
|
||||
...options,
|
||||
headers: buildHeaders([
|
||||
{ 'anthropic-beta': [...(betas ?? []), 'skills-2025-10-02'].toString() },
|
||||
options?.headers,
|
||||
]),
|
||||
});
|
||||
}
|
||||
/**
|
||||
* List Skill Versions
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* // Automatically fetches more pages as needed.
|
||||
* for await (const versionListResponse of client.beta.skills.versions.list(
|
||||
* 'skill_id',
|
||||
* )) {
|
||||
* // ...
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
list(skillID, params = {}, options) {
|
||||
const { betas, ...query } = params ?? {};
|
||||
return this._client.getAPIList(path `/v1/skills/${skillID}/versions?beta=true`, (PageCursor), {
|
||||
query,
|
||||
...options,
|
||||
headers: buildHeaders([
|
||||
{ 'anthropic-beta': [...(betas ?? []), 'skills-2025-10-02'].toString() },
|
||||
options?.headers,
|
||||
]),
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Delete Skill Version
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const version = await client.beta.skills.versions.delete(
|
||||
* 'version',
|
||||
* { skill_id: 'skill_id' },
|
||||
* );
|
||||
* ```
|
||||
*/
|
||||
delete(version, params, options) {
|
||||
const { skill_id, betas } = params;
|
||||
return this._client.delete(path `/v1/skills/${skill_id}/versions/${version}?beta=true`, {
|
||||
...options,
|
||||
headers: buildHeaders([
|
||||
{ 'anthropic-beta': [...(betas ?? []), 'skills-2025-10-02'].toString() },
|
||||
options?.headers,
|
||||
]),
|
||||
});
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=versions.mjs.map
|
||||
19
claude-code-source/node_modules/@anthropic-ai/sdk/resources/completions.mjs
generated
vendored
19
claude-code-source/node_modules/@anthropic-ai/sdk/resources/completions.mjs
generated
vendored
@@ -1,19 +0,0 @@
|
||||
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
||||
import { APIResource } from "../core/resource.mjs";
|
||||
import { buildHeaders } from "../internal/headers.mjs";
|
||||
export class Completions extends APIResource {
|
||||
create(params, options) {
|
||||
const { betas, ...body } = params;
|
||||
return this._client.post('/v1/complete', {
|
||||
body,
|
||||
timeout: this._client._options.timeout ?? 600000,
|
||||
...options,
|
||||
headers: buildHeaders([
|
||||
{ ...(betas?.toString() != null ? { 'anthropic-beta': betas?.toString() } : undefined) },
|
||||
options?.headers,
|
||||
]),
|
||||
stream: params.stream ?? false,
|
||||
});
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=completions.mjs.map
|
||||
7
claude-code-source/node_modules/@anthropic-ai/sdk/resources/index.mjs
generated
vendored
7
claude-code-source/node_modules/@anthropic-ai/sdk/resources/index.mjs
generated
vendored
@@ -1,7 +0,0 @@
|
||||
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
||||
export * from "./shared.mjs";
|
||||
export { Beta, } from "./beta/beta.mjs";
|
||||
export { Completions, } from "./completions.mjs";
|
||||
export { Messages, } from "./messages/messages.mjs";
|
||||
export { Models, } from "./models.mjs";
|
||||
//# sourceMappingURL=index.mjs.map
|
||||
149
claude-code-source/node_modules/@anthropic-ai/sdk/resources/messages/batches.mjs
generated
vendored
149
claude-code-source/node_modules/@anthropic-ai/sdk/resources/messages/batches.mjs
generated
vendored
@@ -1,149 +0,0 @@
|
||||
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
||||
import { APIResource } from "../../core/resource.mjs";
|
||||
import { Page } from "../../core/pagination.mjs";
|
||||
import { buildHeaders } from "../../internal/headers.mjs";
|
||||
import { JSONLDecoder } from "../../internal/decoders/jsonl.mjs";
|
||||
import { AnthropicError } from "../../error.mjs";
|
||||
import { path } from "../../internal/utils/path.mjs";
|
||||
export class Batches extends APIResource {
|
||||
/**
|
||||
* Send a batch of Message creation requests.
|
||||
*
|
||||
* The Message Batches API can be used to process multiple Messages API requests at
|
||||
* once. Once a Message Batch is created, it begins processing immediately. Batches
|
||||
* can take up to 24 hours to complete.
|
||||
*
|
||||
* Learn more about the Message Batches API in our
|
||||
* [user guide](https://docs.claude.com/en/docs/build-with-claude/batch-processing)
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const messageBatch = await client.messages.batches.create({
|
||||
* requests: [
|
||||
* {
|
||||
* custom_id: 'my-custom-id-1',
|
||||
* params: {
|
||||
* max_tokens: 1024,
|
||||
* messages: [
|
||||
* { content: 'Hello, world', role: 'user' },
|
||||
* ],
|
||||
* model: 'claude-opus-4-6',
|
||||
* },
|
||||
* },
|
||||
* ],
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
create(body, options) {
|
||||
return this._client.post('/v1/messages/batches', { body, ...options });
|
||||
}
|
||||
/**
|
||||
* This endpoint is idempotent and can be used to poll for Message Batch
|
||||
* completion. To access the results of a Message Batch, make a request to the
|
||||
* `results_url` field in the response.
|
||||
*
|
||||
* Learn more about the Message Batches API in our
|
||||
* [user guide](https://docs.claude.com/en/docs/build-with-claude/batch-processing)
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const messageBatch = await client.messages.batches.retrieve(
|
||||
* 'message_batch_id',
|
||||
* );
|
||||
* ```
|
||||
*/
|
||||
retrieve(messageBatchID, options) {
|
||||
return this._client.get(path `/v1/messages/batches/${messageBatchID}`, options);
|
||||
}
|
||||
/**
|
||||
* List all Message Batches within a Workspace. Most recently created batches are
|
||||
* returned first.
|
||||
*
|
||||
* Learn more about the Message Batches API in our
|
||||
* [user guide](https://docs.claude.com/en/docs/build-with-claude/batch-processing)
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* // Automatically fetches more pages as needed.
|
||||
* for await (const messageBatch of client.messages.batches.list()) {
|
||||
* // ...
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
list(query = {}, options) {
|
||||
return this._client.getAPIList('/v1/messages/batches', (Page), { query, ...options });
|
||||
}
|
||||
/**
|
||||
* Delete a Message Batch.
|
||||
*
|
||||
* Message Batches can only be deleted once they've finished processing. If you'd
|
||||
* like to delete an in-progress batch, you must first cancel it.
|
||||
*
|
||||
* Learn more about the Message Batches API in our
|
||||
* [user guide](https://docs.claude.com/en/docs/build-with-claude/batch-processing)
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const deletedMessageBatch =
|
||||
* await client.messages.batches.delete('message_batch_id');
|
||||
* ```
|
||||
*/
|
||||
delete(messageBatchID, options) {
|
||||
return this._client.delete(path `/v1/messages/batches/${messageBatchID}`, options);
|
||||
}
|
||||
/**
|
||||
* Batches may be canceled any time before processing ends. Once cancellation is
|
||||
* initiated, the batch enters a `canceling` state, at which time the system may
|
||||
* complete any in-progress, non-interruptible requests before finalizing
|
||||
* cancellation.
|
||||
*
|
||||
* The number of canceled requests is specified in `request_counts`. To determine
|
||||
* which requests were canceled, check the individual results within the batch.
|
||||
* Note that cancellation may not result in any canceled requests if they were
|
||||
* non-interruptible.
|
||||
*
|
||||
* Learn more about the Message Batches API in our
|
||||
* [user guide](https://docs.claude.com/en/docs/build-with-claude/batch-processing)
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const messageBatch = await client.messages.batches.cancel(
|
||||
* 'message_batch_id',
|
||||
* );
|
||||
* ```
|
||||
*/
|
||||
cancel(messageBatchID, options) {
|
||||
return this._client.post(path `/v1/messages/batches/${messageBatchID}/cancel`, options);
|
||||
}
|
||||
/**
|
||||
* Streams the results of a Message Batch as a `.jsonl` file.
|
||||
*
|
||||
* Each line in the file is a JSON object containing the result of a single request
|
||||
* in the Message Batch. Results are not guaranteed to be in the same order as
|
||||
* requests. Use the `custom_id` field to match results to requests.
|
||||
*
|
||||
* Learn more about the Message Batches API in our
|
||||
* [user guide](https://docs.claude.com/en/docs/build-with-claude/batch-processing)
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const messageBatchIndividualResponse =
|
||||
* await client.messages.batches.results('message_batch_id');
|
||||
* ```
|
||||
*/
|
||||
async results(messageBatchID, options) {
|
||||
const batch = await this.retrieve(messageBatchID);
|
||||
if (!batch.results_url) {
|
||||
throw new AnthropicError(`No batch \`results_url\`; Has it finished processing? ${batch.processing_status} - ${batch.id}`);
|
||||
}
|
||||
return this._client
|
||||
.get(batch.results_url, {
|
||||
...options,
|
||||
headers: buildHeaders([{ Accept: 'application/binary' }, options?.headers]),
|
||||
stream: true,
|
||||
__binaryResponse: true,
|
||||
})
|
||||
._thenUnwrap((_, props) => JSONLDecoder.fromResponse(props.response, props.controller));
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=batches.mjs.map
|
||||
123
claude-code-source/node_modules/@anthropic-ai/sdk/resources/messages/messages.mjs
generated
vendored
123
claude-code-source/node_modules/@anthropic-ai/sdk/resources/messages/messages.mjs
generated
vendored
@@ -1,123 +0,0 @@
|
||||
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
||||
import { APIResource } from "../../core/resource.mjs";
|
||||
import { buildHeaders } from "../../internal/headers.mjs";
|
||||
import { stainlessHelperHeader } from "../../lib/stainless-helper-header.mjs";
|
||||
import { MessageStream } from "../../lib/MessageStream.mjs";
|
||||
import { parseMessage, } from "../../lib/parser.mjs";
|
||||
import * as BatchesAPI from "./batches.mjs";
|
||||
import { Batches, } from "./batches.mjs";
|
||||
import { MODEL_NONSTREAMING_TOKENS } from "../../internal/constants.mjs";
|
||||
export class Messages extends APIResource {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this.batches = new BatchesAPI.Batches(this._client);
|
||||
}
|
||||
create(body, options) {
|
||||
if (body.model in DEPRECATED_MODELS) {
|
||||
console.warn(`The model '${body.model}' is deprecated and will reach end-of-life on ${DEPRECATED_MODELS[body.model]}\nPlease migrate to a newer model. Visit https://docs.anthropic.com/en/docs/resources/model-deprecations for more information.`);
|
||||
}
|
||||
if (body.model in MODELS_TO_WARN_WITH_THINKING_ENABLED &&
|
||||
body.thinking &&
|
||||
body.thinking.type === 'enabled') {
|
||||
console.warn(`Using Claude with ${body.model} and 'thinking.type=enabled' is deprecated. Use 'thinking.type=adaptive' instead which results in better model performance in our testing: https://platform.claude.com/docs/en/build-with-claude/adaptive-thinking`);
|
||||
}
|
||||
let timeout = this._client._options.timeout;
|
||||
if (!body.stream && timeout == null) {
|
||||
const maxNonstreamingTokens = MODEL_NONSTREAMING_TOKENS[body.model] ?? undefined;
|
||||
timeout = this._client.calculateNonstreamingTimeout(body.max_tokens, maxNonstreamingTokens);
|
||||
}
|
||||
// Collect helper info from tools and messages
|
||||
const helperHeader = stainlessHelperHeader(body.tools, body.messages);
|
||||
return this._client.post('/v1/messages', {
|
||||
body,
|
||||
timeout: timeout ?? 600000,
|
||||
...options,
|
||||
headers: buildHeaders([helperHeader, options?.headers]),
|
||||
stream: body.stream ?? false,
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Send a structured list of input messages with text and/or image content, along with an expected `output_config.format` and
|
||||
* the response will be automatically parsed and available in the `parsed_output` property of the message.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const message = await client.messages.parse({
|
||||
* model: 'claude-sonnet-4-5-20250929',
|
||||
* max_tokens: 1024,
|
||||
* messages: [{ role: 'user', content: 'What is 2+2?' }],
|
||||
* output_config: {
|
||||
* format: zodOutputFormat(z.object({ answer: z.number() })),
|
||||
* },
|
||||
* });
|
||||
*
|
||||
* console.log(message.parsed_output?.answer); // 4
|
||||
* ```
|
||||
*/
|
||||
parse(params, options) {
|
||||
return this.create(params, options).then((message) => parseMessage(message, params, { logger: this._client.logger ?? console }));
|
||||
}
|
||||
/**
|
||||
* Create a Message stream.
|
||||
*
|
||||
* If `output_config.format` is provided with a parseable format (like `zodOutputFormat()`),
|
||||
* the final message will include a `parsed_output` property with the parsed content.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const stream = client.messages.stream({
|
||||
* model: 'claude-sonnet-4-5-20250929',
|
||||
* max_tokens: 1024,
|
||||
* messages: [{ role: 'user', content: 'What is 2+2?' }],
|
||||
* output_config: {
|
||||
* format: zodOutputFormat(z.object({ answer: z.number() })),
|
||||
* },
|
||||
* });
|
||||
*
|
||||
* const message = await stream.finalMessage();
|
||||
* console.log(message.parsed_output?.answer); // 4
|
||||
* ```
|
||||
*/
|
||||
stream(body, options) {
|
||||
return MessageStream.createMessage(this, body, options, { logger: this._client.logger ?? console });
|
||||
}
|
||||
/**
|
||||
* Count the number of tokens in a Message.
|
||||
*
|
||||
* The Token Count API can be used to count the number of tokens in a Message,
|
||||
* including tools, images, and documents, without creating it.
|
||||
*
|
||||
* Learn more about token counting in our
|
||||
* [user guide](https://docs.claude.com/en/docs/build-with-claude/token-counting)
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const messageTokensCount =
|
||||
* await client.messages.countTokens({
|
||||
* messages: [{ content: 'string', role: 'user' }],
|
||||
* model: 'claude-opus-4-6',
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
countTokens(body, options) {
|
||||
return this._client.post('/v1/messages/count_tokens', { body, ...options });
|
||||
}
|
||||
}
|
||||
const DEPRECATED_MODELS = {
|
||||
'claude-1.3': 'November 6th, 2024',
|
||||
'claude-1.3-100k': 'November 6th, 2024',
|
||||
'claude-instant-1.1': 'November 6th, 2024',
|
||||
'claude-instant-1.1-100k': 'November 6th, 2024',
|
||||
'claude-instant-1.2': 'November 6th, 2024',
|
||||
'claude-3-sonnet-20240229': 'July 21st, 2025',
|
||||
'claude-3-opus-20240229': 'January 5th, 2026',
|
||||
'claude-2.1': 'July 21st, 2025',
|
||||
'claude-2.0': 'July 21st, 2025',
|
||||
'claude-3-7-sonnet-latest': 'February 19th, 2026',
|
||||
'claude-3-7-sonnet-20250219': 'February 19th, 2026',
|
||||
'claude-3-5-haiku-latest': 'February 19th, 2026',
|
||||
'claude-3-5-haiku-20241022': 'February 19th, 2026',
|
||||
};
|
||||
const MODELS_TO_WARN_WITH_THINKING_ENABLED = ['claude-opus-4-6'];
|
||||
Messages.Batches = Batches;
|
||||
//# sourceMappingURL=messages.mjs.map
|
||||
41
claude-code-source/node_modules/@anthropic-ai/sdk/resources/models.mjs
generated
vendored
41
claude-code-source/node_modules/@anthropic-ai/sdk/resources/models.mjs
generated
vendored
@@ -1,41 +0,0 @@
|
||||
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
||||
import { APIResource } from "../core/resource.mjs";
|
||||
import { Page } from "../core/pagination.mjs";
|
||||
import { buildHeaders } from "../internal/headers.mjs";
|
||||
import { path } from "../internal/utils/path.mjs";
|
||||
export class Models extends APIResource {
|
||||
/**
|
||||
* Get a specific model.
|
||||
*
|
||||
* The Models API response can be used to determine information about a specific
|
||||
* model or resolve a model alias to a model ID.
|
||||
*/
|
||||
retrieve(modelID, params = {}, options) {
|
||||
const { betas } = params ?? {};
|
||||
return this._client.get(path `/v1/models/${modelID}`, {
|
||||
...options,
|
||||
headers: buildHeaders([
|
||||
{ ...(betas?.toString() != null ? { 'anthropic-beta': betas?.toString() } : undefined) },
|
||||
options?.headers,
|
||||
]),
|
||||
});
|
||||
}
|
||||
/**
|
||||
* List available models.
|
||||
*
|
||||
* The Models API response can be used to determine which models are available for
|
||||
* use in the API. More recently released models are listed first.
|
||||
*/
|
||||
list(params = {}, options) {
|
||||
const { betas, ...query } = params ?? {};
|
||||
return this._client.getAPIList('/v1/models', (Page), {
|
||||
query,
|
||||
...options,
|
||||
headers: buildHeaders([
|
||||
{ ...(betas?.toString() != null ? { 'anthropic-beta': betas?.toString() } : undefined) },
|
||||
options?.headers,
|
||||
]),
|
||||
});
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=models.mjs.map
|
||||
2
claude-code-source/node_modules/@anthropic-ai/sdk/streaming.mjs
generated
vendored
2
claude-code-source/node_modules/@anthropic-ai/sdk/streaming.mjs
generated
vendored
@@ -1,2 +0,0 @@
|
||||
export * from "./core/streaming.mjs";
|
||||
//# sourceMappingURL=streaming.mjs.map
|
||||
2
claude-code-source/node_modules/@anthropic-ai/sdk/version.mjs
generated
vendored
2
claude-code-source/node_modules/@anthropic-ai/sdk/version.mjs
generated
vendored
@@ -1,2 +0,0 @@
|
||||
export const VERSION = '0.74.0'; // x-release-please-version
|
||||
//# sourceMappingURL=version.mjs.map
|
||||
114
claude-code-source/node_modules/@anthropic-ai/vertex-sdk/client.mjs
generated
vendored
114
claude-code-source/node_modules/@anthropic-ai/vertex-sdk/client.mjs
generated
vendored
@@ -1,114 +0,0 @@
|
||||
import { BaseAnthropic } from '@anthropic-ai/sdk/client';
|
||||
import * as Resources from '@anthropic-ai/sdk/resources/index';
|
||||
import { GoogleAuth } from 'google-auth-library';
|
||||
import { readEnv } from "./internal/utils/env.mjs";
|
||||
import { isObj } from "./internal/utils/values.mjs";
|
||||
import { buildHeaders } from "./internal/headers.mjs";
|
||||
export { BaseAnthropic } from '@anthropic-ai/sdk/client';
|
||||
const DEFAULT_VERSION = 'vertex-2023-10-16';
|
||||
const MODEL_ENDPOINTS = new Set(['/v1/messages', '/v1/messages?beta=true']);
|
||||
export class AnthropicVertex extends BaseAnthropic {
|
||||
/**
|
||||
* API Client for interfacing with the Anthropic Vertex API.
|
||||
*
|
||||
* @param {string | null} opts.accessToken
|
||||
* @param {string | null} opts.projectId
|
||||
* @param {GoogleAuth} opts.googleAuth - Override the default google auth config
|
||||
* @param {AuthClient} opts.authClient - Provide a pre-configured AuthClient instance (alternative to googleAuth)
|
||||
* @param {string | null} [opts.region=process.env['CLOUD_ML_REGION']] - The region to use for the API. Use 'global' for global endpoint. [More details here](https://cloud.google.com/vertex-ai/generative-ai/docs/learn/locations).
|
||||
* @param {string} [opts.baseURL=process.env['ANTHROPIC_VERTEX__BASE_URL'] ?? https://${region}-aiplatform.googleapis.com/v1] - Override the default base URL for the API.
|
||||
* @param {number} [opts.timeout=10 minutes] - The maximum amount of time (in milliseconds) the client will wait for a response before timing out.
|
||||
* @param {MergedRequestInit} [opts.fetchOptions] - Additional `RequestInit` options to be passed to `fetch` calls.
|
||||
* @param {Fetch} [opts.fetch] - Specify a custom `fetch` function implementation.
|
||||
* @param {number} [opts.maxRetries=2] - The maximum number of times the client will retry a request.
|
||||
* @param {HeadersLike} opts.defaultHeaders - Default headers to include with every request to the API.
|
||||
* @param {Record<string, string | undefined>} opts.defaultQuery - Default query parameters to include with every request to the API.
|
||||
* @param {boolean} [opts.dangerouslyAllowBrowser=false] - By default, client-side use of this library is not allowed, as it risks exposing your secret API credentials to attackers.
|
||||
*/
|
||||
constructor({ baseURL = readEnv('ANTHROPIC_VERTEX_BASE_URL'), region = readEnv('CLOUD_ML_REGION') ?? null, projectId = readEnv('ANTHROPIC_VERTEX_PROJECT_ID') ?? null, ...opts } = {}) {
|
||||
if (!region) {
|
||||
throw new Error('No region was given. The client should be instantiated with the `region` option or the `CLOUD_ML_REGION` environment variable should be set.');
|
||||
}
|
||||
super({
|
||||
baseURL: baseURL ||
|
||||
(region === 'global' ?
|
||||
'https://aiplatform.googleapis.com/v1'
|
||||
: `https://${region}-aiplatform.googleapis.com/v1`),
|
||||
...opts,
|
||||
});
|
||||
this.messages = makeMessagesResource(this);
|
||||
this.beta = makeBetaResource(this);
|
||||
this.region = region;
|
||||
this.projectId = projectId;
|
||||
this.accessToken = opts.accessToken ?? null;
|
||||
if (opts.authClient && opts.googleAuth) {
|
||||
throw new Error('You cannot provide both `authClient` and `googleAuth`. Please provide only one of them.');
|
||||
}
|
||||
else if (opts.authClient) {
|
||||
this._authClientPromise = Promise.resolve(opts.authClient);
|
||||
}
|
||||
else {
|
||||
this._auth =
|
||||
opts.googleAuth ?? new GoogleAuth({ scopes: 'https://www.googleapis.com/auth/cloud-platform' });
|
||||
this._authClientPromise = this._auth.getClient();
|
||||
}
|
||||
}
|
||||
validateHeaders() {
|
||||
// auth validation is handled in prepareOptions since it needs to be async
|
||||
}
|
||||
async prepareOptions(options) {
|
||||
const authClient = await this._authClientPromise;
|
||||
const authHeaders = await authClient.getRequestHeaders();
|
||||
const projectId = authClient.projectId ?? authHeaders['x-goog-user-project'];
|
||||
if (!this.projectId && projectId) {
|
||||
this.projectId = projectId;
|
||||
}
|
||||
options.headers = buildHeaders([authHeaders, options.headers]);
|
||||
}
|
||||
async buildRequest(options) {
|
||||
if (isObj(options.body)) {
|
||||
// create a shallow copy of the request body so that code that mutates it later
|
||||
// doesn't mutate the original user-provided object
|
||||
options.body = { ...options.body };
|
||||
}
|
||||
if (isObj(options.body)) {
|
||||
if (!options.body['anthropic_version']) {
|
||||
options.body['anthropic_version'] = DEFAULT_VERSION;
|
||||
}
|
||||
}
|
||||
if (MODEL_ENDPOINTS.has(options.path) && options.method === 'post') {
|
||||
if (!this.projectId) {
|
||||
throw new Error('No projectId was given and it could not be resolved from credentials. The client should be instantiated with the `projectId` option or the `ANTHROPIC_VERTEX_PROJECT_ID` environment variable should be set.');
|
||||
}
|
||||
if (!isObj(options.body)) {
|
||||
throw new Error('Expected request body to be an object for post /v1/messages');
|
||||
}
|
||||
const model = options.body['model'];
|
||||
options.body['model'] = undefined;
|
||||
const stream = options.body['stream'] ?? false;
|
||||
const specifier = stream ? 'streamRawPredict' : 'rawPredict';
|
||||
options.path = `/projects/${this.projectId}/locations/${this.region}/publishers/anthropic/models/${model}:${specifier}`;
|
||||
}
|
||||
if (options.path === '/v1/messages/count_tokens' ||
|
||||
(options.path == '/v1/messages/count_tokens?beta=true' && options.method === 'post')) {
|
||||
if (!this.projectId) {
|
||||
throw new Error('No projectId was given and it could not be resolved from credentials. The client should be instantiated with the `projectId` option or the `ANTHROPIC_VERTEX_PROJECT_ID` environment variable should be set.');
|
||||
}
|
||||
options.path = `/projects/${this.projectId}/locations/${this.region}/publishers/anthropic/models/count-tokens:rawPredict`;
|
||||
}
|
||||
return super.buildRequest(options);
|
||||
}
|
||||
}
|
||||
function makeMessagesResource(client) {
|
||||
const resource = new Resources.Messages(client);
|
||||
// @ts-expect-error we're deleting non-optional properties
|
||||
delete resource.batches;
|
||||
return resource;
|
||||
}
|
||||
function makeBetaResource(client) {
|
||||
const resource = new Resources.Beta(client);
|
||||
// @ts-expect-error we're deleting non-optional properties
|
||||
delete resource.messages.batches;
|
||||
return resource;
|
||||
}
|
||||
//# sourceMappingURL=client.mjs.map
|
||||
2
claude-code-source/node_modules/@anthropic-ai/vertex-sdk/core/error.mjs
generated
vendored
2
claude-code-source/node_modules/@anthropic-ai/vertex-sdk/core/error.mjs
generated
vendored
@@ -1,2 +0,0 @@
|
||||
export * from '@anthropic-ai/sdk/core/error';
|
||||
//# sourceMappingURL=error.mjs.map
|
||||
3
claude-code-source/node_modules/@anthropic-ai/vertex-sdk/index.mjs
generated
vendored
3
claude-code-source/node_modules/@anthropic-ai/vertex-sdk/index.mjs
generated
vendored
@@ -1,3 +0,0 @@
|
||||
export * from "./client.mjs";
|
||||
export { AnthropicVertex as default } from "./client.mjs";
|
||||
//# sourceMappingURL=index.mjs.map
|
||||
74
claude-code-source/node_modules/@anthropic-ai/vertex-sdk/internal/headers.mjs
generated
vendored
74
claude-code-source/node_modules/@anthropic-ai/vertex-sdk/internal/headers.mjs
generated
vendored
@@ -1,74 +0,0 @@
|
||||
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
||||
import { isReadonlyArray } from "./utils/values.mjs";
|
||||
const brand_privateNullableHeaders = Symbol.for('brand.privateNullableHeaders');
|
||||
function* iterateHeaders(headers) {
|
||||
if (!headers)
|
||||
return;
|
||||
if (brand_privateNullableHeaders in headers) {
|
||||
const { values, nulls } = headers;
|
||||
yield* values.entries();
|
||||
for (const name of nulls) {
|
||||
yield [name, null];
|
||||
}
|
||||
return;
|
||||
}
|
||||
let shouldClear = false;
|
||||
let iter;
|
||||
if (headers instanceof Headers) {
|
||||
iter = headers.entries();
|
||||
}
|
||||
else if (isReadonlyArray(headers)) {
|
||||
iter = headers;
|
||||
}
|
||||
else {
|
||||
shouldClear = true;
|
||||
iter = Object.entries(headers ?? {});
|
||||
}
|
||||
for (let row of iter) {
|
||||
const name = row[0];
|
||||
if (typeof name !== 'string')
|
||||
throw new TypeError('expected header name to be a string');
|
||||
const values = isReadonlyArray(row[1]) ? row[1] : [row[1]];
|
||||
let didClear = false;
|
||||
for (const value of values) {
|
||||
if (value === undefined)
|
||||
continue;
|
||||
// Objects keys always overwrite older headers, they never append.
|
||||
// Yield a null to clear the header before adding the new values.
|
||||
if (shouldClear && !didClear) {
|
||||
didClear = true;
|
||||
yield [name, null];
|
||||
}
|
||||
yield [name, value];
|
||||
}
|
||||
}
|
||||
}
|
||||
export const buildHeaders = (newHeaders) => {
|
||||
const targetHeaders = new Headers();
|
||||
const nullHeaders = new Set();
|
||||
for (const headers of newHeaders) {
|
||||
const seenHeaders = new Set();
|
||||
for (const [name, value] of iterateHeaders(headers)) {
|
||||
const lowerName = name.toLowerCase();
|
||||
if (!seenHeaders.has(lowerName)) {
|
||||
targetHeaders.delete(name);
|
||||
seenHeaders.add(lowerName);
|
||||
}
|
||||
if (value === null) {
|
||||
targetHeaders.delete(name);
|
||||
nullHeaders.add(lowerName);
|
||||
}
|
||||
else {
|
||||
targetHeaders.append(name, value);
|
||||
nullHeaders.delete(lowerName);
|
||||
}
|
||||
}
|
||||
}
|
||||
return { [brand_privateNullableHeaders]: true, values: targetHeaders, nulls: nullHeaders };
|
||||
};
|
||||
export const isEmptyHeaders = (headers) => {
|
||||
for (const _ of iterateHeaders(headers))
|
||||
return false;
|
||||
return true;
|
||||
};
|
||||
//# sourceMappingURL=headers.mjs.map
|
||||
18
claude-code-source/node_modules/@anthropic-ai/vertex-sdk/internal/utils/env.mjs
generated
vendored
18
claude-code-source/node_modules/@anthropic-ai/vertex-sdk/internal/utils/env.mjs
generated
vendored
@@ -1,18 +0,0 @@
|
||||
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
||||
/**
|
||||
* Read an environment variable.
|
||||
*
|
||||
* Trims beginning and trailing whitespace.
|
||||
*
|
||||
* Will return undefined if the environment variable doesn't exist or cannot be accessed.
|
||||
*/
|
||||
export const readEnv = (env) => {
|
||||
if (typeof globalThis.process !== 'undefined') {
|
||||
return globalThis.process.env?.[env]?.trim() ?? undefined;
|
||||
}
|
||||
if (typeof globalThis.Deno !== 'undefined') {
|
||||
return globalThis.Deno.env?.get?.(env)?.trim();
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
//# sourceMappingURL=env.mjs.map
|
||||
94
claude-code-source/node_modules/@anthropic-ai/vertex-sdk/internal/utils/values.mjs
generated
vendored
94
claude-code-source/node_modules/@anthropic-ai/vertex-sdk/internal/utils/values.mjs
generated
vendored
@@ -1,94 +0,0 @@
|
||||
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
||||
import { AnthropicError } from "../../core/error.mjs";
|
||||
// https://url.spec.whatwg.org/#url-scheme-string
|
||||
const startsWithSchemeRegexp = /^[a-z][a-z0-9+.-]*:/i;
|
||||
export const isAbsoluteURL = (url) => {
|
||||
return startsWithSchemeRegexp.test(url);
|
||||
};
|
||||
export let isArray = (val) => ((isArray = Array.isArray), isArray(val));
|
||||
export let isReadonlyArray = isArray;
|
||||
/** Returns an object if the given value isn't an object, otherwise returns as-is */
|
||||
export function maybeObj(x) {
|
||||
if (typeof x !== 'object') {
|
||||
return {};
|
||||
}
|
||||
return x ?? {};
|
||||
}
|
||||
// https://stackoverflow.com/a/34491287
|
||||
export function isEmptyObj(obj) {
|
||||
if (!obj)
|
||||
return true;
|
||||
for (const _k in obj)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
// https://eslint.org/docs/latest/rules/no-prototype-builtins
|
||||
export function hasOwn(obj, key) {
|
||||
return Object.prototype.hasOwnProperty.call(obj, key);
|
||||
}
|
||||
export function isObj(obj) {
|
||||
return obj != null && typeof obj === 'object' && !Array.isArray(obj);
|
||||
}
|
||||
export const ensurePresent = (value) => {
|
||||
if (value == null) {
|
||||
throw new AnthropicError(`Expected a value to be given but received ${value} instead.`);
|
||||
}
|
||||
return value;
|
||||
};
|
||||
export const validatePositiveInteger = (name, n) => {
|
||||
if (typeof n !== 'number' || !Number.isInteger(n)) {
|
||||
throw new AnthropicError(`${name} must be an integer`);
|
||||
}
|
||||
if (n < 0) {
|
||||
throw new AnthropicError(`${name} must be a positive integer`);
|
||||
}
|
||||
return n;
|
||||
};
|
||||
export const coerceInteger = (value) => {
|
||||
if (typeof value === 'number')
|
||||
return Math.round(value);
|
||||
if (typeof value === 'string')
|
||||
return parseInt(value, 10);
|
||||
throw new AnthropicError(`Could not coerce ${value} (type: ${typeof value}) into a number`);
|
||||
};
|
||||
export const coerceFloat = (value) => {
|
||||
if (typeof value === 'number')
|
||||
return value;
|
||||
if (typeof value === 'string')
|
||||
return parseFloat(value);
|
||||
throw new AnthropicError(`Could not coerce ${value} (type: ${typeof value}) into a number`);
|
||||
};
|
||||
export const coerceBoolean = (value) => {
|
||||
if (typeof value === 'boolean')
|
||||
return value;
|
||||
if (typeof value === 'string')
|
||||
return value === 'true';
|
||||
return Boolean(value);
|
||||
};
|
||||
export const maybeCoerceInteger = (value) => {
|
||||
if (value == null) {
|
||||
return undefined;
|
||||
}
|
||||
return coerceInteger(value);
|
||||
};
|
||||
export const maybeCoerceFloat = (value) => {
|
||||
if (value == null) {
|
||||
return undefined;
|
||||
}
|
||||
return coerceFloat(value);
|
||||
};
|
||||
export const maybeCoerceBoolean = (value) => {
|
||||
if (value == null) {
|
||||
return undefined;
|
||||
}
|
||||
return coerceBoolean(value);
|
||||
};
|
||||
export const safeJSON = (text) => {
|
||||
try {
|
||||
return JSON.parse(text);
|
||||
}
|
||||
catch (err) {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
//# sourceMappingURL=values.mjs.map
|
||||
31
claude-code-source/node_modules/@aws-crypto/crc32/build/main/aws_crc32.js
generated
vendored
31
claude-code-source/node_modules/@aws-crypto/crc32/build/main/aws_crc32.js
generated
vendored
@@ -1,31 +0,0 @@
|
||||
"use strict";
|
||||
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.AwsCrc32 = void 0;
|
||||
var tslib_1 = require("tslib");
|
||||
var util_1 = require("@aws-crypto/util");
|
||||
var index_1 = require("./index");
|
||||
var AwsCrc32 = /** @class */ (function () {
|
||||
function AwsCrc32() {
|
||||
this.crc32 = new index_1.Crc32();
|
||||
}
|
||||
AwsCrc32.prototype.update = function (toHash) {
|
||||
if ((0, util_1.isEmptyData)(toHash))
|
||||
return;
|
||||
this.crc32.update((0, util_1.convertToBuffer)(toHash));
|
||||
};
|
||||
AwsCrc32.prototype.digest = function () {
|
||||
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
||||
return tslib_1.__generator(this, function (_a) {
|
||||
return [2 /*return*/, (0, util_1.numToUint8)(this.crc32.digest())];
|
||||
});
|
||||
});
|
||||
};
|
||||
AwsCrc32.prototype.reset = function () {
|
||||
this.crc32 = new index_1.Crc32();
|
||||
};
|
||||
return AwsCrc32;
|
||||
}());
|
||||
exports.AwsCrc32 = AwsCrc32;
|
||||
//# sourceMappingURL=aws_crc32.js.map
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user