callman-mcp 0.1.0 → 0.2.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/CHANGELOG.md +82 -0
- package/README.md +45 -16
- package/dist/client/api.d.ts +64 -3
- package/dist/client/api.d.ts.map +1 -1
- package/dist/client/api.js +67 -2
- package/dist/client/api.js.map +1 -1
- package/dist/client/errors.d.ts.map +1 -1
- package/dist/client/errors.js +33 -7
- package/dist/client/errors.js.map +1 -1
- package/dist/client/types.d.ts +91 -2
- package/dist/client/types.d.ts.map +1 -1
- package/dist/context.d.ts +2 -0
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +7 -2
- package/dist/context.js.map +1 -1
- package/dist/domain/contracts.d.ts +893 -0
- package/dist/domain/contracts.d.ts.map +1 -0
- package/dist/domain/contracts.js +90 -0
- package/dist/domain/contracts.js.map +1 -0
- package/dist/domain/diagram/build.d.ts +520 -18
- package/dist/domain/diagram/build.d.ts.map +1 -1
- package/dist/domain/diagram/build.js +65 -19
- package/dist/domain/diagram/build.js.map +1 -1
- package/dist/domain/diagram/patch.d.ts +624 -51
- package/dist/domain/diagram/patch.d.ts.map +1 -1
- package/dist/domain/diagram/patch.js +180 -40
- package/dist/domain/diagram/patch.js.map +1 -1
- package/dist/domain/diagram/style.d.ts +315 -0
- package/dist/domain/diagram/style.d.ts.map +1 -0
- package/dist/domain/diagram/style.js +124 -0
- package/dist/domain/diagram/style.js.map +1 -0
- package/dist/domain/diagram/summarize.d.ts +8 -0
- package/dist/domain/diagram/summarize.d.ts.map +1 -1
- package/dist/domain/diagram/summarize.js +28 -13
- package/dist/domain/diagram/summarize.js.map +1 -1
- package/dist/domain/requestIntegrations.d.ts +719 -0
- package/dist/domain/requestIntegrations.d.ts.map +1 -0
- package/dist/domain/requestIntegrations.js +222 -0
- package/dist/domain/requestIntegrations.js.map +1 -0
- package/dist/domain/requestShape.d.ts +1350 -152
- package/dist/domain/requestShape.d.ts.map +1 -1
- package/dist/domain/requestShape.js +336 -121
- package/dist/domain/requestShape.js.map +1 -1
- package/dist/domain/resolve.d.ts +2 -1
- package/dist/domain/resolve.d.ts.map +1 -1
- package/dist/domain/resolve.js +5 -1
- package/dist/domain/resolve.js.map +1 -1
- package/dist/domain/scenario/build.d.ts +82 -26
- package/dist/domain/scenario/build.d.ts.map +1 -1
- package/dist/domain/scenario/build.js +196 -65
- package/dist/domain/scenario/build.js.map +1 -1
- package/dist/domain/scenario/nodeConfig.d.ts +11 -0
- package/dist/domain/scenario/nodeConfig.d.ts.map +1 -0
- package/dist/domain/scenario/nodeConfig.js +251 -0
- package/dist/domain/scenario/nodeConfig.js.map +1 -0
- package/dist/domain/scenario/summarize.d.ts +145 -25
- package/dist/domain/scenario/summarize.d.ts.map +1 -1
- package/dist/domain/scenario/summarize.js +84 -29
- package/dist/domain/scenario/summarize.js.map +1 -1
- package/dist/lib/mask.d.ts +0 -18
- package/dist/lib/mask.d.ts.map +1 -1
- package/dist/lib/mask.js +2 -44
- package/dist/lib/mask.js.map +1 -1
- package/dist/lib/pagination.d.ts +3 -2
- package/dist/lib/pagination.d.ts.map +1 -1
- package/dist/lib/pagination.js +13 -8
- package/dist/lib/pagination.js.map +1 -1
- package/dist/lib/redact.d.ts +12 -0
- package/dist/lib/redact.d.ts.map +1 -0
- package/dist/lib/redact.js +50 -0
- package/dist/lib/redact.js.map +1 -0
- package/dist/lib/strict.d.ts +4 -0
- package/dist/lib/strict.d.ts.map +1 -0
- package/dist/lib/strict.js +14 -0
- package/dist/lib/strict.js.map +1 -0
- package/dist/prompts/index.js +7 -7
- package/dist/prompts/index.js.map +1 -1
- package/dist/resources/docs/contracts.d.ts +2 -0
- package/dist/resources/docs/contracts.d.ts.map +1 -0
- package/dist/resources/docs/contracts.js +74 -0
- package/dist/resources/docs/contracts.js.map +1 -0
- package/dist/resources/docs/diagramSchema.d.ts +1 -1
- package/dist/resources/docs/diagramSchema.d.ts.map +1 -1
- package/dist/resources/docs/diagramSchema.js +95 -28
- package/dist/resources/docs/diagramSchema.js.map +1 -1
- package/dist/resources/docs/overview.d.ts +1 -1
- package/dist/resources/docs/overview.d.ts.map +1 -1
- package/dist/resources/docs/overview.js +29 -7
- package/dist/resources/docs/overview.js.map +1 -1
- package/dist/resources/docs/requestSchema.d.ts +1 -1
- package/dist/resources/docs/requestSchema.d.ts.map +1 -1
- package/dist/resources/docs/requestSchema.js +85 -16
- package/dist/resources/docs/requestSchema.js.map +1 -1
- package/dist/resources/generated/aiPacks.d.ts +1 -1
- package/dist/resources/generated/aiPacks.d.ts.map +1 -1
- package/dist/resources/generated/aiPacks.js +3 -2
- package/dist/resources/generated/aiPacks.js.map +1 -1
- package/dist/resources/index.d.ts.map +1 -1
- package/dist/resources/index.js +19 -19
- package/dist/resources/index.js.map +1 -1
- package/dist/run/executeCollection.d.ts +3 -1
- package/dist/run/executeCollection.d.ts.map +1 -1
- package/dist/run/executeCollection.js +16 -4
- package/dist/run/executeCollection.js.map +1 -1
- package/dist/run/summarize.d.ts +17 -6
- package/dist/run/summarize.d.ts.map +1 -1
- package/dist/run/summarize.js +48 -41
- package/dist/run/summarize.js.map +1 -1
- package/dist/run/types.d.ts +1 -0
- package/dist/run/types.d.ts.map +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +1 -1
- package/dist/server.js.map +1 -1
- package/dist/tools/catalog.d.ts +1 -1
- package/dist/tools/catalog.d.ts.map +1 -1
- package/dist/tools/catalog.js +18 -0
- package/dist/tools/catalog.js.map +1 -1
- package/dist/tools/collections.d.ts.map +1 -1
- package/dist/tools/collections.js +53 -41
- package/dist/tools/collections.js.map +1 -1
- package/dist/tools/contracts.d.ts +4 -0
- package/dist/tools/contracts.d.ts.map +1 -0
- package/dist/tools/contracts.js +201 -0
- package/dist/tools/contracts.js.map +1 -0
- package/dist/tools/diagrams.d.ts.map +1 -1
- package/dist/tools/diagrams.js +19 -10
- package/dist/tools/diagrams.js.map +1 -1
- package/dist/tools/environments.d.ts.map +1 -1
- package/dist/tools/environments.js +184 -64
- package/dist/tools/environments.js.map +1 -1
- package/dist/tools/import.d.ts.map +1 -1
- package/dist/tools/import.js +111 -20
- package/dist/tools/import.js.map +1 -1
- package/dist/tools/index.d.ts +2 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +19 -1
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/lookups.d.ts +38 -7
- package/dist/tools/lookups.d.ts.map +1 -1
- package/dist/tools/lookups.js +113 -10
- package/dist/tools/lookups.js.map +1 -1
- package/dist/tools/meta.d.ts.map +1 -1
- package/dist/tools/meta.js +9 -4
- package/dist/tools/meta.js.map +1 -1
- package/dist/tools/requests.d.ts.map +1 -1
- package/dist/tools/requests.js +138 -50
- package/dist/tools/requests.js.map +1 -1
- package/dist/tools/run.d.ts.map +1 -1
- package/dist/tools/run.js +84 -28
- package/dist/tools/run.js.map +1 -1
- package/dist/tools/scenarios.d.ts.map +1 -1
- package/dist/tools/scenarios.js +238 -75
- package/dist/tools/scenarios.js.map +1 -1
- package/dist/tools/shared.d.ts +1 -0
- package/dist/tools/shared.d.ts.map +1 -1
- package/dist/tools/shared.js +9 -1
- package/dist/tools/shared.js.map +1 -1
- package/dist/tools/workspaces.d.ts.map +1 -1
- package/dist/tools/workspaces.js +44 -7
- package/dist/tools/workspaces.js.map +1 -1
- package/dist-cjs/client/api.js +67 -2
- package/dist-cjs/client/errors.js +33 -7
- package/dist-cjs/context.js +7 -2
- package/dist-cjs/domain/contracts.js +93 -0
- package/dist-cjs/domain/diagram/build.js +71 -20
- package/dist-cjs/domain/diagram/patch.js +179 -39
- package/dist-cjs/domain/diagram/style.js +130 -0
- package/dist-cjs/domain/diagram/summarize.js +28 -13
- package/dist-cjs/domain/requestIntegrations.js +228 -0
- package/dist-cjs/domain/requestShape.js +342 -121
- package/dist-cjs/domain/resolve.js +5 -1
- package/dist-cjs/domain/scenario/build.js +197 -65
- package/dist-cjs/domain/scenario/nodeConfig.js +260 -0
- package/dist-cjs/domain/scenario/summarize.js +86 -29
- package/dist-cjs/lib/mask.js +3 -48
- package/dist-cjs/lib/pagination.js +13 -8
- package/dist-cjs/lib/redact.js +53 -0
- package/dist-cjs/lib/strict.js +18 -0
- package/dist-cjs/prompts/index.js +7 -7
- package/dist-cjs/resources/docs/contracts.js +76 -0
- package/dist-cjs/resources/docs/diagramSchema.js +95 -28
- package/dist-cjs/resources/docs/overview.js +29 -7
- package/dist-cjs/resources/docs/requestSchema.js +85 -16
- package/dist-cjs/resources/generated/aiPacks.js +3 -2
- package/dist-cjs/resources/index.js +17 -17
- package/dist-cjs/run/executeCollection.js +16 -4
- package/dist-cjs/run/summarize.js +48 -41
- package/dist-cjs/server.js +1 -1
- package/dist-cjs/tools/catalog.js +18 -0
- package/dist-cjs/tools/collections.js +52 -40
- package/dist-cjs/tools/contracts.js +204 -0
- package/dist-cjs/tools/diagrams.js +19 -10
- package/dist-cjs/tools/environments.js +182 -62
- package/dist-cjs/tools/import.js +107 -16
- package/dist-cjs/tools/index.js +21 -2
- package/dist-cjs/tools/lookups.js +123 -11
- package/dist-cjs/tools/meta.js +9 -4
- package/dist-cjs/tools/requests.js +134 -46
- package/dist-cjs/tools/run.js +82 -26
- package/dist-cjs/tools/scenarios.js +235 -72
- package/dist-cjs/tools/shared.js +11 -2
- package/dist-cjs/tools/workspaces.js +43 -6
- package/package.json +2 -2
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.requestSummaryView = exports.compactRequestView = exports.toUpdateRequestPayload = exports.updateRequestInputSchema = exports.toFlatImportRequest = exports.toCreateRequestPayload = exports.
|
|
3
|
+
exports.requestSummaryView = exports.compactRequestView = exports.bodyInputView = exports.toUpdateRequestPayload = exports.updateRequestInputSchema = exports.toFlatImportRequest = exports.toCreateRequestPayload = exports.resolveMaskedValues = exports.authInputView = exports.toAuthPayload = exports.sanitizedKeyWarnings = exports.toBodyPayload = exports.syncUrlAndQuery = exports.buildUrlWithQueryRows = exports.toRows = exports.requestInputSchema = exports.authInputSchema = exports.bodyInputSchema = exports.pathVariableSchema = exports.kvSchema = exports.HTTP_METHODS = void 0;
|
|
4
4
|
const callman_core_1 = require("callman-core");
|
|
5
5
|
const zod_1 = require("zod");
|
|
6
|
+
const errors_js_1 = require("../client/errors.js");
|
|
6
7
|
const mask_js_1 = require("../lib/mask.js");
|
|
8
|
+
const strict_js_1 = require("../lib/strict.js");
|
|
7
9
|
const truncate_js_1 = require("../lib/truncate.js");
|
|
10
|
+
const requestIntegrations_js_1 = require("./requestIntegrations.js");
|
|
8
11
|
// The COMPACT request form a model writes (name/method/url, key-value lists,
|
|
9
12
|
// a body that may be a JSON value, a string or a mode object, a small auth
|
|
10
13
|
// object) and its translation into the backend's `POST /requests` payload —
|
|
@@ -12,76 +15,205 @@ const truncate_js_1 = require("../lib/truncate.js");
|
|
|
12
15
|
// serialisation (`toPersistedRequestBody`) so an imported request opens in
|
|
13
16
|
// the editor exactly like a hand-made one.
|
|
14
17
|
exports.HTTP_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS", "TRACE"];
|
|
15
|
-
|
|
16
|
-
|
|
18
|
+
// Key/value rows — the backend's own limits (key 1–100 chars, value ≤ 5000),
|
|
19
|
+
// strict so a stray `description` or `type` is an error, not a silent drop.
|
|
20
|
+
exports.kvSchema = (0, strict_js_1.strictObject)({
|
|
21
|
+
key: zod_1.z.string().trim().min(1).max(100),
|
|
17
22
|
value: zod_1.z.string().max(5000).default(""),
|
|
18
|
-
enabled: zod_1.z.boolean().optional(),
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
zod_1.z.
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
zod_1.z.
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
])
|
|
23
|
+
enabled: zod_1.z.boolean().optional().describe("false keeps the row but does not send it (default true)"),
|
|
24
|
+
}, "row field");
|
|
25
|
+
exports.pathVariableSchema = (0, strict_js_1.strictObject)({
|
|
26
|
+
key: zod_1.z.string().trim().min(1).max(100).describe("The name after ':' in the URL, without the colon"),
|
|
27
|
+
value: zod_1.z.string().max(5000).default(""),
|
|
28
|
+
description: zod_1.z.string().max(5000).optional(),
|
|
29
|
+
}, "path variable field");
|
|
30
|
+
const RAW_LANGUAGES = ["json", "xml", "text", "html"];
|
|
31
|
+
const rawBodySchema = (0, strict_js_1.strictObject)({
|
|
32
|
+
mode: zod_1.z.literal("raw"),
|
|
33
|
+
raw: zod_1.z.string().max(2_000_000).describe("The body text; {{variables}} are resolved when it runs"),
|
|
34
|
+
language: zod_1.z.enum(RAW_LANGUAGES).optional().describe("Editor language and default Content-Type; sniffed from the text when omitted"),
|
|
35
|
+
rawLanguage: zod_1.z.enum(RAW_LANGUAGES).optional().describe("Same as language (the stored name)"),
|
|
36
|
+
}, "raw body field");
|
|
37
|
+
const formBodySchema = (0, strict_js_1.strictObject)({
|
|
38
|
+
mode: zod_1.z.enum(["formdata", "urlencoded"]),
|
|
39
|
+
entries: zod_1.z.array(exports.kvSchema).max(200).optional().describe("Text fields; file parts cannot be set through the API"),
|
|
40
|
+
formEntries: zod_1.z.array(zod_1.z.object({ key: zod_1.z.string(), value: zod_1.z.string().default(""), enabled: zod_1.z.boolean().optional() }).passthrough()).max(200).optional().describe("Same as entries (the stored name)"),
|
|
41
|
+
}, "form body field");
|
|
42
|
+
const jsonBodySchema = (0, strict_js_1.strictObject)({ mode: zod_1.z.literal("json"), json: zod_1.z.unknown().describe("Any JSON value — use this form when the payload itself has a top-level `mode` key") }, "json body field");
|
|
43
|
+
const noneBodySchema = (0, strict_js_1.strictObject)({ mode: zod_1.z.literal("none") }, "body field");
|
|
44
|
+
const BODY_MODES = ["raw", "formdata", "urlencoded", "json", "none"];
|
|
45
|
+
exports.bodyInputSchema = zod_1.z
|
|
46
|
+
.union([
|
|
47
|
+
zod_1.z.string().max(2_000_000),
|
|
48
|
+
rawBodySchema,
|
|
49
|
+
formBodySchema,
|
|
50
|
+
jsonBodySchema,
|
|
51
|
+
noneBodySchema,
|
|
52
|
+
zod_1.z.array(zod_1.z.unknown()),
|
|
53
|
+
zod_1.z.number(),
|
|
54
|
+
zod_1.z.boolean(),
|
|
55
|
+
zod_1.z.record(zod_1.z.unknown()).refine((value) => !("mode" in value), { message: `A body object with a "mode" key must be one of the modes ${BODY_MODES.join(", ")}` }),
|
|
56
|
+
], {
|
|
57
|
+
errorMap: (issue, ctx) => issue.code === zod_1.z.ZodIssueCode.invalid_union
|
|
58
|
+
? {
|
|
59
|
+
message: `Invalid body. Send a JSON value (object/array), a string, or { mode: "raw", raw, language? } | { mode: "formdata"|"urlencoded", entries: [{ key, value }] } | { mode: "json", json } | { mode: "none" }.`,
|
|
60
|
+
}
|
|
61
|
+
: { message: ctx.defaultError },
|
|
62
|
+
})
|
|
63
|
+
.describe('A JSON object/array (sent as JSON); a string (JSON is parsed, <xml>/<html> sniffed, otherwise text); { mode: "raw", raw, language: json|xml|text|html }; { mode: "formdata"|"urlencoded", entries: [{ key, value }] }; { mode: "json", json } when the payload itself has a top-level "mode" key; { mode: "none" }.');
|
|
64
|
+
const secret = (what) => zod_1.z.string().max(10_000).describe(`${what}. {{variable}} references are fine`);
|
|
34
65
|
exports.authInputSchema = zod_1.z.discriminatedUnion("type", [
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
66
|
+
(0, strict_js_1.strictObject)({ type: zod_1.z.literal("none") }, "auth field"),
|
|
67
|
+
(0, strict_js_1.strictObject)({ type: zod_1.z.literal("bearer"), token: secret("Bearer token") }, "bearer auth field"),
|
|
68
|
+
(0, strict_js_1.strictObject)({ type: zod_1.z.literal("basic"), username: zod_1.z.string().max(5000), password: zod_1.z.string().max(5000).default("") }, "basic auth field"),
|
|
69
|
+
(0, strict_js_1.strictObject)({
|
|
39
70
|
type: zod_1.z.literal("apiKey"),
|
|
40
|
-
key: zod_1.z.string().max(5000),
|
|
41
|
-
value:
|
|
71
|
+
key: zod_1.z.string().max(5000).describe("Header or query parameter name, e.g. X-API-Key"),
|
|
72
|
+
value: secret("API key"),
|
|
42
73
|
location: zod_1.z.enum(["header", "query"]).default("header"),
|
|
43
|
-
}),
|
|
44
|
-
|
|
74
|
+
}, "apiKey auth field"),
|
|
75
|
+
(0, strict_js_1.strictObject)({
|
|
45
76
|
type: zod_1.z.literal("oauth2"),
|
|
46
77
|
grantType: zod_1.z.enum(["client_credentials", "password", "refresh_token"]).default("client_credentials"),
|
|
47
78
|
tokenUrl: zod_1.z.string().max(4096),
|
|
48
79
|
clientId: zod_1.z.string().max(5000).default(""),
|
|
49
80
|
clientSecret: zod_1.z.string().max(10_000).default(""),
|
|
50
81
|
scope: zod_1.z.string().max(5000).default(""),
|
|
51
|
-
username: zod_1.z.string().max(5000).default(""),
|
|
52
|
-
password: zod_1.z.string().max(5000).default(""),
|
|
53
|
-
refreshToken: zod_1.z.string().max(10_000).default(""),
|
|
54
|
-
clientAuth: zod_1.z.enum(["basic", "body"]).default("body"),
|
|
82
|
+
username: zod_1.z.string().max(5000).default("").describe("password grant"),
|
|
83
|
+
password: zod_1.z.string().max(5000).default("").describe("password grant"),
|
|
84
|
+
refreshToken: zod_1.z.string().max(10_000).default("").describe("refresh_token grant"),
|
|
85
|
+
clientAuth: zod_1.z.enum(["basic", "body"]).default("body").describe("Send client credentials as a Basic header or in the form body"),
|
|
55
86
|
audience: zod_1.z.string().max(4096).default(""),
|
|
56
|
-
}),
|
|
87
|
+
}, "oauth2 auth field"),
|
|
57
88
|
]);
|
|
58
|
-
exports.requestInputSchema =
|
|
59
|
-
name: zod_1.z.string().min(1).max(truncate_js_1.LIMITS.NAME).describe("Display name, e.g. \"GET /users\" or \"Login\""),
|
|
89
|
+
exports.requestInputSchema = (0, strict_js_1.strictObject)({
|
|
90
|
+
name: zod_1.z.string().trim().min(1).max(truncate_js_1.LIMITS.NAME).describe("Display name, e.g. \"GET /users\" or \"Login\""),
|
|
60
91
|
method: zod_1.z.enum(exports.HTTP_METHODS),
|
|
61
92
|
url: zod_1.z
|
|
62
93
|
.string()
|
|
94
|
+
.trim()
|
|
63
95
|
.min(1)
|
|
64
96
|
.max(4096)
|
|
65
|
-
.describe("Full URL; use {{variable}} for hosts/tokens (e.g. {{baseUrl}}/users/:id) and :name for path variables"),
|
|
97
|
+
.describe("Full URL; use {{variable}} for hosts/tokens (e.g. {{baseUrl}}/users/:id) and :name for path variables. A ?query in the URL becomes `query` rows (they are the same thing — runs send the rows)"),
|
|
66
98
|
headers: zod_1.z.array(exports.kvSchema).max(200).optional(),
|
|
67
|
-
query: zod_1.z.array(exports.kvSchema).max(200).optional(),
|
|
68
|
-
pathVariables: zod_1.z.array(exports.
|
|
69
|
-
body: exports.bodyInputSchema
|
|
70
|
-
.optional()
|
|
71
|
-
.describe("A JSON value (stored as JSON), a string (JSON is parsed, otherwise raw text/xml/html by sniffing), or { mode: \"raw\" | \"formdata\" | \"urlencoded\" | \"none\", … }"),
|
|
99
|
+
query: zod_1.z.array(exports.kvSchema).max(200).optional().describe("Query parameters; when omitted they are taken from the URL's ?query"),
|
|
100
|
+
pathVariables: zod_1.z.array(exports.pathVariableSchema).max(200).optional().describe("Values for :name segments in the URL"),
|
|
101
|
+
body: exports.bodyInputSchema.optional(),
|
|
72
102
|
auth: exports.authInputSchema.optional(),
|
|
73
|
-
preRequestScript: zod_1.z.string().max(100_000).optional(),
|
|
74
|
-
postResponseScript: zod_1.z.string().max(100_000).optional().describe("pm.* script run after the response (
|
|
75
|
-
testsScript: zod_1.z.string().max(100_000).optional(),
|
|
76
|
-
folder: zod_1.z.string().max(
|
|
77
|
-
folderKey: zod_1.z.string().max(120).optional().describe("
|
|
78
|
-
isEnabledInRunner: zod_1.z.boolean().optional(),
|
|
79
|
-
|
|
103
|
+
preRequestScript: zod_1.z.string().max(100_000).optional().describe("pm.* script run before the request (callman://docs/scripting/pm-api)"),
|
|
104
|
+
postResponseScript: zod_1.z.string().max(100_000).optional().describe("pm.* script run after the response (pm.test, pm.environment.set …)"),
|
|
105
|
+
testsScript: zod_1.z.string().max(100_000).optional().describe("pm.test(...) assertions run after the response"),
|
|
106
|
+
folder: zod_1.z.string().max(300).optional().describe("Folder id, name or path (\"Auth/Login\") inside the collection"),
|
|
107
|
+
folderKey: zod_1.z.string().max(120).optional().describe("create_requests_bulk with collectionName only: key of a folder declared in `folders`"),
|
|
108
|
+
isEnabledInRunner: zod_1.z.boolean().optional().describe("false = skipped by collection runs (run_collection, the desktop runner, the CLI); default true"),
|
|
109
|
+
...requestIntegrations_js_1.requestIntegrationFields,
|
|
110
|
+
}, "request field");
|
|
80
111
|
const toRows = (entries) => (entries ?? [])
|
|
81
112
|
.filter((entry) => entry.key.trim().length > 0)
|
|
82
|
-
.map((entry) => ({ key: entry.key.trim(), value: entry.value ?? "", enabled: entry.enabled ?? true }))
|
|
83
|
-
.slice(0, 200);
|
|
113
|
+
.map((entry) => ({ key: entry.key.trim(), value: entry.value ?? "", enabled: entry.enabled ?? true }));
|
|
84
114
|
exports.toRows = toRows;
|
|
115
|
+
const toPathVariables = (entries) => entries.map((entry) => ({ key: entry.key.trim().replace(/^:/, ""), value: entry.value ?? "", description: entry.description ?? "" }));
|
|
116
|
+
// ── URL ⇄ query rows ───────────────────────────────────────────────────
|
|
117
|
+
// The desktop keeps the URL's ?query and the query rows in sync
|
|
118
|
+
// (request-editor/lib/urlSync.ts), and every runner sends the ROWS — the run
|
|
119
|
+
// bundle strips the URL query. So a query typed into `url` becomes rows, and
|
|
120
|
+
// the stored URL mirrors the enabled rows exactly like the editor does.
|
|
121
|
+
const splitHash = (url) => {
|
|
122
|
+
const index = url.indexOf("#");
|
|
123
|
+
return index === -1 ? { withoutHash: url, hash: "" } : { withoutHash: url.slice(0, index), hash: url.slice(index) };
|
|
124
|
+
};
|
|
125
|
+
const buildUrlWithQueryRows = (url, rows) => {
|
|
126
|
+
const { withoutHash, hash } = splitHash(url);
|
|
127
|
+
const base = (0, callman_core_1.stripUrlQuery)(withoutHash);
|
|
128
|
+
const enabled = rows.filter((row) => row.enabled !== false && row.key.trim());
|
|
129
|
+
return enabled.length === 0 ? `${base}${hash}` : `${base}?${enabled.map((row) => `${row.key}=${row.value}`).join("&")}${hash}`;
|
|
130
|
+
};
|
|
131
|
+
exports.buildUrlWithQueryRows = buildUrlWithQueryRows;
|
|
132
|
+
const syncUrlAndQuery = (url, query) => {
|
|
133
|
+
const fromUrl = (0, callman_core_1.extractUrlQueryPairs)(url).map((pair) => ({ key: pair.key, value: pair.value, enabled: true }));
|
|
134
|
+
if (query === undefined)
|
|
135
|
+
return { url: (0, exports.buildUrlWithQueryRows)(url, fromUrl), query: fromUrl, warnings: [] };
|
|
136
|
+
const rows = (0, exports.toRows)(query);
|
|
137
|
+
const dropped = fromUrl.filter((pair) => !rows.some((row) => row.key === pair.key));
|
|
138
|
+
return {
|
|
139
|
+
url: (0, exports.buildUrlWithQueryRows)(url, rows),
|
|
140
|
+
query: rows,
|
|
141
|
+
warnings: dropped.length > 0 ? [`The URL's query parameter(s) ${dropped.map((pair) => pair.key).join(", ")} were replaced by the \`query\` rows you passed — add them to \`query\` to keep them.`] : [],
|
|
142
|
+
};
|
|
143
|
+
};
|
|
144
|
+
exports.syncUrlAndQuery = syncUrlAndQuery;
|
|
145
|
+
// ── body ───────────────────────────────────────────────────────────────
|
|
146
|
+
const isModeObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value) && typeof value.mode === "string";
|
|
147
|
+
// Persisted body — the exact rules of the desktop editor's serializeBodyState
|
|
148
|
+
// (guarded in the desktop by persistedBody.drift.test.ts): JSON stays a bare
|
|
149
|
+
// JSON value; raw xml/text/html persists as { mode, raw, rawLanguage };
|
|
150
|
+
// form bodies keep their entries; empty → null.
|
|
151
|
+
const toBodyPayload = (body, headers) => {
|
|
152
|
+
if (body === undefined || body === null)
|
|
153
|
+
return null;
|
|
154
|
+
if (typeof body === "string") {
|
|
155
|
+
if (isClipped(body))
|
|
156
|
+
throw clippedError("body");
|
|
157
|
+
return (0, callman_core_1.toPersistedRequestBody)((0, callman_core_1.inferBodyStateFromRaw)(body, headers));
|
|
158
|
+
}
|
|
159
|
+
if (isModeObject(body)) {
|
|
160
|
+
const record = body;
|
|
161
|
+
if (record.mode === "none")
|
|
162
|
+
return null;
|
|
163
|
+
if (record.mode === "json")
|
|
164
|
+
return (record.json ?? null);
|
|
165
|
+
if (record.mode === "raw") {
|
|
166
|
+
const raw = typeof record.raw === "string" ? record.raw : "";
|
|
167
|
+
if (isClipped(raw))
|
|
168
|
+
throw clippedError("body.raw");
|
|
169
|
+
const language = (record.language ?? record.rawLanguage);
|
|
170
|
+
if (language)
|
|
171
|
+
return (0, callman_core_1.toPersistedRequestBody)({ mode: "raw", raw, rawLanguage: language, formEntries: [] });
|
|
172
|
+
return (0, callman_core_1.toPersistedRequestBody)((0, callman_core_1.inferBodyStateFromRaw)(raw, headers));
|
|
173
|
+
}
|
|
174
|
+
if (record.mode === "formdata" || record.mode === "urlencoded") {
|
|
175
|
+
const persisted = Array.isArray(record.formEntries) ? record.formEntries : null;
|
|
176
|
+
if (persisted?.some((entry) => entry.type === "file")) {
|
|
177
|
+
throw new errors_js_1.ToolInputError("FORM_FILE_UNSUPPORTED", "File parts of a form body cannot be set through the API — keep them in the desktop app, or send text fields only.");
|
|
178
|
+
}
|
|
179
|
+
const entries = persisted
|
|
180
|
+
? persisted.map((entry) => ({ key: String(entry.key ?? ""), value: String(entry.value ?? ""), enabled: entry.enabled !== false }))
|
|
181
|
+
: (record.entries ?? []);
|
|
182
|
+
return (0, callman_core_1.toPersistedRequestBody)({ mode: record.mode, raw: "", formEntries: (0, exports.toRows)(entries) });
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
// Any other JSON value is stored as-is (the editor shows it on the JSON tab).
|
|
186
|
+
return body;
|
|
187
|
+
};
|
|
188
|
+
exports.toBodyPayload = toBodyPayload;
|
|
189
|
+
// Previews end in "…" (lib/truncate) — writing one back would store the cut.
|
|
190
|
+
const isClipped = (text) => text.endsWith("…") && text.length >= truncate_js_1.LIMITS.BODY_PREVIEW;
|
|
191
|
+
const clippedError = (field) => new errors_js_1.ToolInputError("CLIPPED_VALUE", `${field} looks like a clipped preview (ends with "…"). Read it with get_request full: true, or pass the complete value.`);
|
|
192
|
+
// The backend (express-mongo-sanitize) rewrites JSON keys that start with "$"
|
|
193
|
+
// or contain "." on ordinary writes — { "$schema": … } is stored as "_schema".
|
|
194
|
+
const sanitizedKeyWarnings = (body) => {
|
|
195
|
+
const found = new Set();
|
|
196
|
+
const walk = (value, depth) => {
|
|
197
|
+
if (depth > 20 || found.size >= 10 || value === null || typeof value !== "object")
|
|
198
|
+
return;
|
|
199
|
+
if (Array.isArray(value)) {
|
|
200
|
+
for (const item of value)
|
|
201
|
+
walk(item, depth + 1);
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
for (const [key, child] of Object.entries(value)) {
|
|
205
|
+
if (key.startsWith("$") || key.includes("."))
|
|
206
|
+
found.add(key);
|
|
207
|
+
walk(child, depth + 1);
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
walk(body, 0);
|
|
211
|
+
return found.size > 0
|
|
212
|
+
? [`The server rewrites JSON keys that start with "$" or contain "." (${[...found].join(", ")} → "_"). Keep such payloads as a raw string body ({ mode: "raw", raw: "…", language: "json" }).`]
|
|
213
|
+
: [];
|
|
214
|
+
};
|
|
215
|
+
exports.sanitizedKeyWarnings = sanitizedKeyWarnings;
|
|
216
|
+
// ── auth ───────────────────────────────────────────────────────────────
|
|
85
217
|
const EMPTY_AUTH = {
|
|
86
218
|
type: "none",
|
|
87
219
|
bearerToken: "",
|
|
@@ -110,89 +242,145 @@ const toAuthPayload = (auth) => {
|
|
|
110
242
|
}
|
|
111
243
|
};
|
|
112
244
|
exports.toAuthPayload = toAuthPayload;
|
|
113
|
-
|
|
114
|
-
//
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
245
|
+
// Stored auth → the SAME shape authInputSchema accepts, so a read can be
|
|
246
|
+
// written straight back. Secrets are masked unless `reveal`.
|
|
247
|
+
const authInputView = (auth, reveal = false) => {
|
|
248
|
+
const hide = (value) => (value ? (reveal ? value : (0, mask_js_1.maskSecret)(value)) : "");
|
|
249
|
+
switch (auth?.type) {
|
|
250
|
+
case "bearer":
|
|
251
|
+
return { type: "bearer", token: hide(auth.bearerToken) };
|
|
252
|
+
case "basic":
|
|
253
|
+
return { type: "basic", username: auth.basicUsername ?? "", password: hide(auth.basicPassword) };
|
|
254
|
+
case "apikey":
|
|
255
|
+
return { type: "apiKey", key: auth.apiKeyKey ?? "", value: hide(auth.apiKeyValue), location: auth.apiKeyLocation ?? "header" };
|
|
256
|
+
case "oauth2": {
|
|
257
|
+
const oauth2 = (auth.oauth2 ?? {});
|
|
258
|
+
return {
|
|
259
|
+
type: "oauth2",
|
|
260
|
+
grantType: oauth2.grantType ?? "client_credentials",
|
|
261
|
+
tokenUrl: oauth2.tokenUrl ?? "",
|
|
262
|
+
clientId: oauth2.clientId ?? "",
|
|
263
|
+
clientSecret: hide(oauth2.clientSecret),
|
|
264
|
+
scope: oauth2.scope ?? "",
|
|
265
|
+
username: oauth2.username ?? "",
|
|
266
|
+
password: hide(oauth2.password),
|
|
267
|
+
refreshToken: hide(oauth2.refreshToken),
|
|
268
|
+
clientAuth: oauth2.clientAuth ?? "body",
|
|
269
|
+
audience: oauth2.audience ?? "",
|
|
270
|
+
};
|
|
135
271
|
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
272
|
+
default:
|
|
273
|
+
return { type: "none" };
|
|
274
|
+
}
|
|
275
|
+
};
|
|
276
|
+
exports.authInputView = authInputView;
|
|
277
|
+
// ── masked values ──────────────────────────────────────────────────────
|
|
278
|
+
// get_request shows secrets as ••••ab. Writing that back would store the
|
|
279
|
+
// dots as the credential. On update a masked value that matches the stored
|
|
280
|
+
// secret's mask means "keep the stored value"; anything else masked is refused.
|
|
281
|
+
const resolveMaskedValues = (item, current) => {
|
|
282
|
+
const problems = [];
|
|
283
|
+
const restoreRows = (field, rows) => rows?.map((row) => {
|
|
284
|
+
if (!(0, mask_js_1.isMasked)(row.value))
|
|
285
|
+
return row;
|
|
286
|
+
const stored = current?.[field]?.find((entry) => entry.key.toLowerCase() === row.key.toLowerCase());
|
|
287
|
+
if (stored && field === "headers" && (0, mask_js_1.maskHeaderValue)(stored.key, stored.value) === row.value)
|
|
288
|
+
return { ...row, value: stored.value };
|
|
289
|
+
problems.push(`${field}.${row.key}`);
|
|
290
|
+
return row;
|
|
291
|
+
});
|
|
292
|
+
const out = { ...item, headers: restoreRows("headers", item.headers), query: restoreRows("query", item.query) };
|
|
293
|
+
if (item.headers === undefined)
|
|
294
|
+
delete out.headers;
|
|
295
|
+
if (item.query === undefined)
|
|
296
|
+
delete out.query;
|
|
297
|
+
for (const entry of item.pathVariables ?? [])
|
|
298
|
+
if ((0, mask_js_1.isMasked)(entry.value))
|
|
299
|
+
problems.push(`pathVariables.${entry.key}`);
|
|
300
|
+
if (item.auth) {
|
|
301
|
+
const storedView = (0, exports.authInputView)(current?.auth, true);
|
|
302
|
+
const auth = { ...item.auth };
|
|
303
|
+
for (const [key, value] of Object.entries(auth)) {
|
|
304
|
+
if (!(0, mask_js_1.isMasked)(value))
|
|
305
|
+
continue;
|
|
306
|
+
const stored = storedView.type === auth.type ? storedView[key] : undefined;
|
|
307
|
+
if (typeof stored === "string" && stored && (0, mask_js_1.maskSecret)(stored) === value)
|
|
308
|
+
auth[key] = stored;
|
|
309
|
+
else
|
|
310
|
+
problems.push(`auth.${key}`);
|
|
139
311
|
}
|
|
312
|
+
out.auth = auth;
|
|
140
313
|
}
|
|
141
|
-
|
|
142
|
-
|
|
314
|
+
if (problems.length > 0) {
|
|
315
|
+
throw new errors_js_1.ToolInputError("MASKED_VALUE", `Masked values (••••) cannot be saved: ${problems.join(", ")}. Pass the real value or a {{variable}}, or leave the field out to keep what is stored (get_request reveal: true shows it).`, { fields: problems });
|
|
316
|
+
}
|
|
317
|
+
return out;
|
|
143
318
|
};
|
|
144
|
-
exports.
|
|
145
|
-
const
|
|
319
|
+
exports.resolveMaskedValues = resolveMaskedValues;
|
|
320
|
+
const noConnections = (_ref, _type, where) => {
|
|
321
|
+
throw new errors_js_1.ToolInputError("CONNECTIONS_UNAVAILABLE", `${where}: connections were not loaded for this call.`);
|
|
322
|
+
};
|
|
323
|
+
const toCreateRequestPayload = (item, target, resolve = noConnections) => {
|
|
146
324
|
const headers = (0, exports.toRows)(item.headers);
|
|
325
|
+
const { url, query, warnings } = (0, exports.syncUrlAndQuery)(item.url.trim(), item.query);
|
|
326
|
+
const body = (0, exports.toBodyPayload)(item.body, headers);
|
|
147
327
|
return {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
.
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
328
|
+
payload: {
|
|
329
|
+
name: item.name.trim().slice(0, truncate_js_1.LIMITS.NAME),
|
|
330
|
+
method: item.method,
|
|
331
|
+
url,
|
|
332
|
+
headers,
|
|
333
|
+
query,
|
|
334
|
+
pathVariables: toPathVariables(item.pathVariables ?? []),
|
|
335
|
+
body,
|
|
336
|
+
auth: (0, exports.toAuthPayload)(item.auth),
|
|
337
|
+
preRequestScript: item.preRequestScript ?? "",
|
|
338
|
+
postResponseScript: item.postResponseScript ?? "",
|
|
339
|
+
testsScript: item.testsScript ?? "",
|
|
340
|
+
...((0, requestIntegrations_js_1.hasIntegrations)(item) ? (0, requestIntegrations_js_1.toIntegrationPayload)(item, resolve) : {}),
|
|
341
|
+
collectionId: target.collectionId,
|
|
342
|
+
folderId: target.folderId,
|
|
343
|
+
},
|
|
344
|
+
warnings: [...warnings, ...(0, exports.sanitizedKeyWarnings)(body)],
|
|
163
345
|
};
|
|
164
346
|
};
|
|
165
347
|
exports.toCreateRequestPayload = toCreateRequestPayload;
|
|
166
348
|
// `format: "requests"` bulk import row — same document minus the ids the
|
|
167
|
-
// server assigns, plus the payload-local folderKey.
|
|
168
|
-
|
|
169
|
-
|
|
349
|
+
// server assigns, plus the payload-local folderKey. The import route is not
|
|
350
|
+
// key-sanitized, so no "$" warning here.
|
|
351
|
+
const toFlatImportRequest = (item, resolve = noConnections) => {
|
|
352
|
+
const { collectionId: _c, folderId: _f, ...payload } = (0, exports.toCreateRequestPayload)(item, { collectionId: "", folderId: null }, resolve).payload;
|
|
170
353
|
return { ...payload, ...(item.folderKey ? { folderKey: item.folderKey } : {}) };
|
|
171
354
|
};
|
|
172
355
|
exports.toFlatImportRequest = toFlatImportRequest;
|
|
173
|
-
exports.updateRequestInputSchema =
|
|
174
|
-
.
|
|
175
|
-
.
|
|
176
|
-
|
|
177
|
-
|
|
356
|
+
exports.updateRequestInputSchema = (0, strict_js_1.strictObject)({
|
|
357
|
+
...Object.fromEntries(Object.entries(exports.requestInputSchema.shape).filter(([key]) => key !== "folderKey").map(([key, schema]) => [key, schema.optional()])),
|
|
358
|
+
collection: zod_1.z.string().max(200).optional().describe("Narrows a request NAME lookup to one collection (it does not move the request — use move_requests)"),
|
|
359
|
+
}, "request field");
|
|
360
|
+
// Only the fields passed change. isEnabledInRunner is NOT part of the PATCH
|
|
361
|
+
// (the backend's update schema strips it) — the caller sends it to the
|
|
362
|
+
// run-toggle endpoint.
|
|
363
|
+
const toUpdateRequestPayload = (item, current, target, resolve = noConnections) => {
|
|
178
364
|
const out = {};
|
|
365
|
+
const warnings = [];
|
|
179
366
|
if (item.name !== undefined)
|
|
180
367
|
out.name = item.name.trim().slice(0, truncate_js_1.LIMITS.NAME);
|
|
181
368
|
if (item.method !== undefined)
|
|
182
369
|
out.method = item.method;
|
|
183
|
-
if (item.url !== undefined)
|
|
184
|
-
|
|
370
|
+
if (item.url !== undefined || item.query !== undefined) {
|
|
371
|
+
const synced = (0, exports.syncUrlAndQuery)((item.url ?? current.url).trim(), item.query ?? (item.url !== undefined ? undefined : current.query ?? []));
|
|
372
|
+
out.url = synced.url;
|
|
373
|
+
out.query = synced.query;
|
|
374
|
+
warnings.push(...synced.warnings);
|
|
375
|
+
}
|
|
185
376
|
if (item.headers !== undefined)
|
|
186
377
|
out.headers = (0, exports.toRows)(item.headers);
|
|
187
|
-
if (item.
|
|
188
|
-
out.
|
|
189
|
-
if (item.
|
|
190
|
-
out.
|
|
191
|
-
|
|
192
|
-
.map((entry) => ({ key: entry.key.trim(), value: entry.value ?? "", description: entry.description ?? "" }));
|
|
378
|
+
if (item.pathVariables !== undefined)
|
|
379
|
+
out.pathVariables = toPathVariables(item.pathVariables);
|
|
380
|
+
if (item.body !== undefined) {
|
|
381
|
+
out.body = (0, exports.toBodyPayload)(item.body, item.headers !== undefined ? (0, exports.toRows)(item.headers) : (current.headers ?? []));
|
|
382
|
+
warnings.push(...(0, exports.sanitizedKeyWarnings)(out.body));
|
|
193
383
|
}
|
|
194
|
-
if (item.body !== undefined)
|
|
195
|
-
out.body = (0, exports.toBodyPayload)(item.body, (0, exports.toRows)(item.headers));
|
|
196
384
|
if (item.auth !== undefined)
|
|
197
385
|
out.auth = (0, exports.toAuthPayload)(item.auth);
|
|
198
386
|
if (item.preRequestScript !== undefined)
|
|
@@ -201,13 +389,11 @@ const toUpdateRequestPayload = (item, target) => {
|
|
|
201
389
|
out.postResponseScript = item.postResponseScript;
|
|
202
390
|
if (item.testsScript !== undefined)
|
|
203
391
|
out.testsScript = item.testsScript;
|
|
204
|
-
if (
|
|
205
|
-
out.
|
|
206
|
-
if (target.collectionId !== undefined)
|
|
207
|
-
out.collectionId = target.collectionId;
|
|
392
|
+
if ((0, requestIntegrations_js_1.hasIntegrations)(item))
|
|
393
|
+
Object.assign(out, (0, requestIntegrations_js_1.toIntegrationPayload)(item, resolve, current));
|
|
208
394
|
if (target.folderId !== undefined)
|
|
209
395
|
out.folderId = target.folderId;
|
|
210
|
-
return out;
|
|
396
|
+
return { payload: out, warnings };
|
|
211
397
|
};
|
|
212
398
|
exports.toUpdateRequestPayload = toUpdateRequestPayload;
|
|
213
399
|
// ── outbound views ─────────────────────────────────────────────────────
|
|
@@ -216,9 +402,36 @@ const kvView = (rows, maskHeaders) => (rows ?? []).map((row) => ({
|
|
|
216
402
|
value: maskHeaders ? (0, mask_js_1.maskHeaderValue)(row.key, row.value) : row.value,
|
|
217
403
|
...(row.enabled === false ? { enabled: false } : {}),
|
|
218
404
|
}));
|
|
405
|
+
// Stored body → the input shape (a bare JSON value stays bare unless it has
|
|
406
|
+
// a top-level "mode", which would read as a mode object).
|
|
407
|
+
const bodyInputView = (body) => {
|
|
408
|
+
if (body === null || body === undefined)
|
|
409
|
+
return null;
|
|
410
|
+
if (isModeObject(body)) {
|
|
411
|
+
const record = body;
|
|
412
|
+
if (record.mode === "raw" && typeof record.raw === "string")
|
|
413
|
+
return { mode: "raw", raw: record.raw, language: record.rawLanguage ?? "text" };
|
|
414
|
+
if ((record.mode === "formdata" || record.mode === "urlencoded") && Array.isArray(record.formEntries)) {
|
|
415
|
+
return {
|
|
416
|
+
mode: record.mode,
|
|
417
|
+
entries: record.formEntries.map((entry) => ({
|
|
418
|
+
key: String(entry.key ?? ""),
|
|
419
|
+
value: String(entry.value ?? ""),
|
|
420
|
+
...(entry.enabled === false ? { enabled: false } : {}),
|
|
421
|
+
...(entry.type === "file" ? { file: true } : {}),
|
|
422
|
+
})),
|
|
423
|
+
};
|
|
424
|
+
}
|
|
425
|
+
return { mode: "json", json: body };
|
|
426
|
+
}
|
|
427
|
+
return body;
|
|
428
|
+
};
|
|
429
|
+
exports.bodyInputView = bodyInputView;
|
|
219
430
|
const compactRequestView = (request, options = {}) => {
|
|
220
|
-
const
|
|
431
|
+
const body = (0, exports.bodyInputView)(request.body);
|
|
432
|
+
const bodyText = body === null ? null : (0, truncate_js_1.safeStringify)(body);
|
|
221
433
|
const bodyTruncated = bodyText !== null && !options.full && bodyText.length > truncate_js_1.LIMITS.BODY_PREVIEW;
|
|
434
|
+
const integrations = (0, requestIntegrations_js_1.integrationsInputView)(request);
|
|
222
435
|
return {
|
|
223
436
|
id: request.id,
|
|
224
437
|
name: request.name,
|
|
@@ -229,17 +442,25 @@ const compactRequestView = (request, options = {}) => {
|
|
|
229
442
|
headers: kvView(request.headers, !options.reveal),
|
|
230
443
|
query: kvView(request.query, false),
|
|
231
444
|
...(request.pathVariables && request.pathVariables.length > 0
|
|
232
|
-
? {
|
|
445
|
+
? {
|
|
446
|
+
pathVariables: request.pathVariables.map((entry) => ({
|
|
447
|
+
key: entry.key,
|
|
448
|
+
value: entry.value ?? "",
|
|
449
|
+
...(entry.description ? { description: entry.description } : {}),
|
|
450
|
+
})),
|
|
451
|
+
}
|
|
233
452
|
: {}),
|
|
234
|
-
body
|
|
235
|
-
|
|
236
|
-
|
|
453
|
+
// A clipped body is never returned as `body` — it would validate as a
|
|
454
|
+
// (cut) body if written back.
|
|
455
|
+
...(bodyTruncated ? { body: null, bodyPreview: (0, truncate_js_1.jsonPreview)(body), bodyTruncated: true } : { body }),
|
|
456
|
+
auth: (0, exports.authInputView)(request.auth, options.reveal),
|
|
237
457
|
scripts: {
|
|
238
458
|
preRequest: scriptView(request.preRequestScript, options.full),
|
|
239
459
|
postResponse: scriptView(request.postResponseScript, options.full),
|
|
240
460
|
tests: scriptView(request.testsScript, options.full),
|
|
241
461
|
},
|
|
242
462
|
isEnabledInRunner: request.isEnabledInRunner !== false,
|
|
463
|
+
...(integrations ?? {}),
|
|
243
464
|
updatedAt: request.updatedAt ?? null,
|
|
244
465
|
};
|
|
245
466
|
};
|
|
@@ -25,6 +25,9 @@ const resolveRef = (kind, ref, items, options) => {
|
|
|
25
25
|
throw new errors_js_1.ToolInputError("REF_AMBIGUOUS", `${exact.length} ${kind}s are named "${reference}" — use the id.`, { kind, ref: reference, candidates: candidatesOf(exact, options) });
|
|
26
26
|
}
|
|
27
27
|
const partial = items.filter((item) => names(item).some((name) => name.includes(needle)));
|
|
28
|
+
if (options?.exact) {
|
|
29
|
+
throw new errors_js_1.ToolInputError("REF_NOT_FOUND", `No ${kind} is named exactly "${reference}". This tool needs the exact name or the id${partial.length > 0 ? " — see candidates" : ""}.`, { kind, ref: reference, candidates: candidatesOf(partial.length > 0 ? partial : items, options) });
|
|
30
|
+
}
|
|
28
31
|
if (partial.length === 1) {
|
|
29
32
|
return { item: partial[0], matched: "partial", annotation: `matched "${reference}" → ${partial[0].name}` };
|
|
30
33
|
}
|
|
@@ -56,8 +59,9 @@ const flattenFolderTree = (tree) => {
|
|
|
56
59
|
return out;
|
|
57
60
|
};
|
|
58
61
|
exports.flattenFolderTree = flattenFolderTree;
|
|
59
|
-
const resolveFolderRef = (ref, folders) => (0, exports.resolveRef)("folder", ref, folders, {
|
|
62
|
+
const resolveFolderRef = (ref, folders, exact = false) => (0, exports.resolveRef)("folder", ref, folders, {
|
|
60
63
|
describe: (folder) => ({ path: folder.path }),
|
|
61
64
|
aliases: (folder) => [folder.path],
|
|
65
|
+
exact,
|
|
62
66
|
});
|
|
63
67
|
exports.resolveFolderRef = resolveFolderRef;
|