@openclaw/cloudflare-ai-gateway-provider 2026.9.5 → 2026.9.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/assets/icon.png CHANGED
Binary file
@@ -2,10 +2,6 @@ import { buildCloudflareAiGatewayModelDefinition, resolveCloudflareAiGatewayBase
2
2
  import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
3
3
  import { coerceSecretRef, resolveNonEnvSecretRefApiKeyMarker } from "openclaw/plugin-sdk/secret-input";
4
4
  //#region extensions/cloudflare-ai-gateway/catalog-provider.ts
5
- /**
6
- * Builds runtime model catalog entries from stored Cloudflare AI Gateway auth
7
- * profiles.
8
- */
9
5
  function resolveCloudflareAiGatewayApiKey(cred) {
10
6
  if (!cred || cred.type !== "api_key") return;
11
7
  const keyRef = coerceSecretRef(cred.keyRef);
@@ -13,13 +9,6 @@ function resolveCloudflareAiGatewayApiKey(cred) {
13
9
  if (keyRef && keyRefId) return keyRef.source === "env" ? keyRefId : resolveNonEnvSecretRefApiKeyMarker(keyRef.source);
14
10
  return normalizeOptionalString(cred.key);
15
11
  }
16
- function resolveCloudflareAiGatewayMetadata(cred) {
17
- if (!cred || cred.type !== "api_key") return {};
18
- return {
19
- accountId: normalizeOptionalString(cred.metadata?.accountId),
20
- gatewayId: normalizeOptionalString(cred.metadata?.gatewayId)
21
- };
22
- }
23
12
  /**
24
13
  * Returns a provider catalog entry when credentials and Gateway metadata are
25
14
  * complete enough to construct an Anthropic-compatible base URL.
@@ -27,15 +16,15 @@ function resolveCloudflareAiGatewayMetadata(cred) {
27
16
  function buildCloudflareAiGatewayCatalogProvider(params) {
28
17
  const apiKey = normalizeOptionalString(params.envApiKey) ?? resolveCloudflareAiGatewayApiKey(params.credential);
29
18
  if (!apiKey) return null;
30
- const { accountId, gatewayId } = resolveCloudflareAiGatewayMetadata(params.credential);
19
+ const metadata = params.credential?.type === "api_key" ? params.credential.metadata : void 0;
20
+ const accountId = normalizeOptionalString(metadata?.accountId);
21
+ const gatewayId = normalizeOptionalString(metadata?.gatewayId);
31
22
  if (!accountId || !gatewayId) return null;
32
- const baseUrl = resolveCloudflareAiGatewayBaseUrl({
33
- accountId,
34
- gatewayId
35
- });
36
- if (!baseUrl) return null;
37
23
  return {
38
- baseUrl,
24
+ baseUrl: resolveCloudflareAiGatewayBaseUrl({
25
+ accountId,
26
+ gatewayId
27
+ }),
39
28
  api: "anthropic-messages",
40
29
  apiKey,
41
30
  models: [buildCloudflareAiGatewayModelDefinition()]
package/dist/index.js CHANGED
@@ -3,8 +3,8 @@ import { buildCloudflareAiGatewayCatalogProvider } from "./catalog-provider.js";
3
3
  import { applyCloudflareAiGatewayConnectionConfig, applyCloudflareAiGatewayProviderConnectionConfig } from "./onboard.js";
4
4
  import { wrapCloudflareAiGatewayProviderStream } from "./stream-wrappers.js";
5
5
  import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
6
- import { applyAuthProfileConfig, buildApiKeyCredential, ensureApiKeyFromOptionEnvOrPrompt, ensureAuthProfileStore, listProfilesForProvider, normalizeApiKeyInput, normalizeOptionalSecretInput, validateApiKeyInput } from "openclaw/plugin-sdk/provider-auth";
7
- import { upsertAuthProfileWithLockOrThrow } from "openclaw/plugin-sdk/provider-auth-api-key";
6
+ import { applyAuthProfileConfig, buildApiKeyCredential, ensureAuthProfileStore, listProfilesForProvider, normalizeOptionalSecretInput } from "openclaw/plugin-sdk/provider-auth";
7
+ import { captureProviderApiKey, persistProviderApiKey } from "openclaw/plugin-sdk/provider-auth-api-key";
8
8
  import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
9
9
  //#region extensions/cloudflare-ai-gateway/index.ts
10
10
  /**
@@ -62,36 +62,22 @@ var cloudflare_ai_gateway_default = definePluginEntry({
62
62
  gatewayId: normalizeOptionalSecretInput(ctx.opts?.cloudflareAiGatewayGatewayId),
63
63
  prompter: ctx.prompter
64
64
  });
65
- let capturedSecretInput = "";
66
- let capturedCredential = false;
67
- let capturedMode;
68
- await ensureApiKeyFromOptionEnvOrPrompt({
65
+ const { input, mode } = await captureProviderApiKey(ctx, {
69
66
  token: normalizeOptionalSecretInput(ctx.opts?.cloudflareAiGatewayApiKey),
70
67
  tokenProvider: "cloudflare-ai-gateway",
71
- secretInputMode: ctx.allowSecretRefPrompt === false ? ctx.secretInputMode ?? "plaintext" : ctx.secretInputMode,
72
- config: ctx.config,
73
- workspaceDir: ctx.workspaceDir,
74
68
  expectedProviders: [PROVIDER_ID],
75
69
  provider: PROVIDER_ID,
76
70
  envLabel: PROVIDER_ENV_VAR,
77
71
  promptMessage: "Enter Cloudflare AI Gateway API key",
78
- normalize: normalizeApiKeyInput,
79
- validate: validateApiKeyInput,
80
- prompter: ctx.prompter,
81
- setCredential: async (apiKey, mode) => {
82
- capturedSecretInput = apiKey;
83
- capturedCredential = true;
84
- capturedMode = mode;
85
- }
72
+ missingInputMessage: "Missing Cloudflare AI Gateway API key."
86
73
  });
87
- if (!capturedCredential) throw new Error("Missing Cloudflare AI Gateway API key.");
88
74
  return {
89
75
  profiles: [{
90
76
  profileId: PROFILE_ID,
91
- credential: buildApiKeyCredential(PROVIDER_ID, capturedSecretInput ?? "", {
77
+ credential: buildApiKeyCredential(PROVIDER_ID, input, {
92
78
  accountId: metadata.accountId,
93
79
  gatewayId: metadata.gatewayId
94
- }, capturedMode ? { secretInputMode: capturedMode } : void 0)
80
+ }, mode ? { secretInputMode: mode } : void 0)
95
81
  }],
96
82
  configPatch: applyCloudflareAiGatewayProviderConnectionConfig(ctx.config, metadata),
97
83
  defaultModel: CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_REF
@@ -117,22 +103,14 @@ var cloudflare_ai_gateway_default = definePluginEntry({
117
103
  envVar: PROVIDER_ENV_VAR
118
104
  });
119
105
  if (!resolved) return null;
120
- if (resolved.source !== "profile") {
121
- const credential = ctx.toApiKeyCredential({
122
- provider: PROVIDER_ID,
123
- resolved,
124
- metadata: {
125
- accountId,
126
- gatewayId
127
- }
128
- });
129
- if (!credential) return null;
130
- await upsertAuthProfileWithLockOrThrow({
131
- profileId: PROFILE_ID,
132
- credential,
133
- agentDir: ctx.agentDir
134
- });
135
- }
106
+ if (!await persistProviderApiKey(ctx, PROFILE_ID, {
107
+ provider: PROVIDER_ID,
108
+ resolved,
109
+ metadata: {
110
+ accountId,
111
+ gatewayId
112
+ }
113
+ })) return null;
136
114
  const next = applyAuthProfileConfig(ctx.config, {
137
115
  profileId: PROFILE_ID,
138
116
  provider: PROVIDER_ID,
@@ -2,24 +2,11 @@ import { createAnthropicThinkingPrefillPayloadWrapper } from "openclaw/plugin-sd
2
2
  import { createSubsystemLogger } from "openclaw/plugin-sdk/runtime-env";
3
3
  //#region extensions/cloudflare-ai-gateway/stream-wrappers.ts
4
4
  const log = createSubsystemLogger("cloudflare-ai-gateway-stream");
5
- function shouldPatchAnthropicMessagesPayload(model) {
6
- return model?.api === void 0 || model.api === "anthropic-messages";
7
- }
8
- /**
9
- * Creates a wrapper that removes trailing assistant prefill messages before
10
- * extended-thinking Anthropic requests are sent through Cloudflare.
11
- */
12
- function createCloudflareAiGatewayAnthropicThinkingPrefillWrapper(baseStreamFn) {
13
- return createAnthropicThinkingPrefillPayloadWrapper(baseStreamFn, (stripped) => {
5
+ function wrapCloudflareAiGatewayProviderStream(ctx) {
6
+ if (ctx.model?.api !== void 0 && ctx.model.api !== "anthropic-messages") return ctx.streamFn;
7
+ return createAnthropicThinkingPrefillPayloadWrapper(ctx.streamFn, (stripped) => {
14
8
  log.warn(`removed ${stripped} trailing assistant prefill message${stripped === 1 ? "" : "s"} because Anthropic extended thinking requires conversations to end with a user turn`);
15
9
  });
16
10
  }
17
- /**
18
- * Applies the Anthropic payload wrapper only for Anthropic-compatible models.
19
- */
20
- function wrapCloudflareAiGatewayProviderStream(ctx) {
21
- if (!shouldPatchAnthropicMessagesPayload(ctx.model)) return ctx.streamFn;
22
- return createCloudflareAiGatewayAnthropicThinkingPrefillWrapper(ctx.streamFn);
23
- }
24
11
  //#endregion
25
12
  export { wrapCloudflareAiGatewayProviderStream };
@@ -9,6 +9,9 @@
9
9
  "modelPricing": {
10
10
  "providers": {
11
11
  "cloudflare-ai-gateway": {
12
+ "modelsDev": {
13
+ "passthroughProviderModel": true
14
+ },
12
15
  "openRouter": {
13
16
  "passthroughProviderModel": true
14
17
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/cloudflare-ai-gateway-provider",
3
- "version": "2026.9.5",
3
+ "version": "2026.9.7",
4
4
  "description": "OpenClaw Cloudflare AI Gateway provider plugin.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -18,10 +18,10 @@
18
18
  "minHostVersion": ">=2026.6.8"
19
19
  },
20
20
  "compat": {
21
- "pluginApi": ">=2026.9.5"
21
+ "pluginApi": ">=2026.9.7"
22
22
  },
23
23
  "build": {
24
- "openclawVersion": "2026.9.5",
24
+ "openclawVersion": "2026.9.7",
25
25
  "bundledDist": false
26
26
  },
27
27
  "release": {
@@ -40,7 +40,7 @@
40
40
  "assets/activity.svg"
41
41
  ],
42
42
  "peerDependencies": {
43
- "openclaw": ">=2026.9.5"
43
+ "openclaw": ">=2026.9.7"
44
44
  },
45
45
  "peerDependenciesMeta": {
46
46
  "openclaw": {