@bettercms-ai/mcp 0.79.1 → 0.81.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/dist/index.js
CHANGED
|
@@ -2907,6 +2907,19 @@ var LISTING_TAIL = /* @__PURE__ */ new Set([
|
|
|
2907
2907
|
"generate_image",
|
|
2908
2908
|
"transform_image",
|
|
2909
2909
|
"write_alt_text",
|
|
2910
|
+
// Custom integrations: reached for once a site exists and its owner names a vendor.
|
|
2911
|
+
"list_integrations",
|
|
2912
|
+
"get_integration",
|
|
2913
|
+
"create_integration",
|
|
2914
|
+
"update_integration",
|
|
2915
|
+
"delete_integration",
|
|
2916
|
+
"test_integration_fetch",
|
|
2917
|
+
"run_integration_sync",
|
|
2918
|
+
"run_integration_function",
|
|
2919
|
+
"search_integration_reference",
|
|
2920
|
+
"start_integration_signin",
|
|
2921
|
+
"save_integration_template",
|
|
2922
|
+
"install_integration_template",
|
|
2910
2923
|
// The ABM campaign lane — also hidden from the default listing (ABM_TOOLS below).
|
|
2911
2924
|
"research_account",
|
|
2912
2925
|
"build_abm_page",
|
|
@@ -2990,7 +3003,19 @@ var NEW_TOOL_TEXT = {
|
|
|
2990
3003
|
import_redirects: "Bulk-create redirects for a migration, from `rows` or from `text` in `format` (our CSV export, a Netlify `_redirects` file, or a vercel.json). Call it with `dryRun: true` FIRST: nothing is written and each row comes back `would-create`, `existing` or `skipped` with a reason. Rows get create_redirect's rules. Max 5000.",
|
|
2991
3004
|
editor_setup: "Make the live build editable: derives pages, collections, forms, bindings and components from the live release (skill bindings). Run it after an import or a rebuild, before the conversion brief. Idempotent: `ready` when it already ran for the live sha, else it starts (`running`; poll with `check: true`). `state`: never or stale (run it), running, ready, failed. 409 = nothing is live yet: deploy first. Then get_next_steps.",
|
|
2992
3005
|
transform_image: "Edit an existing Media Library image with an instruction (e.g. 'remove the background', 'make it dusk'); the result is saved as a NEW asset and the original is kept (5 AI credits). Returns the new asset (id, url, altText).",
|
|
2993
|
-
write_alt_text: "Alt text for a Media Library image (mediaId) or an https image URL (url), written from its pixels (1 AI credit). A suggestion: save it with update_media."
|
|
3006
|
+
write_alt_text: "Alt text for a Media Library image (mediaId) or an https image URL (url), written from its pixels (1 AI credit). A suggestion: save it with update_media.",
|
|
3007
|
+
list_integrations: "List the project's custom integrations (any vendor with a public API) and the workspace's integration `templates`. Each has its hosts, secret NAMES with `secretsPresent` (never a value), syncs, hooks, endpoints, functions and `approved`. Read bettercms://skill/integrations first.",
|
|
3008
|
+
get_integration: "One integration (`integration`: id or slug): `hookUrls`, `endpointUrls`, `oauthStatus`, its last sync runs, write-backs (`pushes`), function runs, webhook deliveries and vendor calls (the call log).",
|
|
3009
|
+
create_integration: "Declare a custom integration. Shapes: bettercms://skill/integrations. Secret VALUES never pass through here (the user sets env vars; list_env_vars shows names). Until an admin approves it, every vendor call, sync, webhook, endpoint and function is refused: give the user `approval.approveUrl` and `approval.changes` in plain words. You cannot approve it.",
|
|
3010
|
+
update_integration: "Change an integration (`integration`: id or slug); parameters as create_integration, keys left out are kept, lists replace the stored ones whole. A change to hosts, secrets, inject, allowPost, auth, oauth, hooks, endpoints, references or functions withdraws its approval (`approval.approveUrl`); name, syncs, settings and panel never need it.",
|
|
3011
|
+
delete_integration: "Delete an integration and its sync runs. Entries it synced stay (their provenance still names it); the env vars stay.",
|
|
3012
|
+
run_integration_sync: "Run one of an integration's syncs now (`integration`, `sync`: its key): every page of the vendor list is fetched and each item is created or updated as a DRAFT entry, matched on its externalKey, so a re-run only changes what changed (`unchanged` counts the rest); `publish: true` on the sync publishes what changed. Answers with the run: queued, running, done (counts: created, updated, unchanged, failed, pages, items) or failed (error). `waitSeconds` (\u2264 20) waits for it to finish; else follow it with get_integration. A sync with `schedule` 'hourly' or 'daily' also runs on its own.",
|
|
3013
|
+
run_integration_function: "Run an integration's function (bettercms/functions/<name>.ts, trigger 'manual') with `input`. Its fetch() reaches only the integration's approved hosts and the server adds the secrets: the code never sees them. `waitSeconds` (\u2264 20) answers with output, logs or error.",
|
|
3014
|
+
search_integration_reference: "Search an integration's live reference (`reference`: its key) at the vendor: up to 20 {id, title, image}. Store the pick in a json field (skill \xA712); the site resolves it live.",
|
|
3015
|
+
start_integration_signin: "Start the vendor sign-in of an integration with `oauth`: a `url` the USER opens to sign in with their own OAuth app (register `redirectUri` in it first). Tokens stay on the server.",
|
|
3016
|
+
save_integration_template: "Save an integration as a workspace template: its shape, never a secret value or its settings, with copies of the collections its syncs write into.",
|
|
3017
|
+
install_integration_template: "Install a workspace template on this project: missing collections are created and the integration waits for approval (`approval.approveUrl`); `secretsNeeded` lists the env vars to set.",
|
|
3018
|
+
test_integration_fetch: "Call the vendor once through the server, as the integration: an approved host only, with the integration's `inject` secrets added server-side and every secret redacted from the answer. The request itself takes no {{...}} templates, and the token endpoint cannot be called. Use it to read the response shape before writing a sync: `items`, `externalKey` and `map` are JSON Pointers into it. Bodies over 1 MB come back truncated. 409 integration_not_approved: an admin must approve it first."
|
|
2994
3019
|
};
|
|
2995
3020
|
var DELETE_PAGE_RUNTIME_BUNDLE = " Or, with no pageId, `runtimeBundle`: 'report' lists the duplicate pages derived from a server app's own bundle (`app/` folders); 'apply' retires them and their empty folders.";
|
|
2996
3021
|
var FIELD_LOCKED_NOTE = "A readOnly 'developer' field keeps its stored value: changing or omitting it without schema access is 403 FIELD_LOCKED.";
|
|
@@ -3041,6 +3066,31 @@ var PARAM_TEXT = {
|
|
|
3041
3066
|
mergeHref: "pageId only: the link field paired with `path` (the label). Both become ONE `button` field keyed `key` (default: their stem, primaryCtaHref \u2192 primaryCta). Each entry's DRAFT gets {label, href} and keeps the old values; the live copy changes on publish. ifMatch is the page's version. 409 CODE_RENDERED_ROUTE: do its `next` recipe in code",
|
|
3042
3067
|
confirmedInput: "true only after the user explicitly approved adding this custom input (`ui.input`); else setting or changing one is refused input_needs_confirmation. Removing one needs no approval"
|
|
3043
3068
|
};
|
|
3069
|
+
var INTEGRATION_PARAM_TEXT = {
|
|
3070
|
+
integration: "the integration's id or slug (from list_integrations)",
|
|
3071
|
+
slug: "lowercase letters, digits, hyphens; at most 48",
|
|
3072
|
+
allowedHosts: "exact hostnames the server may call, e.g. ['boards-api.greenhouse.io']; https only",
|
|
3073
|
+
secrets: "template name (UPPER_SNAKE) -> project env var KEY, e.g. {TOKEN: 'SHOPIFY_ADMIN_TOKEN'}; never a value",
|
|
3074
|
+
inject: "where the secrets go on every vendor request: {headers?: {name: template}, query?: {name: template}}, templates {{secret.NAME}} or {{token}}",
|
|
3075
|
+
allowPost: "true lets requests other than GET through (vendor writes, POST search APIs such as Apollo's); GET only when omitted",
|
|
3076
|
+
auth: "optional token exchange (skill \xA75); its result is {{token}}",
|
|
3077
|
+
settings: "non-secret JSON the panel reads and writes (store id, toggles); at most 16 KB",
|
|
3078
|
+
syncs: "vendor list -> collection [{key, contentModelId, request, items, externalKey, map, item?, writeBack?, publish?, schedule?}] (skill \xA76; two-way \xA715)",
|
|
3079
|
+
hooks: "vendor webhooks [{key, verify, action}] (skill \xA79); the vendor posts to `hookUrls`",
|
|
3080
|
+
endpoints: "public reads for the site [{key, request, params, pick, cacheSeconds?}] (skill \xA711); at `endpointUrls`",
|
|
3081
|
+
references: "live references [{key, label, search, lookup, items, id, title}] (skill \xA712)",
|
|
3082
|
+
functions: "[{name, triggers?, cpuMs?}]: bettercms/functions/<name>.ts (skill \xA710)",
|
|
3083
|
+
oauth: "sign-in with the customer's own OAuth app {authorizeUrl, tokenUrl, scopes, clientId, clientSecret} (secret NAMES; skill \xA713)",
|
|
3084
|
+
alertAfter: "tell admins after this many failed runs in a row (0 = never; 3 when omitted)",
|
|
3085
|
+
reference: "the reference's key (from the integration's references)",
|
|
3086
|
+
template: "the template's slug (from list_integrations `templates`)",
|
|
3087
|
+
panel: "the custom panel's slug: bettercms/panels/<panel>.tsx in the site repo; null for the stock page",
|
|
3088
|
+
url: "the full https URL on an allowed host (no templates in the URL)",
|
|
3089
|
+
sync: "the sync's key (from the integration's syncs)",
|
|
3090
|
+
headers: "header -> value (no templates: the integration's inject adds the secrets)",
|
|
3091
|
+
query: "query parameter -> value (no templates)",
|
|
3092
|
+
json: "a JSON body for POST"
|
|
3093
|
+
};
|
|
3044
3094
|
var INPUT_CONFIRMED_HEADER = "x-bcms-confirmed-input";
|
|
3045
3095
|
var BUTTON_FIELD_NOTE = "'button' is ONE call to action, value {label, href, variant? (a Button family look), size?, arrow?, icon?, newTab?, rel?, fullWidth?} (arrow:false, icon:null off): never a text field beside a link field.";
|
|
3046
3096
|
var LINK_VALUE_NOTE = "A link or button href: a URL string or {type: url|page|entry|email|phone|anchor|file, href, title?, newTab?, rel?, section?, ref: page/entry id}.";
|
|
@@ -3327,6 +3377,7 @@ var uiObject = z.strictObject({
|
|
|
3327
3377
|
placeholder: z.string().min(1).max(120).optional().describe("ghost text, a field of any type. A prop uses its own `placeholder`."),
|
|
3328
3378
|
synced: z.strictObject({ from: z.string().min(1).max(64) }).optional().describe("the value comes from this global; edits apply everywhere."),
|
|
3329
3379
|
valueShape: z.enum(["string", "object"]).optional().describe("a link / image / button writes a plain string or the object."),
|
|
3380
|
+
reference: z.object({ integration: z.string(), key: z.string() }).strict().optional().describe("a json field holding a live vendor item: the integration's slug and reference key."),
|
|
3330
3381
|
access: z.strictObject({ view: z.literal("schema.view").optional(), edit: z.literal("schema.manage").optional() }).optional().describe("who sees (view: developer-only) and who changes (edit) it, gated in the editor. The enforced lock is readOnly:'developer'."),
|
|
3331
3382
|
hidden: z.boolean().optional().describe("true: never shown in the form (a system value). A conditional hide is showIf."),
|
|
3332
3383
|
blocks: z.record(z.string(), z.strictObject({ icon: dockIconArg.optional(), preview: z.record(z.string(), z.string()).optional() })).optional().describe("modular only: per block slug, {icon?, preview?} for its rows."),
|
|
@@ -3511,6 +3562,25 @@ function proseType(f) {
|
|
|
3511
3562
|
}
|
|
3512
3563
|
var confirmedHeaders = (confirmed) => confirmed === true ? { [INPUT_CONFIRMED_HEADER]: "true" } : {};
|
|
3513
3564
|
var withHeaders = (headers) => Object.keys(headers).length > 0 ? { headers } : {};
|
|
3565
|
+
var integrationShape = {
|
|
3566
|
+
allowedHosts: z.array(z.string()).max(10).optional().describe(INTEGRATION_PARAM_TEXT.allowedHosts),
|
|
3567
|
+
secrets: z.record(z.string(), z.string()).optional().describe(INTEGRATION_PARAM_TEXT.secrets),
|
|
3568
|
+
inject: z.object({ headers: z.record(z.string(), z.string()).optional(), query: z.record(z.string(), z.string()).optional() }).optional().describe(INTEGRATION_PARAM_TEXT.inject),
|
|
3569
|
+
allowPost: z.boolean().optional().describe(INTEGRATION_PARAM_TEXT.allowPost),
|
|
3570
|
+
auth: z.record(z.string(), z.unknown()).nullable().optional().describe(INTEGRATION_PARAM_TEXT.auth),
|
|
3571
|
+
settings: z.record(z.string(), z.unknown()).optional().describe(INTEGRATION_PARAM_TEXT.settings),
|
|
3572
|
+
syncs: z.array(z.record(z.string(), z.unknown())).max(20).optional().describe(INTEGRATION_PARAM_TEXT.syncs),
|
|
3573
|
+
panel: z.string().max(48).nullable().optional().describe(INTEGRATION_PARAM_TEXT.panel),
|
|
3574
|
+
hooks: z.array(z.record(z.string(), z.unknown())).max(20).optional().describe(INTEGRATION_PARAM_TEXT.hooks),
|
|
3575
|
+
endpoints: z.array(z.record(z.string(), z.unknown())).max(20).optional().describe(INTEGRATION_PARAM_TEXT.endpoints),
|
|
3576
|
+
references: z.array(z.record(z.string(), z.unknown())).max(10).optional().describe(INTEGRATION_PARAM_TEXT.references),
|
|
3577
|
+
functions: z.array(z.record(z.string(), z.unknown())).max(20).optional().describe(INTEGRATION_PARAM_TEXT.functions),
|
|
3578
|
+
oauth: z.record(z.string(), z.unknown()).nullable().optional().describe(INTEGRATION_PARAM_TEXT.oauth),
|
|
3579
|
+
alertAfter: z.number().int().min(0).max(50).optional().describe(INTEGRATION_PARAM_TEXT.alertAfter)
|
|
3580
|
+
};
|
|
3581
|
+
var integrationShapeBare = Object.fromEntries(
|
|
3582
|
+
Object.entries(integrationShape).map(([k, v]) => [k, v.describe(void 0)])
|
|
3583
|
+
);
|
|
3514
3584
|
var DRY_RUN_SUMMARY = "Dry run: nothing was written.";
|
|
3515
3585
|
var dryRunOf = async (client, method, path, body, headers = {}) => ok(DRY_RUN_SUMMARY, await client.fetchJSON(client.url(path), { method, body: JSON.stringify({ ...body, dryRun: true }), ...withHeaders(headers) }));
|
|
3516
3586
|
function toField(f) {
|
|
@@ -5180,6 +5250,144 @@ ${d.outline}` : "Proposed Content structure.", d);
|
|
|
5180
5250
|
// The whole body: a `test` delivery's outcome rides beside `data`.
|
|
5181
5251
|
async (c, a) => ok("Webhook created. Store the `secret` now: it is never shown again.", await c.fetchJSON(c.url(`/management/webhooks`), { method: "POST", body: JSON.stringify({ name: a.name, url: a.url, events: a.events, isActive: a.isActive, test: a.test }) }))
|
|
5182
5252
|
),
|
|
5253
|
+
def(
|
|
5254
|
+
"list_integrations",
|
|
5255
|
+
"List custom integrations",
|
|
5256
|
+
NEW_TOOL_TEXT.list_integrations,
|
|
5257
|
+
z.object({}).shape,
|
|
5258
|
+
// The whole body: the workspace's `templates` ride beside `data`.
|
|
5259
|
+
async (c) => ok("Integrations.", await c.fetchJSON(c.url(`/management/integrations`), { method: "GET" }))
|
|
5260
|
+
),
|
|
5261
|
+
def(
|
|
5262
|
+
"get_integration",
|
|
5263
|
+
"Get a custom integration",
|
|
5264
|
+
NEW_TOOL_TEXT.get_integration,
|
|
5265
|
+
z.object({ integration: z.string().min(1).describe(INTEGRATION_PARAM_TEXT.integration) }).shape,
|
|
5266
|
+
async (c, a) => ok("Integration.", await data(c, "GET", `/management/integrations/${s(a.integration)}`))
|
|
5267
|
+
),
|
|
5268
|
+
def(
|
|
5269
|
+
"create_integration",
|
|
5270
|
+
"Create a custom integration",
|
|
5271
|
+
NEW_TOOL_TEXT.create_integration,
|
|
5272
|
+
z.object({
|
|
5273
|
+
slug: z.string().min(1).max(48).describe(INTEGRATION_PARAM_TEXT.slug),
|
|
5274
|
+
name: z.string().min(1).max(120).describe("a label, 1-120 chars"),
|
|
5275
|
+
vendor: z.string().max(60).optional().describe("the vendor's name, e.g. 'Greenhouse'"),
|
|
5276
|
+
...integrationShape
|
|
5277
|
+
}).shape,
|
|
5278
|
+
// The whole body: `approval` rides beside `data`.
|
|
5279
|
+
async (c, a) => ok("Integration created.", await c.fetchJSON(c.url(`/management/integrations`), { method: "POST", body: JSON.stringify(a) }))
|
|
5280
|
+
),
|
|
5281
|
+
def(
|
|
5282
|
+
"update_integration",
|
|
5283
|
+
"Update a custom integration",
|
|
5284
|
+
NEW_TOOL_TEXT.update_integration,
|
|
5285
|
+
z.object({
|
|
5286
|
+
integration: z.string().min(1).describe(INTEGRATION_PARAM_TEXT.integration),
|
|
5287
|
+
name: z.string().min(1).max(120).optional(),
|
|
5288
|
+
vendor: z.string().max(60).nullable().optional(),
|
|
5289
|
+
...integrationShapeBare
|
|
5290
|
+
}).shape,
|
|
5291
|
+
async (c, a) => {
|
|
5292
|
+
const { integration, ...body } = a;
|
|
5293
|
+
return ok("Integration updated.", await c.fetchJSON(c.url(`/management/integrations/${s(integration)}`), { method: "PATCH", body: JSON.stringify(body) }));
|
|
5294
|
+
}
|
|
5295
|
+
),
|
|
5296
|
+
def(
|
|
5297
|
+
"delete_integration",
|
|
5298
|
+
"Delete a custom integration",
|
|
5299
|
+
NEW_TOOL_TEXT.delete_integration,
|
|
5300
|
+
z.object({ integration: z.string().min(1).describe(INTEGRATION_PARAM_TEXT.integration) }).shape,
|
|
5301
|
+
async (c, a) => ok("Integration deleted.", await data(c, "DELETE", `/management/integrations/${s(a.integration)}`))
|
|
5302
|
+
),
|
|
5303
|
+
def(
|
|
5304
|
+
"run_integration_sync",
|
|
5305
|
+
"Run an integration's sync",
|
|
5306
|
+
NEW_TOOL_TEXT.run_integration_sync,
|
|
5307
|
+
z.object({
|
|
5308
|
+
integration: z.string().min(1).describe(INTEGRATION_PARAM_TEXT.integration),
|
|
5309
|
+
sync: z.string().min(1).describe(INTEGRATION_PARAM_TEXT.sync),
|
|
5310
|
+
waitSeconds: z.number().min(0).max(50).optional().describe(PARAM_TEXT.waitSeconds)
|
|
5311
|
+
}).shape,
|
|
5312
|
+
async (c, a) => ok("Sync run.", await data(c, "POST", withWait(`/management/integrations/${s(a.integration)}/syncs/${s(a.sync)}/run`, a.waitSeconds)))
|
|
5313
|
+
),
|
|
5314
|
+
def(
|
|
5315
|
+
"run_integration_function",
|
|
5316
|
+
"Run an integration's function",
|
|
5317
|
+
NEW_TOOL_TEXT.run_integration_function,
|
|
5318
|
+
z.object({
|
|
5319
|
+
integration: z.string().min(1).describe(INTEGRATION_PARAM_TEXT.integration),
|
|
5320
|
+
name: z.string().min(1).describe("the function's name"),
|
|
5321
|
+
input: z.unknown().optional().describe("the function's `event` (JSON)"),
|
|
5322
|
+
waitSeconds: z.number().min(0).max(50).optional().describe(PARAM_TEXT.waitSeconds)
|
|
5323
|
+
}).shape,
|
|
5324
|
+
async (c, a) => ok("Function run.", await data(c, "POST", withWait(`/management/integrations/${s(a.integration)}/functions/${s(a.name)}/run`, a.waitSeconds), { input: a.input }))
|
|
5325
|
+
),
|
|
5326
|
+
def(
|
|
5327
|
+
"search_integration_reference",
|
|
5328
|
+
"Search an integration's live reference",
|
|
5329
|
+
NEW_TOOL_TEXT.search_integration_reference,
|
|
5330
|
+
z.object({
|
|
5331
|
+
integration: z.string().min(1).describe(INTEGRATION_PARAM_TEXT.integration),
|
|
5332
|
+
reference: z.string().min(1).describe(INTEGRATION_PARAM_TEXT.reference),
|
|
5333
|
+
query: z.string().max(200).optional().describe("what to search for")
|
|
5334
|
+
}).shape,
|
|
5335
|
+
async (c, a) => ok("Vendor items.", await data(c, "POST", `/management/integrations/${s(a.integration)}/references/${s(a.reference)}/search`, { query: a.query ?? "" }))
|
|
5336
|
+
),
|
|
5337
|
+
def(
|
|
5338
|
+
"start_integration_signin",
|
|
5339
|
+
"Start an integration's vendor sign-in",
|
|
5340
|
+
NEW_TOOL_TEXT.start_integration_signin,
|
|
5341
|
+
z.object({ integration: z.string().min(1).describe(INTEGRATION_PARAM_TEXT.integration) }).shape,
|
|
5342
|
+
async (c, a) => ok("Sign-in URL: give it to the user to open.", await data(c, "POST", `/management/integrations/${s(a.integration)}/oauth/start`))
|
|
5343
|
+
),
|
|
5344
|
+
def(
|
|
5345
|
+
"save_integration_template",
|
|
5346
|
+
"Save an integration as a template",
|
|
5347
|
+
NEW_TOOL_TEXT.save_integration_template,
|
|
5348
|
+
z.object({
|
|
5349
|
+
integration: z.string().min(1).describe(INTEGRATION_PARAM_TEXT.integration),
|
|
5350
|
+
slug: z.string().min(1).max(48).optional().describe(INTEGRATION_PARAM_TEXT.slug),
|
|
5351
|
+
name: z.string().min(1).max(120).optional().describe("a label, 1-120 chars"),
|
|
5352
|
+
description: z.string().max(500).optional().describe("what it connects, for the people installing it")
|
|
5353
|
+
}).shape,
|
|
5354
|
+
async (c, a) => {
|
|
5355
|
+
const { integration, ...body } = a;
|
|
5356
|
+
return ok("Template saved.", await data(c, "POST", `/management/integrations/${s(integration)}/template`, body));
|
|
5357
|
+
}
|
|
5358
|
+
),
|
|
5359
|
+
def(
|
|
5360
|
+
"install_integration_template",
|
|
5361
|
+
"Install an integration template",
|
|
5362
|
+
NEW_TOOL_TEXT.install_integration_template,
|
|
5363
|
+
z.object({
|
|
5364
|
+
template: z.string().min(1).describe(INTEGRATION_PARAM_TEXT.template),
|
|
5365
|
+
slug: z.string().min(1).max(48).optional().describe(INTEGRATION_PARAM_TEXT.slug),
|
|
5366
|
+
name: z.string().min(1).max(120).optional().describe("a label, 1-120 chars")
|
|
5367
|
+
}).shape,
|
|
5368
|
+
// The whole body: `approval`, `secretsNeeded` and `collectionsCreated` ride beside `data`.
|
|
5369
|
+
async (c, a) => {
|
|
5370
|
+
const { template, ...body } = a;
|
|
5371
|
+
return ok("Template installed.", await c.fetchJSON(c.url(`/management/integrations/templates/${s(template)}/install`), { method: "POST", body: JSON.stringify(body) }));
|
|
5372
|
+
}
|
|
5373
|
+
),
|
|
5374
|
+
def(
|
|
5375
|
+
"test_integration_fetch",
|
|
5376
|
+
"Call a vendor through an integration",
|
|
5377
|
+
NEW_TOOL_TEXT.test_integration_fetch,
|
|
5378
|
+
z.object({
|
|
5379
|
+
integration: z.string().min(1).describe(INTEGRATION_PARAM_TEXT.integration),
|
|
5380
|
+
url: z.string().url().describe(INTEGRATION_PARAM_TEXT.url),
|
|
5381
|
+
method: z.enum(["GET", "POST"]).optional().describe("GET when omitted"),
|
|
5382
|
+
headers: z.record(z.string(), z.string()).optional().describe(INTEGRATION_PARAM_TEXT.headers),
|
|
5383
|
+
query: z.record(z.string(), z.string()).optional().describe(INTEGRATION_PARAM_TEXT.query),
|
|
5384
|
+
json: z.unknown().optional().describe(INTEGRATION_PARAM_TEXT.json)
|
|
5385
|
+
}).shape,
|
|
5386
|
+
async (c, a) => {
|
|
5387
|
+
const { integration, ...req } = a;
|
|
5388
|
+
return ok("Vendor response.", await data(c, "POST", `/management/integrations/${s(integration)}/fetch`, req));
|
|
5389
|
+
}
|
|
5390
|
+
),
|
|
5183
5391
|
def(
|
|
5184
5392
|
"list_branches",
|
|
5185
5393
|
"List content branches",
|