@openclaw/cloudflare-ai-gateway-provider 0.0.0 → 2026.6.9

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/README.md CHANGED
@@ -1,3 +1,12 @@
1
- # @openclaw/cloudflare-ai-gateway-provider
1
+ # OpenClaw Cloudflare AI Gateway Provider
2
2
 
3
- Reserved placeholder for the official OpenClaw plugin package. Use a published release version instead.
3
+ Official OpenClaw provider plugin for Cloudflare AI Gateway.
4
+
5
+ Install from OpenClaw:
6
+
7
+ ```bash
8
+ openclaw plugins install @openclaw/cloudflare-ai-gateway-provider
9
+ openclaw gateway restart
10
+ ```
11
+
12
+ See <https://docs.openclaw.ai/providers/cloudflare-ai-gateway> for setup and configuration.
package/dist/api.js ADDED
@@ -0,0 +1,4 @@
1
+ import { CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_ID, CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_REF, CLOUDFLARE_AI_GATEWAY_PROVIDER_ID, buildCloudflareAiGatewayModelDefinition, resolveCloudflareAiGatewayBaseUrl } from "./models.js";
2
+ import { buildCloudflareAiGatewayCatalogProvider } from "./catalog-provider.js";
3
+ import { applyCloudflareAiGatewayConfig, applyCloudflareAiGatewayProviderConfig, buildCloudflareAiGatewayConfigPatch } from "./onboard.js";
4
+ export { CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_ID, CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_REF, CLOUDFLARE_AI_GATEWAY_PROVIDER_ID, applyCloudflareAiGatewayConfig, applyCloudflareAiGatewayProviderConfig, buildCloudflareAiGatewayCatalogProvider, buildCloudflareAiGatewayConfigPatch, buildCloudflareAiGatewayModelDefinition, resolveCloudflareAiGatewayBaseUrl };
@@ -0,0 +1,45 @@
1
+ import { buildCloudflareAiGatewayModelDefinition, resolveCloudflareAiGatewayBaseUrl } from "./models.js";
2
+ import { coerceSecretRef, resolveNonEnvSecretRefApiKeyMarker } from "openclaw/plugin-sdk/provider-auth";
3
+ import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
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
+ function resolveCloudflareAiGatewayApiKey(cred) {
10
+ if (!cred || cred.type !== "api_key") return;
11
+ const keyRef = coerceSecretRef(cred.keyRef);
12
+ const keyRefId = normalizeOptionalString(keyRef?.id);
13
+ if (keyRef && keyRefId) return keyRef.source === "env" ? keyRefId : resolveNonEnvSecretRefApiKeyMarker(keyRef.source);
14
+ return normalizeOptionalString(cred.key);
15
+ }
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
+ /**
24
+ * Returns a provider catalog entry when credentials and Gateway metadata are
25
+ * complete enough to construct an Anthropic-compatible base URL.
26
+ */
27
+ function buildCloudflareAiGatewayCatalogProvider(params) {
28
+ const apiKey = normalizeOptionalString(params.envApiKey) ?? resolveCloudflareAiGatewayApiKey(params.credential);
29
+ if (!apiKey) return null;
30
+ const { accountId, gatewayId } = resolveCloudflareAiGatewayMetadata(params.credential);
31
+ if (!accountId || !gatewayId) return null;
32
+ const baseUrl = resolveCloudflareAiGatewayBaseUrl({
33
+ accountId,
34
+ gatewayId
35
+ });
36
+ if (!baseUrl) return null;
37
+ return {
38
+ baseUrl,
39
+ api: "anthropic-messages",
40
+ apiKey,
41
+ models: [buildCloudflareAiGatewayModelDefinition()]
42
+ };
43
+ }
44
+ //#endregion
45
+ export { buildCloudflareAiGatewayCatalogProvider };
package/dist/index.js ADDED
@@ -0,0 +1,169 @@
1
+ import { CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_REF } from "./models.js";
2
+ import { buildCloudflareAiGatewayCatalogProvider } from "./catalog-provider.js";
3
+ import { applyCloudflareAiGatewayConfig, buildCloudflareAiGatewayConfigPatch } from "./onboard.js";
4
+ import { wrapCloudflareAiGatewayProviderStream } from "./stream-wrappers.js";
5
+ import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
6
+ import { applyAuthProfileConfig, buildApiKeyCredential, ensureApiKeyFromOptionEnvOrPrompt, ensureAuthProfileStore, listProfilesForProvider, normalizeApiKeyInput, normalizeOptionalSecretInput, upsertAuthProfileWithLock, validateApiKeyInput } from "openclaw/plugin-sdk/provider-auth";
7
+ import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
8
+ //#region extensions/cloudflare-ai-gateway/index.ts
9
+ /**
10
+ * Bundled provider plugin entry for Cloudflare AI Gateway setup, catalog
11
+ * discovery, failover classification, and stream wrapping.
12
+ */
13
+ const PROVIDER_ID = "cloudflare-ai-gateway";
14
+ const PROVIDER_ENV_VAR = "CLOUDFLARE_AI_GATEWAY_API_KEY";
15
+ const PROFILE_ID = "cloudflare-ai-gateway:default";
16
+ async function upsertAuthProfileWithLockOrThrow(params) {
17
+ if (!await upsertAuthProfileWithLock(params)) throw new Error("Failed to update auth profile store; the auth store lock may be busy. Wait a moment and retry.");
18
+ }
19
+ function readRequiredTextInput(value) {
20
+ return typeof value === "string" ? value.trim() : "";
21
+ }
22
+ async function resolveCloudflareGatewayMetadataInteractive(ctx) {
23
+ let accountId = normalizeOptionalString(ctx.accountId) ?? "";
24
+ let gatewayId = normalizeOptionalString(ctx.gatewayId) ?? "";
25
+ if (!accountId) accountId = readRequiredTextInput(await ctx.prompter.text({
26
+ message: "Enter Cloudflare Account ID",
27
+ validate: (val) => readRequiredTextInput(val) ? void 0 : "Account ID is required"
28
+ }));
29
+ if (!gatewayId) gatewayId = readRequiredTextInput(await ctx.prompter.text({
30
+ message: "Enter Cloudflare AI Gateway ID",
31
+ validate: (val) => readRequiredTextInput(val) ? void 0 : "Gateway ID is required"
32
+ }));
33
+ return {
34
+ accountId,
35
+ gatewayId
36
+ };
37
+ }
38
+ var cloudflare_ai_gateway_default = definePluginEntry({
39
+ id: PROVIDER_ID,
40
+ name: "Cloudflare AI Gateway Provider",
41
+ description: "Bundled Cloudflare AI Gateway provider plugin",
42
+ register(api) {
43
+ api.registerProvider({
44
+ id: PROVIDER_ID,
45
+ label: "Cloudflare AI Gateway",
46
+ docsPath: "/providers/cloudflare-ai-gateway",
47
+ envVars: ["CLOUDFLARE_AI_GATEWAY_API_KEY"],
48
+ auth: [{
49
+ id: "api-key",
50
+ label: "Cloudflare AI Gateway",
51
+ hint: "Account ID + Gateway ID + API key",
52
+ kind: "api_key",
53
+ wizard: {
54
+ choiceId: "cloudflare-ai-gateway-api-key",
55
+ choiceLabel: "Cloudflare AI Gateway",
56
+ choiceHint: "Account ID + Gateway ID + API key",
57
+ groupId: "cloudflare-ai-gateway",
58
+ groupLabel: "Cloudflare AI Gateway",
59
+ groupHint: "Account ID + Gateway ID + API key"
60
+ },
61
+ run: async (ctx) => {
62
+ const metadata = await resolveCloudflareGatewayMetadataInteractive({
63
+ accountId: normalizeOptionalSecretInput(ctx.opts?.cloudflareAiGatewayAccountId),
64
+ gatewayId: normalizeOptionalSecretInput(ctx.opts?.cloudflareAiGatewayGatewayId),
65
+ prompter: ctx.prompter
66
+ });
67
+ let capturedSecretInput = "";
68
+ let capturedCredential = false;
69
+ let capturedMode;
70
+ await ensureApiKeyFromOptionEnvOrPrompt({
71
+ token: normalizeOptionalSecretInput(ctx.opts?.cloudflareAiGatewayApiKey),
72
+ tokenProvider: "cloudflare-ai-gateway",
73
+ secretInputMode: ctx.allowSecretRefPrompt === false ? ctx.secretInputMode ?? "plaintext" : ctx.secretInputMode,
74
+ config: ctx.config,
75
+ expectedProviders: [PROVIDER_ID],
76
+ provider: PROVIDER_ID,
77
+ envLabel: PROVIDER_ENV_VAR,
78
+ promptMessage: "Enter Cloudflare AI Gateway API key",
79
+ normalize: normalizeApiKeyInput,
80
+ validate: validateApiKeyInput,
81
+ prompter: ctx.prompter,
82
+ setCredential: async (apiKey, mode) => {
83
+ capturedSecretInput = apiKey;
84
+ capturedCredential = true;
85
+ capturedMode = mode;
86
+ }
87
+ });
88
+ if (!capturedCredential) throw new Error("Missing Cloudflare AI Gateway API key.");
89
+ return {
90
+ profiles: [{
91
+ profileId: PROFILE_ID,
92
+ credential: buildApiKeyCredential(PROVIDER_ID, capturedSecretInput ?? "", {
93
+ accountId: metadata.accountId,
94
+ gatewayId: metadata.gatewayId
95
+ }, capturedMode ? { secretInputMode: capturedMode } : void 0)
96
+ }],
97
+ configPatch: buildCloudflareAiGatewayConfigPatch(metadata),
98
+ defaultModel: CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_REF
99
+ };
100
+ },
101
+ runNonInteractive: async (ctx) => {
102
+ const authStore = ensureAuthProfileStore(ctx.agentDir, { allowKeychainPrompt: false });
103
+ const storedMetadata = authStore.profiles[PROFILE_ID]?.type === "api_key" ? {
104
+ accountId: normalizeOptionalString(authStore.profiles[PROFILE_ID]?.metadata?.accountId),
105
+ gatewayId: normalizeOptionalString(authStore.profiles[PROFILE_ID]?.metadata?.gatewayId)
106
+ } : {};
107
+ const accountId = normalizeOptionalSecretInput(ctx.opts.cloudflareAiGatewayAccountId) ?? storedMetadata.accountId;
108
+ const gatewayId = normalizeOptionalSecretInput(ctx.opts.cloudflareAiGatewayGatewayId) ?? storedMetadata.gatewayId;
109
+ if (!accountId || !gatewayId) {
110
+ ctx.runtime.error("Cloudflare AI Gateway setup requires --cloudflare-ai-gateway-account-id and --cloudflare-ai-gateway-gateway-id.");
111
+ ctx.runtime.exit(1);
112
+ return null;
113
+ }
114
+ const resolved = await ctx.resolveApiKey({
115
+ provider: PROVIDER_ID,
116
+ flagValue: normalizeOptionalSecretInput(ctx.opts.cloudflareAiGatewayApiKey),
117
+ flagName: "--cloudflare-ai-gateway-api-key",
118
+ envVar: PROVIDER_ENV_VAR
119
+ });
120
+ if (!resolved) return null;
121
+ if (resolved.source !== "profile") {
122
+ const credential = ctx.toApiKeyCredential({
123
+ provider: PROVIDER_ID,
124
+ resolved,
125
+ metadata: {
126
+ accountId,
127
+ gatewayId
128
+ }
129
+ });
130
+ if (!credential) return null;
131
+ await upsertAuthProfileWithLockOrThrow({
132
+ profileId: PROFILE_ID,
133
+ credential,
134
+ agentDir: ctx.agentDir
135
+ });
136
+ }
137
+ return applyCloudflareAiGatewayConfig(applyAuthProfileConfig(ctx.config, {
138
+ profileId: PROFILE_ID,
139
+ provider: PROVIDER_ID,
140
+ mode: "api_key"
141
+ }), {
142
+ accountId,
143
+ gatewayId
144
+ });
145
+ }
146
+ }],
147
+ catalog: {
148
+ order: "late",
149
+ run: async (ctx) => {
150
+ const authStore = ensureAuthProfileStore(ctx.agentDir, { allowKeychainPrompt: false });
151
+ const envManagedApiKey = normalizeOptionalString(ctx.env[PROVIDER_ENV_VAR]) ? PROVIDER_ENV_VAR : void 0;
152
+ for (const profileId of listProfilesForProvider(authStore, PROVIDER_ID)) {
153
+ const provider = buildCloudflareAiGatewayCatalogProvider({
154
+ credential: authStore.profiles[profileId],
155
+ envApiKey: envManagedApiKey
156
+ });
157
+ if (!provider) continue;
158
+ return { provider };
159
+ }
160
+ return null;
161
+ }
162
+ },
163
+ classifyFailoverReason: ({ errorMessage }) => /\bworkers?_ai\b.*\b(?:rate|limit|quota)\b/i.test(errorMessage) ? "rate_limit" : void 0,
164
+ wrapStreamFn: wrapCloudflareAiGatewayProviderStream
165
+ });
166
+ }
167
+ });
168
+ //#endregion
169
+ export { cloudflare_ai_gateway_default as default };
package/dist/models.js ADDED
@@ -0,0 +1,42 @@
1
+ //#region extensions/cloudflare-ai-gateway/models.ts
2
+ /** Provider id used in model refs and auth profiles. */
3
+ const CLOUDFLARE_AI_GATEWAY_PROVIDER_ID = "cloudflare-ai-gateway";
4
+ /** Default Cloudflare AI Gateway model id exposed by the bundled provider. */
5
+ const CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_ID = "claude-sonnet-4-6";
6
+ /** Fully-qualified default model ref used by onboarding. */
7
+ const CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_REF = `${CLOUDFLARE_AI_GATEWAY_PROVIDER_ID}/${CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_ID}`;
8
+ const CLOUDFLARE_AI_GATEWAY_DEFAULT_CONTEXT_WINDOW = 2e5;
9
+ const CLOUDFLARE_AI_GATEWAY_DEFAULT_MAX_TOKENS = 64e3;
10
+ const CLOUDFLARE_AI_GATEWAY_DEFAULT_COST = {
11
+ input: 3,
12
+ output: 15,
13
+ cacheRead: .3,
14
+ cacheWrite: 3.75
15
+ };
16
+ /**
17
+ * Builds a provider model definition, allowing tests/catalog code to override
18
+ * the model id while preserving Cloudflare defaults.
19
+ */
20
+ function buildCloudflareAiGatewayModelDefinition(params) {
21
+ return {
22
+ id: params?.id?.trim() || "claude-sonnet-4-6",
23
+ name: params?.name ?? "Claude Sonnet 4.6",
24
+ reasoning: params?.reasoning ?? true,
25
+ input: params?.input ?? ["text", "image"],
26
+ cost: CLOUDFLARE_AI_GATEWAY_DEFAULT_COST,
27
+ contextWindow: CLOUDFLARE_AI_GATEWAY_DEFAULT_CONTEXT_WINDOW,
28
+ maxTokens: CLOUDFLARE_AI_GATEWAY_DEFAULT_MAX_TOKENS
29
+ };
30
+ }
31
+ /**
32
+ * Constructs the Anthropic Messages base URL for a Cloudflare account/gateway
33
+ * pair, returning an empty string for incomplete metadata.
34
+ */
35
+ function resolveCloudflareAiGatewayBaseUrl(params) {
36
+ const accountId = params.accountId.trim();
37
+ const gatewayId = params.gatewayId.trim();
38
+ if (!accountId || !gatewayId) return "";
39
+ return `https://gateway.ai.cloudflare.com/v1/${accountId}/${gatewayId}/anthropic`;
40
+ }
41
+ //#endregion
42
+ export { CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_ID, CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_REF, CLOUDFLARE_AI_GATEWAY_PROVIDER_ID, buildCloudflareAiGatewayModelDefinition, resolveCloudflareAiGatewayBaseUrl };
@@ -0,0 +1,60 @@
1
+ import { CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_REF, buildCloudflareAiGatewayModelDefinition, resolveCloudflareAiGatewayBaseUrl } from "./models.js";
2
+ import { applyAgentDefaultModelPrimary, applyProviderConfigWithDefaultModel } from "openclaw/plugin-sdk/provider-onboard";
3
+ //#region extensions/cloudflare-ai-gateway/onboard.ts
4
+ /**
5
+ * Config patch helpers used by Cloudflare AI Gateway interactive and
6
+ * non-interactive onboarding flows.
7
+ */
8
+ /**
9
+ * Builds the minimal config patch for provider setup and default model aliasing.
10
+ */
11
+ function buildCloudflareAiGatewayConfigPatch(params) {
12
+ return {
13
+ models: { providers: { "cloudflare-ai-gateway": {
14
+ baseUrl: resolveCloudflareAiGatewayBaseUrl(params),
15
+ api: "anthropic-messages",
16
+ models: [buildCloudflareAiGatewayModelDefinition()]
17
+ } } },
18
+ agents: { defaults: { models: { [CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_REF]: { alias: "Cloudflare AI Gateway" } } } }
19
+ };
20
+ }
21
+ /**
22
+ * Applies provider model config while preserving existing agent model aliases.
23
+ */
24
+ function applyCloudflareAiGatewayProviderConfig(cfg, params) {
25
+ const models = { ...cfg.agents?.defaults?.models };
26
+ models[CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_REF] = {
27
+ ...models[CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_REF],
28
+ alias: models[CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_REF]?.alias ?? "Cloudflare AI Gateway"
29
+ };
30
+ const existingProvider = cfg.models?.providers?.["cloudflare-ai-gateway"];
31
+ const baseUrl = params?.accountId && params?.gatewayId ? resolveCloudflareAiGatewayBaseUrl({
32
+ accountId: params.accountId,
33
+ gatewayId: params.gatewayId
34
+ }) : typeof existingProvider?.baseUrl === "string" ? existingProvider.baseUrl : void 0;
35
+ if (!baseUrl) return {
36
+ ...cfg,
37
+ agents: {
38
+ ...cfg.agents,
39
+ defaults: {
40
+ ...cfg.agents?.defaults,
41
+ models
42
+ }
43
+ }
44
+ };
45
+ return applyProviderConfigWithDefaultModel(cfg, {
46
+ agentModels: models,
47
+ providerId: "cloudflare-ai-gateway",
48
+ api: "anthropic-messages",
49
+ baseUrl,
50
+ defaultModel: buildCloudflareAiGatewayModelDefinition()
51
+ });
52
+ }
53
+ /**
54
+ * Applies Cloudflare AI Gateway config and makes its default model primary.
55
+ */
56
+ function applyCloudflareAiGatewayConfig(cfg, params) {
57
+ return applyAgentDefaultModelPrimary(applyCloudflareAiGatewayProviderConfig(cfg, params), CLOUDFLARE_AI_GATEWAY_DEFAULT_MODEL_REF);
58
+ }
59
+ //#endregion
60
+ export { applyCloudflareAiGatewayConfig, applyCloudflareAiGatewayProviderConfig, buildCloudflareAiGatewayConfigPatch };
@@ -0,0 +1,30 @@
1
+ import { createAnthropicThinkingPrefillPayloadWrapper } from "openclaw/plugin-sdk/provider-stream-shared";
2
+ import { createSubsystemLogger } from "openclaw/plugin-sdk/runtime-env";
3
+ //#region extensions/cloudflare-ai-gateway/stream-wrappers.ts
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) => {
14
+ log.warn(`removed ${stripped} trailing assistant prefill message${stripped === 1 ? "" : "s"} because Anthropic extended thinking requires conversations to end with a user turn`);
15
+ });
16
+ }
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
+ /** Test-only access to wrapper decisions and logger injection points. */
25
+ const testing = {
26
+ log,
27
+ shouldPatchAnthropicMessagesPayload
28
+ };
29
+ //#endregion
30
+ export { testing as __testing, testing, createCloudflareAiGatewayAnthropicThinkingPrefillWrapper, wrapCloudflareAiGatewayProviderStream };
@@ -0,0 +1,12 @@
1
+ {
2
+ "name": "@openclaw/cloudflare-ai-gateway-provider",
3
+ "version": "2026.6.9",
4
+ "lockfileVersion": 3,
5
+ "requires": true,
6
+ "packages": {
7
+ "": {
8
+ "name": "@openclaw/cloudflare-ai-gateway-provider",
9
+ "version": "2026.6.9"
10
+ }
11
+ }
12
+ }
@@ -0,0 +1,49 @@
1
+ {
2
+ "id": "cloudflare-ai-gateway",
3
+ "activation": {
4
+ "onStartup": false
5
+ },
6
+ "enabledByDefault": true,
7
+ "providers": ["cloudflare-ai-gateway"],
8
+ "modelPricing": {
9
+ "providers": {
10
+ "cloudflare-ai-gateway": {
11
+ "openRouter": {
12
+ "passthroughProviderModel": true
13
+ },
14
+ "liteLLM": {
15
+ "passthroughProviderModel": true
16
+ }
17
+ }
18
+ }
19
+ },
20
+ "setup": {
21
+ "providers": [
22
+ {
23
+ "id": "cloudflare-ai-gateway",
24
+ "envVars": ["CLOUDFLARE_AI_GATEWAY_API_KEY"]
25
+ }
26
+ ]
27
+ },
28
+ "providerAuthChoices": [
29
+ {
30
+ "provider": "cloudflare-ai-gateway",
31
+ "method": "api-key",
32
+ "choiceId": "cloudflare-ai-gateway-api-key",
33
+ "choiceLabel": "Cloudflare AI Gateway",
34
+ "choiceHint": "Account ID + Gateway ID + API key",
35
+ "groupId": "cloudflare-ai-gateway",
36
+ "groupLabel": "Cloudflare AI Gateway",
37
+ "groupHint": "Account ID + Gateway ID + API key",
38
+ "optionKey": "cloudflareAiGatewayApiKey",
39
+ "cliFlag": "--cloudflare-ai-gateway-api-key",
40
+ "cliOption": "--cloudflare-ai-gateway-api-key <key>",
41
+ "cliDescription": "Cloudflare AI Gateway API key"
42
+ }
43
+ ],
44
+ "configSchema": {
45
+ "type": "object",
46
+ "additionalProperties": false,
47
+ "properties": {}
48
+ }
49
+ }
package/package.json CHANGED
@@ -1,14 +1,50 @@
1
1
  {
2
2
  "name": "@openclaw/cloudflare-ai-gateway-provider",
3
- "version": "0.0.0",
4
- "description": "Reserved package name for an official OpenClaw plugin.",
5
- "license": "MIT",
3
+ "version": "2026.6.9",
4
+ "description": "OpenClaw Cloudflare AI Gateway provider plugin.",
6
5
  "repository": {
7
6
  "type": "git",
8
- "url": "git+https://github.com/openclaw/openclaw.git"
7
+ "url": "https://github.com/openclaw/openclaw"
9
8
  },
10
- "publishConfig": {
11
- "access": "public",
12
- "tag": "placeholder"
13
- }
9
+ "type": "module",
10
+ "openclaw": {
11
+ "extensions": [
12
+ "./index.ts"
13
+ ],
14
+ "install": {
15
+ "clawhubSpec": "clawhub:@openclaw/cloudflare-ai-gateway-provider",
16
+ "npmSpec": "@openclaw/cloudflare-ai-gateway-provider",
17
+ "defaultChoice": "npm",
18
+ "minHostVersion": ">=2026.6.8"
19
+ },
20
+ "compat": {
21
+ "pluginApi": ">=2026.6.9"
22
+ },
23
+ "build": {
24
+ "openclawVersion": "2026.6.9",
25
+ "bundledDist": false
26
+ },
27
+ "release": {
28
+ "publishToClawHub": true,
29
+ "publishToNpm": true
30
+ },
31
+ "runtimeExtensions": [
32
+ "./dist/index.js"
33
+ ]
34
+ },
35
+ "files": [
36
+ "dist/**",
37
+ "openclaw.plugin.json",
38
+ "npm-shrinkwrap.json",
39
+ "README.md"
40
+ ],
41
+ "peerDependencies": {
42
+ "openclaw": ">=2026.6.9"
43
+ },
44
+ "peerDependenciesMeta": {
45
+ "openclaw": {
46
+ "optional": true
47
+ }
48
+ },
49
+ "bundledDependencies": []
14
50
  }