@zackbart/connecta 0.15.1 → 0.16.0
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/AGENTS.md +28 -15
- package/CHANGELOG.md +466 -0
- package/README.md +19 -4
- package/bin/connecta.mjs +44 -3
- package/dist/access-tokens.d.ts +0 -1
- package/dist/access-tokens.js +0 -1
- package/dist/activity.d.ts +50 -2
- package/dist/activity.js +34 -1
- package/dist/apps-shell.d.ts +0 -1
- package/dist/apps-shell.js +0 -1
- package/dist/auth/bearer.d.ts +0 -1
- package/dist/auth/bearer.js +0 -1
- package/dist/auth/clerk.d.ts +0 -1
- package/dist/auth/clerk.js +45 -9
- package/dist/auth/downstream-oauth.d.ts +0 -1
- package/dist/auth/downstream-oauth.js +0 -1
- package/dist/call-admission.d.ts +0 -1
- package/dist/call-admission.js +0 -1
- package/dist/catalog-drift.d.ts +99 -0
- package/dist/catalog-drift.js +251 -0
- package/dist/catalog-fingerprint.d.ts +0 -1
- package/dist/catalog-fingerprint.js +0 -1
- package/dist/catalog-limits.d.ts +0 -1
- package/dist/catalog-limits.js +0 -1
- package/dist/catalog-service.d.ts +0 -1
- package/dist/catalog-service.js +0 -1
- package/dist/catalog.d.ts +0 -1
- package/dist/catalog.js +0 -1
- package/dist/concurrency.d.ts +0 -1
- package/dist/concurrency.js +0 -1
- package/dist/connector-scope.d.ts +0 -1
- package/dist/connector-scope.js +0 -1
- package/dist/connectors/api.d.ts +29 -21
- package/dist/connectors/api.js +45 -19
- package/dist/connectors/guarded-fetch.d.ts +106 -0
- package/dist/connectors/guarded-fetch.js +289 -0
- package/dist/connectors/remote-mcp.d.ts +0 -1
- package/dist/connectors/remote-mcp.js +0 -1
- package/dist/credentials.d.ts +0 -1
- package/dist/credentials.js +0 -1
- package/dist/errors.d.ts +0 -1
- package/dist/errors.js +0 -1
- package/dist/execute.d.ts +0 -1
- package/dist/execute.js +0 -1
- package/dist/executor-admission.d.ts +11 -1
- package/dist/executor-admission.js +28 -1
- package/dist/executor-result.d.ts +0 -1
- package/dist/executor-result.js +0 -1
- package/dist/executors/quickjs-child.d.ts +0 -1
- package/dist/executors/quickjs-child.js +0 -1
- package/dist/executors/quickjs-protocol.d.ts +0 -1
- package/dist/executors/quickjs-protocol.js +0 -1
- package/dist/executors/quickjs-runtime.d.ts +0 -1
- package/dist/executors/quickjs-runtime.js +0 -1
- package/dist/executors/quickjs.d.ts +0 -1
- package/dist/executors/quickjs.js +2 -1
- package/dist/favicon.d.ts +0 -1
- package/dist/favicon.js +0 -1
- package/dist/index.d.ts +2 -3
- package/dist/index.js +24 -7
- package/dist/invocation.d.ts +0 -1
- package/dist/invocation.js +0 -1
- package/dist/json-schema.d.ts +0 -1
- package/dist/json-schema.js +0 -1
- package/dist/mcp-result.d.ts +0 -1
- package/dist/mcp-result.js +0 -1
- package/dist/meta-tools.d.ts +0 -1
- package/dist/meta-tools.js +0 -1
- package/dist/node.d.ts +0 -1
- package/dist/node.js +0 -1
- package/dist/operator-ui/generated.d.ts +2 -3
- package/dist/operator-ui/generated.js +3 -4
- package/dist/operator-ui/model.d.ts +10 -1
- package/dist/operator-ui/model.js +0 -1
- package/dist/operator-ui/view.d.ts +167 -0
- package/dist/operator-ui/view.js +270 -0
- package/dist/providers/cloudflare.d.ts +0 -1
- package/dist/providers/cloudflare.js +250 -276
- package/dist/providers/linear.d.ts +26 -5
- package/dist/providers/linear.js +32 -61
- package/dist/providers/mixpanel.d.ts +35 -4
- package/dist/providers/mixpanel.js +53 -79
- package/dist/providers/notion.d.ts +0 -1
- package/dist/providers/notion.js +87 -42
- package/dist/providers/stripe.d.ts +13 -1
- package/dist/providers/stripe.js +31 -60
- package/dist/registry.d.ts +34 -2
- package/dist/registry.js +85 -5
- package/dist/retired-toolkits.d.ts +0 -1
- package/dist/retired-toolkits.js +0 -1
- package/dist/routes/access-tokens.d.ts +0 -1
- package/dist/routes/access-tokens.js +0 -1
- package/dist/routes/activity.d.ts +0 -1
- package/dist/routes/activity.js +0 -1
- package/dist/routes/credentials.d.ts +0 -1
- package/dist/routes/credentials.js +0 -1
- package/dist/routes/mcp.d.ts +0 -1
- package/dist/routes/mcp.js +0 -1
- package/dist/routes/oauth.d.ts +0 -1
- package/dist/routes/oauth.js +0 -1
- package/dist/routes/shared.d.ts +2 -1
- package/dist/routes/shared.js +0 -1
- package/dist/routes/ui.d.ts +0 -1
- package/dist/routes/ui.js +0 -1
- package/dist/server.d.ts +0 -1
- package/dist/server.js +11 -1
- package/dist/skills.d.ts +0 -1
- package/dist/skills.js +0 -1
- package/dist/storage/file.d.ts +0 -1
- package/dist/storage/file.js +0 -1
- package/dist/storage/memory.d.ts +0 -1
- package/dist/storage/memory.js +0 -1
- package/dist/timeout.d.ts +0 -1
- package/dist/timeout.js +0 -1
- package/dist/tool-safety.d.ts +0 -1
- package/dist/tool-safety.js +0 -1
- package/dist/types.d.ts +45 -1
- package/dist/types.js +0 -1
- package/dist/ui.d.ts +0 -1
- package/dist/ui.js +13 -137
- package/dist/validate.d.ts +13 -15
- package/dist/validate.js +24 -11
- package/dist/version.d.ts +1 -2
- package/dist/version.js +1 -2
- package/documentation/architecture.md +186 -5
- package/documentation/auth.md +11 -0
- package/documentation/call-admission.md +142 -6
- package/documentation/cloudflare.md +58 -8
- package/documentation/code-mode.md +12 -12
- package/documentation/connector-guides.md +172 -5
- package/documentation/connectors.md +89 -0
- package/documentation/linear.md +20 -2
- package/documentation/mcp-ui-design.md +2 -2
- package/documentation/mixpanel.md +42 -9
- package/documentation/notion.md +16 -0
- package/documentation/operations.md +283 -5
- package/documentation/operator-ui.md +120 -5
- package/documentation/provider-audit.md +160 -0
- package/documentation/provider-conventions.md +631 -0
- package/documentation/request-admission.md +167 -5
- package/documentation/rich-output-design.md +1 -2
- package/documentation/stripe.md +15 -0
- package/ethos.md +13 -8
- package/examples/worker/README.md +96 -12
- package/examples/worker/src/index.ts +46 -1
- package/examples/worker/wrangler.jsonc +14 -1
- package/package.json +4 -5
- package/templates/node/.dockerignore +10 -0
- package/templates/node/.env.example +40 -3
- package/templates/node/AGENTS.md +11 -1
- package/templates/node/Dockerfile +49 -0
- package/templates/node/README.md +117 -2
- package/templates/node/docker-compose.yml +39 -0
- package/templates/node/package.json +1 -1
- package/templates/node/src/file-activity.ts +182 -0
- package/templates/node/src/index.ts +80 -4
- package/assets/connecta-clay-hero.png +0 -0
- package/dist/access-tokens.d.ts.map +0 -1
- package/dist/access-tokens.js.map +0 -1
- package/dist/activity.d.ts.map +0 -1
- package/dist/activity.js.map +0 -1
- package/dist/apps-shell.d.ts.map +0 -1
- package/dist/apps-shell.js.map +0 -1
- package/dist/auth/bearer.d.ts.map +0 -1
- package/dist/auth/bearer.js.map +0 -1
- package/dist/auth/clerk.d.ts.map +0 -1
- package/dist/auth/clerk.js.map +0 -1
- package/dist/auth/downstream-oauth.d.ts.map +0 -1
- package/dist/auth/downstream-oauth.js.map +0 -1
- package/dist/call-admission.d.ts.map +0 -1
- package/dist/call-admission.js.map +0 -1
- package/dist/catalog-fingerprint.d.ts.map +0 -1
- package/dist/catalog-fingerprint.js.map +0 -1
- package/dist/catalog-limits.d.ts.map +0 -1
- package/dist/catalog-limits.js.map +0 -1
- package/dist/catalog-service.d.ts.map +0 -1
- package/dist/catalog-service.js.map +0 -1
- package/dist/catalog.d.ts.map +0 -1
- package/dist/catalog.js.map +0 -1
- package/dist/concurrency.d.ts.map +0 -1
- package/dist/concurrency.js.map +0 -1
- package/dist/connector-scope.d.ts.map +0 -1
- package/dist/connector-scope.js.map +0 -1
- package/dist/connectors/api.d.ts.map +0 -1
- package/dist/connectors/api.js.map +0 -1
- package/dist/connectors/remote-mcp.d.ts.map +0 -1
- package/dist/connectors/remote-mcp.js.map +0 -1
- package/dist/credentials.d.ts.map +0 -1
- package/dist/credentials.js.map +0 -1
- package/dist/errors.d.ts.map +0 -1
- package/dist/errors.js.map +0 -1
- package/dist/execute.d.ts.map +0 -1
- package/dist/execute.js.map +0 -1
- package/dist/executor-admission.d.ts.map +0 -1
- package/dist/executor-admission.js.map +0 -1
- package/dist/executor-result.d.ts.map +0 -1
- package/dist/executor-result.js.map +0 -1
- package/dist/executors/quickjs-child.d.ts.map +0 -1
- package/dist/executors/quickjs-child.js.map +0 -1
- package/dist/executors/quickjs-protocol.d.ts.map +0 -1
- package/dist/executors/quickjs-protocol.js.map +0 -1
- package/dist/executors/quickjs-runtime.d.ts.map +0 -1
- package/dist/executors/quickjs-runtime.js.map +0 -1
- package/dist/executors/quickjs.d.ts.map +0 -1
- package/dist/executors/quickjs.js.map +0 -1
- package/dist/favicon.d.ts.map +0 -1
- package/dist/favicon.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/invocation.d.ts.map +0 -1
- package/dist/invocation.js.map +0 -1
- package/dist/json-schema.d.ts.map +0 -1
- package/dist/json-schema.js.map +0 -1
- package/dist/mcp-result.d.ts.map +0 -1
- package/dist/mcp-result.js.map +0 -1
- package/dist/meta-tools.d.ts.map +0 -1
- package/dist/meta-tools.js.map +0 -1
- package/dist/node.d.ts.map +0 -1
- package/dist/node.js.map +0 -1
- package/dist/operator-ui/generated.d.ts.map +0 -1
- package/dist/operator-ui/generated.js.map +0 -1
- package/dist/operator-ui/model.d.ts.map +0 -1
- package/dist/operator-ui/model.js.map +0 -1
- package/dist/providers/cloudflare.d.ts.map +0 -1
- package/dist/providers/cloudflare.js.map +0 -1
- package/dist/providers/linear.d.ts.map +0 -1
- package/dist/providers/linear.js.map +0 -1
- package/dist/providers/mixpanel.d.ts.map +0 -1
- package/dist/providers/mixpanel.js.map +0 -1
- package/dist/providers/notion.d.ts.map +0 -1
- package/dist/providers/notion.js.map +0 -1
- package/dist/providers/stripe.d.ts.map +0 -1
- package/dist/providers/stripe.js.map +0 -1
- package/dist/registry.d.ts.map +0 -1
- package/dist/registry.js.map +0 -1
- package/dist/retired-toolkits.d.ts.map +0 -1
- package/dist/retired-toolkits.js.map +0 -1
- package/dist/routes/access-tokens.d.ts.map +0 -1
- package/dist/routes/access-tokens.js.map +0 -1
- package/dist/routes/activity.d.ts.map +0 -1
- package/dist/routes/activity.js.map +0 -1
- package/dist/routes/credentials.d.ts.map +0 -1
- package/dist/routes/credentials.js.map +0 -1
- package/dist/routes/mcp.d.ts.map +0 -1
- package/dist/routes/mcp.js.map +0 -1
- package/dist/routes/oauth.d.ts.map +0 -1
- package/dist/routes/oauth.js.map +0 -1
- package/dist/routes/shared.d.ts.map +0 -1
- package/dist/routes/shared.js.map +0 -1
- package/dist/routes/ui.d.ts.map +0 -1
- package/dist/routes/ui.js.map +0 -1
- package/dist/server.d.ts.map +0 -1
- package/dist/server.js.map +0 -1
- package/dist/skills.d.ts.map +0 -1
- package/dist/skills.js.map +0 -1
- package/dist/storage/file.d.ts.map +0 -1
- package/dist/storage/file.js.map +0 -1
- package/dist/storage/memory.d.ts.map +0 -1
- package/dist/storage/memory.js.map +0 -1
- package/dist/timeout.d.ts.map +0 -1
- package/dist/timeout.js.map +0 -1
- package/dist/tool-safety.d.ts.map +0 -1
- package/dist/tool-safety.js.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js.map +0 -1
- package/dist/ui.d.ts.map +0 -1
- package/dist/ui.js.map +0 -1
- package/dist/validate.d.ts.map +0 -1
- package/dist/validate.js.map +0 -1
- package/dist/version.d.ts.map +0 -1
- package/dist/version.js.map +0 -1
- package/examples/node/README.md +0 -52
- package/examples/node/src/index.ts +0 -71
- package/src/access-tokens.ts +0 -289
- package/src/activity.ts +0 -234
- package/src/apps-shell.ts +0 -370
- package/src/auth/bearer.ts +0 -61
- package/src/auth/clerk.ts +0 -553
- package/src/auth/downstream-oauth.ts +0 -575
- package/src/call-admission.ts +0 -521
- package/src/catalog-fingerprint.ts +0 -52
- package/src/catalog-limits.ts +0 -11
- package/src/catalog-service.ts +0 -1153
- package/src/catalog.ts +0 -790
- package/src/concurrency.ts +0 -39
- package/src/connector-scope.ts +0 -66
- package/src/connectors/api.ts +0 -159
- package/src/connectors/remote-mcp.ts +0 -1090
- package/src/credentials.ts +0 -428
- package/src/errors.ts +0 -364
- package/src/execute.ts +0 -1406
- package/src/executor-admission.ts +0 -328
- package/src/executor-result.ts +0 -107
- package/src/executors/quickjs-child.ts +0 -172
- package/src/executors/quickjs-protocol.ts +0 -99
- package/src/executors/quickjs-runtime.ts +0 -470
- package/src/executors/quickjs.ts +0 -776
- package/src/favicon.ts +0 -53
- package/src/index.ts +0 -666
- package/src/invocation.ts +0 -655
- package/src/json-schema.ts +0 -11
- package/src/mcp-result.ts +0 -43
- package/src/meta-tools.ts +0 -1607
- package/src/node.ts +0 -206
- package/src/operator-ui/browser.css +0 -423
- package/src/operator-ui/browser.ts +0 -1281
- package/src/operator-ui/generated.ts +0 -4
- package/src/operator-ui/model.ts +0 -111
- package/src/providers/cloudflare.ts +0 -3999
- package/src/providers/linear.ts +0 -302
- package/src/providers/mixpanel.ts +0 -229
- package/src/providers/notion.ts +0 -1879
- package/src/providers/stripe.ts +0 -307
- package/src/registry.ts +0 -1085
- package/src/retired-toolkits.ts +0 -14
- package/src/routes/access-tokens.ts +0 -115
- package/src/routes/activity.ts +0 -215
- package/src/routes/credentials.ts +0 -254
- package/src/routes/mcp.ts +0 -429
- package/src/routes/oauth.ts +0 -322
- package/src/routes/shared.ts +0 -247
- package/src/routes/ui.ts +0 -152
- package/src/server.ts +0 -195
- package/src/skills.ts +0 -271
- package/src/storage/file.ts +0 -123
- package/src/storage/memory.ts +0 -44
- package/src/timeout.ts +0 -84
- package/src/tool-safety.ts +0 -15
- package/src/types.ts +0 -523
- package/src/ui.ts +0 -744
- package/src/validate.ts +0 -387
- package/src/version.ts +0 -7
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
* required-key list, and a declared output shape.
|
|
17
17
|
*/
|
|
18
18
|
import { api } from "../connectors/api.js";
|
|
19
|
+
import { guardedFetch, } from "../connectors/guarded-fetch.js";
|
|
19
20
|
import { ConnectorCallError } from "../errors.js";
|
|
20
21
|
/** Cloudflare's v4 REST base. Override only for a proxy or a test double. */
|
|
21
22
|
export const CLOUDFLARE_API_BASE = "https://api.cloudflare.com/client/v4";
|
|
@@ -242,6 +243,16 @@ function failureFor(status, headers, errors) {
|
|
|
242
243
|
}
|
|
243
244
|
return new ConnectorCallError("connector_call_failed", `Cloudflare request failed (HTTP ${status}). ${detail}`);
|
|
244
245
|
}
|
|
246
|
+
// --- The request path --------------------------------------------------------
|
|
247
|
+
/**
|
|
248
|
+
* The largest response this connection will read.
|
|
249
|
+
*
|
|
250
|
+
* Generous rather than tight, because `cloudflare_api_get` legitimately
|
|
251
|
+
* downloads Worker scripts and R2 objects. It is a ceiling on absurdity, not a
|
|
252
|
+
* quota: anything approaching it is already far past whatever `maxResultBytes`
|
|
253
|
+
* the deployment set, so the caller was never going to see it whole.
|
|
254
|
+
*/
|
|
255
|
+
const CLOUDFLARE_MAX_RESPONSE_BYTES = 8 * 1024 * 1024;
|
|
245
256
|
const AUTHENTICATION_CONTEXT = Symbol("cloudflareAuthentication");
|
|
246
257
|
function withAuthentication(ctx, authentication) {
|
|
247
258
|
return { ...ctx, [AUTHENTICATION_CONTEXT]: authentication };
|
|
@@ -262,72 +273,63 @@ async function readAuthenticationHeaders(ctx) {
|
|
|
262
273
|
}
|
|
263
274
|
return { Authorization: `Bearer ${token}` };
|
|
264
275
|
}
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
response = await fetch(buildUrl(base, spec), {
|
|
282
|
-
method: spec.method,
|
|
283
|
-
headers: {
|
|
284
|
-
...authenticationHeaders,
|
|
285
|
-
Accept: "application/json",
|
|
286
|
-
...(spec.body !== undefined
|
|
287
|
-
? { "Content-Type": "application/json" }
|
|
288
|
-
: {}),
|
|
289
|
-
...Object.fromEntries(Object.entries(spec.headers ?? {}).filter((entry) => entry[1] !== undefined)),
|
|
290
|
-
},
|
|
291
|
-
...(spec.body !== undefined
|
|
292
|
-
? { body: JSON.stringify(spec.body) }
|
|
293
|
-
: spec.rawBody !== undefined
|
|
294
|
-
? { body: spec.rawBody }
|
|
295
|
-
: {}),
|
|
296
|
-
...(ctx.signal ? { signal: ctx.signal } : {}),
|
|
297
|
-
});
|
|
298
|
-
}
|
|
299
|
-
catch (cause) {
|
|
300
|
-
throw new ConnectorCallError("unavailable", `Could not reach the Cloudflare API: ${cause instanceof Error ? cause.message : String(cause)}`, { cause });
|
|
301
|
-
}
|
|
302
|
-
return response;
|
|
276
|
+
/**
|
|
277
|
+
* The one transport every Cloudflare tool goes through.
|
|
278
|
+
*
|
|
279
|
+
* URL confinement, `ctx.signal`, redirect refusal, bounded reads, and the
|
|
280
|
+
* "could not reach the provider" normalization all live in the shared helper.
|
|
281
|
+
* What stays here is what only Cloudflare knows: which headers prove identity,
|
|
282
|
+
* and what a status code means once it arrives.
|
|
283
|
+
*/
|
|
284
|
+
function cloudflareTransport(baseUrl) {
|
|
285
|
+
return guardedFetch({
|
|
286
|
+
provider: "Cloudflare",
|
|
287
|
+
baseUrl,
|
|
288
|
+
headers: { Accept: "application/json" },
|
|
289
|
+
maxResponseBytes: CLOUDFLARE_MAX_RESPONSE_BYTES,
|
|
290
|
+
authenticate: (ctx) => readAuthenticationHeaders(ctx),
|
|
291
|
+
});
|
|
303
292
|
}
|
|
304
|
-
async function callCloudflare(
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
293
|
+
async function callCloudflare(send, spec, ctx) {
|
|
294
|
+
return await send(spec, ctx, async (response) => {
|
|
295
|
+
let envelope;
|
|
296
|
+
let parseFailure;
|
|
297
|
+
try {
|
|
298
|
+
envelope = (await response.json());
|
|
299
|
+
}
|
|
300
|
+
catch (cause) {
|
|
301
|
+
// A transport failure is not a parse failure. The connector's byte
|
|
302
|
+
// ceiling fires from inside this read and is deliberately non-retryable;
|
|
303
|
+
// routing it through the branch below would relabel it as a retryable
|
|
304
|
+
// `unavailable` and tell an agent to retry a response that will exceed
|
|
305
|
+
// the ceiling every time.
|
|
306
|
+
if (cause instanceof ConnectorCallError)
|
|
307
|
+
throw cause;
|
|
308
|
+
parseFailure = cause;
|
|
309
|
+
}
|
|
310
|
+
if (envelope === undefined) {
|
|
311
|
+
// A gateway error page or an empty body, not an envelope: the status is
|
|
312
|
+
// the only real signal left.
|
|
313
|
+
throw response.ok
|
|
314
|
+
? new ConnectorCallError("unavailable", "Cloudflare returned a non-JSON body for a successful status.", parseFailure !== undefined ? { cause: parseFailure } : {})
|
|
315
|
+
: failureFor(response.status, response.headers, []);
|
|
316
|
+
}
|
|
317
|
+
const errors = Array.isArray(envelope.errors) ? envelope.errors : [];
|
|
318
|
+
if (!response.ok || envelope.success === false) {
|
|
319
|
+
throw failureFor(response.status, response.headers, errors);
|
|
320
|
+
}
|
|
321
|
+
const isV4Envelope = "success" in envelope ||
|
|
322
|
+
"result" in envelope ||
|
|
323
|
+
"result_info" in envelope ||
|
|
324
|
+
"messages" in envelope;
|
|
325
|
+
return {
|
|
326
|
+
// `/graphql` and a small number of product APIs return ordinary JSON
|
|
327
|
+
// instead of the standard v4 envelope. Preserve that document whole so
|
|
328
|
+
// the raw tools cover them too.
|
|
329
|
+
result: isV4Envelope ? envelope.result : envelope,
|
|
330
|
+
resultInfo: isV4Envelope ? envelope.result_info : undefined,
|
|
331
|
+
};
|
|
332
|
+
});
|
|
331
333
|
}
|
|
332
334
|
function base64FromBytes(bytes) {
|
|
333
335
|
let binary = "";
|
|
@@ -336,33 +338,34 @@ function base64FromBytes(bytes) {
|
|
|
336
338
|
}
|
|
337
339
|
return btoa(binary);
|
|
338
340
|
}
|
|
339
|
-
async function callCloudflareContent(
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
341
|
+
async function callCloudflareContent(send, spec, ctx, responseType) {
|
|
342
|
+
return await send(spec, ctx, async (response) => {
|
|
343
|
+
if (!response.ok) {
|
|
344
|
+
let errors = [];
|
|
345
|
+
try {
|
|
346
|
+
const envelope = (await response.json());
|
|
347
|
+
if (envelope && Array.isArray(envelope.errors))
|
|
348
|
+
errors = envelope.errors;
|
|
349
|
+
}
|
|
350
|
+
catch {
|
|
351
|
+
// A raw or gateway error body has no structured detail to preserve,
|
|
352
|
+
// and one past the byte ceiling has none worth reporting over the
|
|
353
|
+
// status that already failed this call. Either way the throw below
|
|
354
|
+
// classifies the status, so nothing is swallowed into a success.
|
|
355
|
+
}
|
|
356
|
+
throw failureFor(response.status, response.headers, errors);
|
|
347
357
|
}
|
|
348
|
-
|
|
349
|
-
|
|
358
|
+
const common = {
|
|
359
|
+
contentType: response.headers.get("content-type") ?? "application/octet-stream",
|
|
360
|
+
...(response.headers.get("etag")
|
|
361
|
+
? { etag: response.headers.get("etag") }
|
|
362
|
+
: {}),
|
|
363
|
+
};
|
|
364
|
+
if (responseType === "text") {
|
|
365
|
+
return { ...common, text: await response.text() };
|
|
350
366
|
}
|
|
351
|
-
|
|
352
|
-
}
|
|
353
|
-
const common = {
|
|
354
|
-
contentType: response.headers.get("content-type") ?? "application/octet-stream",
|
|
355
|
-
...(response.headers.get("etag")
|
|
356
|
-
? { etag: response.headers.get("etag") }
|
|
357
|
-
: {}),
|
|
358
|
-
};
|
|
359
|
-
if (responseType === "text") {
|
|
360
|
-
return { ...common, text: await response.text() };
|
|
361
|
-
}
|
|
362
|
-
return {
|
|
363
|
-
...common,
|
|
364
|
-
base64: base64FromBytes(new Uint8Array(await response.arrayBuffer())),
|
|
365
|
-
};
|
|
367
|
+
return { ...common, base64: base64FromBytes(await response.bytes()) };
|
|
368
|
+
});
|
|
366
369
|
}
|
|
367
370
|
/**
|
|
368
371
|
* Cloudflare's `result_info` reshaped into the one question an agent actually
|
|
@@ -631,8 +634,8 @@ const RAW_INPUT_PROPERTY = {
|
|
|
631
634
|
* an out-of-range value with a 400, so each caller passes its own. Encoding
|
|
632
635
|
* them in the schema turns a wasted round trip into a local repair — but only
|
|
633
636
|
* where the bound is really Cloudflare's. `bounds` records who chose the
|
|
634
|
-
* range, because `
|
|
635
|
-
*
|
|
637
|
+
* range, because `api()` refuses an out-of-range `perPage` locally and an
|
|
638
|
+
* agent deserves to know whether the wall it hit is the API's or ours:
|
|
636
639
|
*
|
|
637
640
|
* - `"cloudflare"` — the schema's own documented minimum and maximum.
|
|
638
641
|
* - `"clamped"` — Cloudflare accepts more; this connection caps it lower.
|
|
@@ -663,6 +666,24 @@ function pagingInputProperties(minPerPage, maxPerPage, options = {}) {
|
|
|
663
666
|
},
|
|
664
667
|
};
|
|
665
668
|
}
|
|
669
|
+
/**
|
|
670
|
+
* The second pagination convention, and the schemas say so.
|
|
671
|
+
*
|
|
672
|
+
* Rulesets, KV keys, and both R2 listings page by cursor rather than by page
|
|
673
|
+
* number, because that is how Cloudflare built them. The guide names the four,
|
|
674
|
+
* but an agent reading one tool's schema should not have to fetch the guide to
|
|
675
|
+
* learn that the `page` object it expected is not coming: absence of
|
|
676
|
+
* `nextCursor` is the loop condition here, and it is stated on both ends
|
|
677
|
+
* ([#342](https://github.com/zackbart/connecta/issues/342)).
|
|
678
|
+
*/
|
|
679
|
+
const CURSOR_INPUT_PROPERTY = {
|
|
680
|
+
type: "string",
|
|
681
|
+
description: "Opaque cursor from a previous call's nextCursor. This endpoint pages by cursor, not page number.",
|
|
682
|
+
};
|
|
683
|
+
const NEXT_CURSOR_OUTPUT_PROPERTY = {
|
|
684
|
+
type: "string",
|
|
685
|
+
description: "Pass back as `cursor` to continue. Absent when the listing is complete — this is the only signal; there is no page object.",
|
|
686
|
+
};
|
|
666
687
|
function listOutputSchema(key, item) {
|
|
667
688
|
return {
|
|
668
689
|
type: "object",
|
|
@@ -928,7 +949,7 @@ const OPEN_OBJECT_OUTPUT_SCHEMA = {
|
|
|
928
949
|
};
|
|
929
950
|
const QUERY_INPUT_PROPERTY = {
|
|
930
951
|
type: "array",
|
|
931
|
-
description: "
|
|
952
|
+
description: "Query parameters as name/value pairs; each name may appear once.",
|
|
932
953
|
items: {
|
|
933
954
|
type: "object",
|
|
934
955
|
properties: {
|
|
@@ -939,9 +960,14 @@ const QUERY_INPUT_PROPERTY = {
|
|
|
939
960
|
additionalProperties: false,
|
|
940
961
|
},
|
|
941
962
|
};
|
|
963
|
+
// Shared by all three escape hatches, and the compact renderer inlines it
|
|
964
|
+
// three times over. The refused-header list is the connector's boundary rather
|
|
965
|
+
// than a fact the caller composes with, so it lives in the usage guide; keeping
|
|
966
|
+
// it here pushed cloudflare_api_upload's compact input past the 1,024-byte
|
|
967
|
+
// budget ([#342](https://github.com/zackbart/connecta/issues/342)).
|
|
942
968
|
const HEADERS_INPUT_PROPERTY = {
|
|
943
969
|
type: "array",
|
|
944
|
-
description: "
|
|
970
|
+
description: "Endpoint headers as name/value pairs, e.g. cf-r2-jurisdiction or Range. Connector-owned headers are refused.",
|
|
945
971
|
items: {
|
|
946
972
|
type: "object",
|
|
947
973
|
properties: {
|
|
@@ -988,7 +1014,7 @@ const R2_OBJECT_SCHEMA = {
|
|
|
988
1014
|
required: ["key"],
|
|
989
1015
|
};
|
|
990
1016
|
function buildTools(scope, authentication) {
|
|
991
|
-
const {
|
|
1017
|
+
const { send } = scope;
|
|
992
1018
|
const zoneArg = (args) => requireScope(args["zoneId"], scope.zoneId, "zoneId");
|
|
993
1019
|
const accountArg = (args) => requireScope(args["accountId"], scope.accountId, "accountId");
|
|
994
1020
|
const readOnly = { readOnlyHint: true, destructiveHint: false };
|
|
@@ -1018,7 +1044,7 @@ function buildTools(scope, authentication) {
|
|
|
1018
1044
|
required: ["status"],
|
|
1019
1045
|
},
|
|
1020
1046
|
handler: async (_args, ctx) => {
|
|
1021
|
-
const { result } = await callCloudflare(
|
|
1047
|
+
const { result } = await callCloudflare(send, { method: "GET", path: "/user/tokens/verify" }, ctx);
|
|
1022
1048
|
const token = asRecord(result);
|
|
1023
1049
|
return {
|
|
1024
1050
|
id: token["id"],
|
|
@@ -1055,14 +1081,14 @@ function buildTools(scope, authentication) {
|
|
|
1055
1081
|
required: ["email", "status"],
|
|
1056
1082
|
},
|
|
1057
1083
|
handler: async (_args, ctx) => {
|
|
1058
|
-
const { result } = await callCloudflare(
|
|
1084
|
+
const { result } = await callCloudflare(send, { method: "GET", path: "/user" }, ctx);
|
|
1059
1085
|
const user = asRecord(result);
|
|
1060
1086
|
return { id: user["id"], email: user["email"], status: "active" };
|
|
1061
1087
|
},
|
|
1062
1088
|
},
|
|
1063
1089
|
{
|
|
1064
1090
|
name: "cloudflare_api_get",
|
|
1065
|
-
description: "Call any GET endpoint under Cloudflare's v4 API with this connector's credential.
|
|
1091
|
+
description: "Call any GET endpoint under Cloudflare's v4 API with this connector's credential. Prefer a named tool when one exists; this read-only hatch covers the products the named surface does not reach, such as Images, Stream, D1, and Queues.",
|
|
1066
1092
|
annotations: readOnly,
|
|
1067
1093
|
inputSchema: {
|
|
1068
1094
|
type: "object",
|
|
@@ -1111,9 +1137,9 @@ function buildTools(scope, authentication) {
|
|
|
1111
1137
|
...(headers !== undefined ? { headers } : {}),
|
|
1112
1138
|
};
|
|
1113
1139
|
if (responseType === "text" || responseType === "base64") {
|
|
1114
|
-
return await callCloudflareContent(
|
|
1140
|
+
return await callCloudflareContent(send, spec, ctx, responseType);
|
|
1115
1141
|
}
|
|
1116
|
-
const { result, resultInfo } = await callCloudflare(
|
|
1142
|
+
const { result, resultInfo } = await callCloudflare(send, spec, ctx);
|
|
1117
1143
|
return {
|
|
1118
1144
|
result,
|
|
1119
1145
|
...(resultInfo !== undefined ? { resultInfo } : {}),
|
|
@@ -1122,7 +1148,7 @@ function buildTools(scope, authentication) {
|
|
|
1122
1148
|
},
|
|
1123
1149
|
{
|
|
1124
1150
|
name: "cloudflare_api_mutate",
|
|
1125
|
-
description: "Call any JSON POST, PUT, PATCH, or DELETE endpoint under Cloudflare's v4 API with this connector's credential.
|
|
1151
|
+
description: "Call any JSON POST, PUT, PATCH, or DELETE endpoint under Cloudflare's v4 API with this connector's credential. The approval-gated write hatch for products the named surface does not reach. No multipart or binary uploads.",
|
|
1126
1152
|
annotations: { readOnlyHint: false, destructiveHint: true },
|
|
1127
1153
|
inputSchema: {
|
|
1128
1154
|
type: "object",
|
|
@@ -1164,7 +1190,7 @@ function buildTools(scope, authentication) {
|
|
|
1164
1190
|
const method = String(args["method"]);
|
|
1165
1191
|
const query = queryFromArgs(args["query"]);
|
|
1166
1192
|
const headers = headersFromArgs(args["headers"]);
|
|
1167
|
-
const { result, resultInfo } = await callCloudflare(
|
|
1193
|
+
const { result, resultInfo } = await callCloudflare(send, {
|
|
1168
1194
|
method,
|
|
1169
1195
|
path: cloudflareApiPath(args["path"]),
|
|
1170
1196
|
...(query !== undefined ? { query } : {}),
|
|
@@ -1187,31 +1213,31 @@ function buildTools(scope, authentication) {
|
|
|
1187
1213
|
method: {
|
|
1188
1214
|
type: "string",
|
|
1189
1215
|
enum: ["POST", "PUT"],
|
|
1190
|
-
description: "
|
|
1216
|
+
description: "Upload method the Cloudflare endpoint requires.",
|
|
1191
1217
|
},
|
|
1192
1218
|
path: {
|
|
1193
1219
|
type: "string",
|
|
1194
1220
|
minLength: 1,
|
|
1195
|
-
description: "
|
|
1221
|
+
description: "Path below /client/v4, beginning with '/'. No query string.",
|
|
1196
1222
|
},
|
|
1197
1223
|
query: QUERY_INPUT_PROPERTY,
|
|
1198
1224
|
headers: HEADERS_INPUT_PROPERTY,
|
|
1199
1225
|
contentType: {
|
|
1200
1226
|
type: "string",
|
|
1201
1227
|
minLength: 1,
|
|
1202
|
-
description: "Content-Type for a raw text
|
|
1228
|
+
description: "Content-Type for a raw text or base64 body. Omit for multipart.",
|
|
1203
1229
|
},
|
|
1204
1230
|
textBody: {
|
|
1205
1231
|
type: "string",
|
|
1206
|
-
description: "Raw UTF-8
|
|
1232
|
+
description: "Raw UTF-8 body. Exclusive with base64Body and fields/files.",
|
|
1207
1233
|
},
|
|
1208
1234
|
base64Body: {
|
|
1209
1235
|
type: "string",
|
|
1210
|
-
description: "Base64-encoded
|
|
1236
|
+
description: "Base64-encoded body bytes. Exclusive with textBody and fields/files.",
|
|
1211
1237
|
},
|
|
1212
1238
|
fields: {
|
|
1213
1239
|
type: "array",
|
|
1214
|
-
description: "String fields
|
|
1240
|
+
description: "String fields of a multipart/form-data request.",
|
|
1215
1241
|
items: {
|
|
1216
1242
|
type: "object",
|
|
1217
1243
|
properties: {
|
|
@@ -1226,7 +1252,7 @@ function buildTools(scope, authentication) {
|
|
|
1226
1252
|
},
|
|
1227
1253
|
files: {
|
|
1228
1254
|
type: "array",
|
|
1229
|
-
description: "
|
|
1255
|
+
description: "Multipart file parts. Each needs exactly one of text or base64.",
|
|
1230
1256
|
items: {
|
|
1231
1257
|
type: "object",
|
|
1232
1258
|
properties: {
|
|
@@ -1257,7 +1283,7 @@ function buildTools(scope, authentication) {
|
|
|
1257
1283
|
const query = queryFromArgs(args["query"]);
|
|
1258
1284
|
const headers = headersFromArgs(args["headers"]);
|
|
1259
1285
|
const upload = uploadBody(args);
|
|
1260
|
-
const { result } = await callCloudflare(
|
|
1286
|
+
const { result } = await callCloudflare(send, {
|
|
1261
1287
|
method: String(args["method"]),
|
|
1262
1288
|
path: cloudflareApiPath(args["path"]),
|
|
1263
1289
|
...(query !== undefined ? { query } : {}),
|
|
@@ -1288,7 +1314,7 @@ function buildTools(scope, authentication) {
|
|
|
1288
1314
|
},
|
|
1289
1315
|
outputSchema: listOutputSchema("accounts", ACCOUNT_SCHEMA),
|
|
1290
1316
|
handler: async (args, ctx) => {
|
|
1291
|
-
const { result, resultInfo } = await callCloudflare(
|
|
1317
|
+
const { result, resultInfo } = await callCloudflare(send, {
|
|
1292
1318
|
method: "GET",
|
|
1293
1319
|
path: "/accounts",
|
|
1294
1320
|
query: {
|
|
@@ -1333,7 +1359,7 @@ function buildTools(scope, authentication) {
|
|
|
1333
1359
|
},
|
|
1334
1360
|
outputSchema: listOutputSchema("zones", ZONE_SCHEMA),
|
|
1335
1361
|
handler: async (args, ctx) => {
|
|
1336
|
-
const { result, resultInfo } = await callCloudflare(
|
|
1362
|
+
const { result, resultInfo } = await callCloudflare(send, {
|
|
1337
1363
|
method: "GET",
|
|
1338
1364
|
path: "/zones",
|
|
1339
1365
|
query: {
|
|
@@ -1371,7 +1397,7 @@ function buildTools(scope, authentication) {
|
|
|
1371
1397
|
},
|
|
1372
1398
|
outputSchema: ZONE_SCHEMA,
|
|
1373
1399
|
handler: async (args, ctx) => {
|
|
1374
|
-
const { result } = await callCloudflare(
|
|
1400
|
+
const { result } = await callCloudflare(send, { method: "GET", path: `/zones/${encodeURIComponent(zoneArg(args))}` }, ctx);
|
|
1375
1401
|
return args["raw"] === true ? result : projectZone(result);
|
|
1376
1402
|
},
|
|
1377
1403
|
},
|
|
@@ -1389,7 +1415,7 @@ function buildTools(scope, authentication) {
|
|
|
1389
1415
|
},
|
|
1390
1416
|
outputSchema: listOutputSchema("settings", OPEN_OBJECT_OUTPUT_SCHEMA),
|
|
1391
1417
|
handler: async (args, ctx) => {
|
|
1392
|
-
const { result, resultInfo } = await callCloudflare(
|
|
1418
|
+
const { result, resultInfo } = await callCloudflare(send, {
|
|
1393
1419
|
method: "GET",
|
|
1394
1420
|
path: `/zones/${encodePathSegment(zoneArg(args))}/settings`,
|
|
1395
1421
|
}, ctx);
|
|
@@ -1415,7 +1441,7 @@ function buildTools(scope, authentication) {
|
|
|
1415
1441
|
},
|
|
1416
1442
|
outputSchema: OPEN_OBJECT_OUTPUT_SCHEMA,
|
|
1417
1443
|
handler: async (args, ctx) => {
|
|
1418
|
-
const { result } = await callCloudflare(
|
|
1444
|
+
const { result } = await callCloudflare(send, {
|
|
1419
1445
|
method: "GET",
|
|
1420
1446
|
path: `/zones/${encodePathSegment(zoneArg(args))}/settings/${encodePathSegment(requireString(args, "settingId"))}`,
|
|
1421
1447
|
}, ctx);
|
|
@@ -1446,7 +1472,7 @@ function buildTools(scope, authentication) {
|
|
|
1446
1472
|
},
|
|
1447
1473
|
outputSchema: OPEN_OBJECT_OUTPUT_SCHEMA,
|
|
1448
1474
|
handler: async (args, ctx) => {
|
|
1449
|
-
const { result } = await callCloudflare(
|
|
1475
|
+
const { result } = await callCloudflare(send, {
|
|
1450
1476
|
method: "PATCH",
|
|
1451
1477
|
path: `/zones/${encodePathSegment(zoneArg(args))}/settings/${encodePathSegment(requireString(args, "settingId"))}`,
|
|
1452
1478
|
body: { value: args["value"] },
|
|
@@ -1468,10 +1494,7 @@ function buildTools(scope, authentication) {
|
|
|
1468
1494
|
maximum: 50,
|
|
1469
1495
|
description: "Rulesets per request, 1 to 50.",
|
|
1470
1496
|
},
|
|
1471
|
-
cursor:
|
|
1472
|
-
type: "string",
|
|
1473
|
-
description: "Opaque cursor returned as nextCursor by the previous call.",
|
|
1474
|
-
},
|
|
1497
|
+
cursor: CURSOR_INPUT_PROPERTY,
|
|
1475
1498
|
},
|
|
1476
1499
|
required: scopeRequired("zoneId", scope.zoneId),
|
|
1477
1500
|
additionalProperties: false,
|
|
@@ -1480,12 +1503,12 @@ function buildTools(scope, authentication) {
|
|
|
1480
1503
|
type: "object",
|
|
1481
1504
|
properties: {
|
|
1482
1505
|
rulesets: { type: "array", items: OPEN_OBJECT_OUTPUT_SCHEMA },
|
|
1483
|
-
nextCursor:
|
|
1506
|
+
nextCursor: NEXT_CURSOR_OUTPUT_PROPERTY,
|
|
1484
1507
|
},
|
|
1485
1508
|
required: ["rulesets"],
|
|
1486
1509
|
},
|
|
1487
1510
|
handler: async (args, ctx) => {
|
|
1488
|
-
const { result, resultInfo } = await callCloudflare(
|
|
1511
|
+
const { result, resultInfo } = await callCloudflare(send, {
|
|
1489
1512
|
method: "GET",
|
|
1490
1513
|
path: `/zones/${encodePathSegment(zoneArg(args))}/rulesets`,
|
|
1491
1514
|
query: {
|
|
@@ -1521,7 +1544,7 @@ function buildTools(scope, authentication) {
|
|
|
1521
1544
|
},
|
|
1522
1545
|
outputSchema: OPEN_OBJECT_OUTPUT_SCHEMA,
|
|
1523
1546
|
handler: async (args, ctx) => {
|
|
1524
|
-
const { result } = await callCloudflare(
|
|
1547
|
+
const { result } = await callCloudflare(send, {
|
|
1525
1548
|
method: "GET",
|
|
1526
1549
|
path: `/zones/${encodePathSegment(zoneArg(args))}/rulesets/${encodePathSegment(requireString(args, "rulesetId"))}`,
|
|
1527
1550
|
}, ctx);
|
|
@@ -1573,7 +1596,7 @@ function buildTools(scope, authentication) {
|
|
|
1573
1596
|
},
|
|
1574
1597
|
outputSchema: listOutputSchema("records", DNS_RECORD_SCHEMA),
|
|
1575
1598
|
handler: async (args, ctx) => {
|
|
1576
|
-
const { result, resultInfo } = await callCloudflare(
|
|
1599
|
+
const { result, resultInfo } = await callCloudflare(send, {
|
|
1577
1600
|
method: "GET",
|
|
1578
1601
|
path: `/zones/${encodeURIComponent(zoneArg(args))}/dns_records`,
|
|
1579
1602
|
query: {
|
|
@@ -1613,7 +1636,7 @@ function buildTools(scope, authentication) {
|
|
|
1613
1636
|
},
|
|
1614
1637
|
outputSchema: DNS_RECORD_SCHEMA,
|
|
1615
1638
|
handler: async (args, ctx) => {
|
|
1616
|
-
const { result } = await callCloudflare(
|
|
1639
|
+
const { result } = await callCloudflare(send, {
|
|
1617
1640
|
method: "GET",
|
|
1618
1641
|
path: `/zones/${encodeURIComponent(zoneArg(args))}/dns_records/${encodeURIComponent(String(args["recordId"]))}`,
|
|
1619
1642
|
}, ctx);
|
|
@@ -1644,7 +1667,7 @@ function buildTools(scope, authentication) {
|
|
|
1644
1667
|
required: ["id"],
|
|
1645
1668
|
}),
|
|
1646
1669
|
handler: async (args, ctx) => {
|
|
1647
|
-
const { result, resultInfo } = await callCloudflare(
|
|
1670
|
+
const { result, resultInfo } = await callCloudflare(send, {
|
|
1648
1671
|
method: "GET",
|
|
1649
1672
|
path: `/accounts/${encodeURIComponent(accountArg(args))}/workers/scripts`,
|
|
1650
1673
|
}, ctx);
|
|
@@ -1675,7 +1698,7 @@ function buildTools(scope, authentication) {
|
|
|
1675
1698
|
},
|
|
1676
1699
|
outputSchema: OPEN_OBJECT_OUTPUT_SCHEMA,
|
|
1677
1700
|
handler: async (args, ctx) => {
|
|
1678
|
-
const { result } = await callCloudflare(
|
|
1701
|
+
const { result } = await callCloudflare(send, {
|
|
1679
1702
|
method: "GET",
|
|
1680
1703
|
path: `/accounts/${encodePathSegment(accountArg(args))}/workers/scripts/${encodePathSegment(requireString(args, "scriptName"))}/settings`,
|
|
1681
1704
|
}, ctx);
|
|
@@ -1701,7 +1724,7 @@ function buildTools(scope, authentication) {
|
|
|
1701
1724
|
},
|
|
1702
1725
|
outputSchema: listOutputSchema("deployments", OPEN_OBJECT_OUTPUT_SCHEMA),
|
|
1703
1726
|
handler: async (args, ctx) => {
|
|
1704
|
-
const { result } = await callCloudflare(
|
|
1727
|
+
const { result } = await callCloudflare(send, {
|
|
1705
1728
|
method: "GET",
|
|
1706
1729
|
path: `/accounts/${encodePathSegment(accountArg(args))}/workers/scripts/${encodePathSegment(requireString(args, "scriptName"))}/deployments`,
|
|
1707
1730
|
}, ctx);
|
|
@@ -1740,7 +1763,7 @@ function buildTools(scope, authentication) {
|
|
|
1740
1763
|
},
|
|
1741
1764
|
outputSchema: OPEN_OBJECT_OUTPUT_SCHEMA,
|
|
1742
1765
|
handler: async (args, ctx) => {
|
|
1743
|
-
const { result } = await callCloudflare(
|
|
1766
|
+
const { result } = await callCloudflare(send, {
|
|
1744
1767
|
method: "GET",
|
|
1745
1768
|
path: `/accounts/${encodePathSegment(accountArg(args))}/workers/scripts/${encodePathSegment(requireString(args, "scriptName"))}/deployments/${encodePathSegment(requireString(args, "deploymentId"))}`,
|
|
1746
1769
|
}, ctx);
|
|
@@ -1778,7 +1801,7 @@ function buildTools(scope, authentication) {
|
|
|
1778
1801
|
},
|
|
1779
1802
|
handler: async (args, ctx) => {
|
|
1780
1803
|
const scriptName = requireString(args, "scriptName");
|
|
1781
|
-
await callCloudflare(
|
|
1804
|
+
await callCloudflare(send, {
|
|
1782
1805
|
method: "DELETE",
|
|
1783
1806
|
path: `/accounts/${encodePathSegment(accountArg(args))}/workers/scripts/${encodePathSegment(scriptName)}`,
|
|
1784
1807
|
query: { force: optionalBoolean(args, "force") },
|
|
@@ -1810,7 +1833,7 @@ function buildTools(scope, authentication) {
|
|
|
1810
1833
|
required: ["id", "title"],
|
|
1811
1834
|
}),
|
|
1812
1835
|
handler: async (args, ctx) => {
|
|
1813
|
-
const { result, resultInfo } = await callCloudflare(
|
|
1836
|
+
const { result, resultInfo } = await callCloudflare(send, {
|
|
1814
1837
|
method: "GET",
|
|
1815
1838
|
path: `/accounts/${encodeURIComponent(accountArg(args))}/storage/kv/namespaces`,
|
|
1816
1839
|
query: {
|
|
@@ -1845,7 +1868,7 @@ function buildTools(scope, authentication) {
|
|
|
1845
1868
|
},
|
|
1846
1869
|
outputSchema: OPEN_OBJECT_OUTPUT_SCHEMA,
|
|
1847
1870
|
handler: async (args, ctx) => {
|
|
1848
|
-
const { result } = await callCloudflare(
|
|
1871
|
+
const { result } = await callCloudflare(send, {
|
|
1849
1872
|
method: "GET",
|
|
1850
1873
|
path: `/accounts/${encodePathSegment(accountArg(args))}/storage/kv/namespaces/${encodePathSegment(requireString(args, "namespaceId"))}`,
|
|
1851
1874
|
}, ctx);
|
|
@@ -1872,7 +1895,7 @@ function buildTools(scope, authentication) {
|
|
|
1872
1895
|
},
|
|
1873
1896
|
outputSchema: OPEN_OBJECT_OUTPUT_SCHEMA,
|
|
1874
1897
|
handler: async (args, ctx) => {
|
|
1875
|
-
const { result } = await callCloudflare(
|
|
1898
|
+
const { result } = await callCloudflare(send, {
|
|
1876
1899
|
method: "POST",
|
|
1877
1900
|
path: `/accounts/${encodePathSegment(accountArg(args))}/storage/kv/namespaces`,
|
|
1878
1901
|
body: { title: requireString(args, "title") },
|
|
@@ -1909,7 +1932,7 @@ function buildTools(scope, authentication) {
|
|
|
1909
1932
|
},
|
|
1910
1933
|
outputSchema: OPEN_OBJECT_OUTPUT_SCHEMA,
|
|
1911
1934
|
handler: async (args, ctx) => {
|
|
1912
|
-
const { result } = await callCloudflare(
|
|
1935
|
+
const { result } = await callCloudflare(send, {
|
|
1913
1936
|
method: "PUT",
|
|
1914
1937
|
path: `/accounts/${encodePathSegment(accountArg(args))}/storage/kv/namespaces/${encodePathSegment(requireString(args, "namespaceId"))}`,
|
|
1915
1938
|
body: { title: requireString(args, "title") },
|
|
@@ -1944,7 +1967,7 @@ function buildTools(scope, authentication) {
|
|
|
1944
1967
|
},
|
|
1945
1968
|
handler: async (args, ctx) => {
|
|
1946
1969
|
const namespaceId = requireString(args, "namespaceId");
|
|
1947
|
-
await callCloudflare(
|
|
1970
|
+
await callCloudflare(send, {
|
|
1948
1971
|
method: "DELETE",
|
|
1949
1972
|
path: `/accounts/${encodePathSegment(accountArg(args))}/storage/kv/namespaces/${encodePathSegment(namespaceId)}`,
|
|
1950
1973
|
}, ctx);
|
|
@@ -1974,10 +1997,7 @@ function buildTools(scope, authentication) {
|
|
|
1974
1997
|
maximum: 1000,
|
|
1975
1998
|
description: "Keys per request, 10 to 1000. Defaults to 1000.",
|
|
1976
1999
|
},
|
|
1977
|
-
cursor:
|
|
1978
|
-
type: "string",
|
|
1979
|
-
description: "Opaque cursor returned as nextCursor by the previous call.",
|
|
1980
|
-
},
|
|
2000
|
+
cursor: CURSOR_INPUT_PROPERTY,
|
|
1981
2001
|
},
|
|
1982
2002
|
required: [...scopeRequired("accountId", scope.accountId), "namespaceId"],
|
|
1983
2003
|
additionalProperties: false,
|
|
@@ -1986,12 +2006,12 @@ function buildTools(scope, authentication) {
|
|
|
1986
2006
|
type: "object",
|
|
1987
2007
|
properties: {
|
|
1988
2008
|
keys: { type: "array", items: OPEN_OBJECT_OUTPUT_SCHEMA },
|
|
1989
|
-
nextCursor:
|
|
2009
|
+
nextCursor: NEXT_CURSOR_OUTPUT_PROPERTY,
|
|
1990
2010
|
},
|
|
1991
2011
|
required: ["keys"],
|
|
1992
2012
|
},
|
|
1993
2013
|
handler: async (args, ctx) => {
|
|
1994
|
-
const { result, resultInfo } = await callCloudflare(
|
|
2014
|
+
const { result, resultInfo } = await callCloudflare(send, {
|
|
1995
2015
|
method: "GET",
|
|
1996
2016
|
path: `/accounts/${encodePathSegment(accountArg(args))}/storage/kv/namespaces/${encodePathSegment(requireString(args, "namespaceId"))}/keys`,
|
|
1997
2017
|
query: {
|
|
@@ -2048,7 +2068,7 @@ function buildTools(scope, authentication) {
|
|
|
2048
2068
|
},
|
|
2049
2069
|
outputSchema: OPEN_OBJECT_OUTPUT_SCHEMA,
|
|
2050
2070
|
handler: async (args, ctx) => {
|
|
2051
|
-
const { result } = await callCloudflare(
|
|
2071
|
+
const { result } = await callCloudflare(send, {
|
|
2052
2072
|
method: "POST",
|
|
2053
2073
|
path: `/accounts/${encodePathSegment(accountArg(args))}/storage/kv/namespaces/${encodePathSegment(requireString(args, "namespaceId"))}/bulk/get`,
|
|
2054
2074
|
body: {
|
|
@@ -2083,12 +2103,34 @@ function buildTools(scope, authentication) {
|
|
|
2083
2103
|
items: {
|
|
2084
2104
|
type: "object",
|
|
2085
2105
|
properties: {
|
|
2086
|
-
key: {
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2106
|
+
key: {
|
|
2107
|
+
type: "string",
|
|
2108
|
+
minLength: 1,
|
|
2109
|
+
maxLength: 512,
|
|
2110
|
+
description: "Key name, up to Cloudflare's 512 bytes.",
|
|
2111
|
+
},
|
|
2112
|
+
value: {
|
|
2113
|
+
type: "string",
|
|
2114
|
+
maxLength: 26_214_400,
|
|
2115
|
+
description: "Value, up to Cloudflare's 25 MiB.",
|
|
2116
|
+
},
|
|
2117
|
+
expiration: {
|
|
2118
|
+
type: "number",
|
|
2119
|
+
description: "Absolute expiry as a Unix timestamp in seconds.",
|
|
2120
|
+
},
|
|
2121
|
+
expiration_ttl: {
|
|
2122
|
+
type: "number",
|
|
2123
|
+
minimum: 60,
|
|
2124
|
+
description: "Relative expiry in seconds; Cloudflare's floor is 60.",
|
|
2125
|
+
},
|
|
2126
|
+
metadata: {
|
|
2127
|
+
type: ["object", "array", "string", "number", "boolean", "null"],
|
|
2128
|
+
description: "JSON metadata returned beside the key by list_kv_keys.",
|
|
2129
|
+
},
|
|
2130
|
+
base64: {
|
|
2131
|
+
type: "boolean",
|
|
2132
|
+
description: "Treat value as base64 and store the decoded bytes.",
|
|
2133
|
+
},
|
|
2092
2134
|
},
|
|
2093
2135
|
required: ["key", "value"],
|
|
2094
2136
|
additionalProperties: false,
|
|
@@ -2104,7 +2146,7 @@ function buildTools(scope, authentication) {
|
|
|
2104
2146
|
},
|
|
2105
2147
|
outputSchema: OPEN_OBJECT_OUTPUT_SCHEMA,
|
|
2106
2148
|
handler: async (args, ctx) => {
|
|
2107
|
-
const { result } = await callCloudflare(
|
|
2149
|
+
const { result } = await callCloudflare(send, {
|
|
2108
2150
|
method: "PUT",
|
|
2109
2151
|
path: `/accounts/${encodePathSegment(accountArg(args))}/storage/kv/namespaces/${encodePathSegment(requireString(args, "namespaceId"))}/bulk`,
|
|
2110
2152
|
body: args["entries"],
|
|
@@ -2142,7 +2184,7 @@ function buildTools(scope, authentication) {
|
|
|
2142
2184
|
},
|
|
2143
2185
|
outputSchema: OPEN_OBJECT_OUTPUT_SCHEMA,
|
|
2144
2186
|
handler: async (args, ctx) => {
|
|
2145
|
-
const { result } = await callCloudflare(
|
|
2187
|
+
const { result } = await callCloudflare(send, {
|
|
2146
2188
|
method: "POST",
|
|
2147
2189
|
path: `/accounts/${encodePathSegment(accountArg(args))}/storage/kv/namespaces/${encodePathSegment(requireString(args, "namespaceId"))}/bulk/delete`,
|
|
2148
2190
|
body: args["keys"],
|
|
@@ -2168,10 +2210,7 @@ function buildTools(scope, authentication) {
|
|
|
2168
2210
|
maximum: 1000,
|
|
2169
2211
|
description: "Buckets per request, 1 to 1000. Defaults to 20.",
|
|
2170
2212
|
},
|
|
2171
|
-
cursor:
|
|
2172
|
-
type: "string",
|
|
2173
|
-
description: "Opaque cursor from a previous call's nextCursor. R2 paginates by cursor, not page number.",
|
|
2174
|
-
},
|
|
2213
|
+
cursor: CURSOR_INPUT_PROPERTY,
|
|
2175
2214
|
jurisdiction: R2_JURISDICTION_PROPERTY,
|
|
2176
2215
|
raw: RAW_INPUT_PROPERTY,
|
|
2177
2216
|
},
|
|
@@ -2195,15 +2234,12 @@ function buildTools(scope, authentication) {
|
|
|
2195
2234
|
required: ["name"],
|
|
2196
2235
|
},
|
|
2197
2236
|
},
|
|
2198
|
-
nextCursor:
|
|
2199
|
-
type: "string",
|
|
2200
|
-
description: "Pass back as `cursor` to continue. Absent when the listing is complete.",
|
|
2201
|
-
},
|
|
2237
|
+
nextCursor: NEXT_CURSOR_OUTPUT_PROPERTY,
|
|
2202
2238
|
},
|
|
2203
2239
|
required: ["buckets"],
|
|
2204
2240
|
},
|
|
2205
2241
|
handler: async (args, ctx) => {
|
|
2206
|
-
const { result, resultInfo } = await callCloudflare(
|
|
2242
|
+
const { result, resultInfo } = await callCloudflare(send, {
|
|
2207
2243
|
method: "GET",
|
|
2208
2244
|
path: `/accounts/${encodeURIComponent(accountArg(args))}/r2/buckets`,
|
|
2209
2245
|
query: {
|
|
@@ -2243,7 +2279,7 @@ function buildTools(scope, authentication) {
|
|
|
2243
2279
|
},
|
|
2244
2280
|
outputSchema: R2_BUCKET_SCHEMA,
|
|
2245
2281
|
handler: async (args, ctx) => {
|
|
2246
|
-
const { result } = await callCloudflare(
|
|
2282
|
+
const { result } = await callCloudflare(send, {
|
|
2247
2283
|
method: "GET",
|
|
2248
2284
|
path: `/accounts/${encodePathSegment(accountArg(args))}/r2/buckets/${encodePathSegment(requireString(args, "bucketName"))}`,
|
|
2249
2285
|
headers: r2Headers(args),
|
|
@@ -2277,7 +2313,7 @@ function buildTools(scope, authentication) {
|
|
|
2277
2313
|
},
|
|
2278
2314
|
outputSchema: R2_BUCKET_SCHEMA,
|
|
2279
2315
|
handler: async (args, ctx) => {
|
|
2280
|
-
const { result } = await callCloudflare(
|
|
2316
|
+
const { result } = await callCloudflare(send, {
|
|
2281
2317
|
method: "POST",
|
|
2282
2318
|
path: `/accounts/${encodePathSegment(accountArg(args))}/r2/buckets`,
|
|
2283
2319
|
headers: r2Headers(args),
|
|
@@ -2319,7 +2355,7 @@ function buildTools(scope, authentication) {
|
|
|
2319
2355
|
},
|
|
2320
2356
|
outputSchema: R2_BUCKET_SCHEMA,
|
|
2321
2357
|
handler: async (args, ctx) => {
|
|
2322
|
-
const { result } = await callCloudflare(
|
|
2358
|
+
const { result } = await callCloudflare(send, {
|
|
2323
2359
|
method: "PATCH",
|
|
2324
2360
|
path: `/accounts/${encodePathSegment(accountArg(args))}/r2/buckets/${encodePathSegment(requireString(args, "bucketName"))}`,
|
|
2325
2361
|
headers: {
|
|
@@ -2354,7 +2390,7 @@ function buildTools(scope, authentication) {
|
|
|
2354
2390
|
},
|
|
2355
2391
|
handler: async (args, ctx) => {
|
|
2356
2392
|
const bucketName = requireString(args, "bucketName");
|
|
2357
|
-
await callCloudflare(
|
|
2393
|
+
await callCloudflare(send, {
|
|
2358
2394
|
method: "DELETE",
|
|
2359
2395
|
path: `/accounts/${encodePathSegment(accountArg(args))}/r2/buckets/${encodePathSegment(bucketName)}`,
|
|
2360
2396
|
headers: r2Headers(args),
|
|
@@ -2392,10 +2428,7 @@ function buildTools(scope, authentication) {
|
|
|
2392
2428
|
maximum: 1000,
|
|
2393
2429
|
description: "Objects per request, 1 to 1000.",
|
|
2394
2430
|
},
|
|
2395
|
-
cursor:
|
|
2396
|
-
type: "string",
|
|
2397
|
-
description: "Opaque cursor returned as nextCursor by the previous call.",
|
|
2398
|
-
},
|
|
2431
|
+
cursor: CURSOR_INPUT_PROPERTY,
|
|
2399
2432
|
},
|
|
2400
2433
|
required: [...scopeRequired("accountId", scope.accountId), "bucketName"],
|
|
2401
2434
|
additionalProperties: false,
|
|
@@ -2405,13 +2438,13 @@ function buildTools(scope, authentication) {
|
|
|
2405
2438
|
properties: {
|
|
2406
2439
|
objects: { type: "array", items: R2_OBJECT_SCHEMA },
|
|
2407
2440
|
commonPrefixes: { type: "array", items: { type: "string" } },
|
|
2408
|
-
nextCursor:
|
|
2441
|
+
nextCursor: NEXT_CURSOR_OUTPUT_PROPERTY,
|
|
2409
2442
|
truncated: { type: "boolean" },
|
|
2410
2443
|
},
|
|
2411
2444
|
required: ["objects", "truncated"],
|
|
2412
2445
|
},
|
|
2413
2446
|
handler: async (args, ctx) => {
|
|
2414
|
-
const { result, resultInfo } = await callCloudflare(
|
|
2447
|
+
const { result, resultInfo } = await callCloudflare(send, {
|
|
2415
2448
|
method: "GET",
|
|
2416
2449
|
path: `/accounts/${encodePathSegment(accountArg(args))}/r2/buckets/${encodePathSegment(requireString(args, "bucketName"))}/objects`,
|
|
2417
2450
|
headers: r2Headers(args),
|
|
@@ -2469,7 +2502,7 @@ function buildTools(scope, authentication) {
|
|
|
2469
2502
|
},
|
|
2470
2503
|
handler: async (args, ctx) => {
|
|
2471
2504
|
const objectKey = requireString(args, "objectKey");
|
|
2472
|
-
await callCloudflare(
|
|
2505
|
+
await callCloudflare(send, {
|
|
2473
2506
|
method: "DELETE",
|
|
2474
2507
|
path: `/accounts/${encodePathSegment(accountArg(args))}/r2/buckets/${encodePathSegment(requireString(args, "bucketName"))}/objects/${encodeObjectKey(objectKey)}`,
|
|
2475
2508
|
headers: r2Headers(args),
|
|
@@ -2477,25 +2510,17 @@ function buildTools(scope, authentication) {
|
|
|
2477
2510
|
return { deleted: true, objectKey };
|
|
2478
2511
|
},
|
|
2479
2512
|
},
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
handler: async (args, ctx) => {
|
|
2492
|
-
const { result } = await callCloudflare(base, {
|
|
2493
|
-
method: "GET",
|
|
2494
|
-
path: `/accounts/${encodePathSegment(accountArg(args))}/r2/metrics`,
|
|
2495
|
-
}, ctx);
|
|
2496
|
-
return asRecord(result);
|
|
2497
|
-
},
|
|
2498
|
-
},
|
|
2513
|
+
// No `get_r2_metrics`, `set_r2_cors`, or `delete_r2_cors` here on purpose.
|
|
2514
|
+
// The #350 measurement found `get_r2_metrics` an unprojected,
|
|
2515
|
+
// output-schema-less wrapper around a path, and `set_r2_cors` carrying a
|
|
2516
|
+
// free-form `additionalProperties: true` rule body, so its schema did not
|
|
2517
|
+
// validate the part of the call that actually fails. `delete_r2_cors`
|
|
2518
|
+
// measured clean — a fixed `{deleted}` confirmation behind a closed output
|
|
2519
|
+
// schema — and went anyway, as the other half of one policy pair: with the
|
|
2520
|
+
// write unnamed, a named delete would change a CORS policy through a
|
|
2521
|
+
// different route than setting it does. Reading a policy is still named;
|
|
2522
|
+
// changing one takes the approval-gated raw route, exactly as
|
|
2523
|
+
// structured-data DNS records already do.
|
|
2499
2524
|
{
|
|
2500
2525
|
name: "get_r2_cors",
|
|
2501
2526
|
description: "Get the browser CORS rules configured on an R2 bucket.",
|
|
@@ -2512,7 +2537,7 @@ function buildTools(scope, authentication) {
|
|
|
2512
2537
|
},
|
|
2513
2538
|
outputSchema: OPEN_OBJECT_OUTPUT_SCHEMA,
|
|
2514
2539
|
handler: async (args, ctx) => {
|
|
2515
|
-
const { result } = await callCloudflare(
|
|
2540
|
+
const { result } = await callCloudflare(send, {
|
|
2516
2541
|
method: "GET",
|
|
2517
2542
|
path: `/accounts/${encodePathSegment(accountArg(args))}/r2/buckets/${encodePathSegment(requireString(args, "bucketName"))}/cors`,
|
|
2518
2543
|
headers: r2Headers(args),
|
|
@@ -2520,65 +2545,6 @@ function buildTools(scope, authentication) {
|
|
|
2520
2545
|
return asRecord(result);
|
|
2521
2546
|
},
|
|
2522
2547
|
},
|
|
2523
|
-
{
|
|
2524
|
-
name: "set_r2_cors",
|
|
2525
|
-
description: "Replace an R2 bucket's CORS policy. Supply the complete desired rule list; omitted existing rules are removed.",
|
|
2526
|
-
annotations: { readOnlyHint: false, destructiveHint: true },
|
|
2527
|
-
inputSchema: {
|
|
2528
|
-
type: "object",
|
|
2529
|
-
properties: {
|
|
2530
|
-
accountId: scopeProperty("accountId", scope.accountId),
|
|
2531
|
-
bucketName: R2_BUCKET_NAME_PROPERTY,
|
|
2532
|
-
jurisdiction: R2_JURISDICTION_PROPERTY,
|
|
2533
|
-
rules: {
|
|
2534
|
-
type: "array",
|
|
2535
|
-
maxItems: 100,
|
|
2536
|
-
description: "Complete CORS rule list using Cloudflare fields: allowed.methods, allowed.origins, optional allowed.headers, id, exposeHeaders, and maxAgeSeconds.",
|
|
2537
|
-
items: { type: "object", additionalProperties: true },
|
|
2538
|
-
},
|
|
2539
|
-
},
|
|
2540
|
-
required: [...scopeRequired("accountId", scope.accountId), "bucketName", "rules"],
|
|
2541
|
-
additionalProperties: false,
|
|
2542
|
-
},
|
|
2543
|
-
outputSchema: OPEN_OBJECT_OUTPUT_SCHEMA,
|
|
2544
|
-
handler: async (args, ctx) => {
|
|
2545
|
-
const { result } = await callCloudflare(base, {
|
|
2546
|
-
method: "PUT",
|
|
2547
|
-
path: `/accounts/${encodePathSegment(accountArg(args))}/r2/buckets/${encodePathSegment(requireString(args, "bucketName"))}/cors`,
|
|
2548
|
-
headers: r2Headers(args),
|
|
2549
|
-
body: { rules: args["rules"] },
|
|
2550
|
-
}, ctx);
|
|
2551
|
-
return asRecord(result);
|
|
2552
|
-
},
|
|
2553
|
-
},
|
|
2554
|
-
{
|
|
2555
|
-
name: "delete_r2_cors",
|
|
2556
|
-
description: "Remove the complete CORS policy from an R2 bucket.",
|
|
2557
|
-
annotations: { readOnlyHint: false, destructiveHint: true },
|
|
2558
|
-
inputSchema: {
|
|
2559
|
-
type: "object",
|
|
2560
|
-
properties: {
|
|
2561
|
-
accountId: scopeProperty("accountId", scope.accountId),
|
|
2562
|
-
bucketName: R2_BUCKET_NAME_PROPERTY,
|
|
2563
|
-
jurisdiction: R2_JURISDICTION_PROPERTY,
|
|
2564
|
-
},
|
|
2565
|
-
required: [...scopeRequired("accountId", scope.accountId), "bucketName"],
|
|
2566
|
-
additionalProperties: false,
|
|
2567
|
-
},
|
|
2568
|
-
outputSchema: {
|
|
2569
|
-
type: "object",
|
|
2570
|
-
properties: { deleted: { type: "boolean" } },
|
|
2571
|
-
required: ["deleted"],
|
|
2572
|
-
},
|
|
2573
|
-
handler: async (args, ctx) => {
|
|
2574
|
-
await callCloudflare(base, {
|
|
2575
|
-
method: "DELETE",
|
|
2576
|
-
path: `/accounts/${encodePathSegment(accountArg(args))}/r2/buckets/${encodePathSegment(requireString(args, "bucketName"))}/cors`,
|
|
2577
|
-
headers: r2Headers(args),
|
|
2578
|
-
}, ctx);
|
|
2579
|
-
return { deleted: true };
|
|
2580
|
-
},
|
|
2581
|
-
},
|
|
2582
2548
|
{
|
|
2583
2549
|
name: "list_pages_projects",
|
|
2584
2550
|
description: "List Cloudflare Pages projects in an account, with their production branch and latest deployment.",
|
|
@@ -2614,7 +2580,7 @@ function buildTools(scope, authentication) {
|
|
|
2614
2580
|
required: ["name"],
|
|
2615
2581
|
}),
|
|
2616
2582
|
handler: async (args, ctx) => {
|
|
2617
|
-
const { result, resultInfo } = await callCloudflare(
|
|
2583
|
+
const { result, resultInfo } = await callCloudflare(send, {
|
|
2618
2584
|
method: "GET",
|
|
2619
2585
|
path: `/accounts/${encodeURIComponent(accountArg(args))}/pages/projects`,
|
|
2620
2586
|
query: {
|
|
@@ -2650,7 +2616,7 @@ function buildTools(scope, authentication) {
|
|
|
2650
2616
|
},
|
|
2651
2617
|
outputSchema: OPEN_OBJECT_OUTPUT_SCHEMA,
|
|
2652
2618
|
handler: async (args, ctx) => {
|
|
2653
|
-
const { result } = await callCloudflare(
|
|
2619
|
+
const { result } = await callCloudflare(send, {
|
|
2654
2620
|
method: "GET",
|
|
2655
2621
|
path: `/accounts/${encodePathSegment(accountArg(args))}/pages/projects/${encodePathSegment(requireString(args, "projectName"))}`,
|
|
2656
2622
|
}, ctx);
|
|
@@ -2682,7 +2648,7 @@ function buildTools(scope, authentication) {
|
|
|
2682
2648
|
},
|
|
2683
2649
|
outputSchema: listOutputSchema("deployments", OPEN_OBJECT_OUTPUT_SCHEMA),
|
|
2684
2650
|
handler: async (args, ctx) => {
|
|
2685
|
-
const { result, resultInfo } = await callCloudflare(
|
|
2651
|
+
const { result, resultInfo } = await callCloudflare(send, {
|
|
2686
2652
|
method: "GET",
|
|
2687
2653
|
path: `/accounts/${encodePathSegment(accountArg(args))}/pages/projects/${encodePathSegment(requireString(args, "projectName"))}/deployments`,
|
|
2688
2654
|
query: {
|
|
@@ -2726,7 +2692,7 @@ function buildTools(scope, authentication) {
|
|
|
2726
2692
|
},
|
|
2727
2693
|
outputSchema: OPEN_OBJECT_OUTPUT_SCHEMA,
|
|
2728
2694
|
handler: async (args, ctx) => {
|
|
2729
|
-
const { result } = await callCloudflare(
|
|
2695
|
+
const { result } = await callCloudflare(send, {
|
|
2730
2696
|
method: "GET",
|
|
2731
2697
|
path: `/accounts/${encodePathSegment(accountArg(args))}/pages/projects/${encodePathSegment(requireString(args, "projectName"))}/deployments/${encodePathSegment(requireString(args, "deploymentId"))}`,
|
|
2732
2698
|
}, ctx);
|
|
@@ -2749,7 +2715,7 @@ function buildTools(scope, authentication) {
|
|
|
2749
2715
|
},
|
|
2750
2716
|
outputSchema: OPEN_OBJECT_OUTPUT_SCHEMA,
|
|
2751
2717
|
handler: async (args, ctx) => {
|
|
2752
|
-
const { result } = await callCloudflare(
|
|
2718
|
+
const { result } = await callCloudflare(send, {
|
|
2753
2719
|
method: "POST",
|
|
2754
2720
|
path: `/accounts/${encodePathSegment(accountArg(args))}/pages/projects/${encodePathSegment(requireString(args, "projectName"))}/deployments/${encodePathSegment(requireString(args, "deploymentId"))}/retry`,
|
|
2755
2721
|
}, ctx);
|
|
@@ -2772,7 +2738,7 @@ function buildTools(scope, authentication) {
|
|
|
2772
2738
|
},
|
|
2773
2739
|
outputSchema: OPEN_OBJECT_OUTPUT_SCHEMA,
|
|
2774
2740
|
handler: async (args, ctx) => {
|
|
2775
|
-
const { result } = await callCloudflare(
|
|
2741
|
+
const { result } = await callCloudflare(send, {
|
|
2776
2742
|
method: "POST",
|
|
2777
2743
|
path: `/accounts/${encodePathSegment(accountArg(args))}/pages/projects/${encodePathSegment(requireString(args, "projectName"))}/deployments/${encodePathSegment(requireString(args, "deploymentId"))}/rollback`,
|
|
2778
2744
|
}, ctx);
|
|
@@ -2796,7 +2762,7 @@ function buildTools(scope, authentication) {
|
|
|
2796
2762
|
outputSchema: { type: "object", properties: { deleted: { type: "boolean" }, deploymentId: { type: "string" } }, required: ["deleted", "deploymentId"] },
|
|
2797
2763
|
handler: async (args, ctx) => {
|
|
2798
2764
|
const deploymentId = requireString(args, "deploymentId");
|
|
2799
|
-
await callCloudflare(
|
|
2765
|
+
await callCloudflare(send, {
|
|
2800
2766
|
method: "DELETE",
|
|
2801
2767
|
path: `/accounts/${encodePathSegment(accountArg(args))}/pages/projects/${encodePathSegment(requireString(args, "projectName"))}/deployments/${encodePathSegment(deploymentId)}`,
|
|
2802
2768
|
}, ctx);
|
|
@@ -2818,7 +2784,7 @@ function buildTools(scope, authentication) {
|
|
|
2818
2784
|
},
|
|
2819
2785
|
outputSchema: listOutputSchema("domains", OPEN_OBJECT_OUTPUT_SCHEMA),
|
|
2820
2786
|
handler: async (args, ctx) => {
|
|
2821
|
-
const { result } = await callCloudflare(
|
|
2787
|
+
const { result } = await callCloudflare(send, {
|
|
2822
2788
|
method: "GET",
|
|
2823
2789
|
path: `/accounts/${encodePathSegment(accountArg(args))}/pages/projects/${encodePathSegment(requireString(args, "projectName"))}/domains`,
|
|
2824
2790
|
}, ctx);
|
|
@@ -2841,7 +2807,7 @@ function buildTools(scope, authentication) {
|
|
|
2841
2807
|
},
|
|
2842
2808
|
outputSchema: OPEN_OBJECT_OUTPUT_SCHEMA,
|
|
2843
2809
|
handler: async (args, ctx) => {
|
|
2844
|
-
const { result } = await callCloudflare(
|
|
2810
|
+
const { result } = await callCloudflare(send, {
|
|
2845
2811
|
method: "POST",
|
|
2846
2812
|
path: `/accounts/${encodePathSegment(accountArg(args))}/pages/projects/${encodePathSegment(requireString(args, "projectName"))}/domains`,
|
|
2847
2813
|
body: { name: requireString(args, "domain") },
|
|
@@ -2866,7 +2832,7 @@ function buildTools(scope, authentication) {
|
|
|
2866
2832
|
outputSchema: { type: "object", properties: { deleted: { type: "boolean" }, domain: { type: "string" } }, required: ["deleted", "domain"] },
|
|
2867
2833
|
handler: async (args, ctx) => {
|
|
2868
2834
|
const domain = requireString(args, "domain");
|
|
2869
|
-
await callCloudflare(
|
|
2835
|
+
await callCloudflare(send, {
|
|
2870
2836
|
method: "DELETE",
|
|
2871
2837
|
path: `/accounts/${encodePathSegment(accountArg(args))}/pages/projects/${encodePathSegment(requireString(args, "projectName"))}/domains/${encodePathSegment(domain)}`,
|
|
2872
2838
|
}, ctx);
|
|
@@ -2888,7 +2854,7 @@ function buildTools(scope, authentication) {
|
|
|
2888
2854
|
},
|
|
2889
2855
|
outputSchema: { type: "object", properties: { purged: { type: "boolean" } }, required: ["purged"] },
|
|
2890
2856
|
handler: async (args, ctx) => {
|
|
2891
|
-
await callCloudflare(
|
|
2857
|
+
await callCloudflare(send, {
|
|
2892
2858
|
method: "POST",
|
|
2893
2859
|
path: `/accounts/${encodePathSegment(accountArg(args))}/pages/projects/${encodePathSegment(requireString(args, "projectName"))}/purge_build_cache`,
|
|
2894
2860
|
}, ctx);
|
|
@@ -2911,7 +2877,7 @@ function buildTools(scope, authentication) {
|
|
|
2911
2877
|
outputSchema: { type: "object", properties: { deleted: { type: "boolean" }, projectName: { type: "string" } }, required: ["deleted", "projectName"] },
|
|
2912
2878
|
handler: async (args, ctx) => {
|
|
2913
2879
|
const projectName = requireString(args, "projectName");
|
|
2914
|
-
await callCloudflare(
|
|
2880
|
+
await callCloudflare(send, {
|
|
2915
2881
|
method: "DELETE",
|
|
2916
2882
|
path: `/accounts/${encodePathSegment(accountArg(args))}/pages/projects/${encodePathSegment(projectName)}`,
|
|
2917
2883
|
}, ctx);
|
|
@@ -2923,7 +2889,7 @@ function buildTools(scope, authentication) {
|
|
|
2923
2889
|
// `destructiveHint` stays unset. `readOnlyHint: false` already routes it
|
|
2924
2890
|
// through call_destructive_tool.
|
|
2925
2891
|
name: "create_dns_record",
|
|
2926
|
-
description: "Create a content-based DNS record
|
|
2892
|
+
description: "Create a content-based DNS record in a zone; the type enum lists the creatable types. Check list_dns_records first — Cloudflare rejects a duplicate rather than replacing it. Structured types like SRV and CAA are readable but not creatable.",
|
|
2927
2893
|
annotations: { readOnlyHint: false },
|
|
2928
2894
|
inputSchema: {
|
|
2929
2895
|
type: "object",
|
|
@@ -2978,7 +2944,7 @@ function buildTools(scope, authentication) {
|
|
|
2978
2944
|
},
|
|
2979
2945
|
outputSchema: DNS_RECORD_SCHEMA,
|
|
2980
2946
|
handler: async (args, ctx) => {
|
|
2981
|
-
const { result } = await callCloudflare(
|
|
2947
|
+
const { result } = await callCloudflare(send, {
|
|
2982
2948
|
method: "POST",
|
|
2983
2949
|
path: `/zones/${encodeURIComponent(zoneArg(args))}/dns_records`,
|
|
2984
2950
|
body: {
|
|
@@ -3079,7 +3045,7 @@ function buildTools(scope, authentication) {
|
|
|
3079
3045
|
},
|
|
3080
3046
|
});
|
|
3081
3047
|
}
|
|
3082
|
-
const { result } = await callCloudflare(
|
|
3048
|
+
const { result } = await callCloudflare(send, {
|
|
3083
3049
|
method: "PATCH",
|
|
3084
3050
|
path: `/zones/${encodeURIComponent(zoneArg(args))}/dns_records/${encodeURIComponent(String(args["recordId"]))}`,
|
|
3085
3051
|
body,
|
|
@@ -3113,7 +3079,7 @@ function buildTools(scope, authentication) {
|
|
|
3113
3079
|
},
|
|
3114
3080
|
handler: async (args, ctx) => {
|
|
3115
3081
|
const recordId = String(args["recordId"]);
|
|
3116
|
-
await callCloudflare(
|
|
3082
|
+
await callCloudflare(send, {
|
|
3117
3083
|
method: "DELETE",
|
|
3118
3084
|
path: `/zones/${encodeURIComponent(zoneArg(args))}/dns_records/${encodeURIComponent(recordId)}`,
|
|
3119
3085
|
}, ctx);
|
|
@@ -3213,7 +3179,7 @@ function buildTools(scope, authentication) {
|
|
|
3213
3179
|
});
|
|
3214
3180
|
}
|
|
3215
3181
|
const variant = everything ? "everything" : targeted[0];
|
|
3216
|
-
await callCloudflare(
|
|
3182
|
+
await callCloudflare(send, {
|
|
3217
3183
|
method: "POST",
|
|
3218
3184
|
path: `/zones/${encodeURIComponent(zoneId)}/purge_cache`,
|
|
3219
3185
|
body: everything
|
|
@@ -3246,10 +3212,11 @@ Account purpose: ${purpose}
|
|
|
3246
3212
|
|
|
3247
3213
|
- ${zoneLine}
|
|
3248
3214
|
- ${accountLine}
|
|
3249
|
-
- Prefer a named tool: its schema is complete, projected, and enough to call it without provider documentation. For an operation without a named tool, use \`cloudflare_api_get\` for GET, \`cloudflare_api_mutate\` for JSON POST/PUT/PATCH/DELETE, or \`cloudflare_api_upload\` for raw and multipart content. Raw tools take a path below \`/client/v4\`; their argument schemas are complete, but endpoint-specific query, header, and body fields come from Cloudflare's API reference. Use \`headers\` for endpoint-specific controls such as \`cf-r2-jurisdiction\`,
|
|
3215
|
+
- Prefer a named tool: its schema is complete, projected, and enough to call it without provider documentation. For an operation without a named tool, use \`cloudflare_api_get\` for GET, \`cloudflare_api_mutate\` for JSON POST/PUT/PATCH/DELETE, or \`cloudflare_api_upload\` for raw and multipart content. Raw tools take a path below \`/client/v4\`; their argument schemas are complete, but endpoint-specific query, header, and body fields come from Cloudflare's API reference. Use \`headers\` for endpoint-specific controls such as \`cf-r2-jurisdiction\`, \`Range\`, \`If-None-Match\`, and Cloudflare product metadata. \`Authorization\`, \`Cookie\`, \`Host\`, \`Content-Length\`, \`Content-Type\`, and \`Transfer-Encoding\` are connector-owned and refused: authentication, host, content type, and request framing are not the caller's to set.
|
|
3250
3216
|
- The raw tools cover the wider control plane without weakening routing: GET is explicitly read-only; every mutation and upload is destructive and must cross the host's approval boundary. The configured Cloudflare credential remains the hard provider-side permission boundary. Absolute URLs, traversal, and query strings embedded in \`path\` are refused locally.
|
|
3251
3217
|
- Useful raw paths include \`/accounts/{accountId}/images/v1\` (Images), \`/accounts/{accountId}/stream\` (Stream), \`/zones/{zoneId}/email/routing/rules\` (Email Routing), \`/accounts/{accountId}/d1/database\` (D1), and \`/accounts/{accountId}/queues\` (Queues). On GET, use \`responseType: "text"\` or \`"base64"\` for non-JSON content. Direct-upload endpoints can issue upload URLs; \`cloudflare_api_upload\` can also send explicit text, base64 bytes, or multipart fields/files.
|
|
3252
|
-
-
|
|
3218
|
+
- Two R2 areas are deliberately unnamed. Read a bucket's CORS policy with \`get_r2_cors\`, then change it with \`cloudflare_api_mutate\` — \`PUT\` or \`DELETE /accounts/{accountId}/r2/buckets/{bucketName}/cors\`, rule fields per Cloudflare's reference — and read account storage totals with \`cloudflare_api_get\` at \`/accounts/{accountId}/r2/metrics\`.
|
|
3219
|
+
- Lists paginate with \`page\` and \`perPage\` and return a \`page\` object; request the next page only when \`page.hasMore\` is true. \`list_zone_rulesets\`, \`list_r2_buckets\`, \`list_r2_objects\`, and \`list_kv_keys\` page by cursor instead: pass \`cursor\`, continue while \`nextCursor\` is present, and expect no \`page\` object. Their schemas say so too. \`list_worker_scripts\` is unpaginated.
|
|
3253
3220
|
- Results are projected to the fields that identify and describe a resource. Pass \`raw: true\` on a read when you genuinely need a field the projection drops.
|
|
3254
3221
|
- ${authenticationLine}
|
|
3255
3222
|
- A \`rate_limited\` failure carries the wait window. Cloudflare's limit is 1,200 requests per five minutes per user, counted across the dashboard and every token, so do not fan out speculatively; filter server-side with \`name\`, \`type\`, and \`content\` instead of listing everything and filtering locally.
|
|
@@ -3273,7 +3240,7 @@ export function cloudflare(id, options) {
|
|
|
3273
3240
|
throw new Error('cloudflare() authentication must be "apiToken" or "globalApiKey".');
|
|
3274
3241
|
}
|
|
3275
3242
|
const scope = {
|
|
3276
|
-
|
|
3243
|
+
send: cloudflareTransport(options.baseUrl?.trim() || CLOUDFLARE_API_BASE),
|
|
3277
3244
|
accountId: options.accountId?.trim() || undefined,
|
|
3278
3245
|
zoneId: options.zoneId?.trim() || undefined,
|
|
3279
3246
|
};
|
|
@@ -3282,10 +3249,18 @@ export function cloudflare(id, options) {
|
|
|
3282
3249
|
description: `Cloudflare control-plane access for zones, DNS, Workers, KV, R2, Pages, media, email, and other v4 APIs — ${purpose}`,
|
|
3283
3250
|
credential: credentialConfig(authentication, options.credential),
|
|
3284
3251
|
callAdmission: admissionPolicy(maxConcurrency),
|
|
3285
|
-
usageGuide:
|
|
3286
|
-
|
|
3287
|
-
|
|
3288
|
-
|
|
3252
|
+
usageGuide: {
|
|
3253
|
+
content: usageGuide(purpose, scope, options.instructions, authentication),
|
|
3254
|
+
// Explicit rather than derived: the first content line is the zone
|
|
3255
|
+
// scoping rule, which varies per deployment and reads as an instruction
|
|
3256
|
+
// rather than as the routing fact a browsing agent needs.
|
|
3257
|
+
summary: "Zone and account scoping, named-vs-raw routing, two pagination shapes, and lean-vs-raw results.",
|
|
3258
|
+
// Deliberately not `required`. Every named tool's schema is complete
|
|
3259
|
+
// enough to call it correctly on its own, and the scoping convention the
|
|
3260
|
+
// guide carries is repeated on each `zoneId` and `accountId` property —
|
|
3261
|
+
// so forcing the guide into context before every operation would spend
|
|
3262
|
+
// tokens on a sequence the schemas already express.
|
|
3263
|
+
},
|
|
3289
3264
|
...(options.maxResultBytes !== undefined
|
|
3290
3265
|
? { maxResultBytes: options.maxResultBytes }
|
|
3291
3266
|
: {}),
|
|
@@ -3294,7 +3269,7 @@ export function cloudflare(id, options) {
|
|
|
3294
3269
|
? {
|
|
3295
3270
|
async testCredential(value, ctx) {
|
|
3296
3271
|
try {
|
|
3297
|
-
const { result } = await callCloudflare(scope.
|
|
3272
|
+
const { result } = await callCloudflare(scope.send, { method: "GET", path: "/user/tokens/verify" }, withAuthentication({
|
|
3298
3273
|
...ctx,
|
|
3299
3274
|
credential: {
|
|
3300
3275
|
get: async () => value,
|
|
@@ -3317,7 +3292,7 @@ export function cloudflare(id, options) {
|
|
|
3317
3292
|
: {
|
|
3318
3293
|
async testCredentials(values, ctx) {
|
|
3319
3294
|
try {
|
|
3320
|
-
const { result } = await callCloudflare(scope.
|
|
3295
|
+
const { result } = await callCloudflare(scope.send, { method: "GET", path: "/user" }, withAuthentication({
|
|
3321
3296
|
...ctx,
|
|
3322
3297
|
credential: {
|
|
3323
3298
|
get: async (field) => field ? values[field] ?? null : null,
|
|
@@ -3340,4 +3315,3 @@ export function cloudflare(id, options) {
|
|
|
3340
3315
|
}),
|
|
3341
3316
|
});
|
|
3342
3317
|
}
|
|
3343
|
-
//# sourceMappingURL=cloudflare.js.map
|