@openclaw/anthropic-vertex-provider 2026.5.12-beta.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api.js +31 -0
- package/dist/index.js +48 -0
- package/dist/provider-catalog.js +55 -0
- package/dist/provider-discovery.js +48 -0
- package/dist/region.js +73 -0
- package/dist/setup-api.js +18 -0
- package/dist/stream-runtime.js +125 -0
- package/openclaw.plugin.json +16 -0
- package/package.json +54 -0
package/dist/api.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { hasAnthropicVertexAvailableAuth, hasAnthropicVertexCredentials, resolveAnthropicVertexClientRegion, resolveAnthropicVertexConfigApiKey, resolveAnthropicVertexProjectId, resolveAnthropicVertexRegion, resolveAnthropicVertexRegionFromBaseUrl } from "./region.js";
|
|
2
|
+
import { ANTHROPIC_VERTEX_DEFAULT_MODEL_ID, buildAnthropicVertexProvider } from "./provider-catalog.js";
|
|
3
|
+
//#region extensions/anthropic-vertex/api.ts
|
|
4
|
+
function mergeImplicitAnthropicVertexProvider(params) {
|
|
5
|
+
const { existing, implicit } = params;
|
|
6
|
+
if (!existing) return implicit;
|
|
7
|
+
return {
|
|
8
|
+
...implicit,
|
|
9
|
+
...existing,
|
|
10
|
+
models: Array.isArray(existing.models) && existing.models.length > 0 ? existing.models : implicit.models
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
function resolveImplicitAnthropicVertexProvider(params) {
|
|
14
|
+
const env = params?.env ?? process.env;
|
|
15
|
+
if (!hasAnthropicVertexAvailableAuth(env)) return null;
|
|
16
|
+
return buildAnthropicVertexProvider({ env });
|
|
17
|
+
}
|
|
18
|
+
function createAnthropicVertexStreamFn(projectId, region, baseURL, deps) {
|
|
19
|
+
const streamFnPromise = import("./stream-runtime.js").then((runtime) => runtime.createAnthropicVertexStreamFn(projectId, region, baseURL, deps));
|
|
20
|
+
return async (model, context, options) => {
|
|
21
|
+
return (await streamFnPromise)(model, context, options);
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function createAnthropicVertexStreamFnForModel(model, env = process.env, deps) {
|
|
25
|
+
const streamFnPromise = import("./stream-runtime.js").then((runtime) => runtime.createAnthropicVertexStreamFnForModel(model, env, deps));
|
|
26
|
+
return async (...args) => {
|
|
27
|
+
return (await streamFnPromise)(...args);
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
//#endregion
|
|
31
|
+
export { ANTHROPIC_VERTEX_DEFAULT_MODEL_ID, buildAnthropicVertexProvider, createAnthropicVertexStreamFn, createAnthropicVertexStreamFnForModel, hasAnthropicVertexAvailableAuth, hasAnthropicVertexCredentials, mergeImplicitAnthropicVertexProvider, resolveAnthropicVertexClientRegion, resolveAnthropicVertexConfigApiKey, resolveAnthropicVertexProjectId, resolveAnthropicVertexRegion, resolveAnthropicVertexRegionFromBaseUrl, resolveImplicitAnthropicVertexProvider };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { hasAnthropicVertexAvailableAuth, resolveAnthropicVertexConfigApiKey } from "./region.js";
|
|
2
|
+
import { mergeImplicitAnthropicVertexProvider, resolveImplicitAnthropicVertexProvider } from "./api.js";
|
|
3
|
+
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
|
|
4
|
+
import { readConfiguredProviderCatalogEntries } from "openclaw/plugin-sdk/provider-catalog-shared";
|
|
5
|
+
import { NATIVE_ANTHROPIC_REPLAY_HOOKS } from "openclaw/plugin-sdk/provider-model-shared";
|
|
6
|
+
//#region extensions/anthropic-vertex/index.ts
|
|
7
|
+
const PROVIDER_ID = "anthropic-vertex";
|
|
8
|
+
const GCP_VERTEX_CREDENTIALS_MARKER = "gcp-vertex-credentials";
|
|
9
|
+
var anthropic_vertex_default = definePluginEntry({
|
|
10
|
+
id: PROVIDER_ID,
|
|
11
|
+
name: "Anthropic Vertex Provider",
|
|
12
|
+
description: "Bundled Anthropic Vertex provider plugin",
|
|
13
|
+
register(api) {
|
|
14
|
+
api.registerProvider({
|
|
15
|
+
id: PROVIDER_ID,
|
|
16
|
+
label: "Anthropic Vertex",
|
|
17
|
+
docsPath: "/providers/models",
|
|
18
|
+
auth: [],
|
|
19
|
+
catalog: {
|
|
20
|
+
order: "simple",
|
|
21
|
+
run: async (ctx) => {
|
|
22
|
+
const implicit = resolveImplicitAnthropicVertexProvider({ env: ctx.env });
|
|
23
|
+
if (!implicit) return null;
|
|
24
|
+
return { provider: mergeImplicitAnthropicVertexProvider({
|
|
25
|
+
existing: ctx.config.models?.providers?.[PROVIDER_ID],
|
|
26
|
+
implicit
|
|
27
|
+
}) };
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
resolveConfigApiKey: ({ env }) => resolveAnthropicVertexConfigApiKey(env),
|
|
31
|
+
...NATIVE_ANTHROPIC_REPLAY_HOOKS,
|
|
32
|
+
resolveSyntheticAuth: () => {
|
|
33
|
+
if (!hasAnthropicVertexAvailableAuth()) return;
|
|
34
|
+
return {
|
|
35
|
+
apiKey: GCP_VERTEX_CREDENTIALS_MARKER,
|
|
36
|
+
source: "gcp-vertex-credentials (ADC)",
|
|
37
|
+
mode: "api-key"
|
|
38
|
+
};
|
|
39
|
+
},
|
|
40
|
+
augmentModelCatalog: ({ config }) => readConfiguredProviderCatalogEntries({
|
|
41
|
+
config,
|
|
42
|
+
providerId: PROVIDER_ID
|
|
43
|
+
})
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
//#endregion
|
|
48
|
+
export { anthropic_vertex_default as default };
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { resolveAnthropicVertexRegion } from "./region.js";
|
|
2
|
+
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
3
|
+
//#region extensions/anthropic-vertex/provider-catalog.ts
|
|
4
|
+
const ANTHROPIC_VERTEX_DEFAULT_MODEL_ID = "claude-sonnet-4-6";
|
|
5
|
+
const ANTHROPIC_VERTEX_DEFAULT_CONTEXT_WINDOW = 1e6;
|
|
6
|
+
const GCP_VERTEX_CREDENTIALS_MARKER = "gcp-vertex-credentials";
|
|
7
|
+
function buildAnthropicVertexModel(params) {
|
|
8
|
+
return {
|
|
9
|
+
id: params.id,
|
|
10
|
+
name: params.name,
|
|
11
|
+
reasoning: params.reasoning,
|
|
12
|
+
input: params.input,
|
|
13
|
+
cost: params.cost,
|
|
14
|
+
contextWindow: ANTHROPIC_VERTEX_DEFAULT_CONTEXT_WINDOW,
|
|
15
|
+
maxTokens: params.maxTokens
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
function buildAnthropicVertexCatalog() {
|
|
19
|
+
return [buildAnthropicVertexModel({
|
|
20
|
+
id: "claude-opus-4-6",
|
|
21
|
+
name: "Claude Opus 4.6",
|
|
22
|
+
reasoning: true,
|
|
23
|
+
input: ["text", "image"],
|
|
24
|
+
cost: {
|
|
25
|
+
input: 5,
|
|
26
|
+
output: 25,
|
|
27
|
+
cacheRead: .5,
|
|
28
|
+
cacheWrite: 6.25
|
|
29
|
+
},
|
|
30
|
+
maxTokens: 128e3
|
|
31
|
+
}), buildAnthropicVertexModel({
|
|
32
|
+
id: ANTHROPIC_VERTEX_DEFAULT_MODEL_ID,
|
|
33
|
+
name: "Claude Sonnet 4.6",
|
|
34
|
+
reasoning: true,
|
|
35
|
+
input: ["text", "image"],
|
|
36
|
+
cost: {
|
|
37
|
+
input: 3,
|
|
38
|
+
output: 15,
|
|
39
|
+
cacheRead: .3,
|
|
40
|
+
cacheWrite: 3.75
|
|
41
|
+
},
|
|
42
|
+
maxTokens: 128e3
|
|
43
|
+
})];
|
|
44
|
+
}
|
|
45
|
+
function buildAnthropicVertexProvider(params) {
|
|
46
|
+
const region = resolveAnthropicVertexRegion(params?.env);
|
|
47
|
+
return {
|
|
48
|
+
baseUrl: normalizeLowercaseStringOrEmpty(region) === "global" ? "https://aiplatform.googleapis.com" : `https://${region}-aiplatform.googleapis.com`,
|
|
49
|
+
api: "anthropic-messages",
|
|
50
|
+
apiKey: GCP_VERTEX_CREDENTIALS_MARKER,
|
|
51
|
+
models: buildAnthropicVertexCatalog()
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
//#endregion
|
|
55
|
+
export { ANTHROPIC_VERTEX_DEFAULT_MODEL_ID, buildAnthropicVertexProvider };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { hasAnthropicVertexAvailableAuth, resolveAnthropicVertexConfigApiKey } from "./region.js";
|
|
2
|
+
import { buildAnthropicVertexProvider } from "./provider-catalog.js";
|
|
3
|
+
//#region extensions/anthropic-vertex/provider-discovery.ts
|
|
4
|
+
const PROVIDER_ID = "anthropic-vertex";
|
|
5
|
+
const GCP_VERTEX_CREDENTIALS_MARKER = "gcp-vertex-credentials";
|
|
6
|
+
function mergeImplicitAnthropicVertexProvider(params) {
|
|
7
|
+
const { existing, implicit } = params;
|
|
8
|
+
if (!existing) return implicit;
|
|
9
|
+
return {
|
|
10
|
+
...implicit,
|
|
11
|
+
...existing,
|
|
12
|
+
models: Array.isArray(existing.models) && existing.models.length > 0 ? existing.models : implicit.models
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
function resolveImplicitAnthropicVertexProvider(params) {
|
|
16
|
+
const env = params?.env ?? process.env;
|
|
17
|
+
if (!hasAnthropicVertexAvailableAuth(env)) return null;
|
|
18
|
+
return buildAnthropicVertexProvider({ env });
|
|
19
|
+
}
|
|
20
|
+
async function runAnthropicVertexCatalog(ctx) {
|
|
21
|
+
const implicit = resolveImplicitAnthropicVertexProvider({ env: ctx.env });
|
|
22
|
+
if (!implicit) return null;
|
|
23
|
+
return { provider: mergeImplicitAnthropicVertexProvider({
|
|
24
|
+
existing: ctx.config.models?.providers?.[PROVIDER_ID],
|
|
25
|
+
implicit
|
|
26
|
+
}) };
|
|
27
|
+
}
|
|
28
|
+
const anthropicVertexProviderDiscovery = {
|
|
29
|
+
id: PROVIDER_ID,
|
|
30
|
+
label: "Anthropic Vertex",
|
|
31
|
+
docsPath: "/providers/models",
|
|
32
|
+
auth: [],
|
|
33
|
+
catalog: {
|
|
34
|
+
order: "simple",
|
|
35
|
+
run: runAnthropicVertexCatalog
|
|
36
|
+
},
|
|
37
|
+
resolveConfigApiKey: ({ env }) => resolveAnthropicVertexConfigApiKey(env),
|
|
38
|
+
resolveSyntheticAuth: () => {
|
|
39
|
+
if (!hasAnthropicVertexAvailableAuth()) return;
|
|
40
|
+
return {
|
|
41
|
+
apiKey: GCP_VERTEX_CREDENTIALS_MARKER,
|
|
42
|
+
source: "gcp-vertex-credentials (ADC)",
|
|
43
|
+
mode: "api-key"
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
//#endregion
|
|
48
|
+
export { anthropicVertexProviderDiscovery, anthropicVertexProviderDiscovery as default };
|
package/dist/region.js
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
3
|
+
import { homedir, platform } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { resolveProviderEndpoint } from "openclaw/plugin-sdk/provider-http";
|
|
6
|
+
//#region extensions/anthropic-vertex/region.ts
|
|
7
|
+
const ANTHROPIC_VERTEX_DEFAULT_REGION = "global";
|
|
8
|
+
const ANTHROPIC_VERTEX_REGION_RE = /^[a-z0-9-]+$/;
|
|
9
|
+
const GCP_VERTEX_CREDENTIALS_MARKER = "gcp-vertex-credentials";
|
|
10
|
+
function normalizeOptionalSecretInput(value) {
|
|
11
|
+
if (typeof value !== "string") return;
|
|
12
|
+
return value.trim() || void 0;
|
|
13
|
+
}
|
|
14
|
+
function resolveAnthropicVertexRegion(env = process.env) {
|
|
15
|
+
const region = normalizeOptionalSecretInput(env.GOOGLE_CLOUD_LOCATION) || normalizeOptionalSecretInput(env.CLOUD_ML_REGION);
|
|
16
|
+
return region && ANTHROPIC_VERTEX_REGION_RE.test(region) ? region : ANTHROPIC_VERTEX_DEFAULT_REGION;
|
|
17
|
+
}
|
|
18
|
+
function resolveAnthropicVertexProjectId(env = process.env) {
|
|
19
|
+
return normalizeOptionalSecretInput(env.ANTHROPIC_VERTEX_PROJECT_ID) || normalizeOptionalSecretInput(env.GOOGLE_CLOUD_PROJECT) || normalizeOptionalSecretInput(env.GOOGLE_CLOUD_PROJECT_ID) || resolveAnthropicVertexProjectIdFromAdc(env);
|
|
20
|
+
}
|
|
21
|
+
function resolveAnthropicVertexRegionFromBaseUrl(baseUrl) {
|
|
22
|
+
const endpoint = resolveProviderEndpoint(baseUrl);
|
|
23
|
+
return endpoint.endpointClass === "google-vertex" ? endpoint.googleVertexRegion : void 0;
|
|
24
|
+
}
|
|
25
|
+
function resolveAnthropicVertexClientRegion(params) {
|
|
26
|
+
return resolveAnthropicVertexRegionFromBaseUrl(params?.baseUrl) || resolveAnthropicVertexRegion(params?.env);
|
|
27
|
+
}
|
|
28
|
+
function hasAnthropicVertexMetadataServerAdc(env = process.env) {
|
|
29
|
+
const explicitMetadataOptIn = normalizeOptionalSecretInput(env.ANTHROPIC_VERTEX_USE_GCP_METADATA);
|
|
30
|
+
return explicitMetadataOptIn === "1" || normalizeLowercaseStringOrEmpty(explicitMetadataOptIn) === "true";
|
|
31
|
+
}
|
|
32
|
+
function resolveAnthropicVertexHomeDir(env = process.env) {
|
|
33
|
+
return normalizeOptionalSecretInput(env.HOME) || normalizeOptionalSecretInput(env.USERPROFILE) || homedir();
|
|
34
|
+
}
|
|
35
|
+
function resolveAnthropicVertexDefaultAdcPath(env = process.env) {
|
|
36
|
+
return platform() === "win32" ? join(normalizeOptionalSecretInput(env.APPDATA) ?? join(resolveAnthropicVertexHomeDir(env), "AppData", "Roaming"), "gcloud", "application_default_credentials.json") : join(resolveAnthropicVertexHomeDir(env), ".config", "gcloud", "application_default_credentials.json");
|
|
37
|
+
}
|
|
38
|
+
function resolveAnthropicVertexAdcCredentialsPathCandidate(env = process.env) {
|
|
39
|
+
const explicit = normalizeOptionalSecretInput(env.GOOGLE_APPLICATION_CREDENTIALS);
|
|
40
|
+
if (explicit) return explicit;
|
|
41
|
+
return resolveAnthropicVertexDefaultAdcPath(env);
|
|
42
|
+
}
|
|
43
|
+
function canReadAnthropicVertexAdc(env = process.env) {
|
|
44
|
+
const credentialsPath = resolveAnthropicVertexAdcCredentialsPathCandidate(env);
|
|
45
|
+
if (!credentialsPath) return false;
|
|
46
|
+
try {
|
|
47
|
+
readFileSync(credentialsPath, "utf8");
|
|
48
|
+
return true;
|
|
49
|
+
} catch {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function resolveAnthropicVertexProjectIdFromAdc(env = process.env) {
|
|
54
|
+
const credentialsPath = resolveAnthropicVertexAdcCredentialsPathCandidate(env);
|
|
55
|
+
if (!credentialsPath) return;
|
|
56
|
+
try {
|
|
57
|
+
const parsed = JSON.parse(readFileSync(credentialsPath, "utf8"));
|
|
58
|
+
return normalizeOptionalSecretInput(parsed.project_id) || normalizeOptionalSecretInput(parsed.quota_project_id);
|
|
59
|
+
} catch {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function hasAnthropicVertexCredentials(env = process.env) {
|
|
64
|
+
return hasAnthropicVertexMetadataServerAdc(env) || canReadAnthropicVertexAdc(env);
|
|
65
|
+
}
|
|
66
|
+
function hasAnthropicVertexAvailableAuth(env = process.env) {
|
|
67
|
+
return hasAnthropicVertexCredentials(env);
|
|
68
|
+
}
|
|
69
|
+
function resolveAnthropicVertexConfigApiKey(env = process.env) {
|
|
70
|
+
return hasAnthropicVertexAvailableAuth(env) ? GCP_VERTEX_CREDENTIALS_MARKER : void 0;
|
|
71
|
+
}
|
|
72
|
+
//#endregion
|
|
73
|
+
export { hasAnthropicVertexAvailableAuth, hasAnthropicVertexCredentials, resolveAnthropicVertexClientRegion, resolveAnthropicVertexConfigApiKey, resolveAnthropicVertexProjectId, resolveAnthropicVertexRegion, resolveAnthropicVertexRegionFromBaseUrl };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { resolveAnthropicVertexConfigApiKey } from "./region.js";
|
|
2
|
+
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
|
|
3
|
+
//#region extensions/anthropic-vertex/setup-api.ts
|
|
4
|
+
var setup_api_default = definePluginEntry({
|
|
5
|
+
id: "anthropic-vertex",
|
|
6
|
+
name: "Anthropic Vertex Setup",
|
|
7
|
+
description: "Lightweight Anthropic Vertex setup hooks",
|
|
8
|
+
register(api) {
|
|
9
|
+
api.registerProvider({
|
|
10
|
+
id: "anthropic-vertex",
|
|
11
|
+
label: "Anthropic Vertex",
|
|
12
|
+
auth: [],
|
|
13
|
+
resolveConfigApiKey: ({ env }) => resolveAnthropicVertexConfigApiKey(env)
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
//#endregion
|
|
18
|
+
export { setup_api_default as default };
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { resolveAnthropicVertexClientRegion, resolveAnthropicVertexProjectId } from "./region.js";
|
|
2
|
+
import { AnthropicVertex } from "@anthropic-ai/vertex-sdk";
|
|
3
|
+
import { streamAnthropic } from "@earendil-works/pi-ai";
|
|
4
|
+
import { applyAnthropicPayloadPolicyToParams, resolveAnthropicPayloadPolicy } from "openclaw/plugin-sdk/provider-stream-shared";
|
|
5
|
+
//#region extensions/anthropic-vertex/stream-runtime.ts
|
|
6
|
+
const defaultAnthropicVertexStreamDeps = {
|
|
7
|
+
AnthropicVertex,
|
|
8
|
+
streamAnthropic
|
|
9
|
+
};
|
|
10
|
+
function isClaudeOpus47Model(modelId) {
|
|
11
|
+
return modelId.includes("opus-4-7") || modelId.includes("opus-4.7");
|
|
12
|
+
}
|
|
13
|
+
function isClaudeOpus46Model(modelId) {
|
|
14
|
+
return modelId.includes("opus-4-6") || modelId.includes("opus-4.6");
|
|
15
|
+
}
|
|
16
|
+
function supportsAdaptiveThinking(modelId) {
|
|
17
|
+
return isClaudeOpus47Model(modelId) || isClaudeOpus46Model(modelId) || modelId.includes("sonnet-4-6") || modelId.includes("sonnet-4.6");
|
|
18
|
+
}
|
|
19
|
+
function mapAnthropicAdaptiveEffort(reasoning, modelId) {
|
|
20
|
+
return {
|
|
21
|
+
minimal: "low",
|
|
22
|
+
low: "low",
|
|
23
|
+
medium: "medium",
|
|
24
|
+
high: "high",
|
|
25
|
+
xhigh: isClaudeOpus47Model(modelId) ? "xhigh" : isClaudeOpus46Model(modelId) ? "max" : "high"
|
|
26
|
+
}[reasoning] ?? "high";
|
|
27
|
+
}
|
|
28
|
+
function resolveAnthropicVertexMaxTokens(params) {
|
|
29
|
+
const modelMax = typeof params.modelMaxTokens === "number" && Number.isFinite(params.modelMaxTokens) && params.modelMaxTokens > 0 ? Math.floor(params.modelMaxTokens) : void 0;
|
|
30
|
+
const requested = typeof params.requestedMaxTokens === "number" && Number.isFinite(params.requestedMaxTokens) && params.requestedMaxTokens > 0 ? Math.floor(params.requestedMaxTokens) : void 0;
|
|
31
|
+
if (modelMax !== void 0 && requested !== void 0) return Math.min(requested, modelMax);
|
|
32
|
+
return requested ?? modelMax;
|
|
33
|
+
}
|
|
34
|
+
function createAnthropicVertexOnPayload(params) {
|
|
35
|
+
const policy = resolveAnthropicPayloadPolicy({
|
|
36
|
+
provider: params.model.provider,
|
|
37
|
+
api: params.model.api,
|
|
38
|
+
baseUrl: params.model.baseUrl,
|
|
39
|
+
cacheRetention: params.cacheRetention,
|
|
40
|
+
enableCacheControl: true
|
|
41
|
+
});
|
|
42
|
+
function applyPolicy(payload) {
|
|
43
|
+
if (payload && typeof payload === "object" && !Array.isArray(payload)) applyAnthropicPayloadPolicyToParams(payload, policy);
|
|
44
|
+
return payload;
|
|
45
|
+
}
|
|
46
|
+
return async (payload, model) => {
|
|
47
|
+
const shapedPayload = applyPolicy(payload);
|
|
48
|
+
const nextPayload = await params.onPayload?.(shapedPayload, model);
|
|
49
|
+
if (nextPayload === void 0 || nextPayload === shapedPayload) return shapedPayload;
|
|
50
|
+
return applyPolicy(nextPayload);
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Create a StreamFn that routes through pi-ai's `streamAnthropic` with an
|
|
55
|
+
* injected `AnthropicVertex` client. All streaming, message conversion, and
|
|
56
|
+
* event handling is handled by pi-ai — we only supply the GCP-authenticated
|
|
57
|
+
* client and map SimpleStreamOptions → AnthropicOptions.
|
|
58
|
+
*/
|
|
59
|
+
function createAnthropicVertexStreamFn(projectId, region, baseURL, deps = defaultAnthropicVertexStreamDeps) {
|
|
60
|
+
const client = new deps.AnthropicVertex({
|
|
61
|
+
region,
|
|
62
|
+
...baseURL ? { baseURL } : {},
|
|
63
|
+
...projectId ? { projectId } : {}
|
|
64
|
+
});
|
|
65
|
+
return (model, context, options) => {
|
|
66
|
+
const transportModel = model;
|
|
67
|
+
const maxTokens = resolveAnthropicVertexMaxTokens({
|
|
68
|
+
modelMaxTokens: transportModel.maxTokens,
|
|
69
|
+
requestedMaxTokens: options?.maxTokens
|
|
70
|
+
});
|
|
71
|
+
const opts = {
|
|
72
|
+
client,
|
|
73
|
+
temperature: options?.temperature,
|
|
74
|
+
...maxTokens !== void 0 ? { maxTokens } : {},
|
|
75
|
+
signal: options?.signal,
|
|
76
|
+
cacheRetention: options?.cacheRetention,
|
|
77
|
+
sessionId: options?.sessionId,
|
|
78
|
+
headers: options?.headers,
|
|
79
|
+
onPayload: createAnthropicVertexOnPayload({
|
|
80
|
+
model: transportModel,
|
|
81
|
+
cacheRetention: options?.cacheRetention,
|
|
82
|
+
onPayload: options?.onPayload
|
|
83
|
+
}),
|
|
84
|
+
maxRetryDelayMs: options?.maxRetryDelayMs,
|
|
85
|
+
metadata: options?.metadata
|
|
86
|
+
};
|
|
87
|
+
if (options?.reasoning) if (supportsAdaptiveThinking(model.id)) {
|
|
88
|
+
opts.thinkingEnabled = true;
|
|
89
|
+
opts.effort = mapAnthropicAdaptiveEffort(options.reasoning, model.id);
|
|
90
|
+
} else {
|
|
91
|
+
opts.thinkingEnabled = true;
|
|
92
|
+
const budgets = options.thinkingBudgets;
|
|
93
|
+
opts.thinkingBudgetTokens = (budgets && options.reasoning in budgets ? budgets[options.reasoning] : void 0) ?? 1e4;
|
|
94
|
+
}
|
|
95
|
+
else opts.thinkingEnabled = false;
|
|
96
|
+
return deps.streamAnthropic(transportModel, context, opts);
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
function resolveAnthropicVertexSdkBaseUrl(baseUrl) {
|
|
100
|
+
const trimmed = baseUrl?.trim();
|
|
101
|
+
if (!trimmed) return;
|
|
102
|
+
try {
|
|
103
|
+
const url = new URL(trimmed);
|
|
104
|
+
const normalizedPath = url.pathname.replace(/\/+$/, "");
|
|
105
|
+
if (!normalizedPath || normalizedPath === "") {
|
|
106
|
+
url.pathname = "/v1";
|
|
107
|
+
return url.toString().replace(/\/$/, "");
|
|
108
|
+
}
|
|
109
|
+
if (!normalizedPath.endsWith("/v1")) {
|
|
110
|
+
url.pathname = `${normalizedPath}/v1`;
|
|
111
|
+
return url.toString().replace(/\/$/, "");
|
|
112
|
+
}
|
|
113
|
+
return trimmed;
|
|
114
|
+
} catch {
|
|
115
|
+
return trimmed;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
function createAnthropicVertexStreamFnForModel(model, env = process.env, deps) {
|
|
119
|
+
return createAnthropicVertexStreamFn(resolveAnthropicVertexProjectId(env), resolveAnthropicVertexClientRegion({
|
|
120
|
+
baseUrl: model.baseUrl,
|
|
121
|
+
env
|
|
122
|
+
}), resolveAnthropicVertexSdkBaseUrl(model.baseUrl), deps);
|
|
123
|
+
}
|
|
124
|
+
//#endregion
|
|
125
|
+
export { createAnthropicVertexStreamFn, createAnthropicVertexStreamFnForModel };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "anthropic-vertex",
|
|
3
|
+
"activation": {
|
|
4
|
+
"onStartup": false
|
|
5
|
+
},
|
|
6
|
+
"enabledByDefault": true,
|
|
7
|
+
"providers": ["anthropic-vertex"],
|
|
8
|
+
"providerCatalogEntry": "./provider-discovery.ts",
|
|
9
|
+
"syntheticAuthRefs": ["anthropic-vertex"],
|
|
10
|
+
"nonSecretAuthMarkers": ["gcp-vertex-credentials"],
|
|
11
|
+
"configSchema": {
|
|
12
|
+
"type": "object",
|
|
13
|
+
"additionalProperties": false,
|
|
14
|
+
"properties": {}
|
|
15
|
+
}
|
|
16
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@openclaw/anthropic-vertex-provider",
|
|
3
|
+
"version": "2026.5.12-beta.7",
|
|
4
|
+
"description": "OpenClaw Anthropic Vertex provider plugin",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://github.com/openclaw/openclaw"
|
|
8
|
+
},
|
|
9
|
+
"type": "module",
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"@anthropic-ai/vertex-sdk": "0.16.0",
|
|
12
|
+
"@earendil-works/pi-agent-core": "0.74.0",
|
|
13
|
+
"@earendil-works/pi-ai": "0.74.0"
|
|
14
|
+
},
|
|
15
|
+
"devDependencies": {
|
|
16
|
+
"@openclaw/plugin-sdk": "workspace:*"
|
|
17
|
+
},
|
|
18
|
+
"openclaw": {
|
|
19
|
+
"extensions": [
|
|
20
|
+
"./index.ts"
|
|
21
|
+
],
|
|
22
|
+
"install": {
|
|
23
|
+
"npmSpec": "@openclaw/anthropic-vertex-provider",
|
|
24
|
+
"defaultChoice": "npm",
|
|
25
|
+
"minHostVersion": ">=2026.5.12-beta.6"
|
|
26
|
+
},
|
|
27
|
+
"compat": {
|
|
28
|
+
"pluginApi": ">=2026.5.12-beta.7"
|
|
29
|
+
},
|
|
30
|
+
"build": {
|
|
31
|
+
"openclawVersion": "2026.5.12-beta.7",
|
|
32
|
+
"bundledDist": false
|
|
33
|
+
},
|
|
34
|
+
"release": {
|
|
35
|
+
"publishToClawHub": true,
|
|
36
|
+
"publishToNpm": true
|
|
37
|
+
},
|
|
38
|
+
"runtimeExtensions": [
|
|
39
|
+
"./dist/index.js"
|
|
40
|
+
]
|
|
41
|
+
},
|
|
42
|
+
"files": [
|
|
43
|
+
"dist/**",
|
|
44
|
+
"openclaw.plugin.json"
|
|
45
|
+
],
|
|
46
|
+
"peerDependencies": {
|
|
47
|
+
"openclaw": ">=2026.5.12-beta.7"
|
|
48
|
+
},
|
|
49
|
+
"peerDependenciesMeta": {
|
|
50
|
+
"openclaw": {
|
|
51
|
+
"optional": true
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|